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_ImageDimIntrinsicTable_IMPL
49#define GET_RsrcIntrinsics_IMPL
50#define GET_GFX1250BlockingCyclesTable_DECL
51#define GET_GFX1250BlockingCyclesTable_IMPL
58#include "AMDGPUGenSearchableTables.inc"
66 cl::desc(
"Restrict range of branch instructions (DEBUG)"));
69 "amdgpu-fix-16-bit-physreg-copies",
70 cl::desc(
"Fix copies between 32 and 16 bit registers by extending to 32 bit"),
86 unsigned N =
Node->getNumOperands();
87 while (
N &&
Node->getOperand(
N - 1).getValueType() == MVT::Glue)
99 int Op0Idx = AMDGPU::getNamedOperandIdx(Opc0,
OpName);
100 int Op1Idx = AMDGPU::getNamedOperandIdx(Opc1,
OpName);
102 if (Op0Idx == -1 && Op1Idx == -1)
106 if ((Op0Idx == -1 && Op1Idx != -1) ||
107 (Op1Idx == -1 && Op0Idx != -1))
128 return !
MI.memoperands_empty() &&
130 return MMO->isLoad() && MMO->isInvariant();
139static std::tuple<unsigned, unsigned, unsigned>
147 unsigned LoReloc, HiReloc;
177 return {BaseFlags, LoReloc, HiReloc};
195 if (!
MI.hasImplicitDef() &&
196 MI.getNumImplicitOperands() ==
MI.getDesc().implicit_uses().size() &&
197 !
MI.mayRaiseFPException())
206 if (!
MI.getNumOperands() || !
MI.getOperand(0).isReg())
221 if (
MI.isNotDuplicable() ||
MI.mayStore() ||
MI.mayRaiseFPException() ||
222 MI.hasUnmodeledSideEffects())
227 if (
MI.isInlineAsm())
231 if (
MI.mayLoad() && !
MI.isDereferenceableInvariantLoad())
246 if (Reg.isPhysical()) {
262 if (MO.isDef() && Reg != DefReg)
272 case AMDGPU::V_SUBREV_U16_e32:
273 case AMDGPU::V_SUBREV_U16_e64:
275 case AMDGPU::V_SUBREV_U32_e32:
276 case AMDGPU::V_SUBREV_U32_e64:
278 case AMDGPU::V_SUBREV_CO_U32_e32:
279 case AMDGPU::V_SUBREV_CO_U32_e64:
281 case AMDGPU::V_SUBBREV_U32_e32:
282 case AMDGPU::V_SUBBREV_U32_e64:
285 case AMDGPU::V_ASHRREV_I16_e32:
286 case AMDGPU::V_ASHRREV_I16_e64:
287 case AMDGPU::V_ASHRREV_I32_e32:
288 case AMDGPU::V_ASHRREV_I32_e64:
289 case AMDGPU::V_ASHRREV_I64_e64:
290 case AMDGPU::V_LSHLREV_B16_e32:
291 case AMDGPU::V_LSHLREV_B16_e64:
292 case AMDGPU::V_LSHLREV_B32_e32:
293 case AMDGPU::V_LSHLREV_B32_e64:
294 case AMDGPU::V_LSHLREV_B64_e64:
295 case AMDGPU::V_LSHRREV_B16_e32:
296 case AMDGPU::V_LSHRREV_B16_e64:
297 case AMDGPU::V_LSHRREV_B32_e32:
298 case AMDGPU::V_LSHRREV_B32_e64:
299 case AMDGPU::V_LSHRREV_B64_e64:
300 return !ST.hasGFX11Insts();
307bool SIInstrInfo::resultDependsOnExec(
const MachineInstr &
MI)
const {
311 if (
MI.isConvergent())
339 if (
MI.getOpcode() == AMDGPU::SI_IF_BREAK)
344 for (
auto Op :
MI.uses()) {
345 if (
Op.isReg() &&
Op.getReg().isVirtual() &&
359 while (FromCycle && !(ToCycle && CI->
contains(FromCycle, ToCycle))) {
379 int64_t &Offset1)
const {
387 if (!
get(Opc0).mayLoad() || !
get(Opc1).mayLoad())
391 if (!
get(Opc0).getNumDefs() || !
get(Opc1).getNumDefs())
407 int Offset0Idx = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
408 int Offset1Idx = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
409 if (Offset0Idx == -1 || Offset1Idx == -1)
416 Offset0Idx -=
get(Opc0).NumDefs;
417 Offset1Idx -=
get(Opc1).NumDefs;
447 if (!Load0Offset || !Load1Offset)
464 int OffIdx0 = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
465 int OffIdx1 = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
467 if (OffIdx0 == -1 || OffIdx1 == -1)
473 OffIdx0 -=
get(Opc0).NumDefs;
474 OffIdx1 -=
get(Opc1).NumDefs;
493 case AMDGPU::DS_READ2ST64_B32:
494 case AMDGPU::DS_READ2ST64_B64:
495 case AMDGPU::DS_WRITE2ST64_B32:
496 case AMDGPU::DS_WRITE2ST64_B64:
511 OffsetIsScalable =
false;
528 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
530 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
531 if (
Opc == AMDGPU::DS_ATOMIC_ASYNC_BARRIER_ARRIVE_B64)
544 unsigned Offset0 = Offset0Op->
getImm() & 0xff;
545 unsigned Offset1 = Offset1Op->
getImm() & 0xff;
546 if (Offset0 + 1 != Offset1)
557 int Data0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
565 Offset = EltSize * Offset0;
567 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
568 if (DataOpIdx == -1) {
569 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
571 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
587 if (BaseOp && !BaseOp->
isFI())
595 if (SOffset->
isReg())
601 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
603 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
612 isMIMG(LdSt) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
613 int SRsrcIdx = AMDGPU::getNamedOperandIdx(
Opc, RsrcOpName);
615 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
616 if (VAddr0Idx >= 0) {
618 for (
int I = VAddr0Idx;
I < SRsrcIdx; ++
I)
625 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
640 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::sdst);
657 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
659 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
676 if (BaseOps1.
front()->isIdenticalTo(*BaseOps2.
front()))
684 if (MO1->getAddrSpace() != MO2->getAddrSpace())
687 const auto *Base1 = MO1->getValue();
688 const auto *Base2 = MO2->getValue();
689 if (!Base1 || !Base2)
697 return Base1 == Base2;
701 int64_t Offset1,
bool OffsetIsScalable1,
703 int64_t Offset2,
bool OffsetIsScalable2,
704 unsigned ClusterSize,
705 unsigned NumBytes)
const {
718 }
else if (!BaseOps1.
empty() || !BaseOps2.
empty()) {
737 const unsigned LoadSize = NumBytes / ClusterSize;
738 const unsigned NumDWords = ((LoadSize + 3) / 4) * ClusterSize;
739 return NumDWords <= MaxMemoryClusterDWords;
753 int64_t Offset0, int64_t Offset1,
754 unsigned NumLoads)
const {
755 assert(Offset1 > Offset0 &&
756 "Second offset should be larger than first offset!");
761 return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
768 const char *
Msg =
"illegal VGPR to SGPR copy") {
787 assert((
TII.getSubtarget().hasMAIInsts() &&
788 !
TII.getSubtarget().hasGFX90AInsts()) &&
789 "Expected GFX908 subtarget.");
792 AMDGPU::AGPR_32RegClass.
contains(SrcReg)) &&
793 "Source register of the copy should be either an SGPR or an AGPR.");
796 "Destination register of the copy should be an AGPR.");
805 for (
auto Def =
MI,
E =
MBB.begin(); Def !=
E; ) {
808 if (!Def->modifiesRegister(SrcReg, &RI))
811 if (Def->getOpcode() != AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
812 Def->getOperand(0).getReg() != SrcReg)
819 bool SafeToPropagate =
true;
822 for (
auto I = Def;
I !=
MI && SafeToPropagate; ++
I)
823 if (
I->modifiesRegister(DefOp.
getReg(), &RI))
824 SafeToPropagate =
false;
826 if (!SafeToPropagate)
829 for (
auto I = Def;
I !=
MI; ++
I)
830 I->clearRegisterKills(DefOp.
getReg(), &RI);
838 if (ImpUseSuperReg) {
839 Builder.addReg(ImpUseSuperReg,
847 RS.enterBasicBlockEnd(
MBB);
848 RS.backward(std::next(
MI));
857 unsigned RegNo = (DestReg - AMDGPU::AGPR0) % 3;
860 assert(
MBB.getParent()->getRegInfo().isReserved(Tmp) &&
861 "VGPR used for an intermediate copy should have been reserved.");
866 Register Tmp2 = RS.scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass,
MI,
876 unsigned TmpCopyOp = AMDGPU::V_MOV_B32_e32;
877 if (AMDGPU::AGPR_32RegClass.
contains(SrcReg)) {
878 TmpCopyOp = AMDGPU::V_ACCVGPR_READ_B32_e64;
885 if (ImpUseSuperReg) {
886 UseBuilder.
addReg(ImpUseSuperReg,
903 for (
unsigned Idx = 0; Idx < BaseIndices.
size(); ++Idx) {
904 int16_t SubIdx = BaseIndices[Idx];
905 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
906 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
907 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
908 unsigned Opcode = AMDGPU::S_MOV_B32;
911 bool AlignedDest = ((DestSubReg - AMDGPU::SGPR0) % 2) == 0;
912 bool AlignedSrc = ((SrcSubReg - AMDGPU::SGPR0) % 2) == 0;
913 if (AlignedDest && AlignedSrc && (Idx + 1 < BaseIndices.
size())) {
917 DestSubReg = RI.getSubReg(DestReg, SubIdx);
918 SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
919 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
920 Opcode = AMDGPU::S_MOV_B64;
935 assert(FirstMI && LastMI);
940 LastMI->addRegisterKilled(SrcReg, &RI);
946 Register SrcReg,
bool KillSrc,
bool RenamableDest,
947 bool RenamableSrc)
const {
949 unsigned Size = RI.getRegSizeInBits(*RC);
951 unsigned SrcSize = RI.getRegSizeInBits(*SrcRC);
957 if (((
Size == 16) != (SrcSize == 16))) {
959 assert(ST.useRealTrue16Insts());
961 MCRegister SubReg = RI.getSubReg(RegToFix, AMDGPU::lo16);
964 if (DestReg == SrcReg) {
970 RC = RI.getPhysRegBaseClass(DestReg);
971 Size = RI.getRegSizeInBits(*RC);
972 SrcRC = RI.getPhysRegBaseClass(SrcReg);
973 SrcSize = RI.getRegSizeInBits(*SrcRC);
977 if (RC == &AMDGPU::VGPR_32RegClass) {
979 AMDGPU::SReg_32RegClass.
contains(SrcReg) ||
980 AMDGPU::AGPR_32RegClass.
contains(SrcReg));
981 unsigned Opc = AMDGPU::AGPR_32RegClass.contains(SrcReg) ?
982 AMDGPU::V_ACCVGPR_READ_B32_e64 : AMDGPU::V_MOV_B32_e32;
988 if (RC == &AMDGPU::SReg_32_XM0RegClass ||
989 RC == &AMDGPU::SReg_32RegClass) {
990 if (SrcReg == AMDGPU::SCC) {
997 if (!AMDGPU::SReg_32RegClass.
contains(SrcReg)) {
998 if (DestReg == AMDGPU::VCC_LO) {
1016 if (RC == &AMDGPU::SReg_64RegClass) {
1017 if (SrcReg == AMDGPU::SCC) {
1024 if (!AMDGPU::SReg_64_EncodableRegClass.
contains(SrcReg)) {
1025 if (DestReg == AMDGPU::VCC) {
1043 if (DestReg == AMDGPU::SCC) {
1046 if (AMDGPU::SReg_64RegClass.
contains(SrcReg)) {
1050 assert(ST.hasScalarCompareEq64());
1064 if (RC == &AMDGPU::AGPR_32RegClass) {
1065 if (AMDGPU::VGPR_32RegClass.
contains(SrcReg) ||
1066 (ST.hasGFX90AInsts() && AMDGPU::SReg_32RegClass.contains(SrcReg))) {
1072 if (AMDGPU::AGPR_32RegClass.
contains(SrcReg) && ST.hasGFX90AInsts()) {
1081 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1088 AMDGPU::SReg_LO16RegClass.
contains(SrcReg) ||
1089 AMDGPU::AGPR_LO16RegClass.
contains(SrcReg));
1091 bool IsSGPRDst = AMDGPU::SReg_LO16RegClass.contains(DestReg);
1092 bool IsSGPRSrc = AMDGPU::SReg_LO16RegClass.contains(SrcReg);
1093 bool IsAGPRDst = AMDGPU::AGPR_LO16RegClass.contains(DestReg);
1094 bool IsAGPRSrc = AMDGPU::AGPR_LO16RegClass.contains(SrcReg);
1097 MCRegister NewDestReg = RI.get32BitRegister(DestReg);
1098 MCRegister NewSrcReg = RI.get32BitRegister(SrcReg);
1111 if (IsAGPRDst || IsAGPRSrc) {
1112 if (!DstLow || !SrcLow) {
1114 "Cannot use hi16 subreg with an AGPR!");
1121 if (ST.useRealTrue16Insts()) {
1127 if (AMDGPU::VGPR_16_Lo128RegClass.
contains(DestReg) &&
1128 (IsSGPRSrc || AMDGPU::VGPR_16_Lo128RegClass.
contains(SrcReg))) {
1140 if (IsSGPRSrc && !ST.hasSDWAScalar()) {
1141 if (!DstLow || !SrcLow) {
1143 "Cannot use hi16 subreg on VI!");
1169 unsigned SrcOp = 1) {
1173 return DstOpRC && SrcOpRC && DstOpRC->
contains(Dst) &&
1177 if (RC == RI.getVGPR64Class() && (SrcRC == RC || RI.isSGPRClass(SrcRC))) {
1178 if (ST.hasVMovB64Inst() &&
1179 CanCopyWith(AMDGPU::V_MOV_B64_e32, DestReg, SrcReg)) {
1184 if (ST.hasPkMovB32() &&
1185 CanCopyWith(AMDGPU::V_PK_MOV_B32, DestReg, SrcReg, 2)) {
1201 const bool Forward = RI.getHWRegIndex(DestReg) <= RI.getHWRegIndex(SrcReg);
1202 if (RI.isSGPRClass(RC)) {
1203 if (!RI.isSGPRClass(SrcRC)) {
1207 const bool CanKillSuperReg = KillSrc && !RI.regsOverlap(SrcReg, DestReg);
1213 unsigned Opcode = AMDGPU::V_MOV_B32_e32;
1214 unsigned WideOpcode = AMDGPU::INSTRUCTION_LIST_END;
1215 if (RI.isAGPRClass(RC)) {
1216 if (ST.hasGFX90AInsts() && RI.isAGPRClass(SrcRC))
1217 Opcode = AMDGPU::V_ACCVGPR_MOV_B32;
1218 else if (RI.hasVGPRs(SrcRC) ||
1219 (ST.hasGFX90AInsts() && RI.isSGPRClass(SrcRC)))
1220 Opcode = AMDGPU::V_ACCVGPR_WRITE_B32_e64;
1222 Opcode = AMDGPU::INSTRUCTION_LIST_END;
1223 }
else if (RI.hasVGPRs(RC) && RI.isAGPRClass(SrcRC)) {
1224 Opcode = AMDGPU::V_ACCVGPR_READ_B32_e64;
1225 }
else if (RI.isVGPRClass(RC)) {
1226 if (ST.hasVMovB64Inst())
1227 WideOpcode = AMDGPU::V_MOV_B64_e32;
1228 else if (ST.hasPkMovB32())
1229 WideOpcode = AMDGPU::V_PK_MOV_B32;
1233 if (WideOpcode != AMDGPU::INSTRUCTION_LIST_END) {
1235 unsigned SrcOp = WideOpcode == AMDGPU::V_PK_MOV_B32 ? 2 : 1;
1242 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1243 const bool CanKillSuperReg = KillSrc && !Overlap;
1250 std::unique_ptr<RegScavenger> RS;
1251 if (Opcode == AMDGPU::INSTRUCTION_LIST_END)
1252 RS = std::make_unique<RegScavenger>();
1256 for (
unsigned Idx{}; Idx < SubIndices.
size();) {
1257 unsigned NumRegs = 1;
1258 unsigned ThisOpcode = Opcode;
1260 Forward ? SubIndices[Idx] : SubIndices[SubIndices.
size() - Idx - 1];
1262 if (WideDstRC && WideSrcRC && Idx + 1 < SubIndices.
size()) {
1263 unsigned Channel = RI.getChannelFromSubReg(SubIdx);
1267 unsigned WideSubIdx = RI.getSubRegFromChannel(Channel, 2);
1268 Register WideDst = RI.getSubReg(DestReg, WideSubIdx);
1269 Register WideSrc = RI.getSubReg(SrcReg, WideSubIdx);
1271 if (WideDst && WideSrc && WideDstRC->
contains(WideDst) &&
1272 WideSrcRC->contains(WideSrc)) {
1273 SubIdx = WideSubIdx;
1275 ThisOpcode = WideOpcode;
1279 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
1280 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
1281 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
1284 bool UseKill = CanKillSuperReg && Idx == SubIndices.
size();
1286 if (ThisOpcode == AMDGPU::INSTRUCTION_LIST_END) {
1289 *RS, Overlap, ImpUseSuper);
1290 }
else if (ThisOpcode == AMDGPU::V_PK_MOV_B32) {
1331 int64_t &ImmVal)
const {
1332 switch (
MI.getOpcode()) {
1333 case AMDGPU::V_MOV_B32_e32:
1334 case AMDGPU::S_MOV_B32:
1335 case AMDGPU::S_MOVK_I32:
1336 case AMDGPU::S_MOV_B64:
1337 case AMDGPU::V_MOV_B64_e32:
1338 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
1339 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
1340 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
1341 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
1342 case AMDGPU::V_MOV_B64_PSEUDO:
1343 case AMDGPU::V_MOV_B16_t16_e32: {
1347 return MI.getOperand(0).getReg() == Reg;
1352 case AMDGPU::V_MOV_B16_t16_e64: {
1354 if (Src0.
isImm() && !
MI.getOperand(1).getImm()) {
1356 return MI.getOperand(0).getReg() == Reg;
1361 case AMDGPU::S_BREV_B32:
1362 case AMDGPU::V_BFREV_B32_e32:
1363 case AMDGPU::V_BFREV_B32_e64: {
1367 return MI.getOperand(0).getReg() == Reg;
1372 case AMDGPU::S_NOT_B32:
1373 case AMDGPU::V_NOT_B32_e32:
1374 case AMDGPU::V_NOT_B32_e64: {
1377 ImmVal =
static_cast<int64_t
>(~static_cast<int32_t>(Src0.
getImm()));
1378 return MI.getOperand(0).getReg() == Reg;
1388std::optional<int64_t>
1398 if (!
Op.isReg() || !
Op.getReg().isVirtual())
1399 return std::nullopt;
1401 if (Def && Def->isMoveImmediate()) {
1403 if (ImmSrc.
isImm()) {
1410 return std::nullopt;
1413std::optional<int64_t>
1422 if (RI.isAGPRClass(DstRC))
1423 return AMDGPU::COPY;
1424 if (RI.getRegSizeInBits(*DstRC) == 16) {
1427 return RI.isSGPRClass(DstRC) ? AMDGPU::COPY : AMDGPU::V_MOV_B16_t16_e64;
1429 if (RI.getRegSizeInBits(*DstRC) == 32)
1430 return RI.isSGPRClass(DstRC) ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1431 if (RI.getRegSizeInBits(*DstRC) == 64 && RI.isSGPRClass(DstRC))
1432 return AMDGPU::S_MOV_B64;
1433 if (RI.getRegSizeInBits(*DstRC) == 64 && !RI.isSGPRClass(DstRC))
1434 return AMDGPU::V_MOV_B64_PSEUDO;
1435 return AMDGPU::COPY;
1440 bool IsIndirectSrc)
const {
1441 if (IsIndirectSrc) {
1443 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1);
1445 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2);
1447 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3);
1449 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4);
1451 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5);
1453 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6);
1455 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7);
1457 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8);
1459 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9);
1461 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10);
1463 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11);
1465 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12);
1467 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16);
1468 if (VecSize <= 1024)
1469 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32);
1475 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1);
1477 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2);
1479 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3);
1481 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4);
1483 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5);
1485 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6);
1487 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7);
1489 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8);
1491 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9);
1493 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10);
1495 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11);
1497 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12);
1499 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16);
1500 if (VecSize <= 1024)
1501 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32);
1508 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1510 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1512 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1514 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1516 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1518 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1520 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1522 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1524 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1526 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1528 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1530 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1532 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1533 if (VecSize <= 1024)
1534 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1541 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1543 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1545 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1547 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1549 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1551 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1553 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1555 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1557 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1559 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1561 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1563 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1565 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1566 if (VecSize <= 1024)
1567 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1574 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1;
1576 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2;
1578 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4;
1580 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8;
1581 if (VecSize <= 1024)
1582 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16;
1589 bool IsSGPR)
const {
1601 assert(EltSize == 32 &&
"invalid reg indexing elt size");
1608 return NeedsCFI ? AMDGPU::SI_SPILL_S32_CFI_SAVE : AMDGPU::SI_SPILL_S32_SAVE;
1610 return NeedsCFI ? AMDGPU::SI_SPILL_S64_CFI_SAVE : AMDGPU::SI_SPILL_S64_SAVE;
1612 return NeedsCFI ? AMDGPU::SI_SPILL_S96_CFI_SAVE : AMDGPU::SI_SPILL_S96_SAVE;
1614 return NeedsCFI ? AMDGPU::SI_SPILL_S128_CFI_SAVE
1615 : AMDGPU::SI_SPILL_S128_SAVE;
1617 return NeedsCFI ? AMDGPU::SI_SPILL_S160_CFI_SAVE
1618 : AMDGPU::SI_SPILL_S160_SAVE;
1620 return NeedsCFI ? AMDGPU::SI_SPILL_S192_CFI_SAVE
1621 : AMDGPU::SI_SPILL_S192_SAVE;
1623 return NeedsCFI ? AMDGPU::SI_SPILL_S224_CFI_SAVE
1624 : AMDGPU::SI_SPILL_S224_SAVE;
1626 return AMDGPU::SI_SPILL_S256_SAVE;
1628 return AMDGPU::SI_SPILL_S288_SAVE;
1630 return AMDGPU::SI_SPILL_S320_SAVE;
1632 return AMDGPU::SI_SPILL_S352_SAVE;
1634 return AMDGPU::SI_SPILL_S384_SAVE;
1636 return NeedsCFI ? AMDGPU::SI_SPILL_S512_CFI_SAVE
1637 : AMDGPU::SI_SPILL_S512_SAVE;
1639 return NeedsCFI ? AMDGPU::SI_SPILL_S1024_CFI_SAVE
1640 : AMDGPU::SI_SPILL_S1024_SAVE;
1649 return AMDGPU::SI_SPILL_V16_SAVE;
1651 return NeedsCFI ? AMDGPU::SI_SPILL_V32_CFI_SAVE : AMDGPU::SI_SPILL_V32_SAVE;
1653 return NeedsCFI ? AMDGPU::SI_SPILL_V64_CFI_SAVE : AMDGPU::SI_SPILL_V64_SAVE;
1655 return NeedsCFI ? AMDGPU::SI_SPILL_V96_CFI_SAVE : AMDGPU::SI_SPILL_V96_SAVE;
1657 return NeedsCFI ? AMDGPU::SI_SPILL_V128_CFI_SAVE
1658 : AMDGPU::SI_SPILL_V128_SAVE;
1660 return NeedsCFI ? AMDGPU::SI_SPILL_V160_CFI_SAVE
1661 : AMDGPU::SI_SPILL_V160_SAVE;
1663 return NeedsCFI ? AMDGPU::SI_SPILL_V192_CFI_SAVE
1664 : AMDGPU::SI_SPILL_V192_SAVE;
1666 return NeedsCFI ? AMDGPU::SI_SPILL_V224_CFI_SAVE
1667 : AMDGPU::SI_SPILL_V224_SAVE;
1669 return NeedsCFI ? AMDGPU::SI_SPILL_V256_CFI_SAVE
1670 : AMDGPU::SI_SPILL_V256_SAVE;
1672 return NeedsCFI ? AMDGPU::SI_SPILL_V288_CFI_SAVE
1673 : AMDGPU::SI_SPILL_V288_SAVE;
1675 return NeedsCFI ? AMDGPU::SI_SPILL_V320_CFI_SAVE
1676 : AMDGPU::SI_SPILL_V320_SAVE;
1678 return NeedsCFI ? AMDGPU::SI_SPILL_V352_CFI_SAVE
1679 : AMDGPU::SI_SPILL_V352_SAVE;
1681 return NeedsCFI ? AMDGPU::SI_SPILL_V384_CFI_SAVE
1682 : AMDGPU::SI_SPILL_V384_SAVE;
1684 return NeedsCFI ? AMDGPU::SI_SPILL_V512_CFI_SAVE
1685 : AMDGPU::SI_SPILL_V512_SAVE;
1687 return NeedsCFI ? AMDGPU::SI_SPILL_V1024_CFI_SAVE
1688 : AMDGPU::SI_SPILL_V1024_SAVE;
1697 return NeedsCFI ? AMDGPU::SI_SPILL_AV32_CFI_SAVE
1698 : AMDGPU::SI_SPILL_AV32_SAVE;
1700 return NeedsCFI ? AMDGPU::SI_SPILL_AV64_CFI_SAVE
1701 : AMDGPU::SI_SPILL_AV64_SAVE;
1703 return NeedsCFI ? AMDGPU::SI_SPILL_AV96_CFI_SAVE
1704 : AMDGPU::SI_SPILL_AV96_SAVE;
1706 return NeedsCFI ? AMDGPU::SI_SPILL_AV128_CFI_SAVE
1707 : AMDGPU::SI_SPILL_AV128_SAVE;
1709 return NeedsCFI ? AMDGPU::SI_SPILL_AV160_CFI_SAVE
1710 : AMDGPU::SI_SPILL_AV160_SAVE;
1712 return NeedsCFI ? AMDGPU::SI_SPILL_AV192_CFI_SAVE
1713 : AMDGPU::SI_SPILL_AV192_SAVE;
1715 return NeedsCFI ? AMDGPU::SI_SPILL_AV224_CFI_SAVE
1716 : AMDGPU::SI_SPILL_AV224_SAVE;
1718 return NeedsCFI ? AMDGPU::SI_SPILL_AV256_CFI_SAVE
1719 : AMDGPU::SI_SPILL_AV256_SAVE;
1721 return AMDGPU::SI_SPILL_AV288_SAVE;
1723 return AMDGPU::SI_SPILL_AV320_SAVE;
1725 return AMDGPU::SI_SPILL_AV352_SAVE;
1727 return AMDGPU::SI_SPILL_AV384_SAVE;
1729 return NeedsCFI ? AMDGPU::SI_SPILL_AV512_CFI_SAVE
1730 : AMDGPU::SI_SPILL_AV512_SAVE;
1732 return NeedsCFI ? AMDGPU::SI_SPILL_AV1024_CFI_SAVE
1733 : AMDGPU::SI_SPILL_AV1024_SAVE;
1740 bool IsVectorSuperClass) {
1745 if (IsVectorSuperClass)
1746 return AMDGPU::SI_SPILL_WWM_AV32_SAVE;
1748 return AMDGPU::SI_SPILL_WWM_V32_SAVE;
1754 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1761 if (ST.hasMAIInsts())
1767void SIInstrInfo::storeRegToStackSlotImpl(
1780 FrameInfo.getObjectAlign(FrameIndex));
1781 unsigned SpillSize = RI.getSpillSize(*RC);
1787 assert(SrcReg != AMDGPU::M0 &&
"m0 should not be spilled");
1788 assert(SrcReg != AMDGPU::EXEC_LO && SrcReg != AMDGPU::EXEC_HI &&
1789 SrcReg != AMDGPU::EXEC &&
"exec should not be spilled");
1798 if (SrcReg.
isVirtual() && SpillSize == 4) {
1812 SpillSize, *MFI, NeedsCFI);
1827 storeRegToStackSlotImpl(
MBB,
MI, SrcReg, isKill, FrameIndex, RC, VReg, Flags,
1836 storeRegToStackSlotImpl(
MBB,
MI, SrcReg, isKill, FrameIndex, RC,
Register(),
1843 return AMDGPU::SI_SPILL_S32_RESTORE;
1845 return AMDGPU::SI_SPILL_S64_RESTORE;
1847 return AMDGPU::SI_SPILL_S96_RESTORE;
1849 return AMDGPU::SI_SPILL_S128_RESTORE;
1851 return AMDGPU::SI_SPILL_S160_RESTORE;
1853 return AMDGPU::SI_SPILL_S192_RESTORE;
1855 return AMDGPU::SI_SPILL_S224_RESTORE;
1857 return AMDGPU::SI_SPILL_S256_RESTORE;
1859 return AMDGPU::SI_SPILL_S288_RESTORE;
1861 return AMDGPU::SI_SPILL_S320_RESTORE;
1863 return AMDGPU::SI_SPILL_S352_RESTORE;
1865 return AMDGPU::SI_SPILL_S384_RESTORE;
1867 return AMDGPU::SI_SPILL_S512_RESTORE;
1869 return AMDGPU::SI_SPILL_S1024_RESTORE;
1878 return AMDGPU::SI_SPILL_V16_RESTORE;
1880 return AMDGPU::SI_SPILL_V32_RESTORE;
1882 return AMDGPU::SI_SPILL_V64_RESTORE;
1884 return AMDGPU::SI_SPILL_V96_RESTORE;
1886 return AMDGPU::SI_SPILL_V128_RESTORE;
1888 return AMDGPU::SI_SPILL_V160_RESTORE;
1890 return AMDGPU::SI_SPILL_V192_RESTORE;
1892 return AMDGPU::SI_SPILL_V224_RESTORE;
1894 return AMDGPU::SI_SPILL_V256_RESTORE;
1896 return AMDGPU::SI_SPILL_V288_RESTORE;
1898 return AMDGPU::SI_SPILL_V320_RESTORE;
1900 return AMDGPU::SI_SPILL_V352_RESTORE;
1902 return AMDGPU::SI_SPILL_V384_RESTORE;
1904 return AMDGPU::SI_SPILL_V512_RESTORE;
1906 return AMDGPU::SI_SPILL_V1024_RESTORE;
1915 return AMDGPU::SI_SPILL_AV32_RESTORE;
1917 return AMDGPU::SI_SPILL_AV64_RESTORE;
1919 return AMDGPU::SI_SPILL_AV96_RESTORE;
1921 return AMDGPU::SI_SPILL_AV128_RESTORE;
1923 return AMDGPU::SI_SPILL_AV160_RESTORE;
1925 return AMDGPU::SI_SPILL_AV192_RESTORE;
1927 return AMDGPU::SI_SPILL_AV224_RESTORE;
1929 return AMDGPU::SI_SPILL_AV256_RESTORE;
1931 return AMDGPU::SI_SPILL_AV288_RESTORE;
1933 return AMDGPU::SI_SPILL_AV320_RESTORE;
1935 return AMDGPU::SI_SPILL_AV352_RESTORE;
1937 return AMDGPU::SI_SPILL_AV384_RESTORE;
1939 return AMDGPU::SI_SPILL_AV512_RESTORE;
1941 return AMDGPU::SI_SPILL_AV1024_RESTORE;
1948 bool IsVectorSuperClass) {
1953 if (IsVectorSuperClass)
1954 return AMDGPU::SI_SPILL_WWM_AV32_RESTORE;
1956 return AMDGPU::SI_SPILL_WWM_V32_RESTORE;
1962 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1969 if (ST.hasMAIInsts())
1972 assert(!RI.isAGPRClass(RC));
1986 unsigned SpillSize = RI.getSpillSize(*RC);
1993 FrameInfo.getObjectAlign(FrameIndex));
1995 if (RI.isSGPRClass(RC)) {
1998 assert(DestReg != AMDGPU::M0 &&
"m0 should not be reloaded into");
1999 assert(DestReg != AMDGPU::EXEC_LO && DestReg != AMDGPU::EXEC_HI &&
2000 DestReg != AMDGPU::EXEC &&
"exec should not be spilled");
2005 if (DestReg.
isVirtual() && SpillSize == 4) {
2034 unsigned Quantity)
const {
2036 unsigned MaxSNopCount = 1u << ST.getSNopBits();
2037 while (Quantity > 0) {
2038 unsigned Arg = std::min(Quantity, MaxSNopCount);
2049 constexpr unsigned DoorbellIDMask = 0x3ff;
2050 constexpr unsigned ECQueueWaveAbort = 0x400;
2055 if (!
MBB.succ_empty() || std::next(
MI.getIterator()) !=
MBB.end()) {
2056 MBB.splitAt(
MI,
false);
2060 MBB.addSuccessor(TrapBB);
2070 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
2074 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_AND_B32), DoorbellRegMasked)
2079 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_OR_B32), SetWaveAbortBit)
2080 .
addUse(DoorbellRegMasked)
2081 .
addImm(ECQueueWaveAbort);
2082 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2083 .
addUse(SetWaveAbortBit);
2086 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2097 return MBB.getNextNode();
2101 switch (
MI.getOpcode()) {
2103 if (
MI.isMetaInstruction())
2108 return MI.getOperand(0).getImm() + 1;
2119 switch (
MI.getOpcode()) {
2121 case AMDGPU::S_MOV_B64_term:
2124 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2127 case AMDGPU::S_MOV_B32_term:
2130 MI.setDesc(
get(AMDGPU::S_MOV_B32));
2133 case AMDGPU::S_XOR_B64_term:
2136 MI.setDesc(
get(AMDGPU::S_XOR_B64));
2139 case AMDGPU::S_XOR_B32_term:
2142 MI.setDesc(
get(AMDGPU::S_XOR_B32));
2144 case AMDGPU::S_OR_B64_term:
2147 MI.setDesc(
get(AMDGPU::S_OR_B64));
2149 case AMDGPU::S_OR_B32_term:
2152 MI.setDesc(
get(AMDGPU::S_OR_B32));
2155 case AMDGPU::S_ANDN2_B64_term:
2158 MI.setDesc(
get(AMDGPU::S_ANDN2_B64));
2161 case AMDGPU::S_ANDN2_B32_term:
2164 MI.setDesc(
get(AMDGPU::S_ANDN2_B32));
2167 case AMDGPU::S_AND_B64_term:
2170 MI.setDesc(
get(AMDGPU::S_AND_B64));
2173 case AMDGPU::S_AND_B32_term:
2176 MI.setDesc(
get(AMDGPU::S_AND_B32));
2179 case AMDGPU::S_AND_SAVEEXEC_B64_term:
2182 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B64));
2185 case AMDGPU::S_AND_SAVEEXEC_B32_term:
2188 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B32));
2191 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
2192 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32));
2194 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
2195 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32));
2198 case AMDGPU::SI_SPILL_S32_TO_VGPR:
2199 MI.setDesc(
get(AMDGPU::V_WRITELANE_B32));
2202 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
2203 MI.setDesc(
get(AMDGPU::V_READLANE_B32));
2205 case AMDGPU::AV_MOV_B32_IMM_PSEUDO: {
2209 get(IsAGPR ? AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::V_MOV_B32_e32));
2212 case AMDGPU::AV_MOV_B64_IMM_PSEUDO: {
2215 int64_t
Imm =
MI.getOperand(1).getImm();
2217 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2218 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2223 MI.eraseFromParent();
2229 case AMDGPU::V_MOV_B64_PSEUDO: {
2231 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2232 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2240 if (ST.hasVMovB64Inst() && Mov64RC->
contains(Dst)) {
2241 MI.setDesc(Mov64Desc);
2245 (
SrcOp.isGlobal() && ST.has64BitLiterals()))
2248 if (
SrcOp.isGlobal()) {
2253 unsigned BaseFlags, LoReloc, HiReloc;
2254 std::tie(BaseFlags, LoReloc, HiReloc) =
2261 }
else if (
SrcOp.isImm()) {
2263 APInt Lo(32,
Imm.getLoBits(32).getZExtValue());
2264 APInt Hi(32,
Imm.getHiBits(32).getZExtValue());
2288 if (ST.hasPkMovB32() &&
2307 MI.eraseFromParent();
2310 case AMDGPU::V_MOV_B64_DPP_PSEUDO: {
2314 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2318 if (ST.has64BitLiterals()) {
2319 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2323 if (
SrcOp.isGlobal()) {
2325 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2326 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2329 unsigned BaseFlags, LoReloc, HiReloc;
2330 std::tie(BaseFlags, LoReloc, HiReloc) =
2337 MI.eraseFromParent();
2344 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2349 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2350 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2352 APInt Lo(32,
Imm.getLoBits(32).getZExtValue());
2353 APInt Hi(32,
Imm.getHiBits(32).getZExtValue());
2358 MI.eraseFromParent();
2361 case AMDGPU::V_SET_INACTIVE_B32: {
2365 .
add(
MI.getOperand(3))
2366 .
add(
MI.getOperand(4))
2367 .
add(
MI.getOperand(1))
2368 .
add(
MI.getOperand(2))
2369 .
add(
MI.getOperand(5));
2370 MI.eraseFromParent();
2373 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2374 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2375 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2376 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2377 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2378 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2379 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2380 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2381 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2382 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2383 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2384 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2385 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2386 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2387 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2388 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2389 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2390 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2391 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2392 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2393 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2394 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2395 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2396 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2397 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2398 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2399 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2400 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2401 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1:
2402 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2:
2403 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4:
2404 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8:
2405 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16: {
2409 if (RI.hasVGPRs(EltRC)) {
2410 Opc = AMDGPU::V_MOVRELD_B32_e32;
2412 Opc = RI.getRegSizeInBits(*EltRC) == 64 ? AMDGPU::S_MOVRELD_B64
2413 : AMDGPU::S_MOVRELD_B32;
2418 bool IsUndef =
MI.getOperand(1).isUndef();
2419 unsigned SubReg =
MI.getOperand(3).getImm();
2420 assert(VecReg ==
MI.getOperand(1).getReg());
2425 .
add(
MI.getOperand(2))
2429 const int ImpDefIdx =
2431 const int ImpUseIdx = ImpDefIdx + 1;
2433 MI.eraseFromParent();
2436 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1:
2437 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2:
2438 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3:
2439 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4:
2440 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5:
2441 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6:
2442 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7:
2443 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8:
2444 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9:
2445 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10:
2446 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11:
2447 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12:
2448 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16:
2449 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32: {
2450 assert(ST.useVGPRIndexMode());
2452 bool IsUndef =
MI.getOperand(1).isUndef();
2461 const MCInstrDesc &OpDesc =
get(AMDGPU::V_MOV_B32_indirect_write);
2465 .
add(
MI.getOperand(2))
2469 const int ImpDefIdx =
2471 const int ImpUseIdx = ImpDefIdx + 1;
2478 MI.eraseFromParent();
2481 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1:
2482 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2:
2483 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3:
2484 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4:
2485 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5:
2486 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6:
2487 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7:
2488 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8:
2489 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9:
2490 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10:
2491 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11:
2492 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12:
2493 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16:
2494 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32: {
2495 assert(ST.useVGPRIndexMode());
2498 bool IsUndef =
MI.getOperand(1).isUndef();
2502 .
add(
MI.getOperand(2))
2515 MI.eraseFromParent();
2518 case AMDGPU::SI_PC_ADD_REL_OFFSET: {
2521 Register RegLo = RI.getSubReg(Reg, AMDGPU::sub0);
2522 Register RegHi = RI.getSubReg(Reg, AMDGPU::sub1);
2541 if (ST.hasGetPCZeroExtension()) {
2545 BuildMI(MF,
DL,
get(AMDGPU::S_SEXT_I32_I16), RegHi).addReg(RegHi));
2552 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U32), RegLo).addReg(RegLo).add(OpLo));
2562 MI.eraseFromParent();
2565 case AMDGPU::SI_PC_ADD_REL_OFFSET64: {
2575 Op.setOffset(
Op.getOffset() + 4);
2577 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U64), Reg).addReg(Reg).add(
Op));
2581 MI.eraseFromParent();
2584 case AMDGPU::ENTER_STRICT_WWM: {
2590 case AMDGPU::ENTER_STRICT_WQM: {
2597 MI.eraseFromParent();
2600 case AMDGPU::EXIT_STRICT_WWM:
2601 case AMDGPU::EXIT_STRICT_WQM: {
2607 case AMDGPU::SI_RETURN: {
2621 MI.eraseFromParent();
2625 case AMDGPU::S_MUL_U64_U32_PSEUDO:
2626 case AMDGPU::S_MUL_I64_I32_PSEUDO:
2627 MI.setDesc(
get(AMDGPU::S_MUL_U64));
2630 case AMDGPU::S_GETPC_B64_pseudo:
2631 MI.setDesc(
get(AMDGPU::S_GETPC_B64));
2632 if (ST.hasGetPCZeroExtension()) {
2634 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2643 case AMDGPU::V_MAX_BF16_PSEUDO_e64: {
2644 assert(ST.hasBF16PackedInsts());
2645 MI.setDesc(
get(AMDGPU::V_PK_MAX_NUM_BF16));
2656 case AMDGPU::GET_STACK_BASE:
2659 if (ST.getFrameLowering()->mayReserveScratchForCWSR(*
MBB.getParent())) {
2666 Register DestReg =
MI.getOperand(0).getReg();
2676 MI.getOperand(
MI.getNumExplicitOperands()).setIsDead(
false);
2677 MI.getOperand(
MI.getNumExplicitOperands()).setIsUse();
2678 MI.setDesc(
get(AMDGPU::S_CMOVK_I32));
2681 MI.setDesc(
get(AMDGPU::S_MOV_B32));
2684 MI.getNumExplicitOperands());
2702 case AMDGPU::S_MOV_B64:
2703 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2712 if (UsedLanes.
all())
2717 unsigned LoSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub0);
2718 unsigned HiSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub1);
2720 bool NeedLo = (UsedLanes & RI.getSubRegIndexLaneMask(LoSubReg)).any();
2721 bool NeedHi = (UsedLanes & RI.getSubRegIndexLaneMask(HiSubReg)).any();
2723 if (NeedLo && NeedHi)
2727 int32_t Imm32 = NeedLo ?
Lo_32(Imm64) :
Hi_32(Imm64);
2729 unsigned UseSubReg = NeedLo ? LoSubReg : HiSubReg;
2738 case AMDGPU::S_LOAD_DWORDX16_IMM:
2739 case AMDGPU::S_LOAD_DWORDX8_IMM: {
2752 for (
auto &CandMO :
I->operands()) {
2753 if (!CandMO.isReg() || CandMO.getReg() != RegToFind || CandMO.isDef())
2761 if (!UseMO || UseMO->
getSubReg() == AMDGPU::NoSubRegister)
2765 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->
getSubReg());
2771 unsigned NewOpcode = -1;
2772 if (SubregSize == 256)
2773 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2774 else if (SubregSize == 128)
2775 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2785 UseMO->
setSubReg(AMDGPU::NoSubRegister);
2790 MI->getOperand(0).setReg(DestReg);
2791 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2795 OffsetMO->
setImm(FinalOffset);
2801 MI->setMemRefs(*MF, NewMMOs);
2814std::pair<MachineInstr*, MachineInstr*>
2816 assert (
MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2818 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2821 MI.setDesc(
get(AMDGPU::V_MOV_B64_dpp));
2822 return std::pair(&
MI,
nullptr);
2833 for (
auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2835 if (Dst.isPhysical()) {
2836 MovDPP.addDef(RI.getSubReg(Dst,
Sub));
2843 for (
unsigned I = 1;
I <= 2; ++
I) {
2846 if (
SrcOp.isImm()) {
2848 Imm.ashrInPlace(Part * 32);
2849 MovDPP.addImm(
Imm.getLoBits(32).getZExtValue());
2853 if (Src.isPhysical())
2854 MovDPP.addReg(RI.getSubReg(Src,
Sub));
2861 MovDPP.addImm(MO.getImm());
2863 Split[Part] = MovDPP;
2867 if (Dst.isVirtual())
2874 MI.eraseFromParent();
2875 return std::pair(Split[0], Split[1]);
2878std::optional<DestSourcePair>
2880 if (
MI.getOpcode() == AMDGPU::WWM_COPY)
2883 return std::nullopt;
2887 AMDGPU::OpName Src0OpName,
2889 AMDGPU::OpName Src1OpName)
const {
2896 "All commutable instructions have both src0 and src1 modifiers");
2898 int Src0ModsVal = Src0Mods->
getImm();
2899 int Src1ModsVal = Src1Mods->
getImm();
2901 Src1Mods->
setImm(Src0ModsVal);
2902 Src0Mods->
setImm(Src1ModsVal);
2911 bool IsKill = RegOp.
isKill();
2913 bool IsUndef = RegOp.
isUndef();
2914 bool IsDebug = RegOp.
isDebug();
2916 if (NonRegOp.
isImm())
2918 else if (NonRegOp.
isFI())
2939 int64_t NonRegVal = NonRegOp1.
getImm();
2942 NonRegOp2.
setImm(NonRegVal);
2949 unsigned OpIdx1)
const {
2954 unsigned Opc =
MI.getOpcode();
2955 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
2965 if ((
int)OpIdx0 == Src0Idx && !MO0.
isReg() &&
2968 if ((
int)OpIdx1 == Src0Idx && !MO1.
isReg() &&
2973 if ((
int)OpIdx1 != Src0Idx && MO0.
isReg()) {
2979 if ((
int)OpIdx0 != Src0Idx && MO1.
isReg()) {
3001 unsigned Src1Idx)
const {
3002 assert(!NewMI &&
"this should never be used");
3007 unsigned Opc =
MI.getOpcode();
3009 if (CommutedOpcode == -1)
3012 if (Src0Idx > Src1Idx)
3015 assert(AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) ==
3016 static_cast<int>(Src0Idx) &&
3017 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1) ==
3018 static_cast<int>(Src1Idx) &&
3019 "inconsistency with findCommutedOpIndices");
3044 Src1, AMDGPU::OpName::src1_modifiers);
3047 AMDGPU::OpName::src1_sel);
3059 unsigned &SrcOpIdx0,
3060 unsigned &SrcOpIdx1)
const {
3068 unsigned &SrcOpIdx0,
3069 unsigned &SrcOpIdx1)
const {
3070 if (!
Desc.isCommutable())
3073 unsigned Opc =
Desc.getOpcode();
3074 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
3078 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
3082 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
3086 int64_t BrOffset)
const {
3103 return MI.getOperand(0).getMBB();
3108 if (
MI.getOpcode() == AMDGPU::SI_IF ||
MI.getOpcode() == AMDGPU::SI_ELSE ||
3109 MI.getOpcode() == AMDGPU::SI_LOOP ||
3110 MI.getOpcode() == AMDGPU::SI_WATERFALL_LOOP)
3122 "new block should be inserted for expanding unconditional branch");
3125 "restore block should be inserted for restoring clobbered registers");
3133 if (ST.useAddPC64Inst()) {
3135 MCCtx.createTempSymbol(
"offset",
true);
3139 MCCtx.createTempSymbol(
"post_addpc",
true);
3140 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
3144 Offset->setVariableValue(OffsetExpr);
3148 assert(RS &&
"RegScavenger required for long branching");
3156 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
3157 ST.hasVALUReadSGPRHazard();
3158 auto ApplyHazardWorkarounds = [
this, &
MBB, &
I, &
DL, FlushSGPRWrites]() {
3159 if (FlushSGPRWrites)
3167 ApplyHazardWorkarounds();
3170 MCCtx.createTempSymbol(
"post_getpc",
true);
3174 MCCtx.createTempSymbol(
"offset_lo",
true);
3176 MCCtx.createTempSymbol(
"offset_hi",
true);
3179 .
addReg(PCReg, {}, AMDGPU::sub0)
3183 .
addReg(PCReg, {}, AMDGPU::sub1)
3185 ApplyHazardWorkarounds();
3226 if (LongBranchReservedReg) {
3227 RS->enterBasicBlock(
MBB);
3228 Scav = LongBranchReservedReg;
3230 RS->enterBasicBlockEnd(
MBB);
3231 Scav = RS->scavengeRegisterBackwards(
3236 RS->setRegUsed(Scav);
3244 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
3261unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate
Cond) {
3263 case SIInstrInfo::SCC_TRUE:
3264 return AMDGPU::S_CBRANCH_SCC1;
3265 case SIInstrInfo::SCC_FALSE:
3266 return AMDGPU::S_CBRANCH_SCC0;
3267 case SIInstrInfo::VCCNZ:
3268 return AMDGPU::S_CBRANCH_VCCNZ;
3269 case SIInstrInfo::VCCZ:
3270 return AMDGPU::S_CBRANCH_VCCZ;
3271 case SIInstrInfo::EXECNZ:
3272 return AMDGPU::S_CBRANCH_EXECNZ;
3273 case SIInstrInfo::EXECZ:
3274 return AMDGPU::S_CBRANCH_EXECZ;
3280SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(
unsigned Opcode) {
3282 case AMDGPU::S_CBRANCH_SCC0:
3284 case AMDGPU::S_CBRANCH_SCC1:
3286 case AMDGPU::S_CBRANCH_VCCNZ:
3288 case AMDGPU::S_CBRANCH_VCCZ:
3290 case AMDGPU::S_CBRANCH_EXECNZ:
3292 case AMDGPU::S_CBRANCH_EXECZ:
3304 bool AllowModify)
const {
3305 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3307 TBB =
I->getOperand(0).getMBB();
3311 BranchPredicate Pred = getBranchPredicate(
I->getOpcode());
3312 if (Pred == INVALID_BR)
3317 Cond.push_back(
I->getOperand(1));
3321 if (
I ==
MBB.end()) {
3327 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3329 FBB =
I->getOperand(0).getMBB();
3339 bool AllowModify)
const {
3347 while (
I != E && !
I->isBranch() && !
I->isReturn()) {
3348 switch (
I->getOpcode()) {
3349 case AMDGPU::S_MOV_B64_term:
3350 case AMDGPU::S_XOR_B64_term:
3351 case AMDGPU::S_OR_B64_term:
3352 case AMDGPU::S_ANDN2_B64_term:
3353 case AMDGPU::S_AND_B64_term:
3354 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3355 case AMDGPU::S_MOV_B32_term:
3356 case AMDGPU::S_XOR_B32_term:
3357 case AMDGPU::S_OR_B32_term:
3358 case AMDGPU::S_ANDN2_B32_term:
3359 case AMDGPU::S_AND_B32_term:
3360 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3361 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3362 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3365 case AMDGPU::SI_ELSE:
3366 case AMDGPU::SI_KILL_I1_TERMINATOR:
3367 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3384 int *BytesRemoved)
const {
3386 unsigned RemovedSize = 0;
3389 if (
MI.isBranch() ||
MI.isReturn()) {
3391 MI.eraseFromParent();
3397 *BytesRemoved = RemovedSize;
3414 int *BytesAdded)
const {
3415 if (!FBB &&
Cond.empty()) {
3419 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3426 = getBranchOpcode(
static_cast<BranchPredicate
>(
Cond[0].
getImm()));
3438 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3456 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3463 if (
Cond.size() != 2) {
3467 if (
Cond[0].isImm()) {
3488 bool shouldIgnoreForPipelining(
const MachineInstr *
MI)
const override {
3492 std::optional<bool> createTripCountGreaterCondition(
3493 int TC, MachineBasicBlock &
MBB,
3494 SmallVectorImpl<MachineOperand> &CondParam)
override {
3495 CondParam = this->
Cond;
3499 void adjustTripCount(
int TripCountAdjust)
override {}
3501 void setPreheader(MachineBasicBlock *NewPreheader)
override {}
3505std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
3514 if (
TBB == LoopBB && FBB == LoopBB)
3521 assert((
TBB == LoopBB || FBB == LoopBB) &&
3522 "The Loop must be a single-basic-block loop");
3525 BranchPredicate Pred =
static_cast<BranchPredicate
>(
Cond[0].getImm());
3526 if (Pred != SCC_TRUE && Pred != SCC_FALSE)
3531 if (
MI.isCall() ||
MI.isInlineAsm())
3546 if (CmpI == Instructions.end() || CmpI->isPHI())
3550 return std::make_unique<AMDGPUPipelinerLoopInfo>(
CmpInst,
Cond);
3556 Register FalseReg,
int &CondCycles,
3557 int &TrueCycles,
int &FalseCycles)
const {
3567 CondCycles = TrueCycles = FalseCycles = NumInsts;
3570 return RI.hasVGPRs(RC) && NumInsts <= 6;
3584 if (NumInsts % 2 == 0)
3587 CondCycles = TrueCycles = FalseCycles = NumInsts;
3588 return RI.isSGPRClass(RC);
3599 BranchPredicate Pred =
static_cast<BranchPredicate
>(
Cond[0].getImm());
3600 if (Pred == VCCZ || Pred == SCC_FALSE) {
3601 Pred =
static_cast<BranchPredicate
>(-Pred);
3607 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3609 if (DstSize == 32) {
3611 if (Pred == SCC_TRUE) {
3626 if (DstSize == 64 && Pred == SCC_TRUE) {
3636 static const int16_t Sub0_15[] = {
3637 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3638 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3639 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3640 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3643 static const int16_t Sub0_15_64[] = {
3644 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3645 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3646 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3647 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3650 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3652 const int16_t *SubIndices = Sub0_15;
3653 int NElts = DstSize / 32;
3657 if (Pred == SCC_TRUE) {
3659 SelOp = AMDGPU::S_CSELECT_B32;
3660 EltRC = &AMDGPU::SGPR_32RegClass;
3662 SelOp = AMDGPU::S_CSELECT_B64;
3663 EltRC = &AMDGPU::SGPR_64RegClass;
3664 SubIndices = Sub0_15_64;
3670 MBB,
I,
DL,
get(AMDGPU::REG_SEQUENCE), DstReg);
3675 for (
int Idx = 0; Idx != NElts; ++Idx) {
3679 unsigned SubIdx = SubIndices[Idx];
3682 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3684 .
addReg(FalseReg, {}, SubIdx)
3685 .addReg(TrueReg, {}, SubIdx);
3688 .
addReg(TrueReg, {}, SubIdx)
3689 .addReg(FalseReg, {}, SubIdx);
3702 if (
MI.isBranch() ||
MI.isCall() ||
MI.isReturn() ||
MI.isIndirectBranch())
3705 switch (
MI.getOpcode()) {
3706 case AMDGPU::S_ENDPGM:
3707 case AMDGPU::S_ENDPGM_SAVED:
3708 case AMDGPU::S_TRAP:
3709 case AMDGPU::S_GETREG_B32:
3710 case AMDGPU::S_SETREG_B32:
3711 case AMDGPU::S_SETREG_B32_mode:
3712 case AMDGPU::S_SETREG_IMM32_B32:
3713 case AMDGPU::S_SETREG_IMM32_B32_mode:
3714 case AMDGPU::S_SENDMSG:
3715 case AMDGPU::S_SENDMSGHALT:
3716 case AMDGPU::S_SENDMSG_RTN_B32:
3717 case AMDGPU::S_SENDMSG_RTN_B64:
3718 case AMDGPU::S_BARRIER_WAIT:
3719 case AMDGPU::S_BARRIER_SIGNAL_M0:
3720 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3721 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3722 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3730 switch (
MI.getOpcode()) {
3731 case AMDGPU::V_MOV_B16_t16_e32:
3732 case AMDGPU::V_MOV_B16_t16_e64:
3733 case AMDGPU::V_MOV_B32_e32:
3734 case AMDGPU::V_MOV_B32_e64:
3735 case AMDGPU::V_MOV_B64_PSEUDO:
3736 case AMDGPU::V_MOV_B64_e32:
3737 case AMDGPU::V_MOV_B64_e64:
3738 case AMDGPU::S_MOV_B32:
3739 case AMDGPU::S_MOV_B64:
3740 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3742 case AMDGPU::WWM_COPY:
3743 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3744 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3745 case AMDGPU::V_ACCVGPR_MOV_B32:
3746 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3747 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3755 switch (
MI.getOpcode()) {
3756 case AMDGPU::V_MOV_B16_t16_e32:
3757 case AMDGPU::V_MOV_B16_t16_e64:
3759 case AMDGPU::V_MOV_B32_e32:
3760 case AMDGPU::V_MOV_B32_e64:
3761 case AMDGPU::V_MOV_B64_PSEUDO:
3762 case AMDGPU::V_MOV_B64_e32:
3763 case AMDGPU::V_MOV_B64_e64:
3764 case AMDGPU::S_MOV_B32:
3765 case AMDGPU::S_MOV_B64:
3766 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3768 case AMDGPU::WWM_COPY:
3769 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3770 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3771 case AMDGPU::V_ACCVGPR_MOV_B32:
3772 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3773 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3781 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3782 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3783 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3786 unsigned Opc =
MI.getOpcode();
3788 int Idx = AMDGPU::getNamedOperandIdx(
Opc, Name);
3790 MI.removeOperand(Idx);
3796 MI.setDesc(NewDesc);
3802 unsigned NumOps =
Desc.getNumOperands() +
Desc.implicit_uses().size() +
3803 Desc.implicit_defs().size();
3805 for (
unsigned I =
MI.getNumOperands() - 1;
I >=
NumOps; --
I)
3806 MI.removeOperand(
I);
3810 unsigned SubRegIndex) {
3811 switch (SubRegIndex) {
3812 case AMDGPU::NoSubRegister:
3822 case AMDGPU::sub1_lo16:
3824 case AMDGPU::sub1_hi16:
3827 return std::nullopt;
3835 case AMDGPU::V_MAC_F16_e32:
3836 case AMDGPU::V_MAC_F16_e64:
3837 case AMDGPU::V_MAD_F16_e64:
3838 return AMDGPU::V_MADAK_F16;
3839 case AMDGPU::V_MAC_F32_e32:
3840 case AMDGPU::V_MAC_F32_e64:
3841 case AMDGPU::V_MAD_F32_e64:
3842 return AMDGPU::V_MADAK_F32;
3843 case AMDGPU::V_FMAC_F32_e32:
3844 case AMDGPU::V_FMAC_F32_e64:
3845 case AMDGPU::V_FMA_F32_e64:
3846 return AMDGPU::V_FMAAK_F32;
3847 case AMDGPU::V_FMAC_F16_e32:
3848 case AMDGPU::V_FMAC_F16_e64:
3849 case AMDGPU::V_FMAC_F16_t16_e64:
3850 case AMDGPU::V_FMAC_F16_fake16_e64:
3851 case AMDGPU::V_FMAC_F16_t16_e32:
3852 case AMDGPU::V_FMAC_F16_fake16_e32:
3853 case AMDGPU::V_FMA_F16_e64:
3854 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3855 ? AMDGPU::V_FMAAK_F16_t16
3856 : AMDGPU::V_FMAAK_F16_fake16
3857 : AMDGPU::V_FMAAK_F16;
3858 case AMDGPU::V_FMAC_F64_e32:
3859 case AMDGPU::V_FMAC_F64_e64:
3860 case AMDGPU::V_FMA_F64_e64:
3861 return AMDGPU::V_FMAAK_F64;
3869 case AMDGPU::V_MAC_F16_e32:
3870 case AMDGPU::V_MAC_F16_e64:
3871 case AMDGPU::V_MAD_F16_e64:
3872 return AMDGPU::V_MADMK_F16;
3873 case AMDGPU::V_MAC_F32_e32:
3874 case AMDGPU::V_MAC_F32_e64:
3875 case AMDGPU::V_MAD_F32_e64:
3876 return AMDGPU::V_MADMK_F32;
3877 case AMDGPU::V_FMAC_F32_e32:
3878 case AMDGPU::V_FMAC_F32_e64:
3879 case AMDGPU::V_FMA_F32_e64:
3880 return AMDGPU::V_FMAMK_F32;
3881 case AMDGPU::V_FMAC_F16_e32:
3882 case AMDGPU::V_FMAC_F16_e64:
3883 case AMDGPU::V_FMAC_F16_t16_e64:
3884 case AMDGPU::V_FMAC_F16_fake16_e64:
3885 case AMDGPU::V_FMAC_F16_t16_e32:
3886 case AMDGPU::V_FMAC_F16_fake16_e32:
3887 case AMDGPU::V_FMA_F16_e64:
3888 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3889 ? AMDGPU::V_FMAMK_F16_t16
3890 : AMDGPU::V_FMAMK_F16_fake16
3891 : AMDGPU::V_FMAMK_F16;
3892 case AMDGPU::V_FMAC_F64_e32:
3893 case AMDGPU::V_FMAC_F64_e64:
3894 case AMDGPU::V_FMA_F64_e64:
3895 return AMDGPU::V_FMAMK_F64;
3909 assert(!
DefMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3912 if (
Opc == AMDGPU::COPY) {
3913 assert(!
UseMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3920 if (HasMultipleUses) {
3923 unsigned ImmDefSize = RI.getRegSizeInBits(*MRI->
getRegClass(Reg));
3926 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3934 if (ImmDefSize == 32 &&
3939 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3940 RI.getSubRegIdxSize(UseSubReg) == 16;
3943 if (RI.hasVGPRs(DstRC))
3946 if (DstReg.
isVirtual() && UseSubReg != AMDGPU::lo16)
3952 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
3959 for (
unsigned MovOp :
3960 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
3961 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
3969 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
3973 if (MovDstPhysReg) {
3977 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
3984 if (MovDstPhysReg) {
3985 if (!MovDstRC->
contains(MovDstPhysReg))
4001 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
4009 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
4013 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
4015 UseMI.getOperand(0).setReg(MovDstPhysReg);
4020 UseMI.setDesc(NewMCID);
4021 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
4022 UseMI.addImplicitDefUseOperands(*MF);
4026 if (HasMultipleUses)
4029 if (
Opc == AMDGPU::V_MAD_F32_e64 ||
Opc == AMDGPU::V_MAC_F32_e64 ||
4030 Opc == AMDGPU::V_MAD_F16_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4031 Opc == AMDGPU::V_FMA_F32_e64 ||
Opc == AMDGPU::V_FMAC_F32_e64 ||
4032 Opc == AMDGPU::V_FMA_F16_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64 ||
4033 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4034 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
Opc == AMDGPU::V_FMA_F64_e64 ||
4035 Opc == AMDGPU::V_FMAC_F64_e64) {
4044 int Src0Idx = getNamedOperandIdx(
UseMI.getOpcode(), AMDGPU::OpName::src0);
4055 auto CopyRegOperandToNarrowerRC =
4058 if (!
MI.getOperand(OpNo).isReg())
4062 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
4065 BuildMI(*
MI.getParent(),
MI.getIterator(),
MI.getDebugLoc(),
4066 get(AMDGPU::COPY), Tmp)
4068 MI.getOperand(OpNo).setReg(Tmp);
4069 MI.getOperand(OpNo).setIsKill();
4076 Src1->
isReg() && Src1->
getReg() == Reg ? Src0 : Src1;
4077 if (!RegSrc->
isReg())
4080 ST.getConstantBusLimit(
Opc) < 2)
4095 if (Def && Def->isMoveImmediate() &&
4110 unsigned SrcSubReg = RegSrc->
getSubReg();
4115 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4116 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4117 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4118 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
4119 UseMI.untieRegOperand(
4120 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
4127 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
4128 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
4132 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
4133 UseMI.getOperand(0).getReg())
4135 UseMI.getOperand(0).setReg(Tmp);
4136 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
4137 CopyRegOperandToNarrowerRC(
UseMI, 3, NewRC);
4142 DefMI.eraseFromParent();
4149 if (ST.getConstantBusLimit(
Opc) < 2) {
4152 bool Src0Inlined =
false;
4153 if (Src0->
isReg()) {
4158 if (Def && Def->isMoveImmediate() &&
4163 }
else if (ST.getConstantBusLimit(
Opc) <= 1 &&
4164 RI.isSGPRReg(*MRI, Src0->
getReg())) {
4170 if (Src1->
isReg() && !Src0Inlined) {
4173 if (Def && Def->isMoveImmediate() &&
4177 else if (RI.isSGPRReg(*MRI, Src1->
getReg()))
4190 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4191 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4192 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4193 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
4194 UseMI.untieRegOperand(
4195 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
4197 const std::optional<int64_t> SubRegImm =
4207 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
4208 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
4212 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
4213 UseMI.getOperand(0).getReg())
4215 UseMI.getOperand(0).setReg(Tmp);
4216 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
4217 CopyRegOperandToNarrowerRC(
UseMI, 2, NewRC);
4226 AMDGPU::getNamedOperandIdx(
UseMI.getOpcode(), AMDGPU::OpName::src0);
4232 DefMI.eraseFromParent();
4244 if (BaseOps1.
size() != BaseOps2.
size())
4246 for (
size_t I = 0,
E = BaseOps1.
size();
I <
E; ++
I) {
4247 if (!BaseOps1[
I]->isIdenticalTo(*BaseOps2[
I]))
4255 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
4256 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
4257 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
4259 LowOffset + (int)LowWidth.
getValue() <= HighOffset;
4262bool SIInstrInfo::checkInstOffsetsDoNotOverlap(
const MachineInstr &MIa,
4265 int64_t Offset0, Offset1;
4268 bool Offset0IsScalable, Offset1IsScalable;
4282 LocationSize Width0 = MIa.
memoperands().front()->getSize();
4283 LocationSize Width1 = MIb.
memoperands().front()->getSize();
4290 "MIa must load from or modify a memory location");
4292 "MIb must load from or modify a memory location");
4314 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4321 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4331 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4345 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4357 unsigned NumOps =
MI.getNumOperands();
4360 if (
Op.isReg() &&
Op.isKill())
4368 case AMDGPU::V_MAC_F16_e32:
4369 case AMDGPU::V_MAC_F16_e64:
4370 return AMDGPU::V_MAD_F16_e64;
4371 case AMDGPU::V_MAC_F32_e32:
4372 case AMDGPU::V_MAC_F32_e64:
4373 return AMDGPU::V_MAD_F32_e64;
4374 case AMDGPU::V_MAC_LEGACY_F32_e32:
4375 case AMDGPU::V_MAC_LEGACY_F32_e64:
4376 return AMDGPU::V_MAD_LEGACY_F32_e64;
4377 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4378 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4379 return AMDGPU::V_FMA_LEGACY_F32_e64;
4380 case AMDGPU::V_FMAC_F16_e32:
4381 case AMDGPU::V_FMAC_F16_e64:
4382 case AMDGPU::V_FMAC_F16_t16_e64:
4383 case AMDGPU::V_FMAC_F16_fake16_e64:
4384 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4385 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4386 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4387 : AMDGPU::V_FMA_F16_gfx9_e64;
4388 case AMDGPU::V_FMAC_F32_e32:
4389 case AMDGPU::V_FMAC_F32_e64:
4390 return AMDGPU::V_FMA_F32_e64;
4391 case AMDGPU::V_FMAC_F64_e32:
4392 case AMDGPU::V_FMAC_F64_e64:
4393 return AMDGPU::V_FMA_F64_e64;
4413 if (
MI.isBundle()) {
4416 if (
MI.getBundleSize() != 1)
4418 CandidateMI =
MI.getNextNode();
4422 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4426 if (
MI.isBundle()) {
4431 MI.untieRegOperand(MO.getOperandNo());
4439 if (Def.isEarlyClobber() && Def.isReg() &&
4444 auto UpdateDefIndex = [&](
LiveRange &LR) {
4445 auto *S = LR.find(OldIndex);
4446 if (S != LR.end() && S->start == OldIndex) {
4447 assert(S->valno && S->valno->def == OldIndex);
4448 S->start = NewIndex;
4449 S->valno->def = NewIndex;
4453 for (
auto &SR : LI.subranges())
4459 if (U.RemoveMIUse) {
4462 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4466 U.RemoveMIUse->setDesc(
get(AMDGPU::IMPLICIT_DEF));
4467 U.RemoveMIUse->getOperand(0).setIsDead(
true);
4468 for (
unsigned I = U.RemoveMIUse->getNumOperands() - 1;
I != 0; --
I)
4469 U.RemoveMIUse->removeOperand(
I);
4474 if (
MI.isBundle()) {
4478 if (MO.isReg() && MO.getReg() == DefReg) {
4479 assert(MO.getSubReg() == 0 &&
4480 "tied sub-registers in bundles currently not supported");
4481 MI.removeOperand(MO.getOperandNo());
4498 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4499 MIOp.setIsUndef(
true);
4500 MIOp.setReg(DummyReg);
4504 if (
MI.isBundle()) {
4508 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4509 MIOp.setIsUndef(
true);
4510 MIOp.setReg(DummyReg);
4523 return MI.isBundle() ? &
MI : NewMI;
4528 ThreeAddressUpdates &U)
const {
4530 unsigned Opc =
MI.getOpcode();
4534 if (NewMFMAOpc != -1) {
4537 for (
unsigned I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I)
4538 MIB.
add(
MI.getOperand(
I));
4546 for (
unsigned I = 0,
E =
MI.getNumExplicitOperands();
I !=
E; ++
I)
4551 assert(
Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4552 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4553 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4557 bool IsF64 =
Opc == AMDGPU::V_FMAC_F64_e32 ||
Opc == AMDGPU::V_FMAC_F64_e64;
4558 bool IsLegacy =
Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4559 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4560 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4561 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4562 bool Src0Literal =
false;
4567 case AMDGPU::V_MAC_F16_e64:
4568 case AMDGPU::V_FMAC_F16_e64:
4569 case AMDGPU::V_FMAC_F16_t16_e64:
4570 case AMDGPU::V_FMAC_F16_fake16_e64:
4571 case AMDGPU::V_MAC_F32_e64:
4572 case AMDGPU::V_MAC_LEGACY_F32_e64:
4573 case AMDGPU::V_FMAC_F32_e64:
4574 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4575 case AMDGPU::V_FMAC_F64_e64:
4577 case AMDGPU::V_MAC_F16_e32:
4578 case AMDGPU::V_FMAC_F16_e32:
4579 case AMDGPU::V_MAC_F32_e32:
4580 case AMDGPU::V_MAC_LEGACY_F32_e32:
4581 case AMDGPU::V_FMAC_F32_e32:
4582 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4583 case AMDGPU::V_FMAC_F64_e32: {
4584 int Src0Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
4585 AMDGPU::OpName::src0);
4586 const MachineOperand *Src0 = &
MI.getOperand(Src0Idx);
4597 MachineInstrBuilder MIB;
4600 const MachineOperand *Src0Mods =
4603 const MachineOperand *Src1Mods =
4606 const MachineOperand *Src2Mods =
4612 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4613 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4615 (ST.getConstantBusLimit(
Opc) > 1 || !Src0->
isReg() ||
4617 MachineInstr *
DefMI =
nullptr;
4619 std::optional<int64_t> ImmOpt;
4654 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4670 if (Src0Literal && !ST.hasVOP3Literal())
4698 switch (
MI.getOpcode()) {
4699 case AMDGPU::S_SET_GPR_IDX_ON:
4700 case AMDGPU::S_SET_GPR_IDX_MODE:
4701 case AMDGPU::S_SET_GPR_IDX_OFF:
4719 if (
MI.isTerminator() ||
MI.isPosition())
4723 if (
MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4726 if (
MI.getOpcode() == AMDGPU::SCHED_BARRIER &&
MI.getOperand(0).getImm() == 0)
4732 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4733 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4734 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4735 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4736 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4741 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4742 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4743 Opcode == AMDGPU::DS_SUB_GS_REG_RTN ||
isGWS(Opcode);
4757 if (
MI.getMF()->getFunction().hasFnAttribute(
"amdgpu-no-flat-scratch-init"))
4762 if (
MI.memoperands_empty())
4767 unsigned AS = Memop->getAddrSpace();
4768 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4769 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4770 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4771 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4786 if (
MI.memoperands_empty())
4795 unsigned AS = Memop->getAddrSpace();
4805 bool TgSplit)
const {
4818 if (
MI.memoperands_empty())
4823 unsigned AS = Memop->getAddrSpace();
4839 unsigned Opcode =
MI.getOpcode();
4854 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4855 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4856 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4857 Opcode == AMDGPU::S_SETHALT)
4860 if (
MI.isCall() ||
MI.isInlineAsm())
4876 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4877 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4878 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4879 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4887 if (
MI.isMetaInstruction())
4891 if (
MI.isCopyLike()) {
4892 if (!RI.isSGPRReg(MRI,
MI.getOperand(0).getReg()))
4896 return MI.readsRegister(AMDGPU::EXEC, &RI);
4907 return !
isSALU(
MI) ||
MI.readsRegister(AMDGPU::EXEC, &RI);
4911 switch (
Imm.getBitWidth()) {
4917 ST.hasInv2PiInlineImm());
4920 ST.hasInv2PiInlineImm());
4922 return ST.has16BitInsts() &&
4924 ST.hasInv2PiInlineImm());
4931 APInt IntImm =
Imm.bitcastToAPInt();
4933 bool HasInv2Pi = ST.hasInv2PiInlineImm();
4941 return ST.has16BitInsts() &&
4944 return ST.has16BitInsts() &&
4954 switch (OperandType) {
4964 int32_t Trunc =
static_cast<int32_t
>(
Imm);
5008 int16_t Trunc =
static_cast<int16_t
>(
Imm);
5009 return ST.has16BitInsts() &&
5018 int16_t Trunc =
static_cast<int16_t
>(
Imm);
5019 return ST.has16BitInsts() &&
5071 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
5077 return ST.hasVOP3Literal();
5081 int64_t ImmVal)
const {
5083 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
5084 if (Src1Idx != -1 &&
isDPP(
Opc) && !ST.hasDPPSrc1SGPR() &&
5085 OpNo ==
static_cast<unsigned>(Src1Idx))
5090 if (
isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
5091 OpNo == (
unsigned)AMDGPU::getNamedOperandIdx(InstDesc.
getOpcode(),
5092 AMDGPU::OpName::src2))
5095 if (ST.hasBF16InlineConstFromUpperFP32() &&
isVOP1(
Opc)) {
5102 return RI.opCanUseInlineConstant(OpInfo.OperandType);
5114 "unexpected imm-like operand kind");
5127 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
5145 AMDGPU::OpName
OpName)
const {
5147 return Mods && Mods->
getImm();
5160 switch (
MI.getOpcode()) {
5161 default:
return false;
5163 case AMDGPU::V_ADDC_U32_e64:
5164 case AMDGPU::V_SUBB_U32_e64:
5165 case AMDGPU::V_SUBBREV_U32_e64: {
5168 if (!Src1->
isReg() || !RI.isVGPR(MRI, Src1->
getReg()))
5173 case AMDGPU::V_MAC_F16_e64:
5174 case AMDGPU::V_MAC_F32_e64:
5175 case AMDGPU::V_MAC_LEGACY_F32_e64:
5176 case AMDGPU::V_FMAC_F16_e64:
5177 case AMDGPU::V_FMAC_F16_t16_e64:
5178 case AMDGPU::V_FMAC_F16_fake16_e64:
5179 case AMDGPU::V_FMAC_F32_e64:
5180 case AMDGPU::V_FMAC_F64_e64:
5181 case AMDGPU::V_FMAC_LEGACY_F32_e64:
5182 if (!Src2->
isReg() || !RI.isVGPR(MRI, Src2->
getReg()) ||
5187 case AMDGPU::V_CNDMASK_B32_e64:
5193 if (Src1 && (!Src1->
isReg() || !RI.isVGPR(MRI, Src1->
getReg()) ||
5206 if (Src0 && Src0->
isImm()) {
5209 get(Op32), AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src0),
5231 (
Use.getReg() == AMDGPU::VCC ||
Use.getReg() == AMDGPU::VCC_LO)) {
5240 unsigned Op32)
const {
5254 Inst32.
add(
MI.getOperand(
I));
5258 int Idx =
MI.getNumExplicitDefs();
5260 int OpTy =
MI.getDesc().operands()[Idx++].OperandType;
5265 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
5287 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5295 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5298 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5299 AMDGPU::SReg_64RegClass.contains(Reg);
5327 switch (MO.getReg()) {
5329 case AMDGPU::VCC_LO:
5330 case AMDGPU::VCC_HI:
5332 case AMDGPU::FLAT_SCR:
5345 switch (
MI.getOpcode()) {
5346 case AMDGPU::V_READLANE_B32:
5347 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5348 case AMDGPU::V_WRITELANE_B32:
5349 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5356 if (
MI.isPreISelOpcode() ||
5357 SIInstrInfo::isGenericOpcode(
MI.getOpcode()) ||
5375 return SubReg.
getSubReg() != AMDGPU::NoSubRegister &&
5386 if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
5387 ErrInfo =
"illegal copy from vector register to SGPR";
5405 if (!MRI.
isSSA() &&
MI.isCopy())
5406 return verifyCopy(
MI, MRI, ErrInfo);
5408 if (SIInstrInfo::isGenericOpcode(Opcode))
5411 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5412 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5413 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5415 if (Src0Idx == -1) {
5417 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5418 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5419 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5420 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5425 if (!
Desc.isVariadic() &&
5426 Desc.getNumOperands() !=
MI.getNumExplicitOperands()) {
5427 ErrInfo =
"Instruction has wrong number of operands.";
5431 if (
MI.isInlineAsm()) {
5444 if (!Reg.isVirtual() && !RC->
contains(Reg)) {
5445 ErrInfo =
"inlineasm operand has incorrect register class.";
5453 if (
isImage(
MI) &&
MI.memoperands_empty() &&
MI.mayLoadOrStore()) {
5454 ErrInfo =
"missing memory operand from image instruction.";
5459 for (
int i = 0, e =
Desc.getNumOperands(); i != e; ++i) {
5462 ErrInfo =
"FPImm Machine Operands are not supported. ISel should bitcast "
5463 "all fp values to integers.";
5469 switch (OpInfo.OperandType) {
5471 if (
MI.getOperand(i).isImm() ||
MI.getOperand(i).isGlobal()) {
5472 ErrInfo =
"Illegal immediate value for operand.";
5504 ErrInfo =
"Illegal immediate value for operand.";
5513 if (ST.has64BitLiterals() &&
Desc.getSize() != 4 && MO.
isImm() &&
5516 OpInfo.OperandType ==
5518 ErrInfo =
"illegal 64-bit immediate value for operand.";
5525 ErrInfo =
"Expected inline constant for operand.";
5539 if (!
MI.getOperand(i).isImm() && !
MI.getOperand(i).isFI()) {
5540 ErrInfo =
"Expected immediate, but got non-immediate";
5549 if (OpInfo.isGenericType())
5557 if (!ST.hasSDWA()) {
5558 ErrInfo =
"SDWA is not supported on this target";
5562 for (
auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5563 AMDGPU::OpName::dst_sel}) {
5569 ErrInfo =
"Invalid SDWA selection";
5574 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5576 for (
int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5581 if (!ST.hasSDWAScalar()) {
5583 if (!MO.
isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.
getReg()))) {
5584 ErrInfo =
"Only VGPRs allowed as operands in SDWA instructions on VI";
5591 "Only reg allowed as operands in SDWA instructions on GFX9+";
5597 if (!ST.hasSDWAOmod()) {
5600 if (OMod !=
nullptr &&
5602 ErrInfo =
"OMod not allowed in SDWA instructions on VI";
5607 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5608 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5609 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5610 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5613 unsigned Mods = Src0ModsMO->
getImm();
5616 ErrInfo =
"sext, abs and neg are not allowed on this instruction";
5622 if (
isVOPC(BasicOpcode)) {
5623 if (!ST.hasSDWASdst() && DstIdx != -1) {
5626 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5627 ErrInfo =
"Only VCC allowed as dst in SDWA instructions on VI";
5630 }
else if (!ST.hasSDWAOutModsVOPC()) {
5633 if (Clamp && (!Clamp->
isImm() || Clamp->
getImm() != 0)) {
5634 ErrInfo =
"Clamp not allowed in VOPC SDWA instructions on VI";
5640 if (OMod && (!OMod->
isImm() || OMod->
getImm() != 0)) {
5641 ErrInfo =
"OMod not allowed in VOPC SDWA instructions on VI";
5648 if (DstUnused && DstUnused->isImm() &&
5651 if (!Dst.isReg() || !Dst.isTied()) {
5652 ErrInfo =
"Dst register should have tied register";
5657 MI.getOperand(
MI.findTiedOperandIdx(DstIdx));
5660 "Dst register should be tied to implicit use of preserved register";
5664 ErrInfo =
"Dst register should use same physical register as preserved";
5670 if (
isDPP(
MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5672 if (Src1MO.
isReg() && RI.isSGPRReg(MRI, Src1MO.
getReg())) {
5673 ErrInfo =
"DPP src1 cannot be SGPR on this subtarget";
5676 if (Src1MO.
isImm()) {
5677 ErrInfo =
"DPP src1 cannot be an immediate on this subtarget";
5683 if (
isImage(Opcode) && !
MI.mayStore()) {
5688 uint64_t DMaskImm = DMask->
getImm();
5695 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5703 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5707 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5708 if (RegCount > DstSize) {
5709 ErrInfo =
"Image instruction returns too many registers for dst "
5719 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5720 unsigned ConstantBusCount = 0;
5721 bool UsesLiteral =
false;
5724 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5728 LiteralVal = &
MI.getOperand(ImmIdx);
5737 for (
int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5748 }
else if (!MO.
isFI()) {
5755 ErrInfo =
"VOP2/VOP3 instruction uses more than one literal";
5765 if (
llvm::all_of(SGPRsUsed, [
this, SGPRUsed](
unsigned SGPR) {
5766 return !RI.regsOverlap(SGPRUsed, SGPR);
5775 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5776 Opcode != AMDGPU::V_WRITELANE_B32) {
5777 ErrInfo =
"VOP* instruction violates constant bus restriction";
5781 if (
isVOP3(
MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5782 ErrInfo =
"VOP3 instruction uses literal";
5789 if (
Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5790 unsigned SGPRCount = 0;
5793 for (
int OpIdx : {Src0Idx, Src1Idx}) {
5801 if (MO.
getReg() != SGPRUsed)
5806 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5807 ErrInfo =
"WRITELANE instruction violates constant bus restriction";
5814 if (
Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5815 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5822 ErrInfo =
"v_div_scale_{f32|f64} require src0 = src1 or src2";
5832 ErrInfo =
"ABS not allowed in VOP3B instructions";
5845 ErrInfo =
"SOP2/SOPC instruction requires too many immediate constants";
5852 if (
Desc.isBranch()) {
5854 ErrInfo =
"invalid branch target for SOPK instruction";
5858 uint64_t
Imm =
Op->getImm();
5861 ErrInfo =
"invalid immediate for SOPK instruction";
5866 ErrInfo =
"invalid immediate for SOPK instruction";
5873 if (
Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
5874 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
5875 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5876 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
5877 const bool IsDst =
Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5878 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
5880 const unsigned StaticNumOps =
5881 Desc.getNumOperands() +
Desc.implicit_uses().size();
5882 const unsigned NumImplicitOps = IsDst ? 2 : 1;
5888 if (
MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
5889 ErrInfo =
"missing implicit register operands";
5895 if (!Dst->isUse()) {
5896 ErrInfo =
"v_movreld_b32 vdst should be a use operand";
5901 if (!
MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
5902 UseOpIdx != StaticNumOps + 1) {
5903 ErrInfo =
"movrel implicit operands should be tied";
5910 =
MI.getOperand(StaticNumOps + NumImplicitOps - 1);
5912 !
isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
5913 ErrInfo =
"src0 should be subreg of implicit vector use";
5921 if (!
MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
5922 ErrInfo =
"VALU instruction does not implicitly read exec mask";
5928 if (
MI.mayStore() &&
5933 if (Soff && Soff->
getReg() != AMDGPU::M0) {
5934 ErrInfo =
"scalar stores must use m0 as offset register";
5940 if (
isFLAT(
MI) && !ST.hasFlatInstOffsets()) {
5942 if (
Offset->getImm() != 0) {
5943 ErrInfo =
"subtarget does not support offsets in flat instructions";
5948 if (
isDS(
MI) && !ST.hasGDS()) {
5950 if (GDSOp && GDSOp->
getImm() != 0) {
5951 ErrInfo =
"GDS is not supported on this subtarget";
5959 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
5960 AMDGPU::OpName::vaddr0);
5961 AMDGPU::OpName RSrcOpName =
5962 isMIMG(
MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
5963 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
5971 ErrInfo =
"dim is out of range";
5976 if (ST.hasR128A16()) {
5978 IsA16 = R128A16->
getImm() != 0;
5979 }
else if (ST.hasA16()) {
5981 IsA16 = A16->
getImm() != 0;
5984 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
5986 unsigned AddrWords =
5989 unsigned VAddrWords;
5991 VAddrWords = RsrcIdx - VAddr0Idx;
5992 if (ST.hasPartialNSAEncoding() &&
5994 unsigned LastVAddrIdx = RsrcIdx - 1;
5995 VAddrWords +=
getOpSize(
MI, LastVAddrIdx) / 4 - 1;
6003 if (VAddrWords != AddrWords) {
6005 <<
" but got " << VAddrWords <<
"\n");
6006 ErrInfo =
"bad vaddr size";
6016 unsigned DC = DppCt->
getImm();
6017 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
6018 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
6019 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
6020 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
6021 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
6022 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
6023 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
6024 ErrInfo =
"Invalid dpp_ctrl value";
6027 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
6028 !ST.hasDPPWavefrontShifts()) {
6029 ErrInfo =
"Invalid dpp_ctrl value: "
6030 "wavefront shifts are not supported on GFX10+";
6033 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
6034 !ST.hasDPPBroadcasts()) {
6035 ErrInfo =
"Invalid dpp_ctrl value: "
6036 "broadcasts are not supported on GFX10+";
6039 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
6041 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
6042 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
6043 !ST.hasGFX90AInsts()) {
6044 ErrInfo =
"Invalid dpp_ctrl value: "
6045 "row_newbroadcast/row_share is not supported before "
6049 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
6050 ErrInfo =
"Invalid dpp_ctrl value: "
6051 "row_share and row_xmask are not supported before GFX10";
6056 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
6059 ErrInfo =
"Invalid dpp_ctrl value: "
6060 "DP ALU dpp only support row_newbcast";
6067 AMDGPU::OpName DataName =
6068 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
6074 if (!ST.hasGFX90AInsts()) {
6075 if ((Dst && RI.isAGPR(MRI, Dst->getReg())) ||
6076 (
Data && RI.isAGPR(MRI,
Data->getReg())) ||
6077 (Data2 && RI.isAGPR(MRI, Data2->
getReg()))) {
6078 ErrInfo =
"Invalid register class: "
6079 "agpr loads and stores not supported on this GPU";
6085 if (ST.needsAlignedVGPRs()) {
6086 const auto isAlignedReg = [&
MI, &MRI,
this](AMDGPU::OpName
OpName) ->
bool {
6091 if (Reg.isPhysical())
6092 return !(RI.getHWRegIndex(Reg) & 1);
6094 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
6095 !(RI.getChannelFromSubReg(
Op->getSubReg()) & 1);
6099 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
6100 ErrInfo =
"Subtarget requires even aligned vector registers "
6101 "for vaddr operand of image instructions";
6107 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
6109 if (Src->isReg() && RI.isSGPRReg(MRI, Src->getReg())) {
6110 ErrInfo =
"Invalid register class: "
6111 "v_accvgpr_write with an SGPR is not supported on this GPU";
6116 if (
Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
6119 ErrInfo =
"pseudo expects only physical SGPRs";
6126 if (!ST.hasScaleOffset()) {
6127 ErrInfo =
"Subtarget does not support offset scaling";
6131 ErrInfo =
"Instruction does not support offset scaling";
6139 for (
unsigned I = 0;
I < 3; ++
I) {
6145 if (ST.hasFlatScratchHiInB64InstHazard() &&
isSALU(
MI) &&
6146 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI,
nullptr)) {
6148 if ((Dst && RI.getRegClassForReg(MRI, Dst->getReg()) ==
6149 &AMDGPU::SReg_64RegClass) ||
6150 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
6151 ErrInfo =
"Instruction cannot read flat_scratch_base_hi";
6160 if (
MI.getOpcode() == AMDGPU::S_MOV_B32) {
6162 return MI.getOperand(1).isReg() || RI.isAGPR(MRI,
MI.getOperand(0).getReg())
6164 : AMDGPU::V_MOV_B32_e32;
6174 default:
return AMDGPU::INSTRUCTION_LIST_END;
6175 case AMDGPU::REG_SEQUENCE:
return AMDGPU::REG_SEQUENCE;
6176 case AMDGPU::COPY:
return AMDGPU::COPY;
6177 case AMDGPU::PHI:
return AMDGPU::PHI;
6178 case AMDGPU::INSERT_SUBREG:
return AMDGPU::INSERT_SUBREG;
6179 case AMDGPU::WQM:
return AMDGPU::WQM;
6180 case AMDGPU::SOFT_WQM:
return AMDGPU::SOFT_WQM;
6181 case AMDGPU::STRICT_WWM:
return AMDGPU::STRICT_WWM;
6182 case AMDGPU::STRICT_WQM:
return AMDGPU::STRICT_WQM;
6183 case AMDGPU::S_ADD_I32:
6184 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
6185 case AMDGPU::S_ADDC_U32:
6186 return AMDGPU::V_ADDC_U32_e32;
6187 case AMDGPU::S_SUB_I32:
6188 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
6191 case AMDGPU::S_ADD_U32:
6192 return AMDGPU::V_ADD_CO_U32_e32;
6193 case AMDGPU::S_SUB_U32:
6194 return AMDGPU::V_SUB_CO_U32_e32;
6195 case AMDGPU::S_ADD_U64_PSEUDO:
6196 return AMDGPU::V_ADD_U64_PSEUDO;
6197 case AMDGPU::S_SUB_U64_PSEUDO:
6198 return AMDGPU::V_SUB_U64_PSEUDO;
6199 case AMDGPU::S_SUBB_U32:
return AMDGPU::V_SUBB_U32_e32;
6200 case AMDGPU::S_MUL_I32:
return AMDGPU::V_MUL_LO_U32_e64;
6201 case AMDGPU::S_MUL_HI_U32:
return AMDGPU::V_MUL_HI_U32_e64;
6202 case AMDGPU::S_MUL_HI_I32:
return AMDGPU::V_MUL_HI_I32_e64;
6203 case AMDGPU::S_AND_B32:
return AMDGPU::V_AND_B32_e64;
6204 case AMDGPU::S_OR_B32:
return AMDGPU::V_OR_B32_e64;
6205 case AMDGPU::S_XOR_B32:
return AMDGPU::V_XOR_B32_e64;
6206 case AMDGPU::S_XNOR_B32:
6207 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6208 case AMDGPU::S_MIN_I32:
return AMDGPU::V_MIN_I32_e64;
6209 case AMDGPU::S_MIN_U32:
return AMDGPU::V_MIN_U32_e64;
6210 case AMDGPU::S_MAX_I32:
return AMDGPU::V_MAX_I32_e64;
6211 case AMDGPU::S_MAX_U32:
return AMDGPU::V_MAX_U32_e64;
6212 case AMDGPU::S_ASHR_I32:
return AMDGPU::V_ASHR_I32_e32;
6213 case AMDGPU::S_ASHR_I64:
return AMDGPU::V_ASHR_I64_e64;
6214 case AMDGPU::S_LSHL_B32:
return AMDGPU::V_LSHL_B32_e32;
6215 case AMDGPU::S_LSHL_B64:
return AMDGPU::V_LSHL_B64_e64;
6216 case AMDGPU::S_LSHR_B32:
return AMDGPU::V_LSHR_B32_e32;
6217 case AMDGPU::S_LSHR_B64:
return AMDGPU::V_LSHR_B64_e64;
6218 case AMDGPU::S_SEXT_I32_I8:
return AMDGPU::V_BFE_I32_e64;
6219 case AMDGPU::S_SEXT_I32_I16:
return AMDGPU::V_BFE_I32_e64;
6220 case AMDGPU::S_BFE_U32:
return AMDGPU::V_BFE_U32_e64;
6221 case AMDGPU::S_BFE_I32:
return AMDGPU::V_BFE_I32_e64;
6222 case AMDGPU::S_BFM_B32:
return AMDGPU::V_BFM_B32_e64;
6223 case AMDGPU::S_BREV_B32:
return AMDGPU::V_BFREV_B32_e32;
6224 case AMDGPU::S_NOT_B32:
return AMDGPU::V_NOT_B32_e32;
6225 case AMDGPU::S_NOT_B64:
return AMDGPU::V_NOT_B32_e32;
6226 case AMDGPU::S_CMP_EQ_I32:
return AMDGPU::V_CMP_EQ_I32_e64;
6227 case AMDGPU::S_CMP_LG_I32:
return AMDGPU::V_CMP_NE_I32_e64;
6228 case AMDGPU::S_CMP_GT_I32:
return AMDGPU::V_CMP_GT_I32_e64;
6229 case AMDGPU::S_CMP_GE_I32:
return AMDGPU::V_CMP_GE_I32_e64;
6230 case AMDGPU::S_CMP_LT_I32:
return AMDGPU::V_CMP_LT_I32_e64;
6231 case AMDGPU::S_CMP_LE_I32:
return AMDGPU::V_CMP_LE_I32_e64;
6232 case AMDGPU::S_CMP_EQ_U32:
return AMDGPU::V_CMP_EQ_U32_e64;
6233 case AMDGPU::S_CMP_LG_U32:
return AMDGPU::V_CMP_NE_U32_e64;
6234 case AMDGPU::S_CMP_GT_U32:
return AMDGPU::V_CMP_GT_U32_e64;
6235 case AMDGPU::S_CMP_GE_U32:
return AMDGPU::V_CMP_GE_U32_e64;
6236 case AMDGPU::S_CMP_LT_U32:
return AMDGPU::V_CMP_LT_U32_e64;
6237 case AMDGPU::S_CMP_LE_U32:
return AMDGPU::V_CMP_LE_U32_e64;
6238 case AMDGPU::S_CMP_EQ_U64:
return AMDGPU::V_CMP_EQ_U64_e64;
6239 case AMDGPU::S_CMP_LG_U64:
return AMDGPU::V_CMP_NE_U64_e64;
6240 case AMDGPU::S_BCNT1_I32_B32:
return AMDGPU::V_BCNT_U32_B32_e64;
6241 case AMDGPU::S_FF1_I32_B32:
return AMDGPU::V_FFBL_B32_e32;
6242 case AMDGPU::S_FLBIT_I32_B32:
return AMDGPU::V_FFBH_U32_e32;
6243 case AMDGPU::S_FLBIT_I32:
return AMDGPU::V_FFBH_I32_e64;
6244 case AMDGPU::S_CBRANCH_SCC0:
return AMDGPU::S_CBRANCH_VCCZ;
6245 case AMDGPU::S_CBRANCH_SCC1:
return AMDGPU::S_CBRANCH_VCCNZ;
6246 case AMDGPU::S_CVT_F32_I32:
return AMDGPU::V_CVT_F32_I32_e64;
6247 case AMDGPU::S_CVT_F32_U32:
return AMDGPU::V_CVT_F32_U32_e64;
6248 case AMDGPU::S_CVT_I32_F32:
return AMDGPU::V_CVT_I32_F32_e64;
6249 case AMDGPU::S_CVT_U32_F32:
return AMDGPU::V_CVT_U32_F32_e64;
6250 case AMDGPU::S_CVT_F32_F16:
6251 case AMDGPU::S_CVT_HI_F32_F16:
6252 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6253 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6254 case AMDGPU::S_CVT_F16_F32:
6255 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6256 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6257 case AMDGPU::S_CEIL_F32:
return AMDGPU::V_CEIL_F32_e64;
6258 case AMDGPU::S_FLOOR_F32:
return AMDGPU::V_FLOOR_F32_e64;
6259 case AMDGPU::S_TRUNC_F32:
return AMDGPU::V_TRUNC_F32_e64;
6260 case AMDGPU::S_RNDNE_F32:
return AMDGPU::V_RNDNE_F32_e64;
6261 case AMDGPU::S_CEIL_F16:
6262 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6263 : AMDGPU::V_CEIL_F16_fake16_e64;
6264 case AMDGPU::S_FLOOR_F16:
6265 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6266 : AMDGPU::V_FLOOR_F16_fake16_e64;
6267 case AMDGPU::S_TRUNC_F16:
6268 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6269 : AMDGPU::V_TRUNC_F16_fake16_e64;
6270 case AMDGPU::S_RNDNE_F16:
6271 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6272 : AMDGPU::V_RNDNE_F16_fake16_e64;
6273 case AMDGPU::S_ADD_F32:
return AMDGPU::V_ADD_F32_e64;
6274 case AMDGPU::S_SUB_F32:
return AMDGPU::V_SUB_F32_e64;
6275 case AMDGPU::S_MIN_F32:
return AMDGPU::V_MIN_F32_e64;
6276 case AMDGPU::S_MAX_F32:
return AMDGPU::V_MAX_F32_e64;
6277 case AMDGPU::S_MINIMUM_F32:
return AMDGPU::V_MINIMUM_F32_e64;
6278 case AMDGPU::S_MAXIMUM_F32:
return AMDGPU::V_MAXIMUM_F32_e64;
6279 case AMDGPU::S_MUL_F32:
return AMDGPU::V_MUL_F32_e64;
6280 case AMDGPU::S_ADD_F16:
6281 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6282 : AMDGPU::V_ADD_F16_fake16_e64;
6283 case AMDGPU::S_SUB_F16:
6284 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6285 : AMDGPU::V_SUB_F16_fake16_e64;
6286 case AMDGPU::S_MIN_F16:
6287 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6288 : AMDGPU::V_MIN_F16_fake16_e64;
6289 case AMDGPU::S_MAX_F16:
6290 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6291 : AMDGPU::V_MAX_F16_fake16_e64;
6292 case AMDGPU::S_MINIMUM_F16:
6293 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6294 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6295 case AMDGPU::S_MAXIMUM_F16:
6296 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6297 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6298 case AMDGPU::S_MUL_F16:
6299 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6300 : AMDGPU::V_MUL_F16_fake16_e64;
6301 case AMDGPU::S_CVT_PK_RTZ_F16_F32:
return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6302 case AMDGPU::S_FMAC_F32:
return AMDGPU::V_FMAC_F32_e64;
6303 case AMDGPU::S_FMAC_F16:
6304 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6305 : AMDGPU::V_FMAC_F16_fake16_e64;
6306 case AMDGPU::S_FMAMK_F32:
return AMDGPU::V_FMAMK_F32;
6307 case AMDGPU::S_FMAAK_F32:
return AMDGPU::V_FMAAK_F32;
6308 case AMDGPU::S_CMP_LT_F32:
return AMDGPU::V_CMP_LT_F32_e64;
6309 case AMDGPU::S_CMP_EQ_F32:
return AMDGPU::V_CMP_EQ_F32_e64;
6310 case AMDGPU::S_CMP_LE_F32:
return AMDGPU::V_CMP_LE_F32_e64;
6311 case AMDGPU::S_CMP_GT_F32:
return AMDGPU::V_CMP_GT_F32_e64;
6312 case AMDGPU::S_CMP_LG_F32:
return AMDGPU::V_CMP_LG_F32_e64;
6313 case AMDGPU::S_CMP_GE_F32:
return AMDGPU::V_CMP_GE_F32_e64;
6314 case AMDGPU::S_CMP_O_F32:
return AMDGPU::V_CMP_O_F32_e64;
6315 case AMDGPU::S_CMP_U_F32:
return AMDGPU::V_CMP_U_F32_e64;
6316 case AMDGPU::S_CMP_NGE_F32:
return AMDGPU::V_CMP_NGE_F32_e64;
6317 case AMDGPU::S_CMP_NLG_F32:
return AMDGPU::V_CMP_NLG_F32_e64;
6318 case AMDGPU::S_CMP_NGT_F32:
return AMDGPU::V_CMP_NGT_F32_e64;
6319 case AMDGPU::S_CMP_NLE_F32:
return AMDGPU::V_CMP_NLE_F32_e64;
6320 case AMDGPU::S_CMP_NEQ_F32:
return AMDGPU::V_CMP_NEQ_F32_e64;
6321 case AMDGPU::S_CMP_NLT_F32:
return AMDGPU::V_CMP_NLT_F32_e64;
6322 case AMDGPU::S_CMP_LT_F16:
6323 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6324 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6325 case AMDGPU::S_CMP_EQ_F16:
6326 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6327 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6328 case AMDGPU::S_CMP_LE_F16:
6329 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6330 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6331 case AMDGPU::S_CMP_GT_F16:
6332 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6333 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6334 case AMDGPU::S_CMP_LG_F16:
6335 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6336 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6337 case AMDGPU::S_CMP_GE_F16:
6338 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6339 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6340 case AMDGPU::S_CMP_O_F16:
6341 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6342 : AMDGPU::V_CMP_O_F16_fake16_e64;
6343 case AMDGPU::S_CMP_U_F16:
6344 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6345 : AMDGPU::V_CMP_U_F16_fake16_e64;
6346 case AMDGPU::S_CMP_NGE_F16:
6347 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6348 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6349 case AMDGPU::S_CMP_NLG_F16:
6350 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6351 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6352 case AMDGPU::S_CMP_NGT_F16:
6353 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6354 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6355 case AMDGPU::S_CMP_NLE_F16:
6356 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6357 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6358 case AMDGPU::S_CMP_NEQ_F16:
6359 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6360 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6361 case AMDGPU::S_CMP_NLT_F16:
6362 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6363 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6364 case AMDGPU::V_S_EXP_F32_e64:
return AMDGPU::V_EXP_F32_e64;
6365 case AMDGPU::V_S_EXP_F16_e64:
6366 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6367 : AMDGPU::V_EXP_F16_fake16_e64;
6368 case AMDGPU::V_S_LOG_F32_e64:
return AMDGPU::V_LOG_F32_e64;
6369 case AMDGPU::V_S_LOG_F16_e64:
6370 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6371 : AMDGPU::V_LOG_F16_fake16_e64;
6372 case AMDGPU::V_S_RCP_F32_e64:
return AMDGPU::V_RCP_F32_e64;
6373 case AMDGPU::V_S_RCP_F16_e64:
6374 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6375 : AMDGPU::V_RCP_F16_fake16_e64;
6376 case AMDGPU::V_S_RSQ_F32_e64:
return AMDGPU::V_RSQ_F32_e64;
6377 case AMDGPU::V_S_RSQ_F16_e64:
6378 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6379 : AMDGPU::V_RSQ_F16_fake16_e64;
6380 case AMDGPU::V_S_SQRT_F32_e64:
return AMDGPU::V_SQRT_F32_e64;
6381 case AMDGPU::V_S_SQRT_F16_e64:
6382 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6383 : AMDGPU::V_SQRT_F16_fake16_e64;
6386 "Unexpected scalar opcode without corresponding vector one!");
6435 "Not a whole wave func");
6438 if (
MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6439 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6446 unsigned OpNo)
const {
6448 if (
MI.isVariadic() || OpNo >=
Desc.getNumOperands() ||
6449 Desc.operands()[OpNo].RegClass == -1) {
6452 if (Reg.isVirtual()) {
6456 return RI.getPhysRegBaseClass(Reg);
6459 int16_t RegClass = getOpRegClassID(
Desc.operands()[OpNo]);
6460 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6465 constexpr AMDGPU::OpName OpNames[] = {
6466 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6469 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
I]);
6470 if (
static_cast<unsigned>(SrcIdx) == OpIdx)
6482 unsigned RCID = getOpRegClassID(
get(
MI.getOpcode()).operands()[OpIdx]);
6484 unsigned Size = RI.getRegSizeInBits(*RC);
6485 unsigned Opcode = (
Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6486 :
Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6487 : AMDGPU::V_MOV_B32_e32;
6489 Opcode = AMDGPU::COPY;
6490 else if (RI.isSGPRClass(RC))
6491 Opcode = (
Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6516 .
addImm(AMDGPU::sub0_sub1)
6518 .
addImm(AMDGPU::sub2_sub3);
6519 }
else if (Opcode == AMDGPU::V_MOV_B16_t16_e64) {
6536 return RI.getSubReg(SuperReg.
getReg(), SubIdx);
6542 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.
getSubReg(), SubIdx);
6553 if (SubIdx == AMDGPU::sub0)
6555 if (SubIdx == AMDGPU::sub1)
6567void SIInstrInfo::swapOperands(
MachineInstr &Inst)
const {
6583 if (Reg.isPhysical())
6590 RI.getLargestLegalSuperClass(RC, MRI.
getMF());
6593 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.
getSubReg()) !=
nullptr;
6596 return RI.getCommonSubClass(DRC, RC) !=
nullptr;
6603 unsigned Opc =
MI.getOpcode();
6606 if (MO.
isReg() && RI.isSGPRReg(MRI, MO.
getReg()) &&
6616 bool IsAGPR = RI.isAGPR(MRI, MO.
getReg());
6617 if (IsAGPR && !ST.hasMAIInsts())
6623 const int VDstIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
6624 const int DataIdx = AMDGPU::getNamedOperandIdx(
6625 Opc,
isDS(
Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6626 if ((
int)OpIdx == VDstIdx && DataIdx != -1 &&
6627 MI.getOperand(DataIdx).isReg() &&
6628 RI.isAGPR(MRI,
MI.getOperand(DataIdx).getReg()) != IsAGPR)
6630 if ((
int)OpIdx == DataIdx) {
6631 if (VDstIdx != -1 &&
6632 RI.isAGPR(MRI,
MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6635 const int Data1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
6636 if (Data1Idx != -1 &&
MI.getOperand(Data1Idx).isReg() &&
6637 RI.isAGPR(MRI,
MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6642 if (
Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6643 (
int)OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) &&
6644 RI.isSGPRReg(MRI, MO.
getReg()))
6647 if (ST.hasFlatScratchHiInB64InstHazard() &&
6654 if (
Opc == AMDGPU::S_BITCMP0_B64 ||
Opc == AMDGPU::S_BITCMP1_B64)
6657 if (!ST.hasDPPSrc1SGPR() &&
isDPP(
MI) && RI.isSGPRReg(MRI, MO.
getReg()) &&
6658 (
int)OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1))
6678 constexpr unsigned NumOps = 3;
6679 constexpr AMDGPU::OpName OpNames[
NumOps * 2] = {
6680 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6681 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6682 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6687 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[SrcN]);
6690 MO = &
MI.getOperand(SrcIdx);
6693 if (!MO->
isReg() || !RI.isSGPRReg(MRI, MO->
getReg()))
6697 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
NumOps + SrcN]);
6701 unsigned Mods =
MI.getOperand(ModsIdx).getImm();
6705 return !OpSel && !OpSelHi;
6714 int64_t RegClass = getOpRegClassID(OpInfo);
6716 RegClass != -1 ? RI.getRegClass(RegClass) :
nullptr;
6718 MO = &
MI.getOperand(OpIdx);
6722 if (
isVALU(
MI,
false) && !IsInlineConst &&
6726 int ConstantBusLimit = ST.getConstantBusLimit(
MI.getOpcode());
6727 int LiteralLimit = !
isVOP3(
MI) || ST.hasVOP3Literal() ? 1 : 0;
6731 if (!LiteralLimit--)
6741 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6749 if (--ConstantBusLimit <= 0)
6761 if (!LiteralLimit--)
6763 if (--ConstantBusLimit <= 0)
6769 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6773 if (!
Op.isReg() && !
Op.isFI() && !
Op.isRegMask() &&
6775 !
Op.isIdenticalTo(*MO))
6797 bool Is64BitOp = Is64BitFPOp ||
6805 (!ST.has64BitLiterals() || InstDesc.
getSize() != 4))
6814 if (!Is64BitFPOp && (int32_t)
Imm < 0 &&
6832 bool IsGFX950Only = ST.hasGFX950Insts();
6833 bool IsGFX940Only = ST.hasGFX940Insts();
6835 if (!IsGFX950Only && !IsGFX940Only)
6853 unsigned Opcode =
MI.getOpcode();
6855 case AMDGPU::V_CVT_PK_BF8_F32_e64:
6856 case AMDGPU::V_CVT_PK_FP8_F32_e64:
6857 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
6858 case AMDGPU::V_MQSAD_U32_U8_e64:
6859 case AMDGPU::V_PK_ADD_F16:
6860 case AMDGPU::V_PK_ADD_F32:
6861 case AMDGPU::V_PK_ADD_I16:
6862 case AMDGPU::V_PK_ADD_U16:
6863 case AMDGPU::V_PK_ASHRREV_I16:
6864 case AMDGPU::V_PK_FMA_F16:
6865 case AMDGPU::V_PK_FMA_F32:
6866 case AMDGPU::V_PK_FMAC_F16_e32:
6867 case AMDGPU::V_PK_FMAC_F16_e64:
6868 case AMDGPU::V_PK_LSHLREV_B16:
6869 case AMDGPU::V_PK_LSHRREV_B16:
6870 case AMDGPU::V_PK_MAD_I16:
6871 case AMDGPU::V_PK_MAD_U16:
6872 case AMDGPU::V_PK_MAX_F16:
6873 case AMDGPU::V_PK_MAX_I16:
6874 case AMDGPU::V_PK_MAX_U16:
6875 case AMDGPU::V_PK_MIN_F16:
6876 case AMDGPU::V_PK_MIN_I16:
6877 case AMDGPU::V_PK_MIN_U16:
6878 case AMDGPU::V_PK_MOV_B32:
6879 case AMDGPU::V_PK_MUL_F16:
6880 case AMDGPU::V_PK_MUL_F32:
6881 case AMDGPU::V_PK_MUL_LO_U16:
6882 case AMDGPU::V_PK_SUB_I16:
6883 case AMDGPU::V_PK_SUB_U16:
6884 case AMDGPU::V_QSAD_PK_U16_U8_e64:
6893 unsigned Opc =
MI.getOpcode();
6896 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
6899 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
6905 if (HasImplicitSGPR && ST.getConstantBusLimit(
Opc) <= 1 && Src0.
isReg() &&
6906 RI.isSGPRReg(MRI, Src0.
getReg()))
6912 if (
Opc == AMDGPU::V_WRITELANE_B32) {
6914 if (Src0.
isReg() && RI.isVGPR(MRI, Src0.
getReg())) {
6920 if (Src1.
isReg() && RI.isVGPR(MRI, Src1.
getReg())) {
6931 if (
Opc == AMDGPU::V_FMAC_F32_e32 ||
Opc == AMDGPU::V_FMAC_F16_e32) {
6932 int Src2Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2);
6933 if (!RI.isVGPR(MRI,
MI.getOperand(Src2Idx).getReg()))
6945 if (
Opc == AMDGPU::V_READLANE_B32 && Src1.
isReg() &&
6946 RI.isVGPR(MRI, Src1.
getReg())) {
6959 if (HasImplicitSGPR || !
MI.isCommutable()) {
6976 if (CommutedOpc == -1) {
6981 MI.setDesc(
get(CommutedOpc));
6985 bool Src0Kill = Src0.
isKill();
6989 else if (Src1.
isReg()) {
7004 unsigned Opc =
MI.getOpcode();
7007 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0),
7008 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1),
7009 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2)
7012 if (
Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
7013 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
7014 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
7015 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
7016 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
7017 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
7018 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
7028 if (VOP3Idx[2] != -1) {
7040 int ConstantBusLimit = ST.getConstantBusLimit(
Opc);
7041 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
7043 Register SGPRReg = findUsedSGPR(
MI, VOP3Idx);
7045 SGPRsUsed.
insert(SGPRReg);
7049 for (
int Idx : VOP3Idx) {
7058 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
7070 if (!RI.isSGPRClass(RI.getRegClassForReg(MRI, MO.
getReg())))
7077 if (ConstantBusLimit > 0) {
7089 if ((
Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64) &&
7090 !RI.isVGPR(MRI,
MI.getOperand(VOP3Idx[2]).getReg()))
7096 for (
unsigned I = 0;
I < 3; ++
I) {
7109 SRC = RI.getCommonSubClass(SRC, DstRC);
7112 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
7114 if (RI.hasAGPRs(VRC)) {
7115 VRC = RI.getEquivalentVGPRClass(VRC);
7118 get(TargetOpcode::COPY), NewSrcReg)
7125 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
7131 for (
unsigned i = 0; i < SubRegs; ++i) {
7134 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
7135 .
addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
7141 get(AMDGPU::REG_SEQUENCE), DstReg);
7142 for (
unsigned i = 0; i < SubRegs; ++i) {
7144 MIB.
addImm(RI.getSubRegFromChannel(i));
7157 if (SBase && !RI.isSGPRClass(MRI.
getRegClass(SBase->getReg()))) {
7159 SBase->setReg(SGPR);
7162 if (SOff && !RI.isSGPRReg(MRI, SOff->
getReg())) {
7170 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::saddr);
7171 if (OldSAddrIdx < 0)
7184 if (RI.isSGPRReg(MRI, SAddr.
getReg()))
7187 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
7188 if (NewVAddrIdx < 0)
7191 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr);
7195 if (OldVAddrIdx >= 0) {
7209 if (OldVAddrIdx == NewVAddrIdx) {
7220 assert(OldSAddrIdx == NewVAddrIdx);
7222 if (OldVAddrIdx >= 0) {
7223 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7224 AMDGPU::OpName::vdst_in);
7228 if (NewVDstIn != -1) {
7229 int OldVDstIn = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst_in);
7235 if (NewVDstIn != -1) {
7236 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7277 unsigned OpSubReg =
Op.getSubReg();
7280 RI.getRegClassForReg(MRI, OpReg), OpSubReg);
7287 auto Copy =
BuildMI(InsertMBB,
I,
DL,
get(AMDGPU::COPY), DstReg)
7288 .
addReg(OpReg, {}, OpSubReg);
7290 Op.setSubReg(AMDGPU::NoSubRegister);
7297 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7300 bool ImpDef = Def->isImplicitDef();
7301 while (!ImpDef && Def && Def->isCopy()) {
7302 if (Def->getOperand(1).getReg().isPhysical())
7305 ImpDef = Def && Def->isImplicitDef();
7307 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7323 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7328 bool UseNewExecInstructions =
7337 if (UseNewExecInstructions) {
7372 for (
auto [Idx, ScalarOp] :
enumerate(ScalarOps)) {
7373 unsigned RegSize =
TRI->getRegSizeInBits(ScalarOp->getReg(), MRI);
7374 unsigned NumSubRegs =
RegSize / 32;
7375 Register VScalarOp = ScalarOp->getReg();
7378 TII.getRegClass(
TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7380 if (NumSubRegs == 1) {
7383 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7384 Common != VScalarOpRC) {
7391 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7394 if (UseNewExecInstructions) {
7396 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7399 if (
I == LoopBB.
end())
7404 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7410 CondReg = NewCondReg;
7421 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7422 ScalarOp->setReg(CurReg);
7425 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7426 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7428 ScalarOp->setReg(PhySGPRs[Idx]);
7430 ScalarOp->setIsKill();
7434 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7435 "Unhandled register size");
7437 for (
unsigned Idx = 0; Idx < NumSubRegs; Idx += 2) {
7444 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7445 .
addReg(VScalarOp, VScalarOpUndef,
TRI->getSubRegFromChannel(Idx));
7448 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7449 .
addReg(VScalarOp, VScalarOpUndef,
7450 TRI->getSubRegFromChannel(Idx + 1));
7457 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7464 NumSubRegs <= 2 ? 0 :
TRI->getSubRegFromChannel(Idx, 2);
7466 if (UseNewExecInstructions) {
7468 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7470 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7471 if (
I == LoopBB.
end())
7475 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7477 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7481 CondReg = NewCondReg;
7492 const auto *SScalarOpRC =
7498 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7499 unsigned Channel = 0;
7500 for (
Register Piece : ReadlanePieces) {
7501 Merge.addReg(Piece).addImm(
TRI->getSubRegFromChannel(Channel++));
7505 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7506 ScalarOp->setReg(SScalarOp);
7508 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7509 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7511 ScalarOp->setReg(PhySGPRs[Idx]);
7513 ScalarOp->setIsKill();
7520 if (!UseNewExecInstructions) {
7532 if (UseNewExecInstructions) {
7563 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.
size()) &&
7564 "Physical SGPRs must be empty or match the number of scalar operands");
7570 if (!Begin.isValid())
7572 if (!End.isValid()) {
7578 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7587 std::numeric_limits<unsigned>::max()) !=
7605 for (
auto I = Begin;
I != AfterMI;
I++) {
7606 for (
auto &MO :
I->all_uses())
7642 for (
auto &Succ : RemainderBB->
successors()) {
7667static std::tuple<unsigned, unsigned>
7675 TII.buildExtractSubReg(
MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7676 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7683 uint64_t RsrcDataFormat =
TII.getDefaultRsrcDataFormat();
7700 .
addImm(AMDGPU::sub0_sub1)
7706 return std::tuple(RsrcPtr, NewSRsrc);
7717 if (ST.useRealTrue16Insts())
7747 if (
MI.getOpcode() == AMDGPU::PHI) {
7749 assert(!RI.isSGPRClass(VRC));
7752 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7754 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7770 if (
MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7773 if (RI.hasVGPRs(DstRC)) {
7777 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7779 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7797 if (
MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7802 if (DstRC != Src0RC) {
7811 if (
MI.getOpcode() == AMDGPU::SI_INIT_M0) {
7813 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7819 if (
MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
7820 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
7821 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
7822 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
7823 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
7824 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
7825 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
7827 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7840 ? AMDGPU::OpName::rsrc
7841 : AMDGPU::OpName::srsrc;
7846 AMDGPU::OpName SampOpName =
7847 isMIMG(
MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
7856 if (
MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
7864 if (
MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
7868 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src0);
7878 if (
MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
7879 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
7880 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
7881 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
7883 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7890 bool isSoffsetLegal =
true;
7892 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::soffset);
7893 if (SoffsetIdx != -1) {
7897 isSoffsetLegal =
false;
7901 bool isRsrcLegal =
true;
7903 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::srsrc);
7904 if (RsrcIdx != -1) {
7906 if (Rsrc->
isReg() && !RI.isSGPRReg(MRI, Rsrc->
getReg()))
7907 isRsrcLegal =
false;
7911 if (isRsrcLegal && isSoffsetLegal)
7939 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
7943 unsigned RsrcPtr, NewSRsrc;
7950 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
7951 .addReg(VAddr->
getReg(), {}, AMDGPU::sub0)
7957 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
7958 .addReg(VAddr->
getReg(), {}, AMDGPU::sub1)
7971 }
else if (!VAddr && ST.hasAddr64()) {
7975 "FIXME: Need to emit flat atomics here");
7977 unsigned RsrcPtr, NewSRsrc;
8003 MIB.
addImm(CPol->getImm());
8008 MIB.
addImm(TFE->getImm());
8028 MI.removeFromParent();
8033 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
8034 .addImm(AMDGPU::sub0)
8035 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
8036 .addImm(AMDGPU::sub1);
8039 if (!isSoffsetLegal) {
8050 if (!isSoffsetLegal) {
8059 if (InSet.insert(
MI).second)
8063 AMDGPU::getNamedOperandIdx(
MI->getOpcode(), AMDGPU::OpName::srsrc);
8064 if (RsrcIdx != -1) {
8065 DeferredList.insert(
MI);
8070 return DeferredList.contains(
MI);
8080 if (!ST.useRealTrue16Insts())
8083 unsigned Opcode =
MI.getOpcode();
8086 if (OpIdx >=
MI.getNumExplicitOperands() ||
8087 OpIdx >=
get(Opcode).getNumOperands() ||
8088 get(Opcode).operands()[OpIdx].RegClass == -1)
8092 if (!
Op.isReg() || !
Op.getReg().isVirtual() ||
Op.isDef())
8096 if (!RI.isVGPRClass(CurrRC))
8099 int16_t RCID = getOpRegClassID(
get(Opcode).operands()[OpIdx]);
8101 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
8103 if (
Op.getSubReg() == AMDGPU::NoSubRegister)
8104 Op.setSubReg(AMDGPU::lo16);
8109 RI.getSubRegisterClass(CurrRC,
Op.getSubReg());
8110 if (RI.getMatchingSuperRegClass(ExpectedRC, CurrSRC, AMDGPU::lo16)) {
8120 Op.setReg(NewDstReg);
8121 Op.setSubReg(AMDGPU::NoSubRegister);
8126 for (
unsigned OpIdx = 0; OpIdx <
MI.getNumExplicitOperands(); OpIdx++)
8134 assert(
MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
8135 "This only handle waterfall for SI_CALL_ISEL");
8142 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
8145 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
8150 while (End !=
MBB.end() && End->isCopy() &&
8151 MI->definesRegister(End->getOperand(1).getReg(), &RI))
8161 while (!Worklist.
empty()) {
8167 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
8173 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
8175 "Deferred MachineInstr are not supposed to re-populate worklist");
8178 for (
auto &Entry : WaterFalls) {
8179 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
8181 Entry.second.SGPRs);
8184 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
8186 Entry.first->eraseFromParent();
8194 if (SubRegIndices.
size() <= 1) {
8197 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8204 for (int16_t Indice : SubRegIndices) {
8207 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8214 get(AMDGPU::REG_SEQUENCE), DstReg);
8215 for (
unsigned i = 0; i < SubRegIndices.size(); ++i) {
8217 MIB.
addImm(RI.getSubRegFromChannel(i));
8227 if (DstReg == AMDGPU::M0) {
8240 if (
I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
8242 for (
unsigned i = 0; i <
UseMI->getNumOperands(); ++i) {
8243 if (
UseMI->getOperand(i).isReg() &&
8244 UseMI->getOperand(i).getReg() == DstReg) {
8248 V2SCopyInfo.MOs.push_back(MO);
8249 V2SCopyInfo.SGPRs.push_back(DstReg);
8253 }
else if (
I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8254 I->getOperand(0).isReg() &&
8255 I->getOperand(0).getReg() == DstReg) {
8258 }
else if (
I->readsRegister(DstReg, &RI)) {
8260 V2SPhyCopiesToErase[&Inst] =
false;
8262 if (
I->findRegisterDefOperand(DstReg, &RI))
8284 case AMDGPU::S_ADD_I32:
8285 case AMDGPU::S_SUB_I32: {
8289 std::tie(
Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8297 case AMDGPU::S_MUL_U64:
8298 if (ST.useVMulU64Inst()) {
8299 NewOpcode = AMDGPU::V_MUL_U64_e64;
8303 splitScalarSMulU64(Worklist, Inst, MDT);
8307 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8308 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8311 splitScalarSMulPseudo(Worklist, Inst, MDT);
8315 case AMDGPU::S_AND_B64:
8316 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8320 case AMDGPU::S_OR_B64:
8321 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8325 case AMDGPU::S_XOR_B64:
8326 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8330 case AMDGPU::S_NAND_B64:
8331 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8335 case AMDGPU::S_NOR_B64:
8336 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8340 case AMDGPU::S_XNOR_B64:
8341 if (ST.hasDLInsts())
8342 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8344 splitScalar64BitXnor(Worklist, Inst, MDT);
8348 case AMDGPU::S_ANDN2_B64:
8349 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8353 case AMDGPU::S_ORN2_B64:
8354 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8358 case AMDGPU::S_BREV_B64:
8359 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32,
true);
8363 case AMDGPU::S_NOT_B64:
8364 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8368 case AMDGPU::S_BCNT1_I32_B64:
8369 splitScalar64BitBCNT(Worklist, Inst);
8373 case AMDGPU::S_BFE_I64:
8374 splitScalar64BitBFE(Worklist, Inst);
8378 case AMDGPU::S_FLBIT_I32_B64:
8379 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8382 case AMDGPU::S_FF1_I32_B64:
8383 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8387 case AMDGPU::S_LSHL_B32:
8388 if (ST.hasOnlyRevVALUShifts()) {
8389 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8393 case AMDGPU::S_ASHR_I32:
8394 if (ST.hasOnlyRevVALUShifts()) {
8395 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8399 case AMDGPU::S_LSHR_B32:
8400 if (ST.hasOnlyRevVALUShifts()) {
8401 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8405 case AMDGPU::S_LSHL_B64:
8406 if (ST.hasOnlyRevVALUShifts()) {
8408 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8409 : AMDGPU::V_LSHLREV_B64_e64;
8413 case AMDGPU::S_ASHR_I64:
8414 if (ST.hasOnlyRevVALUShifts()) {
8415 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8419 case AMDGPU::S_LSHR_B64:
8420 if (ST.hasOnlyRevVALUShifts()) {
8421 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8426 case AMDGPU::S_ABS_I32:
8427 lowerScalarAbs(Worklist, Inst);
8431 case AMDGPU::S_ABSDIFF_I32:
8432 lowerScalarAbsDiff(Worklist, Inst);
8436 case AMDGPU::S_CBRANCH_SCC0:
8437 case AMDGPU::S_CBRANCH_SCC1: {
8440 bool IsSCC = CondReg == AMDGPU::SCC;
8448 case AMDGPU::S_BFE_U64:
8449 case AMDGPU::S_BFM_B64:
8452 case AMDGPU::S_PACK_LL_B32_B16:
8453 case AMDGPU::S_PACK_LH_B32_B16:
8454 case AMDGPU::S_PACK_HL_B32_B16:
8455 case AMDGPU::S_PACK_HH_B32_B16:
8456 movePackToVALU(Worklist, MRI, Inst);
8460 case AMDGPU::S_XNOR_B32:
8461 lowerScalarXnor(Worklist, Inst);
8465 case AMDGPU::S_NAND_B32:
8466 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8470 case AMDGPU::S_NOR_B32:
8471 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8475 case AMDGPU::S_ANDN2_B32:
8476 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8480 case AMDGPU::S_ORN2_B32:
8481 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8489 case AMDGPU::S_ADD_CO_PSEUDO:
8490 case AMDGPU::S_SUB_CO_PSEUDO: {
8491 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8492 ? AMDGPU::V_ADDC_U32_e64
8493 : AMDGPU::V_SUBB_U32_e64;
8494 const auto *CarryRC = RI.getWaveMaskRegClass();
8516 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8520 case AMDGPU::S_UADDO_PSEUDO:
8521 case AMDGPU::S_USUBO_PSEUDO: {
8527 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8528 ? AMDGPU::V_ADD_CO_U32_e64
8529 : AMDGPU::V_SUB_CO_U32_e64;
8541 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8545 case AMDGPU::S_LSHL1_ADD_U32:
8546 case AMDGPU::S_LSHL2_ADD_U32:
8547 case AMDGPU::S_LSHL3_ADD_U32:
8548 case AMDGPU::S_LSHL4_ADD_U32: {
8552 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8553 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8554 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8568 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8572 case AMDGPU::S_CSELECT_B32:
8573 case AMDGPU::S_CSELECT_B64:
8574 lowerSelect(Worklist, Inst, MDT);
8577 case AMDGPU::S_CMP_EQ_I32:
8578 case AMDGPU::S_CMP_LG_I32:
8579 case AMDGPU::S_CMP_GT_I32:
8580 case AMDGPU::S_CMP_GE_I32:
8581 case AMDGPU::S_CMP_LT_I32:
8582 case AMDGPU::S_CMP_LE_I32:
8583 case AMDGPU::S_CMP_EQ_U32:
8584 case AMDGPU::S_CMP_LG_U32:
8585 case AMDGPU::S_CMP_GT_U32:
8586 case AMDGPU::S_CMP_GE_U32:
8587 case AMDGPU::S_CMP_LT_U32:
8588 case AMDGPU::S_CMP_LE_U32:
8589 case AMDGPU::S_CMP_EQ_U64:
8590 case AMDGPU::S_CMP_LG_U64:
8591 case AMDGPU::S_CMP_LT_F32:
8592 case AMDGPU::S_CMP_EQ_F32:
8593 case AMDGPU::S_CMP_LE_F32:
8594 case AMDGPU::S_CMP_GT_F32:
8595 case AMDGPU::S_CMP_LG_F32:
8596 case AMDGPU::S_CMP_GE_F32:
8597 case AMDGPU::S_CMP_O_F32:
8598 case AMDGPU::S_CMP_U_F32:
8599 case AMDGPU::S_CMP_NGE_F32:
8600 case AMDGPU::S_CMP_NLG_F32:
8601 case AMDGPU::S_CMP_NGT_F32:
8602 case AMDGPU::S_CMP_NLE_F32:
8603 case AMDGPU::S_CMP_NEQ_F32:
8604 case AMDGPU::S_CMP_NLT_F32: {
8609 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8623 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8627 case AMDGPU::S_CMP_LT_F16:
8628 case AMDGPU::S_CMP_EQ_F16:
8629 case AMDGPU::S_CMP_LE_F16:
8630 case AMDGPU::S_CMP_GT_F16:
8631 case AMDGPU::S_CMP_LG_F16:
8632 case AMDGPU::S_CMP_GE_F16:
8633 case AMDGPU::S_CMP_O_F16:
8634 case AMDGPU::S_CMP_U_F16:
8635 case AMDGPU::S_CMP_NGE_F16:
8636 case AMDGPU::S_CMP_NLG_F16:
8637 case AMDGPU::S_CMP_NGT_F16:
8638 case AMDGPU::S_CMP_NLE_F16:
8639 case AMDGPU::S_CMP_NEQ_F16:
8640 case AMDGPU::S_CMP_NLT_F16: {
8662 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8666 case AMDGPU::S_CVT_HI_F32_F16: {
8669 if (ST.useRealTrue16Insts()) {
8674 .
addReg(TmpReg, {}, AMDGPU::hi16)
8690 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8694 case AMDGPU::S_MINIMUM_F32:
8695 case AMDGPU::S_MAXIMUM_F32: {
8707 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8711 case AMDGPU::S_MINIMUM_F16:
8712 case AMDGPU::S_MAXIMUM_F16: {
8714 ? &AMDGPU::VGPR_16RegClass
8715 : &AMDGPU::VGPR_32RegClass);
8726 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8730 case AMDGPU::V_S_EXP_F16_e64:
8731 case AMDGPU::V_S_LOG_F16_e64:
8732 case AMDGPU::V_S_RCP_F16_e64:
8733 case AMDGPU::V_S_RSQ_F16_e64:
8734 case AMDGPU::V_S_SQRT_F16_e64: {
8736 ? &AMDGPU::VGPR_16RegClass
8737 : &AMDGPU::VGPR_32RegClass);
8748 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8754 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8762 if (NewOpcode == Opcode) {
8769 V2SPhyCopiesToErase);
8777 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8784 addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist);
8790 RI.composeSubRegIndices(SrcSubReg, UseMO.getSubReg()));
8791 UseMO.setReg(NewDstReg);
8810 unsigned OpIdx =
UseMI.getOperandNo(&UseMO);
8823 if (ST.useRealTrue16Insts() && Inst.
isCopy() &&
8827 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
8833 get(AMDGPU::REG_SEQUENCE), NewDstReg)
8840 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8842 }
else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
8847 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8855 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8865 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8866 AMDGPU::OpName::src0_modifiers) >= 0)
8870 NewInstr->addOperand(Src);
8873 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
8876 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
8878 NewInstr.addImm(
Size);
8879 }
else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
8883 }
else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
8888 "Scalar BFE is only implemented for constant width and offset");
8896 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8897 AMDGPU::OpName::src1_modifiers) >= 0)
8899 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
8901 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8902 AMDGPU::OpName::src2_modifiers) >= 0)
8904 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
8906 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
8908 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
8910 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
8916 NewInstr->addOperand(
Op);
8923 if (
Op.getReg() == AMDGPU::SCC) {
8925 if (
Op.isDef() && !
Op.isDead())
8926 addSCCDefUsersToVALUWorklist(
Op, Inst, Worklist);
8928 addSCCDefsToVALUWorklist(NewInstr, Worklist);
8933 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
8934 Register DstReg = NewInstr->getOperand(0).getReg();
8947 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8951std::pair<bool, MachineBasicBlock *>
8954 if (ST.hasAddNoCarryInsts()) {
8966 assert(
Opc == AMDGPU::S_ADD_I32 ||
Opc == AMDGPU::S_SUB_I32);
8968 unsigned NewOpc =
Opc == AMDGPU::S_ADD_I32 ?
8969 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
8980 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8981 return std::pair(
true, NewBB);
8984 return std::pair(
false,
nullptr);
9001 bool IsSCC = (CondReg == AMDGPU::SCC);
9009 for (MachineOperand &UseMO :
9011 MachineInstr &
UseMI = *UseMO.getParent();
9012 switch (
UseMI.getOpcode()) {
9013 case AMDGPU::V_CNDMASK_B16_fake16_e32:
9014 case AMDGPU::V_CNDMASK_B16_fake16_e64:
9015 case AMDGPU::V_CNDMASK_B16_t16_e32:
9016 case AMDGPU::V_CNDMASK_B16_t16_e64:
9017 case AMDGPU::V_CNDMASK_B32_e32:
9018 case AMDGPU::V_CNDMASK_B32_e64:
9019 case AMDGPU::V_CNDMASK_B64_PSEUDO:
9020 if (UseMO.isImplicit() ||
9022 UseMO.setReg(CondReg);
9036 bool CopyFound =
false;
9037 for (MachineInstr &CandI :
9040 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) !=
9042 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
9044 .
addReg(CandI.getOperand(1).getReg());
9056 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
9065 MachineInstr *NewInst;
9066 if (Inst.
getOpcode() == AMDGPU::S_CSELECT_B32) {
9067 NewInst =
BuildMI(
MBB, MII,
DL,
get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
9082 addUsersToMoveToVALUWorklist(NewDestReg, MRI, Worklist);
9097 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
9098 : AMDGPU::V_SUB_CO_U32_e32;
9109 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9126 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
9127 : AMDGPU::V_SUB_CO_U32_e32;
9140 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9154 if (ST.hasDLInsts()) {
9164 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9170 bool Src0IsSGPR = Src0.
isReg() &&
9172 bool Src1IsSGPR = Src1.
isReg() &&
9186 }
else if (Src1IsSGPR) {
9204 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9210 unsigned Opcode)
const {
9234 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9239 unsigned Opcode)
const {
9263 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9278 const MCInstrDesc &InstDesc =
get(Opcode);
9281 &AMDGPU::SGPR_32RegClass;
9284 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9287 AMDGPU::sub0, Src0SubRC);
9292 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9295 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0).
add(SrcReg0Sub0);
9298 AMDGPU::sub1, Src0SubRC);
9301 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1).
add(SrcReg0Sub1);
9315 Worklist.
insert(&LoHalf);
9316 Worklist.
insert(&HiHalf);
9322 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9346 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9347 if (RI.isSGPRClass(Src0SubRC))
9348 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9350 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9351 if (RI.isSGPRClass(Src1SubRC))
9352 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9356 MachineOperand Op0L =
9358 MachineOperand Op1L =
9360 MachineOperand Op0H =
9362 MachineOperand Op1H =
9381 MachineInstr *Op1L_Op0H =
9387 MachineInstr *Op1H_Op0L =
9393 MachineInstr *Carry =
9398 MachineInstr *LoHalf =
9408 MachineInstr *HiHalf =
9431 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9455 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9456 if (RI.isSGPRClass(Src0SubRC))
9457 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9459 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9460 if (RI.isSGPRClass(Src1SubRC))
9461 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9465 MachineOperand Op0L =
9467 MachineOperand Op1L =
9471 unsigned NewOpc =
Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9472 ? AMDGPU::V_MUL_HI_U32_e64
9473 : AMDGPU::V_MUL_HI_I32_e64;
9474 MachineInstr *HiHalf =
9477 MachineInstr *LoHalf =
9496 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9512 const MCInstrDesc &InstDesc =
get(Opcode);
9515 &AMDGPU::SGPR_32RegClass;
9518 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9521 &AMDGPU::SGPR_32RegClass;
9524 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9527 AMDGPU::sub0, Src0SubRC);
9529 AMDGPU::sub0, Src1SubRC);
9531 AMDGPU::sub1, Src0SubRC);
9533 AMDGPU::sub1, Src1SubRC);
9538 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9541 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0)
9546 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1)
9559 Worklist.
insert(&LoHalf);
9560 Worklist.
insert(&HiHalf);
9563 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9583 MachineOperand* Op0;
9584 MachineOperand* Op1;
9586 if (Src0.
isReg() && RI.isSGPRReg(MRI, Src0.
getReg())) {
9619 const MCInstrDesc &InstDesc =
get(AMDGPU::V_BCNT_U32_B32_e64);
9622 &AMDGPU::SGPR_32RegClass;
9628 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9631 AMDGPU::sub0, SrcSubRC);
9633 AMDGPU::sub1, SrcSubRC);
9643 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9662 Offset == 0 &&
"Not implemented");
9685 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9695 .
addReg(Src.getReg(), {}, AMDGPU::sub0);
9698 .
addReg(Src.getReg(), {}, AMDGPU::sub0)
9704 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9723 const MCInstrDesc &InstDesc =
get(Opcode);
9725 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9728 Src.isReg() ? MRI.
getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9730 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9732 MachineOperand SrcRegSub0 =
9734 MachineOperand SrcRegSub1 =
9748 .
addReg(IsCtlz ? MidReg1 : MidReg2);
9752 .
addReg(IsCtlz ? MidReg2 : MidReg1);
9756 addUsersToMoveToVALUWorklist(MidReg4, MRI, Worklist);
9759void SIInstrInfo::addUsersToMoveToVALUWorklist(
9763 MachineInstr &
UseMI = *MO.getParent();
9767 switch (
UseMI.getOpcode()) {
9770 case AMDGPU::SOFT_WQM:
9771 case AMDGPU::STRICT_WWM:
9772 case AMDGPU::STRICT_WQM:
9773 case AMDGPU::REG_SEQUENCE:
9775 case AMDGPU::INSERT_SUBREG:
9778 OpNo = MO.getOperandNo();
9785 if (!RI.hasVectorRegisters(OpRC))
9802 if (ST.useRealTrue16Insts()) {
9804 if (!Src0.
isReg() || !RI.isVGPR(MRI, Src0.
getReg())) {
9807 get(Src0.
isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
9813 if (!Src1.
isReg() || !RI.isVGPR(MRI, Src1.
getReg())) {
9816 get(Src1.
isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
9825 auto NewMI =
BuildMI(*
MBB, Inst,
DL,
get(AMDGPU::REG_SEQUENCE), ResultReg);
9827 case AMDGPU::S_PACK_LL_B32_B16:
9829 .addReg(SrcReg0, {},
9830 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9831 .addImm(AMDGPU::lo16)
9832 .addReg(SrcReg1, {},
9833 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9834 .addImm(AMDGPU::hi16);
9836 case AMDGPU::S_PACK_LH_B32_B16:
9838 .addReg(SrcReg0, {},
9839 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9840 .addImm(AMDGPU::lo16)
9841 .addReg(SrcReg1, {}, AMDGPU::hi16)
9842 .addImm(AMDGPU::hi16);
9844 case AMDGPU::S_PACK_HL_B32_B16:
9845 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9846 .addImm(AMDGPU::lo16)
9847 .addReg(SrcReg1, {},
9848 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9849 .addImm(AMDGPU::hi16);
9851 case AMDGPU::S_PACK_HH_B32_B16:
9852 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9853 .addImm(AMDGPU::lo16)
9854 .addReg(SrcReg1, {}, AMDGPU::hi16)
9855 .addImm(AMDGPU::hi16);
9863 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9868 case AMDGPU::S_PACK_LL_B32_B16: {
9887 case AMDGPU::S_PACK_LH_B32_B16: {
9897 case AMDGPU::S_PACK_HL_B32_B16: {
9908 case AMDGPU::S_PACK_HH_B32_B16: {
9928 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9937 assert(
Op.isReg() &&
Op.getReg() == AMDGPU::SCC &&
Op.isDef() &&
9938 !
Op.isDead() &&
Op.getParent() == &SCCDefInst);
9939 SmallVector<MachineInstr *, 4> CopyToDelete;
9942 for (MachineInstr &
MI :
9946 int SCCIdx =
MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI,
false);
9950 Register DestReg =
MI.getOperand(0).getReg();
9957 MI.getOperand(SCCIdx).setReg(NewCond);
9963 if (
MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) != -1)
9966 for (
auto &Copy : CopyToDelete)
9967 Copy->eraseFromParent();
9975void SIInstrInfo::addSCCDefsToVALUWorklist(
MachineInstr *SCCUseInst,
9981 for (MachineInstr &
MI :
9984 if (
MI.modifiesRegister(AMDGPU::VCC, &RI))
9986 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
10003 case AMDGPU::REG_SEQUENCE:
10004 case AMDGPU::INSERT_SUBREG:
10006 case AMDGPU::SOFT_WQM:
10007 case AMDGPU::STRICT_WWM:
10008 case AMDGPU::STRICT_WQM: {
10010 if (RI.isAGPRClass(SrcRC)) {
10011 if (RI.isAGPRClass(NewDstRC))
10016 case AMDGPU::REG_SEQUENCE:
10017 case AMDGPU::INSERT_SUBREG:
10018 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
10021 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10027 if (!RI.isSGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
10030 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10044 int OpIndices[3])
const {
10045 const MCInstrDesc &
Desc =
MI.getDesc();
10063 for (
unsigned i = 0; i < 3; ++i) {
10064 int Idx = OpIndices[i];
10068 const MachineOperand &MO =
MI.getOperand(Idx);
10075 RI.getRegClass(getOpRegClassID(
Desc.operands()[Idx]));
10076 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
10077 if (IsRequiredSGPR)
10083 if (RI.isSGPRClass(RegRC))
10084 UsedSGPRs[i] =
Reg;
10100 if (UsedSGPRs[0]) {
10101 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
10102 SGPRReg = UsedSGPRs[0];
10105 if (!SGPRReg && UsedSGPRs[1]) {
10106 if (UsedSGPRs[1] == UsedSGPRs[2])
10107 SGPRReg = UsedSGPRs[1];
10114 AMDGPU::OpName OperandName)
const {
10115 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
10118 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OperandName);
10122 return &
MI.getOperand(Idx);
10136 if (ST.isAmdHsaOS()) {
10139 RsrcDataFormat |= (1ULL << 56);
10144 RsrcDataFormat |= (2ULL << 59);
10147 return RsrcDataFormat;
10157 uint64_t EltSizeValue =
Log2_32(ST.getMaxPrivateElementSize(
true)) - 1;
10162 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
10169 Rsrc23 &=
~AMDGPU::RSRC_DATA_FORMAT;
10175 unsigned Opc =
MI.getOpcode();
10181 return get(
Opc).mayLoad() &&
10188 if (!Addr || !Addr->
isFI())
10197 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::vdata);
10199 return MI.getOperand(VDataIdx).getReg();
10209 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::data);
10211 return MI.getOperand(DataIdx).getReg();
10232 if (!
MI.mayStore())
10245 unsigned Opc =
MI.getOpcode();
10247 unsigned DescSize =
Desc.getSize();
10252 unsigned Size = DescSize;
10256 if (
MI.isBranch() && ST.hasOffset3fBug())
10267 bool HasLiteral =
false;
10268 unsigned LiteralSize = 4;
10269 for (
int I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I) {
10274 if (ST.has64BitLiterals()) {
10275 switch (OpInfo.OperandType) {
10300 return HasLiteral ? DescSize + LiteralSize : DescSize;
10305 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
10309 int RSrcIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::srsrc);
10310 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10314 case TargetOpcode::BUNDLE:
10315 return getInstBundleSize(
MI);
10316 case TargetOpcode::INLINEASM:
10317 case TargetOpcode::INLINEASM_BR: {
10319 const char *AsmStr =
MI.getOperand(0).getSymbolName();
10323 if (
MI.isMetaInstruction())
10327 const auto *D16Info = AMDGPU::getT16D16Helper(
Opc);
10330 unsigned LoInstOpcode = D16Info->LoOp;
10332 DescSize =
Desc.getSize();
10336 if (
Opc == AMDGPU::V_FMA_MIX_F16_t16 ||
Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10339 DescSize =
Desc.getSize();
10348 if (
MI.isBranch() && ST.hasOffset3fBug())
10349 return InstSizeVerifyMode::NoVerify;
10350 return InstSizeVerifyMode::ExactSize;
10357 if (
MI.memoperands_empty())
10369 static const std::pair<int, const char *> TargetIndices[] = {
10409std::pair<unsigned, unsigned>
10416 static const std::pair<unsigned, const char *> TargetFlags[] = {
10434 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10450 return AMDGPU::WWM_COPY;
10452 return AMDGPU::COPY;
10469 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10473 if (RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg)))
10474 return IsLRSplitInst;
10487 bool IsNullOrVectorRegister =
true;
10491 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg));
10494 return IsNullOrVectorRegister &&
10496 (!
MI.isTerminator() &&
MI.getOpcode() != AMDGPU::COPY &&
10497 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10505 if (ST.hasAddNoCarryInsts())
10521 if (ST.hasAddNoCarryInsts())
10525 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10527 : RS.scavengeRegisterBackwards(
10528 *RI.getBoolRC(),
I,
false,
10541 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10542 case AMDGPU::SI_KILL_I1_TERMINATOR:
10551 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10552 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10553 case AMDGPU::SI_KILL_I1_PSEUDO:
10554 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10566 const unsigned OffsetBits =
10568 return (1 << OffsetBits) - 1;
10572 if (!ST.isWave32())
10575 if (
MI.isInlineAsm())
10578 if (
MI.getNumOperands() <
MI.getDesc().getNumOperands())
10581 for (
auto &
Op :
MI.implicit_operands()) {
10582 if (
Op.isReg() &&
Op.getReg() == AMDGPU::VCC)
10583 Op.setReg(AMDGPU::VCC_LO);
10592 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::sbase);
10596 const int16_t RCID = getOpRegClassID(
MI.getDesc().operands()[Idx]);
10597 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10613 if (
Imm > MaxImm) {
10614 if (
Imm <= MaxImm + 64) {
10616 Overflow =
Imm - MaxImm;
10631 Overflow =
High - Alignment.value();
10635 if (Overflow > 0) {
10643 if (ST.hasRestrictedSOffset())
10648 SOffset = Overflow;
10686 if (!ST.hasFlatInstOffsets())
10690 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10695 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10696 FlatVariant == FlatAddrSpace::FlatScratch &&
Offset < 0 &&
10707std::pair<int64_t, int64_t>
10710 int64_t RemainderOffset = COffsetVal;
10711 int64_t ImmField = 0;
10716 if (AllowNegative) {
10718 int64_t
D = 1LL << NumBits;
10719 RemainderOffset = (COffsetVal /
D) *
D;
10720 ImmField = COffsetVal - RemainderOffset;
10722 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10724 (ImmField % 4) != 0) {
10726 RemainderOffset += ImmField % 4;
10727 ImmField -= ImmField % 4;
10729 }
else if (COffsetVal >= 0) {
10731 RemainderOffset = COffsetVal - ImmField;
10735 assert(RemainderOffset + ImmField == COffsetVal);
10736 return {ImmField, RemainderOffset};
10741 if (ST.hasNegativeScratchOffsetBug() &&
10749 switch (ST.getGeneration()) {
10783 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10784 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10785 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10786 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10787 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10788 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10789 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10790 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10797#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10798 case OPCODE##_dpp: \
10799 case OPCODE##_e32: \
10800 case OPCODE##_e64: \
10801 case OPCODE##_e64_dpp: \
10802 case OPCODE##_sdwa:
10816 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
10817 case AMDGPU::V_DIV_FIXUP_F16_gfx9_fake16_e64:
10818 case AMDGPU::V_FMA_F16_gfx9_e64:
10819 case AMDGPU::V_FMA_F16_gfx9_fake16_e64:
10820 case AMDGPU::V_INTERP_P2_F16:
10821 case AMDGPU::V_MAD_F16_e64:
10822 case AMDGPU::V_MAD_U16_e64:
10823 case AMDGPU::V_MAD_I16_e64:
10832 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
10840 switch (ST.getGeneration()) {
10853 if (
isMAI(Opcode)) {
10867 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
10870 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
10877 if (ST.hasGFX90AInsts()) {
10878 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
10879 if (ST.hasGFX940Insts())
10881 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10883 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10885 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
10891 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
10910 for (
unsigned I = 0, E = (
MI.getNumOperands() - 1)/ 2;
I < E; ++
I)
10911 if (
MI.getOperand(1 + 2 *
I + 1).getImm() == SubReg) {
10912 auto &RegOp =
MI.getOperand(1 + 2 *
I);
10924 switch (
MI.getOpcode()) {
10926 case AMDGPU::REG_SEQUENCE:
10930 case AMDGPU::INSERT_SUBREG:
10931 if (RSR.
SubReg == (
unsigned)
MI.getOperand(3).getImm())
10948 if (!
P.Reg.isVirtual())
10953 while (
auto *
MI = DefInst) {
10955 switch (
MI->getOpcode()) {
10957 case AMDGPU::V_MOV_B32_e32: {
10958 auto &Op1 =
MI->getOperand(1);
10987 auto *DefBB =
DefMI.getParent();
10991 if (
UseMI.getParent() != DefBB)
10994 const int MaxInstScan = 20;
10998 auto E =
UseMI.getIterator();
10999 for (
auto I = std::next(
DefMI.getIterator());
I != E; ++
I) {
11000 if (
I->isDebugInstr())
11003 if (++NumInst > MaxInstScan)
11006 if (
I->modifiesRegister(AMDGPU::EXEC,
TRI))
11019 auto *DefBB =
DefMI.getParent();
11021 const int MaxUseScan = 10;
11025 auto &UseInst = *
Use.getParent();
11028 if (UseInst.getParent() != DefBB || UseInst.isPHI())
11031 if (++NumUse > MaxUseScan)
11038 const int MaxInstScan = 20;
11042 for (
auto I = std::next(
DefMI.getIterator()); ; ++
I) {
11045 if (
I->isDebugInstr())
11048 if (++NumInst > MaxInstScan)
11061 if (Reg == VReg && --NumUse == 0)
11063 }
else if (
TRI->regsOverlap(Reg, AMDGPU::EXEC))
11072 auto Cur =
MBB.begin();
11073 if (Cur !=
MBB.end())
11075 if (!Cur->isPHI() && Cur->readsRegister(Dst,
nullptr))
11078 }
while (Cur !=
MBB.end() && Cur != LastPHIIt);
11087 if (InsPt !=
MBB.end() &&
11088 (InsPt->getOpcode() == AMDGPU::SI_IF ||
11089 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
11090 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
11091 InsPt->definesRegister(Src,
nullptr)) {
11095 .
addReg(Src, {}, SrcSubReg)
11138 if (isFullCopyInstr(
MI)) {
11139 Register DstReg =
MI.getOperand(0).getReg();
11140 Register SrcReg =
MI.getOperand(1).getReg();
11162 unsigned *PredCost)
const {
11163 if (
MI.isBundle()) {
11166 unsigned Lat = 0,
Count = 0;
11167 for (++
I;
I != E &&
I->isBundledWithPred(); ++
I) {
11169 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*
I));
11171 return Lat +
Count - 1;
11174 return SchedModel.computeInstrLatency(&
MI);
11178 if (!ST.hasGFX1250VALUBlockingCycles())
11182 if (
const auto *Entry = AMDGPU::getGFX1250BlockingCyclesInfo(
MI.getOpcode()))
11183 return Entry->GFX1250BlockingCycles;
11192 return *CallAddrOp;
11199 unsigned Opcode =
MI.getOpcode();
11201 auto HandleAddrSpaceCast = [
this, &MRI](
const MachineInstr &
MI) {
11207 unsigned SrcAS = SrcTy.getAddressSpace();
11210 ST.hasGloballyAddressableScratch()
11218 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
11219 return HandleAddrSpaceCast(
MI);
11222 auto IID = GI->getIntrinsicID();
11229 case Intrinsic::amdgcn_if:
11230 case Intrinsic::amdgcn_else:
11244 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11245 Opcode == AMDGPU::G_SEXTLOAD) {
11246 if (
MI.memoperands_empty())
11250 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11251 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11259 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11260 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11261 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11267 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11270 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11278 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11279 return Formatter.get();
11287 unsigned opcode =
MI.getOpcode();
11288 if (opcode == AMDGPU::V_READLANE_B32 ||
11289 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11290 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11295 if (
MI.isInlineAsm()) {
11301 if (!RC || !RI.isSGPRClass(RC))
11306 if (isCopyInstr(
MI)) {
11310 RI.getPhysRegBaseClass(srcOp.
getReg());
11318 if (
MI.isPreISelOpcode())
11333 if (
MI.memoperands_empty())
11337 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11338 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11353 for (
unsigned I = 0, E =
MI.getNumOperands();
I != E; ++
I) {
11355 if (!
SrcOp.isReg())
11359 if (!Reg || !
SrcOp.readsReg())
11365 if (RegBank && RegBank->
getID() != AMDGPU::SGPRRegBankID)
11392 F,
"ds_ordered_count unsupported for this calling conv"));
11406 Register &SrcReg2, int64_t &CmpMask,
11407 int64_t &CmpValue)
const {
11408 if (!
MI.getOperand(0).isReg() ||
MI.getOperand(0).getSubReg())
11411 switch (
MI.getOpcode()) {
11414 case AMDGPU::S_CMP_EQ_U32:
11415 case AMDGPU::S_CMP_EQ_I32:
11416 case AMDGPU::S_CMP_LG_U32:
11417 case AMDGPU::S_CMP_LG_I32:
11418 case AMDGPU::S_CMP_LT_U32:
11419 case AMDGPU::S_CMP_LT_I32:
11420 case AMDGPU::S_CMP_GT_U32:
11421 case AMDGPU::S_CMP_GT_I32:
11422 case AMDGPU::S_CMP_LE_U32:
11423 case AMDGPU::S_CMP_LE_I32:
11424 case AMDGPU::S_CMP_GE_U32:
11425 case AMDGPU::S_CMP_GE_I32:
11426 case AMDGPU::S_CMP_EQ_U64:
11427 case AMDGPU::S_CMP_LG_U64:
11428 SrcReg =
MI.getOperand(0).getReg();
11429 if (
MI.getOperand(1).isReg()) {
11430 if (
MI.getOperand(1).getSubReg())
11432 SrcReg2 =
MI.getOperand(1).getReg();
11434 }
else if (
MI.getOperand(1).isImm()) {
11436 CmpValue =
MI.getOperand(1).getImm();
11442 case AMDGPU::S_CMPK_EQ_U32:
11443 case AMDGPU::S_CMPK_EQ_I32:
11444 case AMDGPU::S_CMPK_LG_U32:
11445 case AMDGPU::S_CMPK_LG_I32:
11446 case AMDGPU::S_CMPK_LT_U32:
11447 case AMDGPU::S_CMPK_LT_I32:
11448 case AMDGPU::S_CMPK_GT_U32:
11449 case AMDGPU::S_CMPK_GT_I32:
11450 case AMDGPU::S_CMPK_LE_U32:
11451 case AMDGPU::S_CMPK_LE_I32:
11452 case AMDGPU::S_CMPK_GE_U32:
11453 case AMDGPU::S_CMPK_GE_I32:
11454 SrcReg =
MI.getOperand(0).getReg();
11456 CmpValue =
MI.getOperand(1).getImm();
11466 if (S->isLiveIn(AMDGPU::SCC))
11475bool SIInstrInfo::invertSCCUse(
MachineInstr *SCCDef)
const {
11478 bool SCCIsDead =
false;
11481 constexpr unsigned ScanLimit = 12;
11482 unsigned Count = 0;
11483 for (MachineInstr &
MI :
11485 if (++
Count > ScanLimit)
11487 if (
MI.readsRegister(AMDGPU::SCC, &RI)) {
11488 if (
MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11489 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11490 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11491 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11496 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
11509 for (MachineInstr *
MI : InvertInstr) {
11510 if (
MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11511 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11513 }
else if (
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11514 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11515 MI->setDesc(
get(
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11516 ? AMDGPU::S_CBRANCH_SCC1
11517 : AMDGPU::S_CBRANCH_SCC0));
11530 bool NeedInversion)
const {
11531 MachineInstr *KillsSCC =
nullptr;
11536 if (
MI.modifiesRegister(AMDGPU::SCC, &RI))
11538 if (
MI.killsRegister(AMDGPU::SCC, &RI))
11541 if (NeedInversion && !invertSCCUse(SCCRedefine))
11543 if (MachineOperand *SccDef =
11545 SccDef->setIsDead(
false);
11553 if (Def.getOpcode() != AMDGPU::S_CSELECT_B32 &&
11554 Def.getOpcode() != AMDGPU::S_CSELECT_B64)
11556 bool Op1IsNonZeroImm =
11557 Def.getOperand(1).isImm() && Def.getOperand(1).getImm() != 0;
11558 bool Op2IsZeroImm =
11559 Def.getOperand(2).isImm() && Def.getOperand(2).getImm() == 0;
11560 return Op1IsNonZeroImm && Op2IsZeroImm;
11564 unsigned &NewDefOpc) {
11567 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11568 Def.getOpcode() != AMDGPU::S_ADD_U32)
11574 Def.getMF()->getSubtarget().getInstrInfo());
11576 auto Imm1 =
TII->getImmOrMaterializedImm(MRI, AddSrc1);
11577 auto Imm2 =
TII->getImmOrMaterializedImm(MRI, AddSrc2);
11578 if ((!Imm1 || *Imm1 != 1) && (!Imm2 || *Imm2 != 1))
11581 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11583 Def.findRegisterDefOperand(AMDGPU::SCC,
nullptr);
11586 NewDefOpc = AMDGPU::S_ADD_U32;
11588 NeedInversion = !NeedInversion;
11593 Register SrcReg2, int64_t CmpMask,
11603 CmpValue = *ImmOpt;
11606 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue, MRI,
11607 this](
bool NeedInversion) ->
bool {
11631 unsigned NewDefOpc = Def->getOpcode();
11637 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11640 if (NewDefOpc != Def->getOpcode())
11641 Def->setDesc(
get(NewDefOpc));
11650 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11657 if (Def1 && Def1->
getOpcode() == AMDGPU::COPY && Def2 &&
11665 optimizeSCC(
Select, Def,
false);
11672 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue, MRI,
11673 this](int64_t ExpectedValue,
unsigned SrcSize,
11674 bool IsReversible,
bool IsSigned) ->
bool {
11702 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11703 Def->getOpcode() != AMDGPU::S_AND_B64)
11707 const auto isMask = [&Mask, SrcSize, MRI,
11719 SrcOp = &Def->getOperand(2);
11720 else if (isMask(&Def->getOperand(2)))
11721 SrcOp = &Def->getOperand(1);
11729 if (IsSigned && BitNo == SrcSize - 1)
11732 ExpectedValue <<= BitNo;
11734 bool IsReversedCC =
false;
11735 if (CmpValue != ExpectedValue) {
11738 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11743 Register DefReg = Def->getOperand(0).getReg();
11744 if (IsReversedCC && !MRI->hasOneNonDBGUse(DefReg))
11747 if (!optimizeSCC(Def, &CmpInstr,
false))
11750 if (!MRI->use_nodbg_empty(DefReg)) {
11758 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11759 : AMDGPU::S_BITCMP1_B32
11760 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11761 : AMDGPU::S_BITCMP1_B64;
11766 Def->eraseFromParent();
11774 case AMDGPU::S_CMP_EQ_U32:
11775 case AMDGPU::S_CMP_EQ_I32:
11776 case AMDGPU::S_CMPK_EQ_U32:
11777 case AMDGPU::S_CMPK_EQ_I32:
11778 return optimizeCmpAnd(1, 32,
true,
false) ||
11779 optimizeCmpSelect(
true);
11780 case AMDGPU::S_CMP_GE_U32:
11781 case AMDGPU::S_CMPK_GE_U32:
11782 return optimizeCmpAnd(1, 32,
false,
false);
11783 case AMDGPU::S_CMP_GE_I32:
11784 case AMDGPU::S_CMPK_GE_I32:
11785 return optimizeCmpAnd(1, 32,
false,
true);
11786 case AMDGPU::S_CMP_EQ_U64:
11787 return optimizeCmpAnd(1, 64,
true,
false);
11788 case AMDGPU::S_CMP_LG_U32:
11789 case AMDGPU::S_CMP_LG_I32:
11790 case AMDGPU::S_CMPK_LG_U32:
11791 case AMDGPU::S_CMPK_LG_I32:
11792 return optimizeCmpAnd(0, 32,
true,
false) ||
11793 optimizeCmpSelect(
false);
11794 case AMDGPU::S_CMP_GT_U32:
11795 case AMDGPU::S_CMPK_GT_U32:
11796 return optimizeCmpAnd(0, 32,
false,
false);
11797 case AMDGPU::S_CMP_GT_I32:
11798 case AMDGPU::S_CMPK_GT_I32:
11799 return optimizeCmpAnd(0, 32,
false,
true);
11800 case AMDGPU::S_CMP_LG_U64:
11801 return optimizeCmpAnd(0, 64,
true,
false) ||
11802 optimizeCmpSelect(
false);
11809 AMDGPU::OpName
OpName)
const {
11810 if (!ST.needsAlignedVGPRs())
11813 int OpNo = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
OpName);
11825 bool IsAGPR = RI.isAGPR(MRI, DataReg);
11827 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
11831 : &AMDGPU::VReg_64_Align2RegClass);
11833 .
addReg(DataReg, {},
Op.getSubReg())
11838 Op.setSubReg(AMDGPU::sub0);
11843 if (!SchedModel.hasInstrSchedModel())
11849 unsigned RepeatRate = 0;
11851 PI = SchedModel.getWriteProcResBegin(SCDesc),
11852 PE = SchedModel.getWriteProcResEnd(SCDesc);
11854 RepeatRate = std::max(RepeatRate, (
unsigned)PI->ReleaseAtCycle);
11871 if (ST.hasGFX1250Insts())
11878 unsigned Opcode =
MI.getOpcode();
11884 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
11885 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
11888 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 MovTermOpc
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
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)
bool isNonCommutableDPP(const MachineInstr &MI) const
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 getBlockingCycles(const MachineInstr &MI) const
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
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)
static bool isSrc1DPPRevOpcode(const GCNSubtarget &ST, uint32_t Opcode)
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_IMM_NOINLINE_FP16
@ 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 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.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
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.
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.
uint8_t GFX1250BlockingCycles
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.