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#include "AMDGPUGenSearchableTables.inc"
58 cl::desc(
"Restrict range of branch instructions (DEBUG)"));
61 "amdgpu-fix-16-bit-physreg-copies",
62 cl::desc(
"Fix copies between 32 and 16 bit registers by extending to 32 bit"),
78 unsigned N =
Node->getNumOperands();
79 while (
N &&
Node->getOperand(
N - 1).getValueType() == MVT::Glue)
91 int Op0Idx = AMDGPU::getNamedOperandIdx(Opc0,
OpName);
92 int Op1Idx = AMDGPU::getNamedOperandIdx(Opc1,
OpName);
94 if (Op0Idx == -1 && Op1Idx == -1)
98 if ((Op0Idx == -1 && Op1Idx != -1) ||
99 (Op1Idx == -1 && Op0Idx != -1))
120 return !
MI.memoperands_empty() &&
122 return MMO->isLoad() && MMO->isInvariant();
131static std::tuple<unsigned, unsigned, unsigned>
139 unsigned LoReloc, HiReloc;
169 return {BaseFlags, LoReloc, HiReloc};
187 if (!
MI.hasImplicitDef() &&
188 MI.getNumImplicitOperands() ==
MI.getDesc().implicit_uses().size() &&
189 !
MI.mayRaiseFPException())
198 if (!
MI.getNumOperands() || !
MI.getOperand(0).isReg())
213 if (
MI.isNotDuplicable() ||
MI.mayStore() ||
MI.mayRaiseFPException() ||
214 MI.hasUnmodeledSideEffects())
219 if (
MI.isInlineAsm())
223 if (
MI.mayLoad() && !
MI.isDereferenceableInvariantLoad())
238 if (Reg.isPhysical()) {
254 if (MO.isDef() && Reg != DefReg)
262bool SIInstrInfo::resultDependsOnExec(
const MachineInstr &
MI)
const {
266 if (
MI.isConvergent())
294 if (
MI.getOpcode() == AMDGPU::SI_IF_BREAK)
299 for (
auto Op :
MI.uses()) {
300 if (
Op.isReg() &&
Op.getReg().isVirtual() &&
314 while (FromCycle && !(ToCycle && CI->
contains(FromCycle, ToCycle))) {
334 int64_t &Offset1)
const {
342 if (!
get(Opc0).mayLoad() || !
get(Opc1).mayLoad())
346 if (!
get(Opc0).getNumDefs() || !
get(Opc1).getNumDefs())
362 int Offset0Idx = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
363 int Offset1Idx = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
364 if (Offset0Idx == -1 || Offset1Idx == -1)
371 Offset0Idx -=
get(Opc0).NumDefs;
372 Offset1Idx -=
get(Opc1).NumDefs;
402 if (!Load0Offset || !Load1Offset)
419 int OffIdx0 = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
420 int OffIdx1 = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
422 if (OffIdx0 == -1 || OffIdx1 == -1)
428 OffIdx0 -=
get(Opc0).NumDefs;
429 OffIdx1 -=
get(Opc1).NumDefs;
448 case AMDGPU::DS_READ2ST64_B32:
449 case AMDGPU::DS_READ2ST64_B64:
450 case AMDGPU::DS_WRITE2ST64_B32:
451 case AMDGPU::DS_WRITE2ST64_B64:
466 OffsetIsScalable =
false;
483 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
485 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
486 if (
Opc == AMDGPU::DS_ATOMIC_ASYNC_BARRIER_ARRIVE_B64)
499 unsigned Offset0 = Offset0Op->
getImm() & 0xff;
500 unsigned Offset1 = Offset1Op->
getImm() & 0xff;
501 if (Offset0 + 1 != Offset1)
512 int Data0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
520 Offset = EltSize * Offset0;
522 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
523 if (DataOpIdx == -1) {
524 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
526 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
542 if (BaseOp && !BaseOp->
isFI())
550 if (SOffset->
isReg())
556 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
558 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
567 isMIMG(LdSt) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
568 int SRsrcIdx = AMDGPU::getNamedOperandIdx(
Opc, RsrcOpName);
570 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
571 if (VAddr0Idx >= 0) {
573 for (
int I = VAddr0Idx;
I < SRsrcIdx; ++
I)
580 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
595 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::sdst);
612 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
614 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
631 if (BaseOps1.
front()->isIdenticalTo(*BaseOps2.
front()))
639 if (MO1->getAddrSpace() != MO2->getAddrSpace())
642 const auto *Base1 = MO1->getValue();
643 const auto *Base2 = MO2->getValue();
644 if (!Base1 || !Base2)
652 return Base1 == Base2;
656 int64_t Offset1,
bool OffsetIsScalable1,
658 int64_t Offset2,
bool OffsetIsScalable2,
659 unsigned ClusterSize,
660 unsigned NumBytes)
const {
673 }
else if (!BaseOps1.
empty() || !BaseOps2.
empty()) {
692 const unsigned LoadSize = NumBytes / ClusterSize;
693 const unsigned NumDWords = ((LoadSize + 3) / 4) * ClusterSize;
694 return NumDWords <= MaxMemoryClusterDWords;
708 int64_t Offset0, int64_t Offset1,
709 unsigned NumLoads)
const {
710 assert(Offset1 > Offset0 &&
711 "Second offset should be larger than first offset!");
716 return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
723 const char *
Msg =
"illegal VGPR to SGPR copy") {
742 assert((
TII.getSubtarget().hasMAIInsts() &&
743 !
TII.getSubtarget().hasGFX90AInsts()) &&
744 "Expected GFX908 subtarget.");
747 AMDGPU::AGPR_32RegClass.
contains(SrcReg)) &&
748 "Source register of the copy should be either an SGPR or an AGPR.");
751 "Destination register of the copy should be an AGPR.");
760 for (
auto Def =
MI,
E =
MBB.begin(); Def !=
E; ) {
763 if (!Def->modifiesRegister(SrcReg, &RI))
766 if (Def->getOpcode() != AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
767 Def->getOperand(0).getReg() != SrcReg)
774 bool SafeToPropagate =
true;
777 for (
auto I = Def;
I !=
MI && SafeToPropagate; ++
I)
778 if (
I->modifiesRegister(DefOp.
getReg(), &RI))
779 SafeToPropagate =
false;
781 if (!SafeToPropagate)
784 for (
auto I = Def;
I !=
MI; ++
I)
785 I->clearRegisterKills(DefOp.
getReg(), &RI);
793 if (ImpUseSuperReg) {
794 Builder.addReg(ImpUseSuperReg,
802 RS.enterBasicBlockEnd(
MBB);
803 RS.backward(std::next(
MI));
812 unsigned RegNo = (DestReg - AMDGPU::AGPR0) % 3;
815 assert(
MBB.getParent()->getRegInfo().isReserved(Tmp) &&
816 "VGPR used for an intermediate copy should have been reserved.");
821 Register Tmp2 = RS.scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass,
MI,
831 unsigned TmpCopyOp = AMDGPU::V_MOV_B32_e32;
832 if (AMDGPU::AGPR_32RegClass.
contains(SrcReg)) {
833 TmpCopyOp = AMDGPU::V_ACCVGPR_READ_B32_e64;
840 if (ImpUseSuperReg) {
841 UseBuilder.
addReg(ImpUseSuperReg,
858 for (
unsigned Idx = 0; Idx < BaseIndices.
size(); ++Idx) {
859 int16_t SubIdx = BaseIndices[Idx];
860 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
861 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
862 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
863 unsigned Opcode = AMDGPU::S_MOV_B32;
866 bool AlignedDest = ((DestSubReg - AMDGPU::SGPR0) % 2) == 0;
867 bool AlignedSrc = ((SrcSubReg - AMDGPU::SGPR0) % 2) == 0;
868 if (AlignedDest && AlignedSrc && (Idx + 1 < BaseIndices.
size())) {
872 DestSubReg = RI.getSubReg(DestReg, SubIdx);
873 SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
874 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
875 Opcode = AMDGPU::S_MOV_B64;
890 assert(FirstMI && LastMI);
895 LastMI->addRegisterKilled(SrcReg, &RI);
901 Register SrcReg,
bool KillSrc,
bool RenamableDest,
902 bool RenamableSrc)
const {
904 unsigned Size = RI.getRegSizeInBits(*RC);
906 unsigned SrcSize = RI.getRegSizeInBits(*SrcRC);
912 if (((
Size == 16) != (SrcSize == 16))) {
914 assert(ST.useRealTrue16Insts());
916 MCRegister SubReg = RI.getSubReg(RegToFix, AMDGPU::lo16);
919 if (DestReg == SrcReg) {
925 RC = RI.getPhysRegBaseClass(DestReg);
926 Size = RI.getRegSizeInBits(*RC);
927 SrcRC = RI.getPhysRegBaseClass(SrcReg);
928 SrcSize = RI.getRegSizeInBits(*SrcRC);
932 if (RC == &AMDGPU::VGPR_32RegClass) {
934 AMDGPU::SReg_32RegClass.
contains(SrcReg) ||
935 AMDGPU::AGPR_32RegClass.
contains(SrcReg));
936 unsigned Opc = AMDGPU::AGPR_32RegClass.contains(SrcReg) ?
937 AMDGPU::V_ACCVGPR_READ_B32_e64 : AMDGPU::V_MOV_B32_e32;
943 if (RC == &AMDGPU::SReg_32_XM0RegClass ||
944 RC == &AMDGPU::SReg_32RegClass) {
945 if (SrcReg == AMDGPU::SCC) {
952 if (!AMDGPU::SReg_32RegClass.
contains(SrcReg)) {
953 if (DestReg == AMDGPU::VCC_LO) {
971 if (RC == &AMDGPU::SReg_64RegClass) {
972 if (SrcReg == AMDGPU::SCC) {
979 if (!AMDGPU::SReg_64_EncodableRegClass.
contains(SrcReg)) {
980 if (DestReg == AMDGPU::VCC) {
998 if (DestReg == AMDGPU::SCC) {
1001 if (AMDGPU::SReg_64RegClass.
contains(SrcReg)) {
1005 assert(ST.hasScalarCompareEq64());
1019 if (RC == &AMDGPU::AGPR_32RegClass) {
1020 if (AMDGPU::VGPR_32RegClass.
contains(SrcReg) ||
1021 (ST.hasGFX90AInsts() && AMDGPU::SReg_32RegClass.contains(SrcReg))) {
1027 if (AMDGPU::AGPR_32RegClass.
contains(SrcReg) && ST.hasGFX90AInsts()) {
1036 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1043 AMDGPU::SReg_LO16RegClass.
contains(SrcReg) ||
1044 AMDGPU::AGPR_LO16RegClass.
contains(SrcReg));
1046 bool IsSGPRDst = AMDGPU::SReg_LO16RegClass.contains(DestReg);
1047 bool IsSGPRSrc = AMDGPU::SReg_LO16RegClass.contains(SrcReg);
1048 bool IsAGPRDst = AMDGPU::AGPR_LO16RegClass.contains(DestReg);
1049 bool IsAGPRSrc = AMDGPU::AGPR_LO16RegClass.contains(SrcReg);
1052 MCRegister NewDestReg = RI.get32BitRegister(DestReg);
1053 MCRegister NewSrcReg = RI.get32BitRegister(SrcReg);
1066 if (IsAGPRDst || IsAGPRSrc) {
1067 if (!DstLow || !SrcLow) {
1069 "Cannot use hi16 subreg with an AGPR!");
1076 if (ST.useRealTrue16Insts()) {
1082 if (AMDGPU::VGPR_16_Lo128RegClass.
contains(DestReg) &&
1083 (IsSGPRSrc || AMDGPU::VGPR_16_Lo128RegClass.
contains(SrcReg))) {
1095 if (IsSGPRSrc && !ST.hasSDWAScalar()) {
1096 if (!DstLow || !SrcLow) {
1098 "Cannot use hi16 subreg on VI!");
1121 if (RC == RI.getVGPR64Class() && (SrcRC == RC || RI.isSGPRClass(SrcRC))) {
1122 if (ST.hasVMovB64Inst()) {
1127 if (ST.hasPkMovB32()) {
1143 const bool Forward = RI.getHWRegIndex(DestReg) <= RI.getHWRegIndex(SrcReg);
1144 if (RI.isSGPRClass(RC)) {
1145 if (!RI.isSGPRClass(SrcRC)) {
1149 const bool CanKillSuperReg = KillSrc && !RI.regsOverlap(SrcReg, DestReg);
1155 unsigned Opcode = AMDGPU::V_MOV_B32_e32;
1156 unsigned WideOpcode = AMDGPU::INSTRUCTION_LIST_END;
1157 if (RI.isAGPRClass(RC)) {
1158 if (ST.hasGFX90AInsts() && RI.isAGPRClass(SrcRC))
1159 Opcode = AMDGPU::V_ACCVGPR_MOV_B32;
1160 else if (RI.hasVGPRs(SrcRC) ||
1161 (ST.hasGFX90AInsts() && RI.isSGPRClass(SrcRC)))
1162 Opcode = AMDGPU::V_ACCVGPR_WRITE_B32_e64;
1164 Opcode = AMDGPU::INSTRUCTION_LIST_END;
1165 }
else if (RI.hasVGPRs(RC) && RI.isAGPRClass(SrcRC)) {
1166 Opcode = AMDGPU::V_ACCVGPR_READ_B32_e64;
1167 }
else if (RI.isVGPRClass(RC)) {
1168 if (ST.hasVMovB64Inst())
1169 WideOpcode = AMDGPU::V_MOV_B64_e32;
1170 else if (ST.hasPkMovB32())
1171 WideOpcode = AMDGPU::V_PK_MOV_B32;
1175 if (WideOpcode != AMDGPU::INSTRUCTION_LIST_END) {
1176 unsigned SrcOp = WideOpcode == AMDGPU::V_PK_MOV_B32 ? 2 : 1;
1182 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1183 const bool CanKillSuperReg = KillSrc && !Overlap;
1190 std::unique_ptr<RegScavenger> RS;
1191 if (Opcode == AMDGPU::INSTRUCTION_LIST_END)
1192 RS = std::make_unique<RegScavenger>();
1196 for (
unsigned Idx{}; Idx < SubIndices.
size();) {
1197 unsigned NumRegs = 1;
1198 unsigned ThisOpcode = Opcode;
1200 Forward ? SubIndices[Idx] : SubIndices[SubIndices.
size() - Idx - 1];
1202 if (WideRC && Idx + 1 < SubIndices.
size()) {
1203 unsigned Channel = RI.getChannelFromSubReg(SubIdx);
1207 unsigned WideSubIdx = RI.getSubRegFromChannel(Channel, 2);
1208 Register WideDst = RI.getSubReg(DestReg, WideSubIdx);
1209 Register WideSrc = RI.getSubReg(SrcReg, WideSubIdx);
1211 if (WideDst && WideSrc && WideRC->
contains(WideDst) &&
1213 SubIdx = WideSubIdx;
1215 ThisOpcode = WideOpcode;
1219 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
1220 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
1221 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
1224 bool UseKill = CanKillSuperReg && Idx == SubIndices.
size();
1226 if (ThisOpcode == AMDGPU::INSTRUCTION_LIST_END) {
1229 *RS, Overlap, ImpUseSuper);
1230 }
else if (ThisOpcode == AMDGPU::V_PK_MOV_B32) {
1271 int64_t &ImmVal)
const {
1272 switch (
MI.getOpcode()) {
1273 case AMDGPU::V_MOV_B32_e32:
1274 case AMDGPU::S_MOV_B32:
1275 case AMDGPU::S_MOVK_I32:
1276 case AMDGPU::S_MOV_B64:
1277 case AMDGPU::V_MOV_B64_e32:
1278 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
1279 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
1280 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
1281 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
1282 case AMDGPU::V_MOV_B64_PSEUDO:
1283 case AMDGPU::V_MOV_B16_t16_e32: {
1287 return MI.getOperand(0).getReg() == Reg;
1292 case AMDGPU::V_MOV_B16_t16_e64: {
1294 if (Src0.
isImm() && !
MI.getOperand(1).getImm()) {
1296 return MI.getOperand(0).getReg() == Reg;
1301 case AMDGPU::S_BREV_B32:
1302 case AMDGPU::V_BFREV_B32_e32:
1303 case AMDGPU::V_BFREV_B32_e64: {
1307 return MI.getOperand(0).getReg() == Reg;
1312 case AMDGPU::S_NOT_B32:
1313 case AMDGPU::V_NOT_B32_e32:
1314 case AMDGPU::V_NOT_B32_e64: {
1317 ImmVal =
static_cast<int64_t
>(~static_cast<int32_t>(Src0.
getImm()));
1318 return MI.getOperand(0).getReg() == Reg;
1328std::optional<int64_t>
1338 if (!
Op.isReg() || !
Op.getReg().isVirtual())
1339 return std::nullopt;
1341 if (Def && Def->isMoveImmediate()) {
1343 if (ImmSrc.
isImm()) {
1350 return std::nullopt;
1353std::optional<int64_t>
1362 if (RI.isAGPRClass(DstRC))
1363 return AMDGPU::COPY;
1364 if (RI.getRegSizeInBits(*DstRC) == 16) {
1367 return RI.isSGPRClass(DstRC) ? AMDGPU::COPY : AMDGPU::V_MOV_B16_t16_e64;
1369 if (RI.getRegSizeInBits(*DstRC) == 32)
1370 return RI.isSGPRClass(DstRC) ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1371 if (RI.getRegSizeInBits(*DstRC) == 64 && RI.isSGPRClass(DstRC))
1372 return AMDGPU::S_MOV_B64;
1373 if (RI.getRegSizeInBits(*DstRC) == 64 && !RI.isSGPRClass(DstRC))
1374 return AMDGPU::V_MOV_B64_PSEUDO;
1375 return AMDGPU::COPY;
1380 bool IsIndirectSrc)
const {
1381 if (IsIndirectSrc) {
1383 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1);
1385 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2);
1387 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3);
1389 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4);
1391 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5);
1393 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6);
1395 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7);
1397 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8);
1399 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9);
1401 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10);
1403 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11);
1405 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12);
1407 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16);
1408 if (VecSize <= 1024)
1409 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32);
1415 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1);
1417 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2);
1419 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3);
1421 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4);
1423 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5);
1425 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6);
1427 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7);
1429 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8);
1431 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9);
1433 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10);
1435 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11);
1437 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12);
1439 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16);
1440 if (VecSize <= 1024)
1441 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32);
1448 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1450 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1452 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1454 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1456 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1458 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1460 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1462 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1464 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1466 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1468 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1470 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1472 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1473 if (VecSize <= 1024)
1474 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1481 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1483 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1485 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1487 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1489 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1491 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1493 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1495 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1497 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1499 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1501 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1503 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1505 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1506 if (VecSize <= 1024)
1507 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1514 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1;
1516 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2;
1518 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4;
1520 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8;
1521 if (VecSize <= 1024)
1522 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16;
1529 bool IsSGPR)
const {
1541 assert(EltSize == 32 &&
"invalid reg indexing elt size");
1548 return NeedsCFI ? AMDGPU::SI_SPILL_S32_CFI_SAVE : AMDGPU::SI_SPILL_S32_SAVE;
1550 return NeedsCFI ? AMDGPU::SI_SPILL_S64_CFI_SAVE : AMDGPU::SI_SPILL_S64_SAVE;
1552 return NeedsCFI ? AMDGPU::SI_SPILL_S96_CFI_SAVE : AMDGPU::SI_SPILL_S96_SAVE;
1554 return NeedsCFI ? AMDGPU::SI_SPILL_S128_CFI_SAVE
1555 : AMDGPU::SI_SPILL_S128_SAVE;
1557 return NeedsCFI ? AMDGPU::SI_SPILL_S160_CFI_SAVE
1558 : AMDGPU::SI_SPILL_S160_SAVE;
1560 return NeedsCFI ? AMDGPU::SI_SPILL_S192_CFI_SAVE
1561 : AMDGPU::SI_SPILL_S192_SAVE;
1563 return NeedsCFI ? AMDGPU::SI_SPILL_S224_CFI_SAVE
1564 : AMDGPU::SI_SPILL_S224_SAVE;
1566 return AMDGPU::SI_SPILL_S256_SAVE;
1568 return AMDGPU::SI_SPILL_S288_SAVE;
1570 return AMDGPU::SI_SPILL_S320_SAVE;
1572 return AMDGPU::SI_SPILL_S352_SAVE;
1574 return AMDGPU::SI_SPILL_S384_SAVE;
1576 return NeedsCFI ? AMDGPU::SI_SPILL_S512_CFI_SAVE
1577 : AMDGPU::SI_SPILL_S512_SAVE;
1579 return NeedsCFI ? AMDGPU::SI_SPILL_S1024_CFI_SAVE
1580 : AMDGPU::SI_SPILL_S1024_SAVE;
1589 return AMDGPU::SI_SPILL_V16_SAVE;
1591 return NeedsCFI ? AMDGPU::SI_SPILL_V32_CFI_SAVE : AMDGPU::SI_SPILL_V32_SAVE;
1593 return NeedsCFI ? AMDGPU::SI_SPILL_V64_CFI_SAVE : AMDGPU::SI_SPILL_V64_SAVE;
1595 return NeedsCFI ? AMDGPU::SI_SPILL_V96_CFI_SAVE : AMDGPU::SI_SPILL_V96_SAVE;
1597 return NeedsCFI ? AMDGPU::SI_SPILL_V128_CFI_SAVE
1598 : AMDGPU::SI_SPILL_V128_SAVE;
1600 return NeedsCFI ? AMDGPU::SI_SPILL_V160_CFI_SAVE
1601 : AMDGPU::SI_SPILL_V160_SAVE;
1603 return NeedsCFI ? AMDGPU::SI_SPILL_V192_CFI_SAVE
1604 : AMDGPU::SI_SPILL_V192_SAVE;
1606 return NeedsCFI ? AMDGPU::SI_SPILL_V224_CFI_SAVE
1607 : AMDGPU::SI_SPILL_V224_SAVE;
1609 return NeedsCFI ? AMDGPU::SI_SPILL_V256_CFI_SAVE
1610 : AMDGPU::SI_SPILL_V256_SAVE;
1612 return NeedsCFI ? AMDGPU::SI_SPILL_V288_CFI_SAVE
1613 : AMDGPU::SI_SPILL_V288_SAVE;
1615 return NeedsCFI ? AMDGPU::SI_SPILL_V320_CFI_SAVE
1616 : AMDGPU::SI_SPILL_V320_SAVE;
1618 return NeedsCFI ? AMDGPU::SI_SPILL_V352_CFI_SAVE
1619 : AMDGPU::SI_SPILL_V352_SAVE;
1621 return NeedsCFI ? AMDGPU::SI_SPILL_V384_CFI_SAVE
1622 : AMDGPU::SI_SPILL_V384_SAVE;
1624 return NeedsCFI ? AMDGPU::SI_SPILL_V512_CFI_SAVE
1625 : AMDGPU::SI_SPILL_V512_SAVE;
1627 return NeedsCFI ? AMDGPU::SI_SPILL_V1024_CFI_SAVE
1628 : AMDGPU::SI_SPILL_V1024_SAVE;
1637 return NeedsCFI ? AMDGPU::SI_SPILL_AV32_CFI_SAVE
1638 : AMDGPU::SI_SPILL_AV32_SAVE;
1640 return NeedsCFI ? AMDGPU::SI_SPILL_AV64_CFI_SAVE
1641 : AMDGPU::SI_SPILL_AV64_SAVE;
1643 return NeedsCFI ? AMDGPU::SI_SPILL_AV96_CFI_SAVE
1644 : AMDGPU::SI_SPILL_AV96_SAVE;
1646 return NeedsCFI ? AMDGPU::SI_SPILL_AV128_CFI_SAVE
1647 : AMDGPU::SI_SPILL_AV128_SAVE;
1649 return NeedsCFI ? AMDGPU::SI_SPILL_AV160_CFI_SAVE
1650 : AMDGPU::SI_SPILL_AV160_SAVE;
1652 return NeedsCFI ? AMDGPU::SI_SPILL_AV192_CFI_SAVE
1653 : AMDGPU::SI_SPILL_AV192_SAVE;
1655 return NeedsCFI ? AMDGPU::SI_SPILL_AV224_CFI_SAVE
1656 : AMDGPU::SI_SPILL_AV224_SAVE;
1658 return NeedsCFI ? AMDGPU::SI_SPILL_AV256_CFI_SAVE
1659 : AMDGPU::SI_SPILL_AV256_SAVE;
1661 return AMDGPU::SI_SPILL_AV288_SAVE;
1663 return AMDGPU::SI_SPILL_AV320_SAVE;
1665 return AMDGPU::SI_SPILL_AV352_SAVE;
1667 return AMDGPU::SI_SPILL_AV384_SAVE;
1669 return NeedsCFI ? AMDGPU::SI_SPILL_AV512_CFI_SAVE
1670 : AMDGPU::SI_SPILL_AV512_SAVE;
1672 return NeedsCFI ? AMDGPU::SI_SPILL_AV1024_CFI_SAVE
1673 : AMDGPU::SI_SPILL_AV1024_SAVE;
1680 bool IsVectorSuperClass) {
1685 if (IsVectorSuperClass)
1686 return AMDGPU::SI_SPILL_WWM_AV32_SAVE;
1688 return AMDGPU::SI_SPILL_WWM_V32_SAVE;
1694 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1701 if (ST.hasMAIInsts())
1707void SIInstrInfo::storeRegToStackSlotImpl(
1720 FrameInfo.getObjectAlign(FrameIndex));
1721 unsigned SpillSize = RI.getSpillSize(*RC);
1727 assert(SrcReg != AMDGPU::M0 &&
"m0 should not be spilled");
1728 assert(SrcReg != AMDGPU::EXEC_LO && SrcReg != AMDGPU::EXEC_HI &&
1729 SrcReg != AMDGPU::EXEC &&
"exec should not be spilled");
1738 if (SrcReg.
isVirtual() && SpillSize == 4) {
1752 SpillSize, *MFI, NeedsCFI);
1767 storeRegToStackSlotImpl(
MBB,
MI, SrcReg, isKill, FrameIndex, RC, VReg, Flags,
1776 storeRegToStackSlotImpl(
MBB,
MI, SrcReg, isKill, FrameIndex, RC,
Register(),
1783 return AMDGPU::SI_SPILL_S32_RESTORE;
1785 return AMDGPU::SI_SPILL_S64_RESTORE;
1787 return AMDGPU::SI_SPILL_S96_RESTORE;
1789 return AMDGPU::SI_SPILL_S128_RESTORE;
1791 return AMDGPU::SI_SPILL_S160_RESTORE;
1793 return AMDGPU::SI_SPILL_S192_RESTORE;
1795 return AMDGPU::SI_SPILL_S224_RESTORE;
1797 return AMDGPU::SI_SPILL_S256_RESTORE;
1799 return AMDGPU::SI_SPILL_S288_RESTORE;
1801 return AMDGPU::SI_SPILL_S320_RESTORE;
1803 return AMDGPU::SI_SPILL_S352_RESTORE;
1805 return AMDGPU::SI_SPILL_S384_RESTORE;
1807 return AMDGPU::SI_SPILL_S512_RESTORE;
1809 return AMDGPU::SI_SPILL_S1024_RESTORE;
1818 return AMDGPU::SI_SPILL_V16_RESTORE;
1820 return AMDGPU::SI_SPILL_V32_RESTORE;
1822 return AMDGPU::SI_SPILL_V64_RESTORE;
1824 return AMDGPU::SI_SPILL_V96_RESTORE;
1826 return AMDGPU::SI_SPILL_V128_RESTORE;
1828 return AMDGPU::SI_SPILL_V160_RESTORE;
1830 return AMDGPU::SI_SPILL_V192_RESTORE;
1832 return AMDGPU::SI_SPILL_V224_RESTORE;
1834 return AMDGPU::SI_SPILL_V256_RESTORE;
1836 return AMDGPU::SI_SPILL_V288_RESTORE;
1838 return AMDGPU::SI_SPILL_V320_RESTORE;
1840 return AMDGPU::SI_SPILL_V352_RESTORE;
1842 return AMDGPU::SI_SPILL_V384_RESTORE;
1844 return AMDGPU::SI_SPILL_V512_RESTORE;
1846 return AMDGPU::SI_SPILL_V1024_RESTORE;
1855 return AMDGPU::SI_SPILL_AV32_RESTORE;
1857 return AMDGPU::SI_SPILL_AV64_RESTORE;
1859 return AMDGPU::SI_SPILL_AV96_RESTORE;
1861 return AMDGPU::SI_SPILL_AV128_RESTORE;
1863 return AMDGPU::SI_SPILL_AV160_RESTORE;
1865 return AMDGPU::SI_SPILL_AV192_RESTORE;
1867 return AMDGPU::SI_SPILL_AV224_RESTORE;
1869 return AMDGPU::SI_SPILL_AV256_RESTORE;
1871 return AMDGPU::SI_SPILL_AV288_RESTORE;
1873 return AMDGPU::SI_SPILL_AV320_RESTORE;
1875 return AMDGPU::SI_SPILL_AV352_RESTORE;
1877 return AMDGPU::SI_SPILL_AV384_RESTORE;
1879 return AMDGPU::SI_SPILL_AV512_RESTORE;
1881 return AMDGPU::SI_SPILL_AV1024_RESTORE;
1888 bool IsVectorSuperClass) {
1893 if (IsVectorSuperClass)
1894 return AMDGPU::SI_SPILL_WWM_AV32_RESTORE;
1896 return AMDGPU::SI_SPILL_WWM_V32_RESTORE;
1902 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1909 if (ST.hasMAIInsts())
1912 assert(!RI.isAGPRClass(RC));
1926 unsigned SpillSize = RI.getSpillSize(*RC);
1933 FrameInfo.getObjectAlign(FrameIndex));
1935 if (RI.isSGPRClass(RC)) {
1938 assert(DestReg != AMDGPU::M0 &&
"m0 should not be reloaded into");
1939 assert(DestReg != AMDGPU::EXEC_LO && DestReg != AMDGPU::EXEC_HI &&
1940 DestReg != AMDGPU::EXEC &&
"exec should not be spilled");
1945 if (DestReg.
isVirtual() && SpillSize == 4) {
1974 unsigned Quantity)
const {
1976 unsigned MaxSNopCount = 1u << ST.getSNopBits();
1977 while (Quantity > 0) {
1978 unsigned Arg = std::min(Quantity, MaxSNopCount);
1989 constexpr unsigned DoorbellIDMask = 0x3ff;
1990 constexpr unsigned ECQueueWaveAbort = 0x400;
1995 if (!
MBB.succ_empty() || std::next(
MI.getIterator()) !=
MBB.end()) {
1996 MBB.splitAt(
MI,
false);
2000 MBB.addSuccessor(TrapBB);
2010 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
2014 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_AND_B32), DoorbellRegMasked)
2019 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_OR_B32), SetWaveAbortBit)
2020 .
addUse(DoorbellRegMasked)
2021 .
addImm(ECQueueWaveAbort);
2022 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2023 .
addUse(SetWaveAbortBit);
2026 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2037 return MBB.getNextNode();
2041 switch (
MI.getOpcode()) {
2043 if (
MI.isMetaInstruction())
2048 return MI.getOperand(0).getImm() + 1;
2059 switch (
MI.getOpcode()) {
2061 case AMDGPU::S_MOV_B64_term:
2064 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2067 case AMDGPU::S_MOV_B32_term:
2070 MI.setDesc(
get(AMDGPU::S_MOV_B32));
2073 case AMDGPU::S_XOR_B64_term:
2076 MI.setDesc(
get(AMDGPU::S_XOR_B64));
2079 case AMDGPU::S_XOR_B32_term:
2082 MI.setDesc(
get(AMDGPU::S_XOR_B32));
2084 case AMDGPU::S_OR_B64_term:
2087 MI.setDesc(
get(AMDGPU::S_OR_B64));
2089 case AMDGPU::S_OR_B32_term:
2092 MI.setDesc(
get(AMDGPU::S_OR_B32));
2095 case AMDGPU::S_ANDN2_B64_term:
2098 MI.setDesc(
get(AMDGPU::S_ANDN2_B64));
2101 case AMDGPU::S_ANDN2_B32_term:
2104 MI.setDesc(
get(AMDGPU::S_ANDN2_B32));
2107 case AMDGPU::S_AND_B64_term:
2110 MI.setDesc(
get(AMDGPU::S_AND_B64));
2113 case AMDGPU::S_AND_B32_term:
2116 MI.setDesc(
get(AMDGPU::S_AND_B32));
2119 case AMDGPU::S_AND_SAVEEXEC_B64_term:
2122 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B64));
2125 case AMDGPU::S_AND_SAVEEXEC_B32_term:
2128 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B32));
2131 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
2132 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32));
2134 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
2135 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32));
2138 case AMDGPU::SI_SPILL_S32_TO_VGPR:
2139 MI.setDesc(
get(AMDGPU::V_WRITELANE_B32));
2142 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
2143 MI.setDesc(
get(AMDGPU::V_READLANE_B32));
2145 case AMDGPU::AV_MOV_B32_IMM_PSEUDO: {
2149 get(IsAGPR ? AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::V_MOV_B32_e32));
2152 case AMDGPU::AV_MOV_B64_IMM_PSEUDO: {
2155 int64_t
Imm =
MI.getOperand(1).getImm();
2157 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2158 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2163 MI.eraseFromParent();
2169 case AMDGPU::V_MOV_B64_PSEUDO: {
2171 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2172 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2180 if (ST.hasVMovB64Inst() && Mov64RC->
contains(Dst)) {
2181 MI.setDesc(Mov64Desc);
2185 (
SrcOp.isGlobal() && ST.has64BitLiterals()))
2188 if (
SrcOp.isGlobal()) {
2193 unsigned BaseFlags, LoReloc, HiReloc;
2194 std::tie(BaseFlags, LoReloc, HiReloc) =
2201 }
else if (
SrcOp.isImm()) {
2203 APInt Lo(32,
Imm.getLoBits(32).getZExtValue());
2204 APInt Hi(32,
Imm.getHiBits(32).getZExtValue());
2228 if (ST.hasPkMovB32() &&
2247 MI.eraseFromParent();
2250 case AMDGPU::V_MOV_B64_DPP_PSEUDO: {
2254 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2258 if (ST.has64BitLiterals()) {
2259 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2263 if (
SrcOp.isGlobal()) {
2265 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2266 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2269 unsigned BaseFlags, LoReloc, HiReloc;
2270 std::tie(BaseFlags, LoReloc, HiReloc) =
2277 MI.eraseFromParent();
2284 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2289 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2290 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2292 APInt Lo(32,
Imm.getLoBits(32).getZExtValue());
2293 APInt Hi(32,
Imm.getHiBits(32).getZExtValue());
2298 MI.eraseFromParent();
2301 case AMDGPU::V_SET_INACTIVE_B32: {
2305 .
add(
MI.getOperand(3))
2306 .
add(
MI.getOperand(4))
2307 .
add(
MI.getOperand(1))
2308 .
add(
MI.getOperand(2))
2309 .
add(
MI.getOperand(5));
2310 MI.eraseFromParent();
2313 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2314 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2315 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2316 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2317 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2318 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2319 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2320 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2321 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2322 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2323 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2324 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2325 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2326 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2327 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2328 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2329 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2330 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2331 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2332 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2333 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2334 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2335 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2336 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2337 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2338 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2339 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2340 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2341 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1:
2342 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2:
2343 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4:
2344 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8:
2345 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16: {
2349 if (RI.hasVGPRs(EltRC)) {
2350 Opc = AMDGPU::V_MOVRELD_B32_e32;
2352 Opc = RI.getRegSizeInBits(*EltRC) == 64 ? AMDGPU::S_MOVRELD_B64
2353 : AMDGPU::S_MOVRELD_B32;
2358 bool IsUndef =
MI.getOperand(1).isUndef();
2359 unsigned SubReg =
MI.getOperand(3).getImm();
2360 assert(VecReg ==
MI.getOperand(1).getReg());
2365 .
add(
MI.getOperand(2))
2369 const int ImpDefIdx =
2371 const int ImpUseIdx = ImpDefIdx + 1;
2373 MI.eraseFromParent();
2376 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1:
2377 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2:
2378 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3:
2379 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4:
2380 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5:
2381 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6:
2382 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7:
2383 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8:
2384 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9:
2385 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10:
2386 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11:
2387 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12:
2388 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16:
2389 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32: {
2390 assert(ST.useVGPRIndexMode());
2392 bool IsUndef =
MI.getOperand(1).isUndef();
2401 const MCInstrDesc &OpDesc =
get(AMDGPU::V_MOV_B32_indirect_write);
2405 .
add(
MI.getOperand(2))
2409 const int ImpDefIdx =
2411 const int ImpUseIdx = ImpDefIdx + 1;
2418 MI.eraseFromParent();
2421 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1:
2422 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2:
2423 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3:
2424 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4:
2425 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5:
2426 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6:
2427 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7:
2428 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8:
2429 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9:
2430 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10:
2431 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11:
2432 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12:
2433 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16:
2434 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32: {
2435 assert(ST.useVGPRIndexMode());
2438 bool IsUndef =
MI.getOperand(1).isUndef();
2442 .
add(
MI.getOperand(2))
2455 MI.eraseFromParent();
2458 case AMDGPU::SI_PC_ADD_REL_OFFSET: {
2461 Register RegLo = RI.getSubReg(Reg, AMDGPU::sub0);
2462 Register RegHi = RI.getSubReg(Reg, AMDGPU::sub1);
2481 if (ST.hasGetPCZeroExtension()) {
2485 BuildMI(MF,
DL,
get(AMDGPU::S_SEXT_I32_I16), RegHi).addReg(RegHi));
2492 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U32), RegLo).addReg(RegLo).add(OpLo));
2502 MI.eraseFromParent();
2505 case AMDGPU::SI_PC_ADD_REL_OFFSET64: {
2515 Op.setOffset(
Op.getOffset() + 4);
2517 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U64), Reg).addReg(Reg).add(
Op));
2521 MI.eraseFromParent();
2524 case AMDGPU::ENTER_STRICT_WWM: {
2530 case AMDGPU::ENTER_STRICT_WQM: {
2537 MI.eraseFromParent();
2540 case AMDGPU::EXIT_STRICT_WWM:
2541 case AMDGPU::EXIT_STRICT_WQM: {
2547 case AMDGPU::SI_RETURN: {
2561 MI.eraseFromParent();
2565 case AMDGPU::S_MUL_U64_U32_PSEUDO:
2566 case AMDGPU::S_MUL_I64_I32_PSEUDO:
2567 MI.setDesc(
get(AMDGPU::S_MUL_U64));
2570 case AMDGPU::S_GETPC_B64_pseudo:
2571 MI.setDesc(
get(AMDGPU::S_GETPC_B64));
2572 if (ST.hasGetPCZeroExtension()) {
2574 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2583 case AMDGPU::V_MAX_BF16_PSEUDO_e64: {
2584 assert(ST.hasBF16PackedInsts());
2585 MI.setDesc(
get(AMDGPU::V_PK_MAX_NUM_BF16));
2596 case AMDGPU::GET_STACK_BASE:
2599 if (ST.getFrameLowering()->mayReserveScratchForCWSR(*
MBB.getParent())) {
2606 Register DestReg =
MI.getOperand(0).getReg();
2616 MI.getOperand(
MI.getNumExplicitOperands()).setIsDead(
false);
2617 MI.getOperand(
MI.getNumExplicitOperands()).setIsUse();
2618 MI.setDesc(
get(AMDGPU::S_CMOVK_I32));
2621 MI.setDesc(
get(AMDGPU::S_MOV_B32));
2624 MI.getNumExplicitOperands());
2642 case AMDGPU::S_MOV_B64:
2643 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2652 if (UsedLanes.
all())
2657 unsigned LoSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub0);
2658 unsigned HiSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub1);
2660 bool NeedLo = (UsedLanes & RI.getSubRegIndexLaneMask(LoSubReg)).any();
2661 bool NeedHi = (UsedLanes & RI.getSubRegIndexLaneMask(HiSubReg)).any();
2663 if (NeedLo && NeedHi)
2667 int32_t Imm32 = NeedLo ?
Lo_32(Imm64) :
Hi_32(Imm64);
2669 unsigned UseSubReg = NeedLo ? LoSubReg : HiSubReg;
2678 case AMDGPU::S_LOAD_DWORDX16_IMM:
2679 case AMDGPU::S_LOAD_DWORDX8_IMM: {
2692 for (
auto &CandMO :
I->operands()) {
2693 if (!CandMO.isReg() || CandMO.getReg() != RegToFind || CandMO.isDef())
2701 if (!UseMO || UseMO->
getSubReg() == AMDGPU::NoSubRegister)
2705 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->
getSubReg());
2711 unsigned NewOpcode = -1;
2712 if (SubregSize == 256)
2713 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2714 else if (SubregSize == 128)
2715 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2725 UseMO->
setSubReg(AMDGPU::NoSubRegister);
2730 MI->getOperand(0).setReg(DestReg);
2731 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2735 OffsetMO->
setImm(FinalOffset);
2741 MI->setMemRefs(*MF, NewMMOs);
2754std::pair<MachineInstr*, MachineInstr*>
2756 assert (
MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2758 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2761 MI.setDesc(
get(AMDGPU::V_MOV_B64_dpp));
2762 return std::pair(&
MI,
nullptr);
2773 for (
auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2775 if (Dst.isPhysical()) {
2776 MovDPP.addDef(RI.getSubReg(Dst,
Sub));
2783 for (
unsigned I = 1;
I <= 2; ++
I) {
2786 if (
SrcOp.isImm()) {
2788 Imm.ashrInPlace(Part * 32);
2789 MovDPP.addImm(
Imm.getLoBits(32).getZExtValue());
2793 if (Src.isPhysical())
2794 MovDPP.addReg(RI.getSubReg(Src,
Sub));
2801 MovDPP.addImm(MO.getImm());
2803 Split[Part] = MovDPP;
2807 if (Dst.isVirtual())
2814 MI.eraseFromParent();
2815 return std::pair(Split[0], Split[1]);
2818std::optional<DestSourcePair>
2820 if (
MI.getOpcode() == AMDGPU::WWM_COPY)
2823 return std::nullopt;
2827 AMDGPU::OpName Src0OpName,
2829 AMDGPU::OpName Src1OpName)
const {
2836 "All commutable instructions have both src0 and src1 modifiers");
2838 int Src0ModsVal = Src0Mods->
getImm();
2839 int Src1ModsVal = Src1Mods->
getImm();
2841 Src1Mods->
setImm(Src0ModsVal);
2842 Src0Mods->
setImm(Src1ModsVal);
2851 bool IsKill = RegOp.
isKill();
2853 bool IsUndef = RegOp.
isUndef();
2854 bool IsDebug = RegOp.
isDebug();
2856 if (NonRegOp.
isImm())
2858 else if (NonRegOp.
isFI())
2879 int64_t NonRegVal = NonRegOp1.
getImm();
2882 NonRegOp2.
setImm(NonRegVal);
2889 unsigned OpIdx1)
const {
2894 unsigned Opc =
MI.getOpcode();
2895 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
2905 if ((
int)OpIdx0 == Src0Idx && !MO0.
isReg() &&
2908 if ((
int)OpIdx1 == Src0Idx && !MO1.
isReg() &&
2913 if ((
int)OpIdx1 != Src0Idx && MO0.
isReg()) {
2919 if ((
int)OpIdx0 != Src0Idx && MO1.
isReg()) {
2934 unsigned Src1Idx)
const {
2935 assert(!NewMI &&
"this should never be used");
2937 unsigned Opc =
MI.getOpcode();
2939 if (CommutedOpcode == -1)
2942 if (Src0Idx > Src1Idx)
2945 assert(AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) ==
2946 static_cast<int>(Src0Idx) &&
2947 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1) ==
2948 static_cast<int>(Src1Idx) &&
2949 "inconsistency with findCommutedOpIndices");
2974 Src1, AMDGPU::OpName::src1_modifiers);
2977 AMDGPU::OpName::src1_sel);
2989 unsigned &SrcOpIdx0,
2990 unsigned &SrcOpIdx1)
const {
2995 unsigned &SrcOpIdx0,
2996 unsigned &SrcOpIdx1)
const {
2997 if (!
Desc.isCommutable())
3000 unsigned Opc =
Desc.getOpcode();
3001 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
3005 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
3009 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
3013 int64_t BrOffset)
const {
3030 return MI.getOperand(0).getMBB();
3035 if (
MI.getOpcode() == AMDGPU::SI_IF ||
MI.getOpcode() == AMDGPU::SI_ELSE ||
3036 MI.getOpcode() == AMDGPU::SI_LOOP)
3048 "new block should be inserted for expanding unconditional branch");
3051 "restore block should be inserted for restoring clobbered registers");
3059 if (ST.useAddPC64Inst()) {
3061 MCCtx.createTempSymbol(
"offset",
true);
3065 MCCtx.createTempSymbol(
"post_addpc",
true);
3066 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
3070 Offset->setVariableValue(OffsetExpr);
3074 assert(RS &&
"RegScavenger required for long branching");
3082 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
3083 ST.hasVALUReadSGPRHazard();
3084 auto ApplyHazardWorkarounds = [
this, &
MBB, &
I, &
DL, FlushSGPRWrites]() {
3085 if (FlushSGPRWrites)
3093 ApplyHazardWorkarounds();
3096 MCCtx.createTempSymbol(
"post_getpc",
true);
3100 MCCtx.createTempSymbol(
"offset_lo",
true);
3102 MCCtx.createTempSymbol(
"offset_hi",
true);
3105 .
addReg(PCReg, {}, AMDGPU::sub0)
3109 .
addReg(PCReg, {}, AMDGPU::sub1)
3111 ApplyHazardWorkarounds();
3152 if (LongBranchReservedReg) {
3153 RS->enterBasicBlock(
MBB);
3154 Scav = LongBranchReservedReg;
3156 RS->enterBasicBlockEnd(
MBB);
3157 Scav = RS->scavengeRegisterBackwards(
3162 RS->setRegUsed(Scav);
3170 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
3187unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate
Cond) {
3189 case SIInstrInfo::SCC_TRUE:
3190 return AMDGPU::S_CBRANCH_SCC1;
3191 case SIInstrInfo::SCC_FALSE:
3192 return AMDGPU::S_CBRANCH_SCC0;
3193 case SIInstrInfo::VCCNZ:
3194 return AMDGPU::S_CBRANCH_VCCNZ;
3195 case SIInstrInfo::VCCZ:
3196 return AMDGPU::S_CBRANCH_VCCZ;
3197 case SIInstrInfo::EXECNZ:
3198 return AMDGPU::S_CBRANCH_EXECNZ;
3199 case SIInstrInfo::EXECZ:
3200 return AMDGPU::S_CBRANCH_EXECZ;
3206SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(
unsigned Opcode) {
3208 case AMDGPU::S_CBRANCH_SCC0:
3210 case AMDGPU::S_CBRANCH_SCC1:
3212 case AMDGPU::S_CBRANCH_VCCNZ:
3214 case AMDGPU::S_CBRANCH_VCCZ:
3216 case AMDGPU::S_CBRANCH_EXECNZ:
3218 case AMDGPU::S_CBRANCH_EXECZ:
3230 bool AllowModify)
const {
3231 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3233 TBB =
I->getOperand(0).getMBB();
3237 BranchPredicate Pred = getBranchPredicate(
I->getOpcode());
3238 if (Pred == INVALID_BR)
3243 Cond.push_back(
I->getOperand(1));
3247 if (
I ==
MBB.end()) {
3253 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3255 FBB =
I->getOperand(0).getMBB();
3265 bool AllowModify)
const {
3273 while (
I != E && !
I->isBranch() && !
I->isReturn()) {
3274 switch (
I->getOpcode()) {
3275 case AMDGPU::S_MOV_B64_term:
3276 case AMDGPU::S_XOR_B64_term:
3277 case AMDGPU::S_OR_B64_term:
3278 case AMDGPU::S_ANDN2_B64_term:
3279 case AMDGPU::S_AND_B64_term:
3280 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3281 case AMDGPU::S_MOV_B32_term:
3282 case AMDGPU::S_XOR_B32_term:
3283 case AMDGPU::S_OR_B32_term:
3284 case AMDGPU::S_ANDN2_B32_term:
3285 case AMDGPU::S_AND_B32_term:
3286 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3287 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3288 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3291 case AMDGPU::SI_ELSE:
3292 case AMDGPU::SI_KILL_I1_TERMINATOR:
3293 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3310 int *BytesRemoved)
const {
3312 unsigned RemovedSize = 0;
3315 if (
MI.isBranch() ||
MI.isReturn()) {
3317 MI.eraseFromParent();
3323 *BytesRemoved = RemovedSize;
3340 int *BytesAdded)
const {
3341 if (!FBB &&
Cond.empty()) {
3345 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3352 = getBranchOpcode(
static_cast<BranchPredicate
>(
Cond[0].
getImm()));
3364 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3382 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3389 if (
Cond.size() != 2) {
3393 if (
Cond[0].isImm()) {
3414 bool shouldIgnoreForPipelining(
const MachineInstr *
MI)
const override {
3418 std::optional<bool> createTripCountGreaterCondition(
3419 int TC, MachineBasicBlock &
MBB,
3420 SmallVectorImpl<MachineOperand> &CondParam)
override {
3421 CondParam = this->
Cond;
3425 void adjustTripCount(
int TripCountAdjust)
override {}
3427 void setPreheader(MachineBasicBlock *NewPreheader)
override {}
3431std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
3440 if (
TBB == LoopBB && FBB == LoopBB)
3447 assert((
TBB == LoopBB || FBB == LoopBB) &&
3448 "The Loop must be a single-basic-block loop");
3451 BranchPredicate Pred =
static_cast<BranchPredicate
>(
Cond[0].getImm());
3452 if (Pred != SCC_TRUE && Pred != SCC_FALSE)
3457 if (
MI.isCall() ||
MI.isInlineAsm())
3472 if (CmpI == Instructions.end() || CmpI->isPHI())
3476 return std::make_unique<AMDGPUPipelinerLoopInfo>(
CmpInst,
Cond);
3482 Register FalseReg,
int &CondCycles,
3483 int &TrueCycles,
int &FalseCycles)
const {
3493 CondCycles = TrueCycles = FalseCycles = NumInsts;
3496 return RI.hasVGPRs(RC) && NumInsts <= 6;
3510 if (NumInsts % 2 == 0)
3513 CondCycles = TrueCycles = FalseCycles = NumInsts;
3514 return RI.isSGPRClass(RC);
3525 BranchPredicate Pred =
static_cast<BranchPredicate
>(
Cond[0].getImm());
3526 if (Pred == VCCZ || Pred == SCC_FALSE) {
3527 Pred =
static_cast<BranchPredicate
>(-Pred);
3533 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3535 if (DstSize == 32) {
3537 if (Pred == SCC_TRUE) {
3552 if (DstSize == 64 && Pred == SCC_TRUE) {
3562 static const int16_t Sub0_15[] = {
3563 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3564 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3565 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3566 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3569 static const int16_t Sub0_15_64[] = {
3570 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3571 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3572 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3573 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3576 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3578 const int16_t *SubIndices = Sub0_15;
3579 int NElts = DstSize / 32;
3583 if (Pred == SCC_TRUE) {
3585 SelOp = AMDGPU::S_CSELECT_B32;
3586 EltRC = &AMDGPU::SGPR_32RegClass;
3588 SelOp = AMDGPU::S_CSELECT_B64;
3589 EltRC = &AMDGPU::SGPR_64RegClass;
3590 SubIndices = Sub0_15_64;
3596 MBB,
I,
DL,
get(AMDGPU::REG_SEQUENCE), DstReg);
3601 for (
int Idx = 0; Idx != NElts; ++Idx) {
3605 unsigned SubIdx = SubIndices[Idx];
3608 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3610 .
addReg(FalseReg, {}, SubIdx)
3611 .addReg(TrueReg, {}, SubIdx);
3614 .
addReg(TrueReg, {}, SubIdx)
3615 .addReg(FalseReg, {}, SubIdx);
3628 if (
MI.isBranch() ||
MI.isCall() ||
MI.isReturn() ||
MI.isIndirectBranch())
3631 switch (
MI.getOpcode()) {
3632 case AMDGPU::S_ENDPGM:
3633 case AMDGPU::S_ENDPGM_SAVED:
3634 case AMDGPU::S_TRAP:
3635 case AMDGPU::S_GETREG_B32:
3636 case AMDGPU::S_SETREG_B32:
3637 case AMDGPU::S_SETREG_B32_mode:
3638 case AMDGPU::S_SETREG_IMM32_B32:
3639 case AMDGPU::S_SETREG_IMM32_B32_mode:
3640 case AMDGPU::S_SENDMSG:
3641 case AMDGPU::S_SENDMSGHALT:
3642 case AMDGPU::S_SENDMSG_RTN_B32:
3643 case AMDGPU::S_SENDMSG_RTN_B64:
3644 case AMDGPU::S_BARRIER_WAIT:
3645 case AMDGPU::S_BARRIER_SIGNAL_M0:
3646 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3647 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3648 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3656 switch (
MI.getOpcode()) {
3657 case AMDGPU::V_MOV_B16_t16_e32:
3658 case AMDGPU::V_MOV_B16_t16_e64:
3659 case AMDGPU::V_MOV_B32_e32:
3660 case AMDGPU::V_MOV_B32_e64:
3661 case AMDGPU::V_MOV_B64_PSEUDO:
3662 case AMDGPU::V_MOV_B64_e32:
3663 case AMDGPU::V_MOV_B64_e64:
3664 case AMDGPU::S_MOV_B32:
3665 case AMDGPU::S_MOV_B64:
3666 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3668 case AMDGPU::WWM_COPY:
3669 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3670 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3671 case AMDGPU::V_ACCVGPR_MOV_B32:
3672 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3673 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3681 switch (
MI.getOpcode()) {
3682 case AMDGPU::V_MOV_B16_t16_e32:
3683 case AMDGPU::V_MOV_B16_t16_e64:
3685 case AMDGPU::V_MOV_B32_e32:
3686 case AMDGPU::V_MOV_B32_e64:
3687 case AMDGPU::V_MOV_B64_PSEUDO:
3688 case AMDGPU::V_MOV_B64_e32:
3689 case AMDGPU::V_MOV_B64_e64:
3690 case AMDGPU::S_MOV_B32:
3691 case AMDGPU::S_MOV_B64:
3692 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3694 case AMDGPU::WWM_COPY:
3695 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3696 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3697 case AMDGPU::V_ACCVGPR_MOV_B32:
3698 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3699 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3707 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3708 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3709 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3712 unsigned Opc =
MI.getOpcode();
3714 int Idx = AMDGPU::getNamedOperandIdx(
Opc, Name);
3716 MI.removeOperand(Idx);
3722 MI.setDesc(NewDesc);
3728 unsigned NumOps =
Desc.getNumOperands() +
Desc.implicit_uses().size() +
3729 Desc.implicit_defs().size();
3731 for (
unsigned I =
MI.getNumOperands() - 1;
I >=
NumOps; --
I)
3732 MI.removeOperand(
I);
3736 unsigned SubRegIndex) {
3737 switch (SubRegIndex) {
3738 case AMDGPU::NoSubRegister:
3748 case AMDGPU::sub1_lo16:
3750 case AMDGPU::sub1_hi16:
3753 return std::nullopt;
3761 case AMDGPU::V_MAC_F16_e32:
3762 case AMDGPU::V_MAC_F16_e64:
3763 case AMDGPU::V_MAD_F16_e64:
3764 return AMDGPU::V_MADAK_F16;
3765 case AMDGPU::V_MAC_F32_e32:
3766 case AMDGPU::V_MAC_F32_e64:
3767 case AMDGPU::V_MAD_F32_e64:
3768 return AMDGPU::V_MADAK_F32;
3769 case AMDGPU::V_FMAC_F32_e32:
3770 case AMDGPU::V_FMAC_F32_e64:
3771 case AMDGPU::V_FMA_F32_e64:
3772 return AMDGPU::V_FMAAK_F32;
3773 case AMDGPU::V_FMAC_F16_e32:
3774 case AMDGPU::V_FMAC_F16_e64:
3775 case AMDGPU::V_FMAC_F16_t16_e64:
3776 case AMDGPU::V_FMAC_F16_fake16_e64:
3777 case AMDGPU::V_FMAC_F16_t16_e32:
3778 case AMDGPU::V_FMAC_F16_fake16_e32:
3779 case AMDGPU::V_FMA_F16_e64:
3780 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3781 ? AMDGPU::V_FMAAK_F16_t16
3782 : AMDGPU::V_FMAAK_F16_fake16
3783 : AMDGPU::V_FMAAK_F16;
3784 case AMDGPU::V_FMAC_F64_e32:
3785 case AMDGPU::V_FMAC_F64_e64:
3786 case AMDGPU::V_FMA_F64_e64:
3787 return AMDGPU::V_FMAAK_F64;
3795 case AMDGPU::V_MAC_F16_e32:
3796 case AMDGPU::V_MAC_F16_e64:
3797 case AMDGPU::V_MAD_F16_e64:
3798 return AMDGPU::V_MADMK_F16;
3799 case AMDGPU::V_MAC_F32_e32:
3800 case AMDGPU::V_MAC_F32_e64:
3801 case AMDGPU::V_MAD_F32_e64:
3802 return AMDGPU::V_MADMK_F32;
3803 case AMDGPU::V_FMAC_F32_e32:
3804 case AMDGPU::V_FMAC_F32_e64:
3805 case AMDGPU::V_FMA_F32_e64:
3806 return AMDGPU::V_FMAMK_F32;
3807 case AMDGPU::V_FMAC_F16_e32:
3808 case AMDGPU::V_FMAC_F16_e64:
3809 case AMDGPU::V_FMAC_F16_t16_e64:
3810 case AMDGPU::V_FMAC_F16_fake16_e64:
3811 case AMDGPU::V_FMAC_F16_t16_e32:
3812 case AMDGPU::V_FMAC_F16_fake16_e32:
3813 case AMDGPU::V_FMA_F16_e64:
3814 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3815 ? AMDGPU::V_FMAMK_F16_t16
3816 : AMDGPU::V_FMAMK_F16_fake16
3817 : AMDGPU::V_FMAMK_F16;
3818 case AMDGPU::V_FMAC_F64_e32:
3819 case AMDGPU::V_FMAC_F64_e64:
3820 case AMDGPU::V_FMA_F64_e64:
3821 return AMDGPU::V_FMAMK_F64;
3835 assert(!
DefMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3838 if (
Opc == AMDGPU::COPY) {
3839 assert(!
UseMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3846 if (HasMultipleUses) {
3849 unsigned ImmDefSize = RI.getRegSizeInBits(*MRI->
getRegClass(Reg));
3852 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3860 if (ImmDefSize == 32 &&
3865 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3866 RI.getSubRegIdxSize(UseSubReg) == 16;
3869 if (RI.hasVGPRs(DstRC))
3872 if (DstReg.
isVirtual() && UseSubReg != AMDGPU::lo16)
3878 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
3885 for (
unsigned MovOp :
3886 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
3887 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
3895 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
3899 if (MovDstPhysReg) {
3903 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
3910 if (MovDstPhysReg) {
3911 if (!MovDstRC->
contains(MovDstPhysReg))
3927 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
3935 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
3939 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
3941 UseMI.getOperand(0).setReg(MovDstPhysReg);
3946 UseMI.setDesc(NewMCID);
3947 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
3948 UseMI.addImplicitDefUseOperands(*MF);
3952 if (HasMultipleUses)
3955 if (
Opc == AMDGPU::V_MAD_F32_e64 ||
Opc == AMDGPU::V_MAC_F32_e64 ||
3956 Opc == AMDGPU::V_MAD_F16_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
3957 Opc == AMDGPU::V_FMA_F32_e64 ||
Opc == AMDGPU::V_FMAC_F32_e64 ||
3958 Opc == AMDGPU::V_FMA_F16_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64 ||
3959 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
3960 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
Opc == AMDGPU::V_FMA_F64_e64 ||
3961 Opc == AMDGPU::V_FMAC_F64_e64) {
3970 int Src0Idx = getNamedOperandIdx(
UseMI.getOpcode(), AMDGPU::OpName::src0);
3981 auto CopyRegOperandToNarrowerRC =
3984 if (!
MI.getOperand(OpNo).isReg())
3988 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
3991 BuildMI(*
MI.getParent(),
MI.getIterator(),
MI.getDebugLoc(),
3992 get(AMDGPU::COPY), Tmp)
3994 MI.getOperand(OpNo).setReg(Tmp);
3995 MI.getOperand(OpNo).setIsKill();
4002 Src1->
isReg() && Src1->
getReg() == Reg ? Src0 : Src1;
4003 if (!RegSrc->
isReg())
4006 ST.getConstantBusLimit(
Opc) < 2)
4021 if (Def && Def->isMoveImmediate() &&
4036 unsigned SrcSubReg = RegSrc->
getSubReg();
4041 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4042 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4043 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4044 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
4045 UseMI.untieRegOperand(
4046 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
4053 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
4054 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
4058 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
4059 UseMI.getOperand(0).getReg())
4061 UseMI.getOperand(0).setReg(Tmp);
4062 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
4063 CopyRegOperandToNarrowerRC(
UseMI, 3, NewRC);
4068 DefMI.eraseFromParent();
4075 if (ST.getConstantBusLimit(
Opc) < 2) {
4078 bool Src0Inlined =
false;
4079 if (Src0->
isReg()) {
4084 if (Def && Def->isMoveImmediate() &&
4089 }
else if (ST.getConstantBusLimit(
Opc) <= 1 &&
4090 RI.isSGPRReg(*MRI, Src0->
getReg())) {
4096 if (Src1->
isReg() && !Src0Inlined) {
4099 if (Def && Def->isMoveImmediate() &&
4103 else if (RI.isSGPRReg(*MRI, Src1->
getReg()))
4116 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4117 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4118 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4119 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
4120 UseMI.untieRegOperand(
4121 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
4123 const std::optional<int64_t> SubRegImm =
4133 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
4134 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
4138 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
4139 UseMI.getOperand(0).getReg())
4141 UseMI.getOperand(0).setReg(Tmp);
4142 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
4143 CopyRegOperandToNarrowerRC(
UseMI, 2, NewRC);
4153 DefMI.eraseFromParent();
4165 if (BaseOps1.
size() != BaseOps2.
size())
4167 for (
size_t I = 0,
E = BaseOps1.
size();
I <
E; ++
I) {
4168 if (!BaseOps1[
I]->isIdenticalTo(*BaseOps2[
I]))
4176 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
4177 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
4178 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
4180 LowOffset + (int)LowWidth.
getValue() <= HighOffset;
4183bool SIInstrInfo::checkInstOffsetsDoNotOverlap(
const MachineInstr &MIa,
4186 int64_t Offset0, Offset1;
4189 bool Offset0IsScalable, Offset1IsScalable;
4203 LocationSize Width0 = MIa.
memoperands().front()->getSize();
4204 LocationSize Width1 = MIb.
memoperands().front()->getSize();
4211 "MIa must load from or modify a memory location");
4213 "MIb must load from or modify a memory location");
4235 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4242 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4252 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4266 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4278 unsigned NumOps =
MI.getNumOperands();
4281 if (
Op.isReg() &&
Op.isKill())
4289 case AMDGPU::V_MAC_F16_e32:
4290 case AMDGPU::V_MAC_F16_e64:
4291 return AMDGPU::V_MAD_F16_e64;
4292 case AMDGPU::V_MAC_F32_e32:
4293 case AMDGPU::V_MAC_F32_e64:
4294 return AMDGPU::V_MAD_F32_e64;
4295 case AMDGPU::V_MAC_LEGACY_F32_e32:
4296 case AMDGPU::V_MAC_LEGACY_F32_e64:
4297 return AMDGPU::V_MAD_LEGACY_F32_e64;
4298 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4299 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4300 return AMDGPU::V_FMA_LEGACY_F32_e64;
4301 case AMDGPU::V_FMAC_F16_e32:
4302 case AMDGPU::V_FMAC_F16_e64:
4303 case AMDGPU::V_FMAC_F16_t16_e64:
4304 case AMDGPU::V_FMAC_F16_fake16_e64:
4305 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4306 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4307 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4308 : AMDGPU::V_FMA_F16_gfx9_e64;
4309 case AMDGPU::V_FMAC_F32_e32:
4310 case AMDGPU::V_FMAC_F32_e64:
4311 return AMDGPU::V_FMA_F32_e64;
4312 case AMDGPU::V_FMAC_F64_e32:
4313 case AMDGPU::V_FMAC_F64_e64:
4314 return AMDGPU::V_FMA_F64_e64;
4334 if (
MI.isBundle()) {
4337 if (
MI.getBundleSize() != 1)
4339 CandidateMI =
MI.getNextNode();
4343 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4347 if (
MI.isBundle()) {
4352 MI.untieRegOperand(MO.getOperandNo());
4360 if (Def.isEarlyClobber() && Def.isReg() &&
4365 auto UpdateDefIndex = [&](
LiveRange &LR) {
4366 auto *S = LR.find(OldIndex);
4367 if (S != LR.end() && S->start == OldIndex) {
4368 assert(S->valno && S->valno->def == OldIndex);
4369 S->start = NewIndex;
4370 S->valno->def = NewIndex;
4374 for (
auto &SR : LI.subranges())
4380 if (U.RemoveMIUse) {
4383 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4387 U.RemoveMIUse->setDesc(
get(AMDGPU::IMPLICIT_DEF));
4388 U.RemoveMIUse->getOperand(0).setIsDead(
true);
4389 for (
unsigned I = U.RemoveMIUse->getNumOperands() - 1;
I != 0; --
I)
4390 U.RemoveMIUse->removeOperand(
I);
4395 if (
MI.isBundle()) {
4399 if (MO.isReg() && MO.getReg() == DefReg) {
4400 assert(MO.getSubReg() == 0 &&
4401 "tied sub-registers in bundles currently not supported");
4402 MI.removeOperand(MO.getOperandNo());
4419 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4420 MIOp.setIsUndef(
true);
4421 MIOp.setReg(DummyReg);
4425 if (
MI.isBundle()) {
4429 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4430 MIOp.setIsUndef(
true);
4431 MIOp.setReg(DummyReg);
4444 return MI.isBundle() ? &
MI : NewMI;
4449 ThreeAddressUpdates &U)
const {
4451 unsigned Opc =
MI.getOpcode();
4455 if (NewMFMAOpc != -1) {
4458 for (
unsigned I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I)
4459 MIB.
add(
MI.getOperand(
I));
4467 for (
unsigned I = 0,
E =
MI.getNumExplicitOperands();
I !=
E; ++
I)
4472 assert(
Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4473 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4474 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4478 bool IsF64 =
Opc == AMDGPU::V_FMAC_F64_e32 ||
Opc == AMDGPU::V_FMAC_F64_e64;
4479 bool IsLegacy =
Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4480 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4481 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4482 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4483 bool Src0Literal =
false;
4488 case AMDGPU::V_MAC_F16_e64:
4489 case AMDGPU::V_FMAC_F16_e64:
4490 case AMDGPU::V_FMAC_F16_t16_e64:
4491 case AMDGPU::V_FMAC_F16_fake16_e64:
4492 case AMDGPU::V_MAC_F32_e64:
4493 case AMDGPU::V_MAC_LEGACY_F32_e64:
4494 case AMDGPU::V_FMAC_F32_e64:
4495 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4496 case AMDGPU::V_FMAC_F64_e64:
4498 case AMDGPU::V_MAC_F16_e32:
4499 case AMDGPU::V_FMAC_F16_e32:
4500 case AMDGPU::V_MAC_F32_e32:
4501 case AMDGPU::V_MAC_LEGACY_F32_e32:
4502 case AMDGPU::V_FMAC_F32_e32:
4503 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4504 case AMDGPU::V_FMAC_F64_e32: {
4505 int Src0Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
4506 AMDGPU::OpName::src0);
4507 const MachineOperand *Src0 = &
MI.getOperand(Src0Idx);
4518 MachineInstrBuilder MIB;
4521 const MachineOperand *Src0Mods =
4524 const MachineOperand *Src1Mods =
4527 const MachineOperand *Src2Mods =
4533 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4534 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4536 (ST.getConstantBusLimit(
Opc) > 1 || !Src0->
isReg() ||
4538 MachineInstr *
DefMI =
nullptr;
4540 std::optional<int64_t> ImmOpt;
4575 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4591 if (Src0Literal && !ST.hasVOP3Literal())
4619 switch (
MI.getOpcode()) {
4620 case AMDGPU::S_SET_GPR_IDX_ON:
4621 case AMDGPU::S_SET_GPR_IDX_MODE:
4622 case AMDGPU::S_SET_GPR_IDX_OFF:
4640 if (
MI.isTerminator() ||
MI.isPosition())
4644 if (
MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4647 if (
MI.getOpcode() == AMDGPU::SCHED_BARRIER &&
MI.getOperand(0).getImm() == 0)
4653 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4654 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4655 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4656 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4657 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4662 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4663 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4664 Opcode == AMDGPU::DS_SUB_GS_REG_RTN ||
isGWS(Opcode);
4678 if (
MI.getMF()->getFunction().hasFnAttribute(
"amdgpu-no-flat-scratch-init"))
4683 if (
MI.memoperands_empty())
4688 unsigned AS = Memop->getAddrSpace();
4689 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4690 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4691 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4692 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4707 if (
MI.memoperands_empty())
4716 unsigned AS = Memop->getAddrSpace();
4726 bool TgSplit)
const {
4739 if (
MI.memoperands_empty())
4744 unsigned AS = Memop->getAddrSpace();
4760 unsigned Opcode =
MI.getOpcode();
4775 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4776 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4777 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4778 Opcode == AMDGPU::S_SETHALT)
4781 if (
MI.isCall() ||
MI.isInlineAsm())
4797 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4798 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4799 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4800 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4808 if (
MI.isMetaInstruction())
4812 if (
MI.isCopyLike()) {
4813 if (!RI.isSGPRReg(MRI,
MI.getOperand(0).getReg()))
4817 return MI.readsRegister(AMDGPU::EXEC, &RI);
4828 return !
isSALU(
MI) ||
MI.readsRegister(AMDGPU::EXEC, &RI);
4832 switch (
Imm.getBitWidth()) {
4838 ST.hasInv2PiInlineImm());
4841 ST.hasInv2PiInlineImm());
4843 return ST.has16BitInsts() &&
4845 ST.hasInv2PiInlineImm());
4852 APInt IntImm =
Imm.bitcastToAPInt();
4854 bool HasInv2Pi = ST.hasInv2PiInlineImm();
4862 return ST.has16BitInsts() &&
4865 return ST.has16BitInsts() &&
4875 switch (OperandType) {
4885 int32_t Trunc =
static_cast<int32_t
>(
Imm);
4929 int16_t Trunc =
static_cast<int16_t
>(
Imm);
4930 return ST.has16BitInsts() &&
4939 int16_t Trunc =
static_cast<int16_t
>(
Imm);
4940 return ST.has16BitInsts() &&
4991 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
4997 return ST.hasVOP3Literal();
5001 int64_t ImmVal)
const {
5003 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
5004 if (Src1Idx != -1 &&
isDPP(
Opc) && !ST.hasDPPSrc1SGPR() &&
5005 OpNo ==
static_cast<unsigned>(Src1Idx))
5010 if (
isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
5011 OpNo == (
unsigned)AMDGPU::getNamedOperandIdx(InstDesc.
getOpcode(),
5012 AMDGPU::OpName::src2))
5015 if (ST.hasBF16InlineConstFromUpperFP32() &&
isVOP1(
Opc)) {
5022 return RI.opCanUseInlineConstant(OpInfo.OperandType);
5034 "unexpected imm-like operand kind");
5047 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
5065 AMDGPU::OpName
OpName)
const {
5067 return Mods && Mods->
getImm();
5080 switch (
MI.getOpcode()) {
5081 default:
return false;
5083 case AMDGPU::V_ADDC_U32_e64:
5084 case AMDGPU::V_SUBB_U32_e64:
5085 case AMDGPU::V_SUBBREV_U32_e64: {
5088 if (!Src1->
isReg() || !RI.isVGPR(MRI, Src1->
getReg()))
5093 case AMDGPU::V_MAC_F16_e64:
5094 case AMDGPU::V_MAC_F32_e64:
5095 case AMDGPU::V_MAC_LEGACY_F32_e64:
5096 case AMDGPU::V_FMAC_F16_e64:
5097 case AMDGPU::V_FMAC_F16_t16_e64:
5098 case AMDGPU::V_FMAC_F16_fake16_e64:
5099 case AMDGPU::V_FMAC_F32_e64:
5100 case AMDGPU::V_FMAC_F64_e64:
5101 case AMDGPU::V_FMAC_LEGACY_F32_e64:
5102 if (!Src2->
isReg() || !RI.isVGPR(MRI, Src2->
getReg()) ||
5107 case AMDGPU::V_CNDMASK_B32_e64:
5113 if (Src1 && (!Src1->
isReg() || !RI.isVGPR(MRI, Src1->
getReg()) ||
5126 if (Src0 && Src0->
isImm()) {
5129 get(Op32), AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src0),
5151 (
Use.getReg() == AMDGPU::VCC ||
Use.getReg() == AMDGPU::VCC_LO)) {
5160 unsigned Op32)
const {
5174 Inst32.
add(
MI.getOperand(
I));
5178 int Idx =
MI.getNumExplicitDefs();
5180 int OpTy =
MI.getDesc().operands()[Idx++].OperandType;
5185 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
5207 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5215 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5218 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5219 AMDGPU::SReg_64RegClass.contains(Reg);
5247 switch (MO.getReg()) {
5249 case AMDGPU::VCC_LO:
5250 case AMDGPU::VCC_HI:
5252 case AMDGPU::FLAT_SCR:
5265 switch (
MI.getOpcode()) {
5266 case AMDGPU::V_READLANE_B32:
5267 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5268 case AMDGPU::V_WRITELANE_B32:
5269 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5276 if (
MI.isPreISelOpcode() ||
5277 SIInstrInfo::isGenericOpcode(
MI.getOpcode()) ||
5295 return SubReg.
getSubReg() != AMDGPU::NoSubRegister &&
5306 if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
5307 ErrInfo =
"illegal copy from vector register to SGPR";
5325 if (!MRI.
isSSA() &&
MI.isCopy())
5326 return verifyCopy(
MI, MRI, ErrInfo);
5328 if (SIInstrInfo::isGenericOpcode(Opcode))
5331 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5332 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5333 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5335 if (Src0Idx == -1) {
5337 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5338 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5339 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5340 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5345 if (!
Desc.isVariadic() &&
5346 Desc.getNumOperands() !=
MI.getNumExplicitOperands()) {
5347 ErrInfo =
"Instruction has wrong number of operands.";
5351 if (
MI.isInlineAsm()) {
5364 if (!Reg.isVirtual() && !RC->
contains(Reg)) {
5365 ErrInfo =
"inlineasm operand has incorrect register class.";
5373 if (
isImage(
MI) &&
MI.memoperands_empty() &&
MI.mayLoadOrStore()) {
5374 ErrInfo =
"missing memory operand from image instruction.";
5379 for (
int i = 0, e =
Desc.getNumOperands(); i != e; ++i) {
5382 ErrInfo =
"FPImm Machine Operands are not supported. ISel should bitcast "
5383 "all fp values to integers.";
5388 int16_t RegClass = getOpRegClassID(OpInfo);
5390 switch (OpInfo.OperandType) {
5392 if (
MI.getOperand(i).isImm() ||
MI.getOperand(i).isGlobal()) {
5393 ErrInfo =
"Illegal immediate value for operand.";
5426 ErrInfo =
"Illegal immediate value for operand.";
5435 if (ST.has64BitLiterals() &&
Desc.getSize() != 4 && MO.
isImm() &&
5438 OpInfo.OperandType ==
5440 ErrInfo =
"illegal 64-bit immediate value for operand.";
5447 ErrInfo =
"Expected inline constant for operand.";
5461 if (!
MI.getOperand(i).isImm() && !
MI.getOperand(i).isFI()) {
5462 ErrInfo =
"Expected immediate, but got non-immediate";
5471 if (OpInfo.isGenericType())
5486 if (ST.needsAlignedVGPRs() && Opcode != AMDGPU::AV_MOV_B64_IMM_PSEUDO &&
5487 Opcode != AMDGPU::V_MOV_B64_PSEUDO && !
isSpill(
MI)) {
5489 if (RI.hasVectorRegisters(RC) && MO.
getSubReg()) {
5491 RI.getSubRegisterClass(RC, MO.
getSubReg())) {
5492 RC = RI.getCompatibleSubRegClass(RC, SubRC, MO.
getSubReg());
5499 if (!RC || !RI.isProperlyAlignedRC(*RC)) {
5500 ErrInfo =
"Subtarget requires even aligned vector registers";
5505 if (RegClass != -1) {
5506 if (Reg.isVirtual())
5511 ErrInfo =
"Operand has incorrect register class.";
5519 if (!ST.hasSDWA()) {
5520 ErrInfo =
"SDWA is not supported on this target";
5524 for (
auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5525 AMDGPU::OpName::dst_sel}) {
5531 ErrInfo =
"Invalid SDWA selection";
5536 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5538 for (
int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5543 if (!ST.hasSDWAScalar()) {
5545 if (!MO.
isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.
getReg()))) {
5546 ErrInfo =
"Only VGPRs allowed as operands in SDWA instructions on VI";
5553 "Only reg allowed as operands in SDWA instructions on GFX9+";
5559 if (!ST.hasSDWAOmod()) {
5562 if (OMod !=
nullptr &&
5564 ErrInfo =
"OMod not allowed in SDWA instructions on VI";
5569 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5570 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5571 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5572 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5575 unsigned Mods = Src0ModsMO->
getImm();
5578 ErrInfo =
"sext, abs and neg are not allowed on this instruction";
5584 if (
isVOPC(BasicOpcode)) {
5585 if (!ST.hasSDWASdst() && DstIdx != -1) {
5588 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5589 ErrInfo =
"Only VCC allowed as dst in SDWA instructions on VI";
5592 }
else if (!ST.hasSDWAOutModsVOPC()) {
5595 if (Clamp && (!Clamp->
isImm() || Clamp->
getImm() != 0)) {
5596 ErrInfo =
"Clamp not allowed in VOPC SDWA instructions on VI";
5602 if (OMod && (!OMod->
isImm() || OMod->
getImm() != 0)) {
5603 ErrInfo =
"OMod not allowed in VOPC SDWA instructions on VI";
5610 if (DstUnused && DstUnused->isImm() &&
5613 if (!Dst.isReg() || !Dst.isTied()) {
5614 ErrInfo =
"Dst register should have tied register";
5619 MI.getOperand(
MI.findTiedOperandIdx(DstIdx));
5622 "Dst register should be tied to implicit use of preserved register";
5626 ErrInfo =
"Dst register should use same physical register as preserved";
5632 if (
isDPP(
MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5634 if (Src1MO.
isReg() && RI.isSGPRReg(MRI, Src1MO.
getReg())) {
5635 ErrInfo =
"DPP src1 cannot be SGPR on this subtarget";
5638 if (Src1MO.
isImm()) {
5639 ErrInfo =
"DPP src1 cannot be an immediate on this subtarget";
5645 if (
isImage(Opcode) && !
MI.mayStore()) {
5650 uint64_t DMaskImm = DMask->
getImm();
5657 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5665 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5669 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5670 if (RegCount > DstSize) {
5671 ErrInfo =
"Image instruction returns too many registers for dst "
5681 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5682 unsigned ConstantBusCount = 0;
5683 bool UsesLiteral =
false;
5686 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5690 LiteralVal = &
MI.getOperand(ImmIdx);
5699 for (
int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5710 }
else if (!MO.
isFI()) {
5717 ErrInfo =
"VOP2/VOP3 instruction uses more than one literal";
5727 if (
llvm::all_of(SGPRsUsed, [
this, SGPRUsed](
unsigned SGPR) {
5728 return !RI.regsOverlap(SGPRUsed, SGPR);
5737 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5738 Opcode != AMDGPU::V_WRITELANE_B32) {
5739 ErrInfo =
"VOP* instruction violates constant bus restriction";
5743 if (
isVOP3(
MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5744 ErrInfo =
"VOP3 instruction uses literal";
5751 if (
Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5752 unsigned SGPRCount = 0;
5755 for (
int OpIdx : {Src0Idx, Src1Idx}) {
5763 if (MO.
getReg() != SGPRUsed)
5768 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5769 ErrInfo =
"WRITELANE instruction violates constant bus restriction";
5776 if (
Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5777 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5784 ErrInfo =
"v_div_scale_{f32|f64} require src0 = src1 or src2";
5794 ErrInfo =
"ABS not allowed in VOP3B instructions";
5807 ErrInfo =
"SOP2/SOPC instruction requires too many immediate constants";
5814 if (
Desc.isBranch()) {
5816 ErrInfo =
"invalid branch target for SOPK instruction";
5820 uint64_t
Imm =
Op->getImm();
5823 ErrInfo =
"invalid immediate for SOPK instruction";
5828 ErrInfo =
"invalid immediate for SOPK instruction";
5835 if (
Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
5836 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
5837 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5838 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
5839 const bool IsDst =
Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5840 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
5842 const unsigned StaticNumOps =
5843 Desc.getNumOperands() +
Desc.implicit_uses().size();
5844 const unsigned NumImplicitOps = IsDst ? 2 : 1;
5850 if (
MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
5851 ErrInfo =
"missing implicit register operands";
5857 if (!Dst->isUse()) {
5858 ErrInfo =
"v_movreld_b32 vdst should be a use operand";
5863 if (!
MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
5864 UseOpIdx != StaticNumOps + 1) {
5865 ErrInfo =
"movrel implicit operands should be tied";
5872 =
MI.getOperand(StaticNumOps + NumImplicitOps - 1);
5874 !
isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
5875 ErrInfo =
"src0 should be subreg of implicit vector use";
5883 if (!
MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
5884 ErrInfo =
"VALU instruction does not implicitly read exec mask";
5890 if (
MI.mayStore() &&
5895 if (Soff && Soff->
getReg() != AMDGPU::M0) {
5896 ErrInfo =
"scalar stores must use m0 as offset register";
5902 if (
isFLAT(
MI) && !ST.hasFlatInstOffsets()) {
5904 if (
Offset->getImm() != 0) {
5905 ErrInfo =
"subtarget does not support offsets in flat instructions";
5910 if (
isDS(
MI) && !ST.hasGDS()) {
5912 if (GDSOp && GDSOp->
getImm() != 0) {
5913 ErrInfo =
"GDS is not supported on this subtarget";
5921 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
5922 AMDGPU::OpName::vaddr0);
5923 AMDGPU::OpName RSrcOpName =
5924 isMIMG(
MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
5925 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
5933 ErrInfo =
"dim is out of range";
5938 if (ST.hasR128A16()) {
5940 IsA16 = R128A16->
getImm() != 0;
5941 }
else if (ST.hasA16()) {
5943 IsA16 = A16->
getImm() != 0;
5946 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
5948 unsigned AddrWords =
5951 unsigned VAddrWords;
5953 VAddrWords = RsrcIdx - VAddr0Idx;
5954 if (ST.hasPartialNSAEncoding() &&
5956 unsigned LastVAddrIdx = RsrcIdx - 1;
5957 VAddrWords +=
getOpSize(
MI, LastVAddrIdx) / 4 - 1;
5965 if (VAddrWords != AddrWords) {
5967 <<
" but got " << VAddrWords <<
"\n");
5968 ErrInfo =
"bad vaddr size";
5978 unsigned DC = DppCt->
getImm();
5979 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
5980 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
5981 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
5982 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
5983 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
5984 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
5985 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
5986 ErrInfo =
"Invalid dpp_ctrl value";
5989 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
5990 !ST.hasDPPWavefrontShifts()) {
5991 ErrInfo =
"Invalid dpp_ctrl value: "
5992 "wavefront shifts are not supported on GFX10+";
5995 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
5996 !ST.hasDPPBroadcasts()) {
5997 ErrInfo =
"Invalid dpp_ctrl value: "
5998 "broadcasts are not supported on GFX10+";
6001 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
6003 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
6004 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
6005 !ST.hasGFX90AInsts()) {
6006 ErrInfo =
"Invalid dpp_ctrl value: "
6007 "row_newbroadcast/row_share is not supported before "
6011 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
6012 ErrInfo =
"Invalid dpp_ctrl value: "
6013 "row_share and row_xmask are not supported before GFX10";
6018 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
6021 ErrInfo =
"Invalid dpp_ctrl value: "
6022 "DP ALU dpp only support row_newbcast";
6029 AMDGPU::OpName DataName =
6030 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
6036 if (!ST.hasGFX90AInsts()) {
6037 if ((Dst && RI.isAGPR(MRI, Dst->getReg())) ||
6038 (
Data && RI.isAGPR(MRI,
Data->getReg())) ||
6039 (Data2 && RI.isAGPR(MRI, Data2->
getReg()))) {
6040 ErrInfo =
"Invalid register class: "
6041 "agpr loads and stores not supported on this GPU";
6047 if (ST.needsAlignedVGPRs()) {
6048 const auto isAlignedReg = [&
MI, &MRI,
this](AMDGPU::OpName
OpName) ->
bool {
6053 if (Reg.isPhysical())
6054 return !(RI.getHWRegIndex(Reg) & 1);
6056 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
6057 !(RI.getChannelFromSubReg(
Op->getSubReg()) & 1);
6060 if (Opcode == AMDGPU::DS_GWS_INIT || Opcode == AMDGPU::DS_GWS_SEMA_BR ||
6061 Opcode == AMDGPU::DS_GWS_BARRIER) {
6063 if (!isAlignedReg(AMDGPU::OpName::data0)) {
6064 ErrInfo =
"Subtarget requires even aligned vector registers "
6065 "for DS_GWS instructions";
6071 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
6072 ErrInfo =
"Subtarget requires even aligned vector registers "
6073 "for vaddr operand of image instructions";
6079 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
6081 if (Src->isReg() && RI.isSGPRReg(MRI, Src->getReg())) {
6082 ErrInfo =
"Invalid register class: "
6083 "v_accvgpr_write with an SGPR is not supported on this GPU";
6088 if (
Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
6091 ErrInfo =
"pseudo expects only physical SGPRs";
6098 if (!ST.hasScaleOffset()) {
6099 ErrInfo =
"Subtarget does not support offset scaling";
6103 ErrInfo =
"Instruction does not support offset scaling";
6111 for (
unsigned I = 0;
I < 3; ++
I) {
6117 if (ST.hasFlatScratchHiInB64InstHazard() &&
isSALU(
MI) &&
6118 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI,
nullptr)) {
6120 if ((Dst && RI.getRegClassForReg(MRI, Dst->getReg()) ==
6121 &AMDGPU::SReg_64RegClass) ||
6122 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
6123 ErrInfo =
"Instruction cannot read flat_scratch_base_hi";
6132 if (
MI.getOpcode() == AMDGPU::S_MOV_B32) {
6134 return MI.getOperand(1).isReg() || RI.isAGPR(MRI,
MI.getOperand(0).getReg())
6136 : AMDGPU::V_MOV_B32_e32;
6146 default:
return AMDGPU::INSTRUCTION_LIST_END;
6147 case AMDGPU::REG_SEQUENCE:
return AMDGPU::REG_SEQUENCE;
6148 case AMDGPU::COPY:
return AMDGPU::COPY;
6149 case AMDGPU::PHI:
return AMDGPU::PHI;
6150 case AMDGPU::INSERT_SUBREG:
return AMDGPU::INSERT_SUBREG;
6151 case AMDGPU::WQM:
return AMDGPU::WQM;
6152 case AMDGPU::SOFT_WQM:
return AMDGPU::SOFT_WQM;
6153 case AMDGPU::STRICT_WWM:
return AMDGPU::STRICT_WWM;
6154 case AMDGPU::STRICT_WQM:
return AMDGPU::STRICT_WQM;
6155 case AMDGPU::S_ADD_I32:
6156 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
6157 case AMDGPU::S_ADDC_U32:
6158 return AMDGPU::V_ADDC_U32_e32;
6159 case AMDGPU::S_SUB_I32:
6160 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
6163 case AMDGPU::S_ADD_U32:
6164 return AMDGPU::V_ADD_CO_U32_e32;
6165 case AMDGPU::S_SUB_U32:
6166 return AMDGPU::V_SUB_CO_U32_e32;
6167 case AMDGPU::S_ADD_U64_PSEUDO:
6168 return AMDGPU::V_ADD_U64_PSEUDO;
6169 case AMDGPU::S_SUB_U64_PSEUDO:
6170 return AMDGPU::V_SUB_U64_PSEUDO;
6171 case AMDGPU::S_SUBB_U32:
return AMDGPU::V_SUBB_U32_e32;
6172 case AMDGPU::S_MUL_I32:
return AMDGPU::V_MUL_LO_U32_e64;
6173 case AMDGPU::S_MUL_HI_U32:
return AMDGPU::V_MUL_HI_U32_e64;
6174 case AMDGPU::S_MUL_HI_I32:
return AMDGPU::V_MUL_HI_I32_e64;
6175 case AMDGPU::S_AND_B32:
return AMDGPU::V_AND_B32_e64;
6176 case AMDGPU::S_OR_B32:
return AMDGPU::V_OR_B32_e64;
6177 case AMDGPU::S_XOR_B32:
return AMDGPU::V_XOR_B32_e64;
6178 case AMDGPU::S_XNOR_B32:
6179 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6180 case AMDGPU::S_MIN_I32:
return AMDGPU::V_MIN_I32_e64;
6181 case AMDGPU::S_MIN_U32:
return AMDGPU::V_MIN_U32_e64;
6182 case AMDGPU::S_MAX_I32:
return AMDGPU::V_MAX_I32_e64;
6183 case AMDGPU::S_MAX_U32:
return AMDGPU::V_MAX_U32_e64;
6184 case AMDGPU::S_ASHR_I32:
return AMDGPU::V_ASHR_I32_e32;
6185 case AMDGPU::S_ASHR_I64:
return AMDGPU::V_ASHR_I64_e64;
6186 case AMDGPU::S_LSHL_B32:
return AMDGPU::V_LSHL_B32_e32;
6187 case AMDGPU::S_LSHL_B64:
return AMDGPU::V_LSHL_B64_e64;
6188 case AMDGPU::S_LSHR_B32:
return AMDGPU::V_LSHR_B32_e32;
6189 case AMDGPU::S_LSHR_B64:
return AMDGPU::V_LSHR_B64_e64;
6190 case AMDGPU::S_SEXT_I32_I8:
return AMDGPU::V_BFE_I32_e64;
6191 case AMDGPU::S_SEXT_I32_I16:
return AMDGPU::V_BFE_I32_e64;
6192 case AMDGPU::S_BFE_U32:
return AMDGPU::V_BFE_U32_e64;
6193 case AMDGPU::S_BFE_I32:
return AMDGPU::V_BFE_I32_e64;
6194 case AMDGPU::S_BFM_B32:
return AMDGPU::V_BFM_B32_e64;
6195 case AMDGPU::S_BREV_B32:
return AMDGPU::V_BFREV_B32_e32;
6196 case AMDGPU::S_NOT_B32:
return AMDGPU::V_NOT_B32_e32;
6197 case AMDGPU::S_NOT_B64:
return AMDGPU::V_NOT_B32_e32;
6198 case AMDGPU::S_CMP_EQ_I32:
return AMDGPU::V_CMP_EQ_I32_e64;
6199 case AMDGPU::S_CMP_LG_I32:
return AMDGPU::V_CMP_NE_I32_e64;
6200 case AMDGPU::S_CMP_GT_I32:
return AMDGPU::V_CMP_GT_I32_e64;
6201 case AMDGPU::S_CMP_GE_I32:
return AMDGPU::V_CMP_GE_I32_e64;
6202 case AMDGPU::S_CMP_LT_I32:
return AMDGPU::V_CMP_LT_I32_e64;
6203 case AMDGPU::S_CMP_LE_I32:
return AMDGPU::V_CMP_LE_I32_e64;
6204 case AMDGPU::S_CMP_EQ_U32:
return AMDGPU::V_CMP_EQ_U32_e64;
6205 case AMDGPU::S_CMP_LG_U32:
return AMDGPU::V_CMP_NE_U32_e64;
6206 case AMDGPU::S_CMP_GT_U32:
return AMDGPU::V_CMP_GT_U32_e64;
6207 case AMDGPU::S_CMP_GE_U32:
return AMDGPU::V_CMP_GE_U32_e64;
6208 case AMDGPU::S_CMP_LT_U32:
return AMDGPU::V_CMP_LT_U32_e64;
6209 case AMDGPU::S_CMP_LE_U32:
return AMDGPU::V_CMP_LE_U32_e64;
6210 case AMDGPU::S_CMP_EQ_U64:
return AMDGPU::V_CMP_EQ_U64_e64;
6211 case AMDGPU::S_CMP_LG_U64:
return AMDGPU::V_CMP_NE_U64_e64;
6212 case AMDGPU::S_BCNT1_I32_B32:
return AMDGPU::V_BCNT_U32_B32_e64;
6213 case AMDGPU::S_FF1_I32_B32:
return AMDGPU::V_FFBL_B32_e32;
6214 case AMDGPU::S_FLBIT_I32_B32:
return AMDGPU::V_FFBH_U32_e32;
6215 case AMDGPU::S_FLBIT_I32:
return AMDGPU::V_FFBH_I32_e64;
6216 case AMDGPU::S_CBRANCH_SCC0:
return AMDGPU::S_CBRANCH_VCCZ;
6217 case AMDGPU::S_CBRANCH_SCC1:
return AMDGPU::S_CBRANCH_VCCNZ;
6218 case AMDGPU::S_CVT_F32_I32:
return AMDGPU::V_CVT_F32_I32_e64;
6219 case AMDGPU::S_CVT_F32_U32:
return AMDGPU::V_CVT_F32_U32_e64;
6220 case AMDGPU::S_CVT_I32_F32:
return AMDGPU::V_CVT_I32_F32_e64;
6221 case AMDGPU::S_CVT_U32_F32:
return AMDGPU::V_CVT_U32_F32_e64;
6222 case AMDGPU::S_CVT_F32_F16:
6223 case AMDGPU::S_CVT_HI_F32_F16:
6224 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6225 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6226 case AMDGPU::S_CVT_F16_F32:
6227 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6228 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6229 case AMDGPU::S_CEIL_F32:
return AMDGPU::V_CEIL_F32_e64;
6230 case AMDGPU::S_FLOOR_F32:
return AMDGPU::V_FLOOR_F32_e64;
6231 case AMDGPU::S_TRUNC_F32:
return AMDGPU::V_TRUNC_F32_e64;
6232 case AMDGPU::S_RNDNE_F32:
return AMDGPU::V_RNDNE_F32_e64;
6233 case AMDGPU::S_CEIL_F16:
6234 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6235 : AMDGPU::V_CEIL_F16_fake16_e64;
6236 case AMDGPU::S_FLOOR_F16:
6237 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6238 : AMDGPU::V_FLOOR_F16_fake16_e64;
6239 case AMDGPU::S_TRUNC_F16:
6240 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6241 : AMDGPU::V_TRUNC_F16_fake16_e64;
6242 case AMDGPU::S_RNDNE_F16:
6243 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6244 : AMDGPU::V_RNDNE_F16_fake16_e64;
6245 case AMDGPU::S_ADD_F32:
return AMDGPU::V_ADD_F32_e64;
6246 case AMDGPU::S_SUB_F32:
return AMDGPU::V_SUB_F32_e64;
6247 case AMDGPU::S_MIN_F32:
return AMDGPU::V_MIN_F32_e64;
6248 case AMDGPU::S_MAX_F32:
return AMDGPU::V_MAX_F32_e64;
6249 case AMDGPU::S_MINIMUM_F32:
return AMDGPU::V_MINIMUM_F32_e64;
6250 case AMDGPU::S_MAXIMUM_F32:
return AMDGPU::V_MAXIMUM_F32_e64;
6251 case AMDGPU::S_MUL_F32:
return AMDGPU::V_MUL_F32_e64;
6252 case AMDGPU::S_ADD_F16:
6253 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6254 : AMDGPU::V_ADD_F16_fake16_e64;
6255 case AMDGPU::S_SUB_F16:
6256 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6257 : AMDGPU::V_SUB_F16_fake16_e64;
6258 case AMDGPU::S_MIN_F16:
6259 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6260 : AMDGPU::V_MIN_F16_fake16_e64;
6261 case AMDGPU::S_MAX_F16:
6262 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6263 : AMDGPU::V_MAX_F16_fake16_e64;
6264 case AMDGPU::S_MINIMUM_F16:
6265 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6266 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6267 case AMDGPU::S_MAXIMUM_F16:
6268 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6269 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6270 case AMDGPU::S_MUL_F16:
6271 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6272 : AMDGPU::V_MUL_F16_fake16_e64;
6273 case AMDGPU::S_CVT_PK_RTZ_F16_F32:
return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6274 case AMDGPU::S_FMAC_F32:
return AMDGPU::V_FMAC_F32_e64;
6275 case AMDGPU::S_FMAC_F16:
6276 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6277 : AMDGPU::V_FMAC_F16_fake16_e64;
6278 case AMDGPU::S_FMAMK_F32:
return AMDGPU::V_FMAMK_F32;
6279 case AMDGPU::S_FMAAK_F32:
return AMDGPU::V_FMAAK_F32;
6280 case AMDGPU::S_CMP_LT_F32:
return AMDGPU::V_CMP_LT_F32_e64;
6281 case AMDGPU::S_CMP_EQ_F32:
return AMDGPU::V_CMP_EQ_F32_e64;
6282 case AMDGPU::S_CMP_LE_F32:
return AMDGPU::V_CMP_LE_F32_e64;
6283 case AMDGPU::S_CMP_GT_F32:
return AMDGPU::V_CMP_GT_F32_e64;
6284 case AMDGPU::S_CMP_LG_F32:
return AMDGPU::V_CMP_LG_F32_e64;
6285 case AMDGPU::S_CMP_GE_F32:
return AMDGPU::V_CMP_GE_F32_e64;
6286 case AMDGPU::S_CMP_O_F32:
return AMDGPU::V_CMP_O_F32_e64;
6287 case AMDGPU::S_CMP_U_F32:
return AMDGPU::V_CMP_U_F32_e64;
6288 case AMDGPU::S_CMP_NGE_F32:
return AMDGPU::V_CMP_NGE_F32_e64;
6289 case AMDGPU::S_CMP_NLG_F32:
return AMDGPU::V_CMP_NLG_F32_e64;
6290 case AMDGPU::S_CMP_NGT_F32:
return AMDGPU::V_CMP_NGT_F32_e64;
6291 case AMDGPU::S_CMP_NLE_F32:
return AMDGPU::V_CMP_NLE_F32_e64;
6292 case AMDGPU::S_CMP_NEQ_F32:
return AMDGPU::V_CMP_NEQ_F32_e64;
6293 case AMDGPU::S_CMP_NLT_F32:
return AMDGPU::V_CMP_NLT_F32_e64;
6294 case AMDGPU::S_CMP_LT_F16:
6295 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6296 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6297 case AMDGPU::S_CMP_EQ_F16:
6298 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6299 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6300 case AMDGPU::S_CMP_LE_F16:
6301 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6302 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6303 case AMDGPU::S_CMP_GT_F16:
6304 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6305 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6306 case AMDGPU::S_CMP_LG_F16:
6307 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6308 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6309 case AMDGPU::S_CMP_GE_F16:
6310 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6311 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6312 case AMDGPU::S_CMP_O_F16:
6313 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6314 : AMDGPU::V_CMP_O_F16_fake16_e64;
6315 case AMDGPU::S_CMP_U_F16:
6316 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6317 : AMDGPU::V_CMP_U_F16_fake16_e64;
6318 case AMDGPU::S_CMP_NGE_F16:
6319 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6320 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6321 case AMDGPU::S_CMP_NLG_F16:
6322 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6323 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6324 case AMDGPU::S_CMP_NGT_F16:
6325 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6326 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6327 case AMDGPU::S_CMP_NLE_F16:
6328 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6329 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6330 case AMDGPU::S_CMP_NEQ_F16:
6331 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6332 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6333 case AMDGPU::S_CMP_NLT_F16:
6334 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6335 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6336 case AMDGPU::V_S_EXP_F32_e64:
return AMDGPU::V_EXP_F32_e64;
6337 case AMDGPU::V_S_EXP_F16_e64:
6338 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6339 : AMDGPU::V_EXP_F16_fake16_e64;
6340 case AMDGPU::V_S_LOG_F32_e64:
return AMDGPU::V_LOG_F32_e64;
6341 case AMDGPU::V_S_LOG_F16_e64:
6342 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6343 : AMDGPU::V_LOG_F16_fake16_e64;
6344 case AMDGPU::V_S_RCP_F32_e64:
return AMDGPU::V_RCP_F32_e64;
6345 case AMDGPU::V_S_RCP_F16_e64:
6346 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6347 : AMDGPU::V_RCP_F16_fake16_e64;
6348 case AMDGPU::V_S_RSQ_F32_e64:
return AMDGPU::V_RSQ_F32_e64;
6349 case AMDGPU::V_S_RSQ_F16_e64:
6350 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6351 : AMDGPU::V_RSQ_F16_fake16_e64;
6352 case AMDGPU::V_S_SQRT_F32_e64:
return AMDGPU::V_SQRT_F32_e64;
6353 case AMDGPU::V_S_SQRT_F16_e64:
6354 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6355 : AMDGPU::V_SQRT_F16_fake16_e64;
6358 "Unexpected scalar opcode without corresponding vector one!");
6407 "Not a whole wave func");
6410 if (
MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6411 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6418 unsigned OpNo)
const {
6420 if (
MI.isVariadic() || OpNo >=
Desc.getNumOperands() ||
6421 Desc.operands()[OpNo].RegClass == -1) {
6424 if (Reg.isVirtual()) {
6428 return RI.getPhysRegBaseClass(Reg);
6431 int16_t RegClass = getOpRegClassID(
Desc.operands()[OpNo]);
6432 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6437 constexpr AMDGPU::OpName OpNames[] = {
6438 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6441 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
I]);
6442 if (
static_cast<unsigned>(SrcIdx) == OpIdx)
6454 unsigned RCID = getOpRegClassID(
get(
MI.getOpcode()).operands()[OpIdx]);
6456 unsigned Size = RI.getRegSizeInBits(*RC);
6457 unsigned Opcode = (
Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6458 :
Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6459 : AMDGPU::V_MOV_B32_e32;
6461 Opcode = AMDGPU::COPY;
6462 else if (RI.isSGPRClass(RC))
6463 Opcode = (
Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6488 .
addImm(AMDGPU::sub0_sub1)
6490 .
addImm(AMDGPU::sub2_sub3);
6503 return RI.getSubReg(SuperReg.
getReg(), SubIdx);
6509 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.
getSubReg(), SubIdx);
6520 if (SubIdx == AMDGPU::sub0)
6522 if (SubIdx == AMDGPU::sub1)
6534void SIInstrInfo::swapOperands(
MachineInstr &Inst)
const {
6550 if (Reg.isPhysical())
6557 RI.getLargestLegalSuperClass(RC, MRI.
getMF());
6560 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.
getSubReg()) !=
nullptr;
6563 return RI.getCommonSubClass(DRC, RC) !=
nullptr;
6570 unsigned Opc =
MI.getOpcode();
6573 if (MO.
isReg() && RI.isSGPRReg(MRI, MO.
getReg()) &&
6583 bool IsAGPR = RI.isAGPR(MRI, MO.
getReg());
6584 if (IsAGPR && !ST.hasMAIInsts())
6590 const int VDstIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
6591 const int DataIdx = AMDGPU::getNamedOperandIdx(
6592 Opc,
isDS(
Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6593 if ((
int)OpIdx == VDstIdx && DataIdx != -1 &&
6594 MI.getOperand(DataIdx).isReg() &&
6595 RI.isAGPR(MRI,
MI.getOperand(DataIdx).getReg()) != IsAGPR)
6597 if ((
int)OpIdx == DataIdx) {
6598 if (VDstIdx != -1 &&
6599 RI.isAGPR(MRI,
MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6602 const int Data1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
6603 if (Data1Idx != -1 &&
MI.getOperand(Data1Idx).isReg() &&
6604 RI.isAGPR(MRI,
MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6609 if (
Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6610 (
int)OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) &&
6611 RI.isSGPRReg(MRI, MO.
getReg()))
6614 if (ST.hasFlatScratchHiInB64InstHazard() &&
6621 if (
Opc == AMDGPU::S_BITCMP0_B64 ||
Opc == AMDGPU::S_BITCMP1_B64)
6624 if (!ST.hasDPPSrc1SGPR() &&
isDPP(
MI) && RI.isSGPRReg(MRI, MO.
getReg()) &&
6625 (
int)OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1))
6645 constexpr unsigned NumOps = 3;
6646 constexpr AMDGPU::OpName OpNames[
NumOps * 2] = {
6647 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6648 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6649 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6654 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[SrcN]);
6657 MO = &
MI.getOperand(SrcIdx);
6660 if (!MO->
isReg() || !RI.isSGPRReg(MRI, MO->
getReg()))
6664 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
NumOps + SrcN]);
6668 unsigned Mods =
MI.getOperand(ModsIdx).getImm();
6672 return !OpSel && !OpSelHi;
6681 int64_t RegClass = getOpRegClassID(OpInfo);
6683 RegClass != -1 ? RI.getRegClass(RegClass) :
nullptr;
6685 MO = &
MI.getOperand(OpIdx);
6689 if (
isVALU(
MI,
true) && !IsInlineConst &&
6693 int ConstantBusLimit = ST.getConstantBusLimit(
MI.getOpcode());
6694 int LiteralLimit = !
isVOP3(
MI) || ST.hasVOP3Literal() ? 1 : 0;
6698 if (!LiteralLimit--)
6708 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6716 if (--ConstantBusLimit <= 0)
6728 if (!LiteralLimit--)
6730 if (--ConstantBusLimit <= 0)
6736 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6740 if (!
Op.isReg() && !
Op.isFI() && !
Op.isRegMask() &&
6742 !
Op.isIdenticalTo(*MO))
6752 }
else if (IsInlineConst && ST.hasNoF16PseudoScalarTransInlineConstants() &&
6767 bool Is64BitOp = Is64BitFPOp ||
6775 (!ST.has64BitLiterals() || InstDesc.
getSize() != 4))
6784 if (!Is64BitFPOp && (int32_t)
Imm < 0 &&
6802 bool IsGFX950Only = ST.hasGFX950Insts();
6803 bool IsGFX940Only = ST.hasGFX940Insts();
6805 if (!IsGFX950Only && !IsGFX940Only)
6823 unsigned Opcode =
MI.getOpcode();
6825 case AMDGPU::V_CVT_PK_BF8_F32_e64:
6826 case AMDGPU::V_CVT_PK_FP8_F32_e64:
6827 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
6828 case AMDGPU::V_MQSAD_U32_U8_e64:
6829 case AMDGPU::V_PK_ADD_F16:
6830 case AMDGPU::V_PK_ADD_F32:
6831 case AMDGPU::V_PK_ADD_I16:
6832 case AMDGPU::V_PK_ADD_U16:
6833 case AMDGPU::V_PK_ASHRREV_I16:
6834 case AMDGPU::V_PK_FMA_F16:
6835 case AMDGPU::V_PK_FMA_F32:
6836 case AMDGPU::V_PK_FMAC_F16_e32:
6837 case AMDGPU::V_PK_FMAC_F16_e64:
6838 case AMDGPU::V_PK_LSHLREV_B16:
6839 case AMDGPU::V_PK_LSHRREV_B16:
6840 case AMDGPU::V_PK_MAD_I16:
6841 case AMDGPU::V_PK_MAD_U16:
6842 case AMDGPU::V_PK_MAX_F16:
6843 case AMDGPU::V_PK_MAX_I16:
6844 case AMDGPU::V_PK_MAX_U16:
6845 case AMDGPU::V_PK_MIN_F16:
6846 case AMDGPU::V_PK_MIN_I16:
6847 case AMDGPU::V_PK_MIN_U16:
6848 case AMDGPU::V_PK_MOV_B32:
6849 case AMDGPU::V_PK_MUL_F16:
6850 case AMDGPU::V_PK_MUL_F32:
6851 case AMDGPU::V_PK_MUL_LO_U16:
6852 case AMDGPU::V_PK_SUB_I16:
6853 case AMDGPU::V_PK_SUB_U16:
6854 case AMDGPU::V_QSAD_PK_U16_U8_e64:
6863 unsigned Opc =
MI.getOpcode();
6866 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
6869 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
6875 if (HasImplicitSGPR && ST.getConstantBusLimit(
Opc) <= 1 && Src0.
isReg() &&
6876 RI.isSGPRReg(MRI, Src0.
getReg()))
6882 if (
Opc == AMDGPU::V_WRITELANE_B32) {
6884 if (Src0.
isReg() && RI.isVGPR(MRI, Src0.
getReg())) {
6890 if (Src1.
isReg() && RI.isVGPR(MRI, Src1.
getReg())) {
6901 if (
Opc == AMDGPU::V_FMAC_F32_e32 ||
Opc == AMDGPU::V_FMAC_F16_e32) {
6902 int Src2Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2);
6903 if (!RI.isVGPR(MRI,
MI.getOperand(Src2Idx).getReg()))
6915 if (
Opc == AMDGPU::V_READLANE_B32 && Src1.
isReg() &&
6916 RI.isVGPR(MRI, Src1.
getReg())) {
6929 if (HasImplicitSGPR || !
MI.isCommutable()) {
6946 if (CommutedOpc == -1) {
6951 MI.setDesc(
get(CommutedOpc));
6955 bool Src0Kill = Src0.
isKill();
6959 else if (Src1.
isReg()) {
6974 unsigned Opc =
MI.getOpcode();
6977 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0),
6978 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1),
6979 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2)
6982 if (
Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
6983 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
6984 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
6985 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
6986 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
6987 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
6988 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
6998 if (VOP3Idx[2] != -1) {
7010 int ConstantBusLimit = ST.getConstantBusLimit(
Opc);
7011 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
7013 Register SGPRReg = findUsedSGPR(
MI, VOP3Idx);
7015 SGPRsUsed.
insert(SGPRReg);
7019 for (
int Idx : VOP3Idx) {
7028 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
7040 if (!RI.isSGPRClass(RI.getRegClassForReg(MRI, MO.
getReg())))
7047 if (ConstantBusLimit > 0) {
7059 if ((
Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64) &&
7060 !RI.isVGPR(MRI,
MI.getOperand(VOP3Idx[2]).getReg()))
7066 for (
unsigned I = 0;
I < 3; ++
I) {
7079 SRC = RI.getCommonSubClass(SRC, DstRC);
7082 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
7084 if (RI.hasAGPRs(VRC)) {
7085 VRC = RI.getEquivalentVGPRClass(VRC);
7088 get(TargetOpcode::COPY), NewSrcReg)
7095 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
7101 for (
unsigned i = 0; i < SubRegs; ++i) {
7104 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
7105 .
addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
7111 get(AMDGPU::REG_SEQUENCE), DstReg);
7112 for (
unsigned i = 0; i < SubRegs; ++i) {
7114 MIB.
addImm(RI.getSubRegFromChannel(i));
7127 if (SBase && !RI.isSGPRClass(MRI.
getRegClass(SBase->getReg()))) {
7129 SBase->setReg(SGPR);
7132 if (SOff && !RI.isSGPRReg(MRI, SOff->
getReg())) {
7140 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::saddr);
7141 if (OldSAddrIdx < 0)
7154 if (RI.isSGPRReg(MRI, SAddr.
getReg()))
7157 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
7158 if (NewVAddrIdx < 0)
7161 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr);
7165 if (OldVAddrIdx >= 0) {
7179 if (OldVAddrIdx == NewVAddrIdx) {
7190 assert(OldSAddrIdx == NewVAddrIdx);
7192 if (OldVAddrIdx >= 0) {
7193 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7194 AMDGPU::OpName::vdst_in);
7198 if (NewVDstIn != -1) {
7199 int OldVDstIn = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst_in);
7205 if (NewVDstIn != -1) {
7206 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7247 unsigned OpSubReg =
Op.getSubReg();
7250 RI.getRegClassForReg(MRI, OpReg), OpSubReg);
7257 auto Copy =
BuildMI(InsertMBB,
I,
DL,
get(AMDGPU::COPY), DstReg)
7258 .
addReg(OpReg, {}, OpSubReg);
7260 Op.setSubReg(AMDGPU::NoSubRegister);
7267 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7270 bool ImpDef = Def->isImplicitDef();
7271 while (!ImpDef && Def && Def->isCopy()) {
7272 if (Def->getOperand(1).getReg().isPhysical())
7275 ImpDef = Def && Def->isImplicitDef();
7277 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7293 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7298 bool UseNewExecInstructions =
7307 if (UseNewExecInstructions) {
7342 for (
auto [Idx, ScalarOp] :
enumerate(ScalarOps)) {
7343 unsigned RegSize =
TRI->getRegSizeInBits(ScalarOp->getReg(), MRI);
7344 unsigned NumSubRegs =
RegSize / 32;
7345 Register VScalarOp = ScalarOp->getReg();
7348 TII.getRegClass(
TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7350 if (NumSubRegs == 1) {
7353 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7354 Common != VScalarOpRC) {
7361 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7364 if (UseNewExecInstructions) {
7366 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7369 if (
I == LoopBB.
end())
7374 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7380 CondReg = NewCondReg;
7391 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7392 ScalarOp->setReg(CurReg);
7395 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7396 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7398 ScalarOp->setReg(PhySGPRs[Idx]);
7400 ScalarOp->setIsKill();
7404 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7405 "Unhandled register size");
7407 for (
unsigned Idx = 0; Idx < NumSubRegs; Idx += 2) {
7414 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7415 .
addReg(VScalarOp, VScalarOpUndef,
TRI->getSubRegFromChannel(Idx));
7418 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7419 .
addReg(VScalarOp, VScalarOpUndef,
7420 TRI->getSubRegFromChannel(Idx + 1));
7427 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7434 NumSubRegs <= 2 ? 0 :
TRI->getSubRegFromChannel(Idx, 2);
7436 if (UseNewExecInstructions) {
7438 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7440 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7441 if (
I == LoopBB.
end())
7445 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7447 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7451 CondReg = NewCondReg;
7462 const auto *SScalarOpRC =
7468 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7469 unsigned Channel = 0;
7470 for (
Register Piece : ReadlanePieces) {
7471 Merge.addReg(Piece).addImm(
TRI->getSubRegFromChannel(Channel++));
7475 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7476 ScalarOp->setReg(SScalarOp);
7478 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7479 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7481 ScalarOp->setReg(PhySGPRs[Idx]);
7483 ScalarOp->setIsKill();
7491 if (!UseNewExecInstructions) {
7503 if (UseNewExecInstructions) {
7527 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.
size()) &&
7528 "Physical SGPRs must be empty or match the number of scalar operands");
7534 if (!Begin.isValid())
7536 if (!End.isValid()) {
7542 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7551 std::numeric_limits<unsigned>::max()) !=
7569 for (
auto I = Begin;
I != AfterMI;
I++) {
7570 for (
auto &MO :
I->all_uses())
7606 for (
auto &Succ : RemainderBB->
successors()) {
7631static std::tuple<unsigned, unsigned>
7639 TII.buildExtractSubReg(
MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7640 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7647 uint64_t RsrcDataFormat =
TII.getDefaultRsrcDataFormat();
7664 .
addImm(AMDGPU::sub0_sub1)
7670 return std::tuple(RsrcPtr, NewSRsrc);
7681 if (ST.useRealTrue16Insts())
7711 if (
MI.getOpcode() == AMDGPU::PHI) {
7713 assert(!RI.isSGPRClass(VRC));
7716 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7718 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7734 if (
MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7737 if (RI.hasVGPRs(DstRC)) {
7741 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7743 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7761 if (
MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7766 if (DstRC != Src0RC) {
7775 if (
MI.getOpcode() == AMDGPU::SI_INIT_M0) {
7777 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7783 if (
MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
7784 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
7785 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
7786 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
7787 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
7788 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
7789 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
7791 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7804 ? AMDGPU::OpName::rsrc
7805 : AMDGPU::OpName::srsrc;
7810 AMDGPU::OpName SampOpName =
7811 isMIMG(
MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
7820 if (
MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
7828 if (
MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
7832 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src0);
7842 if (
MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
7843 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
7844 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
7845 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
7847 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7854 bool isSoffsetLegal =
true;
7856 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::soffset);
7857 if (SoffsetIdx != -1) {
7861 isSoffsetLegal =
false;
7865 bool isRsrcLegal =
true;
7867 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::srsrc);
7868 if (RsrcIdx != -1) {
7870 if (Rsrc->
isReg() && !RI.isSGPRReg(MRI, Rsrc->
getReg()))
7871 isRsrcLegal =
false;
7875 if (isRsrcLegal && isSoffsetLegal)
7903 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
7907 unsigned RsrcPtr, NewSRsrc;
7914 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
7915 .addReg(VAddr->
getReg(), {}, AMDGPU::sub0)
7921 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
7922 .addReg(VAddr->
getReg(), {}, AMDGPU::sub1)
7935 }
else if (!VAddr && ST.hasAddr64()) {
7939 "FIXME: Need to emit flat atomics here");
7941 unsigned RsrcPtr, NewSRsrc;
7967 MIB.
addImm(CPol->getImm());
7972 MIB.
addImm(TFE->getImm());
7992 MI.removeFromParent();
7997 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
7998 .addImm(AMDGPU::sub0)
7999 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
8000 .addImm(AMDGPU::sub1);
8003 if (!isSoffsetLegal) {
8014 if (!isSoffsetLegal) {
8023 if (InSet.insert(
MI).second)
8027 AMDGPU::getNamedOperandIdx(
MI->getOpcode(), AMDGPU::OpName::srsrc);
8028 if (RsrcIdx != -1) {
8029 DeferredList.insert(
MI);
8034 return DeferredList.contains(
MI);
8044 if (!ST.useRealTrue16Insts())
8047 unsigned Opcode =
MI.getOpcode();
8050 if (OpIdx >=
MI.getNumExplicitOperands() ||
8051 OpIdx >=
get(Opcode).getNumOperands() ||
8052 get(Opcode).operands()[OpIdx].RegClass == -1)
8056 if (!
Op.isReg() || !
Op.getReg().isVirtual() ||
Op.isDef())
8060 if (!RI.isVGPRClass(CurrRC))
8063 int16_t RCID = getOpRegClassID(
get(Opcode).operands()[OpIdx]);
8065 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
8067 if (
Op.getSubReg() == AMDGPU::NoSubRegister)
8068 Op.setSubReg(AMDGPU::lo16);
8073 RI.getSubRegisterClass(CurrRC,
Op.getSubReg());
8074 if (RI.getMatchingSuperRegClass(ExpectedRC, CurrSRC, AMDGPU::lo16)) {
8084 Op.setReg(NewDstReg);
8085 Op.setSubReg(AMDGPU::NoSubRegister);
8090 for (
unsigned OpIdx = 0; OpIdx <
MI.getNumExplicitOperands(); OpIdx++)
8098 assert(
MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
8099 "This only handle waterfall for SI_CALL_ISEL");
8106 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
8109 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
8114 while (End !=
MBB.end() && End->isCopy() &&
8115 MI->definesRegister(End->getOperand(1).getReg(), &RI))
8125 while (!Worklist.
empty()) {
8131 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
8137 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
8139 "Deferred MachineInstr are not supposed to re-populate worklist");
8142 for (std::pair<MachineInstr *, V2PhysSCopyInfo> &Entry : WaterFalls) {
8143 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
8145 Entry.second.SGPRs);
8148 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
8150 Entry.first->eraseFromParent();
8158 if (SubRegIndices.
size() <= 1) {
8161 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8168 for (int16_t Indice : SubRegIndices) {
8171 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8178 get(AMDGPU::REG_SEQUENCE), DstReg);
8179 for (
unsigned i = 0; i < SubRegIndices.size(); ++i) {
8181 MIB.
addImm(RI.getSubRegFromChannel(i));
8191 if (DstReg == AMDGPU::M0) {
8204 if (
I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
8206 for (
unsigned i = 0; i <
UseMI->getNumOperands(); ++i) {
8207 if (
UseMI->getOperand(i).isReg() &&
8208 UseMI->getOperand(i).getReg() == DstReg) {
8212 V2SCopyInfo.MOs.push_back(MO);
8213 V2SCopyInfo.SGPRs.push_back(DstReg);
8217 }
else if (
I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8218 I->getOperand(0).isReg() &&
8219 I->getOperand(0).getReg() == DstReg) {
8222 }
else if (
I->readsRegister(DstReg, &RI)) {
8224 V2SPhyCopiesToErase[&Inst] =
false;
8226 if (
I->findRegisterDefOperand(DstReg, &RI))
8248 case AMDGPU::S_ADD_I32:
8249 case AMDGPU::S_SUB_I32: {
8253 std::tie(
Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8261 case AMDGPU::S_MUL_U64:
8262 if (ST.useVMulU64Inst()) {
8263 NewOpcode = AMDGPU::V_MUL_U64_e64;
8267 splitScalarSMulU64(Worklist, Inst, MDT);
8271 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8272 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8275 splitScalarSMulPseudo(Worklist, Inst, MDT);
8279 case AMDGPU::S_AND_B64:
8280 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8284 case AMDGPU::S_OR_B64:
8285 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8289 case AMDGPU::S_XOR_B64:
8290 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8294 case AMDGPU::S_NAND_B64:
8295 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8299 case AMDGPU::S_NOR_B64:
8300 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8304 case AMDGPU::S_XNOR_B64:
8305 if (ST.hasDLInsts())
8306 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8308 splitScalar64BitXnor(Worklist, Inst, MDT);
8312 case AMDGPU::S_ANDN2_B64:
8313 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8317 case AMDGPU::S_ORN2_B64:
8318 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8322 case AMDGPU::S_BREV_B64:
8323 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32,
true);
8327 case AMDGPU::S_NOT_B64:
8328 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8332 case AMDGPU::S_BCNT1_I32_B64:
8333 splitScalar64BitBCNT(Worklist, Inst);
8337 case AMDGPU::S_BFE_I64:
8338 splitScalar64BitBFE(Worklist, Inst);
8342 case AMDGPU::S_FLBIT_I32_B64:
8343 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8346 case AMDGPU::S_FF1_I32_B64:
8347 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8351 case AMDGPU::S_LSHL_B32:
8352 if (ST.hasOnlyRevVALUShifts()) {
8353 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8357 case AMDGPU::S_ASHR_I32:
8358 if (ST.hasOnlyRevVALUShifts()) {
8359 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8363 case AMDGPU::S_LSHR_B32:
8364 if (ST.hasOnlyRevVALUShifts()) {
8365 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8369 case AMDGPU::S_LSHL_B64:
8370 if (ST.hasOnlyRevVALUShifts()) {
8372 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8373 : AMDGPU::V_LSHLREV_B64_e64;
8377 case AMDGPU::S_ASHR_I64:
8378 if (ST.hasOnlyRevVALUShifts()) {
8379 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8383 case AMDGPU::S_LSHR_B64:
8384 if (ST.hasOnlyRevVALUShifts()) {
8385 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8390 case AMDGPU::S_ABS_I32:
8391 lowerScalarAbs(Worklist, Inst);
8395 case AMDGPU::S_ABSDIFF_I32:
8396 lowerScalarAbsDiff(Worklist, Inst);
8400 case AMDGPU::S_CBRANCH_SCC0:
8401 case AMDGPU::S_CBRANCH_SCC1: {
8404 bool IsSCC = CondReg == AMDGPU::SCC;
8412 case AMDGPU::S_BFE_U64:
8413 case AMDGPU::S_BFM_B64:
8416 case AMDGPU::S_PACK_LL_B32_B16:
8417 case AMDGPU::S_PACK_LH_B32_B16:
8418 case AMDGPU::S_PACK_HL_B32_B16:
8419 case AMDGPU::S_PACK_HH_B32_B16:
8420 movePackToVALU(Worklist, MRI, Inst);
8424 case AMDGPU::S_XNOR_B32:
8425 lowerScalarXnor(Worklist, Inst);
8429 case AMDGPU::S_NAND_B32:
8430 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8434 case AMDGPU::S_NOR_B32:
8435 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8439 case AMDGPU::S_ANDN2_B32:
8440 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8444 case AMDGPU::S_ORN2_B32:
8445 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8453 case AMDGPU::S_ADD_CO_PSEUDO:
8454 case AMDGPU::S_SUB_CO_PSEUDO: {
8455 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8456 ? AMDGPU::V_ADDC_U32_e64
8457 : AMDGPU::V_SUBB_U32_e64;
8458 const auto *CarryRC = RI.getWaveMaskRegClass();
8480 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8484 case AMDGPU::S_UADDO_PSEUDO:
8485 case AMDGPU::S_USUBO_PSEUDO: {
8491 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8492 ? AMDGPU::V_ADD_CO_U32_e64
8493 : AMDGPU::V_SUB_CO_U32_e64;
8505 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8509 case AMDGPU::S_LSHL1_ADD_U32:
8510 case AMDGPU::S_LSHL2_ADD_U32:
8511 case AMDGPU::S_LSHL3_ADD_U32:
8512 case AMDGPU::S_LSHL4_ADD_U32: {
8516 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8517 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8518 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8532 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8536 case AMDGPU::S_CSELECT_B32:
8537 case AMDGPU::S_CSELECT_B64:
8538 lowerSelect(Worklist, Inst, MDT);
8541 case AMDGPU::S_CMP_EQ_I32:
8542 case AMDGPU::S_CMP_LG_I32:
8543 case AMDGPU::S_CMP_GT_I32:
8544 case AMDGPU::S_CMP_GE_I32:
8545 case AMDGPU::S_CMP_LT_I32:
8546 case AMDGPU::S_CMP_LE_I32:
8547 case AMDGPU::S_CMP_EQ_U32:
8548 case AMDGPU::S_CMP_LG_U32:
8549 case AMDGPU::S_CMP_GT_U32:
8550 case AMDGPU::S_CMP_GE_U32:
8551 case AMDGPU::S_CMP_LT_U32:
8552 case AMDGPU::S_CMP_LE_U32:
8553 case AMDGPU::S_CMP_EQ_U64:
8554 case AMDGPU::S_CMP_LG_U64:
8555 case AMDGPU::S_CMP_LT_F32:
8556 case AMDGPU::S_CMP_EQ_F32:
8557 case AMDGPU::S_CMP_LE_F32:
8558 case AMDGPU::S_CMP_GT_F32:
8559 case AMDGPU::S_CMP_LG_F32:
8560 case AMDGPU::S_CMP_GE_F32:
8561 case AMDGPU::S_CMP_O_F32:
8562 case AMDGPU::S_CMP_U_F32:
8563 case AMDGPU::S_CMP_NGE_F32:
8564 case AMDGPU::S_CMP_NLG_F32:
8565 case AMDGPU::S_CMP_NGT_F32:
8566 case AMDGPU::S_CMP_NLE_F32:
8567 case AMDGPU::S_CMP_NEQ_F32:
8568 case AMDGPU::S_CMP_NLT_F32: {
8573 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8587 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8591 case AMDGPU::S_CMP_LT_F16:
8592 case AMDGPU::S_CMP_EQ_F16:
8593 case AMDGPU::S_CMP_LE_F16:
8594 case AMDGPU::S_CMP_GT_F16:
8595 case AMDGPU::S_CMP_LG_F16:
8596 case AMDGPU::S_CMP_GE_F16:
8597 case AMDGPU::S_CMP_O_F16:
8598 case AMDGPU::S_CMP_U_F16:
8599 case AMDGPU::S_CMP_NGE_F16:
8600 case AMDGPU::S_CMP_NLG_F16:
8601 case AMDGPU::S_CMP_NGT_F16:
8602 case AMDGPU::S_CMP_NLE_F16:
8603 case AMDGPU::S_CMP_NEQ_F16:
8604 case AMDGPU::S_CMP_NLT_F16: {
8626 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8630 case AMDGPU::S_CVT_HI_F32_F16: {
8633 if (ST.useRealTrue16Insts()) {
8638 .
addReg(TmpReg, {}, AMDGPU::hi16)
8654 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8658 case AMDGPU::S_MINIMUM_F32:
8659 case AMDGPU::S_MAXIMUM_F32: {
8671 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8675 case AMDGPU::S_MINIMUM_F16:
8676 case AMDGPU::S_MAXIMUM_F16: {
8678 ? &AMDGPU::VGPR_16RegClass
8679 : &AMDGPU::VGPR_32RegClass);
8690 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8694 case AMDGPU::V_S_EXP_F16_e64:
8695 case AMDGPU::V_S_LOG_F16_e64:
8696 case AMDGPU::V_S_RCP_F16_e64:
8697 case AMDGPU::V_S_RSQ_F16_e64:
8698 case AMDGPU::V_S_SQRT_F16_e64: {
8700 ? &AMDGPU::VGPR_16RegClass
8701 : &AMDGPU::VGPR_32RegClass);
8712 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8718 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8726 if (NewOpcode == Opcode) {
8733 V2SPhyCopiesToErase);
8741 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8748 addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist);
8754 RI.composeSubRegIndices(SrcSubReg, UseMO.getSubReg()));
8755 UseMO.setReg(NewDstReg);
8774 unsigned OpIdx =
UseMI.getOperandNo(&UseMO);
8787 if (ST.useRealTrue16Insts() && Inst.
isCopy() &&
8791 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
8797 get(AMDGPU::REG_SEQUENCE), NewDstReg)
8804 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8806 }
else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
8811 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8819 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8829 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8830 AMDGPU::OpName::src0_modifiers) >= 0)
8834 NewInstr->addOperand(Src);
8837 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
8840 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
8842 NewInstr.addImm(
Size);
8843 }
else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
8847 }
else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
8852 "Scalar BFE is only implemented for constant width and offset");
8860 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8861 AMDGPU::OpName::src1_modifiers) >= 0)
8863 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
8865 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8866 AMDGPU::OpName::src2_modifiers) >= 0)
8868 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
8870 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
8872 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
8874 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
8880 NewInstr->addOperand(
Op);
8887 if (
Op.getReg() == AMDGPU::SCC) {
8889 if (
Op.isDef() && !
Op.isDead())
8890 addSCCDefUsersToVALUWorklist(
Op, Inst, Worklist);
8892 addSCCDefsToVALUWorklist(NewInstr, Worklist);
8897 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
8898 Register DstReg = NewInstr->getOperand(0).getReg();
8911 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8915std::pair<bool, MachineBasicBlock *>
8918 if (ST.hasAddNoCarryInsts()) {
8930 assert(
Opc == AMDGPU::S_ADD_I32 ||
Opc == AMDGPU::S_SUB_I32);
8932 unsigned NewOpc =
Opc == AMDGPU::S_ADD_I32 ?
8933 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
8944 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8945 return std::pair(
true, NewBB);
8948 return std::pair(
false,
nullptr);
8965 bool IsSCC = (CondReg == AMDGPU::SCC);
8973 for (MachineOperand &UseMO :
8975 MachineInstr &
UseMI = *UseMO.getParent();
8976 switch (
UseMI.getOpcode()) {
8977 case AMDGPU::V_CNDMASK_B16_fake16_e32:
8978 case AMDGPU::V_CNDMASK_B16_fake16_e64:
8979 case AMDGPU::V_CNDMASK_B16_t16_e32:
8980 case AMDGPU::V_CNDMASK_B16_t16_e64:
8981 case AMDGPU::V_CNDMASK_B32_e32:
8982 case AMDGPU::V_CNDMASK_B32_e64:
8983 case AMDGPU::V_CNDMASK_B64_PSEUDO:
8984 if (UseMO.isImplicit() ||
8986 UseMO.setReg(CondReg);
9000 bool CopyFound =
false;
9001 for (MachineInstr &CandI :
9004 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) !=
9006 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
9008 .
addReg(CandI.getOperand(1).getReg());
9020 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
9029 MachineInstr *NewInst;
9030 if (Inst.
getOpcode() == AMDGPU::S_CSELECT_B32) {
9031 NewInst =
BuildMI(
MBB, MII,
DL,
get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
9046 addUsersToMoveToVALUWorklist(NewDestReg, MRI, Worklist);
9061 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
9062 : AMDGPU::V_SUB_CO_U32_e32;
9073 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9090 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
9091 : AMDGPU::V_SUB_CO_U32_e32;
9104 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9118 if (ST.hasDLInsts()) {
9128 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9134 bool Src0IsSGPR = Src0.
isReg() &&
9136 bool Src1IsSGPR = Src1.
isReg() &&
9150 }
else if (Src1IsSGPR) {
9168 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9174 unsigned Opcode)
const {
9198 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9203 unsigned Opcode)
const {
9227 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9242 const MCInstrDesc &InstDesc =
get(Opcode);
9245 &AMDGPU::SGPR_32RegClass;
9248 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9251 AMDGPU::sub0, Src0SubRC);
9256 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9259 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0).
add(SrcReg0Sub0);
9262 AMDGPU::sub1, Src0SubRC);
9265 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1).
add(SrcReg0Sub1);
9279 Worklist.
insert(&LoHalf);
9280 Worklist.
insert(&HiHalf);
9286 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9310 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9311 if (RI.isSGPRClass(Src0SubRC))
9312 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9314 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9315 if (RI.isSGPRClass(Src1SubRC))
9316 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9320 MachineOperand Op0L =
9322 MachineOperand Op1L =
9324 MachineOperand Op0H =
9326 MachineOperand Op1H =
9345 MachineInstr *Op1L_Op0H =
9351 MachineInstr *Op1H_Op0L =
9357 MachineInstr *Carry =
9362 MachineInstr *LoHalf =
9372 MachineInstr *HiHalf =
9395 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9419 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9420 if (RI.isSGPRClass(Src0SubRC))
9421 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9423 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9424 if (RI.isSGPRClass(Src1SubRC))
9425 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9429 MachineOperand Op0L =
9431 MachineOperand Op1L =
9435 unsigned NewOpc =
Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9436 ? AMDGPU::V_MUL_HI_U32_e64
9437 : AMDGPU::V_MUL_HI_I32_e64;
9438 MachineInstr *HiHalf =
9441 MachineInstr *LoHalf =
9460 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9476 const MCInstrDesc &InstDesc =
get(Opcode);
9479 &AMDGPU::SGPR_32RegClass;
9482 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9485 &AMDGPU::SGPR_32RegClass;
9488 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9491 AMDGPU::sub0, Src0SubRC);
9493 AMDGPU::sub0, Src1SubRC);
9495 AMDGPU::sub1, Src0SubRC);
9497 AMDGPU::sub1, Src1SubRC);
9502 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9505 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0)
9510 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1)
9523 Worklist.
insert(&LoHalf);
9524 Worklist.
insert(&HiHalf);
9527 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9547 MachineOperand* Op0;
9548 MachineOperand* Op1;
9550 if (Src0.
isReg() && RI.isSGPRReg(MRI, Src0.
getReg())) {
9583 const MCInstrDesc &InstDesc =
get(AMDGPU::V_BCNT_U32_B32_e64);
9586 &AMDGPU::SGPR_32RegClass;
9592 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9595 AMDGPU::sub0, SrcSubRC);
9597 AMDGPU::sub1, SrcSubRC);
9607 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9626 Offset == 0 &&
"Not implemented");
9649 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9659 .
addReg(Src.getReg(), {}, AMDGPU::sub0);
9662 .
addReg(Src.getReg(), {}, AMDGPU::sub0)
9668 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9687 const MCInstrDesc &InstDesc =
get(Opcode);
9689 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9692 Src.isReg() ? MRI.
getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9694 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9696 MachineOperand SrcRegSub0 =
9698 MachineOperand SrcRegSub1 =
9712 .
addReg(IsCtlz ? MidReg1 : MidReg2);
9716 .
addReg(IsCtlz ? MidReg2 : MidReg1);
9720 addUsersToMoveToVALUWorklist(MidReg4, MRI, Worklist);
9723void SIInstrInfo::addUsersToMoveToVALUWorklist(
9727 MachineInstr &
UseMI = *MO.getParent();
9731 switch (
UseMI.getOpcode()) {
9734 case AMDGPU::SOFT_WQM:
9735 case AMDGPU::STRICT_WWM:
9736 case AMDGPU::STRICT_WQM:
9737 case AMDGPU::REG_SEQUENCE:
9739 case AMDGPU::INSERT_SUBREG:
9742 OpNo = MO.getOperandNo();
9749 if (!RI.hasVectorRegisters(OpRC))
9766 if (ST.useRealTrue16Insts()) {
9768 if (!Src0.
isReg() || !RI.isVGPR(MRI, Src0.
getReg())) {
9771 get(Src0.
isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
9777 if (!Src1.
isReg() || !RI.isVGPR(MRI, Src1.
getReg())) {
9780 get(Src1.
isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
9789 auto NewMI =
BuildMI(*
MBB, Inst,
DL,
get(AMDGPU::REG_SEQUENCE), ResultReg);
9791 case AMDGPU::S_PACK_LL_B32_B16:
9793 .addReg(SrcReg0, {},
9794 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9795 .addImm(AMDGPU::lo16)
9796 .addReg(SrcReg1, {},
9797 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9798 .addImm(AMDGPU::hi16);
9800 case AMDGPU::S_PACK_LH_B32_B16:
9802 .addReg(SrcReg0, {},
9803 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9804 .addImm(AMDGPU::lo16)
9805 .addReg(SrcReg1, {}, AMDGPU::hi16)
9806 .addImm(AMDGPU::hi16);
9808 case AMDGPU::S_PACK_HL_B32_B16:
9809 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9810 .addImm(AMDGPU::lo16)
9811 .addReg(SrcReg1, {},
9812 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9813 .addImm(AMDGPU::hi16);
9815 case AMDGPU::S_PACK_HH_B32_B16:
9816 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9817 .addImm(AMDGPU::lo16)
9818 .addReg(SrcReg1, {}, AMDGPU::hi16)
9819 .addImm(AMDGPU::hi16);
9827 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9832 case AMDGPU::S_PACK_LL_B32_B16: {
9851 case AMDGPU::S_PACK_LH_B32_B16: {
9861 case AMDGPU::S_PACK_HL_B32_B16: {
9872 case AMDGPU::S_PACK_HH_B32_B16: {
9892 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9901 assert(
Op.isReg() &&
Op.getReg() == AMDGPU::SCC &&
Op.isDef() &&
9902 !
Op.isDead() &&
Op.getParent() == &SCCDefInst);
9903 SmallVector<MachineInstr *, 4> CopyToDelete;
9906 for (MachineInstr &
MI :
9910 int SCCIdx =
MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI,
false);
9914 Register DestReg =
MI.getOperand(0).getReg();
9921 MI.getOperand(SCCIdx).setReg(NewCond);
9927 if (
MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) != -1)
9930 for (
auto &Copy : CopyToDelete)
9931 Copy->eraseFromParent();
9939void SIInstrInfo::addSCCDefsToVALUWorklist(
MachineInstr *SCCUseInst,
9945 for (MachineInstr &
MI :
9948 if (
MI.modifiesRegister(AMDGPU::VCC, &RI))
9950 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
9967 case AMDGPU::REG_SEQUENCE:
9968 case AMDGPU::INSERT_SUBREG:
9970 case AMDGPU::SOFT_WQM:
9971 case AMDGPU::STRICT_WWM:
9972 case AMDGPU::STRICT_WQM: {
9974 if (RI.isAGPRClass(SrcRC)) {
9975 if (RI.isAGPRClass(NewDstRC))
9980 case AMDGPU::REG_SEQUENCE:
9981 case AMDGPU::INSERT_SUBREG:
9982 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
9985 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
9991 if (!RI.isSGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
9994 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10008 int OpIndices[3])
const {
10009 const MCInstrDesc &
Desc =
MI.getDesc();
10027 for (
unsigned i = 0; i < 3; ++i) {
10028 int Idx = OpIndices[i];
10032 const MachineOperand &MO =
MI.getOperand(Idx);
10039 RI.getRegClass(getOpRegClassID(
Desc.operands()[Idx]));
10040 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
10041 if (IsRequiredSGPR)
10047 if (RI.isSGPRClass(RegRC))
10048 UsedSGPRs[i] =
Reg;
10064 if (UsedSGPRs[0]) {
10065 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
10066 SGPRReg = UsedSGPRs[0];
10069 if (!SGPRReg && UsedSGPRs[1]) {
10070 if (UsedSGPRs[1] == UsedSGPRs[2])
10071 SGPRReg = UsedSGPRs[1];
10078 AMDGPU::OpName OperandName)
const {
10079 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
10082 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OperandName);
10086 return &
MI.getOperand(Idx);
10100 if (ST.isAmdHsaOS()) {
10103 RsrcDataFormat |= (1ULL << 56);
10108 RsrcDataFormat |= (2ULL << 59);
10111 return RsrcDataFormat;
10121 uint64_t EltSizeValue =
Log2_32(ST.getMaxPrivateElementSize(
true)) - 1;
10126 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
10133 Rsrc23 &=
~AMDGPU::RSRC_DATA_FORMAT;
10139 unsigned Opc =
MI.getOpcode();
10145 return get(
Opc).mayLoad() &&
10152 if (!Addr || !Addr->
isFI())
10161 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::vdata);
10163 return MI.getOperand(VDataIdx).getReg();
10173 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::data);
10175 return MI.getOperand(DataIdx).getReg();
10196 if (!
MI.mayStore())
10209 unsigned Opc =
MI.getOpcode();
10211 unsigned DescSize =
Desc.getSize();
10216 unsigned Size = DescSize;
10220 if (
MI.isBranch() && ST.hasOffset3fBug())
10231 bool HasLiteral =
false;
10232 unsigned LiteralSize = 4;
10233 for (
int I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I) {
10238 if (ST.has64BitLiterals()) {
10239 switch (OpInfo.OperandType) {
10264 return HasLiteral ? DescSize + LiteralSize : DescSize;
10269 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
10273 int RSrcIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::srsrc);
10274 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10278 case TargetOpcode::BUNDLE:
10279 return getInstBundleSize(
MI);
10280 case TargetOpcode::INLINEASM:
10281 case TargetOpcode::INLINEASM_BR: {
10283 const char *AsmStr =
MI.getOperand(0).getSymbolName();
10287 if (
MI.isMetaInstruction())
10291 const auto *D16Info = AMDGPU::getT16D16Helper(
Opc);
10294 unsigned LoInstOpcode = D16Info->LoOp;
10296 DescSize =
Desc.getSize();
10300 if (
Opc == AMDGPU::V_FMA_MIX_F16_t16 ||
Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10303 DescSize =
Desc.getSize();
10312 if (
MI.isBranch() && ST.hasOffset3fBug())
10313 return InstSizeVerifyMode::NoVerify;
10314 return InstSizeVerifyMode::ExactSize;
10321 if (
MI.memoperands_empty())
10333 static const std::pair<int, const char *> TargetIndices[] = {
10373std::pair<unsigned, unsigned>
10380 static const std::pair<unsigned, const char *> TargetFlags[] = {
10398 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10414 return AMDGPU::WWM_COPY;
10416 return AMDGPU::COPY;
10433 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10437 if (RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg)))
10438 return IsLRSplitInst;
10451 bool IsNullOrVectorRegister =
true;
10455 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg));
10458 return IsNullOrVectorRegister &&
10460 (!
MI.isTerminator() &&
MI.getOpcode() != AMDGPU::COPY &&
10461 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10469 if (ST.hasAddNoCarryInsts())
10485 if (ST.hasAddNoCarryInsts())
10489 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10491 : RS.scavengeRegisterBackwards(
10492 *RI.getBoolRC(),
I,
false,
10505 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10506 case AMDGPU::SI_KILL_I1_TERMINATOR:
10515 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10516 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10517 case AMDGPU::SI_KILL_I1_PSEUDO:
10518 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10530 const unsigned OffsetBits =
10532 return (1 << OffsetBits) - 1;
10536 if (!ST.isWave32())
10539 if (
MI.isInlineAsm())
10542 if (
MI.getNumOperands() <
MI.getDesc().getNumOperands())
10545 for (
auto &
Op :
MI.implicit_operands()) {
10546 if (
Op.isReg() &&
Op.getReg() == AMDGPU::VCC)
10547 Op.setReg(AMDGPU::VCC_LO);
10556 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::sbase);
10560 const int16_t RCID = getOpRegClassID(
MI.getDesc().operands()[Idx]);
10561 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10577 if (
Imm > MaxImm) {
10578 if (
Imm <= MaxImm + 64) {
10580 Overflow =
Imm - MaxImm;
10595 Overflow =
High - Alignment.value();
10599 if (Overflow > 0) {
10607 if (ST.hasRestrictedSOffset())
10612 SOffset = Overflow;
10650 if (!ST.hasFlatInstOffsets())
10654 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10659 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10660 FlatVariant == FlatAddrSpace::FlatScratch &&
Offset < 0 &&
10671std::pair<int64_t, int64_t>
10674 int64_t RemainderOffset = COffsetVal;
10675 int64_t ImmField = 0;
10680 if (AllowNegative) {
10682 int64_t
D = 1LL << NumBits;
10683 RemainderOffset = (COffsetVal /
D) *
D;
10684 ImmField = COffsetVal - RemainderOffset;
10686 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10688 (ImmField % 4) != 0) {
10690 RemainderOffset += ImmField % 4;
10691 ImmField -= ImmField % 4;
10693 }
else if (COffsetVal >= 0) {
10695 RemainderOffset = COffsetVal - ImmField;
10699 assert(RemainderOffset + ImmField == COffsetVal);
10700 return {ImmField, RemainderOffset};
10705 if (ST.hasNegativeScratchOffsetBug() &&
10713 switch (ST.getGeneration()) {
10742 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10743 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10744 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10745 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10746 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10747 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10748 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10749 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10756#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10757 case OPCODE##_dpp: \
10758 case OPCODE##_e32: \
10759 case OPCODE##_e64: \
10760 case OPCODE##_e64_dpp: \
10761 case OPCODE##_sdwa:
10775 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
10776 case AMDGPU::V_DIV_FIXUP_F16_gfx9_fake16_e64:
10777 case AMDGPU::V_FMA_F16_gfx9_e64:
10778 case AMDGPU::V_FMA_F16_gfx9_fake16_e64:
10779 case AMDGPU::V_INTERP_P2_F16:
10780 case AMDGPU::V_MAD_F16_e64:
10781 case AMDGPU::V_MAD_U16_e64:
10782 case AMDGPU::V_MAD_I16_e64:
10791 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
10805 switch (ST.getGeneration()) {
10818 if (
isMAI(Opcode)) {
10826 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
10829 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
10836 if (ST.hasGFX90AInsts()) {
10837 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
10838 if (ST.hasGFX940Insts())
10840 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10842 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10844 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
10850 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
10869 for (
unsigned I = 0, E = (
MI.getNumOperands() - 1)/ 2;
I < E; ++
I)
10870 if (
MI.getOperand(1 + 2 *
I + 1).getImm() == SubReg) {
10871 auto &RegOp =
MI.getOperand(1 + 2 *
I);
10883 switch (
MI.getOpcode()) {
10885 case AMDGPU::REG_SEQUENCE:
10889 case AMDGPU::INSERT_SUBREG:
10890 if (RSR.
SubReg == (
unsigned)
MI.getOperand(3).getImm())
10907 if (!
P.Reg.isVirtual())
10912 while (
auto *
MI = DefInst) {
10914 switch (
MI->getOpcode()) {
10916 case AMDGPU::V_MOV_B32_e32: {
10917 auto &Op1 =
MI->getOperand(1);
10946 auto *DefBB =
DefMI.getParent();
10950 if (
UseMI.getParent() != DefBB)
10953 const int MaxInstScan = 20;
10957 auto E =
UseMI.getIterator();
10958 for (
auto I = std::next(
DefMI.getIterator());
I != E; ++
I) {
10959 if (
I->isDebugInstr())
10962 if (++NumInst > MaxInstScan)
10965 if (
I->modifiesRegister(AMDGPU::EXEC,
TRI))
10978 auto *DefBB =
DefMI.getParent();
10980 const int MaxUseScan = 10;
10984 auto &UseInst = *
Use.getParent();
10987 if (UseInst.getParent() != DefBB || UseInst.isPHI())
10990 if (++NumUse > MaxUseScan)
10997 const int MaxInstScan = 20;
11001 for (
auto I = std::next(
DefMI.getIterator()); ; ++
I) {
11004 if (
I->isDebugInstr())
11007 if (++NumInst > MaxInstScan)
11020 if (Reg == VReg && --NumUse == 0)
11022 }
else if (
TRI->regsOverlap(Reg, AMDGPU::EXEC))
11031 auto Cur =
MBB.begin();
11032 if (Cur !=
MBB.end())
11034 if (!Cur->isPHI() && Cur->readsRegister(Dst,
nullptr))
11037 }
while (Cur !=
MBB.end() && Cur != LastPHIIt);
11046 if (InsPt !=
MBB.end() &&
11047 (InsPt->getOpcode() == AMDGPU::SI_IF ||
11048 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
11049 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
11050 InsPt->definesRegister(Src,
nullptr)) {
11054 .
addReg(Src, {}, SrcSubReg)
11097 if (isFullCopyInstr(
MI)) {
11098 Register DstReg =
MI.getOperand(0).getReg();
11099 Register SrcReg =
MI.getOperand(1).getReg();
11121 unsigned *PredCost)
const {
11122 if (
MI.isBundle()) {
11125 unsigned Lat = 0,
Count = 0;
11126 for (++
I;
I != E &&
I->isBundledWithPred(); ++
I) {
11128 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*
I));
11130 return Lat +
Count - 1;
11133 return SchedModel.computeInstrLatency(&
MI);
11140 return *CallAddrOp;
11147 unsigned Opcode =
MI.getOpcode();
11149 auto HandleAddrSpaceCast = [
this, &MRI](
const MachineInstr &
MI) {
11155 unsigned SrcAS = SrcTy.getAddressSpace();
11158 ST.hasGloballyAddressableScratch()
11166 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
11167 return HandleAddrSpaceCast(
MI);
11170 auto IID = GI->getIntrinsicID();
11177 case Intrinsic::amdgcn_if:
11178 case Intrinsic::amdgcn_else:
11192 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11193 Opcode == AMDGPU::G_SEXTLOAD) {
11194 if (
MI.memoperands_empty())
11198 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11199 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11207 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11208 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11209 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11215 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11218 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11226 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11227 return Formatter.get();
11235 unsigned opcode =
MI.getOpcode();
11236 if (opcode == AMDGPU::V_READLANE_B32 ||
11237 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11238 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11243 if (
MI.isInlineAsm()) {
11249 if (!RC || !RI.isSGPRClass(RC))
11254 if (isCopyInstr(
MI)) {
11258 RI.getPhysRegBaseClass(srcOp.
getReg());
11266 if (
MI.isPreISelOpcode())
11281 if (
MI.memoperands_empty())
11285 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11286 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11301 for (
unsigned I = 0, E =
MI.getNumOperands();
I != E; ++
I) {
11303 if (!
SrcOp.isReg())
11307 if (!Reg || !
SrcOp.readsReg())
11313 if (RegBank && RegBank->
getID() != AMDGPU::SGPRRegBankID)
11340 F,
"ds_ordered_count unsupported for this calling conv"));
11354 Register &SrcReg2, int64_t &CmpMask,
11355 int64_t &CmpValue)
const {
11356 if (!
MI.getOperand(0).isReg() ||
MI.getOperand(0).getSubReg())
11359 switch (
MI.getOpcode()) {
11362 case AMDGPU::S_CMP_EQ_U32:
11363 case AMDGPU::S_CMP_EQ_I32:
11364 case AMDGPU::S_CMP_LG_U32:
11365 case AMDGPU::S_CMP_LG_I32:
11366 case AMDGPU::S_CMP_LT_U32:
11367 case AMDGPU::S_CMP_LT_I32:
11368 case AMDGPU::S_CMP_GT_U32:
11369 case AMDGPU::S_CMP_GT_I32:
11370 case AMDGPU::S_CMP_LE_U32:
11371 case AMDGPU::S_CMP_LE_I32:
11372 case AMDGPU::S_CMP_GE_U32:
11373 case AMDGPU::S_CMP_GE_I32:
11374 case AMDGPU::S_CMP_EQ_U64:
11375 case AMDGPU::S_CMP_LG_U64:
11376 SrcReg =
MI.getOperand(0).getReg();
11377 if (
MI.getOperand(1).isReg()) {
11378 if (
MI.getOperand(1).getSubReg())
11380 SrcReg2 =
MI.getOperand(1).getReg();
11382 }
else if (
MI.getOperand(1).isImm()) {
11384 CmpValue =
MI.getOperand(1).getImm();
11390 case AMDGPU::S_CMPK_EQ_U32:
11391 case AMDGPU::S_CMPK_EQ_I32:
11392 case AMDGPU::S_CMPK_LG_U32:
11393 case AMDGPU::S_CMPK_LG_I32:
11394 case AMDGPU::S_CMPK_LT_U32:
11395 case AMDGPU::S_CMPK_LT_I32:
11396 case AMDGPU::S_CMPK_GT_U32:
11397 case AMDGPU::S_CMPK_GT_I32:
11398 case AMDGPU::S_CMPK_LE_U32:
11399 case AMDGPU::S_CMPK_LE_I32:
11400 case AMDGPU::S_CMPK_GE_U32:
11401 case AMDGPU::S_CMPK_GE_I32:
11402 SrcReg =
MI.getOperand(0).getReg();
11404 CmpValue =
MI.getOperand(1).getImm();
11414 if (S->isLiveIn(AMDGPU::SCC))
11423bool SIInstrInfo::invertSCCUse(
MachineInstr *SCCDef)
const {
11426 bool SCCIsDead =
false;
11429 constexpr unsigned ScanLimit = 12;
11430 unsigned Count = 0;
11431 for (MachineInstr &
MI :
11433 if (++
Count > ScanLimit)
11435 if (
MI.readsRegister(AMDGPU::SCC, &RI)) {
11436 if (
MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11437 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11438 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11439 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11444 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
11457 for (MachineInstr *
MI : InvertInstr) {
11458 if (
MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11459 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11461 }
else if (
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11462 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11463 MI->setDesc(
get(
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11464 ? AMDGPU::S_CBRANCH_SCC1
11465 : AMDGPU::S_CBRANCH_SCC0));
11478 bool NeedInversion)
const {
11479 MachineInstr *KillsSCC =
nullptr;
11484 if (
MI.modifiesRegister(AMDGPU::SCC, &RI))
11486 if (
MI.killsRegister(AMDGPU::SCC, &RI))
11489 if (NeedInversion && !invertSCCUse(SCCRedefine))
11491 if (MachineOperand *SccDef =
11493 SccDef->setIsDead(
false);
11501 if (Def.getOpcode() != AMDGPU::S_CSELECT_B32 &&
11502 Def.getOpcode() != AMDGPU::S_CSELECT_B64)
11504 bool Op1IsNonZeroImm =
11505 Def.getOperand(1).isImm() && Def.getOperand(1).getImm() != 0;
11506 bool Op2IsZeroImm =
11507 Def.getOperand(2).isImm() && Def.getOperand(2).getImm() == 0;
11508 if (!Op1IsNonZeroImm || !Op2IsZeroImm)
11514 unsigned &NewDefOpc) {
11517 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11518 Def.getOpcode() != AMDGPU::S_ADD_U32)
11524 Def.getMF()->getSubtarget().getInstrInfo());
11526 auto Imm1 =
TII->getImmOrMaterializedImm(MRI, AddSrc1);
11527 auto Imm2 =
TII->getImmOrMaterializedImm(MRI, AddSrc2);
11528 if ((!Imm1 || *Imm1 != 1) && (!Imm2 || *Imm2 != 1))
11531 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11533 Def.findRegisterDefOperand(AMDGPU::SCC,
nullptr);
11536 NewDefOpc = AMDGPU::S_ADD_U32;
11538 NeedInversion = !NeedInversion;
11543 Register SrcReg2, int64_t CmpMask,
11553 CmpValue = *ImmOpt;
11556 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue, MRI,
11557 this](
bool NeedInversion) ->
bool {
11581 unsigned NewDefOpc = Def->getOpcode();
11587 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11590 if (NewDefOpc != Def->getOpcode())
11591 Def->setDesc(
get(NewDefOpc));
11600 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11607 if (Def1 && Def1->
getOpcode() == AMDGPU::COPY && Def2 &&
11615 optimizeSCC(
Select, Def,
false);
11622 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue, MRI,
11623 this](int64_t ExpectedValue,
unsigned SrcSize,
11624 bool IsReversible,
bool IsSigned) ->
bool {
11652 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11653 Def->getOpcode() != AMDGPU::S_AND_B64)
11657 const auto isMask = [&Mask, SrcSize, MRI,
11669 SrcOp = &Def->getOperand(2);
11670 else if (isMask(&Def->getOperand(2)))
11671 SrcOp = &Def->getOperand(1);
11679 if (IsSigned && BitNo == SrcSize - 1)
11682 ExpectedValue <<= BitNo;
11684 bool IsReversedCC =
false;
11685 if (CmpValue != ExpectedValue) {
11688 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11693 Register DefReg = Def->getOperand(0).getReg();
11694 if (IsReversedCC && !MRI->hasOneNonDBGUse(DefReg))
11697 if (!optimizeSCC(Def, &CmpInstr,
false))
11700 if (!MRI->use_nodbg_empty(DefReg)) {
11708 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11709 : AMDGPU::S_BITCMP1_B32
11710 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11711 : AMDGPU::S_BITCMP1_B64;
11716 Def->eraseFromParent();
11724 case AMDGPU::S_CMP_EQ_U32:
11725 case AMDGPU::S_CMP_EQ_I32:
11726 case AMDGPU::S_CMPK_EQ_U32:
11727 case AMDGPU::S_CMPK_EQ_I32:
11728 return optimizeCmpAnd(1, 32,
true,
false) ||
11729 optimizeCmpSelect(
true);
11730 case AMDGPU::S_CMP_GE_U32:
11731 case AMDGPU::S_CMPK_GE_U32:
11732 return optimizeCmpAnd(1, 32,
false,
false);
11733 case AMDGPU::S_CMP_GE_I32:
11734 case AMDGPU::S_CMPK_GE_I32:
11735 return optimizeCmpAnd(1, 32,
false,
true);
11736 case AMDGPU::S_CMP_EQ_U64:
11737 return optimizeCmpAnd(1, 64,
true,
false);
11738 case AMDGPU::S_CMP_LG_U32:
11739 case AMDGPU::S_CMP_LG_I32:
11740 case AMDGPU::S_CMPK_LG_U32:
11741 case AMDGPU::S_CMPK_LG_I32:
11742 return optimizeCmpAnd(0, 32,
true,
false) ||
11743 optimizeCmpSelect(
false);
11744 case AMDGPU::S_CMP_GT_U32:
11745 case AMDGPU::S_CMPK_GT_U32:
11746 return optimizeCmpAnd(0, 32,
false,
false);
11747 case AMDGPU::S_CMP_GT_I32:
11748 case AMDGPU::S_CMPK_GT_I32:
11749 return optimizeCmpAnd(0, 32,
false,
true);
11750 case AMDGPU::S_CMP_LG_U64:
11751 return optimizeCmpAnd(0, 64,
true,
false) ||
11752 optimizeCmpSelect(
false);
11759 AMDGPU::OpName
OpName)
const {
11760 if (!ST.needsAlignedVGPRs())
11763 int OpNo = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
OpName);
11775 bool IsAGPR = RI.isAGPR(MRI, DataReg);
11777 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
11781 : &AMDGPU::VReg_64_Align2RegClass);
11783 .
addReg(DataReg, {},
Op.getSubReg())
11788 Op.setSubReg(AMDGPU::sub0);
11793 if (!SchedModel.hasInstrSchedModel())
11799 unsigned RepeatRate = 0;
11801 PI = SchedModel.getWriteProcResBegin(SCDesc),
11802 PE = SchedModel.getWriteProcResEnd(SCDesc);
11804 RepeatRate = std::max(RepeatRate, (
unsigned)PI->ReleaseAtCycle);
11821 if (ST.hasGFX1250Insts())
11828 unsigned Opcode =
MI.getOpcode();
11834 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
11835 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
11838 if (!ST.hasGFX940Insts())
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static const TargetRegisterClass * getRegClass(const MachineInstr &MI, Register Reg)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
AMD GCN specific subclass of TargetSubtarget.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static bool isUndef(const MachineInstr &MI)
TargetInstrInfo::RegSubRegPair RegSubRegPair
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
uint64_t IntrinsicInst * II
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
This file declares the machine register scavenger class.
static cl::opt< bool > Fix16BitCopies("amdgpu-fix-16-bit-physreg-copies", cl::desc("Fix copies between 32 and 16 bit registers by extending to 32 bit"), cl::init(true), cl::ReallyHidden)
static void expandSGPRCopy(const SIInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, const TargetRegisterClass *RC, bool Forward)
static unsigned getNewFMAInst(const GCNSubtarget &ST, unsigned Opc)
static unsigned getIndirectSGPRWriteMovRelPseudo32(unsigned VecSize)
static bool compareMachineOp(const MachineOperand &Op0, const MachineOperand &Op1)
static bool isStride64(unsigned Opc)
static MachineBasicBlock * generateWaterFallLoop(const SIInstrInfo &TII, MachineInstr &MI, ArrayRef< MachineOperand * > ScalarOps, MachineDominatorTree *MDT, MachineBasicBlock::iterator Begin=nullptr, MachineBasicBlock::iterator End=nullptr, ArrayRef< Register > PhySGPRs={})
#define GENERATE_RENAMED_GFX9_CASES(OPCODE)
static std::tuple< unsigned, unsigned > extractRsrcPtr(const SIInstrInfo &TII, MachineInstr &MI, MachineOperand &Rsrc)
static unsigned VOP3OpIdxToSrcN(const MachineInstr &MI, unsigned OpIdx)
static bool followSubRegDef(MachineInstr &MI, TargetInstrInfo::RegSubRegPair &RSR)
static unsigned getIndirectSGPRWriteMovRelPseudo64(unsigned VecSize)
static MachineInstr * swapImmOperands(MachineInstr &MI, MachineOperand &NonRegOp1, MachineOperand &NonRegOp2)
static void copyFlagsToImplicitVCC(MachineInstr &MI, const MachineOperand &Orig)
static bool offsetsDoNotOverlap(LocationSize WidthA, int OffsetA, LocationSize WidthB, int OffsetB)
static void indirectCopyToAGPR(const SIInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, RegScavenger &RS, bool RegsOverlap, Register ImpUseSuperReg=Register())
Handle copying from SGPR to AGPR, or from AGPR to AGPR on GFX908.
static unsigned getWWMRegSpillSaveOpcode(unsigned Size, bool IsVectorSuperClass)
static bool memOpsHaveSameBaseOperands(ArrayRef< const MachineOperand * > BaseOps1, ArrayRef< const MachineOperand * > BaseOps2)
static unsigned getWWMRegSpillRestoreOpcode(unsigned Size, bool IsVectorSuperClass)
static unsigned getSGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static bool setsSCCIfResultIsZero(const MachineInstr &Def, bool &NeedInversion, unsigned &NewDefOpc)
static bool isSCCDeadOnExit(MachineBasicBlock *MBB)
static unsigned getIndirectVGPRWriteMovRelPseudoOpc(unsigned VecSize)
static unsigned subtargetEncodingFamily(const GCNSubtarget &ST)
static void preserveCondRegFlags(MachineOperand &CondReg, const MachineOperand &OrigCond)
static Register findImplicitSGPRRead(const MachineInstr &MI)
static unsigned getNewFMAAKInst(const GCNSubtarget &ST, unsigned Opc)
static cl::opt< unsigned > BranchOffsetBits("amdgpu-s-branch-bits", cl::ReallyHidden, cl::init(16), cl::desc("Restrict range of branch instructions (DEBUG)"))
static void updateLiveVariables(LiveVariables *LV, MachineInstr &MI, MachineInstr &NewMI)
static unsigned getAVSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static bool memOpsHaveSameBasePtr(const MachineInstr &MI1, ArrayRef< const MachineOperand * > BaseOps1, const MachineInstr &MI2, ArrayRef< const MachineOperand * > BaseOps2)
static unsigned getSGPRSpillRestoreOpcode(unsigned Size)
static bool isRegOrFI(const MachineOperand &MO)
static unsigned getVGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI)
static constexpr AMDGPU::OpName ModifierOpNames[]
static void reportIllegalCopy(const SIInstrInfo *TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, const char *Msg="illegal VGPR to SGPR copy")
static MachineInstr * swapRegAndNonRegOperand(MachineInstr &MI, MachineOperand &RegOp, MachineOperand &NonRegOp)
static bool shouldReadExec(const MachineInstr &MI)
static unsigned getNewFMAMKInst(const GCNSubtarget &ST, unsigned Opc)
static bool isRenamedInGFX9(int Opcode)
static TargetInstrInfo::RegSubRegPair getRegOrUndef(const MachineOperand &RegOpnd)
static std::tuple< unsigned, unsigned, unsigned > splitGlobalAddressRelocFlags(const GCNSubtarget &ST, const MachineOperand &SrcOp)
static bool changesVGPRIndexingMode(const MachineInstr &MI)
static bool isSubRegOf(const SIRegisterInfo &TRI, const MachineOperand &SuperVec, const MachineOperand &SubReg)
static bool foldableSelect(const MachineInstr &Def)
static bool nodesHaveSameOperandValue(SDNode *N0, SDNode *N1, AMDGPU::OpName OpName)
Returns true if both nodes have the same value for the given operand Op, or if both nodes do not have...
static unsigned getNumOperandsNoGlue(SDNode *Node)
static bool canRemat(const MachineInstr &MI)
static unsigned getAVSpillRestoreOpcode(unsigned Size)
static void emitLoadScalarOpsFromVGPRLoop(const SIInstrInfo &TII, MachineRegisterInfo &MRI, MachineBasicBlock &PredBB, MachineBasicBlock &LoopBB, MachineBasicBlock &BodyBB, const DebugLoc &DL, ArrayRef< MachineOperand * > ScalarOps, ArrayRef< Register > PhySGPRs={})
static unsigned getVGPRSpillRestoreOpcode(unsigned Size)
Interface definition for SIInstrInfo.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
const unsigned AndN2WrExecOpc
static const LaneMaskConstants & get(const GCNSubtarget &ST)
const unsigned XorTermOpc
const unsigned OrSaveExecOpc
const unsigned AndSaveExecOpc
static LLVM_ABI Semantics SemanticsToEnum(const llvm::fltSemantics &Sem)
Class for arbitrary precision integers.
int64_t getSExtValue() const
Get sign extended value.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & front() const
Get the first element.
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
This class is the base class for the comparison instructions.
uint64_t getZExtValue() const
Opaque handle to a cycle within a GenericCycleInfo that wraps the cycle's preorder index.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Diagnostic information for unsupported feature in backend.
void changeImmediateDominator(DomTreeNodeBase< NodeT > *N, DomTreeNodeBase< NodeT > *NewIDom)
changeImmediateDominator - This method is used to update the dominator tree information when a node's...
DomTreeNodeBase< NodeT > * addNewBlock(NodeT *BB, NodeT *DomBB)
Add a new node to the dominator tree information.
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
void getExitingBlocks(CycleRef C, SmallVectorImpl< BlockT * > &TmpStorage) const
Return all blocks of C that have a successor outside of C.
CycleRef getParentCycle(CycleRef C) const
bool contains(CycleRef Outer, CycleRef Inner) const
Returns true iff Outer contains Inner. O(1). Non-strict.
CycleRef getCycle(const BlockT *Block) const
Find the innermost cycle containing Block.
Itinerary data supplied by a subtarget to be used by a target.
constexpr unsigned getAddressSpace() const
This is an important class for using LLVM in a threaded context.
LiveInterval - This class represents the liveness of a register, or stack slot.
bool hasInterval(Register Reg) const
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
LiveInterval & getInterval(Register Reg)
LLVM_ABI bool shrinkToUses(LiveInterval *li, SmallVectorImpl< MachineInstr * > *dead=nullptr)
After removing some uses of a register, shrink its live range to just the remaining uses.
SlotIndex ReplaceMachineInstrInMaps(MachineInstr &MI, MachineInstr &NewMI)
This class represents the liveness of a register, stack slot, etc.
LLVM_ABI void replaceKillInstruction(Register Reg, MachineInstr &OldMI, MachineInstr &NewMI)
replaceKillInstruction - Update register kill info by replacing a kill instruction with a new one.
LLVM_ABI VarInfo & getVarInfo(Register Reg)
getVarInfo - Return the VarInfo structure for the specified VIRTUAL register.
static LocationSize precise(uint64_t Value)
TypeSize getValue() const
static const MCBinaryExpr * createAnd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCBinaryExpr * createAShr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
unsigned getSize() const
Return the number of bytes in the encoding of this instruction, or zero if the encoding size cannot b...
ArrayRef< MCPhysReg > implicit_uses() const
Return a list of registers that are potentially read by any instance of this machine instruction.
unsigned getOpcode() const
Return the opcode number for this descriptor.
This holds information about one operand of a machine instruction, indicating the register class for ...
uint8_t OperandType
Information about the type of the operand.
int16_t RegClass
This specifies the register class enumeration of the operand if the operand is a register.
bool hasSuperClassEq(const MCRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
Wrapper class representing physical registers. Should be passed by value.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
LLVM_ABI void setVariableValue(const MCExpr *Value)
Helper class for constructing bundles of MachineInstrs.
MachineBasicBlock::instr_iterator begin() const
Return an iterator to the first bundled instruction.
MIBundleBuilder & append(MachineInstr *MI)
Insert MI into MBB by appending it to the instructions in the bundle.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
void push_back(MachineInstr *MI)
LLVM_ABI LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, MCRegister Reg, const_iterator Before, unsigned Neighborhood=10) const
Return whether (physical) register Reg has been defined and not killed as of just before Before.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
Instructions::const_iterator const_instr_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< succ_iterator > successors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
@ LQR_Dead
Register is known to be fully dead.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool isImmutableObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to an immutable object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void push_back(MachineBasicBlock *MBB)
MCContext & getContext() const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const
Copy all the implicit operands from OtherMI onto this one.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
const MachineBasicBlock * getParent() const
LLVM_ABI void addImplicitDefUseOperands(MachineFunction &MF)
Add all implicit def and use operands to this instruction.
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
LLVM_ABI unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
mop_range implicit_operands()
bool modifiesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr modifies (fully define or partially define) the specified register.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
LLVM_ABI bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore,...
void untieRegOperand(unsigned OpIdx)
Break any tie involving OpIdx.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
LLVM_ABI void eraseFromBundle()
Unlink 'this' from its basic block and delete it.
bool hasOneMemOperand() const
Return true if this instruction has exactly one MachineMemOperand.
mop_range explicit_operands()
LLVM_ABI void tieOperands(unsigned DefIdx, unsigned UseIdx)
Add a tie between the register operands at DefIdx and UseIdx.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
LLVM_ABI bool hasOrderedMemoryRef() const
Return true if this instruction may have an ordered or volatile memory reference, or if the informati...
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
bool isMoveImmediate(QueryType Type=IgnoreBundle) const
Return true if this instruction is a move immediate (including conditional moves) instruction.
LLVM_ABI void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
filtered_mop_range all_uses()
Returns an iterator range over all operands that are (explicit or implicit) register uses.
LLVM_ABI void setPostInstrSymbol(MachineFunction &MF, MCSymbol *Symbol)
Set a symbol that will be emitted just after the instruction itself.
LLVM_ABI void clearRegisterKills(Register Reg, const TargetRegisterInfo *RegInfo)
Clear all kill flags affecting Reg.
const MachineOperand & getOperand(unsigned i) const
uint32_t getFlags() const
Return the MI flags bitvector.
LLVM_ABI int findRegisterDefOperandIdx(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false) const
Returns the operand index that is a def of the specified register or -1 if it is not found.
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
MachineOperand * findRegisterDefOperand(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false)
Wrapper for findRegisterDefOperandIdx, it returns a pointer to the MachineOperand rather than an inde...
A description of a memory reference used in the backend.
unsigned getAddrSpace() const
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineOperand class - Representation of each machine instruction operand.
void setSubReg(unsigned subReg)
unsigned getSubReg() const
LLVM_ABI unsigned getOperandNo() const
Returns the index of this operand in the instruction that it belongs to.
const GlobalValue * getGlobal() const
LLVM_ABI void ChangeToFrameIndex(int Idx, unsigned TargetFlags=0)
Replace this operand with a frame index.
void setImm(int64_t immVal)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void setIsDead(bool Val=true)
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
LLVM_ABI void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags=0)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value.
LLVM_ABI void ChangeToGA(const GlobalValue *GV, int64_t Offset, unsigned TargetFlags=0)
ChangeToGA - Replace this operand with a new global address operand.
void setIsKill(bool Val=true)
LLVM_ABI void ChangeToRegister(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isDebug=false)
ChangeToRegister - Replace this operand with a new register operand of the specified value.
void setOffset(int64_t Offset)
unsigned getTargetFlags() const
static MachineOperand CreateImm(int64_t Val)
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
bool isTargetIndex() const
isTargetIndex - Tests if this is a MO_TargetIndex operand.
void setTargetFlags(unsigned F)
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
LLVM_ABI bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
@ MO_Immediate
Immediate operand.
@ MO_Register
Register operand.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
int64_t getOffset() const
Return the offset from the symbol in this operand.
bool isFPImm() const
isFPImm - Tests if this is a MO_FPImmediate operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
iterator_range< use_nodbg_iterator > use_nodbg_operands(Register Reg) const
bool use_nodbg_empty(Register RegNo) const
use_nodbg_empty - Return true if there are no non-Debug instructions using the specified register.
LLVM_ABI void moveOperands(MachineOperand *Dst, MachineOperand *Src, unsigned NumOps)
Move NumOps operands from Src to Dst, updating use-def lists as needed.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
bool reservedRegsFrozen() const
reservedRegsFrozen - Returns true after freezeReservedRegs() was called to ensure the set of reserved...
LLVM_ABI void clearVirtRegs()
clearVirtRegs - Remove all virtual registers (after physreg assignment).
void setRegAllocationHint(Register VReg, unsigned Type, Register PrefReg)
setRegAllocationHint - Specify a register allocation hint for the specified virtual register.
const MachineFunction & getMF() const
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
void setSimpleHint(Register VReg, Register PrefReg)
Specify the preferred (target independent) register allocation hint for the specified virtual registe...
const TargetRegisterInfo * getTargetRegisterInfo() const
LLVM_ABI bool isConstantPhysReg(MCRegister PhysReg) const
Returns true if PhysReg is unallocatable and constant throughout the function.
LLVM_ABI Register cloneVirtualRegister(Register VReg, StringRef Name="")
Create and return a new virtual register in the function with the same attributes as the given regist...
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
iterator_range< use_iterator > use_operands(Register Reg) const
LLVM_ABI void removeRegOperandFromUseList(MachineOperand *MO)
Remove MO from its use-def list.
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
LLVM_ABI void addRegOperandToUseList(MachineOperand *MO)
Add MO to the linked list of operands for its register.
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
This class implements the register bank concept.
unsigned getID() const
Get the identifier of this register bank.
Wrapper class representing virtual and physical registers.
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Represents one node in the SelectionDAG.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
bool isLegalMUBUFImmOffset(unsigned Imm) const
bool isInlineConstant(const APInt &Imm) const
void legalizeOperandsVOP3(MachineRegisterInfo &MRI, MachineInstr &MI) const
Fix operands in MI to satisfy constant bus requirements.
bool canAddToBBProlog(const MachineInstr &MI) const
static bool isDS(const MachineInstr &MI)
MachineBasicBlock * legalizeOperands(MachineInstr &MI, MachineDominatorTree *MDT=nullptr) const
Legalize all operands in this instruction.
bool areLoadsFromSameBasePtr(SDNode *Load0, SDNode *Load1, int64_t &Offset0, int64_t &Offset1) const override
unsigned getLiveRangeSplitOpcode(Register Reg, const MachineFunction &MF) const override
bool getMemOperandsWithOffsetWidth(const MachineInstr &LdSt, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width, const TargetRegisterInfo *TRI) const final
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
static bool isNeverUniform(const MachineInstr &MI)
bool isXDLWMMA(const MachineInstr &MI) const
bool isBasicBlockPrologue(const MachineInstr &MI, Register Reg=Register()) const override
bool isSpill(uint32_t Opcode) const
uint64_t getDefaultRsrcDataFormat() const
static bool isSOPP(const MachineInstr &MI)
bool mayAccessScratch(const MachineInstr &MI) const
bool isIGLP(unsigned Opcode) const
static bool isFLATScratch(const MachineInstr &MI)
bool isLegalFLATOffset(int64_t Offset, unsigned AddrSpace, AMDGPU::FlatAddrSpace FlatVariant) const
Returns if Offset is legal for the subtarget as the offset to a FLAT encoded instruction with the giv...
const MCInstrDesc & getIndirectRegWriteMovRelPseudo(unsigned VecSize, unsigned EltSize, bool IsSGPR) const
MachineInstrBuilder getAddNoCarry(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg) const
Return a partially built integer add instruction without carry.
bool mayAccessFlatAddressSpace(const MachineInstr &MI) const
bool shouldScheduleLoadsNear(SDNode *Load0, SDNode *Load1, int64_t Offset0, int64_t Offset1, unsigned NumLoads) const override
bool splitMUBUFOffset(uint32_t Imm, uint32_t &SOffset, uint32_t &ImmOffset, Align Alignment=Align(4)) const
bool isIgnorableUse(const MachineInstr &MI, unsigned OpIdx) const override
ArrayRef< std::pair< unsigned, const char * > > getSerializableDirectMachineOperandTargetFlags() const override
void moveToVALU(SIInstrWorklist &Worklist, MachineDominatorTree *MDT) const
Replace the instructions opcode with the equivalent VALU opcode.
static bool isSMRD(const MachineInstr &MI)
void restoreExec(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register Reg, SlotIndexes *Indexes=nullptr) const
void storeRegToStackSlotCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC) const
bool usesConstantBus(const MachineRegisterInfo &MRI, const MachineOperand &MO, const MCOperandInfo &OpInfo) const
Returns true if this operand uses the constant bus.
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
static unsigned getFoldableCopySrcIdx(const MachineInstr &MI)
unsigned getOpSize(uint32_t Opcode, unsigned OpNo) const
Return the size in bytes of the operand OpNo on the given.
void legalizeOperandsFLAT(MachineRegisterInfo &MRI, MachineInstr &MI) const
bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask, int64_t CmpValue, const MachineRegisterInfo *MRI) const override
static std::optional< int64_t > extractSubregFromImm(int64_t ImmVal, unsigned SubRegIndex)
Return the extracted immediate value in a subregister use from a constant materialized in a super reg...
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
static bool isMTBUF(const MachineInstr &MI)
const MCInstrDesc & getIndirectGPRIDXPseudo(unsigned VecSize, bool IsIndirectSrc) const
static bool isDGEMM(unsigned Opcode)
static bool isEXP(const MachineInstr &MI)
static bool isSALU(const MachineInstr &MI)
static bool setsSCCIfResultIsNonZero(const MachineInstr &MI)
const MIRFormatter * getMIRFormatter() const override
static bool isXcntDrain(const MachineInstr &MI)
True if MI implicitly drains XCNT.
void legalizeGenericOperand(MachineBasicBlock &InsertMBB, MachineBasicBlock::iterator I, const TargetRegisterClass *DstRC, MachineOperand &Op, MachineRegisterInfo &MRI, const DebugLoc &DL) const
MachineInstr * buildShrunkInst(MachineInstr &MI, unsigned NewOpcode) const
static bool isVOP2(const MachineInstr &MI)
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override
static bool isSDWA(const MachineInstr &MI)
const MCInstrDesc & getKillTerminatorFromPseudo(unsigned Opcode) const
void insertNoops(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned Quantity) const override
static bool isGather4(const MachineInstr &MI)
MachineInstr * getWholeWaveFunctionSetup(MachineFunction &MF) const
bool isLegalVSrcOperand(const MachineRegisterInfo &MRI, const MCOperandInfo &OpInfo, const MachineOperand &MO) const
Check if MO would be a valid operand for the given operand definition OpInfo.
static bool isDOT(const MachineInstr &MI)
std::unique_ptr< PipelinerLoopInfo > analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override
InstSizeVerifyMode getInstSizeVerifyMode(const MachineInstr &MI) const override
MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const override
bool hasModifiers(unsigned Opcode) const
Return true if this instruction has any modifiers.
bool shouldClusterMemOps(ArrayRef< const MachineOperand * > BaseOps1, int64_t Offset1, bool OffsetIsScalable1, ArrayRef< const MachineOperand * > BaseOps2, int64_t Offset2, bool OffsetIsScalable2, unsigned ClusterSize, unsigned NumBytes) const override
static bool isSWMMAC(const MachineInstr &MI)
ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *II, const ScheduleDAGMI *DAG) const override
bool isHighLatencyDef(int Opc) const override
void legalizeOpWithMove(MachineInstr &MI, unsigned OpIdx) const
Legalize the OpIndex operand of this instruction by inserting a MOV.
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
static bool isVOPC(const MachineInstr &MI)
void removeModOperands(MachineInstr &MI) const
unsigned getRepeatRate(const MachineInstr &MI) const
Get the repeat rate for a VALU instruction from the scheduling model.
unsigned getVectorRegSpillRestoreOpcode(Register Reg, const TargetRegisterClass *RC, unsigned Size, const SIMachineFunctionInfo &MFI) const
bool isLegalSingleSGPRReadInstOperand(const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN, const MachineOperand *MO=nullptr) const
Check if MO would be a legal operand for a single-SGPR-read instruction.
bool isXDL(const MachineInstr &MI) const
Register isStackAccess(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const
static bool isVIMAGE(const MachineInstr &MI)
void enforceOperandRCAlignment(MachineInstr &MI, AMDGPU::OpName OpName) const
static bool isSOP2(const MachineInstr &MI)
static bool isGWS(const MachineInstr &MI)
bool hasRAWDependency(const MachineInstr &FirstMI, const MachineInstr &SecondMI) const
bool isLegalAV64PseudoImm(uint64_t Imm) const
Check if this immediate value can be used for AV_MOV_B64_IMM_PSEUDO.
bool isNeverCoissue(MachineInstr &MI) const
static bool isBUF(const MachineInstr &MI)
void handleCopyToPhysHelper(SIInstrWorklist &Worklist, Register DstReg, MachineInstr &Inst, MachineRegisterInfo &MRI, DenseMap< MachineInstr *, V2PhysSCopyInfo > &WaterFalls, DenseMap< MachineInstr *, bool > &V2SPhyCopiesToErase) const
bool hasModifiersSet(const MachineInstr &MI, AMDGPU::OpName OpName) const
bool isLegalToSwap(const MachineInstr &MI, unsigned fromIdx, unsigned toIdx) const
static bool isFLATGlobal(const MachineInstr &MI)
MachineInstr * foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, ArrayRef< unsigned > Ops, int FrameIndex, MachineInstr *&CopyMI, LiveIntervals *LIS=nullptr, VirtRegMap *VRM=nullptr) const override
bool isGlobalMemoryObject(const MachineInstr *MI) const override
static bool isVSAMPLE(const MachineInstr &MI)
bool isBufferSMRD(const MachineInstr &MI) const
static bool isKillTerminator(unsigned Opcode)
bool isVOPDAntidependencyAllowed(const MachineInstr &MI) const
If OpX is multicycle, anti-dependencies are not allowed.
bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx0, unsigned &SrcOpIdx1) const override
void insertScratchExecCopy(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register Reg, bool IsSCCLive, SlotIndexes *Indexes=nullptr) const
bool hasVALU32BitEncoding(unsigned Opcode) const
Return true if this 64-bit VALU instruction has a 32-bit encoding.
unsigned getMovOpcode(const TargetRegisterClass *DstRC) const
Register isSGPRStackAccess(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const
unsigned buildExtractSubReg(MachineBasicBlock::iterator MI, MachineRegisterInfo &MRI, const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC, unsigned SubIdx, const TargetRegisterClass *SubRC) const
void legalizeOperandsVOP2(MachineRegisterInfo &MRI, MachineInstr &MI) const
Legalize operands in MI by either commuting it or inserting a copy of src1.
static bool isVALU(const MachineInstr &MI, bool AllowLDSDMA)
bool foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, Register Reg, MachineRegisterInfo *MRI) const final
static bool isTRANS(const MachineInstr &MI)
static bool isImage(const MachineInstr &MI)
static bool isSOPK(const MachineInstr &MI)
const TargetRegisterClass * getOpRegClass(const MachineInstr &MI, unsigned OpNo) const
Return the correct register class for OpNo.
MachineBasicBlock * insertSimulatedTrap(MachineRegisterInfo &MRI, MachineBasicBlock &MBB, MachineInstr &MI, const DebugLoc &DL) const
Build instructions that simulate the behavior of a s_trap 2 instructions for hardware (namely,...
static unsigned getNonSoftWaitcntOpcode(unsigned Opcode)
static unsigned getDSShaderTypeValue(const MachineFunction &MF)
static bool isFoldableCopy(const MachineInstr &MI)
static bool isMUBUF(const MachineInstr &MI)
bool expandPostRAPseudo(MachineInstr &MI) const override
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &CmpMask, int64_t &CmpValue) const override
void createWaterFallForSiCall(MachineInstr *MI, MachineDominatorTree *MDT, ArrayRef< MachineOperand * > ScalarOps, ArrayRef< Register > PhySGPRs={}) const
Wrapper function for generating waterfall for instruction MI This function take into consideration of...
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, unsigned SubReg=0, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
static bool isSegmentSpecificFLAT(const MachineInstr &MI)
bool isReMaterializableImpl(const MachineInstr &MI) const override
static bool isVOP3(const MCInstrDesc &Desc)
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
bool physRegUsesConstantBus(const MachineOperand &Reg) const
static bool isF16PseudoScalarTrans(unsigned Opcode)
void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DstReg, ArrayRef< MachineOperand > Cond, Register TrueReg, Register FalseReg) const override
bool mayAccessVMEMThroughFlat(const MachineInstr &MI) const
static bool isDPP(const MachineInstr &MI)
bool analyzeBranchImpl(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const
static bool isMFMA(const MachineInstr &MI)
bool isLowLatencyInstruction(const MachineInstr &MI) const
std::optional< DestSourcePair > isCopyInstrImpl(const MachineInstr &MI) const override
If the specific machine instruction is a instruction that moves/copies value from one register to ano...
void mutateAndCleanupImplicit(MachineInstr &MI, const MCInstrDesc &NewDesc) const
ValueUniformity getGenericValueUniformity(const MachineInstr &MI) const
static bool isMAI(const MCInstrDesc &Desc)
void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig, LaneBitmask UsedLanes=LaneBitmask::getAll()) const override
static bool usesLGKM_CNT(const MachineInstr &MI)
void legalizeOperandsVALUt16(MachineInstr &Inst, MachineRegisterInfo &MRI) const
Fix operands in Inst to fix 16bit SALU to VALU lowering.
bool isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo, const MachineOperand &MO) const
bool canShrink(const MachineInstr &MI, const MachineRegisterInfo &MRI) const
const MachineOperand & getCalleeOperand(const MachineInstr &MI) const override
bool isAsmOnlyOpcode(int MCOp) const
Check if this instruction should only be used by assembler.
bool isAlwaysGDS(uint32_t Opcode) const
static bool isVGPRSpill(const MachineInstr &MI)
ScheduleHazardRecognizer * CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II, const ScheduleDAG *DAG) const override
This is used by the post-RA scheduler (SchedulePostRAList.cpp).
bool verifyInstruction(const MachineInstr &MI, StringRef &ErrInfo) const override
unsigned getInstrLatency(const InstrItineraryData *ItinData, const MachineInstr &MI, unsigned *PredCost=nullptr) const override
unsigned getVectorRegSpillSaveOpcode(Register Reg, const TargetRegisterClass *RC, unsigned Size, const SIMachineFunctionInfo &MFI, bool NeedsCFI) const
int64_t getNamedImmOperand(const MachineInstr &MI, AMDGPU::OpName OperandName) const
Get required immediate operand.
ArrayRef< std::pair< int, const char * > > getSerializableTargetIndices() const override
bool regUsesConstantBus(const MachineOperand &Reg, const MachineRegisterInfo &MRI) const
static bool isMIMG(const MachineInstr &MI)
MachineOperand buildExtractSubRegOrImm(MachineBasicBlock::iterator MI, MachineRegisterInfo &MRI, const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC, unsigned SubIdx, const TargetRegisterClass *SubRC) const
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
bool isLegalRegOperand(const MachineRegisterInfo &MRI, const MCOperandInfo &OpInfo, const MachineOperand &MO) const
Check if MO (a register operand) is a legal register for the given operand description or operand ind...
static unsigned getNumWaitStates(const MachineInstr &MI)
Return the number of wait states that result from executing this instruction.
unsigned getVALUOp(const MachineInstr &MI) const
static bool modifiesModeRegister(const MachineInstr &MI)
Return true if the instruction modifies the mode register.q.
Register readlaneVGPRToSGPR(Register SrcReg, MachineInstr &UseMI, MachineRegisterInfo &MRI, const TargetRegisterClass *DstRC=nullptr) const
Copy a value from a VGPR (SrcReg) to SGPR.
bool hasDivergentBranch(const MachineBasicBlock *MBB) const
Return whether the block terminate with divergent branch.
std::pair< int64_t, int64_t > splitFlatOffset(int64_t COffsetVal, unsigned AddrSpace, AMDGPU::FlatAddrSpace FlatVariant) const
Split COffsetVal into {immediate offset field, remainder offset} values.
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
void fixImplicitOperands(MachineInstr &MI) const
bool moveFlatAddrToVGPR(MachineInstr &Inst) const
Change SADDR form of a FLAT Inst to its VADDR form if saddr operand was moved to VGPR.
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
void createReadFirstLaneFromCopyToPhysReg(MachineRegisterInfo &MRI, Register DstReg, MachineInstr &Inst) const
bool swapSourceModifiers(MachineInstr &MI, MachineOperand &Src0, AMDGPU::OpName Src0OpName, MachineOperand &Src1, AMDGPU::OpName Src1OpName) const
MachineBasicBlock * getBranchDestBlock(const MachineInstr &MI) const override
bool hasUnwantedEffectsWhenEXECEmpty(const MachineInstr &MI) const
This function is used to determine if an instruction can be safely executed under EXEC = 0 without ha...
bool getConstValDefinedInReg(const MachineInstr &MI, const Register Reg, int64_t &ImmVal) const override
static bool isAtomic(const MachineInstr &MI)
bool canInsertSelect(const MachineBasicBlock &MBB, ArrayRef< MachineOperand > Cond, Register DstReg, Register TrueReg, Register FalseReg, int &CondCycles, int &TrueCycles, int &FalseCycles) const override
bool isLiteralOperandLegal(const MCInstrDesc &InstDesc, const MCOperandInfo &OpInfo) const
static bool isWWMRegSpillOpcode(uint32_t Opcode)
static bool sopkIsZext(unsigned Opcode)
static bool isSGPRSpill(const MachineInstr &MI)
static bool isWMMA(const MachineInstr &MI)
ArrayRef< std::pair< MachineMemOperand::Flags, const char * > > getSerializableMachineMemOperandTargetFlags() const override
MachineInstr * convertToThreeAddress(MachineInstr &MI, LiveVariables *LV, LiveIntervals *LIS) const override
bool mayReadEXEC(const MachineRegisterInfo &MRI, const MachineInstr &MI) const
Returns true if the instruction could potentially depend on the value of exec.
void legalizeOperandsSMRD(MachineRegisterInfo &MRI, MachineInstr &MI) const
bool isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const override
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override
std::pair< MachineInstr *, MachineInstr * > expandMovDPP64(MachineInstr &MI) const
static bool isSOPC(const MachineInstr &MI)
static bool isFLAT(const MachineInstr &MI)
bool isBarrier(unsigned Opcode) const
MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx0, unsigned OpIdx1) const override
bool mayAccessLDSThroughFlat(const MachineInstr &MI, bool TgSplit) const
int pseudoToMCOpcode(int Opcode) const
Return a target-specific opcode if Opcode is a pseudo instruction.
const MCInstrDesc & getMCOpcodeFromPseudo(unsigned Opcode) const
Return the descriptor of the target-specific machine instruction that corresponds to the specified ps...
static bool usesVM_CNT(const MachineInstr &MI)
MachineInstr * createPHIDestinationCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, Register Dst) const override
static bool isFixedSize(const MachineInstr &MI)
bool isSafeToSink(MachineInstr &MI, MachineBasicBlock *SuccToSinkTo, MachineCycleInfo *CI) const override
LLVM_READONLY int commuteOpcode(unsigned Opc) const
ValueUniformity getValueUniformity(const MachineInstr &MI) const final
uint64_t getScratchRsrcWords23() const
LLVM_READONLY MachineOperand * getNamedOperand(MachineInstr &MI, AMDGPU::OpName OperandName) const
Returns the operand named Op.
std::pair< unsigned, unsigned > decomposeMachineOperandsTargetFlags(unsigned TF) const override
bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, const MachineInstr &MIb) const override
bool isOperandLegal(const MachineInstr &MI, unsigned OpIdx, const MachineOperand *MO=nullptr) const
Check if MO is a legal operand if it was the OpIdx Operand for MI.
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
bool allowNegativeFlatOffset(AMDGPU::FlatAddrSpace FlatVariant) const
Returns true if negative offsets are allowed for the given FlatVariant.
void moveToVALUImpl(SIInstrWorklist &Worklist, MachineDominatorTree *MDT, MachineInstr &Inst, DenseMap< MachineInstr *, V2PhysSCopyInfo > &WaterFalls, DenseMap< MachineInstr *, bool > &V2SPhyCopiesToErase) const
static bool isLDSDMA(const MachineInstr &MI)
static bool isVOP1(const MachineInstr &MI)
SIInstrInfo(const GCNSubtarget &ST)
std::optional< int64_t > getImmOrMaterializedImm(const MachineRegisterInfo &MRI, const MachineOperand &Op, MachineInstr **DefMI=nullptr) const
void insertIndirectBranch(MachineBasicBlock &MBB, MachineBasicBlock &NewDestBB, MachineBasicBlock &RestoreBB, const DebugLoc &DL, int64_t BrOffset, RegScavenger *RS) const override
bool hasAnyModifiersSet(const MachineInstr &MI) const
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
Register getLongBranchReservedReg() const
bool isWholeWaveFunction() const
Register getStackPtrOffsetReg() const
unsigned getMaxMemoryClusterDWords() const
void setHasSpilledVGPRs(bool Spill=true)
bool isWWMReg(Register Reg) const
bool checkFlag(Register Reg, uint8_t Flag) const
void setHasSpilledSGPRs(bool Spill=true)
unsigned getScratchReservedForDynamicVGPRs() const
static unsigned getSubRegFromChannel(unsigned Channel, unsigned NumRegs=1)
ArrayRef< int16_t > getRegSplitParts(const TargetRegisterClass *RC, unsigned EltSize) const
unsigned getHWRegIndex(MCRegister Reg) const
bool isSGPRReg(const MachineRegisterInfo &MRI, Register Reg) const
unsigned getRegPressureLimit(const TargetRegisterClass *RC, MachineFunction &MF) const override
unsigned getChannelFromSubReg(unsigned SubReg) const
static bool isSGPRClass(const TargetRegisterClass *RC)
static bool isAGPRClass(const TargetRegisterClass *RC)
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
virtual bool hasVRegLiveness() const
Return true if this DAG supports VReg liveness and RegPressure.
MachineFunction & MF
Machine function.
HazardRecognizer - This determines whether or not an instruction can be issued this cycle,...
SlotIndex - An opaque wrapper around machine indexes.
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def.
SlotIndex insertMachineInstrInMaps(MachineInstr &MI, bool Late=false)
Insert the given machine instruction into the mapping.
Implements a dense probed hash-table based set with some number of buckets stored inline.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Object returned by analyzeLoopForPipelining.
virtual ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *, const ScheduleDAGMI *DAG) const
Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...
virtual MachineInstr * createPHIDestinationCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual const MachineOperand & getCalleeOperand(const MachineInstr &MI) const
Returns the callee operand from the given MI.
virtual void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig, LaneBitmask UsedLanes=LaneBitmask::getAll()) const
Re-issue the specified 'original' instruction at the specific location targeting a new destination re...
virtual MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const
This method commutes the operands of the given machine instruction MI.
virtual bool isGlobalMemoryObject(const MachineInstr *MI) const
Returns true if MI is an instruction we are unable to reason about (like a call or something with unm...
virtual bool expandPostRAPseudo(MachineInstr &MI) const
This function is called for all pseudo instructions that remain after register allocation.
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
const MCWriteProcResEntry * ProcResIter
static constexpr TypeSize getFixed(ScalarTy ExactSize)
A Use represents the edge between a Value definition and its users.
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ PRIVATE_ADDRESS
Address space for private memory.
unsigned encodeFieldSaSdst(unsigned Encoded, unsigned SaSdst)
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi)
const uint64_t RSRC_DATA_FORMAT
bool isPKFMACF16InlineConstant(uint32_t Literal, bool IsGFX11Plus)
LLVM_READONLY const MIMGInfo * getMIMGInfo(unsigned Opc)
bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi)
bool getWMMAIsXDL(unsigned Opc)
unsigned mapWMMA2AddrTo3AddrOpcode(unsigned Opc)
bool isInlinableLiteralV2I16(uint32_t Literal)
bool isDPMACCInstruction(unsigned Opc)
bool isHi16Reg(MCRegister Reg, const MCRegisterInfo &MRI)
bool isInlinableLiteralV2BF16(uint32_t Literal)
LLVM_READONLY int32_t getCommuteRev(uint32_t Opcode)
LLVM_READONLY int32_t getCommuteOrig(uint32_t Opcode)
unsigned getNumFlatOffsetBits(const MCSubtargetInfo &ST)
For pre-GFX12 FLAT instructions the offset must be positive; MSB is ignored and forced to zero.
bool isGFX12Plus(const MCSubtargetInfo &STI)
bool isInlinableLiteralV2F16(uint32_t Literal)
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
bool isValid32BitLiteral(uint64_t Val, bool IsFP64)
LLVM_READONLY int32_t getGlobalVaddrOp(uint32_t Opcode)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
LLVM_READONLY int32_t getMFMAEarlyClobberOp(uint32_t Opcode)
bool getMAIIsGFX940XDL(unsigned Opc)
const uint64_t RSRC_ELEMENT_SIZE_SHIFT
bool isIntrinsicAlwaysUniform(unsigned IntrID)
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, OpName NamedIdx)
bool isPackedSingleSGPR64BitInst(unsigned Opc)
The opcode is a packed 64-bit instruction which only reads low 64 bits of a scalar operand and propag...
LLVM_READONLY int32_t getIfAddr64Inst(uint32_t Opcode)
Check if Opcode is an Addr64 opcode.
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfoByEncoding(uint8_t DimEnc)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
const uint64_t RSRC_TID_ENABLE
LLVM_READONLY int32_t getVOPe32(uint32_t Opcode)
bool isIntrinsicSourceOfDivergence(unsigned IntrID)
constexpr bool isSISrcOperand(const MCOperandInfo &OpInfo)
Is this an AMDGPU specific source operand?
bool isGenericAtomic(unsigned Opc)
LLVM_READNONE bool isInlinableIntLiteral(int64_t Literal)
Is this literal inlinable, and not one of the values intended for floating point values.
unsigned getAddrSizeMIMGOp(const MIMGBaseOpcodeInfo *BaseOpcode, const MIMGDimInfo *Dim, bool IsA16, bool IsG16Supported)
LLVM_READONLY int32_t getAddr64Inst(uint32_t Opcode)
int32_t getMCOpcode(uint32_t Opcode, unsigned Gen)
@ OPERAND_KIMM32
Operand with 32-bit immediate that uses the constant bus.
@ OPERAND_REG_INLINE_C_FP64
@ OPERAND_REG_INLINE_C_BF16
@ OPERAND_REG_INLINE_C_V2BF16
@ OPERAND_REG_IMM_V2INT64
@ OPERAND_REG_IMM_V2INT16
@ OPERAND_REG_IMM_INT32
Operands with register, 32-bit, or 64-bit immediate.
@ OPERAND_REG_IMM_V2FP16_SPLAT
@ OPERAND_REG_INLINE_C_INT64
@ OPERAND_REG_INLINE_C_INT16
Operands with register or inline constant.
@ OPERAND_REG_IMM_NOINLINE_V2FP16
@ OPERAND_REG_INLINE_C_V2FP16
@ OPERAND_REG_INLINE_AC_INT32
Operands with an AccVGPR register or inline constant.
@ OPERAND_REG_INLINE_AC_FP32
@ OPERAND_REG_IMM_V2INT32
@ OPERAND_REG_INLINE_C_FP32
@ OPERAND_REG_INLINE_C_INT32
@ OPERAND_REG_INLINE_C_V2INT16
@ OPERAND_INLINE_C_AV64_PSEUDO
@ OPERAND_REG_INLINE_AC_FP64
@ OPERAND_REG_INLINE_C_FP16
@ OPERAND_INLINE_SPLIT_BARRIER_INT32
LLVM_READONLY int32_t getBasicFromSDWAOp(uint32_t Opcode)
bool isDPALU_DPP(const MCInstrDesc &OpDesc, const MCInstrInfo &MII, const MCSubtargetInfo &ST)
bool isSingleSGPRReadInst(unsigned Opc)
Packed instructions that read a single SGPR for SGPR operands, except for 64-bit elements which read ...
bool supportsScaleOffset(const MCInstrInfo &MII, unsigned Opcode)
const uint64_t RSRC_INDEX_STRIDE_SHIFT
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
LLVM_READONLY int32_t getFlatScratchInstSVfromSS(uint32_t Opcode)
bool isInlinableLiteralI16(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool isGraphics(CallingConv::ID CC)
bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi)
Is this literal inlinable.
@ AMDGPU_CS
Used for Mesa/AMDPAL compute shaders.
@ AMDGPU_VS
Used for Mesa vertex shaders, or AMDPAL last shader stage before rasterization (vertex shader if tess...
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ AMDGPU_HS
Used for Mesa/AMDPAL hull shaders (= tessellation control shaders).
@ AMDGPU_GS
Used for Mesa/AMDPAL geometry shaders.
@ AMDGPU_PS
Used for Mesa/AMDPAL pixel shaders.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ AMDGPU_ES
Used for AMDPAL shader stage before geometry shader if geometry is in use.
@ AMDGPU_LS
Used for AMDPAL vertex shader if tessellation is in use.
@ C
The default llvm calling convention, compatible with C.
Not(const Pred &P) -> Not< Pred >
constexpr bool isD16Buf(const T &...O)
constexpr bool isSDWA(const T &...O)
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
LLVM_ABI void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...
TargetInstrInfo::RegSubRegPair getRegSubRegPair(const MachineOperand &O)
Create RegSubRegPair from a register MachineOperand.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
constexpr uint64_t maxUIntN(uint64_t N)
Gets the maximum value for a N-bit unsigned integer.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
bool execMayBeModifiedBeforeUse(const MachineRegisterInfo &MRI, Register VReg, const MachineInstr &DefMI, const MachineInstr &UseMI)
Return false if EXEC is not changed between the def of VReg at DefMI and the use at UseMI.
RegState
Flags to represent properties of register accesses.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
TargetInstrInfo::RegSubRegPair getRegSequenceSubReg(MachineInstr &MI, unsigned SubReg)
Return the SubReg component from REG_SEQUENCE.
static const MachineMemOperand::Flags MONoClobber
Mark the MMO of a uniform load if there are no potentially clobbering stores on any path from the sta...
constexpr bool has_single_bit(T Value) noexcept
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
auto reverse(ContainerTy &&C)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
MachineInstr * getVRegSubRegDef(const TargetInstrInfo::RegSubRegPair &P, const MachineRegisterInfo &MRI)
Return the defining instruction for a given reg:subreg pair skipping copy like instructions and subre...
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI VirtRegInfo AnalyzeVirtRegInBundle(MachineInstr &MI, Register Reg, SmallVectorImpl< std::pair< MachineInstr *, unsigned > > *Ops=nullptr)
AnalyzeVirtRegInBundle - Analyze how the current instruction or bundle uses a virtual register.
static const MachineMemOperand::Flags MOCooperative
Mark the MMO of cooperative load/store atomics.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
bool isTargetSpecificOpcode(unsigned Opcode)
Check whether the given Opcode is a target-specific opcode.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned DefaultMemoryClusterDWordsLimit
constexpr unsigned BitWidth
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
static const MachineMemOperand::Flags MOLastUse
Mark the MMO of a load as the last use.
constexpr T reverseBits(T Val)
Reverse the bits in Val.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
constexpr RegState getUndefRegState(bool B)
ValueUniformity
Enum describing how values behave with respect to uniformity and divergence, to answer the question: ...
@ AlwaysUniform
The result value is always uniform.
@ NeverUniform
The result value can never be assumed to be uniform.
@ Default
The result value is uniform if and only if all operands are uniform.
static const MachineMemOperand::Flags MOThreadPrivate
Mark the MMO of accesses to memory locations that are never written to by other threads.
bool execMayBeModifiedBeforeAnyUse(const MachineRegisterInfo &MRI, Register VReg, const MachineInstr &DefMI)
Return false if EXEC is not changed between the def of VReg at DefMI and all its uses.
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Helper struct for the implementation of 3-address conversion to communicate updates made to instructi...
MachineInstr * RemoveMIUse
Other instruction whose def is no longer used by the converted instruction.
static constexpr uint64_t encode(Fields... Values)
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr bool all() const
SparseBitVector AliveBlocks
AliveBlocks - Set of blocks in which this value is alive completely through.
Summarize the scheduling resources required for an instruction of a particular scheduling class.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
Utility to store machine instructions worklist.
MachineInstr * top() const
bool isDeferred(MachineInstr *MI)
SetVector< MachineInstr * > & getDeferredList()
void insert(MachineInstr *MI)
A pair composed of a register and a sub-register index.
VirtRegInfo - Information about a virtual register used by a set of operands.
bool Reads
Reads - One of the operands read the virtual register.
bool Writes
Writes - One of the operands writes the virtual register.