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) {
5285 if (OldSDst && OldSDst->
isDead()) {
5288 NewVCC->setIsDead();
5297 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5305 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5308 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5309 AMDGPU::SReg_64RegClass.contains(Reg);
5337 switch (MO.getReg()) {
5339 case AMDGPU::VCC_LO:
5340 case AMDGPU::VCC_HI:
5342 case AMDGPU::FLAT_SCR:
5355 switch (
MI.getOpcode()) {
5356 case AMDGPU::V_READLANE_B32:
5357 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5358 case AMDGPU::V_WRITELANE_B32:
5359 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5366 if (
MI.isPreISelOpcode() ||
5367 SIInstrInfo::isGenericOpcode(
MI.getOpcode()) ||
5385 return SubReg.
getSubReg() != AMDGPU::NoSubRegister &&
5396 if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
5397 ErrInfo =
"illegal copy from vector register to SGPR";
5415 if (!MRI.
isSSA() &&
MI.isCopy())
5416 return verifyCopy(
MI, MRI, ErrInfo);
5418 if (SIInstrInfo::isGenericOpcode(Opcode))
5421 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5422 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5423 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5425 if (Src0Idx == -1) {
5427 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5428 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5429 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5430 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5435 if (!
Desc.isVariadic() &&
5436 Desc.getNumOperands() !=
MI.getNumExplicitOperands()) {
5437 ErrInfo =
"Instruction has wrong number of operands.";
5441 if (
MI.isInlineAsm()) {
5454 if (!Reg.isVirtual() && !RC->
contains(Reg)) {
5455 ErrInfo =
"inlineasm operand has incorrect register class.";
5463 if (
isImage(
MI) &&
MI.memoperands_empty() &&
MI.mayLoadOrStore()) {
5464 ErrInfo =
"missing memory operand from image instruction.";
5469 for (
int i = 0, e =
Desc.getNumOperands(); i != e; ++i) {
5472 ErrInfo =
"FPImm Machine Operands are not supported. ISel should bitcast "
5473 "all fp values to integers.";
5479 switch (OpInfo.OperandType) {
5481 if (
MI.getOperand(i).isImm() ||
MI.getOperand(i).isGlobal()) {
5482 ErrInfo =
"Illegal immediate value for operand.";
5514 ErrInfo =
"Illegal immediate value for operand.";
5523 if (ST.has64BitLiterals() &&
Desc.getSize() != 4 && MO.
isImm() &&
5526 OpInfo.OperandType ==
5528 ErrInfo =
"illegal 64-bit immediate value for operand.";
5535 ErrInfo =
"Expected inline constant for operand.";
5549 if (!
MI.getOperand(i).isImm() && !
MI.getOperand(i).isFI()) {
5550 ErrInfo =
"Expected immediate, but got non-immediate";
5559 if (OpInfo.isGenericType())
5567 if (!ST.hasSDWA()) {
5568 ErrInfo =
"SDWA is not supported on this target";
5572 for (
auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5573 AMDGPU::OpName::dst_sel}) {
5579 ErrInfo =
"Invalid SDWA selection";
5584 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5586 for (
int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5591 if (!ST.hasSDWAScalar()) {
5593 if (!MO.
isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.
getReg()))) {
5594 ErrInfo =
"Only VGPRs allowed as operands in SDWA instructions on VI";
5601 "Only reg allowed as operands in SDWA instructions on GFX9+";
5607 if (!ST.hasSDWAOmod()) {
5610 if (OMod !=
nullptr &&
5612 ErrInfo =
"OMod not allowed in SDWA instructions on VI";
5617 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5618 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5619 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5620 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5623 unsigned Mods = Src0ModsMO->
getImm();
5626 ErrInfo =
"sext, abs and neg are not allowed on this instruction";
5632 if (
isVOPC(BasicOpcode)) {
5633 if (!ST.hasSDWASdst() && DstIdx != -1) {
5636 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5637 ErrInfo =
"Only VCC allowed as dst in SDWA instructions on VI";
5640 }
else if (!ST.hasSDWAOutModsVOPC()) {
5643 if (Clamp && (!Clamp->
isImm() || Clamp->
getImm() != 0)) {
5644 ErrInfo =
"Clamp not allowed in VOPC SDWA instructions on VI";
5650 if (OMod && (!OMod->
isImm() || OMod->
getImm() != 0)) {
5651 ErrInfo =
"OMod not allowed in VOPC SDWA instructions on VI";
5658 if (DstUnused && DstUnused->isImm() &&
5661 if (!Dst.isReg() || !Dst.isTied()) {
5662 ErrInfo =
"Dst register should have tied register";
5667 MI.getOperand(
MI.findTiedOperandIdx(DstIdx));
5670 "Dst register should be tied to implicit use of preserved register";
5674 ErrInfo =
"Dst register should use same physical register as preserved";
5680 if (
isDPP(
MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5682 if (Src1MO.
isReg() && RI.isSGPRReg(MRI, Src1MO.
getReg())) {
5683 ErrInfo =
"DPP src1 cannot be SGPR on this subtarget";
5686 if (Src1MO.
isImm()) {
5687 ErrInfo =
"DPP src1 cannot be an immediate on this subtarget";
5693 if (
isImage(Opcode) && !
MI.mayStore()) {
5698 uint64_t DMaskImm = DMask->
getImm();
5705 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5713 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5717 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5718 if (RegCount > DstSize) {
5719 ErrInfo =
"Image instruction returns too many registers for dst "
5729 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5730 unsigned ConstantBusCount = 0;
5731 bool UsesLiteral =
false;
5734 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5738 LiteralVal = &
MI.getOperand(ImmIdx);
5747 for (
int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5758 }
else if (!MO.
isFI()) {
5765 ErrInfo =
"VOP2/VOP3 instruction uses more than one literal";
5775 if (
llvm::all_of(SGPRsUsed, [
this, SGPRUsed](
unsigned SGPR) {
5776 return !RI.regsOverlap(SGPRUsed, SGPR);
5785 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5786 Opcode != AMDGPU::V_WRITELANE_B32) {
5787 ErrInfo =
"VOP* instruction violates constant bus restriction";
5791 if (
isVOP3(
MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5792 ErrInfo =
"VOP3 instruction uses literal";
5799 if (
Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5800 unsigned SGPRCount = 0;
5803 for (
int OpIdx : {Src0Idx, Src1Idx}) {
5811 if (MO.
getReg() != SGPRUsed)
5816 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5817 ErrInfo =
"WRITELANE instruction violates constant bus restriction";
5824 if (
Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5825 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5832 ErrInfo =
"v_div_scale_{f32|f64} require src0 = src1 or src2";
5842 ErrInfo =
"ABS not allowed in VOP3B instructions";
5855 ErrInfo =
"SOP2/SOPC instruction requires too many immediate constants";
5862 if (
Desc.isBranch()) {
5864 ErrInfo =
"invalid branch target for SOPK instruction";
5868 uint64_t
Imm =
Op->getImm();
5871 ErrInfo =
"invalid immediate for SOPK instruction";
5876 ErrInfo =
"invalid immediate for SOPK instruction";
5883 if (
Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
5884 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
5885 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5886 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
5887 const bool IsDst =
Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5888 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
5890 const unsigned StaticNumOps =
5891 Desc.getNumOperands() +
Desc.implicit_uses().size();
5892 const unsigned NumImplicitOps = IsDst ? 2 : 1;
5898 if (
MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
5899 ErrInfo =
"missing implicit register operands";
5905 if (!Dst->isUse()) {
5906 ErrInfo =
"v_movreld_b32 vdst should be a use operand";
5911 if (!
MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
5912 UseOpIdx != StaticNumOps + 1) {
5913 ErrInfo =
"movrel implicit operands should be tied";
5920 =
MI.getOperand(StaticNumOps + NumImplicitOps - 1);
5922 !
isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
5923 ErrInfo =
"src0 should be subreg of implicit vector use";
5931 if (!
MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
5932 ErrInfo =
"VALU instruction does not implicitly read exec mask";
5938 if (
MI.mayStore() &&
5943 if (Soff && Soff->
getReg() != AMDGPU::M0) {
5944 ErrInfo =
"scalar stores must use m0 as offset register";
5950 if (
isFLAT(
MI) && !ST.hasFlatInstOffsets()) {
5952 if (
Offset->getImm() != 0) {
5953 ErrInfo =
"subtarget does not support offsets in flat instructions";
5958 if (
isDS(
MI) && !ST.hasGDS()) {
5960 if (GDSOp && GDSOp->
getImm() != 0) {
5961 ErrInfo =
"GDS is not supported on this subtarget";
5969 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
5970 AMDGPU::OpName::vaddr0);
5971 AMDGPU::OpName RSrcOpName =
5972 isMIMG(
MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
5973 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
5981 ErrInfo =
"dim is out of range";
5986 if (ST.hasR128A16()) {
5988 IsA16 = R128A16->
getImm() != 0;
5989 }
else if (ST.hasA16()) {
5991 IsA16 = A16->
getImm() != 0;
5994 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
5996 unsigned AddrWords =
5999 unsigned VAddrWords;
6001 VAddrWords = RsrcIdx - VAddr0Idx;
6002 if (ST.hasPartialNSAEncoding() &&
6004 unsigned LastVAddrIdx = RsrcIdx - 1;
6005 VAddrWords +=
getOpSize(
MI, LastVAddrIdx) / 4 - 1;
6013 if (VAddrWords != AddrWords) {
6015 <<
" but got " << VAddrWords <<
"\n");
6016 ErrInfo =
"bad vaddr size";
6026 unsigned DC = DppCt->
getImm();
6027 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
6028 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
6029 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
6030 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
6031 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
6032 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
6033 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
6034 ErrInfo =
"Invalid dpp_ctrl value";
6037 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
6038 !ST.hasDPPWavefrontShifts()) {
6039 ErrInfo =
"Invalid dpp_ctrl value: "
6040 "wavefront shifts are not supported on GFX10+";
6043 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
6044 !ST.hasDPPBroadcasts()) {
6045 ErrInfo =
"Invalid dpp_ctrl value: "
6046 "broadcasts are not supported on GFX10+";
6049 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
6051 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
6052 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
6053 !ST.hasGFX90AInsts()) {
6054 ErrInfo =
"Invalid dpp_ctrl value: "
6055 "row_newbroadcast/row_share is not supported before "
6059 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
6060 ErrInfo =
"Invalid dpp_ctrl value: "
6061 "row_share and row_xmask are not supported before GFX10";
6066 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
6068 ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
6070 ErrInfo =
"Invalid dpp_ctrl value: "
6071 "DP ALU dpp only support row_newbcast";
6078 AMDGPU::OpName DataName =
6079 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
6085 if (!ST.hasGFX90AInsts()) {
6086 if ((Dst && RI.isAGPR(MRI, Dst->getReg())) ||
6087 (
Data && RI.isAGPR(MRI,
Data->getReg())) ||
6088 (Data2 && RI.isAGPR(MRI, Data2->
getReg()))) {
6089 ErrInfo =
"Invalid register class: "
6090 "agpr loads and stores not supported on this GPU";
6096 if (ST.needsAlignedVGPRs()) {
6097 const auto isAlignedReg = [&
MI, &MRI,
this](AMDGPU::OpName
OpName) ->
bool {
6102 if (Reg.isPhysical())
6103 return !(RI.getHWRegIndex(Reg) & 1);
6105 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
6106 !(RI.getChannelFromSubReg(
Op->getSubReg()) & 1);
6110 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
6111 ErrInfo =
"Subtarget requires even aligned vector registers "
6112 "for vaddr operand of image instructions";
6118 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
6120 if (Src->isReg() && RI.isSGPRReg(MRI, Src->getReg())) {
6121 ErrInfo =
"Invalid register class: "
6122 "v_accvgpr_write with an SGPR is not supported on this GPU";
6127 if (
Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
6130 ErrInfo =
"pseudo expects only physical SGPRs";
6137 if (!ST.hasScaleOffset()) {
6138 ErrInfo =
"Subtarget does not support offset scaling";
6142 ErrInfo =
"Instruction does not support offset scaling";
6150 for (
unsigned I = 0;
I < 3; ++
I) {
6156 if (ST.hasFlatScratchHiInB64InstHazard() &&
isSALU(
MI) &&
6157 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI,
nullptr)) {
6159 if ((Dst && RI.getRegClassForReg(MRI, Dst->getReg()) ==
6160 &AMDGPU::SReg_64RegClass) ||
6161 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
6162 ErrInfo =
"Instruction cannot read flat_scratch_base_hi";
6171 if (
MI.getOpcode() == AMDGPU::S_MOV_B32) {
6173 return MI.getOperand(1).isReg() || RI.isAGPR(MRI,
MI.getOperand(0).getReg())
6175 : AMDGPU::V_MOV_B32_e32;
6185 default:
return AMDGPU::INSTRUCTION_LIST_END;
6186 case AMDGPU::REG_SEQUENCE:
return AMDGPU::REG_SEQUENCE;
6187 case AMDGPU::COPY:
return AMDGPU::COPY;
6188 case AMDGPU::PHI:
return AMDGPU::PHI;
6189 case AMDGPU::INSERT_SUBREG:
return AMDGPU::INSERT_SUBREG;
6190 case AMDGPU::WQM:
return AMDGPU::WQM;
6191 case AMDGPU::SOFT_WQM:
return AMDGPU::SOFT_WQM;
6192 case AMDGPU::STRICT_WWM:
return AMDGPU::STRICT_WWM;
6193 case AMDGPU::STRICT_WQM:
return AMDGPU::STRICT_WQM;
6194 case AMDGPU::S_ADD_I32:
6195 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
6196 case AMDGPU::S_ADDC_U32:
6197 return AMDGPU::V_ADDC_U32_e32;
6198 case AMDGPU::S_SUB_I32:
6199 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
6202 case AMDGPU::S_ADD_U32:
6203 return AMDGPU::V_ADD_CO_U32_e32;
6204 case AMDGPU::S_SUB_U32:
6205 return AMDGPU::V_SUB_CO_U32_e32;
6206 case AMDGPU::S_ADD_U64_PSEUDO:
6207 return AMDGPU::V_ADD_U64_PSEUDO;
6208 case AMDGPU::S_SUB_U64_PSEUDO:
6209 return AMDGPU::V_SUB_U64_PSEUDO;
6210 case AMDGPU::S_SUBB_U32:
return AMDGPU::V_SUBB_U32_e32;
6211 case AMDGPU::S_MUL_I32:
return AMDGPU::V_MUL_LO_U32_e64;
6212 case AMDGPU::S_MUL_HI_U32:
return AMDGPU::V_MUL_HI_U32_e64;
6213 case AMDGPU::S_MUL_HI_I32:
return AMDGPU::V_MUL_HI_I32_e64;
6214 case AMDGPU::S_AND_B32:
return AMDGPU::V_AND_B32_e64;
6215 case AMDGPU::S_OR_B32:
return AMDGPU::V_OR_B32_e64;
6216 case AMDGPU::S_XOR_B32:
return AMDGPU::V_XOR_B32_e64;
6217 case AMDGPU::S_XNOR_B32:
6218 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6219 case AMDGPU::S_MIN_I32:
return AMDGPU::V_MIN_I32_e64;
6220 case AMDGPU::S_MIN_U32:
return AMDGPU::V_MIN_U32_e64;
6221 case AMDGPU::S_MAX_I32:
return AMDGPU::V_MAX_I32_e64;
6222 case AMDGPU::S_MAX_U32:
return AMDGPU::V_MAX_U32_e64;
6223 case AMDGPU::S_ASHR_I32:
return AMDGPU::V_ASHR_I32_e32;
6224 case AMDGPU::S_ASHR_I64:
return AMDGPU::V_ASHR_I64_e64;
6225 case AMDGPU::S_LSHL_B32:
return AMDGPU::V_LSHL_B32_e32;
6226 case AMDGPU::S_LSHL_B64:
return AMDGPU::V_LSHL_B64_e64;
6227 case AMDGPU::S_LSHR_B32:
return AMDGPU::V_LSHR_B32_e32;
6228 case AMDGPU::S_LSHR_B64:
return AMDGPU::V_LSHR_B64_e64;
6229 case AMDGPU::S_SEXT_I32_I8:
return AMDGPU::V_BFE_I32_e64;
6230 case AMDGPU::S_SEXT_I32_I16:
return AMDGPU::V_BFE_I32_e64;
6231 case AMDGPU::S_BFE_U32:
return AMDGPU::V_BFE_U32_e64;
6232 case AMDGPU::S_BFE_I32:
return AMDGPU::V_BFE_I32_e64;
6233 case AMDGPU::S_BFM_B32:
return AMDGPU::V_BFM_B32_e64;
6234 case AMDGPU::S_BREV_B32:
return AMDGPU::V_BFREV_B32_e32;
6235 case AMDGPU::S_NOT_B32:
return AMDGPU::V_NOT_B32_e32;
6236 case AMDGPU::S_NOT_B64:
return AMDGPU::V_NOT_B32_e32;
6237 case AMDGPU::S_CMP_EQ_I32:
return AMDGPU::V_CMP_EQ_I32_e64;
6238 case AMDGPU::S_CMP_LG_I32:
return AMDGPU::V_CMP_NE_I32_e64;
6239 case AMDGPU::S_CMP_GT_I32:
return AMDGPU::V_CMP_GT_I32_e64;
6240 case AMDGPU::S_CMP_GE_I32:
return AMDGPU::V_CMP_GE_I32_e64;
6241 case AMDGPU::S_CMP_LT_I32:
return AMDGPU::V_CMP_LT_I32_e64;
6242 case AMDGPU::S_CMP_LE_I32:
return AMDGPU::V_CMP_LE_I32_e64;
6243 case AMDGPU::S_CMP_EQ_U32:
return AMDGPU::V_CMP_EQ_U32_e64;
6244 case AMDGPU::S_CMP_LG_U32:
return AMDGPU::V_CMP_NE_U32_e64;
6245 case AMDGPU::S_CMP_GT_U32:
return AMDGPU::V_CMP_GT_U32_e64;
6246 case AMDGPU::S_CMP_GE_U32:
return AMDGPU::V_CMP_GE_U32_e64;
6247 case AMDGPU::S_CMP_LT_U32:
return AMDGPU::V_CMP_LT_U32_e64;
6248 case AMDGPU::S_CMP_LE_U32:
return AMDGPU::V_CMP_LE_U32_e64;
6249 case AMDGPU::S_CMP_EQ_U64:
return AMDGPU::V_CMP_EQ_U64_e64;
6250 case AMDGPU::S_CMP_LG_U64:
return AMDGPU::V_CMP_NE_U64_e64;
6251 case AMDGPU::S_BCNT1_I32_B32:
return AMDGPU::V_BCNT_U32_B32_e64;
6252 case AMDGPU::S_FF1_I32_B32:
return AMDGPU::V_FFBL_B32_e32;
6253 case AMDGPU::S_FLBIT_I32_B32:
return AMDGPU::V_FFBH_U32_e32;
6254 case AMDGPU::S_FLBIT_I32:
return AMDGPU::V_FFBH_I32_e64;
6255 case AMDGPU::S_CBRANCH_SCC0:
return AMDGPU::S_CBRANCH_VCCZ;
6256 case AMDGPU::S_CBRANCH_SCC1:
return AMDGPU::S_CBRANCH_VCCNZ;
6257 case AMDGPU::S_CVT_F32_I32:
return AMDGPU::V_CVT_F32_I32_e64;
6258 case AMDGPU::S_CVT_F32_U32:
return AMDGPU::V_CVT_F32_U32_e64;
6259 case AMDGPU::S_CVT_I32_F32:
return AMDGPU::V_CVT_I32_F32_e64;
6260 case AMDGPU::S_CVT_U32_F32:
return AMDGPU::V_CVT_U32_F32_e64;
6261 case AMDGPU::S_CVT_F32_F16:
6262 case AMDGPU::S_CVT_HI_F32_F16:
6263 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6264 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6265 case AMDGPU::S_CVT_F16_F32:
6266 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6267 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6268 case AMDGPU::S_CEIL_F32:
return AMDGPU::V_CEIL_F32_e64;
6269 case AMDGPU::S_FLOOR_F32:
return AMDGPU::V_FLOOR_F32_e64;
6270 case AMDGPU::S_TRUNC_F32:
return AMDGPU::V_TRUNC_F32_e64;
6271 case AMDGPU::S_RNDNE_F32:
return AMDGPU::V_RNDNE_F32_e64;
6272 case AMDGPU::S_CEIL_F16:
6273 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6274 : AMDGPU::V_CEIL_F16_fake16_e64;
6275 case AMDGPU::S_FLOOR_F16:
6276 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6277 : AMDGPU::V_FLOOR_F16_fake16_e64;
6278 case AMDGPU::S_TRUNC_F16:
6279 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6280 : AMDGPU::V_TRUNC_F16_fake16_e64;
6281 case AMDGPU::S_RNDNE_F16:
6282 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6283 : AMDGPU::V_RNDNE_F16_fake16_e64;
6284 case AMDGPU::S_ADD_F32:
return AMDGPU::V_ADD_F32_e64;
6285 case AMDGPU::S_SUB_F32:
return AMDGPU::V_SUB_F32_e64;
6286 case AMDGPU::S_MIN_F32:
return AMDGPU::V_MIN_F32_e64;
6287 case AMDGPU::S_MAX_F32:
return AMDGPU::V_MAX_F32_e64;
6288 case AMDGPU::S_MINIMUM_F32:
return AMDGPU::V_MINIMUM_F32_e64;
6289 case AMDGPU::S_MAXIMUM_F32:
return AMDGPU::V_MAXIMUM_F32_e64;
6290 case AMDGPU::S_MUL_F32:
return AMDGPU::V_MUL_F32_e64;
6291 case AMDGPU::S_ADD_F16:
6292 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6293 : AMDGPU::V_ADD_F16_fake16_e64;
6294 case AMDGPU::S_SUB_F16:
6295 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6296 : AMDGPU::V_SUB_F16_fake16_e64;
6297 case AMDGPU::S_MIN_F16:
6298 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6299 : AMDGPU::V_MIN_F16_fake16_e64;
6300 case AMDGPU::S_MAX_F16:
6301 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6302 : AMDGPU::V_MAX_F16_fake16_e64;
6303 case AMDGPU::S_MINIMUM_F16:
6304 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6305 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6306 case AMDGPU::S_MAXIMUM_F16:
6307 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6308 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6309 case AMDGPU::S_MUL_F16:
6310 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6311 : AMDGPU::V_MUL_F16_fake16_e64;
6312 case AMDGPU::S_CVT_PK_RTZ_F16_F32:
return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6313 case AMDGPU::S_FMAC_F32:
return AMDGPU::V_FMAC_F32_e64;
6314 case AMDGPU::S_FMAC_F16:
6315 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6316 : AMDGPU::V_FMAC_F16_fake16_e64;
6317 case AMDGPU::S_FMAMK_F32:
return AMDGPU::V_FMAMK_F32;
6318 case AMDGPU::S_FMAAK_F32:
return AMDGPU::V_FMAAK_F32;
6319 case AMDGPU::S_CMP_LT_F32:
return AMDGPU::V_CMP_LT_F32_e64;
6320 case AMDGPU::S_CMP_EQ_F32:
return AMDGPU::V_CMP_EQ_F32_e64;
6321 case AMDGPU::S_CMP_LE_F32:
return AMDGPU::V_CMP_LE_F32_e64;
6322 case AMDGPU::S_CMP_GT_F32:
return AMDGPU::V_CMP_GT_F32_e64;
6323 case AMDGPU::S_CMP_LG_F32:
return AMDGPU::V_CMP_LG_F32_e64;
6324 case AMDGPU::S_CMP_GE_F32:
return AMDGPU::V_CMP_GE_F32_e64;
6325 case AMDGPU::S_CMP_O_F32:
return AMDGPU::V_CMP_O_F32_e64;
6326 case AMDGPU::S_CMP_U_F32:
return AMDGPU::V_CMP_U_F32_e64;
6327 case AMDGPU::S_CMP_NGE_F32:
return AMDGPU::V_CMP_NGE_F32_e64;
6328 case AMDGPU::S_CMP_NLG_F32:
return AMDGPU::V_CMP_NLG_F32_e64;
6329 case AMDGPU::S_CMP_NGT_F32:
return AMDGPU::V_CMP_NGT_F32_e64;
6330 case AMDGPU::S_CMP_NLE_F32:
return AMDGPU::V_CMP_NLE_F32_e64;
6331 case AMDGPU::S_CMP_NEQ_F32:
return AMDGPU::V_CMP_NEQ_F32_e64;
6332 case AMDGPU::S_CMP_NLT_F32:
return AMDGPU::V_CMP_NLT_F32_e64;
6333 case AMDGPU::S_CMP_LT_F16:
6334 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6335 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6336 case AMDGPU::S_CMP_EQ_F16:
6337 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6338 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6339 case AMDGPU::S_CMP_LE_F16:
6340 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6341 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6342 case AMDGPU::S_CMP_GT_F16:
6343 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6344 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6345 case AMDGPU::S_CMP_LG_F16:
6346 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6347 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6348 case AMDGPU::S_CMP_GE_F16:
6349 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6350 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6351 case AMDGPU::S_CMP_O_F16:
6352 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6353 : AMDGPU::V_CMP_O_F16_fake16_e64;
6354 case AMDGPU::S_CMP_U_F16:
6355 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6356 : AMDGPU::V_CMP_U_F16_fake16_e64;
6357 case AMDGPU::S_CMP_NGE_F16:
6358 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6359 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6360 case AMDGPU::S_CMP_NLG_F16:
6361 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6362 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6363 case AMDGPU::S_CMP_NGT_F16:
6364 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6365 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6366 case AMDGPU::S_CMP_NLE_F16:
6367 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6368 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6369 case AMDGPU::S_CMP_NEQ_F16:
6370 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6371 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6372 case AMDGPU::S_CMP_NLT_F16:
6373 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6374 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6375 case AMDGPU::V_S_EXP_F32_e64:
return AMDGPU::V_EXP_F32_e64;
6376 case AMDGPU::V_S_EXP_F16_e64:
6377 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6378 : AMDGPU::V_EXP_F16_fake16_e64;
6379 case AMDGPU::V_S_LOG_F32_e64:
return AMDGPU::V_LOG_F32_e64;
6380 case AMDGPU::V_S_LOG_F16_e64:
6381 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6382 : AMDGPU::V_LOG_F16_fake16_e64;
6383 case AMDGPU::V_S_RCP_F32_e64:
return AMDGPU::V_RCP_F32_e64;
6384 case AMDGPU::V_S_RCP_F16_e64:
6385 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6386 : AMDGPU::V_RCP_F16_fake16_e64;
6387 case AMDGPU::V_S_RSQ_F32_e64:
return AMDGPU::V_RSQ_F32_e64;
6388 case AMDGPU::V_S_RSQ_F16_e64:
6389 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6390 : AMDGPU::V_RSQ_F16_fake16_e64;
6391 case AMDGPU::V_S_SQRT_F32_e64:
return AMDGPU::V_SQRT_F32_e64;
6392 case AMDGPU::V_S_SQRT_F16_e64:
6393 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6394 : AMDGPU::V_SQRT_F16_fake16_e64;
6397 "Unexpected scalar opcode without corresponding vector one!");
6446 "Not a whole wave func");
6449 if (
MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6450 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6457 unsigned OpNo)
const {
6459 if (
MI.isVariadic() || OpNo >=
Desc.getNumOperands() ||
6460 Desc.operands()[OpNo].RegClass == -1) {
6463 if (Reg.isVirtual()) {
6467 return RI.getPhysRegBaseClass(Reg);
6470 int16_t RegClass = getOpRegClassID(
Desc.operands()[OpNo]);
6471 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6476 constexpr AMDGPU::OpName OpNames[] = {
6477 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6480 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
I]);
6481 if (
static_cast<unsigned>(SrcIdx) == OpIdx)
6493 unsigned RCID = getOpRegClassID(
get(
MI.getOpcode()).operands()[OpIdx]);
6495 unsigned Size = RI.getRegSizeInBits(*RC);
6496 unsigned Opcode = (
Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6497 :
Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6498 : AMDGPU::V_MOV_B32_e32;
6500 Opcode = AMDGPU::COPY;
6501 else if (RI.isSGPRClass(RC))
6502 Opcode = (
Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6527 .
addImm(AMDGPU::sub0_sub1)
6529 .
addImm(AMDGPU::sub2_sub3);
6530 }
else if (Opcode == AMDGPU::V_MOV_B16_t16_e64) {
6547 return RI.getSubReg(SuperReg.
getReg(), SubIdx);
6553 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.
getSubReg(), SubIdx);
6564 if (SubIdx == AMDGPU::sub0)
6566 if (SubIdx == AMDGPU::sub1)
6578void SIInstrInfo::swapOperands(
MachineInstr &Inst)
const {
6594 if (Reg.isPhysical())
6601 RI.getLargestLegalSuperClass(RC, MRI.
getMF());
6604 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.
getSubReg()) !=
nullptr;
6607 return RI.getCommonSubClass(DRC, RC) !=
nullptr;
6614 unsigned Opc =
MI.getOpcode();
6617 if (MO.
isReg() && RI.isSGPRReg(MRI, MO.
getReg()) &&
6627 bool IsAGPR = RI.isAGPR(MRI, MO.
getReg());
6628 if (IsAGPR && !ST.hasMAIInsts())
6634 const int VDstIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
6635 const int DataIdx = AMDGPU::getNamedOperandIdx(
6636 Opc,
isDS(
Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6637 if ((
int)OpIdx == VDstIdx && DataIdx != -1 &&
6638 MI.getOperand(DataIdx).isReg() &&
6639 RI.isAGPR(MRI,
MI.getOperand(DataIdx).getReg()) != IsAGPR)
6641 if ((
int)OpIdx == DataIdx) {
6642 if (VDstIdx != -1 &&
6643 RI.isAGPR(MRI,
MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6646 const int Data1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
6647 if (Data1Idx != -1 &&
MI.getOperand(Data1Idx).isReg() &&
6648 RI.isAGPR(MRI,
MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6653 if (
Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6654 (
int)OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) &&
6655 RI.isSGPRReg(MRI, MO.
getReg()))
6658 if (ST.hasFlatScratchHiInB64InstHazard() &&
6665 if (
Opc == AMDGPU::S_BITCMP0_B64 ||
Opc == AMDGPU::S_BITCMP1_B64)
6668 if (!ST.hasDPPSrc1SGPR() &&
isDPP(
MI) && RI.isSGPRReg(MRI, MO.
getReg()) &&
6669 (
int)OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1))
6689 constexpr unsigned NumOps = 3;
6690 constexpr AMDGPU::OpName OpNames[
NumOps * 2] = {
6691 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6692 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6693 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6698 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[SrcN]);
6701 MO = &
MI.getOperand(SrcIdx);
6704 if (!MO->
isReg() || !RI.isSGPRReg(MRI, MO->
getReg()))
6708 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
NumOps + SrcN]);
6712 unsigned Mods =
MI.getOperand(ModsIdx).getImm();
6716 return !OpSel && !OpSelHi;
6725 int64_t RegClass = getOpRegClassID(OpInfo);
6727 RegClass != -1 ? RI.getRegClass(RegClass) :
nullptr;
6729 MO = &
MI.getOperand(OpIdx);
6733 if (
isVALU(
MI,
false) && !IsInlineConst &&
6737 int ConstantBusLimit = ST.getConstantBusLimit(
MI.getOpcode());
6738 int LiteralLimit = !
isVOP3(
MI) || ST.hasVOP3Literal() ? 1 : 0;
6742 if (!LiteralLimit--)
6752 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6760 if (--ConstantBusLimit <= 0)
6772 if (!LiteralLimit--)
6774 if (--ConstantBusLimit <= 0)
6780 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6784 if (!
Op.isReg() && !
Op.isFI() && !
Op.isRegMask() &&
6786 !
Op.isIdenticalTo(*MO))
6808 bool Is64BitOp = Is64BitFPOp ||
6816 (!ST.has64BitLiterals() || InstDesc.
getSize() != 4))
6825 if (!Is64BitFPOp && (int32_t)
Imm < 0 &&
6843 bool IsGFX950Only = ST.hasGFX950Insts();
6844 bool IsGFX940Only = ST.hasGFX940Insts();
6846 if (!IsGFX950Only && !IsGFX940Only)
6864 unsigned Opcode =
MI.getOpcode();
6866 case AMDGPU::V_CVT_PK_BF8_F32_e64:
6867 case AMDGPU::V_CVT_PK_FP8_F32_e64:
6868 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
6869 case AMDGPU::V_MQSAD_U32_U8_e64:
6870 case AMDGPU::V_PK_ADD_F16:
6871 case AMDGPU::V_PK_ADD_F32:
6872 case AMDGPU::V_PK_ADD_I16:
6873 case AMDGPU::V_PK_ADD_U16:
6874 case AMDGPU::V_PK_ASHRREV_I16:
6875 case AMDGPU::V_PK_FMA_F16:
6876 case AMDGPU::V_PK_FMA_F32:
6877 case AMDGPU::V_PK_FMAC_F16_e32:
6878 case AMDGPU::V_PK_FMAC_F16_e64:
6879 case AMDGPU::V_PK_LSHLREV_B16:
6880 case AMDGPU::V_PK_LSHRREV_B16:
6881 case AMDGPU::V_PK_MAD_I16:
6882 case AMDGPU::V_PK_MAD_U16:
6883 case AMDGPU::V_PK_MAX_F16:
6884 case AMDGPU::V_PK_MAX_I16:
6885 case AMDGPU::V_PK_MAX_U16:
6886 case AMDGPU::V_PK_MIN_F16:
6887 case AMDGPU::V_PK_MIN_I16:
6888 case AMDGPU::V_PK_MIN_U16:
6889 case AMDGPU::V_PK_MOV_B32:
6890 case AMDGPU::V_PK_MUL_F16:
6891 case AMDGPU::V_PK_MUL_F32:
6892 case AMDGPU::V_PK_MUL_LO_U16:
6893 case AMDGPU::V_PK_SUB_I16:
6894 case AMDGPU::V_PK_SUB_U16:
6895 case AMDGPU::V_QSAD_PK_U16_U8_e64:
6904 unsigned Opc =
MI.getOpcode();
6907 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
6910 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
6916 if (HasImplicitSGPR && ST.getConstantBusLimit(
Opc) <= 1 && Src0.
isReg() &&
6917 RI.isSGPRReg(MRI, Src0.
getReg()))
6923 if (
Opc == AMDGPU::V_WRITELANE_B32) {
6925 if (Src0.
isReg() && RI.isVGPR(MRI, Src0.
getReg())) {
6931 if (Src1.
isReg() && RI.isVGPR(MRI, Src1.
getReg())) {
6942 if (
Opc == AMDGPU::V_FMAC_F32_e32 ||
Opc == AMDGPU::V_FMAC_F16_e32) {
6943 int Src2Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2);
6944 if (!RI.isVGPR(MRI,
MI.getOperand(Src2Idx).getReg()))
6956 if (
Opc == AMDGPU::V_READLANE_B32 && Src1.
isReg() &&
6957 RI.isVGPR(MRI, Src1.
getReg())) {
6970 if (HasImplicitSGPR || !
MI.isCommutable()) {
6987 if (CommutedOpc == -1) {
6992 MI.setDesc(
get(CommutedOpc));
6996 bool Src0Kill = Src0.
isKill();
7000 else if (Src1.
isReg()) {
7015 unsigned Opc =
MI.getOpcode();
7018 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0),
7019 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1),
7020 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2)
7023 if (
Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
7024 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
7025 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
7026 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
7027 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
7028 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
7029 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
7039 if (VOP3Idx[2] != -1) {
7051 int ConstantBusLimit = ST.getConstantBusLimit(
Opc);
7052 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
7054 Register SGPRReg = findUsedSGPR(
MI, VOP3Idx);
7056 SGPRsUsed.
insert(SGPRReg);
7060 for (
int Idx : VOP3Idx) {
7069 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
7081 if (!RI.isSGPRClass(RI.getRegClassForReg(MRI, MO.
getReg())))
7088 if (ConstantBusLimit > 0) {
7100 if ((
Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64) &&
7101 !RI.isVGPR(MRI,
MI.getOperand(VOP3Idx[2]).getReg()))
7107 for (
unsigned I = 0;
I < 3; ++
I) {
7120 SRC = RI.getCommonSubClass(SRC, DstRC);
7123 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
7125 if (RI.hasAGPRs(VRC)) {
7126 VRC = RI.getEquivalentVGPRClass(VRC);
7129 get(TargetOpcode::COPY), NewSrcReg)
7136 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
7142 for (
unsigned i = 0; i < SubRegs; ++i) {
7145 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
7146 .
addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
7152 get(AMDGPU::REG_SEQUENCE), DstReg);
7153 for (
unsigned i = 0; i < SubRegs; ++i) {
7155 MIB.
addImm(RI.getSubRegFromChannel(i));
7168 if (SBase && !RI.isSGPRClass(MRI.
getRegClass(SBase->getReg()))) {
7170 SBase->setReg(SGPR);
7173 if (SOff && !RI.isSGPRReg(MRI, SOff->
getReg())) {
7181 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::saddr);
7182 if (OldSAddrIdx < 0)
7195 if (RI.isSGPRReg(MRI, SAddr.
getReg()))
7198 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
7199 if (NewVAddrIdx < 0)
7202 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr);
7206 if (OldVAddrIdx >= 0) {
7220 if (OldVAddrIdx == NewVAddrIdx) {
7231 assert(OldSAddrIdx == NewVAddrIdx);
7233 if (OldVAddrIdx >= 0) {
7234 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7235 AMDGPU::OpName::vdst_in);
7239 if (NewVDstIn != -1) {
7240 int OldVDstIn = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst_in);
7246 if (NewVDstIn != -1) {
7247 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7288 unsigned OpSubReg =
Op.getSubReg();
7291 RI.getRegClassForReg(MRI, OpReg), OpSubReg);
7298 auto Copy =
BuildMI(InsertMBB,
I,
DL,
get(AMDGPU::COPY), DstReg)
7299 .
addReg(OpReg, {}, OpSubReg);
7301 Op.setSubReg(AMDGPU::NoSubRegister);
7308 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7311 bool ImpDef = Def->isImplicitDef();
7312 while (!ImpDef && Def && Def->isCopy()) {
7313 if (Def->getOperand(1).getReg().isPhysical())
7316 ImpDef = Def && Def->isImplicitDef();
7318 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7334 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7339 bool UseNewExecInstructions =
7348 if (UseNewExecInstructions) {
7383 for (
auto [Idx, ScalarOp] :
enumerate(ScalarOps)) {
7384 unsigned RegSize =
TRI->getRegSizeInBits(ScalarOp->getReg(), MRI);
7385 unsigned NumSubRegs =
RegSize / 32;
7386 Register VScalarOp = ScalarOp->getReg();
7389 TII.getRegClass(
TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7391 if (NumSubRegs == 1) {
7394 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7395 Common != VScalarOpRC) {
7402 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7405 if (UseNewExecInstructions) {
7407 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7410 if (
I == LoopBB.
end())
7415 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7421 CondReg = NewCondReg;
7433 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7434 ScalarOp->setReg(CurReg);
7437 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7438 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7440 ScalarOp->setReg(PhySGPRs[Idx]);
7442 ScalarOp->setIsKill();
7446 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7447 "Unhandled register size");
7449 for (
unsigned Idx = 0; Idx < NumSubRegs; Idx += 2) {
7456 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7457 .
addReg(VScalarOp, VScalarOpUndef,
TRI->getSubRegFromChannel(Idx));
7460 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7461 .
addReg(VScalarOp, VScalarOpUndef,
7462 TRI->getSubRegFromChannel(Idx + 1));
7469 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7476 NumSubRegs <= 2 ? 0 :
TRI->getSubRegFromChannel(Idx, 2);
7478 if (UseNewExecInstructions) {
7480 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7482 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7483 if (
I == LoopBB.
end())
7487 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7489 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7493 CondReg = NewCondReg;
7505 const auto *SScalarOpRC =
7511 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7512 unsigned Channel = 0;
7513 for (
Register Piece : ReadlanePieces) {
7514 Merge.addReg(Piece).addImm(
TRI->getSubRegFromChannel(Channel++));
7518 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7519 ScalarOp->setReg(SScalarOp);
7521 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7522 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7524 ScalarOp->setReg(PhySGPRs[Idx]);
7526 ScalarOp->setIsKill();
7533 if (!UseNewExecInstructions) {
7546 if (UseNewExecInstructions) {
7579 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.
size()) &&
7580 "Physical SGPRs must be empty or match the number of scalar operands");
7586 if (!Begin.isValid())
7588 if (!End.isValid()) {
7594 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7603 std::numeric_limits<unsigned>::max()) !=
7621 for (
auto I = Begin;
I != AfterMI;
I++) {
7622 for (
auto &MO :
I->all_uses())
7658 for (
auto &Succ : RemainderBB->
successors()) {
7683static std::tuple<unsigned, unsigned>
7691 TII.buildExtractSubReg(
MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7692 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7699 uint64_t RsrcDataFormat =
TII.getDefaultRsrcDataFormat();
7716 .
addImm(AMDGPU::sub0_sub1)
7722 return std::tuple(RsrcPtr, NewSRsrc);
7733 if (ST.useRealTrue16Insts())
7763 if (
MI.getOpcode() == AMDGPU::PHI) {
7765 assert(!RI.isSGPRClass(VRC));
7768 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7770 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7786 if (
MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7789 if (RI.hasVGPRs(DstRC)) {
7793 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7795 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7813 if (
MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7818 if (DstRC != Src0RC) {
7827 if (
MI.getOpcode() == AMDGPU::SI_INIT_M0) {
7829 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7835 if (
MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
7836 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
7837 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
7838 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
7839 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
7840 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
7841 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
7843 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7856 ? AMDGPU::OpName::rsrc
7857 : AMDGPU::OpName::srsrc;
7862 AMDGPU::OpName SampOpName =
7863 isMIMG(
MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
7872 if (
MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
7880 if (
MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
7884 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src0);
7894 if (
MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
7895 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
7896 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
7897 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
7899 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7906 bool isSoffsetLegal =
true;
7908 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::soffset);
7909 if (SoffsetIdx != -1) {
7913 isSoffsetLegal =
false;
7917 bool isRsrcLegal =
true;
7919 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::srsrc);
7920 if (RsrcIdx != -1) {
7922 if (Rsrc->
isReg() && !RI.isSGPRReg(MRI, Rsrc->
getReg()))
7923 isRsrcLegal =
false;
7927 if (isRsrcLegal && isSoffsetLegal)
7955 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
7959 unsigned RsrcPtr, NewSRsrc;
7966 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
7967 .addReg(VAddr->
getReg(), {}, AMDGPU::sub0)
7973 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
7974 .addReg(VAddr->
getReg(), {}, AMDGPU::sub1)
7987 }
else if (!VAddr && ST.hasAddr64()) {
7991 "FIXME: Need to emit flat atomics here");
7993 unsigned RsrcPtr, NewSRsrc;
8019 MIB.
addImm(CPol->getImm());
8024 MIB.
addImm(TFE->getImm());
8044 MI.removeFromParent();
8049 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
8050 .addImm(AMDGPU::sub0)
8051 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
8052 .addImm(AMDGPU::sub1);
8055 if (!isSoffsetLegal) {
8066 if (!isSoffsetLegal) {
8075 if (InSet.insert(
MI).second)
8079 AMDGPU::getNamedOperandIdx(
MI->getOpcode(), AMDGPU::OpName::srsrc);
8080 if (RsrcIdx != -1) {
8081 DeferredList.insert(
MI);
8086 return DeferredList.contains(
MI);
8096 if (!ST.useRealTrue16Insts())
8099 unsigned Opcode =
MI.getOpcode();
8102 if (OpIdx >=
MI.getNumExplicitOperands() ||
8103 OpIdx >=
get(Opcode).getNumOperands() ||
8104 get(Opcode).operands()[OpIdx].RegClass == -1)
8108 if (!
Op.isReg() || !
Op.getReg().isVirtual() ||
Op.isDef())
8112 if (!RI.isVGPRClass(CurrRC))
8115 int16_t RCID = getOpRegClassID(
get(Opcode).operands()[OpIdx]);
8117 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
8119 if (
Op.getSubReg() == AMDGPU::NoSubRegister)
8120 Op.setSubReg(AMDGPU::lo16);
8125 RI.getSubRegisterClass(CurrRC,
Op.getSubReg());
8126 if (RI.getMatchingSuperRegClass(ExpectedRC, CurrSRC, AMDGPU::lo16)) {
8136 Op.setReg(NewDstReg);
8137 Op.setSubReg(AMDGPU::NoSubRegister);
8142 for (
unsigned OpIdx = 0; OpIdx <
MI.getNumExplicitOperands(); OpIdx++)
8150 assert(
MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
8151 "This only handle waterfall for SI_CALL_ISEL");
8158 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
8161 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
8166 while (End !=
MBB.end() && End->isCopy() &&
8167 MI->definesRegister(End->getOperand(1).getReg(), &RI))
8177 while (!Worklist.
empty()) {
8183 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
8189 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
8191 "Deferred MachineInstr are not supposed to re-populate worklist");
8194 for (
auto &Entry : WaterFalls) {
8195 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
8197 Entry.second.SGPRs);
8200 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
8202 Entry.first->eraseFromParent();
8210 if (SubRegIndices.
size() <= 1) {
8213 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8220 for (int16_t Indice : SubRegIndices) {
8223 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8230 get(AMDGPU::REG_SEQUENCE), DstReg);
8231 for (
unsigned i = 0; i < SubRegIndices.size(); ++i) {
8233 MIB.
addImm(RI.getSubRegFromChannel(i));
8243 if (DstReg == AMDGPU::M0) {
8256 if (
I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
8258 for (
unsigned i = 0; i <
UseMI->getNumOperands(); ++i) {
8259 if (
UseMI->getOperand(i).isReg() &&
8260 UseMI->getOperand(i).getReg() == DstReg) {
8264 V2SCopyInfo.MOs.push_back(MO);
8265 V2SCopyInfo.SGPRs.push_back(DstReg);
8269 }
else if (
I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8270 I->getOperand(0).isReg() &&
8271 I->getOperand(0).getReg() == DstReg) {
8274 }
else if (
I->readsRegister(DstReg, &RI)) {
8276 V2SPhyCopiesToErase[&Inst] =
false;
8278 if (
I->findRegisterDefOperand(DstReg, &RI))
8300 case AMDGPU::S_ADD_I32:
8301 case AMDGPU::S_SUB_I32: {
8305 std::tie(
Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8313 case AMDGPU::S_MUL_U64:
8314 if (ST.useVMulU64Inst()) {
8315 NewOpcode = AMDGPU::V_MUL_U64_e64;
8319 splitScalarSMulU64(Worklist, Inst, MDT);
8323 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8324 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8327 splitScalarSMulPseudo(Worklist, Inst, MDT);
8331 case AMDGPU::S_AND_B64:
8332 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8336 case AMDGPU::S_OR_B64:
8337 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8341 case AMDGPU::S_XOR_B64:
8342 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8346 case AMDGPU::S_NAND_B64:
8347 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8351 case AMDGPU::S_NOR_B64:
8352 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8356 case AMDGPU::S_XNOR_B64:
8357 if (ST.hasDLInsts())
8358 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8360 splitScalar64BitXnor(Worklist, Inst, MDT);
8364 case AMDGPU::S_ANDN2_B64:
8365 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8369 case AMDGPU::S_ORN2_B64:
8370 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8374 case AMDGPU::S_BREV_B64:
8375 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32,
true);
8379 case AMDGPU::S_NOT_B64:
8380 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8384 case AMDGPU::S_BCNT1_I32_B64:
8385 splitScalar64BitBCNT(Worklist, Inst);
8389 case AMDGPU::S_BFE_I64:
8390 splitScalar64BitBFE(Worklist, Inst);
8394 case AMDGPU::S_FLBIT_I32_B64:
8395 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8398 case AMDGPU::S_FF1_I32_B64:
8399 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8403 case AMDGPU::S_LSHL_B32:
8404 if (ST.hasOnlyRevVALUShifts()) {
8405 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8409 case AMDGPU::S_ASHR_I32:
8410 if (ST.hasOnlyRevVALUShifts()) {
8411 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8415 case AMDGPU::S_LSHR_B32:
8416 if (ST.hasOnlyRevVALUShifts()) {
8417 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8421 case AMDGPU::S_LSHL_B64:
8422 if (ST.hasOnlyRevVALUShifts()) {
8424 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8425 : AMDGPU::V_LSHLREV_B64_e64;
8429 case AMDGPU::S_ASHR_I64:
8430 if (ST.hasOnlyRevVALUShifts()) {
8431 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8435 case AMDGPU::S_LSHR_B64:
8436 if (ST.hasOnlyRevVALUShifts()) {
8437 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8442 case AMDGPU::S_ABS_I32:
8443 lowerScalarAbs(Worklist, Inst);
8447 case AMDGPU::S_ABSDIFF_I32:
8448 lowerScalarAbsDiff(Worklist, Inst);
8452 case AMDGPU::S_CBRANCH_SCC0:
8453 case AMDGPU::S_CBRANCH_SCC1: {
8456 bool IsSCC = CondReg == AMDGPU::SCC;
8464 case AMDGPU::S_BFE_U64:
8465 case AMDGPU::S_BFM_B64:
8468 case AMDGPU::S_PACK_LL_B32_B16:
8469 case AMDGPU::S_PACK_LH_B32_B16:
8470 case AMDGPU::S_PACK_HL_B32_B16:
8471 case AMDGPU::S_PACK_HH_B32_B16:
8472 movePackToVALU(Worklist, MRI, Inst);
8476 case AMDGPU::S_XNOR_B32:
8477 lowerScalarXnor(Worklist, Inst);
8481 case AMDGPU::S_NAND_B32:
8482 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8486 case AMDGPU::S_NOR_B32:
8487 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8491 case AMDGPU::S_ANDN2_B32:
8492 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8496 case AMDGPU::S_ORN2_B32:
8497 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8505 case AMDGPU::S_ADD_CO_PSEUDO:
8506 case AMDGPU::S_SUB_CO_PSEUDO: {
8507 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8508 ? AMDGPU::V_ADDC_U32_e64
8509 : AMDGPU::V_SUBB_U32_e64;
8510 const auto *CarryRC = RI.getWaveMaskRegClass();
8532 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8536 case AMDGPU::S_UADDO_PSEUDO:
8537 case AMDGPU::S_USUBO_PSEUDO: {
8543 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8544 ? AMDGPU::V_ADD_CO_U32_e64
8545 : AMDGPU::V_SUB_CO_U32_e64;
8557 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8561 case AMDGPU::S_LSHL1_ADD_U32:
8562 case AMDGPU::S_LSHL2_ADD_U32:
8563 case AMDGPU::S_LSHL3_ADD_U32:
8564 case AMDGPU::S_LSHL4_ADD_U32: {
8568 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8569 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8570 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8584 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8588 case AMDGPU::S_CSELECT_B32:
8589 case AMDGPU::S_CSELECT_B64:
8590 lowerSelect(Worklist, Inst, MDT);
8593 case AMDGPU::S_CMP_EQ_I32:
8594 case AMDGPU::S_CMP_LG_I32:
8595 case AMDGPU::S_CMP_GT_I32:
8596 case AMDGPU::S_CMP_GE_I32:
8597 case AMDGPU::S_CMP_LT_I32:
8598 case AMDGPU::S_CMP_LE_I32:
8599 case AMDGPU::S_CMP_EQ_U32:
8600 case AMDGPU::S_CMP_LG_U32:
8601 case AMDGPU::S_CMP_GT_U32:
8602 case AMDGPU::S_CMP_GE_U32:
8603 case AMDGPU::S_CMP_LT_U32:
8604 case AMDGPU::S_CMP_LE_U32:
8605 case AMDGPU::S_CMP_EQ_U64:
8606 case AMDGPU::S_CMP_LG_U64:
8607 case AMDGPU::S_CMP_LT_F32:
8608 case AMDGPU::S_CMP_EQ_F32:
8609 case AMDGPU::S_CMP_LE_F32:
8610 case AMDGPU::S_CMP_GT_F32:
8611 case AMDGPU::S_CMP_LG_F32:
8612 case AMDGPU::S_CMP_GE_F32:
8613 case AMDGPU::S_CMP_O_F32:
8614 case AMDGPU::S_CMP_U_F32:
8615 case AMDGPU::S_CMP_NGE_F32:
8616 case AMDGPU::S_CMP_NLG_F32:
8617 case AMDGPU::S_CMP_NGT_F32:
8618 case AMDGPU::S_CMP_NLE_F32:
8619 case AMDGPU::S_CMP_NEQ_F32:
8620 case AMDGPU::S_CMP_NLT_F32: {
8625 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8639 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8643 case AMDGPU::S_CMP_LT_F16:
8644 case AMDGPU::S_CMP_EQ_F16:
8645 case AMDGPU::S_CMP_LE_F16:
8646 case AMDGPU::S_CMP_GT_F16:
8647 case AMDGPU::S_CMP_LG_F16:
8648 case AMDGPU::S_CMP_GE_F16:
8649 case AMDGPU::S_CMP_O_F16:
8650 case AMDGPU::S_CMP_U_F16:
8651 case AMDGPU::S_CMP_NGE_F16:
8652 case AMDGPU::S_CMP_NLG_F16:
8653 case AMDGPU::S_CMP_NGT_F16:
8654 case AMDGPU::S_CMP_NLE_F16:
8655 case AMDGPU::S_CMP_NEQ_F16:
8656 case AMDGPU::S_CMP_NLT_F16: {
8678 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8682 case AMDGPU::S_CVT_HI_F32_F16: {
8685 if (ST.useRealTrue16Insts()) {
8690 .
addReg(TmpReg, {}, AMDGPU::hi16)
8706 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8710 case AMDGPU::S_MINIMUM_F32:
8711 case AMDGPU::S_MAXIMUM_F32: {
8723 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8727 case AMDGPU::S_MINIMUM_F16:
8728 case AMDGPU::S_MAXIMUM_F16: {
8730 ? &AMDGPU::VGPR_16RegClass
8731 : &AMDGPU::VGPR_32RegClass);
8742 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8746 case AMDGPU::V_S_EXP_F16_e64:
8747 case AMDGPU::V_S_LOG_F16_e64:
8748 case AMDGPU::V_S_RCP_F16_e64:
8749 case AMDGPU::V_S_RSQ_F16_e64:
8750 case AMDGPU::V_S_SQRT_F16_e64: {
8752 ? &AMDGPU::VGPR_16RegClass
8753 : &AMDGPU::VGPR_32RegClass);
8764 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8770 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8778 if (NewOpcode == Opcode) {
8785 V2SPhyCopiesToErase);
8793 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8800 addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist);
8806 RI.composeSubRegIndices(SrcSubReg, UseMO.getSubReg()));
8807 UseMO.setReg(NewDstReg);
8826 unsigned OpIdx =
UseMI.getOperandNo(&UseMO);
8839 if (ST.useRealTrue16Insts() && Inst.
isCopy() &&
8843 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
8849 get(AMDGPU::REG_SEQUENCE), NewDstReg)
8856 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8858 }
else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
8863 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8871 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8881 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8882 AMDGPU::OpName::src0_modifiers) >= 0)
8886 NewInstr->addOperand(Src);
8889 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
8892 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
8894 NewInstr.addImm(
Size);
8895 }
else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
8899 }
else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
8904 "Scalar BFE is only implemented for constant width and offset");
8912 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8913 AMDGPU::OpName::src1_modifiers) >= 0)
8915 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
8917 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8918 AMDGPU::OpName::src2_modifiers) >= 0)
8920 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
8922 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
8924 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
8926 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
8932 NewInstr->addOperand(
Op);
8938 bool DeadSCCDef =
false;
8940 if (
Op.getReg() == AMDGPU::SCC) {
8946 addSCCDefUsersToVALUWorklist(
Op, Inst, Worklist);
8950 addSCCDefsToVALUWorklist(NewInstr, Worklist);
8955 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
8956 Register DstReg = NewInstr->getOperand(0).getReg();
8970 NewInstr->findRegisterDefOperand(RI.getVCC(), &RI))
8971 VCCDef->setIsDead();
8977 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8981std::pair<bool, MachineBasicBlock *>
8984 if (ST.hasAddNoCarryInsts()) {
8996 assert(
Opc == AMDGPU::S_ADD_I32 ||
Opc == AMDGPU::S_SUB_I32);
8998 unsigned NewOpc =
Opc == AMDGPU::S_ADD_I32 ?
8999 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
9010 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9011 return std::pair(
true, NewBB);
9014 return std::pair(
false,
nullptr);
9031 bool IsSCC = (CondReg == AMDGPU::SCC);
9039 for (MachineOperand &UseMO :
9041 MachineInstr &
UseMI = *UseMO.getParent();
9042 switch (
UseMI.getOpcode()) {
9043 case AMDGPU::V_CNDMASK_B16_fake16_e32:
9044 case AMDGPU::V_CNDMASK_B16_fake16_e64:
9045 case AMDGPU::V_CNDMASK_B16_t16_e32:
9046 case AMDGPU::V_CNDMASK_B16_t16_e64:
9047 case AMDGPU::V_CNDMASK_B32_e32:
9048 case AMDGPU::V_CNDMASK_B32_e64:
9049 case AMDGPU::V_CNDMASK_B64_PSEUDO:
9050 if (UseMO.isImplicit() ||
9052 UseMO.setReg(CondReg);
9066 bool CopyFound =
false;
9067 for (MachineInstr &CandI :
9070 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) !=
9072 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
9074 .
addReg(CandI.getOperand(1).getReg());
9086 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
9095 MachineInstr *NewInst;
9096 if (Inst.
getOpcode() == AMDGPU::S_CSELECT_B32) {
9097 NewInst =
BuildMI(
MBB, MII,
DL,
get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
9112 addUsersToMoveToVALUWorklist(NewDestReg, MRI, Worklist);
9127 bool HasCarryOut = !ST.hasAddNoCarryInsts();
9129 HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
9131 MachineInstrBuilder
Sub =
9141 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9158 bool HasCarryOut = !ST.hasAddNoCarryInsts();
9160 HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
9162 MachineInstrBuilder Sub1 =
BuildMI(
MBB, MII,
DL,
get(SubOp), SubResultReg)
9166 MachineInstrBuilder Sub2 =
9179 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9193 if (ST.hasDLInsts()) {
9203 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9209 bool Src0IsSGPR = Src0.
isReg() &&
9211 bool Src1IsSGPR = Src1.
isReg() &&
9225 }
else if (Src1IsSGPR) {
9243 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9249 unsigned Opcode)
const {
9273 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9278 unsigned Opcode)
const {
9302 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9317 const MCInstrDesc &InstDesc =
get(Opcode);
9320 &AMDGPU::SGPR_32RegClass;
9323 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9326 AMDGPU::sub0, Src0SubRC);
9331 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9334 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0).
add(SrcReg0Sub0);
9337 AMDGPU::sub1, Src0SubRC);
9340 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1).
add(SrcReg0Sub1);
9354 Worklist.
insert(&LoHalf);
9355 Worklist.
insert(&HiHalf);
9361 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9385 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9386 if (RI.isSGPRClass(Src0SubRC))
9387 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9389 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9390 if (RI.isSGPRClass(Src1SubRC))
9391 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9395 MachineOperand Op0L =
9397 MachineOperand Op1L =
9399 MachineOperand Op0H =
9401 MachineOperand Op1H =
9420 MachineInstr *Op1L_Op0H =
9426 MachineInstr *Op1H_Op0L =
9432 MachineInstr *Carry =
9437 MachineInstr *LoHalf =
9447 MachineInstr *HiHalf =
9470 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9494 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9495 if (RI.isSGPRClass(Src0SubRC))
9496 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9498 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9499 if (RI.isSGPRClass(Src1SubRC))
9500 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9504 MachineOperand Op0L =
9506 MachineOperand Op1L =
9510 unsigned NewOpc =
Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9511 ? AMDGPU::V_MUL_HI_U32_e64
9512 : AMDGPU::V_MUL_HI_I32_e64;
9513 MachineInstr *HiHalf =
9516 MachineInstr *LoHalf =
9535 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9551 const MCInstrDesc &InstDesc =
get(Opcode);
9554 &AMDGPU::SGPR_32RegClass;
9557 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9560 &AMDGPU::SGPR_32RegClass;
9563 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9566 AMDGPU::sub0, Src0SubRC);
9568 AMDGPU::sub0, Src1SubRC);
9570 AMDGPU::sub1, Src0SubRC);
9572 AMDGPU::sub1, Src1SubRC);
9577 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9580 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0)
9585 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1)
9598 Worklist.
insert(&LoHalf);
9599 Worklist.
insert(&HiHalf);
9602 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9622 MachineOperand* Op0;
9623 MachineOperand* Op1;
9625 if (Src0.
isReg() && RI.isSGPRReg(MRI, Src0.
getReg())) {
9658 const MCInstrDesc &InstDesc =
get(AMDGPU::V_BCNT_U32_B32_e64);
9661 &AMDGPU::SGPR_32RegClass;
9667 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9670 AMDGPU::sub0, SrcSubRC);
9672 AMDGPU::sub1, SrcSubRC);
9682 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9701 Offset == 0 &&
"Not implemented");
9724 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9734 .
addReg(Src.getReg(), {}, AMDGPU::sub0);
9737 .
addReg(Src.getReg(), {}, AMDGPU::sub0)
9743 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9762 const MCInstrDesc &InstDesc =
get(Opcode);
9764 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9767 Src.isReg() ? MRI.
getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9769 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9771 MachineOperand SrcRegSub0 =
9773 MachineOperand SrcRegSub1 =
9787 .
addReg(IsCtlz ? MidReg1 : MidReg2);
9791 .
addReg(IsCtlz ? MidReg2 : MidReg1);
9795 addUsersToMoveToVALUWorklist(MidReg4, MRI, Worklist);
9798void SIInstrInfo::addUsersToMoveToVALUWorklist(
9802 MachineInstr &
UseMI = *MO.getParent();
9806 switch (
UseMI.getOpcode()) {
9809 case AMDGPU::SOFT_WQM:
9810 case AMDGPU::STRICT_WWM:
9811 case AMDGPU::STRICT_WQM:
9812 case AMDGPU::REG_SEQUENCE:
9814 case AMDGPU::INSERT_SUBREG:
9817 OpNo = MO.getOperandNo();
9824 if (!RI.hasVectorRegisters(OpRC))
9841 if (ST.useRealTrue16Insts()) {
9843 if (!Src0.
isReg() || !RI.isVGPR(MRI, Src0.
getReg())) {
9846 get(Src0.
isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
9852 if (!Src1.
isReg() || !RI.isVGPR(MRI, Src1.
getReg())) {
9855 get(Src1.
isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
9864 auto NewMI =
BuildMI(*
MBB, Inst,
DL,
get(AMDGPU::REG_SEQUENCE), ResultReg);
9866 case AMDGPU::S_PACK_LL_B32_B16:
9868 .addReg(SrcReg0, {},
9869 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9870 .addImm(AMDGPU::lo16)
9871 .addReg(SrcReg1, {},
9872 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9873 .addImm(AMDGPU::hi16);
9875 case AMDGPU::S_PACK_LH_B32_B16:
9877 .addReg(SrcReg0, {},
9878 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9879 .addImm(AMDGPU::lo16)
9880 .addReg(SrcReg1, {}, AMDGPU::hi16)
9881 .addImm(AMDGPU::hi16);
9883 case AMDGPU::S_PACK_HL_B32_B16:
9884 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9885 .addImm(AMDGPU::lo16)
9886 .addReg(SrcReg1, {},
9887 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9888 .addImm(AMDGPU::hi16);
9890 case AMDGPU::S_PACK_HH_B32_B16:
9891 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9892 .addImm(AMDGPU::lo16)
9893 .addReg(SrcReg1, {}, AMDGPU::hi16)
9894 .addImm(AMDGPU::hi16);
9902 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9907 case AMDGPU::S_PACK_LL_B32_B16: {
9926 case AMDGPU::S_PACK_LH_B32_B16: {
9936 case AMDGPU::S_PACK_HL_B32_B16: {
9947 case AMDGPU::S_PACK_HH_B32_B16: {
9967 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9976 assert(
Op.isReg() &&
Op.getReg() == AMDGPU::SCC &&
Op.isDef() &&
9977 !
Op.isDead() &&
Op.getParent() == &SCCDefInst);
9978 SmallVector<MachineInstr *, 4> CopyToDelete;
9981 for (MachineInstr &
MI :
9985 int SCCIdx =
MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI,
false);
9989 Register DestReg =
MI.getOperand(0).getReg();
9996 MI.getOperand(SCCIdx).setReg(NewCond);
10002 if (
MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) != -1)
10005 for (
auto &Copy : CopyToDelete)
10006 Copy->eraseFromParent();
10014void SIInstrInfo::addSCCDefsToVALUWorklist(
MachineInstr *SCCUseInst,
10020 for (MachineInstr &
MI :
10023 if (
MI.modifiesRegister(AMDGPU::VCC, &RI))
10025 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
10042 case AMDGPU::REG_SEQUENCE:
10043 case AMDGPU::INSERT_SUBREG:
10045 case AMDGPU::SOFT_WQM:
10046 case AMDGPU::STRICT_WWM:
10047 case AMDGPU::STRICT_WQM: {
10049 if (RI.isAGPRClass(SrcRC)) {
10050 if (RI.isAGPRClass(NewDstRC))
10055 case AMDGPU::REG_SEQUENCE:
10056 case AMDGPU::INSERT_SUBREG:
10057 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
10060 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10066 if (!RI.isSGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
10069 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10083 int OpIndices[3])
const {
10084 const MCInstrDesc &
Desc =
MI.getDesc();
10102 for (
unsigned i = 0; i < 3; ++i) {
10103 int Idx = OpIndices[i];
10107 const MachineOperand &MO =
MI.getOperand(Idx);
10114 RI.getRegClass(getOpRegClassID(
Desc.operands()[Idx]));
10115 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
10116 if (IsRequiredSGPR)
10122 if (RI.isSGPRClass(RegRC))
10123 UsedSGPRs[i] =
Reg;
10139 if (UsedSGPRs[0]) {
10140 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
10141 SGPRReg = UsedSGPRs[0];
10144 if (!SGPRReg && UsedSGPRs[1]) {
10145 if (UsedSGPRs[1] == UsedSGPRs[2])
10146 SGPRReg = UsedSGPRs[1];
10153 AMDGPU::OpName OperandName)
const {
10154 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
10157 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OperandName);
10161 return &
MI.getOperand(Idx);
10175 if (ST.isAmdHsaOS()) {
10178 RsrcDataFormat |= (1ULL << 56);
10183 RsrcDataFormat |= (2ULL << 59);
10186 return RsrcDataFormat;
10196 uint64_t EltSizeValue =
Log2_32(ST.getMaxPrivateElementSize(
true)) - 1;
10201 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
10208 Rsrc23 &=
~AMDGPU::RSRC_DATA_FORMAT;
10214 unsigned Opc =
MI.getOpcode();
10220 return get(
Opc).mayLoad() &&
10227 if (!Addr || !Addr->
isFI())
10236 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::vdata);
10238 return MI.getOperand(VDataIdx).getReg();
10248 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::data);
10250 return MI.getOperand(DataIdx).getReg();
10271 if (!
MI.mayStore())
10284 unsigned Opc =
MI.getOpcode();
10286 unsigned DescSize =
Desc.getSize();
10291 unsigned Size = DescSize;
10295 if (
MI.isBranch() && ST.hasOffset3fBug())
10306 bool HasLiteral =
false;
10307 unsigned LiteralSize = 4;
10308 for (
int I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I) {
10313 if (ST.has64BitLiterals()) {
10314 switch (OpInfo.OperandType) {
10339 return HasLiteral ? DescSize + LiteralSize : DescSize;
10344 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
10348 int RSrcIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::srsrc);
10349 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10353 case TargetOpcode::BUNDLE:
10354 return getInstBundleSize(
MI);
10355 case TargetOpcode::INLINEASM:
10356 case TargetOpcode::INLINEASM_BR: {
10358 const char *AsmStr =
MI.getOperand(0).getSymbolName();
10362 if (
MI.isMetaInstruction())
10366 const auto *D16Info = AMDGPU::getT16D16Helper(
Opc);
10369 unsigned LoInstOpcode = D16Info->LoOp;
10371 DescSize =
Desc.getSize();
10375 if (
Opc == AMDGPU::V_FMA_MIX_F16_t16 ||
Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10378 DescSize =
Desc.getSize();
10387 if (
MI.isBranch() && ST.hasOffset3fBug())
10388 return InstSizeVerifyMode::NoVerify;
10389 return InstSizeVerifyMode::ExactSize;
10396 if (
MI.memoperands_empty())
10408 static const std::pair<int, const char *> TargetIndices[] = {
10448std::pair<unsigned, unsigned>
10455 static const std::pair<unsigned, const char *> TargetFlags[] = {
10473 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10489 return AMDGPU::WWM_COPY;
10491 return AMDGPU::COPY;
10508 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10512 if (RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg)))
10513 return IsLRSplitInst;
10526 bool IsNullOrVectorRegister =
true;
10530 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg));
10533 return IsNullOrVectorRegister &&
10535 (!
MI.isTerminator() &&
MI.getOpcode() != AMDGPU::COPY &&
10536 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10544 if (ST.hasAddNoCarryInsts())
10560 if (ST.hasAddNoCarryInsts())
10564 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10566 : RS.scavengeRegisterBackwards(
10567 *RI.getBoolRC(),
I,
false,
10580 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10581 case AMDGPU::SI_KILL_I1_TERMINATOR:
10590 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10591 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10592 case AMDGPU::SI_KILL_I1_PSEUDO:
10593 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10605 const unsigned OffsetBits =
10607 return (1 << OffsetBits) - 1;
10611 if (!ST.isWave32())
10614 if (
MI.isInlineAsm())
10617 if (
MI.getNumOperands() <
MI.getDesc().getNumOperands())
10620 for (
auto &
Op :
MI.implicit_operands()) {
10621 if (
Op.isReg() &&
Op.getReg() == AMDGPU::VCC)
10622 Op.setReg(AMDGPU::VCC_LO);
10631 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::sbase);
10635 const int16_t RCID = getOpRegClassID(
MI.getDesc().operands()[Idx]);
10636 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10652 if (
Imm > MaxImm) {
10653 if (
Imm <= MaxImm + 64) {
10655 Overflow =
Imm - MaxImm;
10670 Overflow =
High - Alignment.value();
10674 if (Overflow > 0) {
10682 if (ST.hasRestrictedSOffset())
10687 SOffset = Overflow;
10725 if (!ST.hasFlatInstOffsets())
10729 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10734 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10735 FlatVariant == FlatAddrSpace::FlatScratch &&
Offset < 0 &&
10746std::pair<int64_t, int64_t>
10749 int64_t RemainderOffset = COffsetVal;
10750 int64_t ImmField = 0;
10755 if (AllowNegative) {
10757 int64_t
D = 1LL << NumBits;
10758 RemainderOffset = (COffsetVal /
D) *
D;
10759 ImmField = COffsetVal - RemainderOffset;
10761 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10763 (ImmField % 4) != 0) {
10765 RemainderOffset += ImmField % 4;
10766 ImmField -= ImmField % 4;
10768 }
else if (COffsetVal >= 0) {
10770 RemainderOffset = COffsetVal - ImmField;
10774 assert(RemainderOffset + ImmField == COffsetVal);
10775 return {ImmField, RemainderOffset};
10780 if (ST.hasNegativeScratchOffsetBug() &&
10788 switch (ST.getGeneration()) {
10822 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10823 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10824 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10825 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10826 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10827 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10828 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10829 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10836#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10837 case OPCODE##_dpp: \
10838 case OPCODE##_e32: \
10839 case OPCODE##_e64: \
10840 case OPCODE##_e64_dpp: \
10841 case OPCODE##_sdwa:
10855 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
10856 case AMDGPU::V_DIV_FIXUP_F16_gfx9_fake16_e64:
10857 case AMDGPU::V_FMA_F16_gfx9_e64:
10858 case AMDGPU::V_FMA_F16_gfx9_fake16_e64:
10859 case AMDGPU::V_INTERP_P2_F16:
10860 case AMDGPU::V_MAD_F16_e64:
10861 case AMDGPU::V_MAD_U16_e64:
10862 case AMDGPU::V_MAD_I16_e64:
10871 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
10879 switch (ST.getGeneration()) {
10892 if (
isMAI(Opcode)) {
10906 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
10909 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
10916 if (ST.hasGFX90AInsts()) {
10917 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
10918 if (ST.hasGFX940Insts())
10920 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10922 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10924 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
10930 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
10949 for (
unsigned I = 0, E = (
MI.getNumOperands() - 1)/ 2;
I < E; ++
I)
10950 if (
MI.getOperand(1 + 2 *
I + 1).getImm() == SubReg) {
10951 auto &RegOp =
MI.getOperand(1 + 2 *
I);
10963 switch (
MI.getOpcode()) {
10965 case AMDGPU::REG_SEQUENCE:
10969 case AMDGPU::INSERT_SUBREG:
10970 if (RSR.
SubReg == (
unsigned)
MI.getOperand(3).getImm())
10987 if (!
P.Reg.isVirtual())
10992 while (
auto *
MI = DefInst) {
10994 switch (
MI->getOpcode()) {
10996 case AMDGPU::V_MOV_B32_e32: {
10997 auto &Op1 =
MI->getOperand(1);
11026 auto *DefBB =
DefMI.getParent();
11030 if (
UseMI.getParent() != DefBB)
11033 const int MaxInstScan = 20;
11037 auto E =
UseMI.getIterator();
11038 for (
auto I = std::next(
DefMI.getIterator());
I != E; ++
I) {
11039 if (
I->isDebugInstr())
11042 if (++NumInst > MaxInstScan)
11045 if (
I->modifiesRegister(AMDGPU::EXEC,
TRI))
11058 auto *DefBB =
DefMI.getParent();
11060 const int MaxUseScan = 10;
11064 auto &UseInst = *
Use.getParent();
11067 if (UseInst.getParent() != DefBB || UseInst.isPHI())
11070 if (++NumUse > MaxUseScan)
11077 const int MaxInstScan = 20;
11081 for (
auto I = std::next(
DefMI.getIterator()); ; ++
I) {
11084 if (
I->isDebugInstr())
11087 if (++NumInst > MaxInstScan)
11100 if (Reg == VReg && --NumUse == 0)
11102 }
else if (
TRI->regsOverlap(Reg, AMDGPU::EXEC))
11111 auto Cur =
MBB.begin();
11112 if (Cur !=
MBB.end())
11114 if (!Cur->isPHI() && Cur->readsRegister(Dst,
nullptr))
11117 }
while (Cur !=
MBB.end() && Cur != LastPHIIt);
11126 if (InsPt !=
MBB.end() &&
11127 (InsPt->getOpcode() == AMDGPU::SI_IF ||
11128 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
11129 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
11130 InsPt->definesRegister(Src,
nullptr)) {
11134 .
addReg(Src, {}, SrcSubReg)
11177 if (isFullCopyInstr(
MI)) {
11178 Register DstReg =
MI.getOperand(0).getReg();
11179 Register SrcReg =
MI.getOperand(1).getReg();
11201 unsigned *PredCost)
const {
11202 if (
MI.isBundle()) {
11205 unsigned Lat = 0,
Count = 0;
11206 for (++
I;
I != E &&
I->isBundledWithPred(); ++
I) {
11208 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*
I));
11210 return Lat +
Count - 1;
11213 return SchedModel.computeInstrLatency(&
MI);
11217 if (!ST.hasGFX1250VALUBlockingCycles())
11221 if (
const auto *Entry = AMDGPU::getGFX1250BlockingCyclesInfo(
MI.getOpcode()))
11222 return Entry->GFX1250BlockingCycles;
11231 return *CallAddrOp;
11238 unsigned Opcode =
MI.getOpcode();
11240 auto HandleAddrSpaceCast = [
this, &MRI](
const MachineInstr &
MI) {
11246 unsigned SrcAS = SrcTy.getAddressSpace();
11249 ST.hasGloballyAddressableScratch()
11257 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
11258 return HandleAddrSpaceCast(
MI);
11261 auto IID = GI->getIntrinsicID();
11268 case Intrinsic::amdgcn_if:
11269 case Intrinsic::amdgcn_else:
11283 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11284 Opcode == AMDGPU::G_SEXTLOAD) {
11285 if (
MI.memoperands_empty())
11289 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11290 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11298 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11299 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11300 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11306 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11309 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11317 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11318 return Formatter.get();
11326 unsigned opcode =
MI.getOpcode();
11327 if (opcode == AMDGPU::V_READLANE_B32 ||
11328 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11329 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11334 if (
MI.isInlineAsm()) {
11340 if (!RC || !RI.isSGPRClass(RC))
11345 if (isCopyInstr(
MI)) {
11349 RI.getPhysRegBaseClass(srcOp.
getReg());
11357 if (
MI.isPreISelOpcode())
11372 if (
MI.memoperands_empty())
11376 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11377 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11392 for (
unsigned I = 0, E =
MI.getNumOperands();
I != E; ++
I) {
11394 if (!
SrcOp.isReg())
11398 if (!Reg || !
SrcOp.readsReg())
11404 if (RegBank && RegBank->
getID() != AMDGPU::SGPRRegBankID)
11431 F,
"ds_ordered_count unsupported for this calling conv"));
11445 Register &SrcReg2, int64_t &CmpMask,
11446 int64_t &CmpValue)
const {
11447 if (!
MI.getOperand(0).isReg() ||
MI.getOperand(0).getSubReg())
11450 switch (
MI.getOpcode()) {
11453 case AMDGPU::S_CMP_EQ_U32:
11454 case AMDGPU::S_CMP_EQ_I32:
11455 case AMDGPU::S_CMP_LG_U32:
11456 case AMDGPU::S_CMP_LG_I32:
11457 case AMDGPU::S_CMP_LT_U32:
11458 case AMDGPU::S_CMP_LT_I32:
11459 case AMDGPU::S_CMP_GT_U32:
11460 case AMDGPU::S_CMP_GT_I32:
11461 case AMDGPU::S_CMP_LE_U32:
11462 case AMDGPU::S_CMP_LE_I32:
11463 case AMDGPU::S_CMP_GE_U32:
11464 case AMDGPU::S_CMP_GE_I32:
11465 case AMDGPU::S_CMP_EQ_U64:
11466 case AMDGPU::S_CMP_LG_U64:
11467 SrcReg =
MI.getOperand(0).getReg();
11468 if (
MI.getOperand(1).isReg()) {
11469 if (
MI.getOperand(1).getSubReg())
11471 SrcReg2 =
MI.getOperand(1).getReg();
11473 }
else if (
MI.getOperand(1).isImm()) {
11475 CmpValue =
MI.getOperand(1).getImm();
11481 case AMDGPU::S_CMPK_EQ_U32:
11482 case AMDGPU::S_CMPK_EQ_I32:
11483 case AMDGPU::S_CMPK_LG_U32:
11484 case AMDGPU::S_CMPK_LG_I32:
11485 case AMDGPU::S_CMPK_LT_U32:
11486 case AMDGPU::S_CMPK_LT_I32:
11487 case AMDGPU::S_CMPK_GT_U32:
11488 case AMDGPU::S_CMPK_GT_I32:
11489 case AMDGPU::S_CMPK_LE_U32:
11490 case AMDGPU::S_CMPK_LE_I32:
11491 case AMDGPU::S_CMPK_GE_U32:
11492 case AMDGPU::S_CMPK_GE_I32:
11493 SrcReg =
MI.getOperand(0).getReg();
11495 CmpValue =
MI.getOperand(1).getImm();
11505 if (S->isLiveIn(AMDGPU::SCC))
11514bool SIInstrInfo::invertSCCUse(
MachineInstr *SCCDef)
const {
11517 bool SCCIsDead =
false;
11520 constexpr unsigned ScanLimit = 12;
11521 unsigned Count = 0;
11522 for (MachineInstr &
MI :
11524 if (++
Count > ScanLimit)
11526 if (
MI.readsRegister(AMDGPU::SCC, &RI)) {
11527 if (
MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11528 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11529 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11530 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11535 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
11548 for (MachineInstr *
MI : InvertInstr) {
11549 if (
MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11550 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11552 }
else if (
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11553 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11554 MI->setDesc(
get(
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11555 ? AMDGPU::S_CBRANCH_SCC1
11556 : AMDGPU::S_CBRANCH_SCC0));
11569 bool NeedInversion)
const {
11570 MachineInstr *KillsSCC =
nullptr;
11575 if (
MI.modifiesRegister(AMDGPU::SCC, &RI))
11577 if (
MI.killsRegister(AMDGPU::SCC, &RI))
11580 if (NeedInversion && !invertSCCUse(SCCRedefine))
11582 if (MachineOperand *SccDef =
11584 SccDef->setIsDead(
false);
11592 if (Def.getOpcode() != AMDGPU::S_CSELECT_B32 &&
11593 Def.getOpcode() != AMDGPU::S_CSELECT_B64)
11595 bool Op1IsNonZeroImm =
11596 Def.getOperand(1).isImm() && Def.getOperand(1).getImm() != 0;
11597 bool Op2IsZeroImm =
11598 Def.getOperand(2).isImm() && Def.getOperand(2).getImm() == 0;
11599 return Op1IsNonZeroImm && Op2IsZeroImm;
11603 unsigned &NewDefOpc) {
11606 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11607 Def.getOpcode() != AMDGPU::S_ADD_U32)
11613 Def.getMF()->getSubtarget().getInstrInfo());
11615 auto Imm1 =
TII->getImmOrMaterializedImm(MRI, AddSrc1);
11616 auto Imm2 =
TII->getImmOrMaterializedImm(MRI, AddSrc2);
11617 if ((!Imm1 || *Imm1 != 1) && (!Imm2 || *Imm2 != 1))
11620 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11622 Def.findRegisterDefOperand(AMDGPU::SCC,
nullptr);
11625 NewDefOpc = AMDGPU::S_ADD_U32;
11627 NeedInversion = !NeedInversion;
11632 Register SrcReg2, int64_t CmpMask,
11642 CmpValue = *ImmOpt;
11645 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue, MRI,
11646 this](
bool NeedInversion) ->
bool {
11670 unsigned NewDefOpc = Def->getOpcode();
11676 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11679 if (NewDefOpc != Def->getOpcode())
11680 Def->setDesc(
get(NewDefOpc));
11689 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11696 if (Def1 && Def1->
getOpcode() == AMDGPU::COPY && Def2 &&
11704 optimizeSCC(
Select, Def,
false);
11711 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue, MRI,
11712 this](int64_t ExpectedValue,
unsigned SrcSize,
11713 bool IsReversible,
bool IsSigned) ->
bool {
11741 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11742 Def->getOpcode() != AMDGPU::S_AND_B64)
11746 const auto isMask = [&Mask, SrcSize, MRI,
11758 SrcOp = &Def->getOperand(2);
11759 else if (isMask(&Def->getOperand(2)))
11760 SrcOp = &Def->getOperand(1);
11768 if (IsSigned && BitNo == SrcSize - 1)
11771 ExpectedValue <<= BitNo;
11773 bool IsReversedCC =
false;
11774 if (CmpValue != ExpectedValue) {
11777 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11782 Register DefReg = Def->getOperand(0).getReg();
11783 if (IsReversedCC && !MRI->hasOneNonDBGUse(DefReg))
11786 if (!optimizeSCC(Def, &CmpInstr,
false))
11789 if (!MRI->use_nodbg_empty(DefReg)) {
11797 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11798 : AMDGPU::S_BITCMP1_B32
11799 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11800 : AMDGPU::S_BITCMP1_B64;
11805 Def->eraseFromParent();
11813 case AMDGPU::S_CMP_EQ_U32:
11814 case AMDGPU::S_CMP_EQ_I32:
11815 case AMDGPU::S_CMPK_EQ_U32:
11816 case AMDGPU::S_CMPK_EQ_I32:
11817 return optimizeCmpAnd(1, 32,
true,
false) ||
11818 optimizeCmpSelect(
true);
11819 case AMDGPU::S_CMP_GE_U32:
11820 case AMDGPU::S_CMPK_GE_U32:
11821 return optimizeCmpAnd(1, 32,
false,
false);
11822 case AMDGPU::S_CMP_GE_I32:
11823 case AMDGPU::S_CMPK_GE_I32:
11824 return optimizeCmpAnd(1, 32,
false,
true);
11825 case AMDGPU::S_CMP_EQ_U64:
11826 return optimizeCmpAnd(1, 64,
true,
false);
11827 case AMDGPU::S_CMP_LG_U32:
11828 case AMDGPU::S_CMP_LG_I32:
11829 case AMDGPU::S_CMPK_LG_U32:
11830 case AMDGPU::S_CMPK_LG_I32:
11831 return optimizeCmpAnd(0, 32,
true,
false) ||
11832 optimizeCmpSelect(
false);
11833 case AMDGPU::S_CMP_GT_U32:
11834 case AMDGPU::S_CMPK_GT_U32:
11835 return optimizeCmpAnd(0, 32,
false,
false);
11836 case AMDGPU::S_CMP_GT_I32:
11837 case AMDGPU::S_CMPK_GT_I32:
11838 return optimizeCmpAnd(0, 32,
false,
true);
11839 case AMDGPU::S_CMP_LG_U64:
11840 return optimizeCmpAnd(0, 64,
true,
false) ||
11841 optimizeCmpSelect(
false);
11848 AMDGPU::OpName
OpName)
const {
11849 if (!ST.needsAlignedVGPRs())
11852 int OpNo = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
OpName);
11864 bool IsAGPR = RI.isAGPR(MRI, DataReg);
11866 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
11870 : &AMDGPU::VReg_64_Align2RegClass);
11872 .
addReg(DataReg, {},
Op.getSubReg())
11877 Op.setSubReg(AMDGPU::sub0);
11882 if (!SchedModel.hasInstrSchedModel())
11888 unsigned RepeatRate = 0;
11890 PI = SchedModel.getWriteProcResBegin(SCDesc),
11891 PE = SchedModel.getWriteProcResEnd(SCDesc);
11893 RepeatRate = std::max(RepeatRate, (
unsigned)PI->ReleaseAtCycle);
11910 if (ST.hasGFX1250Insts())
11917 unsigned Opcode =
MI.getOpcode();
11923 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
11924 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
11927 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 & setOperandDead(unsigned OpIdx) const
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.