33#include "llvm/IR/IntrinsicsAMDGPU.h"
41#define DEBUG_TYPE "si-instr-info"
43#define GET_INSTRINFO_CTOR_DTOR
44#include "AMDGPUGenInstrInfo.inc"
47#define GET_ImageDimIntrinsicTable_IMPL
48#define GET_RsrcIntrinsics_IMPL
49#define GET_GFX1250BlockingCyclesTable_DECL
50#define GET_GFX1250BlockingCyclesTable_IMPL
57#include "AMDGPUGenSearchableTables.inc"
72 unsigned N =
Node->getNumOperands();
73 while (
N &&
Node->getOperand(
N - 1).getValueType() == MVT::Glue)
85 int Op0Idx = AMDGPU::getNamedOperandIdx(Opc0,
OpName);
86 int Op1Idx = AMDGPU::getNamedOperandIdx(Opc1,
OpName);
88 if (Op0Idx == -1 && Op1Idx == -1)
92 if ((Op0Idx == -1 && Op1Idx != -1) ||
93 (Op1Idx == -1 && Op0Idx != -1))
114 return !
MI.memoperands_empty() &&
116 return MMO->isLoad() && MMO->isInvariant();
125static std::pair<unsigned, unsigned>
127 const unsigned Flags =
SrcOp.getTargetFlags();
135 const unsigned GotFlags =
137 return {GotFlags, GotFlags};
143 std::optional<unsigned> LoFlags =
145 std::optional<unsigned> HiFlags =
147 if (!LoFlags || !HiFlags)
149 return {*LoFlags, *HiFlags};
167 if (!
MI.hasImplicitDef() &&
168 MI.getNumImplicitOperands() ==
MI.getDesc().implicit_uses().size() &&
169 !
MI.mayRaiseFPException())
178 if (!
MI.getNumOperands() || !
MI.getOperand(0).isReg())
193 if (
MI.isNotDuplicable() ||
MI.mayStore() ||
MI.mayRaiseFPException() ||
194 MI.hasUnmodeledSideEffects())
199 if (
MI.isInlineAsm())
203 if (
MI.mayLoad() && !
MI.isDereferenceableInvariantLoad())
218 if (Reg.isPhysical()) {
223 if (!
MRI.isConstantPhysReg(Reg))
234 if (MO.isDef() && Reg != DefReg)
244 case AMDGPU::V_SUBREV_U16_e32:
245 case AMDGPU::V_SUBREV_U16_e64:
247 case AMDGPU::V_SUBREV_U32_e32:
248 case AMDGPU::V_SUBREV_U32_e64:
250 case AMDGPU::V_SUBREV_CO_U32_e32:
251 case AMDGPU::V_SUBREV_CO_U32_e64:
253 case AMDGPU::V_SUBBREV_U32_e32:
254 case AMDGPU::V_SUBBREV_U32_e64:
257 case AMDGPU::V_ASHRREV_I16_e32:
258 case AMDGPU::V_ASHRREV_I16_e64:
259 case AMDGPU::V_ASHRREV_I32_e32:
260 case AMDGPU::V_ASHRREV_I32_e64:
261 case AMDGPU::V_ASHRREV_I64_e64:
262 case AMDGPU::V_LSHLREV_B16_e32:
263 case AMDGPU::V_LSHLREV_B16_e64:
264 case AMDGPU::V_LSHLREV_B32_e32:
265 case AMDGPU::V_LSHLREV_B32_e64:
266 case AMDGPU::V_LSHLREV_B64_e64:
267 case AMDGPU::V_LSHRREV_B16_e32:
268 case AMDGPU::V_LSHRREV_B16_e64:
269 case AMDGPU::V_LSHRREV_B32_e32:
270 case AMDGPU::V_LSHRREV_B32_e64:
271 case AMDGPU::V_LSHRREV_B64_e64:
272 return !ST.hasGFX11Insts();
279bool SIInstrInfo::resultDependsOnExec(
const MachineInstr &
MI)
const {
283 if (
MI.isConvergent())
311 if (
MI.getOpcode() == AMDGPU::SI_IF_BREAK)
316 for (
auto Op :
MI.uses()) {
317 if (
Op.isReg() &&
Op.getReg().isVirtual() &&
318 RI.isSGPRClass(
MRI.getRegClass(
Op.getReg()))) {
331 while (FromCycle && !(ToCycle && CI->
contains(FromCycle, ToCycle))) {
351 int64_t &Offset1)
const {
359 if (!
get(Opc0).mayLoad() || !
get(Opc1).mayLoad())
363 if (!
get(Opc0).getNumDefs() || !
get(Opc1).getNumDefs())
379 int Offset0Idx = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
380 int Offset1Idx = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
381 if (Offset0Idx == -1 || Offset1Idx == -1)
388 Offset0Idx -=
get(Opc0).NumDefs;
389 Offset1Idx -=
get(Opc1).NumDefs;
419 if (!Load0Offset || !Load1Offset)
436 int OffIdx0 = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
437 int OffIdx1 = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
439 if (OffIdx0 == -1 || OffIdx1 == -1)
445 OffIdx0 -=
get(Opc0).NumDefs;
446 OffIdx1 -=
get(Opc1).NumDefs;
465 case AMDGPU::DS_READ2ST64_B32:
466 case AMDGPU::DS_READ2ST64_B64:
467 case AMDGPU::DS_WRITE2ST64_B32:
468 case AMDGPU::DS_WRITE2ST64_B64:
482 OffsetIsScalable =
false;
499 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
501 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
502 if (
Opc == AMDGPU::DS_ATOMIC_ASYNC_BARRIER_ARRIVE_B64)
515 unsigned Offset0 = Offset0Op->
getImm() & 0xff;
516 unsigned Offset1 = Offset1Op->
getImm() & 0xff;
517 if (Offset0 + 1 != Offset1)
528 int Data0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
529 EltSize = RI.getRegSizeInBits(*
getOpRegClass(LdSt, Data0Idx)) / 8;
536 Offset = EltSize * Offset0;
538 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
539 if (DataOpIdx == -1) {
540 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
542 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
558 if (BaseOp && !BaseOp->
isFI())
566 if (SOffset->
isReg())
572 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
574 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
583 isMIMG(LdSt) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
584 int SRsrcIdx = AMDGPU::getNamedOperandIdx(
Opc, RsrcOpName);
586 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
587 if (VAddr0Idx >= 0) {
589 for (
int I = VAddr0Idx;
I < SRsrcIdx; ++
I)
596 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
611 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::sdst);
628 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
630 DataOpIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdata);
647 if (BaseOps1.
front()->isIdenticalTo(*BaseOps2.
front()))
655 if (MO1->getAddrSpace() != MO2->getAddrSpace())
658 const auto *Base1 = MO1->getValue();
659 const auto *Base2 = MO2->getValue();
660 if (!Base1 || !Base2)
668 return Base1 == Base2;
679 *BaseOps2.
front()->getParent(), BaseOps2);
683 int64_t Offset1,
bool OffsetIsScalable1,
685 int64_t Offset2,
bool OffsetIsScalable2,
686 unsigned ClusterSize,
687 unsigned NumBytes)
const {
697 if (!BaseOps1.
empty()) {
699 MaxMemoryClusterDWords =
717 const unsigned LoadSize = NumBytes / ClusterSize;
718 const unsigned NumDWords = ((LoadSize + 3) / 4) * ClusterSize;
719 return NumDWords <= MaxMemoryClusterDWords;
733 int64_t Offset0, int64_t Offset1,
734 unsigned NumLoads)
const {
735 assert(Offset1 > Offset0 &&
736 "Second offset should be larger than first offset!");
741 return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
748 const char *
Msg =
"illegal VGPR to SGPR copy") {
767 assert((
TII.getSubtarget().hasMAIInsts() &&
768 !
TII.getSubtarget().hasGFX90AInsts()) &&
769 "Expected GFX908 subtarget.");
772 AMDGPU::AGPR_32RegClass.
contains(SrcReg)) &&
773 "Source register of the copy should be either an SGPR or an AGPR.");
776 "Destination register of the copy should be an AGPR.");
785 for (
auto Def =
MI,
E =
MBB.begin(); Def !=
E; ) {
788 if (!Def->modifiesRegister(SrcReg, &RI))
791 if (Def->getOpcode() != AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
792 Def->getOperand(0).getReg() != SrcReg)
799 bool SafeToPropagate =
true;
802 for (
auto I = Def;
I !=
MI && SafeToPropagate; ++
I)
803 if (
I->modifiesRegister(DefOp.
getReg(), &RI))
804 SafeToPropagate =
false;
806 if (!SafeToPropagate)
809 for (
auto I = Def;
I !=
MI; ++
I)
810 I->clearRegisterKills(DefOp.
getReg(), &RI);
818 if (ImpUseSuperReg) {
819 Builder.addReg(ImpUseSuperReg,
827 RS.enterBasicBlockEnd(
MBB);
828 RS.backward(std::next(
MI));
837 unsigned RegNo = (DestReg - AMDGPU::AGPR0) % 3;
840 assert(
MBB.getParent()->getRegInfo().isReserved(Tmp) &&
841 "VGPR used for an intermediate copy should have been reserved.");
846 Register Tmp2 = RS.scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass,
MI,
856 unsigned TmpCopyOp = AMDGPU::V_MOV_B32_e32;
857 if (AMDGPU::AGPR_32RegClass.
contains(SrcReg)) {
858 TmpCopyOp = AMDGPU::V_ACCVGPR_READ_B32_e64;
865 if (ImpUseSuperReg) {
866 UseBuilder.
addReg(ImpUseSuperReg,
883 for (
unsigned Idx = 0; Idx < BaseIndices.
size(); ++Idx) {
884 int16_t SubIdx = BaseIndices[Idx];
885 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
886 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
887 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
888 unsigned Opcode = AMDGPU::S_MOV_B32;
891 bool AlignedDest = ((DestSubReg - AMDGPU::SGPR0) % 2) == 0;
892 bool AlignedSrc = ((SrcSubReg - AMDGPU::SGPR0) % 2) == 0;
893 if (AlignedDest && AlignedSrc && (Idx + 1 < BaseIndices.
size())) {
897 DestSubReg = RI.getSubReg(DestReg, SubIdx);
898 SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
899 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
900 Opcode = AMDGPU::S_MOV_B64;
915 assert(FirstMI && LastMI);
920 LastMI->addRegisterKilled(SrcReg, &RI);
926 Register SrcReg,
bool KillSrc,
bool RenamableDest,
927 bool RenamableSrc)
const {
929 unsigned Size = RI.getRegSizeInBits(*RC);
931 unsigned SrcSize = RI.getRegSizeInBits(*SrcRC);
936 if (ST.getCLOpts().fix_16_bit_physreg_copies) {
937 if (((
Size == 16) != (SrcSize == 16))) {
939 assert(ST.useRealTrue16Insts());
941 MCRegister SubReg = RI.getSubReg(RegToFix, AMDGPU::lo16);
944 if (DestReg == SrcReg) {
950 RC = RI.getPhysRegBaseClass(DestReg);
951 Size = RI.getRegSizeInBits(*RC);
952 SrcRC = RI.getPhysRegBaseClass(SrcReg);
953 SrcSize = RI.getRegSizeInBits(*SrcRC);
957 if (RC == &AMDGPU::VGPR_32RegClass) {
959 AMDGPU::SReg_32RegClass.
contains(SrcReg) ||
960 AMDGPU::AGPR_32RegClass.
contains(SrcReg));
961 unsigned Opc = AMDGPU::AGPR_32RegClass.contains(SrcReg) ?
962 AMDGPU::V_ACCVGPR_READ_B32_e64 : AMDGPU::V_MOV_B32_e32;
968 if (RC == &AMDGPU::SReg_32_XM0RegClass ||
969 RC == &AMDGPU::SReg_32RegClass) {
970 if (SrcReg == AMDGPU::SCC) {
977 if (!AMDGPU::SReg_32RegClass.
contains(SrcReg)) {
978 if (DestReg == AMDGPU::VCC_LO) {
996 if (RC == &AMDGPU::SReg_64RegClass) {
997 if (SrcReg == AMDGPU::SCC) {
1004 if (!AMDGPU::SReg_64_EncodableRegClass.
contains(SrcReg)) {
1005 if (DestReg == AMDGPU::VCC) {
1023 if (DestReg == AMDGPU::SCC) {
1026 if (AMDGPU::SReg_64RegClass.
contains(SrcReg)) {
1030 assert(ST.hasScalarCompareEq64());
1044 if (RC == &AMDGPU::AGPR_32RegClass) {
1045 if (AMDGPU::VGPR_32RegClass.
contains(SrcReg) ||
1046 (ST.hasGFX90AInsts() && AMDGPU::SReg_32RegClass.contains(SrcReg))) {
1052 if (AMDGPU::AGPR_32RegClass.
contains(SrcReg) && ST.hasGFX90AInsts()) {
1061 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1068 AMDGPU::SReg_LO16RegClass.
contains(SrcReg) ||
1069 AMDGPU::AGPR_LO16RegClass.
contains(SrcReg));
1071 bool IsSGPRDst = AMDGPU::SReg_LO16RegClass.contains(DestReg);
1072 bool IsSGPRSrc = AMDGPU::SReg_LO16RegClass.contains(SrcReg);
1073 bool IsAGPRDst = AMDGPU::AGPR_LO16RegClass.contains(DestReg);
1074 bool IsAGPRSrc = AMDGPU::AGPR_LO16RegClass.contains(SrcReg);
1077 MCRegister NewDestReg = RI.get32BitRegister(DestReg);
1078 MCRegister NewSrcReg = RI.get32BitRegister(SrcReg);
1091 if (IsAGPRDst || IsAGPRSrc) {
1092 if (!DstLow || !SrcLow) {
1094 "Cannot use hi16 subreg with an AGPR!");
1101 if (ST.useRealTrue16Insts()) {
1107 if (AMDGPU::VGPR_16_Lo128RegClass.
contains(DestReg) &&
1108 (IsSGPRSrc || AMDGPU::VGPR_16_Lo128RegClass.
contains(SrcReg))) {
1120 if (IsSGPRSrc && !ST.hasSDWAScalar()) {
1121 if (!DstLow || !SrcLow) {
1123 "Cannot use hi16 subreg on VI!");
1149 unsigned SrcOp = 1) {
1153 return DstOpRC && SrcOpRC && DstOpRC->
contains(Dst) &&
1157 if (RC == RI.getVGPR64Class() && (SrcRC == RC || RI.isSGPRClass(SrcRC))) {
1158 if (ST.hasVMovB64Inst() &&
1159 CanCopyWith(AMDGPU::V_MOV_B64_e32, DestReg, SrcReg)) {
1164 if (ST.hasPkMovB32() &&
1165 CanCopyWith(AMDGPU::V_PK_MOV_B32, DestReg, SrcReg, 2)) {
1181 const bool Forward = RI.getHWRegIndex(DestReg) <= RI.getHWRegIndex(SrcReg);
1182 if (RI.isSGPRClass(RC)) {
1183 if (!RI.isSGPRClass(SrcRC)) {
1187 const bool CanKillSuperReg = KillSrc && !RI.regsOverlap(SrcReg, DestReg);
1193 unsigned Opcode = AMDGPU::V_MOV_B32_e32;
1194 unsigned WideOpcode = AMDGPU::INSTRUCTION_LIST_END;
1195 if (RI.isAGPRClass(RC)) {
1196 if (ST.hasGFX90AInsts() && RI.isAGPRClass(SrcRC))
1197 Opcode = AMDGPU::V_ACCVGPR_MOV_B32;
1198 else if (RI.hasVGPRs(SrcRC) ||
1199 (ST.hasGFX90AInsts() && RI.isSGPRClass(SrcRC)))
1200 Opcode = AMDGPU::V_ACCVGPR_WRITE_B32_e64;
1202 Opcode = AMDGPU::INSTRUCTION_LIST_END;
1203 }
else if (RI.hasVGPRs(RC) && RI.isAGPRClass(SrcRC)) {
1204 Opcode = AMDGPU::V_ACCVGPR_READ_B32_e64;
1205 }
else if (RI.isVGPRClass(RC)) {
1206 if (ST.hasVMovB64Inst())
1207 WideOpcode = AMDGPU::V_MOV_B64_e32;
1208 else if (ST.hasPkMovB32())
1209 WideOpcode = AMDGPU::V_PK_MOV_B32;
1213 if (WideOpcode != AMDGPU::INSTRUCTION_LIST_END) {
1215 unsigned SrcOp = WideOpcode == AMDGPU::V_PK_MOV_B32 ? 2 : 1;
1222 const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
1223 const bool CanKillSuperReg = KillSrc && !Overlap;
1230 std::unique_ptr<RegScavenger> RS;
1231 if (Opcode == AMDGPU::INSTRUCTION_LIST_END)
1232 RS = std::make_unique<RegScavenger>();
1236 for (
unsigned Idx{}; Idx < SubIndices.
size();) {
1237 unsigned NumRegs = 1;
1238 unsigned ThisOpcode = Opcode;
1240 Forward ? SubIndices[Idx] : SubIndices[SubIndices.
size() - Idx - 1];
1242 if (WideDstRC && WideSrcRC && Idx + 1 < SubIndices.
size()) {
1243 unsigned Channel = RI.getChannelFromSubReg(SubIdx);
1247 unsigned WideSubIdx = RI.getSubRegFromChannel(Channel, 2);
1248 Register WideDst = RI.getSubReg(DestReg, WideSubIdx);
1249 Register WideSrc = RI.getSubReg(SrcReg, WideSubIdx);
1251 if (WideDst && WideSrc && WideDstRC->
contains(WideDst) &&
1252 WideSrcRC->contains(WideSrc)) {
1253 SubIdx = WideSubIdx;
1255 ThisOpcode = WideOpcode;
1259 Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
1260 Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
1261 assert(DestSubReg && SrcSubReg &&
"Failed to find subregs!");
1264 bool UseKill = CanKillSuperReg && Idx == SubIndices.
size();
1266 if (ThisOpcode == AMDGPU::INSTRUCTION_LIST_END) {
1269 *RS, Overlap, ImpUseSuper);
1270 }
else if (ThisOpcode == AMDGPU::V_PK_MOV_B32) {
1311 int64_t &ImmVal)
const {
1312 switch (
MI.getOpcode()) {
1313 case AMDGPU::V_MOV_B32_e32:
1314 case AMDGPU::S_MOV_B32:
1315 case AMDGPU::S_MOVK_I32:
1316 case AMDGPU::S_MOV_B64:
1317 case AMDGPU::V_MOV_B64_e32:
1318 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
1319 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
1320 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
1321 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
1322 case AMDGPU::V_MOV_B64_PSEUDO:
1323 case AMDGPU::V_MOV_B16_t16_e32: {
1326 ImmVal = Src0.getImm();
1327 return MI.getOperand(0).getReg() == Reg;
1332 case AMDGPU::V_MOV_B16_t16_e64: {
1334 if (Src0.isImm() && !
MI.getOperand(1).getImm()) {
1335 ImmVal = Src0.getImm();
1336 return MI.getOperand(0).getReg() == Reg;
1341 case AMDGPU::S_BREV_B32:
1342 case AMDGPU::V_BFREV_B32_e32:
1343 case AMDGPU::V_BFREV_B32_e64: {
1347 return MI.getOperand(0).getReg() == Reg;
1352 case AMDGPU::S_NOT_B32:
1353 case AMDGPU::V_NOT_B32_e32:
1354 case AMDGPU::V_NOT_B32_e64: {
1357 ImmVal =
static_cast<int64_t
>(~static_cast<int32_t>(Src0.getImm()));
1358 return MI.getOperand(0).getReg() == Reg;
1368std::optional<int64_t>
1378 if (!
Op.isReg() || !
Op.getReg().isVirtual())
1379 return std::nullopt;
1381 if (Def && Def->isMoveImmediate()) {
1383 if (ImmSrc.
isImm()) {
1390 return std::nullopt;
1393std::optional<int64_t>
1402 if (RI.isAGPRClass(DstRC))
1403 return AMDGPU::COPY;
1404 if (RI.getRegSizeInBits(*DstRC) == 16) {
1407 return RI.isSGPRClass(DstRC) ? AMDGPU::COPY : AMDGPU::V_MOV_B16_t16_e64;
1409 if (RI.getRegSizeInBits(*DstRC) == 32)
1410 return RI.isSGPRClass(DstRC) ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1411 if (RI.getRegSizeInBits(*DstRC) == 64 && RI.isSGPRClass(DstRC))
1412 return AMDGPU::S_MOV_B64;
1413 if (RI.getRegSizeInBits(*DstRC) == 64 && !RI.isSGPRClass(DstRC))
1414 return AMDGPU::V_MOV_B64_PSEUDO;
1415 return AMDGPU::COPY;
1420 bool IsIndirectSrc)
const {
1421 if (IsIndirectSrc) {
1423 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1);
1425 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2);
1427 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3);
1429 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4);
1431 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5);
1433 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6);
1435 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7);
1437 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8);
1439 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9);
1441 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10);
1443 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11);
1445 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12);
1447 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16);
1448 if (VecSize <= 1024)
1449 return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32);
1455 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1);
1457 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2);
1459 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3);
1461 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4);
1463 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5);
1465 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6);
1467 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7);
1469 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8);
1471 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9);
1473 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10);
1475 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11);
1477 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12);
1479 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16);
1480 if (VecSize <= 1024)
1481 return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32);
1488 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1490 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1492 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1494 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1496 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1498 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1500 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1502 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1504 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1506 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1508 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1510 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1512 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1513 if (VecSize <= 1024)
1514 return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1521 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1;
1523 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2;
1525 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3;
1527 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4;
1529 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5;
1531 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6;
1533 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7;
1535 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8;
1537 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9;
1539 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10;
1541 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11;
1543 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12;
1545 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16;
1546 if (VecSize <= 1024)
1547 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32;
1554 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1;
1556 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2;
1558 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4;
1560 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8;
1561 if (VecSize <= 1024)
1562 return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16;
1569 bool IsSGPR)
const {
1581 assert(EltSize == 32 &&
"invalid reg indexing elt size");
1588 return NeedsCFI ? AMDGPU::SI_SPILL_S32_CFI_SAVE : AMDGPU::SI_SPILL_S32_SAVE;
1590 return NeedsCFI ? AMDGPU::SI_SPILL_S64_CFI_SAVE : AMDGPU::SI_SPILL_S64_SAVE;
1592 return NeedsCFI ? AMDGPU::SI_SPILL_S96_CFI_SAVE : AMDGPU::SI_SPILL_S96_SAVE;
1594 return NeedsCFI ? AMDGPU::SI_SPILL_S128_CFI_SAVE
1595 : AMDGPU::SI_SPILL_S128_SAVE;
1597 return NeedsCFI ? AMDGPU::SI_SPILL_S160_CFI_SAVE
1598 : AMDGPU::SI_SPILL_S160_SAVE;
1600 return NeedsCFI ? AMDGPU::SI_SPILL_S192_CFI_SAVE
1601 : AMDGPU::SI_SPILL_S192_SAVE;
1603 return NeedsCFI ? AMDGPU::SI_SPILL_S224_CFI_SAVE
1604 : AMDGPU::SI_SPILL_S224_SAVE;
1606 return AMDGPU::SI_SPILL_S256_SAVE;
1608 return AMDGPU::SI_SPILL_S288_SAVE;
1610 return AMDGPU::SI_SPILL_S320_SAVE;
1612 return AMDGPU::SI_SPILL_S352_SAVE;
1614 return AMDGPU::SI_SPILL_S384_SAVE;
1616 return NeedsCFI ? AMDGPU::SI_SPILL_S512_CFI_SAVE
1617 : AMDGPU::SI_SPILL_S512_SAVE;
1619 return NeedsCFI ? AMDGPU::SI_SPILL_S1024_CFI_SAVE
1620 : AMDGPU::SI_SPILL_S1024_SAVE;
1629 return AMDGPU::SI_SPILL_V16_SAVE;
1631 return NeedsCFI ? AMDGPU::SI_SPILL_V32_CFI_SAVE : AMDGPU::SI_SPILL_V32_SAVE;
1633 return NeedsCFI ? AMDGPU::SI_SPILL_V64_CFI_SAVE : AMDGPU::SI_SPILL_V64_SAVE;
1635 return NeedsCFI ? AMDGPU::SI_SPILL_V96_CFI_SAVE : AMDGPU::SI_SPILL_V96_SAVE;
1637 return NeedsCFI ? AMDGPU::SI_SPILL_V128_CFI_SAVE
1638 : AMDGPU::SI_SPILL_V128_SAVE;
1640 return NeedsCFI ? AMDGPU::SI_SPILL_V160_CFI_SAVE
1641 : AMDGPU::SI_SPILL_V160_SAVE;
1643 return NeedsCFI ? AMDGPU::SI_SPILL_V192_CFI_SAVE
1644 : AMDGPU::SI_SPILL_V192_SAVE;
1646 return NeedsCFI ? AMDGPU::SI_SPILL_V224_CFI_SAVE
1647 : AMDGPU::SI_SPILL_V224_SAVE;
1649 return NeedsCFI ? AMDGPU::SI_SPILL_V256_CFI_SAVE
1650 : AMDGPU::SI_SPILL_V256_SAVE;
1652 return NeedsCFI ? AMDGPU::SI_SPILL_V288_CFI_SAVE
1653 : AMDGPU::SI_SPILL_V288_SAVE;
1655 return NeedsCFI ? AMDGPU::SI_SPILL_V320_CFI_SAVE
1656 : AMDGPU::SI_SPILL_V320_SAVE;
1658 return NeedsCFI ? AMDGPU::SI_SPILL_V352_CFI_SAVE
1659 : AMDGPU::SI_SPILL_V352_SAVE;
1661 return NeedsCFI ? AMDGPU::SI_SPILL_V384_CFI_SAVE
1662 : AMDGPU::SI_SPILL_V384_SAVE;
1664 return NeedsCFI ? AMDGPU::SI_SPILL_V512_CFI_SAVE
1665 : AMDGPU::SI_SPILL_V512_SAVE;
1667 return NeedsCFI ? AMDGPU::SI_SPILL_V1024_CFI_SAVE
1668 : AMDGPU::SI_SPILL_V1024_SAVE;
1677 return NeedsCFI ? AMDGPU::SI_SPILL_AV32_CFI_SAVE
1678 : AMDGPU::SI_SPILL_AV32_SAVE;
1680 return NeedsCFI ? AMDGPU::SI_SPILL_AV64_CFI_SAVE
1681 : AMDGPU::SI_SPILL_AV64_SAVE;
1683 return NeedsCFI ? AMDGPU::SI_SPILL_AV96_CFI_SAVE
1684 : AMDGPU::SI_SPILL_AV96_SAVE;
1686 return NeedsCFI ? AMDGPU::SI_SPILL_AV128_CFI_SAVE
1687 : AMDGPU::SI_SPILL_AV128_SAVE;
1689 return NeedsCFI ? AMDGPU::SI_SPILL_AV160_CFI_SAVE
1690 : AMDGPU::SI_SPILL_AV160_SAVE;
1692 return NeedsCFI ? AMDGPU::SI_SPILL_AV192_CFI_SAVE
1693 : AMDGPU::SI_SPILL_AV192_SAVE;
1695 return NeedsCFI ? AMDGPU::SI_SPILL_AV224_CFI_SAVE
1696 : AMDGPU::SI_SPILL_AV224_SAVE;
1698 return NeedsCFI ? AMDGPU::SI_SPILL_AV256_CFI_SAVE
1699 : AMDGPU::SI_SPILL_AV256_SAVE;
1701 return AMDGPU::SI_SPILL_AV288_SAVE;
1703 return AMDGPU::SI_SPILL_AV320_SAVE;
1705 return AMDGPU::SI_SPILL_AV352_SAVE;
1707 return AMDGPU::SI_SPILL_AV384_SAVE;
1709 return NeedsCFI ? AMDGPU::SI_SPILL_AV512_CFI_SAVE
1710 : AMDGPU::SI_SPILL_AV512_SAVE;
1712 return NeedsCFI ? AMDGPU::SI_SPILL_AV1024_CFI_SAVE
1713 : AMDGPU::SI_SPILL_AV1024_SAVE;
1720 bool IsVectorSuperClass) {
1725 if (IsVectorSuperClass)
1726 return AMDGPU::SI_SPILL_WWM_AV32_SAVE;
1728 return AMDGPU::SI_SPILL_WWM_V32_SAVE;
1734 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1741 if (ST.hasMAIInsts())
1747void SIInstrInfo::storeRegToStackSlotImpl(
1760 FrameInfo.getObjectAlign(FrameIndex));
1761 unsigned SpillSize = RI.getSpillSize(*RC);
1767 assert(SrcReg != AMDGPU::M0 &&
"m0 should not be spilled");
1768 assert(SrcReg != AMDGPU::EXEC_LO && SrcReg != AMDGPU::EXEC_HI &&
1769 SrcReg != AMDGPU::EXEC &&
"exec should not be spilled");
1778 if (SrcReg.
isVirtual() && SpillSize == 4) {
1779 MRI.constrainRegClass(SrcReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
1792 SpillSize, *MFI, NeedsCFI);
1807 storeRegToStackSlotImpl(
MBB,
MI, SrcReg, isKill, FrameIndex, RC, VReg, Flags,
1816 storeRegToStackSlotImpl(
MBB,
MI, SrcReg, isKill, FrameIndex, RC,
Register(),
1823 return AMDGPU::SI_SPILL_S32_RESTORE;
1825 return AMDGPU::SI_SPILL_S64_RESTORE;
1827 return AMDGPU::SI_SPILL_S96_RESTORE;
1829 return AMDGPU::SI_SPILL_S128_RESTORE;
1831 return AMDGPU::SI_SPILL_S160_RESTORE;
1833 return AMDGPU::SI_SPILL_S192_RESTORE;
1835 return AMDGPU::SI_SPILL_S224_RESTORE;
1837 return AMDGPU::SI_SPILL_S256_RESTORE;
1839 return AMDGPU::SI_SPILL_S288_RESTORE;
1841 return AMDGPU::SI_SPILL_S320_RESTORE;
1843 return AMDGPU::SI_SPILL_S352_RESTORE;
1845 return AMDGPU::SI_SPILL_S384_RESTORE;
1847 return AMDGPU::SI_SPILL_S512_RESTORE;
1849 return AMDGPU::SI_SPILL_S1024_RESTORE;
1858 return AMDGPU::SI_SPILL_V16_RESTORE;
1860 return AMDGPU::SI_SPILL_V32_RESTORE;
1862 return AMDGPU::SI_SPILL_V64_RESTORE;
1864 return AMDGPU::SI_SPILL_V96_RESTORE;
1866 return AMDGPU::SI_SPILL_V128_RESTORE;
1868 return AMDGPU::SI_SPILL_V160_RESTORE;
1870 return AMDGPU::SI_SPILL_V192_RESTORE;
1872 return AMDGPU::SI_SPILL_V224_RESTORE;
1874 return AMDGPU::SI_SPILL_V256_RESTORE;
1876 return AMDGPU::SI_SPILL_V288_RESTORE;
1878 return AMDGPU::SI_SPILL_V320_RESTORE;
1880 return AMDGPU::SI_SPILL_V352_RESTORE;
1882 return AMDGPU::SI_SPILL_V384_RESTORE;
1884 return AMDGPU::SI_SPILL_V512_RESTORE;
1886 return AMDGPU::SI_SPILL_V1024_RESTORE;
1895 return AMDGPU::SI_SPILL_AV32_RESTORE;
1897 return AMDGPU::SI_SPILL_AV64_RESTORE;
1899 return AMDGPU::SI_SPILL_AV96_RESTORE;
1901 return AMDGPU::SI_SPILL_AV128_RESTORE;
1903 return AMDGPU::SI_SPILL_AV160_RESTORE;
1905 return AMDGPU::SI_SPILL_AV192_RESTORE;
1907 return AMDGPU::SI_SPILL_AV224_RESTORE;
1909 return AMDGPU::SI_SPILL_AV256_RESTORE;
1911 return AMDGPU::SI_SPILL_AV288_RESTORE;
1913 return AMDGPU::SI_SPILL_AV320_RESTORE;
1915 return AMDGPU::SI_SPILL_AV352_RESTORE;
1917 return AMDGPU::SI_SPILL_AV384_RESTORE;
1919 return AMDGPU::SI_SPILL_AV512_RESTORE;
1921 return AMDGPU::SI_SPILL_AV1024_RESTORE;
1928 bool IsVectorSuperClass) {
1933 if (IsVectorSuperClass)
1934 return AMDGPU::SI_SPILL_WWM_AV32_RESTORE;
1936 return AMDGPU::SI_SPILL_WWM_V32_RESTORE;
1942 bool IsVectorSuperClass = RI.isVectorSuperClass(RC);
1949 if (ST.hasMAIInsts())
1952 assert(!RI.isAGPRClass(RC));
1966 unsigned SpillSize = RI.getSpillSize(*RC);
1973 FrameInfo.getObjectAlign(FrameIndex));
1975 if (RI.isSGPRClass(RC)) {
1978 assert(DestReg != AMDGPU::M0 &&
"m0 should not be reloaded into");
1979 assert(DestReg != AMDGPU::EXEC_LO && DestReg != AMDGPU::EXEC_HI &&
1980 DestReg != AMDGPU::EXEC &&
"exec should not be spilled");
1985 if (DestReg.
isVirtual() && SpillSize == 4) {
1987 MRI.constrainRegClass(DestReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
2014 unsigned Quantity)
const {
2016 unsigned MaxSNopCount = 1u << ST.getSNopBits();
2017 while (Quantity > 0) {
2018 unsigned Arg = std::min(Quantity, MaxSNopCount);
2029 constexpr unsigned DoorbellIDMask = 0x3ff;
2030 constexpr unsigned ECQueueWaveAbort = 0x400;
2035 if (!
MBB.succ_empty() ||
2037 false) !=
MBB.end()) {
2038 MBB.splitAt(
MI,
false);
2042 MBB.addSuccessor(TrapBB);
2048 Register DoorbellReg =
MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2052 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
2055 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2056 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_AND_B32), DoorbellRegMasked)
2061 MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
2062 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_OR_B32), SetWaveAbortBit)
2063 .
addUse(DoorbellRegMasked)
2064 .
addImm(ECQueueWaveAbort)
2066 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2067 .
addUse(SetWaveAbortBit);
2070 BuildMI(*TrapBB, TrapBB->
end(),
DL,
get(AMDGPU::S_MOV_B32), AMDGPU::M0)
2081 return MBB.getNextNode();
2085 switch (
MI.getOpcode()) {
2087 if (
MI.isMetaInstruction())
2092 return MI.getOperand(0).getImm() + 1;
2103 switch (
MI.getOpcode()) {
2105 case AMDGPU::S_MOV_B64_term:
2108 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2111 case AMDGPU::S_MOV_B32_term:
2114 MI.setDesc(
get(AMDGPU::S_MOV_B32));
2117 case AMDGPU::S_XOR_B64_term:
2120 MI.setDesc(
get(AMDGPU::S_XOR_B64));
2123 case AMDGPU::S_XOR_B32_term:
2126 MI.setDesc(
get(AMDGPU::S_XOR_B32));
2128 case AMDGPU::S_OR_B64_term:
2131 MI.setDesc(
get(AMDGPU::S_OR_B64));
2133 case AMDGPU::S_OR_B32_term:
2136 MI.setDesc(
get(AMDGPU::S_OR_B32));
2139 case AMDGPU::S_ANDN2_B64_term:
2142 MI.setDesc(
get(AMDGPU::S_ANDN2_B64));
2145 case AMDGPU::S_ANDN2_B32_term:
2148 MI.setDesc(
get(AMDGPU::S_ANDN2_B32));
2151 case AMDGPU::S_AND_B64_term:
2154 MI.setDesc(
get(AMDGPU::S_AND_B64));
2157 case AMDGPU::S_AND_B32_term:
2160 MI.setDesc(
get(AMDGPU::S_AND_B32));
2163 case AMDGPU::S_AND_SAVEEXEC_B64_term:
2166 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B64));
2169 case AMDGPU::S_AND_SAVEEXEC_B32_term:
2172 MI.setDesc(
get(AMDGPU::S_AND_SAVEEXEC_B32));
2175 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
2176 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32));
2178 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
2179 MI.setDesc(
get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32));
2182 case AMDGPU::SI_SPILL_S32_TO_VGPR:
2183 MI.setDesc(
get(AMDGPU::V_WRITELANE_B32));
2186 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
2187 MI.setDesc(
get(AMDGPU::V_READLANE_B32));
2189 case AMDGPU::AV_MOV_B32_IMM_PSEUDO: {
2193 get(IsAGPR ? AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::V_MOV_B32_e32));
2196 case AMDGPU::AV_MOV_B64_IMM_PSEUDO: {
2199 int64_t
Imm =
MI.getOperand(1).getImm();
2201 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2202 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2207 MI.eraseFromParent();
2213 case AMDGPU::V_MOV_B64_PSEUDO: {
2215 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2216 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2224 if (ST.hasVMovB64Inst() && Mov64RC->
contains(Dst)) {
2225 MI.setDesc(Mov64Desc);
2229 (
SrcOp.isGlobal() && ST.has64BitLiterals()))
2232 if (
SrcOp.isGlobal()) {
2243 }
else if (
SrcOp.isImm()) {
2245 APInt Lo(32,
Imm.getLoBits(32).getZExtValue());
2246 APInt Hi(32,
Imm.getHiBits(32).getZExtValue());
2270 if (ST.hasPkMovB32() &&
2289 MI.eraseFromParent();
2292 case AMDGPU::V_MOV_B64_DPP_PSEUDO: {
2296 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2300 if (ST.has64BitLiterals()) {
2301 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2305 if (
SrcOp.isGlobal()) {
2307 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2308 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2317 MI.eraseFromParent();
2324 MI.setDesc(
get(AMDGPU::S_MOV_B64));
2329 Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
2330 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2332 APInt Lo(32,
Imm.getLoBits(32).getZExtValue());
2333 APInt Hi(32,
Imm.getHiBits(32).getZExtValue());
2338 MI.eraseFromParent();
2341 case AMDGPU::V_SET_INACTIVE_B32: {
2345 .
add(
MI.getOperand(3))
2346 .
add(
MI.getOperand(4))
2347 .
add(
MI.getOperand(1))
2348 .
add(
MI.getOperand(2))
2349 .
add(
MI.getOperand(5));
2350 MI.eraseFromParent();
2353 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2354 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2355 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2356 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2357 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2358 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2359 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2360 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2361 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2362 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2363 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2364 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2365 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2366 case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2367 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1:
2368 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2:
2369 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3:
2370 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4:
2371 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5:
2372 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6:
2373 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7:
2374 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8:
2375 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9:
2376 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10:
2377 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11:
2378 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12:
2379 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16:
2380 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32:
2381 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1:
2382 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2:
2383 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4:
2384 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8:
2385 case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16: {
2389 if (RI.hasVGPRs(EltRC)) {
2390 Opc = AMDGPU::V_MOVRELD_B32_e32;
2392 Opc = RI.getRegSizeInBits(*EltRC) == 64 ? AMDGPU::S_MOVRELD_B64
2393 : AMDGPU::S_MOVRELD_B32;
2398 bool IsUndef =
MI.getOperand(1).isUndef();
2399 unsigned SubReg =
MI.getOperand(3).getImm();
2400 assert(VecReg ==
MI.getOperand(1).getReg());
2405 .
add(
MI.getOperand(2))
2409 const int ImpDefIdx =
2411 const int ImpUseIdx = ImpDefIdx + 1;
2413 MI.eraseFromParent();
2416 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1:
2417 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2:
2418 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3:
2419 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4:
2420 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5:
2421 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6:
2422 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7:
2423 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8:
2424 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9:
2425 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10:
2426 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11:
2427 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12:
2428 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16:
2429 case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32: {
2430 assert(ST.useVGPRIndexMode());
2432 bool IsUndef =
MI.getOperand(1).isUndef();
2441 const MCInstrDesc &OpDesc =
get(AMDGPU::V_MOV_B32_indirect_write);
2445 .
add(
MI.getOperand(2))
2449 const int ImpDefIdx =
2451 const int ImpUseIdx = ImpDefIdx + 1;
2458 MI.eraseFromParent();
2461 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1:
2462 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2:
2463 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3:
2464 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4:
2465 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5:
2466 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6:
2467 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7:
2468 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8:
2469 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9:
2470 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10:
2471 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11:
2472 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12:
2473 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16:
2474 case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32: {
2475 assert(ST.useVGPRIndexMode());
2478 bool IsUndef =
MI.getOperand(1).isUndef();
2482 .
add(
MI.getOperand(2))
2495 MI.eraseFromParent();
2498 case AMDGPU::SI_PC_ADD_REL_OFFSET: {
2501 Register RegLo = RI.getSubReg(Reg, AMDGPU::sub0);
2502 Register RegHi = RI.getSubReg(Reg, AMDGPU::sub1);
2521 if (ST.hasGetPCZeroExtension()) {
2525 BuildMI(MF,
DL,
get(AMDGPU::S_SEXT_I32_I16), RegHi).addReg(RegHi));
2532 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U32), RegLo).addReg(RegLo).add(OpLo));
2542 MI.eraseFromParent();
2545 case AMDGPU::SI_PC_ADD_REL_OFFSET64: {
2555 Op.setOffset(
Op.getOffset() + 4);
2557 BuildMI(MF,
DL,
get(AMDGPU::S_ADD_U64), Reg).addReg(Reg).add(
Op));
2561 MI.eraseFromParent();
2564 case AMDGPU::ENTER_STRICT_WWM: {
2570 case AMDGPU::ENTER_STRICT_WQM: {
2577 MI.eraseFromParent();
2580 case AMDGPU::EXIT_STRICT_WWM:
2581 case AMDGPU::EXIT_STRICT_WQM: {
2587 case AMDGPU::SI_RETURN: {
2601 MI.eraseFromParent();
2605 case AMDGPU::S_MUL_U64_U32_PSEUDO:
2606 case AMDGPU::S_MUL_I64_I32_PSEUDO:
2607 MI.setDesc(
get(AMDGPU::S_MUL_U64));
2610 case AMDGPU::S_GETPC_B64_pseudo:
2611 MI.setDesc(
get(AMDGPU::S_GETPC_B64));
2612 if (ST.hasGetPCZeroExtension()) {
2614 Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
2623 case AMDGPU::V_MAX_BF16_PSEUDO_e64: {
2624 assert(ST.hasBF16PackedInsts());
2625 MI.setDesc(
get(AMDGPU::V_PK_MAX_NUM_BF16));
2636 case AMDGPU::GET_STACK_BASE:
2639 if (ST.getFrameLowering()->mayReserveScratchForCWSR(*
MBB.getParent())) {
2646 Register DestReg =
MI.getOperand(0).getReg();
2656 MI.getOperand(
MI.getNumExplicitOperands()).setIsDead(
false);
2657 MI.getOperand(
MI.getNumExplicitOperands()).setIsUse();
2658 MI.setDesc(
get(AMDGPU::S_CMOVK_I32));
2661 MI.setDesc(
get(AMDGPU::S_MOV_B32));
2664 MI.getNumExplicitOperands());
2682 case AMDGPU::S_MOV_B64:
2683 case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
2692 if (UsedLanes.
all())
2697 unsigned LoSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub0);
2698 unsigned HiSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub1);
2700 bool NeedLo = (UsedLanes & RI.getSubRegIndexLaneMask(LoSubReg)).any();
2701 bool NeedHi = (UsedLanes & RI.getSubRegIndexLaneMask(HiSubReg)).any();
2703 if (NeedLo && NeedHi)
2707 int32_t Imm32 = NeedLo ?
Lo_32(Imm64) :
Hi_32(Imm64);
2709 unsigned UseSubReg = NeedLo ? LoSubReg : HiSubReg;
2718 case AMDGPU::S_LOAD_DWORDX16_IMM:
2719 case AMDGPU::S_LOAD_DWORDX8_IMM: {
2720 if (SubIdx != 0 || UsedLanes.
all())
2731 assert(
MRI.use_nodbg_empty(DestReg) &&
"DestReg should have no users yet.");
2738 UseMO !=
I->findRegisterUseOperand(RegToFind,
nullptr) ||
2739 UseMO->
getSubReg() == AMDGPU::NoSubRegister)
2743 unsigned SubregSize = RI.getSubRegIdxSize(UseMO->
getSubReg());
2745 unsigned NewOpcode = -1;
2746 if (SubregSize == 256)
2747 NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
2748 else if (SubregSize == 128)
2749 NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
2756 MRI.setRegClass(DestReg, NewRC);
2759 UseMO->
setSubReg(AMDGPU::NoSubRegister);
2764 MI->getOperand(0).setReg(DestReg);
2765 MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
2769 OffsetMO->
setImm(FinalOffset);
2775 MI->setMemRefs(*MF, NewMMOs);
2788std::pair<MachineInstr*, MachineInstr*>
2790 assert (
MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);
2792 if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
2795 MI.setDesc(
get(AMDGPU::V_MOV_B64_dpp));
2796 return std::pair(&
MI,
nullptr);
2807 for (
auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
2809 if (Dst.isPhysical()) {
2810 MovDPP.addDef(RI.getSubReg(Dst,
Sub));
2813 auto Tmp =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
2817 for (
unsigned I = 1;
I <= 2; ++
I) {
2820 if (
SrcOp.isImm()) {
2822 Imm.ashrInPlace(Part * 32);
2823 MovDPP.addImm(
Imm.getLoBits(32).getZExtValue());
2827 if (Src.isPhysical())
2828 MovDPP.addReg(RI.getSubReg(Src,
Sub));
2835 MovDPP.addImm(MO.getImm());
2837 Split[Part] = MovDPP;
2841 if (Dst.isVirtual())
2848 MI.eraseFromParent();
2849 return std::pair(Split[0], Split[1]);
2852std::optional<DestSourcePair>
2854 if (
MI.getOpcode() == AMDGPU::WWM_COPY)
2857 return std::nullopt;
2861 AMDGPU::OpName Src0OpName,
2863 AMDGPU::OpName Src1OpName)
const {
2870 "All commutable instructions have both src0 and src1 modifiers");
2872 int Src0ModsVal = Src0Mods->
getImm();
2873 int Src1ModsVal = Src1Mods->
getImm();
2875 Src1Mods->
setImm(Src0ModsVal);
2876 Src0Mods->
setImm(Src1ModsVal);
2885 bool IsKill = RegOp.
isKill();
2887 bool IsUndef = RegOp.
isUndef();
2888 bool IsDebug = RegOp.
isDebug();
2890 if (NonRegOp.
isImm())
2892 else if (NonRegOp.
isFI())
2913 int64_t NonRegVal = NonRegOp1.
getImm();
2916 NonRegOp2.
setImm(NonRegVal);
2926 bool CheckSwappedSrc =
false) {
2927 unsigned Opc =
MI.getOpcode();
2928 if (!
TII.getSubtarget().hasPkF32InvalidOpSel() ||
2929 (
Opc != AMDGPU::V_PK_ADD_F32 &&
Opc != AMDGPU::V_PK_MUL_F32 &&
2930 Opc != AMDGPU::V_PK_FMA_F32))
2933 auto Mods = [&](AMDGPU::OpName Name) {
2935 return Op ?
static_cast<unsigned>(
Op->getImm()) : 0u;
2937 unsigned Src0Mods = Mods(AMDGPU::OpName::src0_modifiers);
2938 unsigned Src1Mods = Mods(AMDGPU::OpName::src1_modifiers);
2939 unsigned Src2Mods = Mods(AMDGPU::OpName::src2_modifiers);
2941 if (CheckSwappedSrc)
2944 if (
Opc == AMDGPU::V_PK_FMA_F32)
2950 unsigned OpIdx1)
const {
2955 unsigned Opc =
MI.getOpcode();
2956 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
2957 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
2961 bool IsSrc01Swap = ((int)OpIdx0 == Src0Idx && (int)OpIdx1 == Src1Idx) ||
2962 ((
int)OpIdx0 == Src1Idx && (
int)OpIdx1 == Src0Idx);
2974 if ((
int)OpIdx0 == Src0Idx && !MO0.
isReg() &&
2977 if ((
int)OpIdx1 == Src0Idx && !MO1.
isReg() &&
2982 if ((
int)OpIdx1 != Src0Idx && MO0.
isReg()) {
2988 if ((
int)OpIdx0 != Src0Idx && MO1.
isReg()) {
3010 unsigned Src1Idx)
const {
3011 assert(!NewMI &&
"this should never be used");
3016 unsigned Opc =
MI.getOpcode();
3018 if (CommutedOpcode == -1)
3021 if (Src0Idx > Src1Idx)
3024 assert(AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) ==
3025 static_cast<int>(Src0Idx) &&
3026 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1) ==
3027 static_cast<int>(Src1Idx) &&
3028 "inconsistency with findCommutedOpIndices");
3036 if (Src0.isReg() && Src1.isReg()) {
3040 }
else if (Src0.isReg() && !Src1.isReg()) {
3042 }
else if (!Src0.isReg() && Src1.isReg()) {
3044 }
else if (Src0.isImm() && Src1.isImm()) {
3053 Src1, AMDGPU::OpName::src1_modifiers);
3056 AMDGPU::OpName::src1_sel);
3068 unsigned &SrcOpIdx0,
3069 unsigned &SrcOpIdx1)
const {
3077 unsigned &SrcOpIdx0,
3078 unsigned &SrcOpIdx1)
const {
3079 if (!
Desc.isCommutable())
3082 unsigned Opc =
Desc.getOpcode();
3083 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
3087 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
3091 return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
3095 int64_t BrOffset)
const {
3107 return isIntN(ST.getCLOpts().s_branch_bits, BrOffset);
3112 return MI.getOperand(0).getMBB();
3117 if (
MI.getOpcode() == AMDGPU::SI_IF ||
MI.getOpcode() == AMDGPU::SI_ELSE ||
3118 MI.getOpcode() == AMDGPU::SI_LOOP ||
3119 MI.getOpcode() == AMDGPU::SI_WATERFALL_LOOP)
3131 "new block should be inserted for expanding unconditional branch");
3134 "restore block should be inserted for restoring clobbered registers");
3142 if (ST.useAddPCI64Inst()) {
3144 MCCtx.createTempSymbol(
"offset",
true);
3148 MCCtx.createTempSymbol(
"post_addpc",
true);
3149 AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
3153 Offset->setVariableValue(OffsetExpr);
3157 assert(RS &&
"RegScavenger required for long branching");
3161 Register PCReg =
MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
3165 const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
3166 ST.hasVALUReadSGPRHazard();
3167 auto ApplyHazardWorkarounds = [
this, &
MBB, &
I, &
DL, FlushSGPRWrites]() {
3168 if (FlushSGPRWrites)
3176 ApplyHazardWorkarounds();
3179 MCCtx.createTempSymbol(
"post_getpc",
true);
3183 MCCtx.createTempSymbol(
"offset_lo",
true);
3185 MCCtx.createTempSymbol(
"offset_hi",
true);
3188 .
addReg(PCReg, {}, AMDGPU::sub0)
3192 .
addReg(PCReg, {}, AMDGPU::sub1)
3194 ApplyHazardWorkarounds();
3235 if (LongBranchReservedReg) {
3236 RS->enterBasicBlock(
MBB);
3237 Scav = LongBranchReservedReg;
3239 RS->enterBasicBlockEnd(
MBB);
3240 Scav = RS->scavengeRegisterBackwards(
3245 RS->setRegUsed(Scav);
3246 MRI.replaceRegWith(PCReg, Scav);
3247 MRI.clearVirtRegs();
3253 TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
3254 MRI.replaceRegWith(PCReg, AMDGPU::SGPR0_SGPR1);
3255 MRI.clearVirtRegs();
3270unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate
Cond) {
3272 case SIInstrInfo::SCC_TRUE:
3273 return AMDGPU::S_CBRANCH_SCC1;
3274 case SIInstrInfo::SCC_FALSE:
3275 return AMDGPU::S_CBRANCH_SCC0;
3276 case SIInstrInfo::VCCNZ:
3277 return AMDGPU::S_CBRANCH_VCCNZ;
3278 case SIInstrInfo::VCCZ:
3279 return AMDGPU::S_CBRANCH_VCCZ;
3280 case SIInstrInfo::EXECNZ:
3281 return AMDGPU::S_CBRANCH_EXECNZ;
3282 case SIInstrInfo::EXECZ:
3283 return AMDGPU::S_CBRANCH_EXECZ;
3289SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(
unsigned Opcode) {
3291 case AMDGPU::S_CBRANCH_SCC0:
3293 case AMDGPU::S_CBRANCH_SCC1:
3295 case AMDGPU::S_CBRANCH_VCCNZ:
3297 case AMDGPU::S_CBRANCH_VCCZ:
3299 case AMDGPU::S_CBRANCH_EXECNZ:
3301 case AMDGPU::S_CBRANCH_EXECZ:
3313 bool AllowModify)
const {
3314 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3316 TBB =
I->getOperand(0).getMBB();
3320 BranchPredicate Pred = getBranchPredicate(
I->getOpcode());
3321 if (Pred == INVALID_BR)
3326 Cond.push_back(
I->getOperand(1));
3330 if (
I ==
MBB.end()) {
3336 if (
I->getOpcode() == AMDGPU::S_BRANCH) {
3338 FBB =
I->getOperand(0).getMBB();
3348 bool AllowModify)
const {
3356 while (
I != E && !
I->isBranch() && !
I->isReturn()) {
3357 switch (
I->getOpcode()) {
3358 case AMDGPU::S_MOV_B64_term:
3359 case AMDGPU::S_XOR_B64_term:
3360 case AMDGPU::S_OR_B64_term:
3361 case AMDGPU::S_ANDN2_B64_term:
3362 case AMDGPU::S_AND_B64_term:
3363 case AMDGPU::S_AND_SAVEEXEC_B64_term:
3364 case AMDGPU::S_MOV_B32_term:
3365 case AMDGPU::S_XOR_B32_term:
3366 case AMDGPU::S_OR_B32_term:
3367 case AMDGPU::S_ANDN2_B32_term:
3368 case AMDGPU::S_AND_B32_term:
3369 case AMDGPU::S_AND_SAVEEXEC_B32_term:
3370 case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
3371 case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
3374 case AMDGPU::SI_ELSE:
3375 case AMDGPU::SI_KILL_I1_TERMINATOR:
3376 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
3393 int *BytesRemoved)
const {
3395 unsigned RemovedSize = 0;
3398 if (
MI.isBranch() ||
MI.isReturn()) {
3400 MI.eraseFromParent();
3406 *BytesRemoved = RemovedSize;
3423 int *BytesAdded)
const {
3424 if (!FBB &&
Cond.empty()) {
3428 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3435 = getBranchOpcode(
static_cast<BranchPredicate
>(
Cond[0].
getImm()));
3447 *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
3465 *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;
3472 if (
Cond.size() != 2) {
3476 if (
Cond[0].isImm()) {
3497 bool shouldIgnoreForPipelining(
const MachineInstr *
MI)
const override {
3501 std::optional<bool> createTripCountGreaterCondition(
3502 int TC, MachineBasicBlock &
MBB,
3503 SmallVectorImpl<MachineOperand> &CondParam)
override {
3504 CondParam = this->
Cond;
3508 void adjustTripCount(
int TripCountAdjust)
override {}
3510 void setPreheader(MachineBasicBlock *NewPreheader)
override {}
3514std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
3523 if (
TBB == LoopBB && FBB == LoopBB)
3530 assert((
TBB == LoopBB || FBB == LoopBB) &&
3531 "The Loop must be a single-basic-block loop");
3534 BranchPredicate Pred =
static_cast<BranchPredicate
>(
Cond[0].getImm());
3535 if (Pred != SCC_TRUE && Pred != SCC_FALSE)
3540 if (
MI.isCall() ||
MI.isInlineAsm())
3555 if (CmpI == Instructions.end() || CmpI->isPHI())
3559 return std::make_unique<AMDGPUPipelinerLoopInfo>(
CmpInst,
Cond);
3566 SelectExpansion &Exp)
const {
3572 if (
MRI.getRegClass(FalseReg) != RC)
3576 Exp.CondCycles = Exp.TrueCycles = Exp.FalseCycles = NumInsts;
3579 return RI.hasVGPRs(RC) && NumInsts <= 6;
3587 if (
MRI.getRegClass(FalseReg) != RC)
3593 if (NumInsts % 2 == 0)
3596 Exp.CondCycles = Exp.TrueCycles = Exp.FalseCycles = NumInsts;
3597 return RI.isSGPRClass(RC);
3608 BranchPredicate Pred =
static_cast<BranchPredicate
>(
Cond[0].getImm());
3609 if (Pred == VCCZ || Pred == SCC_FALSE) {
3610 Pred =
static_cast<BranchPredicate
>(-Pred);
3616 unsigned DstSize = RI.getRegSizeInBits(*DstRC);
3618 if (DstSize == 32) {
3620 if (Pred == SCC_TRUE) {
3635 if (DstSize == 64 && Pred == SCC_TRUE) {
3645 static const int16_t Sub0_15[] = {
3646 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
3647 AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
3648 AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
3649 AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
3652 static const int16_t Sub0_15_64[] = {
3653 AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
3654 AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
3655 AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
3656 AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
3659 unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
3661 const int16_t *SubIndices = Sub0_15;
3662 int NElts = DstSize / 32;
3666 if (Pred == SCC_TRUE) {
3668 SelOp = AMDGPU::S_CSELECT_B32;
3669 EltRC = &AMDGPU::SGPR_32RegClass;
3671 SelOp = AMDGPU::S_CSELECT_B64;
3672 EltRC = &AMDGPU::SGPR_64RegClass;
3673 SubIndices = Sub0_15_64;
3679 MBB,
I,
DL,
get(AMDGPU::REG_SEQUENCE), DstReg);
3684 for (
int Idx = 0; Idx != NElts; ++Idx) {
3685 Register DstElt =
MRI.createVirtualRegister(EltRC);
3688 unsigned SubIdx = SubIndices[Idx];
3691 if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
3693 .
addReg(FalseReg, {}, SubIdx)
3694 .addReg(TrueReg, {}, SubIdx);
3697 .
addReg(TrueReg, {}, SubIdx)
3698 .addReg(FalseReg, {}, SubIdx);
3711 if (
MI.isBranch() ||
MI.isCall() ||
MI.isReturn() ||
MI.isIndirectBranch())
3714 switch (
MI.getOpcode()) {
3715 case AMDGPU::S_ENDPGM:
3716 case AMDGPU::S_ENDPGM_SAVED:
3717 case AMDGPU::S_TRAP:
3718 case AMDGPU::S_GETREG_B32:
3719 case AMDGPU::S_SETREG_B32:
3720 case AMDGPU::S_SETREG_B32_mode:
3721 case AMDGPU::S_SETREG_IMM32_B32:
3722 case AMDGPU::S_SETREG_IMM32_B32_mode:
3723 case AMDGPU::S_SENDMSG:
3724 case AMDGPU::S_SENDMSGHALT:
3725 case AMDGPU::S_SENDMSG_RTN_B32:
3726 case AMDGPU::S_SENDMSG_RTN_B64:
3727 case AMDGPU::S_BARRIER_WAIT:
3728 case AMDGPU::S_BARRIER_SIGNAL_M0:
3729 case AMDGPU::S_BARRIER_SIGNAL_IMM:
3730 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
3731 case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
3739 switch (
MI.getOpcode()) {
3740 case AMDGPU::V_MOV_B16_t16_e32:
3741 case AMDGPU::V_MOV_B16_t16_e64:
3742 case AMDGPU::V_MOV_B32_e32:
3743 case AMDGPU::V_MOV_B32_e64:
3744 case AMDGPU::V_MOV_B64_PSEUDO:
3745 case AMDGPU::V_MOV_B64_e32:
3746 case AMDGPU::V_MOV_B64_e64:
3747 case AMDGPU::S_MOV_B32:
3748 case AMDGPU::S_MOV_B64:
3749 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3751 case AMDGPU::WWM_COPY:
3752 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3753 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3754 case AMDGPU::V_ACCVGPR_MOV_B32:
3755 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3756 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3764 switch (
MI.getOpcode()) {
3765 case AMDGPU::V_MOV_B16_t16_e32:
3766 case AMDGPU::V_MOV_B16_t16_e64:
3768 case AMDGPU::V_MOV_B32_e32:
3769 case AMDGPU::V_MOV_B32_e64:
3770 case AMDGPU::V_MOV_B64_PSEUDO:
3771 case AMDGPU::V_MOV_B64_e32:
3772 case AMDGPU::V_MOV_B64_e64:
3773 case AMDGPU::S_MOV_B32:
3774 case AMDGPU::S_MOV_B64:
3775 case AMDGPU::S_MOV_B64_IMM_PSEUDO:
3777 case AMDGPU::WWM_COPY:
3778 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
3779 case AMDGPU::V_ACCVGPR_READ_B32_e64:
3780 case AMDGPU::V_ACCVGPR_MOV_B32:
3781 case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
3782 case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
3790 AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
3791 AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
3792 AMDGPU::OpName::omod, AMDGPU::OpName::op_sel};
3795 unsigned Opc =
MI.getOpcode();
3797 int Idx = AMDGPU::getNamedOperandIdx(
Opc, Name);
3799 MI.removeOperand(Idx);
3805 MI.setDesc(NewDesc);
3811 unsigned NumOps =
Desc.getNumOperands() +
Desc.implicit_uses().size() +
3812 Desc.implicit_defs().size();
3814 for (
unsigned I =
MI.getNumOperands() - 1;
I >=
NumOps; --
I)
3815 MI.removeOperand(
I);
3819 unsigned SubRegIndex) {
3820 switch (SubRegIndex) {
3821 case AMDGPU::NoSubRegister:
3831 case AMDGPU::sub1_lo16:
3833 case AMDGPU::sub1_hi16:
3836 return std::nullopt;
3842std::optional<unsigned>
3844 unsigned SubRegIndex) {
3845 if (SubRegIndex == AMDGPU::NoSubRegister)
3848 unsigned LoReloc, HiReloc;
3849 switch (TargetFlags &
MO_MASK) {
3868 return std::nullopt;
3871 const unsigned BaseFlags = TargetFlags &
~MO_MASK;
3872 switch (SubRegIndex) {
3874 return BaseFlags | LoReloc;
3876 return BaseFlags | HiReloc;
3878 return std::nullopt;
3884 case AMDGPU::V_MAC_F16_e32:
3885 case AMDGPU::V_MAC_F16_e64:
3886 case AMDGPU::V_MAD_F16_e64:
3887 return AMDGPU::V_MADAK_F16;
3888 case AMDGPU::V_MAC_F32_e32:
3889 case AMDGPU::V_MAC_F32_e64:
3890 case AMDGPU::V_MAD_F32_e64:
3891 return AMDGPU::V_MADAK_F32;
3892 case AMDGPU::V_FMAC_F32_e32:
3893 case AMDGPU::V_FMAC_F32_e64:
3894 case AMDGPU::V_FMA_F32_e64:
3895 return AMDGPU::V_FMAAK_F32;
3896 case AMDGPU::V_FMAC_F16_e32:
3897 case AMDGPU::V_FMAC_F16_e64:
3898 case AMDGPU::V_FMAC_F16_t16_e64:
3899 case AMDGPU::V_FMAC_F16_fake16_e64:
3900 case AMDGPU::V_FMAC_F16_t16_e32:
3901 case AMDGPU::V_FMAC_F16_fake16_e32:
3902 case AMDGPU::V_FMA_F16_e64:
3903 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3904 ? AMDGPU::V_FMAAK_F16_t16
3905 : AMDGPU::V_FMAAK_F16_fake16
3906 : AMDGPU::V_FMAAK_F16;
3907 case AMDGPU::V_FMAC_F64_e32:
3908 case AMDGPU::V_FMAC_F64_e64:
3909 case AMDGPU::V_FMA_F64_e64:
3910 return AMDGPU::V_FMAAK_F64;
3918 case AMDGPU::V_MAC_F16_e32:
3919 case AMDGPU::V_MAC_F16_e64:
3920 case AMDGPU::V_MAD_F16_e64:
3921 return AMDGPU::V_MADMK_F16;
3922 case AMDGPU::V_MAC_F32_e32:
3923 case AMDGPU::V_MAC_F32_e64:
3924 case AMDGPU::V_MAD_F32_e64:
3925 return AMDGPU::V_MADMK_F32;
3926 case AMDGPU::V_FMAC_F32_e32:
3927 case AMDGPU::V_FMAC_F32_e64:
3928 case AMDGPU::V_FMA_F32_e64:
3929 return AMDGPU::V_FMAMK_F32;
3930 case AMDGPU::V_FMAC_F16_e32:
3931 case AMDGPU::V_FMAC_F16_e64:
3932 case AMDGPU::V_FMAC_F16_t16_e64:
3933 case AMDGPU::V_FMAC_F16_fake16_e64:
3934 case AMDGPU::V_FMAC_F16_t16_e32:
3935 case AMDGPU::V_FMAC_F16_fake16_e32:
3936 case AMDGPU::V_FMA_F16_e64:
3937 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
3938 ? AMDGPU::V_FMAMK_F16_t16
3939 : AMDGPU::V_FMAMK_F16_fake16
3940 : AMDGPU::V_FMAMK_F16;
3941 case AMDGPU::V_FMAC_F64_e32:
3942 case AMDGPU::V_FMAC_F64_e64:
3943 case AMDGPU::V_FMA_F64_e64:
3944 return AMDGPU::V_FMAMK_F64;
3956 const bool HasMultipleUses = !
MRI->hasOneNonDBGUse(Reg);
3958 assert(!
DefMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3961 if (
Opc == AMDGPU::COPY) {
3962 assert(!
UseMI.getOperand(0).getSubReg() &&
"Expected SSA form");
3969 if (HasMultipleUses) {
3972 unsigned ImmDefSize = RI.getRegSizeInBits(*
MRI->getRegClass(Reg));
3975 if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
3983 if (ImmDefSize == 32 &&
3988 bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
3989 RI.getSubRegIdxSize(UseSubReg) == 16;
3992 if (RI.hasVGPRs(DstRC))
3995 if (DstReg.
isVirtual() && UseSubReg != AMDGPU::lo16)
4001 unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
4008 for (
unsigned MovOp :
4009 {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
4010 AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
4018 MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
4022 if (MovDstPhysReg) {
4026 RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
4033 if (MovDstPhysReg) {
4034 if (!MovDstRC->
contains(MovDstPhysReg))
4036 }
else if (!
MRI->constrainRegClass(DstReg, MovDstRC)) {
4050 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
4058 if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
4062 UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
4064 UseMI.getOperand(0).setReg(MovDstPhysReg);
4069 UseMI.setDesc(NewMCID);
4070 UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
4071 UseMI.addImplicitDefUseOperands(*MF);
4075 if (HasMultipleUses)
4078 if (
Opc == AMDGPU::V_MAD_F32_e64 ||
Opc == AMDGPU::V_MAC_F32_e64 ||
4079 Opc == AMDGPU::V_MAD_F16_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4080 Opc == AMDGPU::V_FMA_F32_e64 ||
Opc == AMDGPU::V_FMAC_F32_e64 ||
4081 Opc == AMDGPU::V_FMA_F16_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64 ||
4082 Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4083 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
Opc == AMDGPU::V_FMA_F64_e64 ||
4084 Opc == AMDGPU::V_FMAC_F64_e64) {
4093 int Src0Idx = getNamedOperandIdx(
UseMI.getOpcode(), AMDGPU::OpName::src0);
4104 auto CopyRegOperandToNarrowerRC =
4107 if (!
MI.getOperand(OpNo).isReg())
4111 if (RI.getCommonSubClass(RC, NewRC) != NewRC)
4114 BuildMI(*
MI.getParent(),
MI.getIterator(),
MI.getDebugLoc(),
4115 get(AMDGPU::COPY), Tmp)
4117 MI.getOperand(OpNo).setReg(Tmp);
4121 if ((Src0->isReg() && Src0->getReg() == Reg) ||
4122 (Src1->isReg() && Src1->getReg() == Reg)) {
4124 Src1->isReg() && Src1->getReg() == Reg ? Src0 : Src1;
4125 if (!RegSrc->
isReg())
4127 if (RI.isSGPRClass(
MRI->getRegClass(RegSrc->
getReg())) &&
4128 ST.getConstantBusLimit(
Opc) < 2)
4131 if (!Src2->isReg() || RI.isSGPRClass(
MRI->getRegClass(Src2->getReg())))
4143 if (Def && Def->isMoveImmediate() &&
4152 Imm, RegSrc == Src1 ? Src0->getSubReg() : Src1->getSubReg());
4158 unsigned SrcSubReg = RegSrc->
getSubReg();
4159 Src0->setReg(SrcReg);
4160 Src0->setSubReg(SrcSubReg);
4161 Src0->setIsKill(RegSrc->
isKill());
4163 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4164 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4165 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4166 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
4167 UseMI.untieRegOperand(
4168 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
4170 Src1->ChangeToImmediate(*SubRegImm);
4175 if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
4176 NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
4180 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
4181 UseMI.getOperand(0).getReg())
4183 UseMI.getOperand(0).setReg(Tmp);
4184 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
4185 CopyRegOperandToNarrowerRC(
UseMI, 3, NewRC);
4188 bool DeleteDef =
MRI->use_nodbg_empty(Reg);
4190 DefMI.eraseFromParent();
4196 if (Src2->isReg() && Src2->getReg() == Reg) {
4197 if (ST.getConstantBusLimit(
Opc) < 2) {
4200 bool Src0Inlined =
false;
4201 if (Src0->isReg()) {
4206 if (Def && Def->isMoveImmediate() &&
4208 MRI->hasOneNonDBGUse(Src0->getReg())) {
4209 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4211 }
else if (ST.getConstantBusLimit(
Opc) <= 1 &&
4212 RI.isSGPRReg(*
MRI, Src0->getReg())) {
4218 if (Src1->isReg() && !Src0Inlined) {
4221 if (Def && Def->isMoveImmediate() &&
4223 MRI->hasOneNonDBGUse(Src1->getReg()) && commuteInstruction(
UseMI))
4224 Src0->ChangeToImmediate(Def->getOperand(1).getImm());
4225 else if (RI.isSGPRReg(*
MRI, Src1->getReg()))
4238 if (
Opc == AMDGPU::V_MAC_F32_e64 ||
Opc == AMDGPU::V_MAC_F16_e64 ||
4239 Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
4240 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
4241 Opc == AMDGPU::V_FMAC_F16_e64 ||
Opc == AMDGPU::V_FMAC_F64_e64)
4242 UseMI.untieRegOperand(
4243 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2));
4245 const std::optional<int64_t> SubRegImm =
4249 Src2->ChangeToImmediate(*SubRegImm);
4255 if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
4256 NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
4260 UseMI.getDebugLoc(),
get(AMDGPU::COPY),
4261 UseMI.getOperand(0).getReg())
4263 UseMI.getOperand(0).setReg(Tmp);
4264 CopyRegOperandToNarrowerRC(
UseMI, 1, NewRC);
4265 CopyRegOperandToNarrowerRC(
UseMI, 2, NewRC);
4274 AMDGPU::getNamedOperandIdx(
UseMI.getOpcode(), AMDGPU::OpName::src0);
4278 bool DeleteDef =
MRI->use_nodbg_empty(Reg);
4280 DefMI.eraseFromParent();
4292 if (BaseOps1.
size() != BaseOps2.
size())
4294 for (
size_t I = 0,
E = BaseOps1.
size();
I <
E; ++
I) {
4295 if (!BaseOps1[
I]->isIdenticalTo(*BaseOps2[
I]))
4303 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
4304 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
4305 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
4307 LowOffset + (int)LowWidth.
getValue() <= HighOffset;
4310bool SIInstrInfo::checkInstOffsetsDoNotOverlap(
const MachineInstr &MIa,
4313 int64_t Offset0, Offset1;
4316 bool Offset0IsScalable, Offset1IsScalable;
4330 LocationSize Width0 = MIa.
memoperands().front()->getSize();
4331 LocationSize Width1 = MIb.
memoperands().front()->getSize();
4338 "MIa must load from or modify a memory location");
4340 "MIb must load from or modify a memory location");
4362 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4369 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4379 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4393 return checkInstOffsetsDoNotOverlap(MIa, MIb);
4404 case AMDGPU::V_MAC_F16_e32:
4405 case AMDGPU::V_MAC_F16_e64:
4406 return AMDGPU::V_MAD_F16_e64;
4407 case AMDGPU::V_MAC_F32_e32:
4408 case AMDGPU::V_MAC_F32_e64:
4409 return AMDGPU::V_MAD_F32_e64;
4410 case AMDGPU::V_MAC_LEGACY_F32_e32:
4411 case AMDGPU::V_MAC_LEGACY_F32_e64:
4412 return AMDGPU::V_MAD_LEGACY_F32_e64;
4413 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4414 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4415 return AMDGPU::V_FMA_LEGACY_F32_e64;
4416 case AMDGPU::V_FMAC_F16_e32:
4417 case AMDGPU::V_FMAC_F16_e64:
4418 case AMDGPU::V_FMAC_F16_t16_e64:
4419 case AMDGPU::V_FMAC_F16_fake16_e64:
4420 return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
4421 ? AMDGPU::V_FMA_F16_gfx9_t16_e64
4422 : AMDGPU::V_FMA_F16_gfx9_fake16_e64
4423 : AMDGPU::V_FMA_F16_gfx9_e64;
4424 case AMDGPU::V_FMAC_F32_e32:
4425 case AMDGPU::V_FMAC_F32_e64:
4426 return AMDGPU::V_FMA_F32_e64;
4427 case AMDGPU::V_FMAC_F64_e32:
4428 case AMDGPU::V_FMAC_F64_e64:
4429 return AMDGPU::V_FMA_F64_e64;
4448 if (
MI.isBundle()) {
4451 if (
MI.getBundleSize() != 1)
4453 CandidateMI =
MI.getNextNode();
4457 MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
4461 if (
MI.isBundle()) {
4466 MI.untieRegOperand(MO.getOperandNo());
4473 if (Def.isEarlyClobber() && Def.isReg() &&
4478 auto UpdateDefIndex = [&](
LiveRange &LR) {
4479 auto *S = LR.find(OldIndex);
4480 if (S != LR.end() && S->start == OldIndex) {
4481 assert(S->valno && S->valno->def == OldIndex);
4482 S->start = NewIndex;
4483 S->valno->def = NewIndex;
4487 for (
auto &SR : LI.subranges())
4497 "expected a tied def in the two-address form");
4502 SlotIndex OldEnd = Idx.getRegSlot(
true);
4504 auto UpdateUseIndex = [&](
LiveRange &LR) {
4506 if (S && S->
end == OldEnd)
4517 if (U.RemoveMIUse) {
4520 Register DefReg = U.RemoveMIUse->getOperand(0).getReg();
4522 if (
MRI.hasOneNonDBGUse(DefReg)) {
4524 U.RemoveMIUse->setDesc(
get(AMDGPU::IMPLICIT_DEF));
4525 U.RemoveMIUse->getOperand(0).setIsDead(
true);
4526 for (
unsigned I = U.RemoveMIUse->getNumOperands() - 1;
I != 0; --
I)
4527 U.RemoveMIUse->removeOperand(
I);
4530 if (
MI.isBundle()) {
4534 if (MO.isReg() && MO.getReg() == DefReg) {
4535 assert(MO.getSubReg() == 0 &&
4536 "tied sub-registers in bundles currently not supported");
4537 MI.removeOperand(MO.getOperandNo());
4552 Register DummyReg =
MRI.cloneVirtualRegister(DefReg);
4554 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4555 MIOp.setIsUndef(
true);
4556 MIOp.setReg(DummyReg);
4560 if (
MI.isBundle()) {
4564 if (MIOp.isReg() && MIOp.getReg() == DefReg) {
4565 MIOp.setIsUndef(
true);
4566 MIOp.setReg(DummyReg);
4579 return MI.isBundle() ? &
MI : NewMI;
4584 ThreeAddressUpdates &U)
const {
4586 unsigned Opc =
MI.getOpcode();
4590 if (NewMFMAOpc != -1) {
4593 for (
unsigned I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I)
4594 MIB.
add(
MI.getOperand(
I));
4602 for (
unsigned I = 0,
E =
MI.getNumExplicitOperands();
I !=
E; ++
I)
4607 assert(
Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
4608 Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
4609 "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
4613 bool IsF64 =
Opc == AMDGPU::V_FMAC_F64_e32 ||
Opc == AMDGPU::V_FMAC_F64_e64;
4614 bool IsLegacy =
Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
4615 Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
4616 Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
4617 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
4618 bool Src0Literal =
false;
4623 case AMDGPU::V_MAC_F16_e64:
4624 case AMDGPU::V_FMAC_F16_e64:
4625 case AMDGPU::V_FMAC_F16_t16_e64:
4626 case AMDGPU::V_FMAC_F16_fake16_e64:
4627 case AMDGPU::V_MAC_F32_e64:
4628 case AMDGPU::V_MAC_LEGACY_F32_e64:
4629 case AMDGPU::V_FMAC_F32_e64:
4630 case AMDGPU::V_FMAC_LEGACY_F32_e64:
4631 case AMDGPU::V_FMAC_F64_e64:
4633 case AMDGPU::V_MAC_F16_e32:
4634 case AMDGPU::V_FMAC_F16_e32:
4635 case AMDGPU::V_MAC_F32_e32:
4636 case AMDGPU::V_MAC_LEGACY_F32_e32:
4637 case AMDGPU::V_FMAC_F32_e32:
4638 case AMDGPU::V_FMAC_LEGACY_F32_e32:
4639 case AMDGPU::V_FMAC_F64_e32: {
4640 int Src0Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
4641 AMDGPU::OpName::src0);
4642 const MachineOperand *
Src0 = &
MI.getOperand(Src0Idx);
4643 if (!
Src0->isReg() && !
Src0->isImm())
4653 MachineInstrBuilder MIB;
4656 const MachineOperand *Src0Mods =
4659 const MachineOperand *Src1Mods =
4662 const MachineOperand *Src2Mods =
4668 if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
4669 (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
4671 (ST.getConstantBusLimit(
Opc) > 1 || !
Src0->isReg() ||
4673 MachineInstr *
DefMI =
nullptr;
4675 std::optional<int64_t> ImmOpt;
4710 MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
4726 if (Src0Literal && !ST.hasVOP3Literal())
4754 switch (
MI.getOpcode()) {
4755 case AMDGPU::S_SET_GPR_IDX_ON:
4756 case AMDGPU::S_SET_GPR_IDX_MODE:
4757 case AMDGPU::S_SET_GPR_IDX_OFF:
4775 if (
MI.isTerminator() ||
MI.isPosition())
4779 if (
MI.getOpcode() == TargetOpcode::INLINEASM_BR)
4782 if (
MI.getOpcode() == AMDGPU::SCHED_BARRIER &&
MI.getOperand(0).getImm() == 0)
4788 return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
4789 MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
4790 MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
4791 MI.getOpcode() == AMDGPU::S_SETPRIO ||
4792 MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
4797 return Opcode == AMDGPU::DS_ORDERED_COUNT ||
4798 Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
4799 Opcode == AMDGPU::DS_SUB_GS_REG_RTN ||
isGWS(Opcode);
4813 if (
MI.getMF()->getFunction().hasFnAttribute(
"amdgpu-no-flat-scratch-init"))
4818 if (
MI.memoperands_empty())
4823 unsigned AS = Memop->getAddrSpace();
4824 if (AS == AMDGPUAS::FLAT_ADDRESS) {
4825 const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
4826 return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
4827 *MD, AMDGPUAS::PRIVATE_ADDRESS);
4842 if (
MI.memoperands_empty())
4851 unsigned AS = Memop->getAddrSpace();
4861 bool TgSplit)
const {
4874 if (
MI.memoperands_empty())
4879 unsigned AS = Memop->getAddrSpace();
4897 switch (
MI.getOpcode()) {
4899 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B8:
4900 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B8_SADDR:
4901 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B32:
4902 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B32_SADDR:
4903 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B64:
4904 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B64_SADDR:
4905 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B128:
4906 case AMDGPU::GLOBAL_LOAD_ASYNC_TO_LDS_B128_SADDR:
4908 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B8:
4909 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B8_SADDR:
4910 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B32:
4911 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B32_SADDR:
4912 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B64:
4913 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B64_SADDR:
4914 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B128:
4915 case AMDGPU::CLUSTER_LOAD_ASYNC_TO_LDS_B128_SADDR:
4917 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B8:
4918 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B8_SADDR:
4919 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B32:
4920 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B32_SADDR:
4921 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B64:
4922 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B64_SADDR:
4923 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B128:
4924 case AMDGPU::GLOBAL_STORE_ASYNC_FROM_LDS_B128_SADDR:
4939 unsigned Opcode =
MI.getOpcode();
4954 if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
4955 isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
4956 Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
4957 Opcode == AMDGPU::S_SETHALT)
4960 if (
MI.isCall() ||
MI.isInlineAsm())
4966 if (ST.hasVPermPk16Hazard() &&
isVPermPk16(Opcode))
4982 if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
4983 Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
4984 Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
4985 Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
4993 if (
MI.isMetaInstruction())
4997 if (
MI.isCopyLike()) {
4998 if (!RI.isSGPRReg(
MRI,
MI.getOperand(0).getReg()))
5002 return MI.readsRegister(AMDGPU::EXEC, &RI);
5013 return !
isSALU(
MI) ||
MI.readsRegister(AMDGPU::EXEC, &RI);
5017 switch (
Imm.getBitWidth()) {
5023 ST.hasInv2PiInlineImm());
5026 ST.hasInv2PiInlineImm());
5028 return ST.has16BitInsts() &&
5030 ST.hasInv2PiInlineImm());
5037 APInt IntImm =
Imm.bitcastToAPInt();
5039 bool HasInv2Pi = ST.hasInv2PiInlineImm();
5047 return ST.has16BitInsts() &&
5050 return ST.has16BitInsts() &&
5060 switch (OperandType) {
5070 int32_t Trunc =
static_cast<int32_t
>(
Imm);
5114 int16_t Trunc =
static_cast<int16_t
>(
Imm);
5115 return ST.has16BitInsts() &&
5124 int16_t Trunc =
static_cast<int16_t
>(
Imm);
5125 return ST.has16BitInsts() &&
5177 if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
5183 return ST.hasVOP3Literal();
5187 int64_t ImmVal)
const {
5189 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
5190 if (Src1Idx != -1 &&
isDPP(
Opc) && !ST.hasDPPSrc1SGPR() &&
5191 OpNo ==
static_cast<unsigned>(Src1Idx))
5196 if (
isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
5197 OpNo == (
unsigned)AMDGPU::getNamedOperandIdx(InstDesc.
getOpcode(),
5198 AMDGPU::OpName::src2))
5201 if (ST.hasBF16InlineConstFromUpperFP32() &&
isVOP1(
Opc)) {
5208 return RI.opCanUseInlineConstant(OpInfo.OperandType);
5220 "unexpected imm-like operand kind");
5233 if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
5253 return Op32 != -1 &&
TII.isVOPC(Op32);
5258 unsigned Depth)
const {
5259 assert(
MRI.isSSA() &&
"isMaskedByExec requires SSA form");
5268 constexpr unsigned MaxDepth = 6;
5269 if (
Depth >= MaxDepth || !Reg.isVirtual())
5275 if (!Def || Def->getParent() !=
MBB)
5283 auto Recurse = [&](
unsigned OpIdx) {
5289 unsigned Opc = Def->getOpcode();
5290 if (
Opc == AMDGPU::COPY && Recurse(1))
5292 if (
Opc == LMC.
AndOpc && (Recurse(1) || Recurse(2)))
5312 AMDGPU::OpName
OpName)
const {
5314 return Mods && Mods->
getImm();
5327 switch (
MI.getOpcode()) {
5328 default:
return false;
5330 case AMDGPU::V_ADDC_U32_e64:
5331 case AMDGPU::V_SUBB_U32_e64:
5332 case AMDGPU::V_SUBBREV_U32_e64: {
5335 if (!Src1->isReg() || !RI.isVGPR(
MRI, Src1->getReg()))
5340 case AMDGPU::V_MAC_F16_e64:
5341 case AMDGPU::V_MAC_F32_e64:
5342 case AMDGPU::V_MAC_LEGACY_F32_e64:
5343 case AMDGPU::V_FMAC_F16_e64:
5344 case AMDGPU::V_FMAC_F16_t16_e64:
5345 case AMDGPU::V_FMAC_F16_fake16_e64:
5346 case AMDGPU::V_FMAC_F32_e64:
5347 case AMDGPU::V_FMAC_F64_e64:
5348 case AMDGPU::V_FMAC_LEGACY_F32_e64:
5349 if (!Src2->isReg() || !RI.isVGPR(
MRI, Src2->getReg()) ||
5354 case AMDGPU::V_CNDMASK_B32_e64:
5360 if (Src1 && (!Src1->isReg() || !RI.isVGPR(
MRI, Src1->getReg()) ||
5373 if (Src0 && Src0->isImm()) {
5376 get(Op32), AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src0),
5398 (
Use.getReg() == AMDGPU::VCC ||
Use.getReg() == AMDGPU::VCC_LO)) {
5407 unsigned Op32)
const {
5421 Inst32.
add(
MI.getOperand(
I));
5425 int Idx =
MI.getNumExplicitDefs();
5427 int OpTy =
MI.getDesc().operands()[Idx++].OperandType;
5432 if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
5452 if (OldSDst && OldSDst->
isDead()) {
5455 NewVCC->setIsDead();
5464 if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
5472 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
5475 return AMDGPU::SReg_32RegClass.contains(Reg) ||
5476 AMDGPU::SReg_64RegClass.contains(Reg);
5482 return Reg.
isVirtual() ? RI.isSGPRClass(
MRI.getRegClass(Reg))
5494 return Reg.
isVirtual() ? RI.isSGPRClass(
MRI.getRegClass(Reg))
5504 switch (MO.getReg()) {
5506 case AMDGPU::VCC_LO:
5507 case AMDGPU::VCC_HI:
5509 case AMDGPU::FLAT_SCR:
5522 switch (
MI.getOpcode()) {
5523 case AMDGPU::V_READLANE_B32:
5524 case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
5525 case AMDGPU::V_WRITELANE_B32:
5526 case AMDGPU::SI_SPILL_S32_TO_VGPR:
5533 if (
MI.isPreISelOpcode() ||
5534 SIInstrInfo::isGenericOpcode(
MI.getOpcode()) ||
5552 return SubReg.
getSubReg() != AMDGPU::NoSubRegister &&
5563 if (RI.isVectorRegister(
MRI, SrcReg) && RI.isSGPRReg(
MRI, DstReg)) {
5564 ErrInfo =
"illegal copy from vector register to SGPR";
5582 if (!
MRI.isSSA() &&
MI.isCopy())
5583 return verifyCopy(
MI,
MRI, ErrInfo);
5585 if (SIInstrInfo::isGenericOpcode(Opcode))
5588 int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
5589 int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
5590 int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
5592 if (Src0Idx == -1) {
5594 Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
5595 Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
5596 Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
5597 Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
5602 if (!
Desc.isVariadic() &&
5603 Desc.getNumOperands() !=
MI.getNumExplicitOperands()) {
5604 ErrInfo =
"Instruction has wrong number of operands.";
5608 if (
MI.isInlineAsm()) {
5621 if (!Reg.isVirtual() && !RC->
contains(Reg)) {
5622 ErrInfo =
"inlineasm operand has incorrect register class.";
5630 if (
isImage(
MI) &&
MI.memoperands_empty() &&
MI.mayLoadOrStore()) {
5631 ErrInfo =
"missing memory operand from image instruction.";
5636 for (
int i = 0, e =
Desc.getNumOperands(); i != e; ++i) {
5639 ErrInfo =
"FPImm Machine Operands are not supported. ISel should bitcast "
5640 "all fp values to integers.";
5646 switch (OpInfo.OperandType) {
5648 if (
MI.getOperand(i).isImm() ||
MI.getOperand(i).isGlobal()) {
5649 ErrInfo =
"Illegal immediate value for operand.";
5681 ErrInfo =
"Illegal immediate value for operand.";
5690 if (ST.has64BitLiterals() &&
Desc.getSize() != 4 && MO.
isImm() &&
5693 OpInfo.OperandType ==
5695 ErrInfo =
"illegal 64-bit immediate value for operand.";
5702 ErrInfo =
"Expected inline constant for operand.";
5716 if (!
MI.getOperand(i).isImm() && !
MI.getOperand(i).isFI()) {
5717 ErrInfo =
"Expected immediate, but got non-immediate";
5726 if (OpInfo.isGenericType())
5734 if (!ST.hasSDWA()) {
5735 ErrInfo =
"SDWA is not supported on this target";
5739 for (
auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
5740 AMDGPU::OpName::dst_sel}) {
5746 ErrInfo =
"Invalid SDWA selection";
5751 int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
5753 for (
int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
5758 if (!ST.hasSDWAScalar()) {
5760 if (!MO.
isReg() || !RI.hasVGPRs(RI.getRegClassForReg(
MRI, MO.
getReg()))) {
5761 ErrInfo =
"Only VGPRs allowed as operands in SDWA instructions on VI";
5768 "Only reg allowed as operands in SDWA instructions on GFX9+";
5774 if (!ST.hasSDWAOmod()) {
5777 if (OMod !=
nullptr &&
5779 ErrInfo =
"OMod not allowed in SDWA instructions on VI";
5784 if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
5785 Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
5786 Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
5787 Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
5790 unsigned Mods = Src0ModsMO->
getImm();
5793 ErrInfo =
"sext, abs and neg are not allowed on this instruction";
5799 if (
isVOPC(BasicOpcode)) {
5800 if (!ST.hasSDWASdst() && DstIdx != -1) {
5803 if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
5804 ErrInfo =
"Only VCC allowed as dst in SDWA instructions on VI";
5807 }
else if (!ST.hasSDWAOutModsVOPC()) {
5810 if (Clamp && (!Clamp->
isImm() || Clamp->
getImm() != 0)) {
5811 ErrInfo =
"Clamp not allowed in VOPC SDWA instructions on VI";
5817 if (OMod && (!OMod->
isImm() || OMod->
getImm() != 0)) {
5818 ErrInfo =
"OMod not allowed in VOPC SDWA instructions on VI";
5825 if (DstUnused && DstUnused->isImm() &&
5828 if (!Dst.isReg() || !Dst.isTied()) {
5829 ErrInfo =
"Dst register should have tied register";
5834 MI.getOperand(
MI.findTiedOperandIdx(DstIdx));
5837 "Dst register should be tied to implicit use of preserved register";
5841 ErrInfo =
"Dst register should use same physical register as preserved";
5847 if (
isDPP(
MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
5850 ErrInfo =
"DPP src1 cannot be SGPR on this subtarget";
5853 if (Src1MO.
isImm()) {
5854 ErrInfo =
"DPP src1 cannot be an immediate on this subtarget";
5860 if (
isImage(Opcode) && !
MI.mayStore()) {
5865 uint64_t DMaskImm = DMask->
getImm();
5872 if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
5880 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
5884 uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
5885 if (RegCount > DstSize) {
5886 ErrInfo =
"Image instruction returns too many registers for dst "
5896 Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
5897 unsigned ConstantBusCount = 0;
5898 bool UsesLiteral =
false;
5901 int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
5905 LiteralVal = &
MI.getOperand(ImmIdx);
5914 for (
int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
5925 }
else if (!MO.
isFI()) {
5932 ErrInfo =
"VOP2/VOP3 instruction uses more than one literal";
5942 if (
llvm::all_of(SGPRsUsed, [
this, SGPRUsed](
unsigned SGPR) {
5943 return !RI.regsOverlap(SGPRUsed, SGPR);
5952 if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
5953 Opcode != AMDGPU::V_WRITELANE_B32) {
5954 ErrInfo =
"VOP* instruction violates constant bus restriction";
5958 if (
isVOP3(
MI) && UsesLiteral && !ST.hasVOP3Literal()) {
5959 ErrInfo =
"VOP3 instruction uses literal";
5966 if (
Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
5967 unsigned SGPRCount = 0;
5970 for (
int OpIdx : {Src0Idx, Src1Idx}) {
5978 if (MO.
getReg() != SGPRUsed)
5983 if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
5984 ErrInfo =
"WRITELANE instruction violates constant bus restriction";
5990 if (Opcode == AMDGPU::ASYNCMARK || Opcode == AMDGPU::WAIT_ASYNCMARK) {
5991 int64_t Mask =
MI.getOperand(
MI.getNumExplicitOperands() - 1).getImm();
5993 ErrInfo =
"invalid asyncmark stage mask";
5999 if (
Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
6000 Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
6004 if (Src0.isReg() && Src1.isReg() && Src2.isReg()) {
6007 ErrInfo =
"v_div_scale_{f32|f64} require src0 = src1 or src2";
6017 ErrInfo =
"ABS not allowed in VOP3B instructions";
6029 !Src0.isIdenticalTo(Src1)) {
6030 ErrInfo =
"SOP2/SOPC instruction requires too many immediate constants";
6037 if (
Desc.isBranch()) {
6039 ErrInfo =
"invalid branch target for SOPK instruction";
6043 uint64_t
Imm =
Op->getImm();
6046 ErrInfo =
"invalid immediate for SOPK instruction";
6051 ErrInfo =
"invalid immediate for SOPK instruction";
6058 if (
Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
6059 Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
6060 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
6061 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
6062 const bool IsDst =
Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
6063 Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;
6065 const unsigned StaticNumOps =
6066 Desc.getNumOperands() +
Desc.implicit_uses().size();
6067 const unsigned NumImplicitOps = IsDst ? 2 : 1;
6073 if (
MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
6074 ErrInfo =
"missing implicit register operands";
6080 if (!Dst->isUse()) {
6081 ErrInfo =
"v_movreld_b32 vdst should be a use operand";
6086 if (!
MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
6087 UseOpIdx != StaticNumOps + 1) {
6088 ErrInfo =
"movrel implicit operands should be tied";
6095 =
MI.getOperand(StaticNumOps + NumImplicitOps - 1);
6097 !
isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
6098 ErrInfo =
"src0 should be subreg of implicit vector use";
6106 if (!
MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
6107 ErrInfo =
"VALU instruction does not implicitly read exec mask";
6113 if (
MI.mayStore() &&
6118 if (Soff && Soff->
getReg() != AMDGPU::M0) {
6119 ErrInfo =
"scalar stores must use m0 as offset register";
6125 if (
isFLAT(
MI) && !ST.hasFlatInstOffsets()) {
6127 if (
Offset->getImm() != 0) {
6128 ErrInfo =
"subtarget does not support offsets in flat instructions";
6133 if (
isDS(
MI) && !ST.hasGDS()) {
6135 if (GDSOp && GDSOp->
getImm() != 0) {
6136 ErrInfo =
"GDS is not supported on this subtarget";
6144 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
6145 AMDGPU::OpName::vaddr0);
6146 AMDGPU::OpName RSrcOpName =
6147 isMIMG(
MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
6148 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
6156 ErrInfo =
"dim is out of range";
6161 if (ST.hasR128A16()) {
6163 IsA16 = R128A16->
getImm() != 0;
6164 }
else if (ST.hasA16()) {
6166 IsA16 = A16->
getImm() != 0;
6169 bool IsNSA = RsrcIdx - VAddr0Idx > 1;
6171 unsigned AddrWords =
6174 unsigned VAddrWords;
6176 VAddrWords = RsrcIdx - VAddr0Idx;
6177 if (ST.hasPartialNSAEncoding() &&
6179 unsigned LastVAddrIdx = RsrcIdx - 1;
6180 VAddrWords +=
getOpSize(
MI, LastVAddrIdx) / 4 - 1;
6188 if (VAddrWords != AddrWords) {
6190 <<
" but got " << VAddrWords <<
"\n");
6191 ErrInfo =
"bad vaddr size";
6201 unsigned DC = DppCt->
getImm();
6202 if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
6203 DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
6204 (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
6205 (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
6206 (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
6207 (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
6208 (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
6209 ErrInfo =
"Invalid dpp_ctrl value";
6212 if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
6213 !ST.hasDPPWavefrontShifts()) {
6214 ErrInfo =
"Invalid dpp_ctrl value: "
6215 "wavefront shifts are not supported on GFX10+";
6218 if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
6219 !ST.hasDPPBroadcasts()) {
6220 ErrInfo =
"Invalid dpp_ctrl value: "
6221 "broadcasts are not supported on GFX10+";
6224 if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
6226 if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
6227 DC <= DppCtrl::ROW_NEWBCAST_LAST &&
6228 !ST.hasGFX90AInsts()) {
6229 ErrInfo =
"Invalid dpp_ctrl value: "
6230 "row_newbroadcast/row_share is not supported before "
6234 if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
6235 ErrInfo =
"Invalid dpp_ctrl value: "
6236 "row_share and row_xmask are not supported before GFX10";
6241 if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
6243 ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
6245 ErrInfo =
"Invalid dpp_ctrl value: "
6246 "DP ALU dpp only support row_newbcast";
6253 AMDGPU::OpName DataName =
6254 isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
6260 if (!ST.hasGFX90AInsts()) {
6261 if ((Dst && RI.isAGPR(
MRI, Dst->getReg())) ||
6263 (Data2 && RI.isAGPR(
MRI, Data2->
getReg()))) {
6264 ErrInfo =
"Invalid register class: "
6265 "agpr loads and stores not supported on this GPU";
6271 if (ST.needsAlignedVGPRs()) {
6272 const auto isAlignedReg = [&
MI, &
MRI,
this](AMDGPU::OpName
OpName) ->
bool {
6277 if (Reg.isPhysical())
6278 return !(RI.getHWRegIndex(Reg) & 1);
6280 return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
6281 !(RI.getChannelFromSubReg(
Op->getSubReg()) & 1);
6285 if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
6286 ErrInfo =
"Subtarget requires even aligned vector registers "
6287 "for vaddr operand of image instructions";
6293 if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
6295 if (Src->isReg() && RI.isSGPRReg(
MRI, Src->getReg())) {
6296 ErrInfo =
"Invalid register class: "
6297 "v_accvgpr_write with an SGPR is not supported on this GPU";
6302 if (
Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
6305 ErrInfo =
"pseudo expects only physical SGPRs";
6312 if (!ST.hasScaleOffset()) {
6313 ErrInfo =
"Subtarget does not support offset scaling";
6317 ErrInfo =
"Instruction does not support offset scaling";
6325 for (
unsigned I = 0;
I < 3; ++
I) {
6331 if (ST.hasFlatScratchHiInB64InstHazard() &&
isSALU(
MI) &&
6332 MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI,
nullptr)) {
6334 if ((Dst && RI.getRegClassForReg(
MRI, Dst->getReg()) ==
6335 &AMDGPU::SReg_64RegClass) ||
6336 Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
6337 ErrInfo =
"Instruction cannot read flat_scratch_base_hi";
6344 ErrInfo =
"GFX950 v_pk_{add,mul,fma}_f32 has an invalid op_sel.";
6352 if (
MI.getOpcode() == AMDGPU::S_MOV_B32) {
6354 return MI.getOperand(1).isReg() || RI.isAGPR(
MRI,
MI.getOperand(0).getReg())
6356 : AMDGPU::V_MOV_B32_e32;
6366 default:
return AMDGPU::INSTRUCTION_LIST_END;
6367 case AMDGPU::REG_SEQUENCE:
return AMDGPU::REG_SEQUENCE;
6368 case AMDGPU::COPY:
return AMDGPU::COPY;
6369 case AMDGPU::PHI:
return AMDGPU::PHI;
6370 case AMDGPU::INSERT_SUBREG:
return AMDGPU::INSERT_SUBREG;
6371 case AMDGPU::WQM:
return AMDGPU::WQM;
6372 case AMDGPU::SOFT_WQM:
return AMDGPU::SOFT_WQM;
6373 case AMDGPU::STRICT_WWM:
return AMDGPU::STRICT_WWM;
6374 case AMDGPU::STRICT_WQM:
return AMDGPU::STRICT_WQM;
6375 case AMDGPU::S_ADD_I32:
6376 return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
6377 case AMDGPU::S_ADDC_U32:
6378 return AMDGPU::V_ADDC_U32_e32;
6379 case AMDGPU::S_SUB_I32:
6380 return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
6383 case AMDGPU::S_ADD_U32:
6384 return AMDGPU::V_ADD_CO_U32_e32;
6385 case AMDGPU::S_SUB_U32:
6386 return AMDGPU::V_SUB_CO_U32_e32;
6387 case AMDGPU::S_ADD_U64_PSEUDO:
6388 return AMDGPU::V_ADD_U64_PSEUDO;
6389 case AMDGPU::S_SUB_U64_PSEUDO:
6390 return AMDGPU::V_SUB_U64_PSEUDO;
6391 case AMDGPU::S_SUBB_U32:
return AMDGPU::V_SUBB_U32_e32;
6392 case AMDGPU::S_MUL_I32:
return AMDGPU::V_MUL_LO_U32_e64;
6393 case AMDGPU::S_MUL_HI_U32:
return AMDGPU::V_MUL_HI_U32_e64;
6394 case AMDGPU::S_MUL_HI_I32:
return AMDGPU::V_MUL_HI_I32_e64;
6395 case AMDGPU::S_AND_B32:
return AMDGPU::V_AND_B32_e64;
6396 case AMDGPU::S_OR_B32:
return AMDGPU::V_OR_B32_e64;
6397 case AMDGPU::S_XOR_B32:
return AMDGPU::V_XOR_B32_e64;
6398 case AMDGPU::S_XNOR_B32:
6399 return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
6400 case AMDGPU::S_MIN_I32:
return AMDGPU::V_MIN_I32_e64;
6401 case AMDGPU::S_MIN_U32:
return AMDGPU::V_MIN_U32_e64;
6402 case AMDGPU::S_MAX_I32:
return AMDGPU::V_MAX_I32_e64;
6403 case AMDGPU::S_MAX_U32:
return AMDGPU::V_MAX_U32_e64;
6404 case AMDGPU::S_ASHR_I32:
return AMDGPU::V_ASHR_I32_e32;
6405 case AMDGPU::S_ASHR_I64:
return AMDGPU::V_ASHR_I64_e64;
6406 case AMDGPU::S_LSHL_B32:
return AMDGPU::V_LSHL_B32_e32;
6407 case AMDGPU::S_LSHL_B64:
return AMDGPU::V_LSHL_B64_e64;
6408 case AMDGPU::S_LSHR_B32:
return AMDGPU::V_LSHR_B32_e32;
6409 case AMDGPU::S_LSHR_B64:
return AMDGPU::V_LSHR_B64_e64;
6410 case AMDGPU::S_SEXT_I32_I8:
return AMDGPU::V_BFE_I32_e64;
6411 case AMDGPU::S_SEXT_I32_I16:
return AMDGPU::V_BFE_I32_e64;
6412 case AMDGPU::S_BFE_U32:
return AMDGPU::V_BFE_U32_e64;
6413 case AMDGPU::S_BFE_I32:
return AMDGPU::V_BFE_I32_e64;
6414 case AMDGPU::S_BFM_B32:
return AMDGPU::V_BFM_B32_e64;
6415 case AMDGPU::S_BREV_B32:
return AMDGPU::V_BFREV_B32_e32;
6416 case AMDGPU::S_NOT_B32:
return AMDGPU::V_NOT_B32_e32;
6417 case AMDGPU::S_NOT_B64:
return AMDGPU::V_NOT_B32_e32;
6418 case AMDGPU::S_CMP_EQ_I32:
return AMDGPU::V_CMP_EQ_I32_e64;
6419 case AMDGPU::S_CMP_LG_I32:
return AMDGPU::V_CMP_NE_I32_e64;
6420 case AMDGPU::S_CMP_GT_I32:
return AMDGPU::V_CMP_GT_I32_e64;
6421 case AMDGPU::S_CMP_GE_I32:
return AMDGPU::V_CMP_GE_I32_e64;
6422 case AMDGPU::S_CMP_LT_I32:
return AMDGPU::V_CMP_LT_I32_e64;
6423 case AMDGPU::S_CMP_LE_I32:
return AMDGPU::V_CMP_LE_I32_e64;
6424 case AMDGPU::S_CMP_EQ_U32:
return AMDGPU::V_CMP_EQ_U32_e64;
6425 case AMDGPU::S_CMP_LG_U32:
return AMDGPU::V_CMP_NE_U32_e64;
6426 case AMDGPU::S_CMP_GT_U32:
return AMDGPU::V_CMP_GT_U32_e64;
6427 case AMDGPU::S_CMP_GE_U32:
return AMDGPU::V_CMP_GE_U32_e64;
6428 case AMDGPU::S_CMP_LT_U32:
return AMDGPU::V_CMP_LT_U32_e64;
6429 case AMDGPU::S_CMP_LE_U32:
return AMDGPU::V_CMP_LE_U32_e64;
6430 case AMDGPU::S_CMP_EQ_U64:
return AMDGPU::V_CMP_EQ_U64_e64;
6431 case AMDGPU::S_CMP_LG_U64:
return AMDGPU::V_CMP_NE_U64_e64;
6432 case AMDGPU::S_BCNT1_I32_B32:
return AMDGPU::V_BCNT_U32_B32_e64;
6433 case AMDGPU::S_FF1_I32_B32:
return AMDGPU::V_FFBL_B32_e32;
6434 case AMDGPU::S_FLBIT_I32_B32:
return AMDGPU::V_FFBH_U32_e32;
6435 case AMDGPU::S_FLBIT_I32:
return AMDGPU::V_FFBH_I32_e64;
6436 case AMDGPU::S_CBRANCH_SCC0:
return AMDGPU::S_CBRANCH_VCCZ;
6437 case AMDGPU::S_CBRANCH_SCC1:
return AMDGPU::S_CBRANCH_VCCNZ;
6438 case AMDGPU::S_CVT_F32_I32:
return AMDGPU::V_CVT_F32_I32_e64;
6439 case AMDGPU::S_CVT_F32_U32:
return AMDGPU::V_CVT_F32_U32_e64;
6440 case AMDGPU::S_CVT_I32_F32:
return AMDGPU::V_CVT_I32_F32_e64;
6441 case AMDGPU::S_CVT_U32_F32:
return AMDGPU::V_CVT_U32_F32_e64;
6442 case AMDGPU::S_CVT_F32_F16:
6443 case AMDGPU::S_CVT_HI_F32_F16:
6444 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
6445 : AMDGPU::V_CVT_F32_F16_fake16_e64;
6446 case AMDGPU::S_CVT_F16_F32:
6447 return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
6448 : AMDGPU::V_CVT_F16_F32_fake16_e64;
6449 case AMDGPU::S_CEIL_F32:
return AMDGPU::V_CEIL_F32_e64;
6450 case AMDGPU::S_FLOOR_F32:
return AMDGPU::V_FLOOR_F32_e64;
6451 case AMDGPU::S_TRUNC_F32:
return AMDGPU::V_TRUNC_F32_e64;
6452 case AMDGPU::S_RNDNE_F32:
return AMDGPU::V_RNDNE_F32_e64;
6453 case AMDGPU::S_CEIL_F16:
6454 return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
6455 : AMDGPU::V_CEIL_F16_fake16_e64;
6456 case AMDGPU::S_FLOOR_F16:
6457 return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
6458 : AMDGPU::V_FLOOR_F16_fake16_e64;
6459 case AMDGPU::S_TRUNC_F16:
6460 return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
6461 : AMDGPU::V_TRUNC_F16_fake16_e64;
6462 case AMDGPU::S_RNDNE_F16:
6463 return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
6464 : AMDGPU::V_RNDNE_F16_fake16_e64;
6465 case AMDGPU::S_ADD_F32:
return AMDGPU::V_ADD_F32_e64;
6466 case AMDGPU::S_SUB_F32:
return AMDGPU::V_SUB_F32_e64;
6467 case AMDGPU::S_MIN_F32:
return AMDGPU::V_MIN_F32_e64;
6468 case AMDGPU::S_MAX_F32:
return AMDGPU::V_MAX_F32_e64;
6469 case AMDGPU::S_MINIMUM_F32:
return AMDGPU::V_MINIMUM_F32_e64;
6470 case AMDGPU::S_MAXIMUM_F32:
return AMDGPU::V_MAXIMUM_F32_e64;
6471 case AMDGPU::S_MUL_F32:
return AMDGPU::V_MUL_F32_e64;
6472 case AMDGPU::S_ADD_F16:
6473 return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
6474 : AMDGPU::V_ADD_F16_fake16_e64;
6475 case AMDGPU::S_SUB_F16:
6476 return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
6477 : AMDGPU::V_SUB_F16_fake16_e64;
6478 case AMDGPU::S_MIN_F16:
6479 return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
6480 : AMDGPU::V_MIN_F16_fake16_e64;
6481 case AMDGPU::S_MAX_F16:
6482 return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
6483 : AMDGPU::V_MAX_F16_fake16_e64;
6484 case AMDGPU::S_MINIMUM_F16:
6485 return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
6486 : AMDGPU::V_MINIMUM_F16_fake16_e64;
6487 case AMDGPU::S_MAXIMUM_F16:
6488 return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
6489 : AMDGPU::V_MAXIMUM_F16_fake16_e64;
6490 case AMDGPU::S_MUL_F16:
6491 return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
6492 : AMDGPU::V_MUL_F16_fake16_e64;
6493 case AMDGPU::S_CVT_PK_RTZ_F16_F32:
return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
6494 case AMDGPU::S_FMAC_F32:
return AMDGPU::V_FMAC_F32_e64;
6495 case AMDGPU::S_FMAC_F16:
6496 return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
6497 : AMDGPU::V_FMAC_F16_fake16_e64;
6498 case AMDGPU::S_FMAMK_F32:
return AMDGPU::V_FMAMK_F32;
6499 case AMDGPU::S_FMAAK_F32:
return AMDGPU::V_FMAAK_F32;
6500 case AMDGPU::S_CMP_LT_F32:
return AMDGPU::V_CMP_LT_F32_e64;
6501 case AMDGPU::S_CMP_EQ_F32:
return AMDGPU::V_CMP_EQ_F32_e64;
6502 case AMDGPU::S_CMP_LE_F32:
return AMDGPU::V_CMP_LE_F32_e64;
6503 case AMDGPU::S_CMP_GT_F32:
return AMDGPU::V_CMP_GT_F32_e64;
6504 case AMDGPU::S_CMP_LG_F32:
return AMDGPU::V_CMP_LG_F32_e64;
6505 case AMDGPU::S_CMP_GE_F32:
return AMDGPU::V_CMP_GE_F32_e64;
6506 case AMDGPU::S_CMP_O_F32:
return AMDGPU::V_CMP_O_F32_e64;
6507 case AMDGPU::S_CMP_U_F32:
return AMDGPU::V_CMP_U_F32_e64;
6508 case AMDGPU::S_CMP_NGE_F32:
return AMDGPU::V_CMP_NGE_F32_e64;
6509 case AMDGPU::S_CMP_NLG_F32:
return AMDGPU::V_CMP_NLG_F32_e64;
6510 case AMDGPU::S_CMP_NGT_F32:
return AMDGPU::V_CMP_NGT_F32_e64;
6511 case AMDGPU::S_CMP_NLE_F32:
return AMDGPU::V_CMP_NLE_F32_e64;
6512 case AMDGPU::S_CMP_NEQ_F32:
return AMDGPU::V_CMP_NEQ_F32_e64;
6513 case AMDGPU::S_CMP_NLT_F32:
return AMDGPU::V_CMP_NLT_F32_e64;
6514 case AMDGPU::S_CMP_LT_F16:
6515 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
6516 : AMDGPU::V_CMP_LT_F16_fake16_e64;
6517 case AMDGPU::S_CMP_EQ_F16:
6518 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
6519 : AMDGPU::V_CMP_EQ_F16_fake16_e64;
6520 case AMDGPU::S_CMP_LE_F16:
6521 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
6522 : AMDGPU::V_CMP_LE_F16_fake16_e64;
6523 case AMDGPU::S_CMP_GT_F16:
6524 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
6525 : AMDGPU::V_CMP_GT_F16_fake16_e64;
6526 case AMDGPU::S_CMP_LG_F16:
6527 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
6528 : AMDGPU::V_CMP_LG_F16_fake16_e64;
6529 case AMDGPU::S_CMP_GE_F16:
6530 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
6531 : AMDGPU::V_CMP_GE_F16_fake16_e64;
6532 case AMDGPU::S_CMP_O_F16:
6533 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
6534 : AMDGPU::V_CMP_O_F16_fake16_e64;
6535 case AMDGPU::S_CMP_U_F16:
6536 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
6537 : AMDGPU::V_CMP_U_F16_fake16_e64;
6538 case AMDGPU::S_CMP_NGE_F16:
6539 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
6540 : AMDGPU::V_CMP_NGE_F16_fake16_e64;
6541 case AMDGPU::S_CMP_NLG_F16:
6542 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
6543 : AMDGPU::V_CMP_NLG_F16_fake16_e64;
6544 case AMDGPU::S_CMP_NGT_F16:
6545 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
6546 : AMDGPU::V_CMP_NGT_F16_fake16_e64;
6547 case AMDGPU::S_CMP_NLE_F16:
6548 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
6549 : AMDGPU::V_CMP_NLE_F16_fake16_e64;
6550 case AMDGPU::S_CMP_NEQ_F16:
6551 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
6552 : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
6553 case AMDGPU::S_CMP_NLT_F16:
6554 return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
6555 : AMDGPU::V_CMP_NLT_F16_fake16_e64;
6556 case AMDGPU::V_S_EXP_F32_e64:
return AMDGPU::V_EXP_F32_e64;
6557 case AMDGPU::V_S_EXP_F16_e64:
6558 return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
6559 : AMDGPU::V_EXP_F16_fake16_e64;
6560 case AMDGPU::V_S_LOG_F32_e64:
return AMDGPU::V_LOG_F32_e64;
6561 case AMDGPU::V_S_LOG_F16_e64:
6562 return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
6563 : AMDGPU::V_LOG_F16_fake16_e64;
6564 case AMDGPU::V_S_RCP_F32_e64:
return AMDGPU::V_RCP_F32_e64;
6565 case AMDGPU::V_S_RCP_F16_e64:
6566 return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
6567 : AMDGPU::V_RCP_F16_fake16_e64;
6568 case AMDGPU::V_S_RSQ_F32_e64:
return AMDGPU::V_RSQ_F32_e64;
6569 case AMDGPU::V_S_RSQ_F16_e64:
6570 return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
6571 : AMDGPU::V_RSQ_F16_fake16_e64;
6572 case AMDGPU::V_S_SQRT_F32_e64:
return AMDGPU::V_SQRT_F32_e64;
6573 case AMDGPU::V_S_SQRT_F16_e64:
6574 return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
6575 : AMDGPU::V_SQRT_F16_fake16_e64;
6578 "Unexpected scalar opcode without corresponding vector one!");
6627 "Not a whole wave func");
6630 if (
MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
6631 MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
6638 unsigned OpNo)
const {
6640 if (
MI.isVariadic() || OpNo >=
Desc.getNumOperands() ||
6641 Desc.operands()[OpNo].RegClass == -1) {
6644 if (Reg.isVirtual()) {
6646 return MRI.getRegClass(Reg);
6648 return RI.getPhysRegBaseClass(Reg);
6651 int16_t RegClass = getOpRegClassID(
Desc.operands()[OpNo]);
6652 return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
6657 constexpr AMDGPU::OpName OpNames[] = {
6658 AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};
6661 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
I]);
6662 if (
static_cast<unsigned>(SrcIdx) == OpIdx)
6674 unsigned RCID = getOpRegClassID(
get(
MI.getOpcode()).operands()[OpIdx]);
6676 unsigned Size = RI.getRegSizeInBits(*RC);
6677 unsigned Opcode = (
Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
6678 :
Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
6679 : AMDGPU::V_MOV_B32_e32;
6681 Opcode = AMDGPU::COPY;
6682 else if (RI.isSGPRClass(RC))
6683 Opcode = (
Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
6702 Register Low64 =
MRI.createVirtualRegister(VRC64);
6708 .
addImm(AMDGPU::sub0_sub1)
6710 .
addImm(AMDGPU::sub2_sub3);
6711 }
else if (Opcode == AMDGPU::V_MOV_B16_t16_e64) {
6728 return RI.getSubReg(SuperReg.
getReg(), SubIdx);
6732 Register SubReg =
MRI.createVirtualRegister(SubRC);
6734 unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.
getSubReg(), SubIdx);
6745 if (SubIdx == AMDGPU::sub0)
6747 if (SubIdx == AMDGPU::sub1)
6759void SIInstrInfo::swapOperands(
MachineInstr &Inst)
const {
6775 if (Reg.isPhysical())
6782 RI.getLargestLegalSuperClass(RC,
MRI.getMF());
6785 return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.
getSubReg()) !=
nullptr;
6788 return RI.getCommonSubClass(DRC, RC) !=
nullptr;
6795 unsigned Opc =
MI.getOpcode();
6808 bool IsAGPR = RI.isAGPR(
MRI, MO.
getReg());
6809 if (IsAGPR && !ST.hasMAIInsts())
6811 if (IsAGPR && (!ST.hasGFX90AInsts() || !
MRI.reservedRegsFrozen()) &&
6815 const int VDstIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst);
6816 const int DataIdx = AMDGPU::getNamedOperandIdx(
6817 Opc,
isDS(
Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
6818 if ((
int)OpIdx == VDstIdx && DataIdx != -1 &&
6819 MI.getOperand(DataIdx).isReg() &&
6820 RI.isAGPR(
MRI,
MI.getOperand(DataIdx).getReg()) != IsAGPR)
6822 if ((
int)OpIdx == DataIdx) {
6823 if (VDstIdx != -1 &&
6824 RI.isAGPR(
MRI,
MI.getOperand(VDstIdx).getReg()) != IsAGPR)
6827 const int Data1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data1);
6828 if (Data1Idx != -1 &&
MI.getOperand(Data1Idx).isReg() &&
6829 RI.isAGPR(
MRI,
MI.getOperand(Data1Idx).getReg()) != IsAGPR)
6834 if (
Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
6835 (
int)OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0) &&
6839 if (ST.hasFlatScratchHiInB64InstHazard() &&
6846 if (
Opc == AMDGPU::S_BITCMP0_B64 ||
Opc == AMDGPU::S_BITCMP1_B64)
6850 (
int)OpIdx == AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1))
6859 constexpr unsigned NumOps = 3;
6860 constexpr AMDGPU::OpName OpNames[
NumOps * 2] = {
6861 AMDGPU::OpName::src0, AMDGPU::OpName::src1,
6862 AMDGPU::OpName::src2, AMDGPU::OpName::src0_modifiers,
6863 AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};
6868 int SrcIdx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[SrcN]);
6871 MO = &
MI.getOperand(SrcIdx);
6878 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OpNames[
NumOps + SrcN]);
6882 unsigned Mods =
MI.getOperand(ModsIdx).getImm();
6886 return !OpSel && !OpSelHi;
6895 int64_t RegClass = getOpRegClassID(OpInfo);
6897 RegClass != -1 ? RI.getRegClass(RegClass) :
nullptr;
6899 MO = &
MI.getOperand(OpIdx);
6903 if (
isVALU(
MI,
false) && !IsInlineConst &&
6907 int ConstantBusLimit = ST.getConstantBusLimit(
MI.getOpcode());
6908 int LiteralLimit = !
isVOP3(
MI) || ST.hasVOP3Literal() ? 1 : 0;
6912 if (!LiteralLimit--)
6922 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6930 if (--ConstantBusLimit <= 0)
6942 if (!LiteralLimit--)
6944 if (--ConstantBusLimit <= 0)
6950 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
6954 if (!
Op.isReg() && !
Op.isFI() && !
Op.isRegMask() &&
6956 !
Op.isIdenticalTo(*MO))
6978 bool Is64BitOp = Is64BitFPOp ||
6986 (!ST.has64BitLiterals() || InstDesc.
getSize() != 4))
6995 if (!Is64BitFPOp && (int32_t)
Imm < 0 &&
7013 bool IsGFX950Only = ST.hasGFX950Insts();
7014 bool IsGFX940Only = ST.hasGFX940Insts();
7016 if (!IsGFX950Only && !IsGFX940Only)
7034 unsigned Opcode =
MI.getOpcode();
7036 case AMDGPU::V_CVT_PK_BF8_F32_e64:
7037 case AMDGPU::V_CVT_PK_FP8_F32_e64:
7038 case AMDGPU::V_MQSAD_PK_U16_U8_e64:
7039 case AMDGPU::V_MQSAD_U32_U8_e64:
7040 case AMDGPU::V_PK_ADD_F16:
7041 case AMDGPU::V_PK_ADD_F32:
7042 case AMDGPU::V_PK_ADD_I16:
7043 case AMDGPU::V_PK_ADD_U16:
7044 case AMDGPU::V_PK_ASHRREV_I16:
7045 case AMDGPU::V_PK_FMA_F16:
7046 case AMDGPU::V_PK_FMA_F32:
7047 case AMDGPU::V_PK_FMAC_F16_e32:
7048 case AMDGPU::V_PK_FMAC_F16_e64:
7049 case AMDGPU::V_PK_LSHLREV_B16:
7050 case AMDGPU::V_PK_LSHRREV_B16:
7051 case AMDGPU::V_PK_MAD_I16:
7052 case AMDGPU::V_PK_MAD_U16:
7053 case AMDGPU::V_PK_MAX_F16:
7054 case AMDGPU::V_PK_MAX_I16:
7055 case AMDGPU::V_PK_MAX_U16:
7056 case AMDGPU::V_PK_MIN_F16:
7057 case AMDGPU::V_PK_MIN_I16:
7058 case AMDGPU::V_PK_MIN_U16:
7059 case AMDGPU::V_PK_MOV_B32:
7060 case AMDGPU::V_PK_MUL_F16:
7061 case AMDGPU::V_PK_MUL_F32:
7062 case AMDGPU::V_PK_MUL_LO_U16:
7063 case AMDGPU::V_PK_SUB_I16:
7064 case AMDGPU::V_PK_SUB_U16:
7065 case AMDGPU::V_QSAD_PK_U16_U8_e64:
7074 unsigned Opc =
MI.getOpcode();
7077 int Src0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0);
7080 int Src1Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1);
7086 if (HasImplicitSGPR && ST.getConstantBusLimit(
Opc) <= 1 && Src0.isReg() &&
7087 RI.isSGPRReg(
MRI, Src0.getReg()))
7093 if (
Opc == AMDGPU::V_WRITELANE_B32) {
7095 if (Src0.isReg() && RI.isVGPR(
MRI, Src0.getReg())) {
7096 Register Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7099 Src0.ChangeToRegister(Reg,
false);
7101 if (Src1.isReg() && RI.isVGPR(
MRI, Src1.getReg())) {
7102 Register Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7106 Src1.ChangeToRegister(Reg,
false);
7112 if (
Opc == AMDGPU::V_FMAC_F32_e32 ||
Opc == AMDGPU::V_FMAC_F16_e32) {
7113 int Src2Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2);
7114 if (!RI.isVGPR(
MRI,
MI.getOperand(Src2Idx).getReg()))
7126 if (
Opc == AMDGPU::V_READLANE_B32 && Src1.isReg() &&
7127 RI.isVGPR(
MRI, Src1.getReg())) {
7128 Register Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7132 Src1.ChangeToRegister(Reg,
false);
7140 if (HasImplicitSGPR || !
MI.isCommutable()) {
7150 if ((!Src1.isImm() && !Src1.isReg()) ||
7157 if (CommutedOpc == -1) {
7162 MI.setDesc(
get(CommutedOpc));
7165 unsigned Src0SubReg = Src0.getSubReg();
7166 bool Src0Kill = Src0.isKill();
7169 Src0.ChangeToImmediate(Src1.getImm());
7170 else if (Src1.isReg()) {
7171 Src0.ChangeToRegister(Src1.getReg(),
false,
false, Src1.isKill());
7172 Src0.setSubReg(Src1.getSubReg());
7176 Src1.ChangeToRegister(Src0Reg,
false,
false, Src0Kill);
7177 Src1.setSubReg(Src0SubReg);
7185 unsigned Opc =
MI.getOpcode();
7188 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src0),
7189 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src1),
7190 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::src2)
7193 if (
Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
7194 Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
7195 Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
7196 Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
7197 Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
7198 Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
7199 Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
7203 if (Src1.isReg() && !RI.isSGPRClass(
MRI.getRegClass(Src1.getReg()))) {
7204 Register Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7207 Src1.ChangeToRegister(Reg,
false);
7209 if (VOP3Idx[2] != -1) {
7211 if (Src2.isReg() && !RI.isSGPRClass(
MRI.getRegClass(Src2.getReg()))) {
7212 Register Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
7215 Src2.ChangeToRegister(Reg,
false);
7221 int ConstantBusLimit = ST.getConstantBusLimit(
Opc);
7222 int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
7224 Register SGPRReg = findUsedSGPR(
MI, VOP3Idx);
7226 SGPRsUsed.
insert(SGPRReg);
7230 for (
int Idx : VOP3Idx) {
7239 if (LiteralLimit > 0 && ConstantBusLimit > 0) {
7251 if (!RI.isSGPRClass(RI.getRegClassForReg(
MRI, MO.
getReg())))
7258 if (ConstantBusLimit > 0) {
7270 if ((
Opc == AMDGPU::V_FMAC_F32_e64 ||
Opc == AMDGPU::V_FMAC_F16_e64 ||
7271 Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
7272 Opc == AMDGPU::V_FMAC_F16_t16_e64) &&
7273 !RI.isVGPR(
MRI,
MI.getOperand(VOP3Idx[2]).getReg()))
7279 for (
unsigned I = 0;
I < 3; ++
I) {
7292 SRC = RI.getCommonSubClass(SRC, DstRC);
7295 unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;
7297 if (RI.hasAGPRs(VRC)) {
7298 VRC = RI.getEquivalentVGPRClass(VRC);
7299 Register NewSrcReg =
MRI.createVirtualRegister(VRC);
7301 get(TargetOpcode::COPY), NewSrcReg)
7308 get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
7314 for (
unsigned i = 0; i < SubRegs; ++i) {
7315 Register SGPR =
MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7317 get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
7318 .
addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
7324 get(AMDGPU::REG_SEQUENCE), DstReg);
7325 for (
unsigned i = 0; i < SubRegs; ++i) {
7327 MIB.
addImm(RI.getSubRegFromChannel(i));
7340 if (SBase && !RI.isSGPRClass(
MRI.getRegClass(SBase->getReg()))) {
7342 SBase->setReg(SGPR);
7345 if (SOff && !RI.isSGPRReg(
MRI, SOff->
getReg())) {
7353 int OldSAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::saddr);
7354 if (OldSAddrIdx < 0)
7370 int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
7371 if (NewVAddrIdx < 0)
7374 int OldVAddrIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr);
7378 if (OldVAddrIdx >= 0) {
7380 VAddrDef =
MRI.getUniqueVRegDef(VAddr.
getReg());
7392 if (OldVAddrIdx == NewVAddrIdx) {
7395 MRI.removeRegOperandFromUseList(&NewVAddr);
7396 MRI.moveOperands(&NewVAddr, &SAddr, 1);
7400 MRI.removeRegOperandFromUseList(&NewVAddr);
7401 MRI.addRegOperandToUseList(&NewVAddr);
7403 assert(OldSAddrIdx == NewVAddrIdx);
7405 if (OldVAddrIdx >= 0) {
7406 int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
7407 AMDGPU::OpName::vdst_in);
7411 if (NewVDstIn != -1) {
7412 int OldVDstIn = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vdst_in);
7418 if (NewVDstIn != -1) {
7419 int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
7440 if (!SAddr || RI.isSGPRClass(
MRI.getRegClass(SAddr->
getReg())))
7460 unsigned OpSubReg =
Op.getSubReg();
7463 RI.getRegClassForReg(
MRI, OpReg), OpSubReg);
7469 Register DstReg =
MRI.createVirtualRegister(DstRC);
7470 auto Copy =
BuildMI(InsertMBB,
I,
DL,
get(AMDGPU::COPY), DstReg)
7471 .
addReg(OpReg, {}, OpSubReg);
7473 Op.setSubReg(AMDGPU::NoSubRegister);
7480 if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
7483 bool ImpDef = Def->isImplicitDef();
7484 while (!ImpDef && Def && Def->isCopy()) {
7485 if (Def->getOperand(1).getReg().isPhysical())
7487 Def =
MRI.getUniqueVRegDef(Def->getOperand(1).getReg());
7488 ImpDef = Def && Def->isImplicitDef();
7490 if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
7506 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7511 bool UseNewExecInstructions =
7520 if (UseNewExecInstructions) {
7555 for (
auto [Idx, ScalarOp] :
enumerate(ScalarOps)) {
7556 unsigned RegSize =
TRI->getRegSizeInBits(ScalarOp->getReg(),
MRI);
7557 unsigned NumSubRegs =
RegSize / 32;
7558 Register VScalarOp = ScalarOp->getReg();
7561 TII.getRegClass(
TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);
7563 if (NumSubRegs == 1) {
7566 TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
7567 Common != VScalarOpRC) {
7574 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
7577 if (UseNewExecInstructions) {
7579 TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
7582 if (
I == LoopBB.
end())
7587 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
7593 CondReg = NewCondReg;
7605 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7606 ScalarOp->setReg(CurReg);
7609 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7610 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7612 ScalarOp->setReg(PhySGPRs[Idx]);
7617 assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
7618 "Unhandled register size");
7620 for (
unsigned Idx = 0;
Idx < NumSubRegs;
Idx += 2) {
7627 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
7628 .
addReg(VScalarOp, VScalarOpUndef,
TRI->getSubRegFromChannel(Idx));
7631 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
7632 .
addReg(VScalarOp, VScalarOpUndef,
7633 TRI->getSubRegFromChannel(Idx + 1));
7640 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), CurReg)
7647 NumSubRegs <= 2 ? 0 :
TRI->getSubRegFromChannel(Idx, 2);
7649 if (UseNewExecInstructions) {
7651 TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
7653 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7654 if (
I == LoopBB.
end())
7658 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
7660 .
addReg(VScalarOp, VScalarOpUndef, SubReg);
7664 CondReg = NewCondReg;
7676 const auto *SScalarOpRC =
7682 BuildMI(LoopBB,
I,
DL,
TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
7683 unsigned Channel = 0;
7684 for (
Register Piece : ReadlanePieces) {
7685 Merge.addReg(Piece).addImm(
TRI->getSubRegFromChannel(Channel++));
7689 if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
7690 ScalarOp->setReg(SScalarOp);
7692 BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(),
DL,
7693 TII.get(AMDGPU::COPY), PhySGPRs[Idx])
7695 ScalarOp->setReg(PhySGPRs[Idx]);
7703 if (!UseNewExecInstructions) {
7716 if (UseNewExecInstructions) {
7749 assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.
size()) &&
7750 "Physical SGPRs must be empty or match the number of scalar operands");
7756 if (!Begin.isValid())
7758 if (!
End.isValid()) {
7764 const auto *BoolXExecRC =
TRI->getWaveMaskRegClass();
7773 std::numeric_limits<unsigned>::max()) !=
7819 for (
auto &Succ : RemainderBB->
successors()) {
7844static std::tuple<unsigned, unsigned>
7852 TII.buildExtractSubReg(
MI,
MRI, Rsrc, &AMDGPU::VReg_128RegClass,
7853 AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);
7856 Register Zero64 =
MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
7857 Register SRsrcFormatLo =
MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7858 Register SRsrcFormatHi =
MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
7859 Register NewSRsrc =
MRI.createVirtualRegister(&AMDGPU::SGPR_128RegClass);
7860 uint64_t RsrcDataFormat =
TII.getDefaultRsrcDataFormat();
7877 .
addImm(AMDGPU::sub0_sub1)
7883 return std::tuple(RsrcPtr, NewSRsrc);
7894 if (ST.useRealTrue16Insts())
7924 if (
MI.getOpcode() == AMDGPU::PHI) {
7926 assert(!RI.isSGPRClass(VRC));
7929 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7931 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7947 if (
MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
7950 if (RI.hasVGPRs(DstRC)) {
7954 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
7956 if (!
Op.isReg() || !
Op.getReg().isVirtual())
7973 if (
MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
7978 if (DstRC != Src0RC) {
7987 if (
MI.getOpcode() == AMDGPU::SI_INIT_M0) {
7989 if (Src.isReg() && RI.hasVectorRegisters(
MRI.getRegClass(Src.getReg())))
7995 if (
MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
7996 MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
7997 MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
7998 MI.getOpcode() == AMDGPU::S_WQM_B32 ||
7999 MI.getOpcode() == AMDGPU::S_WQM_B64 ||
8000 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
8001 MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
8003 if (Src.isReg() && RI.hasVectorRegisters(
MRI.getRegClass(Src.getReg())))
8016 ? AMDGPU::OpName::rsrc
8017 : AMDGPU::OpName::srsrc;
8019 if (SRsrc && !RI.isSGPRClass(
MRI.getRegClass(SRsrc->
getReg())))
8022 AMDGPU::OpName SampOpName =
8023 isMIMG(
MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
8025 if (SSamp && !RI.isSGPRClass(
MRI.getRegClass(SSamp->
getReg())))
8032 if (
MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
8034 if (!RI.isSGPRClass(
MRI.getRegClass(Dest->
getReg()))) {
8040 if (
MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
8042 Register Reg =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8044 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::src0);
8048 Src0.ChangeToRegister(Reg,
false);
8054 if (
MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
8055 MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
8056 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
8057 MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
8059 if (Src.isReg() && RI.hasVectorRegisters(
MRI.getRegClass(Src.getReg())))
8066 bool isSoffsetLegal =
true;
8068 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::soffset);
8069 if (SoffsetIdx != -1) {
8072 !RI.isSGPRClass(
MRI.getRegClass(Soffset->
getReg()))) {
8073 isSoffsetLegal =
false;
8077 bool isRsrcLegal =
true;
8079 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::srsrc);
8080 if (RsrcIdx != -1) {
8083 isRsrcLegal =
false;
8087 if (isRsrcLegal && isSoffsetLegal)
8111 Register NewVAddrLo =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8112 Register NewVAddrHi =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8113 Register NewVAddr =
MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
8115 const auto *BoolXExecRC = RI.getWaveMaskRegClass();
8116 Register CondReg0 =
MRI.createVirtualRegister(BoolXExecRC);
8117 Register CondReg1 =
MRI.createVirtualRegister(BoolXExecRC);
8119 unsigned RsrcPtr, NewSRsrc;
8126 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
8127 .addReg(VAddr->
getReg(), {}, AMDGPU::sub0)
8133 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
8134 .addReg(VAddr->
getReg(), {}, AMDGPU::sub1)
8147 }
else if (!VAddr && ST.hasAddr64()) {
8151 "FIXME: Need to emit flat atomics here");
8153 unsigned RsrcPtr, NewSRsrc;
8156 Register NewVAddr =
MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
8179 MIB.
addImm(CPol->getImm());
8184 MIB.
addImm(TFE->getImm());
8204 MI.removeFromParent();
8209 .
addReg(RsrcPtr, {}, AMDGPU::sub0)
8210 .addImm(AMDGPU::sub0)
8211 .
addReg(RsrcPtr, {}, AMDGPU::sub1)
8212 .addImm(AMDGPU::sub1);
8215 if (!isSoffsetLegal) {
8226 if (!isSoffsetLegal) {
8235 if (InSet.insert(
MI).second)
8239 AMDGPU::getNamedOperandIdx(
MI->getOpcode(), AMDGPU::OpName::srsrc);
8240 if (RsrcIdx != -1) {
8241 DeferredList.insert(
MI);
8246 return DeferredList.contains(
MI);
8256 if (!ST.useRealTrue16Insts())
8259 unsigned Opcode =
MI.getOpcode();
8262 if (OpIdx >=
MI.getNumExplicitOperands() ||
8263 OpIdx >=
get(Opcode).getNumOperands() ||
8264 get(Opcode).operands()[OpIdx].RegClass == -1)
8268 if (!
Op.isReg() || !
Op.getReg().isVirtual() ||
Op.isDef())
8272 if (!RI.isVGPRClass(CurrRC))
8275 int16_t RCID = getOpRegClassID(
get(Opcode).operands()[OpIdx]);
8277 if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
8279 if (
Op.getSubReg() == AMDGPU::NoSubRegister)
8280 Op.setSubReg(AMDGPU::lo16);
8285 RI.getSubRegisterClass(CurrRC,
Op.getSubReg());
8286 if (RI.getMatchingSuperRegClass(ExpectedRC, CurrSRC, AMDGPU::lo16)) {
8288 Register NewDstReg =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8296 Op.setReg(NewDstReg);
8297 Op.setSubReg(AMDGPU::NoSubRegister);
8302 for (
unsigned OpIdx = 0; OpIdx <
MI.getNumExplicitOperands(); OpIdx++)
8310 assert(
MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
8311 "This only handle waterfall for SI_CALL_ISEL");
8318 while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
8321 while (
End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
8326 while (
End !=
MBB.end() &&
End->isCopy() &&
8327 MI->definesRegister(
End->getOperand(1).getReg(), &RI))
8337 while (!Worklist.
empty()) {
8343 moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
8349 moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
8351 "Deferred MachineInstr are not supposed to re-populate worklist");
8354 for (
auto &Entry : WaterFalls) {
8355 if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
8357 Entry.second.SGPRs);
8360 for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
8362 Entry.first->eraseFromParent();
8370 if (SubRegIndices.
size() <= 1) {
8371 Register NewDst =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8373 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8380 for (int16_t Indice : SubRegIndices) {
8381 Register NewDst =
MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
8383 get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
8390 get(AMDGPU::REG_SEQUENCE), DstReg);
8391 for (
unsigned i = 0; i < SubRegIndices.size(); ++i) {
8393 MIB.
addImm(RI.getSubRegFromChannel(i));
8403 if (DstReg == AMDGPU::M0) {
8416 if (
MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
8418 for (
unsigned i = 0; i <
UseMI->getNumOperands(); ++i) {
8419 if (
UseMI->getOperand(i).isReg() &&
8420 UseMI->getOperand(i).getReg() == DstReg) {
8424 V2SCopyInfo.MOs.push_back(MO);
8425 V2SCopyInfo.SGPRs.push_back(DstReg);
8429 }
else if (
MI.getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
8430 MI.getOperand(0).isReg() &&
8431 MI.getOperand(0).getReg() == DstReg) {
8434 }
else if (
MI.readsRegister(DstReg, &RI)) {
8436 V2SPhyCopiesToErase[&Inst] =
false;
8438 if (
MI.modifiesRegister(DstReg, &RI))
8460 case AMDGPU::S_ADD_I32:
8461 case AMDGPU::S_SUB_I32: {
8465 std::tie(
Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
8473 case AMDGPU::S_MUL_U64:
8474 if (ST.useVMulU64Inst()) {
8475 NewOpcode = AMDGPU::V_MUL_U64_e64;
8479 splitScalarSMulU64(Worklist, Inst, MDT);
8483 case AMDGPU::S_MUL_U64_U32_PSEUDO:
8484 case AMDGPU::S_MUL_I64_I32_PSEUDO:
8487 splitScalarSMulPseudo(Worklist, Inst, MDT);
8491 case AMDGPU::S_AND_B64:
8492 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
8496 case AMDGPU::S_OR_B64:
8497 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
8501 case AMDGPU::S_XOR_B64:
8502 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
8506 case AMDGPU::S_NAND_B64:
8507 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
8511 case AMDGPU::S_NOR_B64:
8512 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
8516 case AMDGPU::S_XNOR_B64:
8517 if (ST.hasDLInsts())
8518 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
8520 splitScalar64BitXnor(Worklist, Inst, MDT);
8524 case AMDGPU::S_ANDN2_B64:
8525 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
8529 case AMDGPU::S_ORN2_B64:
8530 splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
8534 case AMDGPU::S_BREV_B64:
8535 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32,
true);
8539 case AMDGPU::S_NOT_B64:
8540 splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
8544 case AMDGPU::S_BCNT1_I32_B64:
8545 splitScalar64BitBCNT(Worklist, Inst);
8549 case AMDGPU::S_BFE_I64:
8550 splitScalar64BitBFE(Worklist, Inst);
8554 case AMDGPU::S_FLBIT_I32_B64:
8555 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
8558 case AMDGPU::S_FF1_I32_B64:
8559 splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
8563 case AMDGPU::S_LSHL_B32:
8564 if (ST.hasOnlyRevVALUShifts()) {
8565 NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
8569 case AMDGPU::S_ASHR_I32:
8570 if (ST.hasOnlyRevVALUShifts()) {
8571 NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
8575 case AMDGPU::S_LSHR_B32:
8576 if (ST.hasOnlyRevVALUShifts()) {
8577 NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
8581 case AMDGPU::S_LSHL_B64:
8582 if (ST.hasOnlyRevVALUShifts()) {
8584 ? AMDGPU::V_LSHLREV_B64_pseudo_e64
8585 : AMDGPU::V_LSHLREV_B64_e64;
8589 case AMDGPU::S_ASHR_I64:
8590 if (ST.hasOnlyRevVALUShifts()) {
8591 NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
8595 case AMDGPU::S_LSHR_B64:
8596 if (ST.hasOnlyRevVALUShifts()) {
8597 NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
8602 case AMDGPU::S_ABS_I32:
8603 lowerScalarAbs(Worklist, Inst);
8607 case AMDGPU::S_ABSDIFF_I32:
8608 lowerScalarAbsDiff(Worklist, Inst);
8612 case AMDGPU::S_CBRANCH_SCC0:
8613 case AMDGPU::S_CBRANCH_SCC1: {
8616 bool IsSCC = CondReg == AMDGPU::SCC;
8625 case AMDGPU::S_BFE_U64:
8626 case AMDGPU::S_BFM_B64:
8629 case AMDGPU::S_PACK_LL_B32_B16:
8630 case AMDGPU::S_PACK_LH_B32_B16:
8631 case AMDGPU::S_PACK_HL_B32_B16:
8632 case AMDGPU::S_PACK_HH_B32_B16:
8633 movePackToVALU(Worklist,
MRI, Inst);
8637 case AMDGPU::S_XNOR_B32:
8638 lowerScalarXnor(Worklist, Inst);
8642 case AMDGPU::S_NAND_B32:
8643 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
8647 case AMDGPU::S_NOR_B32:
8648 splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
8652 case AMDGPU::S_ANDN2_B32:
8653 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
8657 case AMDGPU::S_ORN2_B32:
8658 splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
8666 case AMDGPU::S_ADD_CO_PSEUDO:
8667 case AMDGPU::S_SUB_CO_PSEUDO: {
8668 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
8669 ? AMDGPU::V_ADDC_U32_e64
8670 : AMDGPU::V_SUBB_U32_e64;
8671 const auto *CarryRC = RI.getWaveMaskRegClass();
8674 if (!
MRI.constrainRegClass(CarryInReg, CarryRC)) {
8675 Register NewCarryReg =
MRI.createVirtualRegister(CarryRC);
8682 Register DestReg =
MRI.createVirtualRegister(RI.getEquivalentVGPRClass(
8693 addUsersToMoveToVALUWorklist(DestReg,
MRI, Worklist);
8697 case AMDGPU::S_UADDO_PSEUDO:
8698 case AMDGPU::S_USUBO_PSEUDO: {
8704 unsigned Opc = (Inst.
getOpcode() == AMDGPU::S_UADDO_PSEUDO)
8705 ? AMDGPU::V_ADD_CO_U32_e64
8706 : AMDGPU::V_SUB_CO_U32_e64;
8708 RI.getEquivalentVGPRClass(
MRI.getRegClass(Dest0.
getReg()));
8709 Register DestReg =
MRI.createVirtualRegister(NewRC);
8717 MRI.replaceRegWith(Dest0.
getReg(), DestReg);
8718 addUsersToMoveToVALUWorklist(DestReg,
MRI, Worklist);
8722 case AMDGPU::S_LSHL1_ADD_U32:
8723 case AMDGPU::S_LSHL2_ADD_U32:
8724 case AMDGPU::S_LSHL3_ADD_U32:
8725 case AMDGPU::S_LSHL4_ADD_U32: {
8729 unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32 ? 1
8730 : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
8731 : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
8735 RI.getEquivalentVGPRClass(
MRI.getRegClass(Dest.
getReg()));
8736 Register DestReg =
MRI.createVirtualRegister(NewRC);
8744 MRI.replaceRegWith(Dest.
getReg(), DestReg);
8745 addUsersToMoveToVALUWorklist(DestReg,
MRI, Worklist);
8749 case AMDGPU::S_CSELECT_B32:
8750 case AMDGPU::S_CSELECT_B64:
8751 lowerSelect(Worklist, Inst, MDT);
8754 case AMDGPU::S_CMP_EQ_I32:
8755 case AMDGPU::S_CMP_LG_I32:
8756 case AMDGPU::S_CMP_GT_I32:
8757 case AMDGPU::S_CMP_GE_I32:
8758 case AMDGPU::S_CMP_LT_I32:
8759 case AMDGPU::S_CMP_LE_I32:
8760 case AMDGPU::S_CMP_EQ_U32:
8761 case AMDGPU::S_CMP_LG_U32:
8762 case AMDGPU::S_CMP_GT_U32:
8763 case AMDGPU::S_CMP_GE_U32:
8764 case AMDGPU::S_CMP_LT_U32:
8765 case AMDGPU::S_CMP_LE_U32:
8766 case AMDGPU::S_CMP_EQ_U64:
8767 case AMDGPU::S_CMP_LG_U64:
8768 case AMDGPU::S_CMP_LT_F32:
8769 case AMDGPU::S_CMP_EQ_F32:
8770 case AMDGPU::S_CMP_LE_F32:
8771 case AMDGPU::S_CMP_GT_F32:
8772 case AMDGPU::S_CMP_LG_F32:
8773 case AMDGPU::S_CMP_GE_F32:
8774 case AMDGPU::S_CMP_O_F32:
8775 case AMDGPU::S_CMP_U_F32:
8776 case AMDGPU::S_CMP_NGE_F32:
8777 case AMDGPU::S_CMP_NLG_F32:
8778 case AMDGPU::S_CMP_NGT_F32:
8779 case AMDGPU::S_CMP_NLE_F32:
8780 case AMDGPU::S_CMP_NEQ_F32:
8781 case AMDGPU::S_CMP_NLT_F32: {
8782 Register CondReg =
MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8786 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
8800 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8804 case AMDGPU::S_CMP_LT_F16:
8805 case AMDGPU::S_CMP_EQ_F16:
8806 case AMDGPU::S_CMP_LE_F16:
8807 case AMDGPU::S_CMP_GT_F16:
8808 case AMDGPU::S_CMP_LG_F16:
8809 case AMDGPU::S_CMP_GE_F16:
8810 case AMDGPU::S_CMP_O_F16:
8811 case AMDGPU::S_CMP_U_F16:
8812 case AMDGPU::S_CMP_NGE_F16:
8813 case AMDGPU::S_CMP_NLG_F16:
8814 case AMDGPU::S_CMP_NGT_F16:
8815 case AMDGPU::S_CMP_NLE_F16:
8816 case AMDGPU::S_CMP_NEQ_F16:
8817 case AMDGPU::S_CMP_NLT_F16: {
8818 Register CondReg =
MRI.createVirtualRegister(RI.getWaveMaskRegClass());
8839 addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
8843 case AMDGPU::S_CVT_HI_F32_F16: {
8844 Register TmpReg =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8845 Register NewDst =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8846 if (ST.useRealTrue16Insts()) {
8851 .
addReg(TmpReg, {}, AMDGPU::hi16)
8867 addUsersToMoveToVALUWorklist(NewDst,
MRI, Worklist);
8871 case AMDGPU::S_MINIMUM_F32:
8872 case AMDGPU::S_MAXIMUM_F32: {
8873 Register NewDst =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
8884 addUsersToMoveToVALUWorklist(NewDst,
MRI, Worklist);
8888 case AMDGPU::S_MINIMUM_F16:
8889 case AMDGPU::S_MAXIMUM_F16: {
8890 Register NewDst =
MRI.createVirtualRegister(ST.useRealTrue16Insts()
8891 ? &AMDGPU::VGPR_16RegClass
8892 : &AMDGPU::VGPR_32RegClass);
8903 addUsersToMoveToVALUWorklist(NewDst,
MRI, Worklist);
8907 case AMDGPU::V_S_EXP_F16_e64:
8908 case AMDGPU::V_S_LOG_F16_e64:
8909 case AMDGPU::V_S_RCP_F16_e64:
8910 case AMDGPU::V_S_RSQ_F16_e64:
8911 case AMDGPU::V_S_SQRT_F16_e64: {
8912 Register NewDst =
MRI.createVirtualRegister(ST.useRealTrue16Insts()
8913 ? &AMDGPU::VGPR_16RegClass
8914 : &AMDGPU::VGPR_32RegClass);
8925 addUsersToMoveToVALUWorklist(NewDst,
MRI, Worklist);
8931 if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
8939 if (NewOpcode == Opcode) {
8946 V2SPhyCopiesToErase);
8954 RI.getCommonSubClass(NewDstRC, SrcRC)) {
8961 addUsersToMoveToVALUWorklist(DstReg,
MRI, Worklist);
8967 RI.composeSubRegIndices(SrcSubReg, UseMO.getSubReg()));
8968 UseMO.setReg(NewDstReg);
8973 if (!
MRI.constrainRegClass(NewDstReg, CommonRC))
8986 unsigned OpIdx =
UseMI.getOperandNo(&UseMO);
8989 MRI.constrainRegClass(NewDstReg, OpRC);
8999 if (ST.useRealTrue16Insts() && Inst.
isCopy() &&
9003 if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
9004 Register NewDstReg =
MRI.createVirtualRegister(NewDstRC);
9009 get(AMDGPU::REG_SEQUENCE), NewDstReg)
9015 MRI.replaceRegWith(DstReg, NewDstReg);
9016 addUsersToMoveToVALUWorklist(NewDstReg,
MRI, Worklist);
9018 }
else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
9021 Register NewDstReg =
MRI.createVirtualRegister(NewDstRC);
9022 MRI.replaceRegWith(DstReg, NewDstReg);
9023 addUsersToMoveToVALUWorklist(NewDstReg,
MRI, Worklist);
9028 Register NewDstReg =
MRI.createVirtualRegister(NewDstRC);
9029 MRI.replaceRegWith(DstReg, NewDstReg);
9031 addUsersToMoveToVALUWorklist(NewDstReg,
MRI, Worklist);
9041 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9042 AMDGPU::OpName::src0_modifiers) >= 0)
9046 NewInstr->addOperand(Src);
9049 if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
9052 unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
9054 NewInstr.addImm(
Size);
9055 }
else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
9059 }
else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
9064 "Scalar BFE is only implemented for constant width and offset");
9072 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9073 AMDGPU::OpName::src1_modifiers) >= 0)
9075 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
9077 if (AMDGPU::getNamedOperandIdx(NewOpcode,
9078 AMDGPU::OpName::src2_modifiers) >= 0)
9080 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
9082 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
9084 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
9086 if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
9092 NewInstr->addOperand(
Op);
9098 bool DeadSCCDef =
false;
9100 if (
Op.getReg() == AMDGPU::SCC) {
9106 addSCCDefUsersToVALUWorklist(
Op, Inst, Worklist);
9110 addSCCDefsToVALUWorklist(NewInstr, Worklist);
9115 if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
9116 Register DstReg = NewInstr->getOperand(0).getReg();
9121 NewDstReg =
MRI.createVirtualRegister(NewDstRC);
9122 MRI.replaceRegWith(DstReg, NewDstReg);
9130 NewInstr->findRegisterDefOperand(RI.getVCC(), &RI))
9131 VCCDef->setIsDead();
9137 addUsersToMoveToVALUWorklist(NewDstReg,
MRI, Worklist);
9141std::pair<bool, MachineBasicBlock *>
9144 if (ST.hasAddNoCarryInsts()) {
9153 Register ResultReg =
MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
9156 assert(
Opc == AMDGPU::S_ADD_I32 ||
Opc == AMDGPU::S_SUB_I32);
9158 unsigned NewOpc =
Opc == AMDGPU::S_ADD_I32 ?
9159 AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;
9167 MRI.replaceRegWith(OldDstReg, ResultReg);
9170 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
9171 return std::pair(
true, NewBB);
9174 return std::pair(
false,
nullptr);
9191 bool IsSCC = (CondReg == AMDGPU::SCC);
9197 if (!IsSCC &&
Src0.isImm() && (
Src0.getImm() == -1) &&
Src1.isImm() &&
9198 (
Src1.getImm() == 0)) {
9199 for (MachineOperand &UseMO :
9201 MachineInstr &
UseMI = *UseMO.getParent();
9202 switch (
UseMI.getOpcode()) {
9203 case AMDGPU::V_CNDMASK_B16_fake16_e32:
9204 case AMDGPU::V_CNDMASK_B16_fake16_e64:
9205 case AMDGPU::V_CNDMASK_B16_t16_e32:
9206 case AMDGPU::V_CNDMASK_B16_t16_e64:
9207 case AMDGPU::V_CNDMASK_B32_e32:
9208 case AMDGPU::V_CNDMASK_B32_e64:
9209 case AMDGPU::V_CNDMASK_B64_PSEUDO:
9210 if (UseMO.isImplicit() ||
9212 UseMO.setReg(CondReg);
9226 bool CopyFound =
false;
9227 for (MachineInstr &CandI :
9230 if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) !=
9232 if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
9234 .
addReg(CandI.getOperand(1).getReg());
9246 ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
9255 MachineInstr *NewInst;
9256 if (Inst.
getOpcode() == AMDGPU::S_CSELECT_B32) {
9257 NewInst =
BuildMI(
MBB, MII,
DL,
get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
9272 addUsersToMoveToVALUWorklist(NewDestReg,
MRI, Worklist);
9287 bool HasCarryOut = !ST.hasAddNoCarryInsts();
9289 HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
9291 MachineInstrBuilder
Sub =
9301 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
9318 bool HasCarryOut = !ST.hasAddNoCarryInsts();
9320 HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
9322 MachineInstrBuilder Sub1 =
BuildMI(
MBB, MII,
DL,
get(SubOp), SubResultReg)
9326 MachineInstrBuilder Sub2 =
9339 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
9353 if (ST.hasDLInsts()) {
9363 addUsersToMoveToVALUWorklist(NewDest,
MRI, Worklist);
9369 bool Src0IsSGPR =
Src0.isReg() &&
9371 bool Src1IsSGPR =
Src1.isReg() &&
9385 }
else if (Src1IsSGPR) {
9403 addUsersToMoveToVALUWorklist(NewDest,
MRI, Worklist);
9409 unsigned Opcode)
const {
9433 addUsersToMoveToVALUWorklist(NewDest,
MRI, Worklist);
9438 unsigned Opcode)
const {
9462 addUsersToMoveToVALUWorklist(NewDest,
MRI, Worklist);
9477 const MCInstrDesc &InstDesc =
get(Opcode);
9480 &AMDGPU::SGPR_32RegClass;
9483 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9486 AMDGPU::sub0, Src0SubRC);
9491 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9494 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0).
add(SrcReg0Sub0);
9497 AMDGPU::sub1, Src0SubRC);
9500 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1).
add(SrcReg0Sub1);
9514 Worklist.
insert(&LoHalf);
9515 Worklist.
insert(&HiHalf);
9521 addUsersToMoveToVALUWorklist(FullDestReg,
MRI, Worklist);
9545 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9546 if (RI.isSGPRClass(Src0SubRC))
9547 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9549 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9550 if (RI.isSGPRClass(Src1SubRC))
9551 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9555 MachineOperand Op0L =
9557 MachineOperand Op1L =
9559 MachineOperand Op0H =
9561 MachineOperand Op1H =
9580 MachineInstr *Op1L_Op0H =
9586 MachineInstr *Op1H_Op0L =
9592 MachineInstr *Carry =
9597 MachineInstr *LoHalf =
9607 MachineInstr *HiHalf =
9630 addUsersToMoveToVALUWorklist(FullDestReg,
MRI, Worklist);
9654 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9655 if (RI.isSGPRClass(Src0SubRC))
9656 Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
9658 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9659 if (RI.isSGPRClass(Src1SubRC))
9660 Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);
9664 MachineOperand Op0L =
9666 MachineOperand Op1L =
9670 unsigned NewOpc =
Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
9671 ? AMDGPU::V_MUL_HI_U32_e64
9672 : AMDGPU::V_MUL_HI_I32_e64;
9673 MachineInstr *HiHalf =
9676 MachineInstr *LoHalf =
9695 addUsersToMoveToVALUWorklist(FullDestReg,
MRI, Worklist);
9711 const MCInstrDesc &InstDesc =
get(Opcode);
9714 &AMDGPU::SGPR_32RegClass;
9717 RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
9720 &AMDGPU::SGPR_32RegClass;
9723 RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
9726 AMDGPU::sub0, Src0SubRC);
9728 AMDGPU::sub0, Src1SubRC);
9730 AMDGPU::sub1, Src0SubRC);
9732 AMDGPU::sub1, Src1SubRC);
9737 RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);
9740 MachineInstr &LoHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub0)
9745 MachineInstr &HiHalf = *
BuildMI(
MBB, MII,
DL, InstDesc, DestSub1)
9758 Worklist.
insert(&LoHalf);
9759 Worklist.
insert(&HiHalf);
9762 addUsersToMoveToVALUWorklist(FullDestReg,
MRI, Worklist);
9782 MachineOperand* Op0;
9783 MachineOperand* Op1;
9785 if (
Src0.isReg() && RI.isSGPRReg(
MRI,
Src0.getReg())) {
9818 const MCInstrDesc &InstDesc =
get(AMDGPU::V_BCNT_U32_B32_e64);
9821 &AMDGPU::SGPR_32RegClass;
9827 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9830 AMDGPU::sub0, SrcSubRC);
9832 AMDGPU::sub1, SrcSubRC);
9842 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
9861 Offset == 0 &&
"Not implemented");
9884 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
9894 .
addReg(Src.getReg(), {}, AMDGPU::sub0);
9897 .
addReg(Src.getReg(), {}, AMDGPU::sub0)
9903 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
9922 const MCInstrDesc &InstDesc =
get(Opcode);
9924 bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
9927 Src.isReg() ?
MRI.
getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
9929 RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);
9931 MachineOperand SrcRegSub0 =
9933 MachineOperand SrcRegSub1 =
9947 .
addReg(IsCtlz ? MidReg1 : MidReg2);
9951 .
addReg(IsCtlz ? MidReg2 : MidReg1);
9955 addUsersToMoveToVALUWorklist(MidReg4,
MRI, Worklist);
9958void SIInstrInfo::addUsersToMoveToVALUWorklist(
9962 MachineInstr &
UseMI = *MO.getParent();
9966 switch (
UseMI.getOpcode()) {
9969 case AMDGPU::SOFT_WQM:
9970 case AMDGPU::STRICT_WWM:
9971 case AMDGPU::STRICT_WQM:
9972 case AMDGPU::REG_SEQUENCE:
9974 case AMDGPU::INSERT_SUBREG:
9977 OpNo = MO.getOperandNo();
9984 if (!RI.hasVectorRegisters(OpRC))
10001 if (ST.useRealTrue16Insts()) {
10003 if (!
Src0.isReg() || !RI.isVGPR(
MRI,
Src0.getReg())) {
10006 get(
Src0.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
10009 SrcReg0 =
Src0.getReg();
10012 if (!
Src1.isReg() || !RI.isVGPR(
MRI,
Src1.getReg())) {
10015 get(
Src1.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
10018 SrcReg1 =
Src1.getReg();
10024 auto NewMI =
BuildMI(*
MBB, Inst,
DL,
get(AMDGPU::REG_SEQUENCE), ResultReg);
10026 case AMDGPU::S_PACK_LL_B32_B16:
10028 .addReg(SrcReg0, {},
10029 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10030 .addImm(AMDGPU::lo16)
10031 .addReg(SrcReg1, {},
10032 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10033 .addImm(AMDGPU::hi16);
10035 case AMDGPU::S_PACK_LH_B32_B16:
10037 .addReg(SrcReg0, {},
10038 isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10039 .addImm(AMDGPU::lo16)
10040 .addReg(SrcReg1, {}, AMDGPU::hi16)
10041 .addImm(AMDGPU::hi16);
10043 case AMDGPU::S_PACK_HL_B32_B16:
10044 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
10045 .addImm(AMDGPU::lo16)
10046 .addReg(SrcReg1, {},
10047 isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
10048 .addImm(AMDGPU::hi16);
10050 case AMDGPU::S_PACK_HH_B32_B16:
10051 NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
10052 .addImm(AMDGPU::lo16)
10053 .addReg(SrcReg1, {}, AMDGPU::hi16)
10054 .addImm(AMDGPU::hi16);
10062 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
10067 case AMDGPU::S_PACK_LL_B32_B16: {
10086 case AMDGPU::S_PACK_LH_B32_B16: {
10096 case AMDGPU::S_PACK_HL_B32_B16: {
10107 case AMDGPU::S_PACK_HH_B32_B16: {
10127 addUsersToMoveToVALUWorklist(ResultReg,
MRI, Worklist);
10136 assert(
Op.isReg() &&
Op.getReg() == AMDGPU::SCC &&
Op.isDef() &&
10137 !
Op.isDead() &&
Op.getParent() == &SCCDefInst);
10138 SmallVector<MachineInstr *, 4> CopyToDelete;
10141 for (MachineInstr &
MI :
10145 int SCCIdx =
MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI,
false);
10146 if (SCCIdx != -1) {
10149 Register DestReg =
MI.getOperand(0).getReg();
10156 MI.getOperand(SCCIdx).setReg(NewCond);
10162 if (
MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI,
false,
false) != -1)
10165 for (
auto &Copy : CopyToDelete)
10166 Copy->eraseFromParent();
10174void SIInstrInfo::addSCCDefsToVALUWorklist(
MachineInstr *SCCUseInst,
10180 for (MachineInstr &
MI :
10183 if (
MI.modifiesRegister(AMDGPU::VCC, &RI))
10185 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
10202 case AMDGPU::REG_SEQUENCE:
10203 case AMDGPU::INSERT_SUBREG:
10205 case AMDGPU::SOFT_WQM:
10206 case AMDGPU::STRICT_WWM:
10207 case AMDGPU::STRICT_WQM: {
10209 if (RI.isAGPRClass(SrcRC)) {
10210 if (RI.isAGPRClass(NewDstRC))
10215 case AMDGPU::REG_SEQUENCE:
10216 case AMDGPU::INSERT_SUBREG:
10217 NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
10220 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10226 if (!RI.isSGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
10229 NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
10243 int OpIndices[3])
const {
10244 const MCInstrDesc &
Desc =
MI.getDesc();
10262 for (
unsigned i = 0; i < 3; ++i) {
10263 int Idx = OpIndices[i];
10267 const MachineOperand &MO =
MI.getOperand(Idx);
10274 RI.getRegClass(getOpRegClassID(
Desc.operands()[Idx]));
10275 bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
10276 if (IsRequiredSGPR)
10282 if (RI.isSGPRClass(RegRC))
10283 UsedSGPRs[i] =
Reg;
10299 if (UsedSGPRs[0]) {
10300 if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
10301 SGPRReg = UsedSGPRs[0];
10304 if (!SGPRReg && UsedSGPRs[1]) {
10305 if (UsedSGPRs[1] == UsedSGPRs[2])
10306 SGPRReg = UsedSGPRs[1];
10313 AMDGPU::OpName OperandName)
const {
10314 if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
10317 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), OperandName);
10321 return &
MI.getOperand(Idx);
10335 if (ST.isAmdHsaOS()) {
10338 RsrcDataFormat |= (1ULL << 56);
10343 RsrcDataFormat |= (2ULL << 59);
10346 return RsrcDataFormat;
10356 uint64_t EltSizeValue =
Log2_32(ST.getMaxPrivateElementSize(
true)) - 1;
10361 uint64_t IndexStride = ST.isWave64() ? 3 : 2;
10368 Rsrc23 &=
~AMDGPU::RSRC_DATA_FORMAT;
10374 unsigned Opc =
MI.getOpcode();
10380 return get(
Opc).mayLoad() &&
10387 if (!Addr || !Addr->
isFI())
10396 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::vdata);
10398 return MI.getOperand(VDataIdx).getReg();
10408 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::data);
10410 return MI.getOperand(DataIdx).getReg();
10431 if (!
MI.mayStore())
10444 unsigned Opc =
MI.getOpcode();
10446 unsigned DescSize =
Desc.getSize();
10451 unsigned Size = DescSize;
10455 if (
MI.isBranch() && ST.hasOffset3fBug())
10466 bool HasLiteral =
false;
10467 unsigned LiteralSize = 4;
10468 for (
int I = 0, E =
MI.getNumExplicitOperands();
I != E; ++
I) {
10473 if (ST.has64BitLiterals()) {
10474 switch (OpInfo.OperandType) {
10499 return HasLiteral ? DescSize + LiteralSize : DescSize;
10504 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
10508 int RSrcIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::srsrc);
10509 return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
10513 case TargetOpcode::BUNDLE:
10514 return getInstBundleSize(
MI);
10515 case TargetOpcode::INLINEASM:
10516 case TargetOpcode::INLINEASM_BR: {
10518 const char *AsmStr =
MI.getOperand(0).getSymbolName();
10522 if (
MI.isMetaInstruction())
10526 const auto *D16Info = AMDGPU::getT16D16Helper(
Opc);
10529 unsigned LoInstOpcode = D16Info->LoOp;
10531 DescSize =
Desc.getSize();
10535 if (
Opc == AMDGPU::V_FMA_MIX_F16_t16 ||
Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
10538 DescSize =
Desc.getSize();
10547 if (
MI.isBranch() && ST.hasOffset3fBug())
10548 return InstSizeVerifyMode::NoVerify;
10549 return InstSizeVerifyMode::ExactSize;
10554 static const std::pair<int, const char *> TargetIndices[] = {
10594std::pair<unsigned, unsigned>
10601 static const std::pair<unsigned, const char *> TargetFlags[] = {
10619 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10637 return AMDGPU::WWM_COPY;
10639 return AMDGPU::COPY;
10656 if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
10660 if (RI.isSGPRClass(RI.getRegClassForReg(
MRI, Reg)))
10661 return IsLRSplitInst;
10674 bool IsNullOrVectorRegister =
true;
10678 IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(
MRI, Reg));
10681 return IsNullOrVectorRegister &&
10683 (!
MI.isTerminator() &&
MI.getOpcode() != AMDGPU::COPY &&
10684 MI.modifiesRegister(AMDGPU::EXEC, &RI)));
10692 if (ST.hasAddNoCarryInsts())
10696 Register UnusedCarry =
MRI.createVirtualRegister(RI.getBoolRC());
10697 MRI.setRegAllocationHint(UnusedCarry, 0, RI.getVCC());
10708 if (ST.hasAddNoCarryInsts())
10712 Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
10714 : RS.scavengeRegisterBackwards(
10715 *RI.getBoolRC(),
I,
false,
10728 case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
10729 case AMDGPU::SI_KILL_I1_TERMINATOR:
10738 case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
10739 return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
10740 case AMDGPU::SI_KILL_I1_PSEUDO:
10741 return get(AMDGPU::SI_KILL_I1_TERMINATOR);
10753 const unsigned OffsetBits =
10755 return (1 << OffsetBits) - 1;
10759 if (!ST.isWave32())
10762 if (
MI.isInlineAsm())
10765 if (
MI.getNumOperands() <
MI.getDesc().getNumOperands())
10768 for (
auto &
Op :
MI.implicit_operands()) {
10769 if (
Op.isReg() &&
Op.getReg() == AMDGPU::VCC)
10770 Op.setReg(AMDGPU::VCC_LO);
10779 int Idx = AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::sbase);
10783 const int16_t RCID = getOpRegClassID(
MI.getDesc().operands()[Idx]);
10784 return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
10800 if (
Imm > MaxImm) {
10801 if (
Imm <= MaxImm + 64) {
10803 Overflow =
Imm - MaxImm;
10818 Overflow =
High - Alignment.value();
10822 if (Overflow > 0) {
10830 if (ST.hasRestrictedSOffset())
10835 SOffset = Overflow;
10873 if (!ST.hasFlatInstOffsets())
10877 if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
10882 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10883 FlatVariant == FlatAddrSpace::FlatScratch &&
Offset < 0 &&
10894std::pair<int64_t, int64_t>
10897 int64_t RemainderOffset = COffsetVal;
10898 int64_t ImmField = 0;
10903 if (AllowNegative) {
10905 int64_t
D = 1LL << NumBits;
10906 RemainderOffset = (COffsetVal /
D) *
D;
10907 ImmField = COffsetVal - RemainderOffset;
10909 if (ST.hasNegativeUnalignedScratchOffsetBug() &&
10911 (ImmField % 4) != 0) {
10913 RemainderOffset += ImmField % 4;
10914 ImmField -= ImmField % 4;
10916 }
else if (COffsetVal >= 0) {
10918 RemainderOffset = COffsetVal - ImmField;
10922 assert(RemainderOffset + ImmField == COffsetVal);
10923 return {ImmField, RemainderOffset};
10928 if (ST.hasNegativeScratchOffsetBug() &&
10936 switch (ST.getGeneration()) {
10970 case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
10971 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
10972 case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
10973 case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
10974 case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
10975 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
10976 case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
10977 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
10984#define GENERATE_RENAMED_GFX9_CASES(OPCODE) \
10985 case OPCODE##_dpp: \
10986 case OPCODE##_e32: \
11000 case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
11001 case AMDGPU::V_FMA_F16_gfx9_e64:
11002 case AMDGPU::V_INTERP_P2_F16:
11003 case AMDGPU::V_MAD_F16_e64:
11004 case AMDGPU::V_MAD_U16_e64:
11005 case AMDGPU::V_MAD_I16_e64:
11006 case AMDGPU::V_MAD_U16_gfx9_e64:
11007 case AMDGPU::V_MAD_I16_gfx9_e64:
11016 "SIInsertWaitcnts should have promoted soft waitcnt instructions!");
11024 switch (ST.getGeneration()) {
11037 if (
isMAI(Opcode)) {
11051 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
11054 if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
11061 if (ST.hasGFX90AInsts()) {
11062 uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
11063 if (ST.hasGFX940Insts())
11065 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
11067 if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
11069 if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
11075 if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
11094 for (
unsigned I = 0, E = (
MI.getNumOperands() - 1)/ 2;
I < E; ++
I)
11095 if (
MI.getOperand(1 + 2 *
I + 1).getImm() == SubReg) {
11096 auto &RegOp =
MI.getOperand(1 + 2 *
I);
11108 switch (
MI.getOpcode()) {
11110 case AMDGPU::REG_SEQUENCE:
11114 case AMDGPU::INSERT_SUBREG:
11115 if (RSR.
SubReg == (
unsigned)
MI.getOperand(3).getImm())
11132 if (!
P.Reg.isVirtual())
11136 auto *DefInst =
MRI.getVRegDef(RSR.Reg);
11137 while (
auto *
MI = DefInst) {
11139 switch (
MI->getOpcode()) {
11141 case AMDGPU::V_MOV_B32_e32: {
11142 auto &Op1 =
MI->getOperand(1);
11147 DefInst =
MRI.getVRegDef(RSR.Reg);
11155 DefInst =
MRI.getVRegDef(RSR.Reg);
11168 assert(
MRI.isSSA() &&
"Must be run on SSA");
11170 auto *
TRI =
MRI.getTargetRegisterInfo();
11171 auto *DefBB =
DefMI.getParent();
11175 if (
UseMI.getParent() != DefBB)
11178 const int MaxInstScan = 20;
11182 auto E =
UseMI.getIterator();
11183 for (
auto I = std::next(
DefMI.getIterator());
I != E; ++
I) {
11184 if (
I->isDebugInstr())
11187 if (++NumInst > MaxInstScan)
11190 if (
I->modifiesRegister(AMDGPU::EXEC,
TRI))
11200 assert(
MRI.isSSA() &&
"Must be run on SSA");
11202 auto *
TRI =
MRI.getTargetRegisterInfo();
11203 auto *DefBB =
DefMI.getParent();
11205 const int MaxUseScan = 10;
11208 for (
auto &
Use :
MRI.use_nodbg_operands(VReg)) {
11209 auto &UseInst = *
Use.getParent();
11212 if (UseInst.getParent() != DefBB || UseInst.isPHI())
11215 if (++NumUse > MaxUseScan)
11222 const int MaxInstScan = 20;
11226 for (
auto I = std::next(
DefMI.getIterator()); ; ++
I) {
11229 if (
I->isDebugInstr())
11232 if (++NumInst > MaxInstScan)
11245 if (Reg == VReg && --NumUse == 0)
11247 }
else if (
TRI->regsOverlap(Reg, AMDGPU::EXEC))
11256 auto Cur =
MBB.begin();
11257 if (Cur !=
MBB.end())
11259 if (!Cur->isPHI() && Cur->readsRegister(Dst,
nullptr))
11262 }
while (Cur !=
MBB.end() && Cur != LastPHIIt);
11271 if (InsPt !=
MBB.end() &&
11272 (InsPt->getOpcode() == AMDGPU::SI_IF ||
11273 InsPt->getOpcode() == AMDGPU::SI_ELSE ||
11274 InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
11275 InsPt->definesRegister(Src,
nullptr)) {
11279 .
addReg(Src, {}, SrcSubReg)
11322 if (isFullCopyInstr(
MI)) {
11323 Register DstReg =
MI.getOperand(0).getReg();
11324 Register SrcReg =
MI.getOperand(1).getReg();
11331 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
11335 MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_64_XEXECRegClass);
11346 unsigned *PredCost)
const {
11347 if (
MI.isBundle()) {
11350 unsigned Lat = 0,
Count = 0;
11351 for (++
I;
I != E &&
I->isBundledWithPred(); ++
I) {
11353 Lat = std::max(Lat, SchedModel.computeInstrLatency(&*
I));
11355 return Lat +
Count - 1;
11358 return SchedModel.computeInstrLatency(&
MI);
11362 if (!ST.hasGFX1250VALUBlockingCycles())
11369 if (
const auto *Entry = AMDGPU::getGFX1250BlockingCyclesInfo(
MI.getOpcode()))
11370 return Entry->GFX1250BlockingCycles;
11378 return *CallAddrOp;
11385 unsigned Opcode =
MI.getOpcode();
11390 LLT DstTy =
MRI.getType(Dst);
11391 LLT SrcTy =
MRI.getType(Src);
11393 unsigned SrcAS = SrcTy.getAddressSpace();
11396 ST.hasGloballyAddressableScratch()
11404 if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
11405 return HandleAddrSpaceCast(
MI);
11408 auto IID = GI->getIntrinsicID();
11415 case Intrinsic::amdgcn_if:
11416 case Intrinsic::amdgcn_else:
11430 if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
11431 Opcode == AMDGPU::G_SEXTLOAD) {
11432 if (
MI.memoperands_empty())
11436 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11437 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11445 if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
11446 Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
11447 Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
11453 if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
11456 if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
11464 Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
11465 return Formatter.get();
11473 unsigned opcode =
MI.getOpcode();
11474 if (opcode == AMDGPU::V_READLANE_B32 ||
11475 opcode == AMDGPU::V_READFIRSTLANE_B32 ||
11476 opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
11481 if (
MI.isInlineAsm()) {
11487 if (!RC || !RI.isSGPRClass(RC))
11492 if (isCopyInstr(
MI)) {
11496 RI.getPhysRegBaseClass(srcOp.
getReg());
11504 if (
MI.isPreISelOpcode())
11519 if (
MI.memoperands_empty())
11523 return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
11524 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
11539 for (
unsigned I = 0, E =
MI.getNumOperands();
I != E; ++
I) {
11541 if (!
SrcOp.isReg())
11545 if (!Reg || !
SrcOp.readsReg())
11551 if (RegBank && RegBank->
getID() != AMDGPU::SGPRRegBankID)
11578 F,
"ds_ordered_count unsupported for this calling conv"));
11592 Register &SrcReg2, int64_t &CmpMask,
11593 int64_t &CmpValue)
const {
11594 if (!
MI.getOperand(0).isReg() ||
MI.getOperand(0).getSubReg())
11597 switch (
MI.getOpcode()) {
11600 case AMDGPU::S_CMP_EQ_U32:
11601 case AMDGPU::S_CMP_EQ_I32:
11602 case AMDGPU::S_CMP_LG_U32:
11603 case AMDGPU::S_CMP_LG_I32:
11604 case AMDGPU::S_CMP_LT_U32:
11605 case AMDGPU::S_CMP_LT_I32:
11606 case AMDGPU::S_CMP_GT_U32:
11607 case AMDGPU::S_CMP_GT_I32:
11608 case AMDGPU::S_CMP_LE_U32:
11609 case AMDGPU::S_CMP_LE_I32:
11610 case AMDGPU::S_CMP_GE_U32:
11611 case AMDGPU::S_CMP_GE_I32:
11612 case AMDGPU::S_CMP_EQ_U64:
11613 case AMDGPU::S_CMP_LG_U64:
11614 SrcReg =
MI.getOperand(0).getReg();
11615 if (
MI.getOperand(1).isReg()) {
11616 if (
MI.getOperand(1).getSubReg())
11618 SrcReg2 =
MI.getOperand(1).getReg();
11620 }
else if (
MI.getOperand(1).isImm()) {
11622 CmpValue =
MI.getOperand(1).getImm();
11628 case AMDGPU::S_CMPK_EQ_U32:
11629 case AMDGPU::S_CMPK_EQ_I32:
11630 case AMDGPU::S_CMPK_LG_U32:
11631 case AMDGPU::S_CMPK_LG_I32:
11632 case AMDGPU::S_CMPK_LT_U32:
11633 case AMDGPU::S_CMPK_LT_I32:
11634 case AMDGPU::S_CMPK_GT_U32:
11635 case AMDGPU::S_CMPK_GT_I32:
11636 case AMDGPU::S_CMPK_LE_U32:
11637 case AMDGPU::S_CMPK_LE_I32:
11638 case AMDGPU::S_CMPK_GE_U32:
11639 case AMDGPU::S_CMPK_GE_I32:
11640 SrcReg =
MI.getOperand(0).getReg();
11642 CmpValue =
MI.getOperand(1).getImm();
11652 if (S->isLiveIn(AMDGPU::SCC))
11661bool SIInstrInfo::invertSCCUse(
MachineInstr *SCCDef)
const {
11664 bool SCCIsDead =
false;
11667 constexpr unsigned ScanLimit = 12;
11668 unsigned Count = 0;
11671 if (++
Count > ScanLimit)
11673 if (
MI.readsRegister(AMDGPU::SCC, &RI)) {
11674 if (
MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
11675 MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
11676 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11677 MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
11682 if (
MI.definesRegister(AMDGPU::SCC, &RI)) {
11695 for (MachineInstr *
MI : InvertInstr) {
11696 if (
MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
11697 MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
11699 }
else if (
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
11700 MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
11701 MI->setDesc(
get(
MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
11702 ? AMDGPU::S_CBRANCH_SCC1
11703 : AMDGPU::S_CBRANCH_SCC0));
11716 bool NeedInversion)
const {
11717 MachineInstr *KillsSCC =
nullptr;
11722 if (
MI.modifiesRegister(AMDGPU::SCC, &RI))
11724 if (
MI.killsRegister(AMDGPU::SCC, &RI))
11727 if (NeedInversion && !invertSCCUse(SCCRedefine))
11729 if (MachineOperand *SccDef =
11731 SccDef->setIsDead(
false);
11740static std::optional<std::pair<int64_t, int64_t>>
11744 if (
Opc != AMDGPU::S_CSELECT_B32 &&
Opc != AMDGPU::S_CSELECT_B64)
11746 std::optional<int64_t>
A =
11750 std::optional<int64_t>
B =
11754 if (
Opc == AMDGPU::S_CSELECT_B32) {
11760 return std::pair(*
A, *
B);
11764 unsigned &NewDefOpc) {
11767 if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
11768 Def.getOpcode() != AMDGPU::S_ADD_U32)
11774 Def.getMF()->getSubtarget().getInstrInfo());
11776 auto Imm1 =
TII->getImmOrMaterializedImm(
MRI, AddSrc1);
11777 auto Imm2 =
TII->getImmOrMaterializedImm(
MRI, AddSrc2);
11778 if ((!Imm1 || *Imm1 != 1) && (!Imm2 || *Imm2 != 1))
11781 if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
11783 Def.findRegisterDefOperand(AMDGPU::SCC,
nullptr);
11786 NewDefOpc = AMDGPU::S_ADD_U32;
11788 NeedInversion = !NeedInversion;
11793 Register SrcReg2, int64_t CmpMask,
11803 CmpValue = *ImmOpt;
11806 const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue,
MRI,
11807 this](
bool NeedInversion) ->
bool {
11812 unsigned NewDefOpc = Def->getOpcode();
11819 auto [
A,
B] = *Consts;
11820 int64_t
C = Def->getOpcode() == AMDGPU::S_CSELECT_B32 ?
Lo_32(CmpValue)
11823 NeedInversion = !NeedInversion;
11835 if (CmpValue != 0 ||
11841 if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
11844 if (NewDefOpc != Def->getOpcode())
11845 Def->setDesc(
get(NewDefOpc));
11854 if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
11855 MRI->use_nodbg_empty(Def->getOperand(0).getReg())) {
11861 if (Def1 && Def1->
getOpcode() == AMDGPU::COPY && Def2 &&
11870 auto [
A,
B] = *Consts;
11871 if (
A == 0 ||
B == 0)
11872 optimizeSCC(
Select, Def,
A == 0);
11881 const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue,
MRI,
11882 this](int64_t ExpectedValue,
unsigned SrcSize,
11883 bool IsReversible,
bool IsSigned) ->
bool {
11911 if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
11912 Def->getOpcode() != AMDGPU::S_AND_B64)
11916 const auto isMask = [&Mask, SrcSize,
MRI,
11928 SrcOp = &Def->getOperand(2);
11929 else if (isMask(&Def->getOperand(2)))
11930 SrcOp = &Def->getOperand(1);
11938 if (IsSigned && BitNo == SrcSize - 1)
11941 ExpectedValue <<= BitNo;
11943 bool IsReversedCC =
false;
11944 if (CmpValue != ExpectedValue) {
11947 IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
11952 Register DefReg = Def->getOperand(0).getReg();
11953 if (IsReversedCC && !
MRI->hasOneNonDBGUse(DefReg))
11956 if (!optimizeSCC(Def, &CmpInstr,
false))
11959 if (!
MRI->use_nodbg_empty(DefReg)) {
11967 unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
11968 : AMDGPU::S_BITCMP1_B32
11969 : IsReversedCC ? AMDGPU::S_BITCMP0_B64
11970 : AMDGPU::S_BITCMP1_B64;
11975 Def->eraseFromParent();
11983 case AMDGPU::S_CMP_EQ_U32:
11984 case AMDGPU::S_CMP_EQ_I32:
11985 case AMDGPU::S_CMPK_EQ_U32:
11986 case AMDGPU::S_CMPK_EQ_I32:
11987 return optimizeCmpAnd(1, 32,
true,
false) ||
11988 optimizeCmpSelect(
true);
11989 case AMDGPU::S_CMP_GE_U32:
11990 case AMDGPU::S_CMPK_GE_U32:
11991 return optimizeCmpAnd(1, 32,
false,
false);
11992 case AMDGPU::S_CMP_GE_I32:
11993 case AMDGPU::S_CMPK_GE_I32:
11994 return optimizeCmpAnd(1, 32,
false,
true);
11995 case AMDGPU::S_CMP_EQ_U64:
11996 return optimizeCmpAnd(1, 64,
true,
false) ||
11997 optimizeCmpSelect(
true);
11998 case AMDGPU::S_CMP_LG_U32:
11999 case AMDGPU::S_CMP_LG_I32:
12000 case AMDGPU::S_CMPK_LG_U32:
12001 case AMDGPU::S_CMPK_LG_I32:
12002 return optimizeCmpAnd(0, 32,
true,
false) ||
12003 optimizeCmpSelect(
false);
12004 case AMDGPU::S_CMP_GT_U32:
12005 case AMDGPU::S_CMPK_GT_U32:
12006 return optimizeCmpAnd(0, 32,
false,
false);
12007 case AMDGPU::S_CMP_GT_I32:
12008 case AMDGPU::S_CMPK_GT_I32:
12009 return optimizeCmpAnd(0, 32,
false,
true);
12010 case AMDGPU::S_CMP_LG_U64:
12011 return optimizeCmpAnd(0, 64,
true,
false) ||
12012 optimizeCmpSelect(
false);
12019 AMDGPU::OpName
OpName)
const {
12020 if (!ST.needsAlignedVGPRs())
12023 int OpNo = AMDGPU::getNamedOperandIdx(
MI.getOpcode(),
OpName);
12035 bool IsAGPR = RI.isAGPR(
MRI, DataReg);
12037 IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
12040 MRI.createVirtualRegister(IsAGPR ? &AMDGPU::AReg_64_Align2RegClass
12041 : &AMDGPU::VReg_64_Align2RegClass);
12043 .
addReg(DataReg, {},
Op.getSubReg())
12048 Op.setSubReg(AMDGPU::sub0);
12053 if (!SchedModel.hasInstrSchedModel())
12059 unsigned RepeatRate = 0;
12061 PI = SchedModel.getWriteProcResBegin(SCDesc),
12062 PE = SchedModel.getWriteProcResEnd(SCDesc);
12064 RepeatRate = std::max(RepeatRate, (
unsigned)PI->ReleaseAtCycle);
12081 if (ST.hasGFX1250Insts())
12088 unsigned Opcode =
MI.getOpcode();
12094 Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
12095 Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
12098 if (!ST.hasGFX940Insts())
12105 constexpr unsigned MinOrderedXDLVAVDSTVGPRs = 8;
12112 return DstRC && RI.isVGPRClass(DstRC) &&
12113 RI.getRegSizeInBits(*DstRC) >= MinOrderedXDLVAVDSTVGPRs * 32;
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static const TargetRegisterClass * getRegClass(const MachineInstr &MI, Register Reg)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Shared AMDGPU asyncmark stage definitions.
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< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
AMD GCN specific subclass of TargetSubtarget.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
static Register UseReg(const MachineOperand &MO)
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
SmallVector< MachineOperand, 4 > Cond
MachineRegisterInfo & MRI
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
This file declares the machine register scavenger class.
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 std::optional< std::pair< int64_t, int64_t > > getSelectConstants(const SIInstrInfo &TII, const MachineRegisterInfo &MRI, const MachineInstr &Sel)
If Sel is an S_CSELECT* of two different constants A and B, return them, truncated to the width of th...
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 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 bool isVCmp(const SIInstrInfo &TII, const MachineInstr &MI)
Return true if MI is a VALU comparison, i.e.
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 isLegalPkF32OpSel(const SIInstrInfo &TII, const MachineInstr &MI, bool CheckSwappedSrc=false)
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 bool changesVGPRIndexingMode(const MachineInstr &MI)
static bool isSubRegOf(const SIRegisterInfo &TRI, const MachineOperand &SuperVec, const MachineOperand &SubReg)
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 std::pair< unsigned, unsigned > splitGlobalAddressRelocFlags(const MachineOperand &SrcOp)
static unsigned getNumOperandsNoGlue(SDNode *Node)
static bool canRemat(const MachineInstr &MI)
static unsigned getAVSpillRestoreOpcode(unsigned Size)
static void emitLoadScalarOpsFromVGPRLoop(const SIInstrInfo &TII, MachineRegisterInfo &MRI, MachineBasicBlock &PredBB, MachineBasicBlock &LoopBB, MachineBasicBlock &BodyBB, const DebugLoc &DL, ArrayRef< MachineOperand * > ScalarOps, ArrayRef< Register > PhySGPRs={})
static unsigned getVGPRSpillRestoreOpcode(unsigned Size)
Interface definition for SIInstrInfo.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
const unsigned AndN2WrExecOpc
static const LaneMaskConstants & get(const GCNSubtarget &ST)
const unsigned XorTermOpc
const unsigned MovTermOpc
const unsigned OrSaveExecOpc
const unsigned AndSaveExecOpc
static LLVM_ABI Semantics SemanticsToEnum(const llvm::fltSemantics &Sem)
Class for arbitrary precision integers.
int64_t getSExtValue() const
Get sign extended value.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & front() const
Get the first element.
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
This class is the base class for the comparison instructions.
uint64_t getZExtValue() const
Opaque handle to a cycle within a GenericCycleInfo that wraps the cycle's preorder index.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Diagnostic information for unsupported feature in backend.
void changeImmediateDominator(DomTreeNodeBase< NodeT > *N, DomTreeNodeBase< NodeT > *NewIDom)
changeImmediateDominator - This method is used to update the dominator tree information when a node's...
DomTreeNodeBase< NodeT > * addNewBlock(NodeT *BB, NodeT *DomBB)
Add a new node to the dominator tree information.
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
void getExitingBlocks(CycleRef C, SmallVectorImpl< BlockT * > &TmpStorage) const
Return all blocks of C that have a successor outside of C.
CycleRef getParentCycle(CycleRef C) const
bool contains(CycleRef Outer, CycleRef Inner) const
Returns true iff Outer contains Inner. O(1). Non-strict.
CycleRef getCycle(const BlockT *Block) const
Find the innermost cycle containing Block.
Itinerary data supplied by a subtarget to be used by a target.
constexpr unsigned getAddressSpace() const
This is an important class for using LLVM in a threaded context.
A live range for subregisters.
LiveInterval - This class represents the liveness of a register, or stack slot.
iterator_range< subrange_iterator > subranges()
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.
static LocationSize precise(uint64_t Value)
TypeSize getValue() const
static const MCBinaryExpr * createAnd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCBinaryExpr * createAShr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
unsigned getSize() const
Return the number of bytes in the encoding of this instruction, or zero if the encoding size cannot b...
ArrayRef< MCPhysReg > implicit_uses() const
Return a list of registers that are potentially read by any instance of this machine instruction.
unsigned getOpcode() const
Return the opcode number for this descriptor.
This holds information about one operand of a machine instruction, indicating the register class for ...
uint8_t OperandType
Information about the type of the operand.
int16_t RegClass
This specifies the register class enumeration of the operand if the operand is a register.
bool hasSuperClassEq(const MCRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
Wrapper class representing physical registers. Should be passed by value.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
LLVM_ABI void setVariableValue(const MCExpr *Value)
Helper class for constructing bundles of MachineInstrs.
MachineBasicBlock::instr_iterator begin() const
Return an iterator to the first bundled instruction.
MIBundleBuilder & append(MachineInstr *MI)
Insert MI into MBB by appending it to the instructions in the bundle.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
void push_back(MachineInstr *MI)
LLVM_ABI LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, MCRegister Reg, const_iterator Before, unsigned Neighborhood=10) const
Return whether (physical) register Reg has been defined and not killed as of just before Before.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
Instructions::const_iterator const_instr_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< succ_iterator > successors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
@ LQR_Dead
Register is known to be fully dead.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool isImmutableObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to an immutable object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void push_back(MachineBasicBlock *MBB)
MCContext & getContext() const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const
Copy all the implicit operands from OtherMI onto this one.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
const MachineBasicBlock * getParent() const
LLVM_ABI void addImplicitDefUseOperands(MachineFunction &MF)
Add all implicit def and use operands to this instruction.
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
LLVM_ABI unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
mop_range implicit_operands()
bool modifiesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr modifies (fully define or partially define) the specified register.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
LLVM_ABI bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore,...
void untieRegOperand(unsigned OpIdx)
Break any tie involving OpIdx.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
LLVM_ABI void eraseFromBundle()
Unlink 'this' from its basic block and delete it.
bool hasOneMemOperand() const
Return true if this instruction has exactly one MachineMemOperand.
mop_range explicit_operands()
LLVM_ABI void tieOperands(unsigned DefIdx, unsigned UseIdx)
Add a tie between the register operands at DefIdx and UseIdx.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
LLVM_ABI bool hasOrderedMemoryRef() const
Return true if this instruction may have an ordered or volatile memory reference, or if the informati...
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
bool isMoveImmediate(QueryType Type=IgnoreBundle) const
Return true if this instruction is a move immediate (including conditional moves) instruction.
LLVM_ABI void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
filtered_mop_range all_uses()
Returns an iterator range over all operands that are (explicit or implicit) register uses.
LLVM_ABI void setPostInstrSymbol(MachineFunction &MF, MCSymbol *Symbol)
Set a symbol that will be emitted just after the instruction itself.
LLVM_ABI void clearRegisterKills(Register Reg, const TargetRegisterInfo *RegInfo)
Clear all kill flags affecting Reg.
const MachineOperand & getOperand(unsigned i) const
uint32_t getFlags() const
Return the MI flags bitvector.
LLVM_ABI int findRegisterDefOperandIdx(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false) const
Returns the operand index that is a def of the specified register or -1 if it is not found.
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
MachineOperand * findRegisterDefOperand(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false)
Wrapper for findRegisterDefOperandIdx, it returns a pointer to the MachineOperand rather than an inde...
A description of a memory reference used in the backend.
@ 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)
bool isEarlyClobber() const
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,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
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 Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
const MachineFunction & getMF() const
void setSimpleHint(Register VReg, Register PrefReg)
Specify the preferred (target independent) register allocation hint for the specified virtual registe...
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 replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
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 std::optional< unsigned > extractSubregFromGlobalAddressFlags(unsigned TargetFlags, unsigned SubRegIndex)
Return the target flags for a global address operand reading subregister SubRegIndex of a 64-bit glob...
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
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 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)
unsigned getGFX1250BlockingCyclesTable(const MachineInstr &MI) const
GFX1250 blocking-cycles table lookup with no occupancy subtarget gate.
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
bool getMemOperandsWithOffsetWidth(const MachineInstr &LdSt, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width) const final
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
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
static bool usesTENSOR_CNT(const MachineInstr &MI)
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
bool canInsertSelect(const MachineBasicBlock &MBB, ArrayRef< MachineOperand > Cond, Register DstReg, Register TrueReg, Register FalseReg, SelectExpansion &Exp) const override
static bool isVSAMPLE(const MachineInstr &MI)
bool isBufferSMRD(const MachineInstr &MI) const
static bool isKillTerminator(unsigned Opcode)
bool isVOPDAntidependencyAllowed(const MachineInstr &MI) const
If OpX is multicycle, anti-dependencies are not allowed.
bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx0, unsigned &SrcOpIdx1) const override
void insertScratchExecCopy(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register Reg, bool IsSCCLive, SlotIndexes *Indexes=nullptr) const
bool hasVALU32BitEncoding(unsigned Opcode) const
Return true if this 64-bit VALU instruction has a 32-bit encoding.
unsigned getBlockingCycles(const MachineInstr &MI) const
unsigned getMovOpcode(const TargetRegisterClass *DstRC) const
Register isSGPRStackAccess(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const
unsigned buildExtractSubReg(MachineBasicBlock::iterator MI, MachineRegisterInfo &MRI, const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC, unsigned SubIdx, const TargetRegisterClass *SubRC) const
void legalizeOperandsVOP2(MachineRegisterInfo &MRI, MachineInstr &MI) const
Legalize operands in MI by either commuting it or inserting a copy of src1.
static bool isVPermPk16(unsigned Opcode)
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
AMDGPU::AsyncStages getAsyncStage(const MachineInstr &MI) const
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.
bool isVAVDSTOrderedXDL(const MachineInstr &MI) const
On gfx1250, an XDL instruction whose destination spans at least eight VGPRs decrements VA_VDST only a...
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.
static bool usesASYNC_CNT(const MachineInstr &MI)
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
bool isMaskedByExec(Register Reg, const MachineInstr &Use, const MachineRegisterInfo &MRI, unsigned Depth=0) const
Return true if Reg is a lane mask that already has 0 in every bit corresponding to a lane that is ina...
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 isAsync(const MachineInstr &MI) const
bool memOpsHaveSameBase(ArrayRef< const MachineOperand * > BaseOps1, ArrayRef< const MachineOperand * > BaseOps2) const
Return true if the memory operations described by BaseOps1 and BaseOps2 (as returned by getMemOperand...
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 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
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.
MachineInstr * convertToThreeAddress(MachineInstr &MI, LiveIntervals *LIS) const override
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
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
ArrayRef< int16_t > getRegSplitParts(const TargetRegisterClass *RC, unsigned EltSize) const
unsigned getHWRegIndex(MCRegister Reg) const
static unsigned getSubRegFromChannel(uint64_t Channel, uint64_t NumRegs=1)
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.
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)
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)
constexpr bool isValidAsyncStageMask(int64_t Mask)
AsyncStages
Bit mask of the async stages tracked by the asyncmark / wait_asyncmark intrinsics.
@ GLOBAL_LOAD_ASYNC_TO_LDS
@ GLOBAL_LOAD_ASYNC_TO_LDS_MCAST
@ GLOBAL_STORE_ASYNC_FROM_LDS
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)
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 bool hasNamedOperand(uint32_t Opcode, OpName NamedIdx)
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.
bool isInlinableLiteralBF16(int16_t Literal, bool HasInv2Pi, bool *IsBF16)
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 isGFX1250(const MCSubtargetInfo &STI)
bool isSingleSGPRReadInst(unsigned Opc)
Packed instructions that read a single SGPR for SGPR operands, except for 64-bit elements which read ...
bool supportsScaleOffset(const MCInstrInfo &MII, unsigned Opcode)
const uint64_t RSRC_INDEX_STRIDE_SHIFT
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
LLVM_READONLY int32_t getFlatScratchInstSVfromSS(uint32_t Opcode)
bool isInlinableLiteralI16(int32_t Literal, bool HasInv2Pi)
LLVM_READNONE constexpr bool isGraphics(CallingConv::ID CC)
bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi)
Is this literal inlinable.
@ AMDGPU_CS
Used for Mesa/AMDPAL compute shaders.
@ AMDGPU_VS
Used for Mesa vertex shaders, or AMDPAL last shader stage before rasterization (vertex shader if tess...
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ AMDGPU_HS
Used for Mesa/AMDPAL hull shaders (= tessellation control shaders).
@ AMDGPU_GS
Used for Mesa/AMDPAL geometry shaders.
@ AMDGPU_PS
Used for Mesa/AMDPAL pixel shaders.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ AMDGPU_ES
Used for AMDPAL shader stage before geometry shader if geometry is in use.
@ AMDGPU_LS
Used for AMDPAL vertex shader if tessellation is in use.
@ C
The default llvm calling convention, compatible with C.
Not(const Pred &P) -> Not< Pred >
constexpr bool isSDWA(const T &...O)
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
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...
static const MachineMemOperand::Flags MOCFSB1
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.
auto instructionsWithoutDebug(IterT It, IterT End, bool SkipPseudoOp=true)
Construct a range iterator which begins at It and moves forwards until End is reached,...
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI VirtRegInfo AnalyzeVirtRegInBundle(MachineInstr &MI, Register Reg, SmallVectorImpl< std::pair< MachineInstr *, unsigned > > *Ops=nullptr)
AnalyzeVirtRegInBundle - Analyze how the current instruction or bundle uses a virtual register.
static const MachineMemOperand::Flags MOCooperative
Mark the MMO of cooperative load/store atomics.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
bool isTargetSpecificOpcode(unsigned Opcode)
Check whether the given Opcode is a target-specific opcode.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned DefaultMemoryClusterDWordsLimit
constexpr unsigned BitWidth
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
static const MachineMemOperand::Flags MOLastUse
Mark the MMO of a load as the last use.
constexpr T reverseBits(T Val)
Reverse the bits in Val.
static const MachineMemOperand::Flags MOCFSB0
Use two MMO flags to encode the 2-bit cache fill size field for GFX13+.
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.
@ End
Run the machine verifier once, at the end of the pipeline.
constexpr RegState getUndefRegState(bool B)
ValueUniformity
Enum describing how values behave with respect to uniformity and divergence, to answer the question: ...
@ AlwaysUniform
The result value is always uniform.
@ NeverUniform
The result value can never be assumed to be uniform.
@ Default
The result value is uniform if and only if all operands are uniform.
static const MachineMemOperand::Flags MOThreadPrivate
Mark the MMO of accesses to memory locations that are never written to by other threads.
bool execMayBeModifiedBeforeAnyUse(const MachineRegisterInfo &MRI, Register VReg, const MachineInstr &DefMI)
Return false if EXEC is not changed between the def of VReg at DefMI and all its uses.
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Helper struct for the implementation of 3-address conversion to communicate updates made to instructi...
MachineInstr * RemoveMIUse
Other instruction whose def is no longer used by the converted instruction.
uint8_t GFX1250BlockingCycles
static constexpr uint64_t encode(Fields... Values)
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr bool all() const
This represents a simple continuous liveness interval for a value.
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.