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)
264 case AMDGPU::V_SUBREV_U16_e32:
265 case AMDGPU::V_SUBREV_U16_e64:
267 case AMDGPU::V_SUBREV_U32_e32:
268 case AMDGPU::V_SUBREV_U32_e64:
270 case AMDGPU::V_SUBREV_CO_U32_e32:
271 case AMDGPU::V_SUBREV_CO_U32_e64:
273 case AMDGPU::V_SUBBREV_U32_e32:
274 case AMDGPU::V_SUBBREV_U32_e64:
277 case AMDGPU::V_ASHRREV_I16_e32:
278 case AMDGPU::V_ASHRREV_I16_e64:
279 case AMDGPU::V_ASHRREV_I32_e32:
280 case AMDGPU::V_ASHRREV_I32_e64:
281 case AMDGPU::V_ASHRREV_I64_e64:
282 case AMDGPU::V_LSHLREV_B16_e32:
283 case AMDGPU::V_LSHLREV_B16_e64:
284 case AMDGPU::V_LSHLREV_B32_e32:
285 case AMDGPU::V_LSHLREV_B32_e64:
286 case AMDGPU::V_LSHLREV_B64_e64:
287 case AMDGPU::V_LSHRREV_B16_e32:
288 case AMDGPU::V_LSHRREV_B16_e64:
289 case AMDGPU::V_LSHRREV_B32_e32:
290 case AMDGPU::V_LSHRREV_B32_e64:
291 case AMDGPU::V_LSHRREV_B64_e64:
292 return !ST.hasGFX11Insts();
299bool SIInstrInfo::resultDependsOnExec(
const MachineInstr &
MI)
const {
303 if (
MI.isConvergent())
331 if (
MI.getOpcode() == AMDGPU::SI_IF_BREAK)
336 for (
auto Op :
MI.uses()) {
337 if (
Op.isReg() &&
Op.getReg().isVirtual() &&
351 while (FromCycle && !(ToCycle && CI->
contains(FromCycle, ToCycle))) {
371 int64_t &Offset1)
const {
379 if (!
get(Opc0).mayLoad() || !
get(Opc1).mayLoad())
383 if (!
get(Opc0).getNumDefs() || !
get(Opc1).getNumDefs())
399 int Offset0Idx = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
400 int Offset1Idx = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
401 if (Offset0Idx == -1 || Offset1Idx == -1)
408 Offset0Idx -=
get(Opc0).NumDefs;
409 Offset1Idx -=
get(Opc1).NumDefs;
439 if (!Load0Offset || !Load1Offset)
456 int OffIdx0 = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
457 int OffIdx1 = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
459 if (OffIdx0 == -1 || OffIdx1 == -1)
465 OffIdx0 -=
get(Opc0).NumDefs;
466 OffIdx1 -=
get(Opc1).NumDefs;
485 case AMDGPU::DS_READ2ST64_B32:
486 case AMDGPU::DS_READ2ST64_B64:
487 case AMDGPU::DS_WRITE2ST64_B32:
488 case AMDGPU::DS_WRITE2ST64_B64:
503 OffsetIsScalable =
false;
520 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
522 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
523 if (
Opc == AMDGPU::DS_ATOMIC_ASYNC_BARRIER_ARRIVE_B64)
536 unsigned Offset0 = Offset0Op->
getImm() & 0xff;
537 unsigned Offset1 = Offset1Op->
getImm() & 0xff;
538 if (Offset0 + 1 != Offset1)
549 int Data0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
557 Offset = EltSize * Offset0;
559 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
560 if (DataOpIdx == -1) {
561 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
563 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
579 if (BaseOp && !BaseOp->
isFI())
587 if (SOffset->
isReg())
593 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
595 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
604 isMIMG(LdSt) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
605 int SRsrcIdx = AMDGPU::getNamedOperandIdx(
Opc, RsrcOpName);
607 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
608 if (VAddr0Idx >= 0) {
610 for (
int I = VAddr0Idx;
I < SRsrcIdx; ++
I)
617 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
632 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::sdst);
649 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
651 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
668 if (BaseOps1.
front()->isIdenticalTo(*BaseOps2.
front()))
676 if (MO1->getAddrSpace() != MO2->getAddrSpace())
679 const auto *Base1 = MO1->getValue();
680 const auto *Base2 = MO2->getValue();
681 if (!Base1 || !Base2)
689 return Base1 == Base2;
693 int64_t Offset1,
bool OffsetIsScalable1,
695 int64_t Offset2,
bool OffsetIsScalable2,
696 unsigned ClusterSize,
697 unsigned NumBytes)
const {
710 }
else if (!BaseOps1.
empty() || !BaseOps2.
empty()) {
729 const unsigned LoadSize = NumBytes / ClusterSize;
730 const unsigned NumDWords = ((LoadSize + 3) / 4) * ClusterSize;
731 return NumDWords <= MaxMemoryClusterDWords;
745 int64_t Offset0, int64_t Offset1,
746 unsigned NumLoads)
const {
747 assert(Offset1 > Offset0 &&
748 "Second offset should be larger than first offset!");
753 return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
760 const char *
Msg =
"illegal VGPR to SGPR copy") {
779 assert((
TII.getSubtarget().hasMAIInsts() &&
780 !
TII.getSubtarget().hasGFX90AInsts()) &&
781 "Expected GFX908 subtarget.");
784 AMDGPU::AGPR_32RegClass.
contains(SrcReg)) &&
785 "Source register of the copy should be either an SGPR or an AGPR.");
788 "Destination register of the copy should be an AGPR.");
797 for (
auto Def =
MI,
E =
MBB.begin(); Def !=
E; ) {
800 if (!Def->modifiesRegister(SrcReg, &RI))
803 if (Def->getOpcode() != AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
804 Def->getOperand(0).getReg() != SrcReg)
811 bool SafeToPropagate =
true;
814 for (
auto I = Def;
I !=
MI && SafeToPropagate; ++
I)
815 if (
I->modifiesRegister(DefOp.
getReg(), &RI))
816 SafeToPropagate =
false;
818 if (!SafeToPropagate)
821 for (
auto I = Def;
I !=
MI; ++
I)
822 I->clearRegisterKills(DefOp.
getReg(), &RI);
830 if (ImpUseSuperReg) {
831 Builder.addReg(ImpUseSuperReg,
839 RS.enterBasicBlockEnd(
MBB);
840 RS.backward(std::next(
MI));
849 unsigned RegNo = (DestReg - AMDGPU::AGPR0) % 3;
852 assert(
MBB.getParent()->getRegInfo().isReserved(Tmp) &&
853 "VGPR used for an intermediate copy should have been reserved.");
858 Register Tmp2 = RS.scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass,
MI,
868 unsigned TmpCopyOp = AMDGPU::V_MOV_B32_e32;
869 if (AMDGPU::AGPR_32RegClass.
contains(SrcReg)) {
870 TmpCopyOp = AMDGPU::V_ACCVGPR_READ_B32_e64;
877 if (ImpUseSuperReg) {
878 UseBuilder.
addReg(ImpUseSuperReg,
895 for (
unsigned Idx = 0; Idx < BaseIndices.
size(); ++Idx) {
896 int16_t SubIdx = BaseIndices[Idx];
897 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
898 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
899 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
900 unsigned Opcode = AMDGPU::S_MOV_B32;
903 bool AlignedDest = ((DestSubReg - AMDGPU::SGPR0) % 2) == 0;
904 bool AlignedSrc = ((SrcSubReg - AMDGPU::SGPR0) % 2) == 0;
905 if (AlignedDest && AlignedSrc && (Idx + 1 < BaseIndices.
size())) {
909 DestSubReg = RI.getSubReg(DestReg, SubIdx);
910 SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
911 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
912 Opcode = AMDGPU::S_MOV_B64;
927 assert(FirstMI && LastMI);
932 LastMI->addRegisterKilled(SrcReg, &RI);
938 Register SrcReg,
bool KillSrc,
bool RenamableDest,
939 bool RenamableSrc)
const {
941 unsigned Size = RI.getRegSizeInBits(*RC);
943 unsigned SrcSize = RI.getRegSizeInBits(*SrcRC);
949 if (((
Size == 16) != (SrcSize == 16))) {
951 assert(ST.useRealTrue16Insts());
953 MCRegister SubReg = RI.getSubReg(RegToFix, AMDGPU::lo16);
956 if (DestReg == SrcReg) {
962 RC = RI.getPhysRegBaseClass(DestReg);
963 Size = RI.getRegSizeInBits(*RC);
964 SrcRC = RI.getPhysRegBaseClass(SrcReg);
965 SrcSize = RI.getRegSizeInBits(*SrcRC);
969 if (RC == &AMDGPU::VGPR_32RegClass) {
971 AMDGPU::SReg_32RegClass.
contains(SrcReg) ||
972 AMDGPU::AGPR_32RegClass.
contains(SrcReg));
973 unsigned Opc = AMDGPU::AGPR_32RegClass.contains(SrcReg) ?
974 AMDGPU::V_ACCVGPR_READ_B32_e64 : AMDGPU::V_MOV_B32_e32;
980 if (RC == &AMDGPU::SReg_32_XM0RegClass ||
981 RC == &AMDGPU::SReg_32RegClass) {
982 if (SrcReg == AMDGPU::SCC) {
989 if (!AMDGPU::SReg_32RegClass.
contains(SrcReg)) {
990 if (DestReg == AMDGPU::VCC_LO) {
1008 if (RC == &AMDGPU::SReg_64RegClass) {
1009 if (SrcReg == AMDGPU::SCC) {
1016 if (!AMDGPU::SReg_64_EncodableRegClass.
contains(SrcReg)) {
1017 if (DestReg == AMDGPU::VCC) {
1035 if (DestReg == AMDGPU::SCC) {
1038 if (AMDGPU::SReg_64RegClass.
contains(SrcReg)) {
1042 assert(ST.hasScalarCompareEq64());
1056 if (RC == &AMDGPU::AGPR_32RegClass) {
1057 if (AMDGPU::VGPR_32RegClass.
contains(SrcReg) ||
1058 (ST.hasGFX90AInsts() && AMDGPU::SReg_32RegClass.contains(SrcReg))) {
1064 if (AMDGPU::AGPR_32RegClass.
contains(SrcReg) && ST.hasGFX90AInsts()) {
1073 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1080 AMDGPU::SReg_LO16RegClass.
contains(SrcReg) ||
1081 AMDGPU::AGPR_LO16RegClass.
contains(SrcReg));
1083 bool IsSGPRDst = AMDGPU::SReg_LO16RegClass.contains(DestReg);
1084 bool IsSGPRSrc = AMDGPU::SReg_LO16RegClass.contains(SrcReg);
1085 bool IsAGPRDst = AMDGPU::AGPR_LO16RegClass.contains(DestReg);
1086 bool IsAGPRSrc = AMDGPU::AGPR_LO16RegClass.contains(SrcReg);
1089 MCRegister NewDestReg = RI.get32BitRegister(DestReg);
1090 MCRegister NewSrcReg = RI.get32BitRegister(SrcReg);
1103 if (IsAGPRDst || IsAGPRSrc) {
1104 if (!DstLow || !SrcLow) {
1106 "Cannot use hi16 subreg with an AGPR!");
1113 if (ST.useRealTrue16Insts()) {
1119 if (AMDGPU::VGPR_16_Lo128RegClass.
contains(DestReg) &&
1120 (IsSGPRSrc || AMDGPU::VGPR_16_Lo128RegClass.
contains(SrcReg))) {
1132 if (IsSGPRSrc && !ST.hasSDWAScalar()) {
1133 if (!DstLow || !SrcLow) {
1135 "Cannot use hi16 subreg on VI!");
1161 unsigned SrcOp = 1) {
1165 return DstOpRC && SrcOpRC && DstOpRC->
contains(Dst) &&
1169 if (RC == RI.getVGPR64Class() && (SrcRC == RC || RI.isSGPRClass(SrcRC))) {
1170 if (ST.hasVMovB64Inst() &&
1171 CanCopyWith(AMDGPU::V_MOV_B64_e32, DestReg, SrcReg)) {
1176 if (ST.hasPkMovB32() &&
1177 CanCopyWith(AMDGPU::V_PK_MOV_B32, DestReg, SrcReg, 2)) {
1193 const bool Forward = RI.getHWRegIndex(DestReg) <= RI.getHWRegIndex(SrcReg);
1194 if (RI.isSGPRClass(RC)) {
1195 if (!RI.isSGPRClass(SrcRC)) {
1199 const bool CanKillSuperReg = KillSrc && !RI.regsOverlap(SrcReg, DestReg);
1205 unsigned Opcode = AMDGPU::V_MOV_B32_e32;
1206 unsigned WideOpcode = AMDGPU::INSTRUCTION_LIST_END;
1207 if (RI.isAGPRClass(RC)) {
1208 if (ST.hasGFX90AInsts() && RI.isAGPRClass(SrcRC))
1209 Opcode = AMDGPU::V_ACCVGPR_MOV_B32;
1210 else if (RI.hasVGPRs(SrcRC) ||
1211 (ST.hasGFX90AInsts() && RI.isSGPRClass(SrcRC)))
1212 Opcode = AMDGPU::V_ACCVGPR_WRITE_B32_e64;
1214 Opcode = AMDGPU::INSTRUCTION_LIST_END;
1215 }
else if (RI.hasVGPRs(RC) && RI.isAGPRClass(SrcRC)) {
1216 Opcode = AMDGPU::V_ACCVGPR_READ_B32_e64;
1217 }
else if (RI.isVGPRClass(RC)) {
1218 if (ST.hasVMovB64Inst())
1219 WideOpcode = AMDGPU::V_MOV_B64_e32;
1220 else if (ST.hasPkMovB32())
1221 WideOpcode = AMDGPU::V_PK_MOV_B32;
1225 if (WideOpcode != AMDGPU::INSTRUCTION_LIST_END) {
1227 unsigned SrcOp = WideOpcode == AMDGPU::V_PK_MOV_B32 ? 2 : 1;
1234 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1235 const bool CanKillSuperReg = KillSrc && !Overlap;
1242 std::unique_ptr<RegScavenger> RS;
1243 if (Opcode == AMDGPU::INSTRUCTION_LIST_END)
1244 RS = std::make_unique<RegScavenger>();
1248 for (
unsigned Idx{}; Idx < SubIndices.
size();) {
1249 unsigned NumRegs = 1;
1250 unsigned ThisOpcode = Opcode;
1252 Forward ? SubIndices[Idx] : SubIndices[SubIndices.
size() - Idx - 1];
1254 if (WideDstRC && WideSrcRC && Idx + 1 < SubIndices.
size()) {
1255 unsigned Channel = RI.getChannelFromSubReg(SubIdx);
1259 unsigned WideSubIdx = RI.getSubRegFromChannel(Channel, 2);
1260 Register WideDst = RI.getSubReg(DestReg, WideSubIdx);
1261 Register WideSrc = RI.getSubReg(SrcReg, WideSubIdx);
1263 if (WideDst && WideSrc && WideDstRC->
contains(WideDst) &&
1264 WideSrcRC->contains(WideSrc)) {
1265 SubIdx = WideSubIdx;
1267 ThisOpcode = WideOpcode;
1271 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
1272 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
1273 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
1276 bool UseKill = CanKillSuperReg && Idx == SubIndices.
size();
1278 if (ThisOpcode == AMDGPU::INSTRUCTION_LIST_END) {
1281 *RS, Overlap, ImpUseSuper);
1282 }
else if (ThisOpcode == AMDGPU::V_PK_MOV_B32) {
1323 int64_t &ImmVal)
const {
1324 switch (
MI.getOpcode()) {
1325 case AMDGPU::V_MOV_B32_e32:
1326 case AMDGPU::S_MOV_B32:
1327 case AMDGPU::S_MOVK_I32:
1328 case AMDGPU::S_MOV_B64:
1329 case AMDGPU::V_MOV_B64_e32:
1330 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
1331 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
1332 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
1333 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
1334 case AMDGPU::V_MOV_B64_PSEUDO:
1335 case AMDGPU::V_MOV_B16_t16_e32: {
1339 return MI.getOperand(0).getReg() == Reg;
1344 case AMDGPU::V_MOV_B16_t16_e64: {
1346 if (Src0.
isImm() && !
MI.getOperand(1).getImm()) {
1348 return MI.getOperand(0).getReg() == Reg;
1353 case AMDGPU::S_BREV_B32:
1354 case AMDGPU::V_BFREV_B32_e32:
1355 case AMDGPU::V_BFREV_B32_e64: {
1359 return MI.getOperand(0).getReg() == Reg;
1364 case AMDGPU::S_NOT_B32:
1365 case AMDGPU::V_NOT_B32_e32:
1366 case AMDGPU::V_NOT_B32_e64: {
1369 ImmVal =
static_cast<int64_t
>(~static_cast<int32_t>(Src0.
getImm()));
1370 return MI.getOperand(0).getReg() == Reg;
1380std::optional<int64_t>
1390 if (!
Op.isReg() || !
Op.getReg().isVirtual())
1391 return std::nullopt;
1393 if (Def && Def->isMoveImmediate()) {
1395 if (ImmSrc.
isImm()) {
1402 return std::nullopt;
1405std::optional<int64_t>
1414 if (RI.isAGPRClass(DstRC))
1415 return AMDGPU::COPY;
1416 if (RI.getRegSizeInBits(*DstRC) == 16) {
1419 return RI.isSGPRClass(DstRC) ? AMDGPU::COPY : AMDGPU::V_MOV_B16_t16_e64;
1421 if (RI.getRegSizeInBits(*DstRC) == 32)
1422 return RI.isSGPRClass(DstRC) ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1423 if (RI.getRegSizeInBits(*DstRC) == 64 && RI.isSGPRClass(DstRC))
1424 return AMDGPU::S_MOV_B64;
1425 if (RI.getRegSizeInBits(*DstRC) == 64 && !RI.isSGPRClass(DstRC))
1426 return AMDGPU::V_MOV_B64_PSEUDO;
1427 return AMDGPU::COPY;
1432 bool IsIndirectSrc)
const {
1433 if (IsIndirectSrc) {
1435 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1);
1437 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2);
1439 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3);
1441 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4);
1443 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5);
1445 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6);
1447 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7);
1449 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8);
1451 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9);
1453 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10);
1455 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11);
1457 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12);
1459 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16);
1460 if (VecSize <= 1024)
1461 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32);
1467 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1);
1469 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2);
1471 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3);
1473 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4);
1475 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5);
1477 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6);
1479 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7);
1481 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8);
1483 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9);
1485 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10);
1487 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11);
1489 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12);
1491 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16);
1492 if (VecSize <= 1024)
1493 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32);
1500 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1502 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1504 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1506 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1508 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1510 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1512 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1514 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1516 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1518 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1520 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1522 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1524 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1525 if (VecSize <= 1024)
1526 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1533 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1535 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1537 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1539 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1541 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1543 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1545 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1547 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1549 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1551 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1553 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1555 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1557 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1558 if (VecSize <= 1024)
1559 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1566 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1;
1568 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2;
1570 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4;
1572 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8;
1573 if (VecSize <= 1024)
1574 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16;
1581 bool IsSGPR)
const {
1593 assert(EltSize == 32 &&
"invalid reg indexing elt size");
1600 return NeedsCFI ? AMDGPU::SI_SPILL_S32_CFI_SAVE : AMDGPU::SI_SPILL_S32_SAVE;
1602 return NeedsCFI ? AMDGPU::SI_SPILL_S64_CFI_SAVE : AMDGPU::SI_SPILL_S64_SAVE;
1604 return NeedsCFI ? AMDGPU::SI_SPILL_S96_CFI_SAVE : AMDGPU::SI_SPILL_S96_SAVE;
1606 return NeedsCFI ? AMDGPU::SI_SPILL_S128_CFI_SAVE
1607 : AMDGPU::SI_SPILL_S128_SAVE;
1609 return NeedsCFI ? AMDGPU::SI_SPILL_S160_CFI_SAVE
1610 : AMDGPU::SI_SPILL_S160_SAVE;
1612 return NeedsCFI ? AMDGPU::SI_SPILL_S192_CFI_SAVE
1613 : AMDGPU::SI_SPILL_S192_SAVE;
1615 return NeedsCFI ? AMDGPU::SI_SPILL_S224_CFI_SAVE
1616 : AMDGPU::SI_SPILL_S224_SAVE;
1618 return AMDGPU::SI_SPILL_S256_SAVE;
1620 return AMDGPU::SI_SPILL_S288_SAVE;
1622 return AMDGPU::SI_SPILL_S320_SAVE;
1624 return AMDGPU::SI_SPILL_S352_SAVE;
1626 return AMDGPU::SI_SPILL_S384_SAVE;
1628 return NeedsCFI ? AMDGPU::SI_SPILL_S512_CFI_SAVE
1629 : AMDGPU::SI_SPILL_S512_SAVE;
1631 return NeedsCFI ? AMDGPU::SI_SPILL_S1024_CFI_SAVE
1632 : AMDGPU::SI_SPILL_S1024_SAVE;
1641 return AMDGPU::SI_SPILL_V16_SAVE;
1643 return NeedsCFI ? AMDGPU::SI_SPILL_V32_CFI_SAVE : AMDGPU::SI_SPILL_V32_SAVE;
1645 return NeedsCFI ? AMDGPU::SI_SPILL_V64_CFI_SAVE : AMDGPU::SI_SPILL_V64_SAVE;
1647 return NeedsCFI ? AMDGPU::SI_SPILL_V96_CFI_SAVE : AMDGPU::SI_SPILL_V96_SAVE;
1649 return NeedsCFI ? AMDGPU::SI_SPILL_V128_CFI_SAVE
1650 : AMDGPU::SI_SPILL_V128_SAVE;
1652 return NeedsCFI ? AMDGPU::SI_SPILL_V160_CFI_SAVE
1653 : AMDGPU::SI_SPILL_V160_SAVE;
1655 return NeedsCFI ? AMDGPU::SI_SPILL_V192_CFI_SAVE
1656 : AMDGPU::SI_SPILL_V192_SAVE;
1658 return NeedsCFI ? AMDGPU::SI_SPILL_V224_CFI_SAVE
1659 : AMDGPU::SI_SPILL_V224_SAVE;
1661 return NeedsCFI ? AMDGPU::SI_SPILL_V256_CFI_SAVE
1662 : AMDGPU::SI_SPILL_V256_SAVE;
1664 return NeedsCFI ? AMDGPU::SI_SPILL_V288_CFI_SAVE
1665 : AMDGPU::SI_SPILL_V288_SAVE;
1667 return NeedsCFI ? AMDGPU::SI_SPILL_V320_CFI_SAVE
1668 : AMDGPU::SI_SPILL_V320_SAVE;
1670 return NeedsCFI ? AMDGPU::SI_SPILL_V352_CFI_SAVE
1671 : AMDGPU::SI_SPILL_V352_SAVE;
1673 return NeedsCFI ? AMDGPU::SI_SPILL_V384_CFI_SAVE
1674 : AMDGPU::SI_SPILL_V384_SAVE;
1676 return NeedsCFI ? AMDGPU::SI_SPILL_V512_CFI_SAVE
1677 : AMDGPU::SI_SPILL_V512_SAVE;
1679 return NeedsCFI ? AMDGPU::SI_SPILL_V1024_CFI_SAVE
1680 : AMDGPU::SI_SPILL_V1024_SAVE;
1689 return NeedsCFI ? AMDGPU::SI_SPILL_AV32_CFI_SAVE
1690 : AMDGPU::SI_SPILL_AV32_SAVE;
1692 return NeedsCFI ? AMDGPU::SI_SPILL_AV64_CFI_SAVE
1693 : AMDGPU::SI_SPILL_AV64_SAVE;
1695 return NeedsCFI ? AMDGPU::SI_SPILL_AV96_CFI_SAVE
1696 : AMDGPU::SI_SPILL_AV96_SAVE;
1698 return NeedsCFI ? AMDGPU::SI_SPILL_AV128_CFI_SAVE
1699 : AMDGPU::SI_SPILL_AV128_SAVE;
1701 return NeedsCFI ? AMDGPU::SI_SPILL_AV160_CFI_SAVE
1702 : AMDGPU::SI_SPILL_AV160_SAVE;
1704 return NeedsCFI ? AMDGPU::SI_SPILL_AV192_CFI_SAVE
1705 : AMDGPU::SI_SPILL_AV192_SAVE;
1707 return NeedsCFI ? AMDGPU::SI_SPILL_AV224_CFI_SAVE
1708 : AMDGPU::SI_SPILL_AV224_SAVE;
1710 return NeedsCFI ? AMDGPU::SI_SPILL_AV256_CFI_SAVE
1711 : AMDGPU::SI_SPILL_AV256_SAVE;
1713 return AMDGPU::SI_SPILL_AV288_SAVE;
1715 return AMDGPU::SI_SPILL_AV320_SAVE;
1717 return AMDGPU::SI_SPILL_AV352_SAVE;
1719 return AMDGPU::SI_SPILL_AV384_SAVE;
1721 return NeedsCFI ? AMDGPU::SI_SPILL_AV512_CFI_SAVE
1722 : AMDGPU::SI_SPILL_AV512_SAVE;
1724 return NeedsCFI ? AMDGPU::SI_SPILL_AV1024_CFI_SAVE
1725 : AMDGPU::SI_SPILL_AV1024_SAVE;
1732 bool IsVectorSuperClass) {
1737 if (IsVectorSuperClass)
1738 return AMDGPU::SI_SPILL_WWM_AV32_SAVE;
1740 return AMDGPU::SI_SPILL_WWM_V32_SAVE;
1746 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1753 if (ST.hasMAIInsts())
1759void SIInstrInfo::storeRegToStackSlotImpl(
1772 FrameInfo.getObjectAlign(FrameIndex));
1773 unsigned SpillSize = RI.getSpillSize(*RC);
1779 assert(SrcReg != AMDGPU::M0 &&
"m0 should not be spilled");
1780 assert(SrcReg != AMDGPU::EXEC_LO && SrcReg != AMDGPU::EXEC_HI &&
1781 SrcReg != AMDGPU::EXEC &&
"exec should not be spilled");
1790 if (SrcReg.
isVirtual() && SpillSize == 4) {
1804 SpillSize, *MFI, NeedsCFI);
1819 storeRegToStackSlotImpl(
MBB,
MI, SrcReg, isKill, FrameIndex, RC, VReg, Flags,
1828 storeRegToStackSlotImpl(
MBB,
MI, SrcReg, isKill, FrameIndex, RC,
Register(),
1835 return AMDGPU::SI_SPILL_S32_RESTORE;
1837 return AMDGPU::SI_SPILL_S64_RESTORE;
1839 return AMDGPU::SI_SPILL_S96_RESTORE;
1841 return AMDGPU::SI_SPILL_S128_RESTORE;
1843 return AMDGPU::SI_SPILL_S160_RESTORE;
1845 return AMDGPU::SI_SPILL_S192_RESTORE;
1847 return AMDGPU::SI_SPILL_S224_RESTORE;
1849 return AMDGPU::SI_SPILL_S256_RESTORE;
1851 return AMDGPU::SI_SPILL_S288_RESTORE;
1853 return AMDGPU::SI_SPILL_S320_RESTORE;
1855 return AMDGPU::SI_SPILL_S352_RESTORE;
1857 return AMDGPU::SI_SPILL_S384_RESTORE;
1859 return AMDGPU::SI_SPILL_S512_RESTORE;
1861 return AMDGPU::SI_SPILL_S1024_RESTORE;
1870 return AMDGPU::SI_SPILL_V16_RESTORE;
1872 return AMDGPU::SI_SPILL_V32_RESTORE;
1874 return AMDGPU::SI_SPILL_V64_RESTORE;
1876 return AMDGPU::SI_SPILL_V96_RESTORE;
1878 return AMDGPU::SI_SPILL_V128_RESTORE;
1880 return AMDGPU::SI_SPILL_V160_RESTORE;
1882 return AMDGPU::SI_SPILL_V192_RESTORE;
1884 return AMDGPU::SI_SPILL_V224_RESTORE;
1886 return AMDGPU::SI_SPILL_V256_RESTORE;
1888 return AMDGPU::SI_SPILL_V288_RESTORE;
1890 return AMDGPU::SI_SPILL_V320_RESTORE;
1892 return AMDGPU::SI_SPILL_V352_RESTORE;
1894 return AMDGPU::SI_SPILL_V384_RESTORE;
1896 return AMDGPU::SI_SPILL_V512_RESTORE;
1898 return AMDGPU::SI_SPILL_V1024_RESTORE;
1907 return AMDGPU::SI_SPILL_AV32_RESTORE;
1909 return AMDGPU::SI_SPILL_AV64_RESTORE;
1911 return AMDGPU::SI_SPILL_AV96_RESTORE;
1913 return AMDGPU::SI_SPILL_AV128_RESTORE;
1915 return AMDGPU::SI_SPILL_AV160_RESTORE;
1917 return AMDGPU::SI_SPILL_AV192_RESTORE;
1919 return AMDGPU::SI_SPILL_AV224_RESTORE;
1921 return AMDGPU::SI_SPILL_AV256_RESTORE;
1923 return AMDGPU::SI_SPILL_AV288_RESTORE;
1925 return AMDGPU::SI_SPILL_AV320_RESTORE;
1927 return AMDGPU::SI_SPILL_AV352_RESTORE;
1929 return AMDGPU::SI_SPILL_AV384_RESTORE;
1931 return AMDGPU::SI_SPILL_AV512_RESTORE;
1933 return AMDGPU::SI_SPILL_AV1024_RESTORE;
1940 bool IsVectorSuperClass) {
1945 if (IsVectorSuperClass)
1946 return AMDGPU::SI_SPILL_WWM_AV32_RESTORE;
1948 return AMDGPU::SI_SPILL_WWM_V32_RESTORE;
1954 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1961 if (ST.hasMAIInsts())
1964 assert(!RI.isAGPRClass(RC));
1978 unsigned SpillSize = RI.getSpillSize(*RC);
1985 FrameInfo.getObjectAlign(FrameIndex));
1987 if (RI.isSGPRClass(RC)) {
1990 assert(DestReg != AMDGPU::M0 &&
"m0 should not be reloaded into");
1991 assert(DestReg != AMDGPU::EXEC_LO && DestReg != AMDGPU::EXEC_HI &&
1992 DestReg != AMDGPU::EXEC &&
"exec should not be spilled");
1997 if (DestReg.
isVirtual() && SpillSize == 4) {
2026 unsigned Quantity)
const {
2028 unsigned MaxSNopCount = 1u << ST.getSNopBits();
2029 while (Quantity > 0) {
2030 unsigned Arg = std::min(Quantity, MaxSNopCount);
2041 constexpr unsigned DoorbellIDMask = 0x3ff;
2042 constexpr unsigned ECQueueWaveAbort = 0x400;
2047 if (!
MBB.succ_empty() || std::next(
MI.getIterator()) !=
MBB.end()) {
2048 MBB.splitAt(
MI,
false);
2052 MBB.addSuccessor(TrapBB);
2062 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
2066 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_AND_B32), DoorbellRegMasked)
2071 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_OR_B32), SetWaveAbortBit)
2072 .
addUse(DoorbellRegMasked)
2073 .
addImm(ECQueueWaveAbort);
2074 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2075 .
addUse(SetWaveAbortBit);
2078 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2089 return MBB.getNextNode();
2093 switch (
MI.getOpcode()) {
2095 if (
MI.isMetaInstruction())
2100 return MI.getOperand(0).getImm() + 1;
2111 switch (
MI.getOpcode()) {
2113 case AMDGPU::S_MOV_B64_term:
2116 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2119 case AMDGPU::S_MOV_B32_term:
2122 MI.setDesc(
get(AMDGPU::S_MOV_B32));
2125 case AMDGPU::S_XOR_B64_term:
2128 MI.setDesc(
get(AMDGPU::S_XOR_B64));
2131 case AMDGPU::S_XOR_B32_term:
2134 MI.setDesc(
get(AMDGPU::S_XOR_B32));
2136 case AMDGPU::S_OR_B64_term:
2139 MI.setDesc(
get(AMDGPU::S_OR_B64));
2141 case AMDGPU::S_OR_B32_term:
2144 MI.setDesc(
get(AMDGPU::S_OR_B32));
2147 case AMDGPU::S_ANDN2_B64_term:
2150 MI.setDesc(
get(AMDGPU::S_ANDN2_B64));
2153 case AMDGPU::S_ANDN2_B32_term:
2156 MI.setDesc(
get(AMDGPU::S_ANDN2_B32));
2159 case AMDGPU::S_AND_B64_term:
2162 MI.setDesc(
get(AMDGPU::S_AND_B64));
2165 case AMDGPU::S_AND_B32_term:
2168 MI.setDesc(
get(AMDGPU::S_AND_B32));
2171 case AMDGPU::S_AND_SAVEEXEC_B64_term:
2174 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B64));
2177 case AMDGPU::S_AND_SAVEEXEC_B32_term:
2180 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B32));
2183 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
2184 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32));
2186 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
2187 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32));
2190 case AMDGPU::SI_SPILL_S32_TO_VGPR:
2191 MI.setDesc(
get(AMDGPU::V_WRITELANE_B32));
2194 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
2195 MI.setDesc(
get(AMDGPU::V_READLANE_B32));
2197 case AMDGPU::AV_MOV_B32_IMM_PSEUDO: {
2201 get(IsAGPR ? AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::V_MOV_B32_e32));
2204 case AMDGPU::AV_MOV_B64_IMM_PSEUDO: {
2207 int64_t
Imm =
MI.getOperand(1).getImm();
2209 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2210 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2215 MI.eraseFromParent();
2221 case AMDGPU::V_MOV_B64_PSEUDO: {
2223 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2224 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2232 if (ST.hasVMovB64Inst() && Mov64RC->
contains(Dst)) {
2233 MI.setDesc(Mov64Desc);
2237 (
SrcOp.isGlobal() && ST.has64BitLiterals()))
2240 if (
SrcOp.isGlobal()) {
2245 unsigned BaseFlags, LoReloc, HiReloc;
2246 std::tie(BaseFlags, LoReloc, HiReloc) =
2253 }
else if (
SrcOp.isImm()) {
2255 APInt Lo(32,
Imm.getLoBits(32).getZExtValue());
2256 APInt Hi(32,
Imm.getHiBits(32).getZExtValue());
2280 if (ST.hasPkMovB32() &&
2299 MI.eraseFromParent();
2302 case AMDGPU::V_MOV_B64_DPP_PSEUDO: {
2306 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2310 if (ST.has64BitLiterals()) {
2311 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2315 if (
SrcOp.isGlobal()) {
2317 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2318 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2321 unsigned BaseFlags, LoReloc, HiReloc;
2322 std::tie(BaseFlags, LoReloc, HiReloc) =
2329 MI.eraseFromParent();
2336 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2341 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2342 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2344 APInt Lo(32,
Imm.getLoBits(32).getZExtValue());
2345 APInt Hi(32,
Imm.getHiBits(32).getZExtValue());
2350 MI.eraseFromParent();
2353 case AMDGPU::V_SET_INACTIVE_B32: {
2357 .
add(
MI.getOperand(3))
2358 .
add(
MI.getOperand(4))
2359 .
add(
MI.getOperand(1))
2360 .
add(
MI.getOperand(2))
2361 .
add(
MI.getOperand(5));
2362 MI.eraseFromParent();
2365 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2366 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2367 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2368 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2369 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2370 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2371 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2372 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2373 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2374 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2375 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2376 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2377 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2378 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2379 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2380 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2381 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2382 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2383 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2384 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2385 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2386 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2387 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2388 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2389 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2390 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2391 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2392 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2393 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1:
2394 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2:
2395 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4:
2396 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8:
2397 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16: {
2401 if (RI.hasVGPRs(EltRC)) {
2402 Opc = AMDGPU::V_MOVRELD_B32_e32;
2404 Opc = RI.getRegSizeInBits(*EltRC) == 64 ? AMDGPU::S_MOVRELD_B64
2405 : AMDGPU::S_MOVRELD_B32;
2410 bool IsUndef =
MI.getOperand(1).isUndef();
2411 unsigned SubReg =
MI.getOperand(3).getImm();
2412 assert(VecReg ==
MI.getOperand(1).getReg());
2417 .
add(
MI.getOperand(2))
2421 const int ImpDefIdx =
2423 const int ImpUseIdx = ImpDefIdx + 1;
2425 MI.eraseFromParent();
2428 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1:
2429 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2:
2430 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3:
2431 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4:
2432 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5:
2433 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6:
2434 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7:
2435 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8:
2436 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9:
2437 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10:
2438 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11:
2439 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12:
2440 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16:
2441 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32: {
2442 assert(ST.useVGPRIndexMode());
2444 bool IsUndef =
MI.getOperand(1).isUndef();
2453 const MCInstrDesc &OpDesc =
get(AMDGPU::V_MOV_B32_indirect_write);
2457 .
add(
MI.getOperand(2))
2461 const int ImpDefIdx =
2463 const int ImpUseIdx = ImpDefIdx + 1;
2470 MI.eraseFromParent();
2473 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1:
2474 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2:
2475 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3:
2476 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4:
2477 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5:
2478 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6:
2479 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7:
2480 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8:
2481 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9:
2482 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10:
2483 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11:
2484 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12:
2485 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16:
2486 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32: {
2487 assert(ST.useVGPRIndexMode());
2490 bool IsUndef =
MI.getOperand(1).isUndef();
2494 .
add(
MI.getOperand(2))
2507 MI.eraseFromParent();
2510 case AMDGPU::SI_PC_ADD_REL_OFFSET: {
2513 Register RegLo = RI.getSubReg(Reg, AMDGPU::sub0);
2514 Register RegHi = RI.getSubReg(Reg, AMDGPU::sub1);
2533 if (ST.hasGetPCZeroExtension()) {
2537 BuildMI(MF,
DL,
get(AMDGPU::S_SEXT_I32_I16), RegHi).addReg(RegHi));
2544 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U32), RegLo).addReg(RegLo).add(OpLo));
2554 MI.eraseFromParent();
2557 case AMDGPU::SI_PC_ADD_REL_OFFSET64: {
2567 Op.setOffset(
Op.getOffset() + 4);
2569 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U64), Reg).addReg(Reg).add(
Op));
2573 MI.eraseFromParent();
2576 case AMDGPU::ENTER_STRICT_WWM: {
2582 case AMDGPU::ENTER_STRICT_WQM: {
2589 MI.eraseFromParent();
2592 case AMDGPU::EXIT_STRICT_WWM:
2593 case AMDGPU::EXIT_STRICT_WQM: {
2599 case AMDGPU::SI_RETURN: {
2613 MI.eraseFromParent();
2617 case AMDGPU::S_MUL_U64_U32_PSEUDO:
2618 case AMDGPU::S_MUL_I64_I32_PSEUDO:
2619 MI.setDesc(
get(AMDGPU::S_MUL_U64));
2622 case AMDGPU::S_GETPC_B64_pseudo:
2623 MI.setDesc(
get(AMDGPU::S_GETPC_B64));
2624 if (ST.hasGetPCZeroExtension()) {
2626 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2635 case AMDGPU::V_MAX_BF16_PSEUDO_e64: {
2636 assert(ST.hasBF16PackedInsts());
2637 MI.setDesc(
get(AMDGPU::V_PK_MAX_NUM_BF16));
2648 case AMDGPU::GET_STACK_BASE:
2651 if (ST.getFrameLowering()->mayReserveScratchForCWSR(*
MBB.getParent())) {
2658 Register DestReg =
MI.getOperand(0).getReg();
2668 MI.getOperand(
MI.getNumExplicitOperands()).setIsDead(
false);
2669 MI.getOperand(
MI.getNumExplicitOperands()).setIsUse();
2670 MI.setDesc(
get(AMDGPU::S_CMOVK_I32));
2673 MI.setDesc(
get(AMDGPU::S_MOV_B32));
2676 MI.getNumExplicitOperands());
2694 case AMDGPU::S_MOV_B64:
2695 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2704 if (UsedLanes.
all())
2709 unsigned LoSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub0);
2710 unsigned HiSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub1);
2712 bool NeedLo = (UsedLanes & RI.getSubRegIndexLaneMask(LoSubReg)).any();
2713 bool NeedHi = (UsedLanes & RI.getSubRegIndexLaneMask(HiSubReg)).any();
2715 if (NeedLo && NeedHi)
2719 int32_t Imm32 = NeedLo ?
Lo_32(Imm64) :
Hi_32(Imm64);
2721 unsigned UseSubReg = NeedLo ? LoSubReg : HiSubReg;
2730 case AMDGPU::S_LOAD_DWORDX16_IMM:
2731 case AMDGPU::S_LOAD_DWORDX8_IMM: {
2744 for (
auto &CandMO :
I->operands()) {
2745 if (!CandMO.isReg() || CandMO.getReg() != RegToFind || CandMO.isDef())
2753 if (!UseMO || UseMO->
getSubReg() == AMDGPU::NoSubRegister)
2757 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->
getSubReg());
2763 unsigned NewOpcode = -1;
2764 if (SubregSize == 256)
2765 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2766 else if (SubregSize == 128)
2767 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2777 UseMO->
setSubReg(AMDGPU::NoSubRegister);
2782 MI->getOperand(0).setReg(DestReg);
2783 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2787 OffsetMO->
setImm(FinalOffset);
2793 MI->setMemRefs(*MF, NewMMOs);
2806std::pair<MachineInstr*, MachineInstr*>
2808 assert (
MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2810 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2813 MI.setDesc(
get(AMDGPU::V_MOV_B64_dpp));
2814 return std::pair(&
MI,
nullptr);
2825 for (
auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2827 if (Dst.isPhysical()) {
2828 MovDPP.addDef(RI.getSubReg(Dst,
Sub));
2835 for (
unsigned I = 1;
I <= 2; ++
I) {
2838 if (
SrcOp.isImm()) {
2840 Imm.ashrInPlace(Part * 32);
2841 MovDPP.addImm(
Imm.getLoBits(32).getZExtValue());
2845 if (Src.isPhysical())
2846 MovDPP.addReg(RI.getSubReg(Src,
Sub));
2853 MovDPP.addImm(MO.getImm());
2855 Split[Part] = MovDPP;
2859 if (Dst.isVirtual())
2866 MI.eraseFromParent();
2867 return std::pair(Split[0], Split[1]);
2870std::optional<DestSourcePair>
2872 if (
MI.getOpcode() == AMDGPU::WWM_COPY)
2875 return std::nullopt;
2879 AMDGPU::OpName Src0OpName,
2881 AMDGPU::OpName Src1OpName)
const {
2888 "All commutable instructions have both src0 and src1 modifiers");
2890 int Src0ModsVal = Src0Mods->
getImm();
2891 int Src1ModsVal = Src1Mods->
getImm();
2893 Src1Mods->
setImm(Src0ModsVal);
2894 Src0Mods->
setImm(Src1ModsVal);
2903 bool IsKill = RegOp.
isKill();
2905 bool IsUndef = RegOp.
isUndef();
2906 bool IsDebug = RegOp.
isDebug();
2908 if (NonRegOp.
isImm())
2910 else if (NonRegOp.
isFI())
2931 int64_t NonRegVal = NonRegOp1.
getImm();
2934 NonRegOp2.
setImm(NonRegVal);
2941 unsigned OpIdx1)
const {
2946 unsigned Opc =
MI.getOpcode();
2947 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
2957 if ((
int)OpIdx0 == Src0Idx && !MO0.
isReg() &&
2960 if ((
int)OpIdx1 == Src0Idx && !MO1.
isReg() &&
2965 if ((
int)OpIdx1 != Src0Idx && MO0.
isReg()) {
2971 if ((
int)OpIdx0 != Src0Idx && MO1.
isReg()) {
2993 unsigned Src1Idx)
const {
2994 assert(!NewMI &&
"this should never be used");
2999 unsigned Opc =
MI.getOpcode();
3001 if (CommutedOpcode == -1)
3004 if (Src0Idx > Src1Idx)
3007 assert(AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) ==
3008 static_cast<int>(Src0Idx) &&
3009 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1) ==
3010 static_cast<int>(Src1Idx) &&
3011 "inconsistency with findCommutedOpIndices");
3036 Src1, AMDGPU::OpName::src1_modifiers);
3039 AMDGPU::OpName::src1_sel);
3051 unsigned &SrcOpIdx0,
3052 unsigned &SrcOpIdx1)
const {
3060 unsigned &SrcOpIdx0,
3061 unsigned &SrcOpIdx1)
const {
3062 if (!
Desc.isCommutable())
3065 unsigned Opc =
Desc.getOpcode();
3066 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
3070 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
3074 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
3078 int64_t BrOffset)
const {
3095 return MI.getOperand(0).getMBB();
3100 if (
MI.getOpcode() == AMDGPU::SI_IF ||
MI.getOpcode() == AMDGPU::SI_ELSE ||
3101 MI.getOpcode() == AMDGPU::SI_LOOP)
3113 "new block should be inserted for expanding unconditional branch");
3116 "restore block should be inserted for restoring clobbered registers");
3124 if (ST.useAddPC64Inst()) {
3126 MCCtx.createTempSymbol(
"offset",
true);
3130 MCCtx.createTempSymbol(
"post_addpc",
true);
3131 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
3135 Offset->setVariableValue(OffsetExpr);
3139 assert(RS &&
"RegScavenger required for long branching");
3147 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
3148 ST.hasVALUReadSGPRHazard();
3149 auto ApplyHazardWorkarounds = [
this, &
MBB, &
I, &
DL, FlushSGPRWrites]() {
3150 if (FlushSGPRWrites)
3158 ApplyHazardWorkarounds();
3161 MCCtx.createTempSymbol(
"post_getpc",
true);
3165 MCCtx.createTempSymbol(
"offset_lo",
true);
3167 MCCtx.createTempSymbol(
"offset_hi",
true);
3170 .
addReg(PCReg, {}, AMDGPU::sub0)
3174 .
addReg(PCReg, {}, AMDGPU::sub1)
3176 ApplyHazardWorkarounds();
3217 if (LongBranchReservedReg) {
3218 RS->enterBasicBlock(
MBB);
3219 Scav = LongBranchReservedReg;
3221 RS->enterBasicBlockEnd(
MBB);
3222 Scav = RS->scavengeRegisterBackwards(
3227 RS->setRegUsed(Scav);
3235 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
3252unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate
Cond) {
3254 case SIInstrInfo::SCC_TRUE:
3255 return AMDGPU::S_CBRANCH_SCC1;
3256 case SIInstrInfo::SCC_FALSE:
3257 return AMDGPU::S_CBRANCH_SCC0;
3258 case SIInstrInfo::VCCNZ:
3259 return AMDGPU::S_CBRANCH_VCCNZ;
3260 case SIInstrInfo::VCCZ:
3261 return AMDGPU::S_CBRANCH_VCCZ;
3262 case SIInstrInfo::EXECNZ:
3263 return AMDGPU::S_CBRANCH_EXECNZ;
3264 case SIInstrInfo::EXECZ:
3265 return AMDGPU::S_CBRANCH_EXECZ;
3271SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(
unsigned Opcode) {
3273 case AMDGPU::S_CBRANCH_SCC0:
3275 case AMDGPU::S_CBRANCH_SCC1:
3277 case AMDGPU::S_CBRANCH_VCCNZ:
3279 case AMDGPU::S_CBRANCH_VCCZ:
3281 case AMDGPU::S_CBRANCH_EXECNZ:
3283 case AMDGPU::S_CBRANCH_EXECZ:
3295 bool AllowModify)
const {
3296 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3298 TBB =
I->getOperand(0).getMBB();
3302 BranchPredicate Pred = getBranchPredicate(
I->getOpcode());
3303 if (Pred == INVALID_BR)
3308 Cond.push_back(
I->getOperand(1));
3312 if (
I ==
MBB.end()) {
3318 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3320 FBB =
I->getOperand(0).getMBB();
3330 bool AllowModify)
const {
3338 while (
I != E && !
I->isBranch() && !
I->isReturn()) {
3339 switch (
I->getOpcode()) {
3340 case AMDGPU::S_MOV_B64_term:
3341 case AMDGPU::S_XOR_B64_term:
3342 case AMDGPU::S_OR_B64_term:
3343 case AMDGPU::S_ANDN2_B64_term:
3344 case AMDGPU::S_AND_B64_term:
3345 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3346 case AMDGPU::S_MOV_B32_term:
3347 case AMDGPU::S_XOR_B32_term:
3348 case AMDGPU::S_OR_B32_term:
3349 case AMDGPU::S_ANDN2_B32_term:
3350 case AMDGPU::S_AND_B32_term:
3351 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3352 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3353 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3356 case AMDGPU::SI_ELSE:
3357 case AMDGPU::SI_KILL_I1_TERMINATOR:
3358 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3375 int *BytesRemoved)
const {
3377 unsigned RemovedSize = 0;
3380 if (
MI.isBranch() ||
MI.isReturn()) {
3382 MI.eraseFromParent();
3388 *BytesRemoved = RemovedSize;
3405 int *BytesAdded)
const {
3406 if (!FBB &&
Cond.empty()) {
3410 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3417 = getBranchOpcode(
static_cast<BranchPredicate
>(
Cond[0].
getImm()));
3429 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3447 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3454 if (
Cond.size() != 2) {
3458 if (
Cond[0].isImm()) {
3479 bool shouldIgnoreForPipelining(
const MachineInstr *
MI)
const override {
3483 std::optional<bool> createTripCountGreaterCondition(
3484 int TC, MachineBasicBlock &
MBB,
3485 SmallVectorImpl<MachineOperand> &CondParam)
override {
3486 CondParam = this->
Cond;
3490 void adjustTripCount(
int TripCountAdjust)
override {}
3492 void setPreheader(MachineBasicBlock *NewPreheader)
override {}
3496std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
3505 if (
TBB == LoopBB && FBB == LoopBB)
3512 assert((
TBB == LoopBB || FBB == LoopBB) &&
3513 "The Loop must be a single-basic-block loop");
3516 BranchPredicate Pred =
static_cast<BranchPredicate
>(
Cond[0].getImm());
3517 if (Pred != SCC_TRUE && Pred != SCC_FALSE)
3522 if (
MI.isCall() ||
MI.isInlineAsm())
3537 if (CmpI == Instructions.end() || CmpI->isPHI())
3541 return std::make_unique<AMDGPUPipelinerLoopInfo>(
CmpInst,
Cond);
3547 Register FalseReg,
int &CondCycles,
3548 int &TrueCycles,
int &FalseCycles)
const {
3558 CondCycles = TrueCycles = FalseCycles = NumInsts;
3561 return RI.hasVGPRs(RC) && NumInsts <= 6;
3575 if (NumInsts % 2 == 0)
3578 CondCycles = TrueCycles = FalseCycles = NumInsts;
3579 return RI.isSGPRClass(RC);
3590 BranchPredicate Pred =
static_cast<BranchPredicate
>(
Cond[0].getImm());
3591 if (Pred == VCCZ || Pred == SCC_FALSE) {
3592 Pred =
static_cast<BranchPredicate
>(-Pred);
3598 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3600 if (DstSize == 32) {
3602 if (Pred == SCC_TRUE) {
3617 if (DstSize == 64 && Pred == SCC_TRUE) {
3627 static const int16_t Sub0_15[] = {
3628 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3629 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3630 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3631 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3634 static const int16_t Sub0_15_64[] = {
3635 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3636 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3637 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3638 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3641 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3643 const int16_t *SubIndices = Sub0_15;
3644 int NElts = DstSize / 32;
3648 if (Pred == SCC_TRUE) {
3650 SelOp = AMDGPU::S_CSELECT_B32;
3651 EltRC = &AMDGPU::SGPR_32RegClass;
3653 SelOp = AMDGPU::S_CSELECT_B64;
3654 EltRC = &AMDGPU::SGPR_64RegClass;
3655 SubIndices = Sub0_15_64;
3661 MBB,
I,
DL,
get(AMDGPU::REG_SEQUENCE), DstReg);
3666 for (
int Idx = 0; Idx != NElts; ++Idx) {
3670 unsigned SubIdx = SubIndices[Idx];
3673 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3675 .
addReg(FalseReg, {}, SubIdx)
3676 .addReg(TrueReg, {}, SubIdx);
3679 .
addReg(TrueReg, {}, SubIdx)
3680 .addReg(FalseReg, {}, SubIdx);
3693 if (
MI.isBranch() ||
MI.isCall() ||
MI.isReturn() ||
MI.isIndirectBranch())
3696 switch (
MI.getOpcode()) {
3697 case AMDGPU::S_ENDPGM:
3698 case AMDGPU::S_ENDPGM_SAVED:
3699 case AMDGPU::S_TRAP:
3700 case AMDGPU::S_GETREG_B32:
3701 case AMDGPU::S_SETREG_B32:
3702 case AMDGPU::S_SETREG_B32_mode:
3703 case AMDGPU::S_SETREG_IMM32_B32:
3704 case AMDGPU::S_SETREG_IMM32_B32_mode:
3705 case AMDGPU::S_SENDMSG:
3706 case AMDGPU::S_SENDMSGHALT:
3707 case AMDGPU::S_SENDMSG_RTN_B32:
3708 case AMDGPU::S_SENDMSG_RTN_B64:
3709 case AMDGPU::S_BARRIER_WAIT:
3710 case AMDGPU::S_BARRIER_SIGNAL_M0:
3711 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3712 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3713 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3721 switch (
MI.getOpcode()) {
3722 case AMDGPU::V_MOV_B16_t16_e32:
3723 case AMDGPU::V_MOV_B16_t16_e64:
3724 case AMDGPU::V_MOV_B32_e32:
3725 case AMDGPU::V_MOV_B32_e64:
3726 case AMDGPU::V_MOV_B64_PSEUDO:
3727 case AMDGPU::V_MOV_B64_e32:
3728 case AMDGPU::V_MOV_B64_e64:
3729 case AMDGPU::S_MOV_B32:
3730 case AMDGPU::S_MOV_B64:
3731 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3733 case AMDGPU::WWM_COPY:
3734 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3735 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3736 case AMDGPU::V_ACCVGPR_MOV_B32:
3737 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3738 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3746 switch (
MI.getOpcode()) {
3747 case AMDGPU::V_MOV_B16_t16_e32:
3748 case AMDGPU::V_MOV_B16_t16_e64:
3750 case AMDGPU::V_MOV_B32_e32:
3751 case AMDGPU::V_MOV_B32_e64:
3752 case AMDGPU::V_MOV_B64_PSEUDO:
3753 case AMDGPU::V_MOV_B64_e32:
3754 case AMDGPU::V_MOV_B64_e64:
3755 case AMDGPU::S_MOV_B32:
3756 case AMDGPU::S_MOV_B64:
3757 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3759 case AMDGPU::WWM_COPY:
3760 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3761 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3762 case AMDGPU::V_ACCVGPR_MOV_B32:
3763 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3764 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3772 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3773 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3774 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3777 unsigned Opc =
MI.getOpcode();
3779 int Idx = AMDGPU::getNamedOperandIdx(
Opc, Name);
3781 MI.removeOperand(Idx);
3787 MI.setDesc(NewDesc);
3793 unsigned NumOps =
Desc.getNumOperands() +
Desc.implicit_uses().size() +
3794 Desc.implicit_defs().size();
3796 for (
unsigned I =
MI.getNumOperands() - 1;
I >=
NumOps; --
I)
3797 MI.removeOperand(
I);
3801 unsigned SubRegIndex) {
3802 switch (SubRegIndex) {
3803 case AMDGPU::NoSubRegister:
3813 case AMDGPU::sub1_lo16:
3815 case AMDGPU::sub1_hi16:
3818 return std::nullopt;
3826 case AMDGPU::V_MAC_F16_e32:
3827 case AMDGPU::V_MAC_F16_e64:
3828 case AMDGPU::V_MAD_F16_e64:
3829 return AMDGPU::V_MADAK_F16;
3830 case AMDGPU::V_MAC_F32_e32:
3831 case AMDGPU::V_MAC_F32_e64:
3832 case AMDGPU::V_MAD_F32_e64:
3833 return AMDGPU::V_MADAK_F32;
3834 case AMDGPU::V_FMAC_F32_e32:
3835 case AMDGPU::V_FMAC_F32_e64:
3836 case AMDGPU::V_FMA_F32_e64:
3837 return AMDGPU::V_FMAAK_F32;
3838 case AMDGPU::V_FMAC_F16_e32:
3839 case AMDGPU::V_FMAC_F16_e64:
3840 case AMDGPU::V_FMAC_F16_t16_e64:
3841 case AMDGPU::V_FMAC_F16_fake16_e64:
3842 case AMDGPU::V_FMAC_F16_t16_e32:
3843 case AMDGPU::V_FMAC_F16_fake16_e32:
3844 case AMDGPU::V_FMA_F16_e64:
3845 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3846 ? AMDGPU::V_FMAAK_F16_t16
3847 : AMDGPU::V_FMAAK_F16_fake16
3848 : AMDGPU::V_FMAAK_F16;
3849 case AMDGPU::V_FMAC_F64_e32:
3850 case AMDGPU::V_FMAC_F64_e64:
3851 case AMDGPU::V_FMA_F64_e64:
3852 return AMDGPU::V_FMAAK_F64;
3860 case AMDGPU::V_MAC_F16_e32:
3861 case AMDGPU::V_MAC_F16_e64:
3862 case AMDGPU::V_MAD_F16_e64:
3863 return AMDGPU::V_MADMK_F16;
3864 case AMDGPU::V_MAC_F32_e32:
3865 case AMDGPU::V_MAC_F32_e64:
3866 case AMDGPU::V_MAD_F32_e64:
3867 return AMDGPU::V_MADMK_F32;
3868 case AMDGPU::V_FMAC_F32_e32:
3869 case AMDGPU::V_FMAC_F32_e64:
3870 case AMDGPU::V_FMA_F32_e64:
3871 return AMDGPU::V_FMAMK_F32;
3872 case AMDGPU::V_FMAC_F16_e32:
3873 case AMDGPU::V_FMAC_F16_e64:
3874 case AMDGPU::V_FMAC_F16_t16_e64:
3875 case AMDGPU::V_FMAC_F16_fake16_e64:
3876 case AMDGPU::V_FMAC_F16_t16_e32:
3877 case AMDGPU::V_FMAC_F16_fake16_e32:
3878 case AMDGPU::V_FMA_F16_e64:
3879 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3880 ? AMDGPU::V_FMAMK_F16_t16
3881 : AMDGPU::V_FMAMK_F16_fake16
3882 : AMDGPU::V_FMAMK_F16;
3883 case AMDGPU::V_FMAC_F64_e32:
3884 case AMDGPU::V_FMAC_F64_e64:
3885 case AMDGPU::V_FMA_F64_e64:
3886 return AMDGPU::V_FMAMK_F64;
3900 assert(!
DefMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3903 if (
Opc == AMDGPU::COPY) {
3904 assert(!
UseMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3911 if (HasMultipleUses) {
3914 unsigned ImmDefSize = RI.getRegSizeInBits(*MRI->
getRegClass(Reg));
3917 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3925 if (ImmDefSize == 32 &&
3930 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3931 RI.getSubRegIdxSize(UseSubReg) == 16;
3934 if (RI.hasVGPRs(DstRC))
3937 if (DstReg.
isVirtual() && UseSubReg != AMDGPU::lo16)
3943 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
3950 for (
unsigned MovOp :
3951 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
3952 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
3960 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
3964 if (MovDstPhysReg) {
3968 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
3975 if (MovDstPhysReg) {
3976 if (!MovDstRC->
contains(MovDstPhysReg))
3992 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
4000 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
4004 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
4006 UseMI.getOperand(0).setReg(MovDstPhysReg);
4011 UseMI.setDesc(NewMCID);
4012 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
4013 UseMI.addImplicitDefUseOperands(*MF);
4017 if (HasMultipleUses)
4020 if (
Opc == AMDGPU::V_MAD_F32_e64 ||
Opc == AMDGPU::V_MAC_F32_e64 ||
4021 Opc == AMDGPU::V_MAD_F16_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4022 Opc == AMDGPU::V_FMA_F32_e64 ||
Opc == AMDGPU::V_FMAC_F32_e64 ||
4023 Opc == AMDGPU::V_FMA_F16_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64 ||
4024 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4025 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
Opc == AMDGPU::V_FMA_F64_e64 ||
4026 Opc == AMDGPU::V_FMAC_F64_e64) {
4035 int Src0Idx = getNamedOperandIdx(
UseMI.getOpcode(), AMDGPU::OpName::src0);
4046 auto CopyRegOperandToNarrowerRC =
4049 if (!
MI.getOperand(OpNo).isReg())
4053 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
4056 BuildMI(*
MI.getParent(),
MI.getIterator(),
MI.getDebugLoc(),
4057 get(AMDGPU::COPY), Tmp)
4059 MI.getOperand(OpNo).setReg(Tmp);
4060 MI.getOperand(OpNo).setIsKill();
4067 Src1->
isReg() && Src1->
getReg() == Reg ? Src0 : Src1;
4068 if (!RegSrc->
isReg())
4071 ST.getConstantBusLimit(
Opc) < 2)
4086 if (Def && Def->isMoveImmediate() &&
4101 unsigned SrcSubReg = RegSrc->
getSubReg();
4106 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4107 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4108 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4109 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
4110 UseMI.untieRegOperand(
4111 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
4118 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
4119 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
4123 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
4124 UseMI.getOperand(0).getReg())
4126 UseMI.getOperand(0).setReg(Tmp);
4127 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
4128 CopyRegOperandToNarrowerRC(
UseMI, 3, NewRC);
4133 DefMI.eraseFromParent();
4140 if (ST.getConstantBusLimit(
Opc) < 2) {
4143 bool Src0Inlined =
false;
4144 if (Src0->
isReg()) {
4149 if (Def && Def->isMoveImmediate() &&
4154 }
else if (ST.getConstantBusLimit(
Opc) <= 1 &&
4155 RI.isSGPRReg(*MRI, Src0->
getReg())) {
4161 if (Src1->
isReg() && !Src0Inlined) {
4164 if (Def && Def->isMoveImmediate() &&
4168 else if (RI.isSGPRReg(*MRI, Src1->
getReg()))
4181 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4182 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4183 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4184 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
4185 UseMI.untieRegOperand(
4186 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
4188 const std::optional<int64_t> SubRegImm =
4198 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
4199 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
4203 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
4204 UseMI.getOperand(0).getReg())
4206 UseMI.getOperand(0).setReg(Tmp);
4207 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
4208 CopyRegOperandToNarrowerRC(
UseMI, 2, NewRC);
4218 DefMI.eraseFromParent();
4230 if (BaseOps1.
size() != BaseOps2.
size())
4232 for (
size_t I = 0,
E = BaseOps1.
size();
I <
E; ++
I) {
4233 if (!BaseOps1[
I]->isIdenticalTo(*BaseOps2[
I]))
4241 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
4242 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
4243 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
4245 LowOffset + (int)LowWidth.
getValue() <= HighOffset;
4248bool SIInstrInfo::checkInstOffsetsDoNotOverlap(
const MachineInstr &MIa,
4251 int64_t Offset0, Offset1;
4254 bool Offset0IsScalable, Offset1IsScalable;
4268 LocationSize Width0 = MIa.
memoperands().front()->getSize();
4269 LocationSize Width1 = MIb.
memoperands().front()->getSize();
4276 "MIa must load from or modify a memory location");
4278 "MIb must load from or modify a memory location");
4300 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4307 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4317 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4331 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4343 unsigned NumOps =
MI.getNumOperands();
4346 if (
Op.isReg() &&
Op.isKill())
4354 case AMDGPU::V_MAC_F16_e32:
4355 case AMDGPU::V_MAC_F16_e64:
4356 return AMDGPU::V_MAD_F16_e64;
4357 case AMDGPU::V_MAC_F32_e32:
4358 case AMDGPU::V_MAC_F32_e64:
4359 return AMDGPU::V_MAD_F32_e64;
4360 case AMDGPU::V_MAC_LEGACY_F32_e32:
4361 case AMDGPU::V_MAC_LEGACY_F32_e64:
4362 return AMDGPU::V_MAD_LEGACY_F32_e64;
4363 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4364 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4365 return AMDGPU::V_FMA_LEGACY_F32_e64;
4366 case AMDGPU::V_FMAC_F16_e32:
4367 case AMDGPU::V_FMAC_F16_e64:
4368 case AMDGPU::V_FMAC_F16_t16_e64:
4369 case AMDGPU::V_FMAC_F16_fake16_e64:
4370 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4371 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4372 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4373 : AMDGPU::V_FMA_F16_gfx9_e64;
4374 case AMDGPU::V_FMAC_F32_e32:
4375 case AMDGPU::V_FMAC_F32_e64:
4376 return AMDGPU::V_FMA_F32_e64;
4377 case AMDGPU::V_FMAC_F64_e32:
4378 case AMDGPU::V_FMAC_F64_e64:
4379 return AMDGPU::V_FMA_F64_e64;
4399 if (
MI.isBundle()) {
4402 if (
MI.getBundleSize() != 1)
4404 CandidateMI =
MI.getNextNode();
4408 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4412 if (
MI.isBundle()) {
4417 MI.untieRegOperand(MO.getOperandNo());
4425 if (Def.isEarlyClobber() && Def.isReg() &&
4430 auto UpdateDefIndex = [&](
LiveRange &LR) {
4431 auto *S = LR.find(OldIndex);
4432 if (S != LR.end() && S->start == OldIndex) {
4433 assert(S->valno && S->valno->def == OldIndex);
4434 S->start = NewIndex;
4435 S->valno->def = NewIndex;
4439 for (
auto &SR : LI.subranges())
4445 if (U.RemoveMIUse) {
4448 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4452 U.RemoveMIUse->setDesc(
get(AMDGPU::IMPLICIT_DEF));
4453 U.RemoveMIUse->getOperand(0).setIsDead(
true);
4454 for (
unsigned I = U.RemoveMIUse->getNumOperands() - 1;
I != 0; --
I)
4455 U.RemoveMIUse->removeOperand(
I);
4460 if (
MI.isBundle()) {
4464 if (MO.isReg() && MO.getReg() == DefReg) {
4465 assert(MO.getSubReg() == 0 &&
4466 "tied sub-registers in bundles currently not supported");
4467 MI.removeOperand(MO.getOperandNo());
4484 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4485 MIOp.setIsUndef(
true);
4486 MIOp.setReg(DummyReg);
4490 if (
MI.isBundle()) {
4494 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4495 MIOp.setIsUndef(
true);
4496 MIOp.setReg(DummyReg);
4509 return MI.isBundle() ? &
MI : NewMI;
4514 ThreeAddressUpdates &U)
const {
4516 unsigned Opc =
MI.getOpcode();
4520 if (NewMFMAOpc != -1) {
4523 for (
unsigned I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I)
4524 MIB.
add(
MI.getOperand(
I));
4532 for (
unsigned I = 0,
E =
MI.getNumExplicitOperands();
I !=
E; ++
I)
4537 assert(
Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4538 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4539 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4543 bool IsF64 =
Opc == AMDGPU::V_FMAC_F64_e32 ||
Opc == AMDGPU::V_FMAC_F64_e64;
4544 bool IsLegacy =
Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4545 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4546 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4547 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4548 bool Src0Literal =
false;
4553 case AMDGPU::V_MAC_F16_e64:
4554 case AMDGPU::V_FMAC_F16_e64:
4555 case AMDGPU::V_FMAC_F16_t16_e64:
4556 case AMDGPU::V_FMAC_F16_fake16_e64:
4557 case AMDGPU::V_MAC_F32_e64:
4558 case AMDGPU::V_MAC_LEGACY_F32_e64:
4559 case AMDGPU::V_FMAC_F32_e64:
4560 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4561 case AMDGPU::V_FMAC_F64_e64:
4563 case AMDGPU::V_MAC_F16_e32:
4564 case AMDGPU::V_FMAC_F16_e32:
4565 case AMDGPU::V_MAC_F32_e32:
4566 case AMDGPU::V_MAC_LEGACY_F32_e32:
4567 case AMDGPU::V_FMAC_F32_e32:
4568 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4569 case AMDGPU::V_FMAC_F64_e32: {
4570 int Src0Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
4571 AMDGPU::OpName::src0);
4572 const MachineOperand *Src0 = &
MI.getOperand(Src0Idx);
4583 MachineInstrBuilder MIB;
4586 const MachineOperand *Src0Mods =
4589 const MachineOperand *Src1Mods =
4592 const MachineOperand *Src2Mods =
4598 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4599 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4601 (ST.getConstantBusLimit(
Opc) > 1 || !Src0->
isReg() ||
4603 MachineInstr *
DefMI =
nullptr;
4605 std::optional<int64_t> ImmOpt;
4640 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4656 if (Src0Literal && !ST.hasVOP3Literal())
4684 switch (
MI.getOpcode()) {
4685 case AMDGPU::S_SET_GPR_IDX_ON:
4686 case AMDGPU::S_SET_GPR_IDX_MODE:
4687 case AMDGPU::S_SET_GPR_IDX_OFF:
4705 if (
MI.isTerminator() ||
MI.isPosition())
4709 if (
MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4712 if (
MI.getOpcode() == AMDGPU::SCHED_BARRIER &&
MI.getOperand(0).getImm() == 0)
4718 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4719 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4720 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4721 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4722 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4727 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4728 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4729 Opcode == AMDGPU::DS_SUB_GS_REG_RTN ||
isGWS(Opcode);
4743 if (
MI.getMF()->getFunction().hasFnAttribute(
"amdgpu-no-flat-scratch-init"))
4748 if (
MI.memoperands_empty())
4753 unsigned AS = Memop->getAddrSpace();
4754 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4755 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4756 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4757 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4772 if (
MI.memoperands_empty())
4781 unsigned AS = Memop->getAddrSpace();
4791 bool TgSplit)
const {
4804 if (
MI.memoperands_empty())
4809 unsigned AS = Memop->getAddrSpace();
4825 unsigned Opcode =
MI.getOpcode();
4840 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4841 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4842 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4843 Opcode == AMDGPU::S_SETHALT)
4846 if (
MI.isCall() ||
MI.isInlineAsm())
4862 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4863 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4864 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4865 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4873 if (
MI.isMetaInstruction())
4877 if (
MI.isCopyLike()) {
4878 if (!RI.isSGPRReg(MRI,
MI.getOperand(0).getReg()))
4882 return MI.readsRegister(AMDGPU::EXEC, &RI);
4893 return !
isSALU(
MI) ||
MI.readsRegister(AMDGPU::EXEC, &RI);
4897 switch (
Imm.getBitWidth()) {
4903 ST.hasInv2PiInlineImm());
4906 ST.hasInv2PiInlineImm());
4908 return ST.has16BitInsts() &&
4910 ST.hasInv2PiInlineImm());
4917 APInt IntImm =
Imm.bitcastToAPInt();
4919 bool HasInv2Pi = ST.hasInv2PiInlineImm();
4927 return ST.has16BitInsts() &&
4930 return ST.has16BitInsts() &&
4940 switch (OperandType) {
4950 int32_t Trunc =
static_cast<int32_t
>(
Imm);
4994 int16_t Trunc =
static_cast<int16_t
>(
Imm);
4995 return ST.has16BitInsts() &&
5004 int16_t Trunc =
static_cast<int16_t
>(
Imm);
5005 return ST.has16BitInsts() &&
5057 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
5063 return ST.hasVOP3Literal();
5067 int64_t ImmVal)
const {
5069 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
5070 if (Src1Idx != -1 &&
isDPP(
Opc) && !ST.hasDPPSrc1SGPR() &&
5071 OpNo ==
static_cast<unsigned>(Src1Idx))
5076 if (
isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
5077 OpNo == (
unsigned)AMDGPU::getNamedOperandIdx(InstDesc.
getOpcode(),
5078 AMDGPU::OpName::src2))
5081 if (ST.hasBF16InlineConstFromUpperFP32() &&
isVOP1(
Opc)) {
5088 return RI.opCanUseInlineConstant(OpInfo.OperandType);
5100 "unexpected imm-like operand kind");
5113 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
5131 AMDGPU::OpName
OpName)
const {
5133 return Mods && Mods->
getImm();
5146 switch (
MI.getOpcode()) {
5147 default:
return false;
5149 case AMDGPU::V_ADDC_U32_e64:
5150 case AMDGPU::V_SUBB_U32_e64:
5151 case AMDGPU::V_SUBBREV_U32_e64: {
5154 if (!Src1->
isReg() || !RI.isVGPR(MRI, Src1->
getReg()))
5159 case AMDGPU::V_MAC_F16_e64:
5160 case AMDGPU::V_MAC_F32_e64:
5161 case AMDGPU::V_MAC_LEGACY_F32_e64:
5162 case AMDGPU::V_FMAC_F16_e64:
5163 case AMDGPU::V_FMAC_F16_t16_e64:
5164 case AMDGPU::V_FMAC_F16_fake16_e64:
5165 case AMDGPU::V_FMAC_F32_e64:
5166 case AMDGPU::V_FMAC_F64_e64:
5167 case AMDGPU::V_FMAC_LEGACY_F32_e64:
5168 if (!Src2->
isReg() || !RI.isVGPR(MRI, Src2->
getReg()) ||
5173 case AMDGPU::V_CNDMASK_B32_e64:
5179 if (Src1 && (!Src1->
isReg() || !RI.isVGPR(MRI, Src1->
getReg()) ||
5192 if (Src0 && Src0->
isImm()) {
5195 get(Op32), AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src0),
5217 (
Use.getReg() == AMDGPU::VCC ||
Use.getReg() == AMDGPU::VCC_LO)) {
5226 unsigned Op32)
const {
5240 Inst32.
add(
MI.getOperand(
I));
5244 int Idx =
MI.getNumExplicitDefs();
5246 int OpTy =
MI.getDesc().operands()[Idx++].OperandType;
5251 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
5273 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5281 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5284 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5285 AMDGPU::SReg_64RegClass.contains(Reg);
5313 switch (MO.getReg()) {
5315 case AMDGPU::VCC_LO:
5316 case AMDGPU::VCC_HI:
5318 case AMDGPU::FLAT_SCR:
5331 switch (
MI.getOpcode()) {
5332 case AMDGPU::V_READLANE_B32:
5333 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5334 case AMDGPU::V_WRITELANE_B32:
5335 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5342 if (
MI.isPreISelOpcode() ||
5343 SIInstrInfo::isGenericOpcode(
MI.getOpcode()) ||
5361 return SubReg.
getSubReg() != AMDGPU::NoSubRegister &&
5372 if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
5373 ErrInfo =
"illegal copy from vector register to SGPR";
5391 if (!MRI.
isSSA() &&
MI.isCopy())
5392 return verifyCopy(
MI, MRI, ErrInfo);
5394 if (SIInstrInfo::isGenericOpcode(Opcode))
5397 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5398 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5399 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5401 if (Src0Idx == -1) {
5403 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5404 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5405 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5406 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5411 if (!
Desc.isVariadic() &&
5412 Desc.getNumOperands() !=
MI.getNumExplicitOperands()) {
5413 ErrInfo =
"Instruction has wrong number of operands.";
5417 if (
MI.isInlineAsm()) {
5430 if (!Reg.isVirtual() && !RC->
contains(Reg)) {
5431 ErrInfo =
"inlineasm operand has incorrect register class.";
5439 if (
isImage(
MI) &&
MI.memoperands_empty() &&
MI.mayLoadOrStore()) {
5440 ErrInfo =
"missing memory operand from image instruction.";
5445 for (
int i = 0, e =
Desc.getNumOperands(); i != e; ++i) {
5448 ErrInfo =
"FPImm Machine Operands are not supported. ISel should bitcast "
5449 "all fp values to integers.";
5455 switch (OpInfo.OperandType) {
5457 if (
MI.getOperand(i).isImm() ||
MI.getOperand(i).isGlobal()) {
5458 ErrInfo =
"Illegal immediate value for operand.";
5490 ErrInfo =
"Illegal immediate value for operand.";
5499 if (ST.has64BitLiterals() &&
Desc.getSize() != 4 && MO.
isImm() &&
5502 OpInfo.OperandType ==
5504 ErrInfo =
"illegal 64-bit immediate value for operand.";
5511 ErrInfo =
"Expected inline constant for operand.";
5525 if (!
MI.getOperand(i).isImm() && !
MI.getOperand(i).isFI()) {
5526 ErrInfo =
"Expected immediate, but got non-immediate";
5535 if (OpInfo.isGenericType())
5543 if (!ST.hasSDWA()) {
5544 ErrInfo =
"SDWA is not supported on this target";
5548 for (
auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5549 AMDGPU::OpName::dst_sel}) {
5555 ErrInfo =
"Invalid SDWA selection";
5560 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5562 for (
int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5567 if (!ST.hasSDWAScalar()) {
5569 if (!MO.
isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.
getReg()))) {
5570 ErrInfo =
"Only VGPRs allowed as operands in SDWA instructions on VI";
5577 "Only reg allowed as operands in SDWA instructions on GFX9+";
5583 if (!ST.hasSDWAOmod()) {
5586 if (OMod !=
nullptr &&
5588 ErrInfo =
"OMod not allowed in SDWA instructions on VI";
5593 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5594 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5595 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5596 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5599 unsigned Mods = Src0ModsMO->
getImm();
5602 ErrInfo =
"sext, abs and neg are not allowed on this instruction";
5608 if (
isVOPC(BasicOpcode)) {
5609 if (!ST.hasSDWASdst() && DstIdx != -1) {
5612 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5613 ErrInfo =
"Only VCC allowed as dst in SDWA instructions on VI";
5616 }
else if (!ST.hasSDWAOutModsVOPC()) {
5619 if (Clamp && (!Clamp->
isImm() || Clamp->
getImm() != 0)) {
5620 ErrInfo =
"Clamp not allowed in VOPC SDWA instructions on VI";
5626 if (OMod && (!OMod->
isImm() || OMod->
getImm() != 0)) {
5627 ErrInfo =
"OMod not allowed in VOPC SDWA instructions on VI";
5634 if (DstUnused && DstUnused->isImm() &&
5637 if (!Dst.isReg() || !Dst.isTied()) {
5638 ErrInfo =
"Dst register should have tied register";
5643 MI.getOperand(
MI.findTiedOperandIdx(DstIdx));
5646 "Dst register should be tied to implicit use of preserved register";
5650 ErrInfo =
"Dst register should use same physical register as preserved";
5656 if (
isDPP(
MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5658 if (Src1MO.
isReg() && RI.isSGPRReg(MRI, Src1MO.
getReg())) {
5659 ErrInfo =
"DPP src1 cannot be SGPR on this subtarget";
5662 if (Src1MO.
isImm()) {
5663 ErrInfo =
"DPP src1 cannot be an immediate on this subtarget";
5669 if (
isImage(Opcode) && !
MI.mayStore()) {
5674 uint64_t DMaskImm = DMask->
getImm();
5681 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5689 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5693 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5694 if (RegCount > DstSize) {
5695 ErrInfo =
"Image instruction returns too many registers for dst "
5705 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5706 unsigned ConstantBusCount = 0;
5707 bool UsesLiteral =
false;
5710 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5714 LiteralVal = &
MI.getOperand(ImmIdx);
5723 for (
int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5734 }
else if (!MO.
isFI()) {
5741 ErrInfo =
"VOP2/VOP3 instruction uses more than one literal";
5751 if (
llvm::all_of(SGPRsUsed, [
this, SGPRUsed](
unsigned SGPR) {
5752 return !RI.regsOverlap(SGPRUsed, SGPR);
5761 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5762 Opcode != AMDGPU::V_WRITELANE_B32) {
5763 ErrInfo =
"VOP* instruction violates constant bus restriction";
5767 if (
isVOP3(
MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5768 ErrInfo =
"VOP3 instruction uses literal";
5775 if (
Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5776 unsigned SGPRCount = 0;
5779 for (
int OpIdx : {Src0Idx, Src1Idx}) {
5787 if (MO.
getReg() != SGPRUsed)
5792 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5793 ErrInfo =
"WRITELANE instruction violates constant bus restriction";
5800 if (
Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
5801 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
5808 ErrInfo =
"v_div_scale_{f32|f64} require src0 = src1 or src2";
5818 ErrInfo =
"ABS not allowed in VOP3B instructions";
5831 ErrInfo =
"SOP2/SOPC instruction requires too many immediate constants";
5838 if (
Desc.isBranch()) {
5840 ErrInfo =
"invalid branch target for SOPK instruction";
5844 uint64_t
Imm =
Op->getImm();
5847 ErrInfo =
"invalid immediate for SOPK instruction";
5852 ErrInfo =
"invalid immediate for SOPK instruction";
5859 if (
Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
5860 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
5861 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5862 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
5863 const bool IsDst =
Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
5864 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
5866 const unsigned StaticNumOps =
5867 Desc.getNumOperands() +
Desc.implicit_uses().size();
5868 const unsigned NumImplicitOps = IsDst ? 2 : 1;
5874 if (
MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
5875 ErrInfo =
"missing implicit register operands";
5881 if (!Dst->isUse()) {
5882 ErrInfo =
"v_movreld_b32 vdst should be a use operand";
5887 if (!
MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
5888 UseOpIdx != StaticNumOps + 1) {
5889 ErrInfo =
"movrel implicit operands should be tied";
5896 =
MI.getOperand(StaticNumOps + NumImplicitOps - 1);
5898 !
isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
5899 ErrInfo =
"src0 should be subreg of implicit vector use";
5907 if (!
MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
5908 ErrInfo =
"VALU instruction does not implicitly read exec mask";
5914 if (
MI.mayStore() &&
5919 if (Soff && Soff->
getReg() != AMDGPU::M0) {
5920 ErrInfo =
"scalar stores must use m0 as offset register";
5926 if (
isFLAT(
MI) && !ST.hasFlatInstOffsets()) {
5928 if (
Offset->getImm() != 0) {
5929 ErrInfo =
"subtarget does not support offsets in flat instructions";
5934 if (
isDS(
MI) && !ST.hasGDS()) {
5936 if (GDSOp && GDSOp->
getImm() != 0) {
5937 ErrInfo =
"GDS is not supported on this subtarget";
5945 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
5946 AMDGPU::OpName::vaddr0);
5947 AMDGPU::OpName RSrcOpName =
5948 isMIMG(
MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
5949 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
5957 ErrInfo =
"dim is out of range";
5962 if (ST.hasR128A16()) {
5964 IsA16 = R128A16->
getImm() != 0;
5965 }
else if (ST.hasA16()) {
5967 IsA16 = A16->
getImm() != 0;
5970 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
5972 unsigned AddrWords =
5975 unsigned VAddrWords;
5977 VAddrWords = RsrcIdx - VAddr0Idx;
5978 if (ST.hasPartialNSAEncoding() &&
5980 unsigned LastVAddrIdx = RsrcIdx - 1;
5981 VAddrWords +=
getOpSize(
MI, LastVAddrIdx) / 4 - 1;
5989 if (VAddrWords != AddrWords) {
5991 <<
" but got " << VAddrWords <<
"\n");
5992 ErrInfo =
"bad vaddr size";
6002 unsigned DC = DppCt->
getImm();
6003 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
6004 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
6005 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
6006 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
6007 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
6008 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
6009 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
6010 ErrInfo =
"Invalid dpp_ctrl value";
6013 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
6014 !ST.hasDPPWavefrontShifts()) {
6015 ErrInfo =
"Invalid dpp_ctrl value: "
6016 "wavefront shifts are not supported on GFX10+";
6019 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
6020 !ST.hasDPPBroadcasts()) {
6021 ErrInfo =
"Invalid dpp_ctrl value: "
6022 "broadcasts are not supported on GFX10+";
6025 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
6027 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
6028 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
6029 !ST.hasGFX90AInsts()) {
6030 ErrInfo =
"Invalid dpp_ctrl value: "
6031 "row_newbroadcast/row_share is not supported before "
6035 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
6036 ErrInfo =
"Invalid dpp_ctrl value: "
6037 "row_share and row_xmask are not supported before GFX10";
6042 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
6045 ErrInfo =
"Invalid dpp_ctrl value: "
6046 "DP ALU dpp only support row_newbcast";
6053 AMDGPU::OpName DataName =
6054 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
6060 if (!ST.hasGFX90AInsts()) {
6061 if ((Dst && RI.isAGPR(MRI, Dst->getReg())) ||
6062 (
Data && RI.isAGPR(MRI,
Data->getReg())) ||
6063 (Data2 && RI.isAGPR(MRI, Data2->
getReg()))) {
6064 ErrInfo =
"Invalid register class: "
6065 "agpr loads and stores not supported on this GPU";
6071 if (ST.needsAlignedVGPRs()) {
6072 const auto isAlignedReg = [&
MI, &MRI,
this](AMDGPU::OpName
OpName) ->
bool {
6077 if (Reg.isPhysical())
6078 return !(RI.getHWRegIndex(Reg) & 1);
6080 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
6081 !(RI.getChannelFromSubReg(
Op->getSubReg()) & 1);
6085 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
6086 ErrInfo =
"Subtarget requires even aligned vector registers "
6087 "for vaddr operand of image instructions";
6093 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
6095 if (Src->isReg() && RI.isSGPRReg(MRI, Src->getReg())) {
6096 ErrInfo =
"Invalid register class: "
6097 "v_accvgpr_write with an SGPR is not supported on this GPU";
6102 if (
Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
6105 ErrInfo =
"pseudo expects only physical SGPRs";
6112 if (!ST.hasScaleOffset()) {
6113 ErrInfo =
"Subtarget does not support offset scaling";
6117 ErrInfo =
"Instruction does not support offset scaling";
6125 for (
unsigned I = 0;
I < 3; ++
I) {
6131 if (ST.hasFlatScratchHiInB64InstHazard() &&
isSALU(
MI) &&
6132 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI,
nullptr)) {
6134 if ((Dst && RI.getRegClassForReg(MRI, Dst->getReg()) ==
6135 &AMDGPU::SReg_64RegClass) ||
6136 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
6137 ErrInfo =
"Instruction cannot read flat_scratch_base_hi";
6146 if (
MI.getOpcode() == AMDGPU::S_MOV_B32) {
6148 return MI.getOperand(1).isReg() || RI.isAGPR(MRI,
MI.getOperand(0).getReg())
6150 : AMDGPU::V_MOV_B32_e32;
6160 default:
return AMDGPU::INSTRUCTION_LIST_END;
6161 case AMDGPU::REG_SEQUENCE:
return AMDGPU::REG_SEQUENCE;
6162 case AMDGPU::COPY:
return AMDGPU::COPY;
6163 case AMDGPU::PHI:
return AMDGPU::PHI;
6164 case AMDGPU::INSERT_SUBREG:
return AMDGPU::INSERT_SUBREG;
6165 case AMDGPU::WQM:
return AMDGPU::WQM;
6166 case AMDGPU::SOFT_WQM:
return AMDGPU::SOFT_WQM;
6167 case AMDGPU::STRICT_WWM:
return AMDGPU::STRICT_WWM;
6168 case AMDGPU::STRICT_WQM:
return AMDGPU::STRICT_WQM;
6169 case AMDGPU::S_ADD_I32:
6170 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
6171 case AMDGPU::S_ADDC_U32:
6172 return AMDGPU::V_ADDC_U32_e32;
6173 case AMDGPU::S_SUB_I32:
6174 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
6177 case AMDGPU::S_ADD_U32:
6178 return AMDGPU::V_ADD_CO_U32_e32;
6179 case AMDGPU::S_SUB_U32:
6180 return AMDGPU::V_SUB_CO_U32_e32;
6181 case AMDGPU::S_ADD_U64_PSEUDO:
6182 return AMDGPU::V_ADD_U64_PSEUDO;
6183 case AMDGPU::S_SUB_U64_PSEUDO:
6184 return AMDGPU::V_SUB_U64_PSEUDO;
6185 case AMDGPU::S_SUBB_U32:
return AMDGPU::V_SUBB_U32_e32;
6186 case AMDGPU::S_MUL_I32:
return AMDGPU::V_MUL_LO_U32_e64;
6187 case AMDGPU::S_MUL_HI_U32:
return AMDGPU::V_MUL_HI_U32_e64;
6188 case AMDGPU::S_MUL_HI_I32:
return AMDGPU::V_MUL_HI_I32_e64;
6189 case AMDGPU::S_AND_B32:
return AMDGPU::V_AND_B32_e64;
6190 case AMDGPU::S_OR_B32:
return AMDGPU::V_OR_B32_e64;
6191 case AMDGPU::S_XOR_B32:
return AMDGPU::V_XOR_B32_e64;
6192 case AMDGPU::S_XNOR_B32:
6193 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6194 case AMDGPU::S_MIN_I32:
return AMDGPU::V_MIN_I32_e64;
6195 case AMDGPU::S_MIN_U32:
return AMDGPU::V_MIN_U32_e64;
6196 case AMDGPU::S_MAX_I32:
return AMDGPU::V_MAX_I32_e64;
6197 case AMDGPU::S_MAX_U32:
return AMDGPU::V_MAX_U32_e64;
6198 case AMDGPU::S_ASHR_I32:
return AMDGPU::V_ASHR_I32_e32;
6199 case AMDGPU::S_ASHR_I64:
return AMDGPU::V_ASHR_I64_e64;
6200 case AMDGPU::S_LSHL_B32:
return AMDGPU::V_LSHL_B32_e32;
6201 case AMDGPU::S_LSHL_B64:
return AMDGPU::V_LSHL_B64_e64;
6202 case AMDGPU::S_LSHR_B32:
return AMDGPU::V_LSHR_B32_e32;
6203 case AMDGPU::S_LSHR_B64:
return AMDGPU::V_LSHR_B64_e64;
6204 case AMDGPU::S_SEXT_I32_I8:
return AMDGPU::V_BFE_I32_e64;
6205 case AMDGPU::S_SEXT_I32_I16:
return AMDGPU::V_BFE_I32_e64;
6206 case AMDGPU::S_BFE_U32:
return AMDGPU::V_BFE_U32_e64;
6207 case AMDGPU::S_BFE_I32:
return AMDGPU::V_BFE_I32_e64;
6208 case AMDGPU::S_BFM_B32:
return AMDGPU::V_BFM_B32_e64;
6209 case AMDGPU::S_BREV_B32:
return AMDGPU::V_BFREV_B32_e32;
6210 case AMDGPU::S_NOT_B32:
return AMDGPU::V_NOT_B32_e32;
6211 case AMDGPU::S_NOT_B64:
return AMDGPU::V_NOT_B32_e32;
6212 case AMDGPU::S_CMP_EQ_I32:
return AMDGPU::V_CMP_EQ_I32_e64;
6213 case AMDGPU::S_CMP_LG_I32:
return AMDGPU::V_CMP_NE_I32_e64;
6214 case AMDGPU::S_CMP_GT_I32:
return AMDGPU::V_CMP_GT_I32_e64;
6215 case AMDGPU::S_CMP_GE_I32:
return AMDGPU::V_CMP_GE_I32_e64;
6216 case AMDGPU::S_CMP_LT_I32:
return AMDGPU::V_CMP_LT_I32_e64;
6217 case AMDGPU::S_CMP_LE_I32:
return AMDGPU::V_CMP_LE_I32_e64;
6218 case AMDGPU::S_CMP_EQ_U32:
return AMDGPU::V_CMP_EQ_U32_e64;
6219 case AMDGPU::S_CMP_LG_U32:
return AMDGPU::V_CMP_NE_U32_e64;
6220 case AMDGPU::S_CMP_GT_U32:
return AMDGPU::V_CMP_GT_U32_e64;
6221 case AMDGPU::S_CMP_GE_U32:
return AMDGPU::V_CMP_GE_U32_e64;
6222 case AMDGPU::S_CMP_LT_U32:
return AMDGPU::V_CMP_LT_U32_e64;
6223 case AMDGPU::S_CMP_LE_U32:
return AMDGPU::V_CMP_LE_U32_e64;
6224 case AMDGPU::S_CMP_EQ_U64:
return AMDGPU::V_CMP_EQ_U64_e64;
6225 case AMDGPU::S_CMP_LG_U64:
return AMDGPU::V_CMP_NE_U64_e64;
6226 case AMDGPU::S_BCNT1_I32_B32:
return AMDGPU::V_BCNT_U32_B32_e64;
6227 case AMDGPU::S_FF1_I32_B32:
return AMDGPU::V_FFBL_B32_e32;
6228 case AMDGPU::S_FLBIT_I32_B32:
return AMDGPU::V_FFBH_U32_e32;
6229 case AMDGPU::S_FLBIT_I32:
return AMDGPU::V_FFBH_I32_e64;
6230 case AMDGPU::S_CBRANCH_SCC0:
return AMDGPU::S_CBRANCH_VCCZ;
6231 case AMDGPU::S_CBRANCH_SCC1:
return AMDGPU::S_CBRANCH_VCCNZ;
6232 case AMDGPU::S_CVT_F32_I32:
return AMDGPU::V_CVT_F32_I32_e64;
6233 case AMDGPU::S_CVT_F32_U32:
return AMDGPU::V_CVT_F32_U32_e64;
6234 case AMDGPU::S_CVT_I32_F32:
return AMDGPU::V_CVT_I32_F32_e64;
6235 case AMDGPU::S_CVT_U32_F32:
return AMDGPU::V_CVT_U32_F32_e64;
6236 case AMDGPU::S_CVT_F32_F16:
6237 case AMDGPU::S_CVT_HI_F32_F16:
6238 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6239 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6240 case AMDGPU::S_CVT_F16_F32:
6241 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6242 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6243 case AMDGPU::S_CEIL_F32:
return AMDGPU::V_CEIL_F32_e64;
6244 case AMDGPU::S_FLOOR_F32:
return AMDGPU::V_FLOOR_F32_e64;
6245 case AMDGPU::S_TRUNC_F32:
return AMDGPU::V_TRUNC_F32_e64;
6246 case AMDGPU::S_RNDNE_F32:
return AMDGPU::V_RNDNE_F32_e64;
6247 case AMDGPU::S_CEIL_F16:
6248 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6249 : AMDGPU::V_CEIL_F16_fake16_e64;
6250 case AMDGPU::S_FLOOR_F16:
6251 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6252 : AMDGPU::V_FLOOR_F16_fake16_e64;
6253 case AMDGPU::S_TRUNC_F16:
6254 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6255 : AMDGPU::V_TRUNC_F16_fake16_e64;
6256 case AMDGPU::S_RNDNE_F16:
6257 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6258 : AMDGPU::V_RNDNE_F16_fake16_e64;
6259 case AMDGPU::S_ADD_F32:
return AMDGPU::V_ADD_F32_e64;
6260 case AMDGPU::S_SUB_F32:
return AMDGPU::V_SUB_F32_e64;
6261 case AMDGPU::S_MIN_F32:
return AMDGPU::V_MIN_F32_e64;
6262 case AMDGPU::S_MAX_F32:
return AMDGPU::V_MAX_F32_e64;
6263 case AMDGPU::S_MINIMUM_F32:
return AMDGPU::V_MINIMUM_F32_e64;
6264 case AMDGPU::S_MAXIMUM_F32:
return AMDGPU::V_MAXIMUM_F32_e64;
6265 case AMDGPU::S_MUL_F32:
return AMDGPU::V_MUL_F32_e64;
6266 case AMDGPU::S_ADD_F16:
6267 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6268 : AMDGPU::V_ADD_F16_fake16_e64;
6269 case AMDGPU::S_SUB_F16:
6270 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6271 : AMDGPU::V_SUB_F16_fake16_e64;
6272 case AMDGPU::S_MIN_F16:
6273 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6274 : AMDGPU::V_MIN_F16_fake16_e64;
6275 case AMDGPU::S_MAX_F16:
6276 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6277 : AMDGPU::V_MAX_F16_fake16_e64;
6278 case AMDGPU::S_MINIMUM_F16:
6279 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6280 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6281 case AMDGPU::S_MAXIMUM_F16:
6282 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6283 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6284 case AMDGPU::S_MUL_F16:
6285 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6286 : AMDGPU::V_MUL_F16_fake16_e64;
6287 case AMDGPU::S_CVT_PK_RTZ_F16_F32:
return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6288 case AMDGPU::S_FMAC_F32:
return AMDGPU::V_FMAC_F32_e64;
6289 case AMDGPU::S_FMAC_F16:
6290 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6291 : AMDGPU::V_FMAC_F16_fake16_e64;
6292 case AMDGPU::S_FMAMK_F32:
return AMDGPU::V_FMAMK_F32;
6293 case AMDGPU::S_FMAAK_F32:
return AMDGPU::V_FMAAK_F32;
6294 case AMDGPU::S_CMP_LT_F32:
return AMDGPU::V_CMP_LT_F32_e64;
6295 case AMDGPU::S_CMP_EQ_F32:
return AMDGPU::V_CMP_EQ_F32_e64;
6296 case AMDGPU::S_CMP_LE_F32:
return AMDGPU::V_CMP_LE_F32_e64;
6297 case AMDGPU::S_CMP_GT_F32:
return AMDGPU::V_CMP_GT_F32_e64;
6298 case AMDGPU::S_CMP_LG_F32:
return AMDGPU::V_CMP_LG_F32_e64;
6299 case AMDGPU::S_CMP_GE_F32:
return AMDGPU::V_CMP_GE_F32_e64;
6300 case AMDGPU::S_CMP_O_F32:
return AMDGPU::V_CMP_O_F32_e64;
6301 case AMDGPU::S_CMP_U_F32:
return AMDGPU::V_CMP_U_F32_e64;
6302 case AMDGPU::S_CMP_NGE_F32:
return AMDGPU::V_CMP_NGE_F32_e64;
6303 case AMDGPU::S_CMP_NLG_F32:
return AMDGPU::V_CMP_NLG_F32_e64;
6304 case AMDGPU::S_CMP_NGT_F32:
return AMDGPU::V_CMP_NGT_F32_e64;
6305 case AMDGPU::S_CMP_NLE_F32:
return AMDGPU::V_CMP_NLE_F32_e64;
6306 case AMDGPU::S_CMP_NEQ_F32:
return AMDGPU::V_CMP_NEQ_F32_e64;
6307 case AMDGPU::S_CMP_NLT_F32:
return AMDGPU::V_CMP_NLT_F32_e64;
6308 case AMDGPU::S_CMP_LT_F16:
6309 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6310 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6311 case AMDGPU::S_CMP_EQ_F16:
6312 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6313 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6314 case AMDGPU::S_CMP_LE_F16:
6315 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6316 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6317 case AMDGPU::S_CMP_GT_F16:
6318 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6319 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6320 case AMDGPU::S_CMP_LG_F16:
6321 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6322 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6323 case AMDGPU::S_CMP_GE_F16:
6324 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6325 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6326 case AMDGPU::S_CMP_O_F16:
6327 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6328 : AMDGPU::V_CMP_O_F16_fake16_e64;
6329 case AMDGPU::S_CMP_U_F16:
6330 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6331 : AMDGPU::V_CMP_U_F16_fake16_e64;
6332 case AMDGPU::S_CMP_NGE_F16:
6333 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6334 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6335 case AMDGPU::S_CMP_NLG_F16:
6336 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6337 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6338 case AMDGPU::S_CMP_NGT_F16:
6339 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6340 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6341 case AMDGPU::S_CMP_NLE_F16:
6342 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6343 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6344 case AMDGPU::S_CMP_NEQ_F16:
6345 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6346 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6347 case AMDGPU::S_CMP_NLT_F16:
6348 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6349 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6350 case AMDGPU::V_S_EXP_F32_e64:
return AMDGPU::V_EXP_F32_e64;
6351 case AMDGPU::V_S_EXP_F16_e64:
6352 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6353 : AMDGPU::V_EXP_F16_fake16_e64;
6354 case AMDGPU::V_S_LOG_F32_e64:
return AMDGPU::V_LOG_F32_e64;
6355 case AMDGPU::V_S_LOG_F16_e64:
6356 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6357 : AMDGPU::V_LOG_F16_fake16_e64;
6358 case AMDGPU::V_S_RCP_F32_e64:
return AMDGPU::V_RCP_F32_e64;
6359 case AMDGPU::V_S_RCP_F16_e64:
6360 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6361 : AMDGPU::V_RCP_F16_fake16_e64;
6362 case AMDGPU::V_S_RSQ_F32_e64:
return AMDGPU::V_RSQ_F32_e64;
6363 case AMDGPU::V_S_RSQ_F16_e64:
6364 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6365 : AMDGPU::V_RSQ_F16_fake16_e64;
6366 case AMDGPU::V_S_SQRT_F32_e64:
return AMDGPU::V_SQRT_F32_e64;
6367 case AMDGPU::V_S_SQRT_F16_e64:
6368 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6369 : AMDGPU::V_SQRT_F16_fake16_e64;
6372 "Unexpected scalar opcode without corresponding vector one!");
6421 "Not a whole wave func");
6424 if (
MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6425 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6432 unsigned OpNo)
const {
6434 if (
MI.isVariadic() || OpNo >=
Desc.getNumOperands() ||
6435 Desc.operands()[OpNo].RegClass == -1) {
6438 if (Reg.isVirtual()) {
6442 return RI.getPhysRegBaseClass(Reg);
6445 int16_t RegClass = getOpRegClassID(
Desc.operands()[OpNo]);
6446 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6451 constexpr AMDGPU::OpName OpNames[] = {
6452 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6455 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
I]);
6456 if (
static_cast<unsigned>(SrcIdx) == OpIdx)
6468 unsigned RCID = getOpRegClassID(
get(
MI.getOpcode()).operands()[OpIdx]);
6470 unsigned Size = RI.getRegSizeInBits(*RC);
6471 unsigned Opcode = (
Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6472 :
Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6473 : AMDGPU::V_MOV_B32_e32;
6475 Opcode = AMDGPU::COPY;
6476 else if (RI.isSGPRClass(RC))
6477 Opcode = (
Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6502 .
addImm(AMDGPU::sub0_sub1)
6504 .
addImm(AMDGPU::sub2_sub3);
6517 return RI.getSubReg(SuperReg.
getReg(), SubIdx);
6523 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.
getSubReg(), SubIdx);
6534 if (SubIdx == AMDGPU::sub0)
6536 if (SubIdx == AMDGPU::sub1)
6548void SIInstrInfo::swapOperands(
MachineInstr &Inst)
const {
6564 if (Reg.isPhysical())
6571 RI.getLargestLegalSuperClass(RC, MRI.
getMF());
6574 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.
getSubReg()) !=
nullptr;
6577 return RI.getCommonSubClass(DRC, RC) !=
nullptr;
6584 unsigned Opc =
MI.getOpcode();
6587 if (MO.
isReg() && RI.isSGPRReg(MRI, MO.
getReg()) &&
6597 bool IsAGPR = RI.isAGPR(MRI, MO.
getReg());
6598 if (IsAGPR && !ST.hasMAIInsts())
6604 const int VDstIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
6605 const int DataIdx = AMDGPU::getNamedOperandIdx(
6606 Opc,
isDS(
Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6607 if ((
int)OpIdx == VDstIdx && DataIdx != -1 &&
6608 MI.getOperand(DataIdx).isReg() &&
6609 RI.isAGPR(MRI,
MI.getOperand(DataIdx).getReg()) != IsAGPR)
6611 if ((
int)OpIdx == DataIdx) {
6612 if (VDstIdx != -1 &&
6613 RI.isAGPR(MRI,
MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6616 const int Data1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
6617 if (Data1Idx != -1 &&
MI.getOperand(Data1Idx).isReg() &&
6618 RI.isAGPR(MRI,
MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6623 if (
Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6624 (
int)OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) &&
6625 RI.isSGPRReg(MRI, MO.
getReg()))
6628 if (ST.hasFlatScratchHiInB64InstHazard() &&
6635 if (
Opc == AMDGPU::S_BITCMP0_B64 ||
Opc == AMDGPU::S_BITCMP1_B64)
6638 if (!ST.hasDPPSrc1SGPR() &&
isDPP(
MI) && RI.isSGPRReg(MRI, MO.
getReg()) &&
6639 (
int)OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1))
6659 constexpr unsigned NumOps = 3;
6660 constexpr AMDGPU::OpName OpNames[
NumOps * 2] = {
6661 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6662 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6663 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6668 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[SrcN]);
6671 MO = &
MI.getOperand(SrcIdx);
6674 if (!MO->
isReg() || !RI.isSGPRReg(MRI, MO->
getReg()))
6678 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
NumOps + SrcN]);
6682 unsigned Mods =
MI.getOperand(ModsIdx).getImm();
6686 return !OpSel && !OpSelHi;
6695 int64_t RegClass = getOpRegClassID(OpInfo);
6697 RegClass != -1 ? RI.getRegClass(RegClass) :
nullptr;
6699 MO = &
MI.getOperand(OpIdx);
6703 if (
isVALU(
MI,
false) && !IsInlineConst &&
6707 int ConstantBusLimit = ST.getConstantBusLimit(
MI.getOpcode());
6708 int LiteralLimit = !
isVOP3(
MI) || ST.hasVOP3Literal() ? 1 : 0;
6712 if (!LiteralLimit--)
6722 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6730 if (--ConstantBusLimit <= 0)
6742 if (!LiteralLimit--)
6744 if (--ConstantBusLimit <= 0)
6750 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6754 if (!
Op.isReg() && !
Op.isFI() && !
Op.isRegMask() &&
6756 !
Op.isIdenticalTo(*MO))
6778 bool Is64BitOp = Is64BitFPOp ||
6786 (!ST.has64BitLiterals() || InstDesc.
getSize() != 4))
6795 if (!Is64BitFPOp && (int32_t)
Imm < 0 &&
6813 bool IsGFX950Only = ST.hasGFX950Insts();
6814 bool IsGFX940Only = ST.hasGFX940Insts();
6816 if (!IsGFX950Only && !IsGFX940Only)
6834 unsigned Opcode =
MI.getOpcode();
6836 case AMDGPU::V_CVT_PK_BF8_F32_e64:
6837 case AMDGPU::V_CVT_PK_FP8_F32_e64:
6838 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
6839 case AMDGPU::V_MQSAD_U32_U8_e64:
6840 case AMDGPU::V_PK_ADD_F16:
6841 case AMDGPU::V_PK_ADD_F32:
6842 case AMDGPU::V_PK_ADD_I16:
6843 case AMDGPU::V_PK_ADD_U16:
6844 case AMDGPU::V_PK_ASHRREV_I16:
6845 case AMDGPU::V_PK_FMA_F16:
6846 case AMDGPU::V_PK_FMA_F32:
6847 case AMDGPU::V_PK_FMAC_F16_e32:
6848 case AMDGPU::V_PK_FMAC_F16_e64:
6849 case AMDGPU::V_PK_LSHLREV_B16:
6850 case AMDGPU::V_PK_LSHRREV_B16:
6851 case AMDGPU::V_PK_MAD_I16:
6852 case AMDGPU::V_PK_MAD_U16:
6853 case AMDGPU::V_PK_MAX_F16:
6854 case AMDGPU::V_PK_MAX_I16:
6855 case AMDGPU::V_PK_MAX_U16:
6856 case AMDGPU::V_PK_MIN_F16:
6857 case AMDGPU::V_PK_MIN_I16:
6858 case AMDGPU::V_PK_MIN_U16:
6859 case AMDGPU::V_PK_MOV_B32:
6860 case AMDGPU::V_PK_MUL_F16:
6861 case AMDGPU::V_PK_MUL_F32:
6862 case AMDGPU::V_PK_MUL_LO_U16:
6863 case AMDGPU::V_PK_SUB_I16:
6864 case AMDGPU::V_PK_SUB_U16:
6865 case AMDGPU::V_QSAD_PK_U16_U8_e64:
6874 unsigned Opc =
MI.getOpcode();
6877 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
6880 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
6886 if (HasImplicitSGPR && ST.getConstantBusLimit(
Opc) <= 1 && Src0.
isReg() &&
6887 RI.isSGPRReg(MRI, Src0.
getReg()))
6893 if (
Opc == AMDGPU::V_WRITELANE_B32) {
6895 if (Src0.
isReg() && RI.isVGPR(MRI, Src0.
getReg())) {
6901 if (Src1.
isReg() && RI.isVGPR(MRI, Src1.
getReg())) {
6912 if (
Opc == AMDGPU::V_FMAC_F32_e32 ||
Opc == AMDGPU::V_FMAC_F16_e32) {
6913 int Src2Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2);
6914 if (!RI.isVGPR(MRI,
MI.getOperand(Src2Idx).getReg()))
6926 if (
Opc == AMDGPU::V_READLANE_B32 && Src1.
isReg() &&
6927 RI.isVGPR(MRI, Src1.
getReg())) {
6940 if (HasImplicitSGPR || !
MI.isCommutable()) {
6957 if (CommutedOpc == -1) {
6962 MI.setDesc(
get(CommutedOpc));
6966 bool Src0Kill = Src0.
isKill();
6970 else if (Src1.
isReg()) {
6985 unsigned Opc =
MI.getOpcode();
6988 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0),
6989 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1),
6990 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2)
6993 if (
Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
6994 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
6995 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
6996 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
6997 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
6998 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
6999 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
7009 if (VOP3Idx[2] != -1) {
7021 int ConstantBusLimit = ST.getConstantBusLimit(
Opc);
7022 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
7024 Register SGPRReg = findUsedSGPR(
MI, VOP3Idx);
7026 SGPRsUsed.
insert(SGPRReg);
7030 for (
int Idx : VOP3Idx) {
7039 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
7051 if (!RI.isSGPRClass(RI.getRegClassForReg(MRI, MO.
getReg())))
7058 if (ConstantBusLimit > 0) {
7070 if ((
Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64) &&
7071 !RI.isVGPR(MRI,
MI.getOperand(VOP3Idx[2]).getReg()))
7077 for (
unsigned I = 0;
I < 3; ++
I) {
7090 SRC = RI.getCommonSubClass(SRC, DstRC);
7093 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
7095 if (RI.hasAGPRs(VRC)) {
7096 VRC = RI.getEquivalentVGPRClass(VRC);
7099 get(TargetOpcode::COPY), NewSrcReg)
7106 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
7112 for (
unsigned i = 0; i < SubRegs; ++i) {
7115 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
7116 .
addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
7122 get(AMDGPU::REG_SEQUENCE), DstReg);
7123 for (
unsigned i = 0; i < SubRegs; ++i) {
7125 MIB.
addImm(RI.getSubRegFromChannel(i));
7138 if (SBase && !RI.isSGPRClass(MRI.
getRegClass(SBase->getReg()))) {
7140 SBase->setReg(SGPR);
7143 if (SOff && !RI.isSGPRReg(MRI, SOff->
getReg())) {
7151 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::saddr);
7152 if (OldSAddrIdx < 0)
7165 if (RI.isSGPRReg(MRI, SAddr.
getReg()))
7168 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
7169 if (NewVAddrIdx < 0)
7172 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr);
7176 if (OldVAddrIdx >= 0) {
7190 if (OldVAddrIdx == NewVAddrIdx) {
7201 assert(OldSAddrIdx == NewVAddrIdx);
7203 if (OldVAddrIdx >= 0) {
7204 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7205 AMDGPU::OpName::vdst_in);
7209 if (NewVDstIn != -1) {
7210 int OldVDstIn = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst_in);
7216 if (NewVDstIn != -1) {
7217 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7258 unsigned OpSubReg =
Op.getSubReg();
7261 RI.getRegClassForReg(MRI, OpReg), OpSubReg);
7268 auto Copy =
BuildMI(InsertMBB,
I,
DL,
get(AMDGPU::COPY), DstReg)
7269 .
addReg(OpReg, {}, OpSubReg);
7271 Op.setSubReg(AMDGPU::NoSubRegister);
7278 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7281 bool ImpDef = Def->isImplicitDef();
7282 while (!ImpDef && Def && Def->isCopy()) {
7283 if (Def->getOperand(1).getReg().isPhysical())
7286 ImpDef = Def && Def->isImplicitDef();
7288 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7304 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7309 bool UseNewExecInstructions =
7318 if (UseNewExecInstructions) {
7353 for (
auto [Idx, ScalarOp] :
enumerate(ScalarOps)) {
7354 unsigned RegSize =
TRI->getRegSizeInBits(ScalarOp->getReg(), MRI);
7355 unsigned NumSubRegs =
RegSize / 32;
7356 Register VScalarOp = ScalarOp->getReg();
7359 TII.getRegClass(
TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7361 if (NumSubRegs == 1) {
7364 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7365 Common != VScalarOpRC) {
7372 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7375 if (UseNewExecInstructions) {
7377 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7380 if (
I == LoopBB.
end())
7385 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7391 CondReg = NewCondReg;
7402 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7403 ScalarOp->setReg(CurReg);
7406 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7407 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7409 ScalarOp->setReg(PhySGPRs[Idx]);
7411 ScalarOp->setIsKill();
7415 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7416 "Unhandled register size");
7418 for (
unsigned Idx = 0; Idx < NumSubRegs; Idx += 2) {
7425 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7426 .
addReg(VScalarOp, VScalarOpUndef,
TRI->getSubRegFromChannel(Idx));
7429 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7430 .
addReg(VScalarOp, VScalarOpUndef,
7431 TRI->getSubRegFromChannel(Idx + 1));
7438 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7445 NumSubRegs <= 2 ? 0 :
TRI->getSubRegFromChannel(Idx, 2);
7447 if (UseNewExecInstructions) {
7449 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7451 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7452 if (
I == LoopBB.
end())
7456 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7458 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7462 CondReg = NewCondReg;
7473 const auto *SScalarOpRC =
7479 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7480 unsigned Channel = 0;
7481 for (
Register Piece : ReadlanePieces) {
7482 Merge.addReg(Piece).addImm(
TRI->getSubRegFromChannel(Channel++));
7486 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7487 ScalarOp->setReg(SScalarOp);
7489 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7490 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7492 ScalarOp->setReg(PhySGPRs[Idx]);
7494 ScalarOp->setIsKill();
7502 if (!UseNewExecInstructions) {
7514 if (UseNewExecInstructions) {
7538 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.
size()) &&
7539 "Physical SGPRs must be empty or match the number of scalar operands");
7545 if (!Begin.isValid())
7547 if (!End.isValid()) {
7553 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7562 std::numeric_limits<unsigned>::max()) !=
7580 for (
auto I = Begin;
I != AfterMI;
I++) {
7581 for (
auto &MO :
I->all_uses())
7617 for (
auto &Succ : RemainderBB->
successors()) {
7642static std::tuple<unsigned, unsigned>
7650 TII.buildExtractSubReg(
MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7651 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7658 uint64_t RsrcDataFormat =
TII.getDefaultRsrcDataFormat();
7675 .
addImm(AMDGPU::sub0_sub1)
7681 return std::tuple(RsrcPtr, NewSRsrc);
7692 if (ST.useRealTrue16Insts())
7722 if (
MI.getOpcode() == AMDGPU::PHI) {
7724 assert(!RI.isSGPRClass(VRC));
7727 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7729 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7745 if (
MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7748 if (RI.hasVGPRs(DstRC)) {
7752 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7754 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7772 if (
MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7777 if (DstRC != Src0RC) {
7786 if (
MI.getOpcode() == AMDGPU::SI_INIT_M0) {
7788 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7794 if (
MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
7795 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
7796 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
7797 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
7798 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
7799 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
7800 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
7802 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7815 ? AMDGPU::OpName::rsrc
7816 : AMDGPU::OpName::srsrc;
7821 AMDGPU::OpName SampOpName =
7822 isMIMG(
MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
7831 if (
MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
7839 if (
MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
7843 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src0);
7853 if (
MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
7854 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
7855 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
7856 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
7858 if (Src.isReg() && RI.hasVectorRegisters(MRI.
getRegClass(Src.getReg())))
7865 bool isSoffsetLegal =
true;
7867 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::soffset);
7868 if (SoffsetIdx != -1) {
7872 isSoffsetLegal =
false;
7876 bool isRsrcLegal =
true;
7878 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::srsrc);
7879 if (RsrcIdx != -1) {
7881 if (Rsrc->
isReg() && !RI.isSGPRReg(MRI, Rsrc->
getReg()))
7882 isRsrcLegal =
false;
7886 if (isRsrcLegal && isSoffsetLegal)
7914 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
7918 unsigned RsrcPtr, NewSRsrc;
7925 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
7926 .addReg(VAddr->
getReg(), {}, AMDGPU::sub0)
7932 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
7933 .addReg(VAddr->
getReg(), {}, AMDGPU::sub1)
7946 }
else if (!VAddr && ST.hasAddr64()) {
7950 "FIXME: Need to emit flat atomics here");
7952 unsigned RsrcPtr, NewSRsrc;
7978 MIB.
addImm(CPol->getImm());
7983 MIB.
addImm(TFE->getImm());
8003 MI.removeFromParent();
8008 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
8009 .addImm(AMDGPU::sub0)
8010 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
8011 .addImm(AMDGPU::sub1);
8014 if (!isSoffsetLegal) {
8025 if (!isSoffsetLegal) {
8034 if (InSet.insert(
MI).second)
8038 AMDGPU::getNamedOperandIdx(
MI->getOpcode(), AMDGPU::OpName::srsrc);
8039 if (RsrcIdx != -1) {
8040 DeferredList.insert(
MI);
8045 return DeferredList.contains(
MI);
8055 if (!ST.useRealTrue16Insts())
8058 unsigned Opcode =
MI.getOpcode();
8061 if (OpIdx >=
MI.getNumExplicitOperands() ||
8062 OpIdx >=
get(Opcode).getNumOperands() ||
8063 get(Opcode).operands()[OpIdx].RegClass == -1)
8067 if (!
Op.isReg() || !
Op.getReg().isVirtual() ||
Op.isDef())
8071 if (!RI.isVGPRClass(CurrRC))
8074 int16_t RCID = getOpRegClassID(
get(Opcode).operands()[OpIdx]);
8076 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
8078 if (
Op.getSubReg() == AMDGPU::NoSubRegister)
8079 Op.setSubReg(AMDGPU::lo16);
8084 RI.getSubRegisterClass(CurrRC,
Op.getSubReg());
8085 if (RI.getMatchingSuperRegClass(ExpectedRC, CurrSRC, AMDGPU::lo16)) {
8095 Op.setReg(NewDstReg);
8096 Op.setSubReg(AMDGPU::NoSubRegister);
8101 for (
unsigned OpIdx = 0; OpIdx <
MI.getNumExplicitOperands(); OpIdx++)
8109 assert(
MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
8110 "This only handle waterfall for SI_CALL_ISEL");
8117 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
8120 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
8125 while (End !=
MBB.end() && End->isCopy() &&
8126 MI->definesRegister(End->getOperand(1).getReg(), &RI))
8136 while (!Worklist.
empty()) {
8142 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
8148 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
8150 "Deferred MachineInstr are not supposed to re-populate worklist");
8153 for (
auto &Entry : WaterFalls) {
8154 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
8156 Entry.second.SGPRs);
8159 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
8161 Entry.first->eraseFromParent();
8169 if (SubRegIndices.
size() <= 1) {
8172 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8179 for (int16_t Indice : SubRegIndices) {
8182 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8189 get(AMDGPU::REG_SEQUENCE), DstReg);
8190 for (
unsigned i = 0; i < SubRegIndices.size(); ++i) {
8192 MIB.
addImm(RI.getSubRegFromChannel(i));
8202 if (DstReg == AMDGPU::M0) {
8215 if (
I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
8217 for (
unsigned i = 0; i <
UseMI->getNumOperands(); ++i) {
8218 if (
UseMI->getOperand(i).isReg() &&
8219 UseMI->getOperand(i).getReg() == DstReg) {
8223 V2SCopyInfo.MOs.push_back(MO);
8224 V2SCopyInfo.SGPRs.push_back(DstReg);
8228 }
else if (
I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8229 I->getOperand(0).isReg() &&
8230 I->getOperand(0).getReg() == DstReg) {
8233 }
else if (
I->readsRegister(DstReg, &RI)) {
8235 V2SPhyCopiesToErase[&Inst] =
false;
8237 if (
I->findRegisterDefOperand(DstReg, &RI))
8259 case AMDGPU::S_ADD_I32:
8260 case AMDGPU::S_SUB_I32: {
8264 std::tie(
Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8272 case AMDGPU::S_MUL_U64:
8273 if (ST.useVMulU64Inst()) {
8274 NewOpcode = AMDGPU::V_MUL_U64_e64;
8278 splitScalarSMulU64(Worklist, Inst, MDT);
8282 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8283 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8286 splitScalarSMulPseudo(Worklist, Inst, MDT);
8290 case AMDGPU::S_AND_B64:
8291 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8295 case AMDGPU::S_OR_B64:
8296 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8300 case AMDGPU::S_XOR_B64:
8301 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8305 case AMDGPU::S_NAND_B64:
8306 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8310 case AMDGPU::S_NOR_B64:
8311 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8315 case AMDGPU::S_XNOR_B64:
8316 if (ST.hasDLInsts())
8317 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8319 splitScalar64BitXnor(Worklist, Inst, MDT);
8323 case AMDGPU::S_ANDN2_B64:
8324 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8328 case AMDGPU::S_ORN2_B64:
8329 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8333 case AMDGPU::S_BREV_B64:
8334 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32,
true);
8338 case AMDGPU::S_NOT_B64:
8339 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8343 case AMDGPU::S_BCNT1_I32_B64:
8344 splitScalar64BitBCNT(Worklist, Inst);
8348 case AMDGPU::S_BFE_I64:
8349 splitScalar64BitBFE(Worklist, Inst);
8353 case AMDGPU::S_FLBIT_I32_B64:
8354 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8357 case AMDGPU::S_FF1_I32_B64:
8358 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8362 case AMDGPU::S_LSHL_B32:
8363 if (ST.hasOnlyRevVALUShifts()) {
8364 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8368 case AMDGPU::S_ASHR_I32:
8369 if (ST.hasOnlyRevVALUShifts()) {
8370 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8374 case AMDGPU::S_LSHR_B32:
8375 if (ST.hasOnlyRevVALUShifts()) {
8376 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8380 case AMDGPU::S_LSHL_B64:
8381 if (ST.hasOnlyRevVALUShifts()) {
8383 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8384 : AMDGPU::V_LSHLREV_B64_e64;
8388 case AMDGPU::S_ASHR_I64:
8389 if (ST.hasOnlyRevVALUShifts()) {
8390 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8394 case AMDGPU::S_LSHR_B64:
8395 if (ST.hasOnlyRevVALUShifts()) {
8396 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8401 case AMDGPU::S_ABS_I32:
8402 lowerScalarAbs(Worklist, Inst);
8406 case AMDGPU::S_ABSDIFF_I32:
8407 lowerScalarAbsDiff(Worklist, Inst);
8411 case AMDGPU::S_CBRANCH_SCC0:
8412 case AMDGPU::S_CBRANCH_SCC1: {
8415 bool IsSCC = CondReg == AMDGPU::SCC;
8423 case AMDGPU::S_BFE_U64:
8424 case AMDGPU::S_BFM_B64:
8427 case AMDGPU::S_PACK_LL_B32_B16:
8428 case AMDGPU::S_PACK_LH_B32_B16:
8429 case AMDGPU::S_PACK_HL_B32_B16:
8430 case AMDGPU::S_PACK_HH_B32_B16:
8431 movePackToVALU(Worklist, MRI, Inst);
8435 case AMDGPU::S_XNOR_B32:
8436 lowerScalarXnor(Worklist, Inst);
8440 case AMDGPU::S_NAND_B32:
8441 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8445 case AMDGPU::S_NOR_B32:
8446 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8450 case AMDGPU::S_ANDN2_B32:
8451 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8455 case AMDGPU::S_ORN2_B32:
8456 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8464 case AMDGPU::S_ADD_CO_PSEUDO:
8465 case AMDGPU::S_SUB_CO_PSEUDO: {
8466 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8467 ? AMDGPU::V_ADDC_U32_e64
8468 : AMDGPU::V_SUBB_U32_e64;
8469 const auto *CarryRC = RI.getWaveMaskRegClass();
8491 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8495 case AMDGPU::S_UADDO_PSEUDO:
8496 case AMDGPU::S_USUBO_PSEUDO: {
8502 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8503 ? AMDGPU::V_ADD_CO_U32_e64
8504 : AMDGPU::V_SUB_CO_U32_e64;
8516 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8520 case AMDGPU::S_LSHL1_ADD_U32:
8521 case AMDGPU::S_LSHL2_ADD_U32:
8522 case AMDGPU::S_LSHL3_ADD_U32:
8523 case AMDGPU::S_LSHL4_ADD_U32: {
8527 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8528 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8529 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8543 addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
8547 case AMDGPU::S_CSELECT_B32:
8548 case AMDGPU::S_CSELECT_B64:
8549 lowerSelect(Worklist, Inst, MDT);
8552 case AMDGPU::S_CMP_EQ_I32:
8553 case AMDGPU::S_CMP_LG_I32:
8554 case AMDGPU::S_CMP_GT_I32:
8555 case AMDGPU::S_CMP_GE_I32:
8556 case AMDGPU::S_CMP_LT_I32:
8557 case AMDGPU::S_CMP_LE_I32:
8558 case AMDGPU::S_CMP_EQ_U32:
8559 case AMDGPU::S_CMP_LG_U32:
8560 case AMDGPU::S_CMP_GT_U32:
8561 case AMDGPU::S_CMP_GE_U32:
8562 case AMDGPU::S_CMP_LT_U32:
8563 case AMDGPU::S_CMP_LE_U32:
8564 case AMDGPU::S_CMP_EQ_U64:
8565 case AMDGPU::S_CMP_LG_U64:
8566 case AMDGPU::S_CMP_LT_F32:
8567 case AMDGPU::S_CMP_EQ_F32:
8568 case AMDGPU::S_CMP_LE_F32:
8569 case AMDGPU::S_CMP_GT_F32:
8570 case AMDGPU::S_CMP_LG_F32:
8571 case AMDGPU::S_CMP_GE_F32:
8572 case AMDGPU::S_CMP_O_F32:
8573 case AMDGPU::S_CMP_U_F32:
8574 case AMDGPU::S_CMP_NGE_F32:
8575 case AMDGPU::S_CMP_NLG_F32:
8576 case AMDGPU::S_CMP_NGT_F32:
8577 case AMDGPU::S_CMP_NLE_F32:
8578 case AMDGPU::S_CMP_NEQ_F32:
8579 case AMDGPU::S_CMP_NLT_F32: {
8584 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8598 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8602 case AMDGPU::S_CMP_LT_F16:
8603 case AMDGPU::S_CMP_EQ_F16:
8604 case AMDGPU::S_CMP_LE_F16:
8605 case AMDGPU::S_CMP_GT_F16:
8606 case AMDGPU::S_CMP_LG_F16:
8607 case AMDGPU::S_CMP_GE_F16:
8608 case AMDGPU::S_CMP_O_F16:
8609 case AMDGPU::S_CMP_U_F16:
8610 case AMDGPU::S_CMP_NGE_F16:
8611 case AMDGPU::S_CMP_NLG_F16:
8612 case AMDGPU::S_CMP_NGT_F16:
8613 case AMDGPU::S_CMP_NLE_F16:
8614 case AMDGPU::S_CMP_NEQ_F16:
8615 case AMDGPU::S_CMP_NLT_F16: {
8637 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8641 case AMDGPU::S_CVT_HI_F32_F16: {
8644 if (ST.useRealTrue16Insts()) {
8649 .
addReg(TmpReg, {}, AMDGPU::hi16)
8665 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8669 case AMDGPU::S_MINIMUM_F32:
8670 case AMDGPU::S_MAXIMUM_F32: {
8682 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8686 case AMDGPU::S_MINIMUM_F16:
8687 case AMDGPU::S_MAXIMUM_F16: {
8689 ? &AMDGPU::VGPR_16RegClass
8690 : &AMDGPU::VGPR_32RegClass);
8701 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8705 case AMDGPU::V_S_EXP_F16_e64:
8706 case AMDGPU::V_S_LOG_F16_e64:
8707 case AMDGPU::V_S_RCP_F16_e64:
8708 case AMDGPU::V_S_RSQ_F16_e64:
8709 case AMDGPU::V_S_SQRT_F16_e64: {
8711 ? &AMDGPU::VGPR_16RegClass
8712 : &AMDGPU::VGPR_32RegClass);
8723 addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
8729 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8737 if (NewOpcode == Opcode) {
8744 V2SPhyCopiesToErase);
8752 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8759 addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist);
8765 RI.composeSubRegIndices(SrcSubReg, UseMO.getSubReg()));
8766 UseMO.setReg(NewDstReg);
8785 unsigned OpIdx =
UseMI.getOperandNo(&UseMO);
8798 if (ST.useRealTrue16Insts() && Inst.
isCopy() &&
8802 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
8808 get(AMDGPU::REG_SEQUENCE), NewDstReg)
8815 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8817 }
else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
8822 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8830 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8840 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8841 AMDGPU::OpName::src0_modifiers) >= 0)
8845 NewInstr->addOperand(Src);
8848 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
8851 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
8853 NewInstr.addImm(
Size);
8854 }
else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
8858 }
else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
8863 "Scalar BFE is only implemented for constant width and offset");
8871 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8872 AMDGPU::OpName::src1_modifiers) >= 0)
8874 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
8876 if (AMDGPU::getNamedOperandIdx(NewOpcode,
8877 AMDGPU::OpName::src2_modifiers) >= 0)
8879 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
8881 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
8883 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
8885 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
8891 NewInstr->addOperand(
Op);
8898 if (
Op.getReg() == AMDGPU::SCC) {
8900 if (
Op.isDef() && !
Op.isDead())
8901 addSCCDefUsersToVALUWorklist(
Op, Inst, Worklist);
8903 addSCCDefsToVALUWorklist(NewInstr, Worklist);
8908 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
8909 Register DstReg = NewInstr->getOperand(0).getReg();
8922 addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
8926std::pair<bool, MachineBasicBlock *>
8929 if (ST.hasAddNoCarryInsts()) {
8941 assert(
Opc == AMDGPU::S_ADD_I32 ||
Opc == AMDGPU::S_SUB_I32);
8943 unsigned NewOpc =
Opc == AMDGPU::S_ADD_I32 ?
8944 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
8955 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
8956 return std::pair(
true, NewBB);
8959 return std::pair(
false,
nullptr);
8976 bool IsSCC = (CondReg == AMDGPU::SCC);
8984 for (MachineOperand &UseMO :
8986 MachineInstr &
UseMI = *UseMO.getParent();
8987 switch (
UseMI.getOpcode()) {
8988 case AMDGPU::V_CNDMASK_B16_fake16_e32:
8989 case AMDGPU::V_CNDMASK_B16_fake16_e64:
8990 case AMDGPU::V_CNDMASK_B16_t16_e32:
8991 case AMDGPU::V_CNDMASK_B16_t16_e64:
8992 case AMDGPU::V_CNDMASK_B32_e32:
8993 case AMDGPU::V_CNDMASK_B32_e64:
8994 case AMDGPU::V_CNDMASK_B64_PSEUDO:
8995 if (UseMO.isImplicit() ||
8997 UseMO.setReg(CondReg);
9011 bool CopyFound =
false;
9012 for (MachineInstr &CandI :
9015 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) !=
9017 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
9019 .
addReg(CandI.getOperand(1).getReg());
9031 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
9040 MachineInstr *NewInst;
9041 if (Inst.
getOpcode() == AMDGPU::S_CSELECT_B32) {
9042 NewInst =
BuildMI(
MBB, MII,
DL,
get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
9057 addUsersToMoveToVALUWorklist(NewDestReg, MRI, Worklist);
9072 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
9073 : AMDGPU::V_SUB_CO_U32_e32;
9084 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9101 unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
9102 : AMDGPU::V_SUB_CO_U32_e32;
9115 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9129 if (ST.hasDLInsts()) {
9139 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9145 bool Src0IsSGPR = Src0.
isReg() &&
9147 bool Src1IsSGPR = Src1.
isReg() &&
9161 }
else if (Src1IsSGPR) {
9179 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9185 unsigned Opcode)
const {
9209 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9214 unsigned Opcode)
const {
9238 addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
9253 const MCInstrDesc &InstDesc =
get(Opcode);
9256 &AMDGPU::SGPR_32RegClass;
9259 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9262 AMDGPU::sub0, Src0SubRC);
9267 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9270 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0).
add(SrcReg0Sub0);
9273 AMDGPU::sub1, Src0SubRC);
9276 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1).
add(SrcReg0Sub1);
9290 Worklist.
insert(&LoHalf);
9291 Worklist.
insert(&HiHalf);
9297 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9321 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9322 if (RI.isSGPRClass(Src0SubRC))
9323 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9325 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9326 if (RI.isSGPRClass(Src1SubRC))
9327 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9331 MachineOperand Op0L =
9333 MachineOperand Op1L =
9335 MachineOperand Op0H =
9337 MachineOperand Op1H =
9356 MachineInstr *Op1L_Op0H =
9362 MachineInstr *Op1H_Op0L =
9368 MachineInstr *Carry =
9373 MachineInstr *LoHalf =
9383 MachineInstr *HiHalf =
9406 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9430 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9431 if (RI.isSGPRClass(Src0SubRC))
9432 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9434 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9435 if (RI.isSGPRClass(Src1SubRC))
9436 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9440 MachineOperand Op0L =
9442 MachineOperand Op1L =
9446 unsigned NewOpc =
Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9447 ? AMDGPU::V_MUL_HI_U32_e64
9448 : AMDGPU::V_MUL_HI_I32_e64;
9449 MachineInstr *HiHalf =
9452 MachineInstr *LoHalf =
9471 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9487 const MCInstrDesc &InstDesc =
get(Opcode);
9490 &AMDGPU::SGPR_32RegClass;
9493 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9496 &AMDGPU::SGPR_32RegClass;
9499 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9502 AMDGPU::sub0, Src0SubRC);
9504 AMDGPU::sub0, Src1SubRC);
9506 AMDGPU::sub1, Src0SubRC);
9508 AMDGPU::sub1, Src1SubRC);
9513 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9516 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0)
9521 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1)
9534 Worklist.
insert(&LoHalf);
9535 Worklist.
insert(&HiHalf);
9538 addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
9558 MachineOperand* Op0;
9559 MachineOperand* Op1;
9561 if (Src0.
isReg() && RI.isSGPRReg(MRI, Src0.
getReg())) {
9594 const MCInstrDesc &InstDesc =
get(AMDGPU::V_BCNT_U32_B32_e64);
9597 &AMDGPU::SGPR_32RegClass;
9603 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9606 AMDGPU::sub0, SrcSubRC);
9608 AMDGPU::sub1, SrcSubRC);
9618 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9637 Offset == 0 &&
"Not implemented");
9660 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9670 .
addReg(Src.getReg(), {}, AMDGPU::sub0);
9673 .
addReg(Src.getReg(), {}, AMDGPU::sub0)
9679 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9698 const MCInstrDesc &InstDesc =
get(Opcode);
9700 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9703 Src.isReg() ? MRI.
getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9705 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9707 MachineOperand SrcRegSub0 =
9709 MachineOperand SrcRegSub1 =
9723 .
addReg(IsCtlz ? MidReg1 : MidReg2);
9727 .
addReg(IsCtlz ? MidReg2 : MidReg1);
9731 addUsersToMoveToVALUWorklist(MidReg4, MRI, Worklist);
9734void SIInstrInfo::addUsersToMoveToVALUWorklist(
9738 MachineInstr &
UseMI = *MO.getParent();
9742 switch (
UseMI.getOpcode()) {
9745 case AMDGPU::SOFT_WQM:
9746 case AMDGPU::STRICT_WWM:
9747 case AMDGPU::STRICT_WQM:
9748 case AMDGPU::REG_SEQUENCE:
9750 case AMDGPU::INSERT_SUBREG:
9753 OpNo = MO.getOperandNo();
9760 if (!RI.hasVectorRegisters(OpRC))
9777 if (ST.useRealTrue16Insts()) {
9779 if (!Src0.
isReg() || !RI.isVGPR(MRI, Src0.
getReg())) {
9782 get(Src0.
isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
9788 if (!Src1.
isReg() || !RI.isVGPR(MRI, Src1.
getReg())) {
9791 get(Src1.
isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
9800 auto NewMI =
BuildMI(*
MBB, Inst,
DL,
get(AMDGPU::REG_SEQUENCE), ResultReg);
9802 case AMDGPU::S_PACK_LL_B32_B16:
9804 .addReg(SrcReg0, {},
9805 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9806 .addImm(AMDGPU::lo16)
9807 .addReg(SrcReg1, {},
9808 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9809 .addImm(AMDGPU::hi16);
9811 case AMDGPU::S_PACK_LH_B32_B16:
9813 .addReg(SrcReg0, {},
9814 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9815 .addImm(AMDGPU::lo16)
9816 .addReg(SrcReg1, {}, AMDGPU::hi16)
9817 .addImm(AMDGPU::hi16);
9819 case AMDGPU::S_PACK_HL_B32_B16:
9820 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9821 .addImm(AMDGPU::lo16)
9822 .addReg(SrcReg1, {},
9823 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
9824 .addImm(AMDGPU::hi16);
9826 case AMDGPU::S_PACK_HH_B32_B16:
9827 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
9828 .addImm(AMDGPU::lo16)
9829 .addReg(SrcReg1, {}, AMDGPU::hi16)
9830 .addImm(AMDGPU::hi16);
9838 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9843 case AMDGPU::S_PACK_LL_B32_B16: {
9862 case AMDGPU::S_PACK_LH_B32_B16: {
9872 case AMDGPU::S_PACK_HL_B32_B16: {
9883 case AMDGPU::S_PACK_HH_B32_B16: {
9903 addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
9912 assert(
Op.isReg() &&
Op.getReg() == AMDGPU::SCC &&
Op.isDef() &&
9913 !
Op.isDead() &&
Op.getParent() == &SCCDefInst);
9914 SmallVector<MachineInstr *, 4> CopyToDelete;
9917 for (MachineInstr &
MI :
9921 int SCCIdx =
MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI,
false);
9925 Register DestReg =
MI.getOperand(0).getReg();
9932 MI.getOperand(SCCIdx).setReg(NewCond);
9938 if (
MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) != -1)
9941 for (
auto &Copy : CopyToDelete)
9942 Copy->eraseFromParent();
9950void SIInstrInfo::addSCCDefsToVALUWorklist(
MachineInstr *SCCUseInst,
9956 for (MachineInstr &
MI :
9959 if (
MI.modifiesRegister(AMDGPU::VCC, &RI))
9961 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
9978 case AMDGPU::REG_SEQUENCE:
9979 case AMDGPU::INSERT_SUBREG:
9981 case AMDGPU::SOFT_WQM:
9982 case AMDGPU::STRICT_WWM:
9983 case AMDGPU::STRICT_WQM: {
9985 if (RI.isAGPRClass(SrcRC)) {
9986 if (RI.isAGPRClass(NewDstRC))
9991 case AMDGPU::REG_SEQUENCE:
9992 case AMDGPU::INSERT_SUBREG:
9993 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
9996 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10002 if (!RI.isSGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
10005 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10019 int OpIndices[3])
const {
10020 const MCInstrDesc &
Desc =
MI.getDesc();
10038 for (
unsigned i = 0; i < 3; ++i) {
10039 int Idx = OpIndices[i];
10043 const MachineOperand &MO =
MI.getOperand(Idx);
10050 RI.getRegClass(getOpRegClassID(
Desc.operands()[Idx]));
10051 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
10052 if (IsRequiredSGPR)
10058 if (RI.isSGPRClass(RegRC))
10059 UsedSGPRs[i] =
Reg;
10075 if (UsedSGPRs[0]) {
10076 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
10077 SGPRReg = UsedSGPRs[0];
10080 if (!SGPRReg && UsedSGPRs[1]) {
10081 if (UsedSGPRs[1] == UsedSGPRs[2])
10082 SGPRReg = UsedSGPRs[1];
10089 AMDGPU::OpName OperandName)
const {
10090 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
10093 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OperandName);
10097 return &
MI.getOperand(Idx);
10111 if (ST.isAmdHsaOS()) {
10114 RsrcDataFormat |= (1ULL << 56);
10119 RsrcDataFormat |= (2ULL << 59);
10122 return RsrcDataFormat;
10132 uint64_t EltSizeValue =
Log2_32(ST.getMaxPrivateElementSize(
true)) - 1;
10137 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
10144 Rsrc23 &=
~AMDGPU::RSRC_DATA_FORMAT;
10150 unsigned Opc =
MI.getOpcode();
10156 return get(
Opc).mayLoad() &&
10163 if (!Addr || !Addr->
isFI())
10172 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::vdata);
10174 return MI.getOperand(VDataIdx).getReg();
10184 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::data);
10186 return MI.getOperand(DataIdx).getReg();
10207 if (!
MI.mayStore())
10220 unsigned Opc =
MI.getOpcode();
10222 unsigned DescSize =
Desc.getSize();
10227 unsigned Size = DescSize;
10231 if (
MI.isBranch() && ST.hasOffset3fBug())
10242 bool HasLiteral =
false;
10243 unsigned LiteralSize = 4;
10244 for (
int I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I) {
10249 if (ST.has64BitLiterals()) {
10250 switch (OpInfo.OperandType) {
10275 return HasLiteral ? DescSize + LiteralSize : DescSize;
10280 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
10284 int RSrcIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::srsrc);
10285 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10289 case TargetOpcode::BUNDLE:
10290 return getInstBundleSize(
MI);
10291 case TargetOpcode::INLINEASM:
10292 case TargetOpcode::INLINEASM_BR: {
10294 const char *AsmStr =
MI.getOperand(0).getSymbolName();
10298 if (
MI.isMetaInstruction())
10302 const auto *D16Info = AMDGPU::getT16D16Helper(
Opc);
10305 unsigned LoInstOpcode = D16Info->LoOp;
10307 DescSize =
Desc.getSize();
10311 if (
Opc == AMDGPU::V_FMA_MIX_F16_t16 ||
Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10314 DescSize =
Desc.getSize();
10323 if (
MI.isBranch() && ST.hasOffset3fBug())
10324 return InstSizeVerifyMode::NoVerify;
10325 return InstSizeVerifyMode::ExactSize;
10332 if (
MI.memoperands_empty())
10344 static const std::pair<int, const char *> TargetIndices[] = {
10384std::pair<unsigned, unsigned>
10391 static const std::pair<unsigned, const char *> TargetFlags[] = {
10409 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10425 return AMDGPU::WWM_COPY;
10427 return AMDGPU::COPY;
10444 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10448 if (RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg)))
10449 return IsLRSplitInst;
10462 bool IsNullOrVectorRegister =
true;
10466 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg));
10469 return IsNullOrVectorRegister &&
10471 (!
MI.isTerminator() &&
MI.getOpcode() != AMDGPU::COPY &&
10472 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10480 if (ST.hasAddNoCarryInsts())
10496 if (ST.hasAddNoCarryInsts())
10500 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10502 : RS.scavengeRegisterBackwards(
10503 *RI.getBoolRC(),
I,
false,
10516 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10517 case AMDGPU::SI_KILL_I1_TERMINATOR:
10526 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10527 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10528 case AMDGPU::SI_KILL_I1_PSEUDO:
10529 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10541 const unsigned OffsetBits =
10543 return (1 << OffsetBits) - 1;
10547 if (!ST.isWave32())
10550 if (
MI.isInlineAsm())
10553 if (
MI.getNumOperands() <
MI.getDesc().getNumOperands())
10556 for (
auto &
Op :
MI.implicit_operands()) {
10557 if (
Op.isReg() &&
Op.getReg() == AMDGPU::VCC)
10558 Op.setReg(AMDGPU::VCC_LO);
10567 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::sbase);
10571 const int16_t RCID = getOpRegClassID(
MI.getDesc().operands()[Idx]);
10572 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10588 if (
Imm > MaxImm) {
10589 if (
Imm <= MaxImm + 64) {
10591 Overflow =
Imm - MaxImm;
10606 Overflow =
High - Alignment.value();
10610 if (Overflow > 0) {
10618 if (ST.hasRestrictedSOffset())
10623 SOffset = Overflow;
10661 if (!ST.hasFlatInstOffsets())
10665 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10670 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10671 FlatVariant == FlatAddrSpace::FlatScratch &&
Offset < 0 &&
10682std::pair<int64_t, int64_t>
10685 int64_t RemainderOffset = COffsetVal;
10686 int64_t ImmField = 0;
10691 if (AllowNegative) {
10693 int64_t
D = 1LL << NumBits;
10694 RemainderOffset = (COffsetVal /
D) *
D;
10695 ImmField = COffsetVal - RemainderOffset;
10697 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10699 (ImmField % 4) != 0) {
10701 RemainderOffset += ImmField % 4;
10702 ImmField -= ImmField % 4;
10704 }
else if (COffsetVal >= 0) {
10706 RemainderOffset = COffsetVal - ImmField;
10710 assert(RemainderOffset + ImmField == COffsetVal);
10711 return {ImmField, RemainderOffset};
10716 if (ST.hasNegativeScratchOffsetBug() &&
10724 switch (ST.getGeneration()) {
10753 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10754 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10755 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10756 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10757 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10758 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10759 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10760 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10767#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10768 case OPCODE##_dpp: \
10769 case OPCODE##_e32: \
10770 case OPCODE##_e64: \
10771 case OPCODE##_e64_dpp: \
10772 case OPCODE##_sdwa:
10786 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
10787 case AMDGPU::V_DIV_FIXUP_F16_gfx9_fake16_e64:
10788 case AMDGPU::V_FMA_F16_gfx9_e64:
10789 case AMDGPU::V_FMA_F16_gfx9_fake16_e64:
10790 case AMDGPU::V_INTERP_P2_F16:
10791 case AMDGPU::V_MAD_F16_e64:
10792 case AMDGPU::V_MAD_U16_e64:
10793 case AMDGPU::V_MAD_I16_e64:
10802 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
10816 switch (ST.getGeneration()) {
10829 if (
isMAI(Opcode)) {
10837 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
10840 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
10847 if (ST.hasGFX90AInsts()) {
10848 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
10849 if (ST.hasGFX940Insts())
10851 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10853 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
10855 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
10861 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
10880 for (
unsigned I = 0, E = (
MI.getNumOperands() - 1)/ 2;
I < E; ++
I)
10881 if (
MI.getOperand(1 + 2 *
I + 1).getImm() == SubReg) {
10882 auto &RegOp =
MI.getOperand(1 + 2 *
I);
10894 switch (
MI.getOpcode()) {
10896 case AMDGPU::REG_SEQUENCE:
10900 case AMDGPU::INSERT_SUBREG:
10901 if (RSR.
SubReg == (
unsigned)
MI.getOperand(3).getImm())
10918 if (!
P.Reg.isVirtual())
10923 while (
auto *
MI = DefInst) {
10925 switch (
MI->getOpcode()) {
10927 case AMDGPU::V_MOV_B32_e32: {
10928 auto &Op1 =
MI->getOperand(1);
10957 auto *DefBB =
DefMI.getParent();
10961 if (
UseMI.getParent() != DefBB)
10964 const int MaxInstScan = 20;
10968 auto E =
UseMI.getIterator();
10969 for (
auto I = std::next(
DefMI.getIterator());
I != E; ++
I) {
10970 if (
I->isDebugInstr())
10973 if (++NumInst > MaxInstScan)
10976 if (
I->modifiesRegister(AMDGPU::EXEC,
TRI))
10989 auto *DefBB =
DefMI.getParent();
10991 const int MaxUseScan = 10;
10995 auto &UseInst = *
Use.getParent();
10998 if (UseInst.getParent() != DefBB || UseInst.isPHI())
11001 if (++NumUse > MaxUseScan)
11008 const int MaxInstScan = 20;
11012 for (
auto I = std::next(
DefMI.getIterator()); ; ++
I) {
11015 if (
I->isDebugInstr())
11018 if (++NumInst > MaxInstScan)
11031 if (Reg == VReg && --NumUse == 0)
11033 }
else if (
TRI->regsOverlap(Reg, AMDGPU::EXEC))
11042 auto Cur =
MBB.begin();
11043 if (Cur !=
MBB.end())
11045 if (!Cur->isPHI() && Cur->readsRegister(Dst,
nullptr))
11048 }
while (Cur !=
MBB.end() && Cur != LastPHIIt);
11057 if (InsPt !=
MBB.end() &&
11058 (InsPt->getOpcode() == AMDGPU::SI_IF ||
11059 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
11060 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
11061 InsPt->definesRegister(Src,
nullptr)) {
11065 .
addReg(Src, {}, SrcSubReg)
11108 if (isFullCopyInstr(
MI)) {
11109 Register DstReg =
MI.getOperand(0).getReg();
11110 Register SrcReg =
MI.getOperand(1).getReg();
11132 unsigned *PredCost)
const {
11133 if (
MI.isBundle()) {
11136 unsigned Lat = 0,
Count = 0;
11137 for (++
I;
I != E &&
I->isBundledWithPred(); ++
I) {
11139 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*
I));
11141 return Lat +
Count - 1;
11144 return SchedModel.computeInstrLatency(&
MI);
11151 return *CallAddrOp;
11158 unsigned Opcode =
MI.getOpcode();
11160 auto HandleAddrSpaceCast = [
this, &MRI](
const MachineInstr &
MI) {
11166 unsigned SrcAS = SrcTy.getAddressSpace();
11169 ST.hasGloballyAddressableScratch()
11177 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
11178 return HandleAddrSpaceCast(
MI);
11181 auto IID = GI->getIntrinsicID();
11188 case Intrinsic::amdgcn_if:
11189 case Intrinsic::amdgcn_else:
11203 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11204 Opcode == AMDGPU::G_SEXTLOAD) {
11205 if (
MI.memoperands_empty())
11209 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11210 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11218 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11219 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11220 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11226 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11229 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11237 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11238 return Formatter.get();
11246 unsigned opcode =
MI.getOpcode();
11247 if (opcode == AMDGPU::V_READLANE_B32 ||
11248 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11249 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11254 if (
MI.isInlineAsm()) {
11260 if (!RC || !RI.isSGPRClass(RC))
11265 if (isCopyInstr(
MI)) {
11269 RI.getPhysRegBaseClass(srcOp.
getReg());
11277 if (
MI.isPreISelOpcode())
11292 if (
MI.memoperands_empty())
11296 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11297 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11312 for (
unsigned I = 0, E =
MI.getNumOperands();
I != E; ++
I) {
11314 if (!
SrcOp.isReg())
11318 if (!Reg || !
SrcOp.readsReg())
11324 if (RegBank && RegBank->
getID() != AMDGPU::SGPRRegBankID)
11351 F,
"ds_ordered_count unsupported for this calling conv"));
11365 Register &SrcReg2, int64_t &CmpMask,
11366 int64_t &CmpValue)
const {
11367 if (!
MI.getOperand(0).isReg() ||
MI.getOperand(0).getSubReg())
11370 switch (
MI.getOpcode()) {
11373 case AMDGPU::S_CMP_EQ_U32:
11374 case AMDGPU::S_CMP_EQ_I32:
11375 case AMDGPU::S_CMP_LG_U32:
11376 case AMDGPU::S_CMP_LG_I32:
11377 case AMDGPU::S_CMP_LT_U32:
11378 case AMDGPU::S_CMP_LT_I32:
11379 case AMDGPU::S_CMP_GT_U32:
11380 case AMDGPU::S_CMP_GT_I32:
11381 case AMDGPU::S_CMP_LE_U32:
11382 case AMDGPU::S_CMP_LE_I32:
11383 case AMDGPU::S_CMP_GE_U32:
11384 case AMDGPU::S_CMP_GE_I32:
11385 case AMDGPU::S_CMP_EQ_U64:
11386 case AMDGPU::S_CMP_LG_U64:
11387 SrcReg =
MI.getOperand(0).getReg();
11388 if (
MI.getOperand(1).isReg()) {
11389 if (
MI.getOperand(1).getSubReg())
11391 SrcReg2 =
MI.getOperand(1).getReg();
11393 }
else if (
MI.getOperand(1).isImm()) {
11395 CmpValue =
MI.getOperand(1).getImm();
11401 case AMDGPU::S_CMPK_EQ_U32:
11402 case AMDGPU::S_CMPK_EQ_I32:
11403 case AMDGPU::S_CMPK_LG_U32:
11404 case AMDGPU::S_CMPK_LG_I32:
11405 case AMDGPU::S_CMPK_LT_U32:
11406 case AMDGPU::S_CMPK_LT_I32:
11407 case AMDGPU::S_CMPK_GT_U32:
11408 case AMDGPU::S_CMPK_GT_I32:
11409 case AMDGPU::S_CMPK_LE_U32:
11410 case AMDGPU::S_CMPK_LE_I32:
11411 case AMDGPU::S_CMPK_GE_U32:
11412 case AMDGPU::S_CMPK_GE_I32:
11413 SrcReg =
MI.getOperand(0).getReg();
11415 CmpValue =
MI.getOperand(1).getImm();
11425 if (S->isLiveIn(AMDGPU::SCC))
11434bool SIInstrInfo::invertSCCUse(
MachineInstr *SCCDef)
const {
11437 bool SCCIsDead =
false;
11440 constexpr unsigned ScanLimit = 12;
11441 unsigned Count = 0;
11442 for (MachineInstr &
MI :
11444 if (++
Count > ScanLimit)
11446 if (
MI.readsRegister(AMDGPU::SCC, &RI)) {
11447 if (
MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11448 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11449 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11450 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11455 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
11468 for (MachineInstr *
MI : InvertInstr) {
11469 if (
MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11470 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11472 }
else if (
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11473 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11474 MI->setDesc(
get(
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11475 ? AMDGPU::S_CBRANCH_SCC1
11476 : AMDGPU::S_CBRANCH_SCC0));
11489 bool NeedInversion)
const {
11490 MachineInstr *KillsSCC =
nullptr;
11495 if (
MI.modifiesRegister(AMDGPU::SCC, &RI))
11497 if (
MI.killsRegister(AMDGPU::SCC, &RI))
11500 if (NeedInversion && !invertSCCUse(SCCRedefine))
11502 if (MachineOperand *SccDef =
11504 SccDef->setIsDead(
false);
11512 if (Def.getOpcode() != AMDGPU::S_CSELECT_B32 &&
11513 Def.getOpcode() != AMDGPU::S_CSELECT_B64)
11515 bool Op1IsNonZeroImm =
11516 Def.getOperand(1).isImm() && Def.getOperand(1).getImm() != 0;
11517 bool Op2IsZeroImm =
11518 Def.getOperand(2).isImm() && Def.getOperand(2).getImm() == 0;
11519 return Op1IsNonZeroImm && Op2IsZeroImm;
11523 unsigned &NewDefOpc) {
11526 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11527 Def.getOpcode() != AMDGPU::S_ADD_U32)
11533 Def.getMF()->getSubtarget().getInstrInfo());
11535 auto Imm1 =
TII->getImmOrMaterializedImm(MRI, AddSrc1);
11536 auto Imm2 =
TII->getImmOrMaterializedImm(MRI, AddSrc2);
11537 if ((!Imm1 || *Imm1 != 1) && (!Imm2 || *Imm2 != 1))
11540 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11542 Def.findRegisterDefOperand(AMDGPU::SCC,
nullptr);
11545 NewDefOpc = AMDGPU::S_ADD_U32;
11547 NeedInversion = !NeedInversion;
11552 Register SrcReg2, int64_t CmpMask,
11562 CmpValue = *ImmOpt;
11565 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue, MRI,
11566 this](
bool NeedInversion) ->
bool {
11590 unsigned NewDefOpc = Def->getOpcode();
11596 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11599 if (NewDefOpc != Def->getOpcode())
11600 Def->setDesc(
get(NewDefOpc));
11609 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11616 if (Def1 && Def1->
getOpcode() == AMDGPU::COPY && Def2 &&
11624 optimizeSCC(
Select, Def,
false);
11631 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue, MRI,
11632 this](int64_t ExpectedValue,
unsigned SrcSize,
11633 bool IsReversible,
bool IsSigned) ->
bool {
11661 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11662 Def->getOpcode() != AMDGPU::S_AND_B64)
11666 const auto isMask = [&Mask, SrcSize, MRI,
11678 SrcOp = &Def->getOperand(2);
11679 else if (isMask(&Def->getOperand(2)))
11680 SrcOp = &Def->getOperand(1);
11688 if (IsSigned && BitNo == SrcSize - 1)
11691 ExpectedValue <<= BitNo;
11693 bool IsReversedCC =
false;
11694 if (CmpValue != ExpectedValue) {
11697 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11702 Register DefReg = Def->getOperand(0).getReg();
11703 if (IsReversedCC && !MRI->hasOneNonDBGUse(DefReg))
11706 if (!optimizeSCC(Def, &CmpInstr,
false))
11709 if (!MRI->use_nodbg_empty(DefReg)) {
11717 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11718 : AMDGPU::S_BITCMP1_B32
11719 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11720 : AMDGPU::S_BITCMP1_B64;
11725 Def->eraseFromParent();
11733 case AMDGPU::S_CMP_EQ_U32:
11734 case AMDGPU::S_CMP_EQ_I32:
11735 case AMDGPU::S_CMPK_EQ_U32:
11736 case AMDGPU::S_CMPK_EQ_I32:
11737 return optimizeCmpAnd(1, 32,
true,
false) ||
11738 optimizeCmpSelect(
true);
11739 case AMDGPU::S_CMP_GE_U32:
11740 case AMDGPU::S_CMPK_GE_U32:
11741 return optimizeCmpAnd(1, 32,
false,
false);
11742 case AMDGPU::S_CMP_GE_I32:
11743 case AMDGPU::S_CMPK_GE_I32:
11744 return optimizeCmpAnd(1, 32,
false,
true);
11745 case AMDGPU::S_CMP_EQ_U64:
11746 return optimizeCmpAnd(1, 64,
true,
false);
11747 case AMDGPU::S_CMP_LG_U32:
11748 case AMDGPU::S_CMP_LG_I32:
11749 case AMDGPU::S_CMPK_LG_U32:
11750 case AMDGPU::S_CMPK_LG_I32:
11751 return optimizeCmpAnd(0, 32,
true,
false) ||
11752 optimizeCmpSelect(
false);
11753 case AMDGPU::S_CMP_GT_U32:
11754 case AMDGPU::S_CMPK_GT_U32:
11755 return optimizeCmpAnd(0, 32,
false,
false);
11756 case AMDGPU::S_CMP_GT_I32:
11757 case AMDGPU::S_CMPK_GT_I32:
11758 return optimizeCmpAnd(0, 32,
false,
true);
11759 case AMDGPU::S_CMP_LG_U64:
11760 return optimizeCmpAnd(0, 64,
true,
false) ||
11761 optimizeCmpSelect(
false);
11768 AMDGPU::OpName
OpName)
const {
11769 if (!ST.needsAlignedVGPRs())
11772 int OpNo = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
OpName);
11784 bool IsAGPR = RI.isAGPR(MRI, DataReg);
11786 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
11790 : &AMDGPU::VReg_64_Align2RegClass);
11792 .
addReg(DataReg, {},
Op.getSubReg())
11797 Op.setSubReg(AMDGPU::sub0);
11802 if (!SchedModel.hasInstrSchedModel())
11808 unsigned RepeatRate = 0;
11810 PI = SchedModel.getWriteProcResBegin(SCDesc),
11811 PE = SchedModel.getWriteProcResEnd(SCDesc);
11813 RepeatRate = std::max(RepeatRate, (
unsigned)PI->ReleaseAtCycle);
11830 if (ST.hasGFX1250Insts())
11837 unsigned Opcode =
MI.getOpcode();
11843 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
11844 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
11847 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
uint64_t getDefaultRsrcDataFormat() const
static bool isSOPP(const MachineInstr &MI)
bool mayAccessScratch(const MachineInstr &MI) const
bool isIGLP(unsigned Opcode) const
static bool isFLATScratch(const MachineInstr &MI)
bool isLegalFLATOffset(int64_t Offset, unsigned AddrSpace, AMDGPU::FlatAddrSpace FlatVariant) const
Returns if Offset is legal for the subtarget as the offset to a FLAT encoded instruction with the giv...
const MCInstrDesc & getIndirectRegWriteMovRelPseudo(unsigned VecSize, unsigned EltSize, bool IsSGPR) const
MachineInstrBuilder getAddNoCarry(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg) const
Return a partially built integer add instruction without carry.
bool mayAccessFlatAddressSpace(const MachineInstr &MI) const
bool shouldScheduleLoadsNear(SDNode *Load0, SDNode *Load1, int64_t Offset0, int64_t Offset1, unsigned NumLoads) const override
bool splitMUBUFOffset(uint32_t Imm, uint32_t &SOffset, uint32_t &ImmOffset, Align Alignment=Align(4)) const
bool isIgnorableUse(const MachineInstr &MI, unsigned OpIdx) const override
ArrayRef< std::pair< unsigned, const char * > > getSerializableDirectMachineOperandTargetFlags() const override
void moveToVALU(SIInstrWorklist &Worklist, MachineDominatorTree *MDT) const
Replace the instructions opcode with the equivalent VALU opcode.
static bool isSMRD(const MachineInstr &MI)
void restoreExec(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register Reg, SlotIndexes *Indexes=nullptr) const
void storeRegToStackSlotCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC) const
bool usesConstantBus(const MachineRegisterInfo &MRI, const MachineOperand &MO, const MCOperandInfo &OpInfo) const
Returns true if this operand uses the constant bus.
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
static unsigned getFoldableCopySrcIdx(const MachineInstr &MI)
unsigned getOpSize(uint32_t Opcode, unsigned OpNo) const
Return the size in bytes of the operand OpNo on the given.
void legalizeOperandsFLAT(MachineRegisterInfo &MRI, MachineInstr &MI) const
bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask, int64_t CmpValue, const MachineRegisterInfo *MRI) const override
static std::optional< int64_t > extractSubregFromImm(int64_t ImmVal, unsigned SubRegIndex)
Return the extracted immediate value in a subregister use from a constant materialized in a super reg...
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
static bool isMTBUF(const MachineInstr &MI)
const MCInstrDesc & getIndirectGPRIDXPseudo(unsigned VecSize, bool IsIndirectSrc) const
static bool isDGEMM(unsigned Opcode)
static bool isEXP(const MachineInstr &MI)
static bool isSALU(const MachineInstr &MI)
static bool setsSCCIfResultIsNonZero(const MachineInstr &MI)
const MIRFormatter * getMIRFormatter() const override
static bool isXcntDrain(const MachineInstr &MI)
True if MI implicitly drains XCNT.
void legalizeGenericOperand(MachineBasicBlock &InsertMBB, MachineBasicBlock::iterator I, const TargetRegisterClass *DstRC, MachineOperand &Op, MachineRegisterInfo &MRI, const DebugLoc &DL) const
MachineInstr * buildShrunkInst(MachineInstr &MI, unsigned NewOpcode) const
static bool isVOP2(const MachineInstr &MI)
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override
static bool isSDWA(const MachineInstr &MI)
const MCInstrDesc & getKillTerminatorFromPseudo(unsigned Opcode) const
void insertNoops(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned Quantity) const override
static bool isGather4(const MachineInstr &MI)
MachineInstr * getWholeWaveFunctionSetup(MachineFunction &MF) const
bool isLegalVSrcOperand(const MachineRegisterInfo &MRI, const MCOperandInfo &OpInfo, const MachineOperand &MO) const
Check if MO would be a valid operand for the given operand definition OpInfo.
static bool isDOT(const MachineInstr &MI)
std::unique_ptr< PipelinerLoopInfo > analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override
InstSizeVerifyMode getInstSizeVerifyMode(const MachineInstr &MI) const override
MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const override
bool hasModifiers(unsigned Opcode) const
Return true if this instruction has any modifiers.
bool shouldClusterMemOps(ArrayRef< const MachineOperand * > BaseOps1, int64_t Offset1, bool OffsetIsScalable1, ArrayRef< const MachineOperand * > BaseOps2, int64_t Offset2, bool OffsetIsScalable2, unsigned ClusterSize, unsigned NumBytes) const override
static bool isSWMMAC(const MachineInstr &MI)
ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *II, const ScheduleDAGMI *DAG) const override
bool isHighLatencyDef(int Opc) const override
void legalizeOpWithMove(MachineInstr &MI, unsigned OpIdx) const
Legalize the OpIndex operand of this instruction by inserting a MOV.
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
static bool isVOPC(const MachineInstr &MI)
void removeModOperands(MachineInstr &MI) const
unsigned getRepeatRate(const MachineInstr &MI) const
Get the repeat rate for a VALU instruction from the scheduling model.
unsigned getVectorRegSpillRestoreOpcode(Register Reg, const TargetRegisterClass *RC, unsigned Size, const SIMachineFunctionInfo &MFI) const
bool isLegalSingleSGPRReadInstOperand(const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN, const MachineOperand *MO=nullptr) const
Check if MO would be a legal operand for a single-SGPR-read instruction.
bool isXDL(const MachineInstr &MI) const
Register isStackAccess(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const
static bool isVIMAGE(const MachineInstr &MI)
void enforceOperandRCAlignment(MachineInstr &MI, AMDGPU::OpName OpName) const
static bool isSOP2(const MachineInstr &MI)
static bool isGWS(const MachineInstr &MI)
bool hasRAWDependency(const MachineInstr &FirstMI, const MachineInstr &SecondMI) const
bool isLegalAV64PseudoImm(uint64_t Imm) const
Check if this immediate value can be used for AV_MOV_B64_IMM_PSEUDO.
bool isNeverCoissue(MachineInstr &MI) const
static bool isBUF(const MachineInstr &MI)
bool isNonCommutableDPP(const MachineInstr &MI) const
void handleCopyToPhysHelper(SIInstrWorklist &Worklist, Register DstReg, MachineInstr &Inst, MachineRegisterInfo &MRI, DenseMap< MachineInstr *, V2PhysSCopyInfo > &WaterFalls, DenseMap< MachineInstr *, bool > &V2SPhyCopiesToErase) const
bool hasModifiersSet(const MachineInstr &MI, AMDGPU::OpName OpName) const
bool isLegalToSwap(const MachineInstr &MI, unsigned fromIdx, unsigned toIdx) const
static bool isFLATGlobal(const MachineInstr &MI)
MachineInstr * foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, ArrayRef< unsigned > Ops, int FrameIndex, MachineInstr *&CopyMI, LiveIntervals *LIS=nullptr, VirtRegMap *VRM=nullptr) const override
bool isGlobalMemoryObject(const MachineInstr *MI) const override
static bool isVSAMPLE(const MachineInstr &MI)
bool isBufferSMRD(const MachineInstr &MI) const
static bool isKillTerminator(unsigned Opcode)
bool isVOPDAntidependencyAllowed(const MachineInstr &MI) const
If OpX is multicycle, anti-dependencies are not allowed.
bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx0, unsigned &SrcOpIdx1) const override
void insertScratchExecCopy(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register Reg, bool IsSCCLive, SlotIndexes *Indexes=nullptr) const
bool hasVALU32BitEncoding(unsigned Opcode) const
Return true if this 64-bit VALU instruction has a 32-bit encoding.
unsigned getMovOpcode(const TargetRegisterClass *DstRC) const
Register isSGPRStackAccess(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const
unsigned buildExtractSubReg(MachineBasicBlock::iterator MI, MachineRegisterInfo &MRI, const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC, unsigned SubIdx, const TargetRegisterClass *SubRC) const
void legalizeOperandsVOP2(MachineRegisterInfo &MRI, MachineInstr &MI) const
Legalize operands in MI by either commuting it or inserting a copy of src1.
static bool isVALU(const MachineInstr &MI, bool AllowLDSDMA)
bool foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, Register Reg, MachineRegisterInfo *MRI) const final
static bool isTRANS(const MachineInstr &MI)
static bool isImage(const MachineInstr &MI)
static bool isSOPK(const MachineInstr &MI)
const TargetRegisterClass * getOpRegClass(const MachineInstr &MI, unsigned OpNo) const
Return the correct register class for OpNo.
MachineBasicBlock * insertSimulatedTrap(MachineRegisterInfo &MRI, MachineBasicBlock &MBB, MachineInstr &MI, const DebugLoc &DL) const
Build instructions that simulate the behavior of a s_trap 2 instructions for hardware (namely,...
static unsigned getNonSoftWaitcntOpcode(unsigned Opcode)
static unsigned getDSShaderTypeValue(const MachineFunction &MF)
static bool isFoldableCopy(const MachineInstr &MI)
static bool isMUBUF(const MachineInstr &MI)
bool expandPostRAPseudo(MachineInstr &MI) const override
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &CmpMask, int64_t &CmpValue) const override
void createWaterFallForSiCall(MachineInstr *MI, MachineDominatorTree *MDT, ArrayRef< MachineOperand * > ScalarOps, ArrayRef< Register > PhySGPRs={}) const
Wrapper function for generating waterfall for instruction MI This function take into consideration of...
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, unsigned SubReg=0, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
static bool isSegmentSpecificFLAT(const MachineInstr &MI)
bool isReMaterializableImpl(const MachineInstr &MI) const override
static bool isVOP3(const MCInstrDesc &Desc)
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
bool physRegUsesConstantBus(const MachineOperand &Reg) const
void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DstReg, ArrayRef< MachineOperand > Cond, Register TrueReg, Register FalseReg) const override
bool mayAccessVMEMThroughFlat(const MachineInstr &MI) const
static bool isDPP(const MachineInstr &MI)
bool analyzeBranchImpl(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const
static bool isMFMA(const MachineInstr &MI)
bool isLowLatencyInstruction(const MachineInstr &MI) const
std::optional< DestSourcePair > isCopyInstrImpl(const MachineInstr &MI) const override
If the specific machine instruction is a instruction that moves/copies value from one register to ano...
void mutateAndCleanupImplicit(MachineInstr &MI, const MCInstrDesc &NewDesc) const
ValueUniformity getGenericValueUniformity(const MachineInstr &MI) const
static bool isMAI(const MCInstrDesc &Desc)
static bool isSrc1DPPRevOpcode(const GCNSubtarget &ST, uint32_t Opcode)
void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig, LaneBitmask UsedLanes=LaneBitmask::getAll()) const override
static bool usesLGKM_CNT(const MachineInstr &MI)
void legalizeOperandsVALUt16(MachineInstr &Inst, MachineRegisterInfo &MRI) const
Fix operands in Inst to fix 16bit SALU to VALU lowering.
bool isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo, const MachineOperand &MO) const
bool canShrink(const MachineInstr &MI, const MachineRegisterInfo &MRI) const
const MachineOperand & getCalleeOperand(const MachineInstr &MI) const override
bool isAsmOnlyOpcode(int MCOp) const
Check if this instruction should only be used by assembler.
bool isAlwaysGDS(uint32_t Opcode) const
static bool isVGPRSpill(const MachineInstr &MI)
ScheduleHazardRecognizer * CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II, const ScheduleDAG *DAG) const override
This is used by the post-RA scheduler (SchedulePostRAList.cpp).
bool verifyInstruction(const MachineInstr &MI, StringRef &ErrInfo) const override
unsigned getInstrLatency(const InstrItineraryData *ItinData, const MachineInstr &MI, unsigned *PredCost=nullptr) const override
unsigned getVectorRegSpillSaveOpcode(Register Reg, const TargetRegisterClass *RC, unsigned Size, const SIMachineFunctionInfo &MFI, bool NeedsCFI) const
int64_t getNamedImmOperand(const MachineInstr &MI, AMDGPU::OpName OperandName) const
Get required immediate operand.
ArrayRef< std::pair< int, const char * > > getSerializableTargetIndices() const override
bool regUsesConstantBus(const MachineOperand &Reg, const MachineRegisterInfo &MRI) const
static bool isMIMG(const MachineInstr &MI)
MachineOperand buildExtractSubRegOrImm(MachineBasicBlock::iterator MI, MachineRegisterInfo &MRI, const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC, unsigned SubIdx, const TargetRegisterClass *SubRC) const
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
bool isLegalRegOperand(const MachineRegisterInfo &MRI, const MCOperandInfo &OpInfo, const MachineOperand &MO) const
Check if MO (a register operand) is a legal register for the given operand description or operand ind...
static unsigned getNumWaitStates(const MachineInstr &MI)
Return the number of wait states that result from executing this instruction.
unsigned getVALUOp(const MachineInstr &MI) const
static bool modifiesModeRegister(const MachineInstr &MI)
Return true if the instruction modifies the mode register.q.
Register readlaneVGPRToSGPR(Register SrcReg, MachineInstr &UseMI, MachineRegisterInfo &MRI, const TargetRegisterClass *DstRC=nullptr) const
Copy a value from a VGPR (SrcReg) to SGPR.
bool hasDivergentBranch(const MachineBasicBlock *MBB) const
Return whether the block terminate with divergent branch.
std::pair< int64_t, int64_t > splitFlatOffset(int64_t COffsetVal, unsigned AddrSpace, AMDGPU::FlatAddrSpace FlatVariant) const
Split COffsetVal into {immediate offset field, remainder offset} values.
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
void fixImplicitOperands(MachineInstr &MI) const
bool moveFlatAddrToVGPR(MachineInstr &Inst) const
Change SADDR form of a FLAT Inst to its VADDR form if saddr operand was moved to VGPR.
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
void createReadFirstLaneFromCopyToPhysReg(MachineRegisterInfo &MRI, Register DstReg, MachineInstr &Inst) const
bool swapSourceModifiers(MachineInstr &MI, MachineOperand &Src0, AMDGPU::OpName Src0OpName, MachineOperand &Src1, AMDGPU::OpName Src1OpName) const
MachineBasicBlock * getBranchDestBlock(const MachineInstr &MI) const override
bool hasUnwantedEffectsWhenEXECEmpty(const MachineInstr &MI) const
This function is used to determine if an instruction can be safely executed under EXEC = 0 without ha...
bool getConstValDefinedInReg(const MachineInstr &MI, const Register Reg, int64_t &ImmVal) const override
static bool isAtomic(const MachineInstr &MI)
bool canInsertSelect(const MachineBasicBlock &MBB, ArrayRef< MachineOperand > Cond, Register DstReg, Register TrueReg, Register FalseReg, int &CondCycles, int &TrueCycles, int &FalseCycles) const override
bool isLiteralOperandLegal(const MCInstrDesc &InstDesc, const MCOperandInfo &OpInfo) const
static bool isWWMRegSpillOpcode(uint32_t Opcode)
static bool sopkIsZext(unsigned Opcode)
static bool isSGPRSpill(const MachineInstr &MI)
static bool isWMMA(const MachineInstr &MI)
ArrayRef< std::pair< MachineMemOperand::Flags, const char * > > getSerializableMachineMemOperandTargetFlags() const override
MachineInstr * convertToThreeAddress(MachineInstr &MI, LiveVariables *LV, LiveIntervals *LIS) const override
bool mayReadEXEC(const MachineRegisterInfo &MRI, const MachineInstr &MI) const
Returns true if the instruction could potentially depend on the value of exec.
void legalizeOperandsSMRD(MachineRegisterInfo &MRI, MachineInstr &MI) const
bool isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const override
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override
std::pair< MachineInstr *, MachineInstr * > expandMovDPP64(MachineInstr &MI) const
static bool isSOPC(const MachineInstr &MI)
static bool isFLAT(const MachineInstr &MI)
bool isBarrier(unsigned Opcode) const
MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx0, unsigned OpIdx1) const override
bool mayAccessLDSThroughFlat(const MachineInstr &MI, bool TgSplit) const
int pseudoToMCOpcode(int Opcode) const
Return a target-specific opcode if Opcode is a pseudo instruction.
const MCInstrDesc & getMCOpcodeFromPseudo(unsigned Opcode) const
Return the descriptor of the target-specific machine instruction that corresponds to the specified ps...
static bool usesVM_CNT(const MachineInstr &MI)
MachineInstr * createPHIDestinationCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, Register Dst) const override
static bool isFixedSize(const MachineInstr &MI)
bool isSafeToSink(MachineInstr &MI, MachineBasicBlock *SuccToSinkTo, MachineCycleInfo *CI) const override
LLVM_READONLY int commuteOpcode(unsigned Opc) const
ValueUniformity getValueUniformity(const MachineInstr &MI) const final
uint64_t getScratchRsrcWords23() const
LLVM_READONLY MachineOperand * getNamedOperand(MachineInstr &MI, AMDGPU::OpName OperandName) const
Returns the operand named Op.
std::pair< unsigned, unsigned > decomposeMachineOperandsTargetFlags(unsigned TF) const override
bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, const MachineInstr &MIb) const override
bool isOperandLegal(const MachineInstr &MI, unsigned OpIdx, const MachineOperand *MO=nullptr) const
Check if MO is a legal operand if it was the OpIdx Operand for MI.
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
bool allowNegativeFlatOffset(AMDGPU::FlatAddrSpace FlatVariant) const
Returns true if negative offsets are allowed for the given FlatVariant.
void moveToVALUImpl(SIInstrWorklist &Worklist, MachineDominatorTree *MDT, MachineInstr &Inst, DenseMap< MachineInstr *, V2PhysSCopyInfo > &WaterFalls, DenseMap< MachineInstr *, bool > &V2SPhyCopiesToErase) const
static bool isLDSDMA(const MachineInstr &MI)
static bool isVOP1(const MachineInstr &MI)
SIInstrInfo(const GCNSubtarget &ST)
std::optional< int64_t > getImmOrMaterializedImm(const MachineRegisterInfo &MRI, const MachineOperand &Op, MachineInstr **DefMI=nullptr) const
void insertIndirectBranch(MachineBasicBlock &MBB, MachineBasicBlock &NewDestBB, MachineBasicBlock &RestoreBB, const DebugLoc &DL, int64_t BrOffset, RegScavenger *RS) const override
bool hasAnyModifiersSet(const MachineInstr &MI) const
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
Register getLongBranchReservedReg() const
bool isWholeWaveFunction() const
Register getStackPtrOffsetReg() const
unsigned getMaxMemoryClusterDWords() const
void setHasSpilledVGPRs(bool Spill=true)
bool isWWMReg(Register Reg) const
bool checkFlag(Register Reg, uint8_t Flag) const
void setHasSpilledSGPRs(bool Spill=true)
unsigned getScratchReservedForDynamicVGPRs() const
static unsigned getSubRegFromChannel(unsigned Channel, unsigned NumRegs=1)
ArrayRef< int16_t > getRegSplitParts(const TargetRegisterClass *RC, unsigned EltSize) const
unsigned getHWRegIndex(MCRegister Reg) const
bool isSGPRReg(const MachineRegisterInfo &MRI, Register Reg) const
unsigned getRegPressureLimit(const TargetRegisterClass *RC, MachineFunction &MF) const override
unsigned getChannelFromSubReg(unsigned SubReg) const
static bool isSGPRClass(const TargetRegisterClass *RC)
static bool isAGPRClass(const TargetRegisterClass *RC)
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
virtual bool hasVRegLiveness() const
Return true if this DAG supports VReg liveness and RegPressure.
MachineFunction & MF
Machine function.
HazardRecognizer - This determines whether or not an instruction can be issued this cycle,...
SlotIndex - An opaque wrapper around machine indexes.
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def.
SlotIndex insertMachineInstrInMaps(MachineInstr &MI, bool Late=false)
Insert the given machine instruction into the mapping.
Implements a dense probed hash-table based set with some number of buckets stored inline.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Object returned by analyzeLoopForPipelining.
virtual ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *, const ScheduleDAGMI *DAG) const
Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...
virtual MachineInstr * createPHIDestinationCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual const MachineOperand & getCalleeOperand(const MachineInstr &MI) const
Returns the callee operand from the given MI.
virtual void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig, LaneBitmask UsedLanes=LaneBitmask::getAll()) const
Re-issue the specified 'original' instruction at the specific location targeting a new destination re...
virtual MachineInstr * createPHISourceCopy(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt, const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const
During PHI eleimination lets target to make necessary checks and insert the copy to the PHI destinati...
virtual MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const
This method commutes the operands of the given machine instruction MI.
virtual bool isGlobalMemoryObject(const MachineInstr *MI) const
Returns true if MI is an instruction we are unable to reason about (like a call or something with unm...
virtual bool expandPostRAPseudo(MachineInstr &MI) const
This function is called for all pseudo instructions that remain after register allocation.
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
const MCWriteProcResEntry * ProcResIter
static constexpr TypeSize getFixed(ScalarTy ExactSize)
A Use represents the edge between a Value definition and its users.
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ PRIVATE_ADDRESS
Address space for private memory.
unsigned encodeFieldSaSdst(unsigned Encoded, unsigned SaSdst)
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi)
const uint64_t RSRC_DATA_FORMAT
bool isPKFMACF16InlineConstant(uint32_t Literal, bool IsGFX11Plus)
LLVM_READONLY const MIMGInfo * getMIMGInfo(unsigned Opc)
bool isInlinableLiteralFP16(int16_t Literal, bool HasInv2Pi)
bool getWMMAIsXDL(unsigned Opc)
unsigned mapWMMA2AddrTo3AddrOpcode(unsigned Opc)
bool isInlinableLiteralV2I16(uint32_t Literal)
bool isDPMACCInstruction(unsigned Opc)
bool isHi16Reg(MCRegister Reg, const MCRegisterInfo &MRI)
bool isInlinableLiteralV2BF16(uint32_t Literal)
LLVM_READONLY int32_t getCommuteRev(uint32_t Opcode)
LLVM_READONLY int32_t getCommuteOrig(uint32_t Opcode)
unsigned getNumFlatOffsetBits(const MCSubtargetInfo &ST)
For pre-GFX12 FLAT instructions the offset must be positive; MSB is ignored and forced to zero.
bool isGFX12Plus(const MCSubtargetInfo &STI)
bool isInlinableLiteralV2F16(uint32_t Literal)
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
bool isValid32BitLiteral(uint64_t Val, bool IsFP64)
LLVM_READONLY int32_t getGlobalVaddrOp(uint32_t Opcode)
LLVM_READNONE bool isLegalDPALU_DPPControl(const MCSubtargetInfo &ST, unsigned DC)
LLVM_READONLY int32_t getMFMAEarlyClobberOp(uint32_t Opcode)
bool getMAIIsGFX940XDL(unsigned Opc)
const uint64_t RSRC_ELEMENT_SIZE_SHIFT
bool isIntrinsicAlwaysUniform(unsigned IntrID)
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, OpName NamedIdx)
bool isPackedSingleSGPR64BitInst(unsigned Opc)
The opcode is a packed 64-bit instruction which only reads low 64 bits of a scalar operand and propag...
LLVM_READONLY int32_t getIfAddr64Inst(uint32_t Opcode)
Check if Opcode is an Addr64 opcode.
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfoByEncoding(uint8_t DimEnc)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
const uint64_t RSRC_TID_ENABLE
LLVM_READONLY int32_t getVOPe32(uint32_t Opcode)
bool isIntrinsicSourceOfDivergence(unsigned IntrID)
constexpr bool isSISrcOperand(const MCOperandInfo &OpInfo)
Is this an AMDGPU specific source operand?
bool isGenericAtomic(unsigned Opc)
LLVM_READNONE bool isInlinableIntLiteral(int64_t Literal)
Is this literal inlinable, and not one of the values intended for floating point values.
unsigned getAddrSizeMIMGOp(const MIMGBaseOpcodeInfo *BaseOpcode, const MIMGDimInfo *Dim, bool IsA16, bool IsG16Supported)
LLVM_READONLY int32_t getAddr64Inst(uint32_t Opcode)
int32_t getMCOpcode(uint32_t Opcode, unsigned Gen)
@ OPERAND_KIMM32
Operand with 32-bit immediate that uses the constant bus.
@ OPERAND_REG_INLINE_C_FP64
@ OPERAND_REG_IMM_NOINLINE_FP16
@ OPERAND_REG_INLINE_C_BF16
@ OPERAND_REG_INLINE_C_V2BF16
@ OPERAND_REG_IMM_V2INT64
@ OPERAND_REG_IMM_V2INT16
@ OPERAND_REG_IMM_INT32
Operands with register, 32-bit, or 64-bit immediate.
@ OPERAND_REG_IMM_V2FP16_SPLAT
@ OPERAND_REG_INLINE_C_INT64
@ OPERAND_REG_INLINE_C_INT16
Operands with register or inline constant.
@ OPERAND_REG_IMM_NOINLINE_V2FP16
@ OPERAND_REG_INLINE_C_V2FP16
@ OPERAND_REG_INLINE_AC_INT32
Operands with an AccVGPR register or inline constant.
@ OPERAND_REG_INLINE_AC_FP32
@ OPERAND_REG_IMM_V2INT32
@ OPERAND_REG_INLINE_C_FP32
@ OPERAND_REG_INLINE_C_INT32
@ OPERAND_REG_INLINE_C_V2INT16
@ OPERAND_INLINE_C_AV64_PSEUDO
@ OPERAND_REG_INLINE_AC_FP64
@ OPERAND_REG_INLINE_C_FP16
@ OPERAND_INLINE_SPLIT_BARRIER_INT32
LLVM_READONLY int32_t getBasicFromSDWAOp(uint32_t Opcode)
bool isDPALU_DPP(const MCInstrDesc &OpDesc, const MCInstrInfo &MII, const MCSubtargetInfo &ST)
bool isSingleSGPRReadInst(unsigned Opc)
Packed instructions that read a single SGPR for SGPR operands, except for 64-bit elements which read ...
bool supportsScaleOffset(const MCInstrInfo &MII, unsigned Opcode)
const uint64_t RSRC_INDEX_STRIDE_SHIFT
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
LLVM_READONLY int32_t getFlatScratchInstSVfromSS(uint32_t Opcode)
bool isInlinableLiteralI16(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool isGraphics(CallingConv::ID CC)
bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi)
Is this literal inlinable.
@ AMDGPU_CS
Used for Mesa/AMDPAL compute shaders.
@ AMDGPU_VS
Used for Mesa vertex shaders, or AMDPAL last shader stage before rasterization (vertex shader if tess...
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ AMDGPU_HS
Used for Mesa/AMDPAL hull shaders (= tessellation control shaders).
@ AMDGPU_GS
Used for Mesa/AMDPAL geometry shaders.
@ AMDGPU_PS
Used for Mesa/AMDPAL pixel shaders.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ AMDGPU_ES
Used for AMDPAL shader stage before geometry shader if geometry is in use.
@ AMDGPU_LS
Used for AMDPAL vertex shader if tessellation is in use.
@ C
The default llvm calling convention, compatible with C.
Not(const Pred &P) -> Not< Pred >
constexpr bool 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.