28#include "llvm/IR/IntrinsicsAMDGPU.h"
31#define DEBUG_TYPE "amdgpu-isel"
36#define GET_GLOBALISEL_IMPL
37#define AMDGPUSubtarget GCNSubtarget
38#include "AMDGPUGenGlobalISel.inc"
39#undef GET_GLOBALISEL_IMPL
44 : TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()), RBI(RBI), STI(STI),
46#include
"AMDGPUGenGlobalISel.inc"
49#include
"AMDGPUGenGlobalISel.inc"
61 MRI = &
MF.getRegInfo();
69 return Def->getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS
70 ? Def->getOperand(1).getReg()
80 auto &RegClassOrBank = MRI.getRegClassOrRegBank(
Reg);
84 const LLT Ty = MRI.getType(
Reg);
93 return RB->
getID() == AMDGPU::VCCRegBankID;
96bool AMDGPUInstructionSelector::constrainCopyLikeIntrin(
MachineInstr &
MI,
97 unsigned NewOpc)
const {
98 MI.setDesc(TII.get(NewOpc));
110 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
112 TRI.getConstrainedRegClassForReg(SrcReg, *MRI);
113 if (!DstRC || DstRC != SrcRC)
116 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
117 !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI))
119 const MCInstrDesc &MCID =
MI.getDesc();
121 MI.getOperand(0).setIsEarlyClobber(
true);
126bool AMDGPUInstructionSelector::selectCOPY(
MachineInstr &
I)
const {
129 I.setDesc(TII.get(TargetOpcode::COPY));
131 Register DstReg =
I.getOperand(0).getReg();
132 Register SrcReg =
I.getOperand(1).getReg();
134 if (isVCC(DstReg, *MRI)) {
135 if (SrcReg == AMDGPU::SCC) {
137 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
140 return RBI.constrainGenericRegister(DstReg, *RC, *MRI);
143 if (!isVCC(SrcReg, *MRI)) {
145 if (!RBI.constrainGenericRegister(DstReg, *TRI.getBoolRC(), *MRI))
149 TRI.getConstrainedRegClassForReg(SrcReg, *MRI);
151 std::optional<ValueAndVReg> ConstVal =
155 STI.isWave64() ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
157 .
addImm(ConstVal->Value.getBoolValue() ? -1 : 0);
159 Register MaskedReg = MRI->createVirtualRegister(SrcRC);
166 assert(Subtarget->useRealTrue16Insts());
167 const int64_t NoMods = 0;
168 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::V_AND_B16_t16_e64), MaskedReg)
174 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::V_CMP_NE_U16_t16_e64), DstReg)
181 bool IsSGPR = TRI.isSGPRClass(SrcRC);
182 unsigned AndOpc = IsSGPR ? AMDGPU::S_AND_B32 : AMDGPU::V_AND_B32_e32;
189 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::V_CMP_NE_U32_e64), DstReg)
195 if (!MRI->getRegClassOrNull(SrcReg))
196 MRI->setRegClass(SrcReg, SrcRC);
202 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
203 if (RC && !RBI.constrainGenericRegister(DstReg, *RC, *MRI))
209 for (
const MachineOperand &MO :
I.operands()) {
210 if (MO.getReg().isPhysical())
214 TRI.getConstrainedRegClassForReg(MO.getReg(), *MRI);
217 RBI.constrainGenericRegister(MO.getReg(), *RC, *MRI);
222bool AMDGPUInstructionSelector::selectCOPY_SCC_VCC(
MachineInstr &
I)
const {
225 Register VCCReg =
I.getOperand(1).getReg();
229 if (STI.hasScalarCompareEq64()) {
231 STI.isWave64() ? AMDGPU::S_CMP_LG_U64 : AMDGPU::S_CMP_LG_U32;
234 Register DeadDst = MRI->createVirtualRegister(&AMDGPU::SReg_64RegClass);
235 Cmp =
BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_OR_B64), DeadDst)
242 Register DstReg =
I.getOperand(0).getReg();
246 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_32RegClass, *MRI);
249bool AMDGPUInstructionSelector::selectCOPY_VCC_SCC(
MachineInstr &
I)
const {
253 Register DstReg =
I.getOperand(0).getReg();
254 Register SrcReg =
I.getOperand(1).getReg();
255 std::optional<ValueAndVReg> Arg =
259 const int64_t
Value = Arg->Value.getZExtValue();
261 unsigned Opcode = STI.isWave64() ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
268 return RBI.constrainGenericRegister(DstReg, *TRI.getBoolRC(), *MRI);
274 unsigned SelectOpcode =
275 STI.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
285bool AMDGPUInstructionSelector::selectReadAnyLane(
MachineInstr &
I)
const {
286 Register DstReg =
I.getOperand(0).getReg();
287 Register SrcReg =
I.getOperand(1).getReg();
292 auto RFL =
BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
300bool AMDGPUInstructionSelector::selectPHI(
MachineInstr &
I)
const {
301 const Register DefReg =
I.getOperand(0).getReg();
302 const LLT DefTy = MRI->getType(DefReg);
314 MRI->getRegClassOrRegBank(DefReg);
325 DefRC = TRI.getRegClassForTypeOnBank(DefTy, RB);
334 for (
unsigned i = 1; i !=
I.getNumOperands(); i += 2) {
335 const Register SrcReg =
I.getOperand(i).getReg();
337 const RegisterBank *RB = MRI->getRegBankOrNull(SrcReg);
339 const LLT SrcTy = MRI->getType(SrcReg);
341 TRI.getRegClassForTypeOnBank(SrcTy, *RB);
342 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI))
347 I.setDesc(TII.get(TargetOpcode::PHI));
348 return RBI.constrainGenericRegister(DefReg, *DefRC, *MRI);
354 unsigned SubIdx)
const {
358 Register DstReg = MRI->createVirtualRegister(&SubRC);
361 unsigned ComposedSubIdx = TRI.composeSubRegIndices(MO.
getSubReg(), SubIdx);
363 BuildMI(*BB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::COPY), DstReg)
389 return Is64 ? AMDGPU::S_AND_B64 : AMDGPU::S_AND_B32;
391 return Is64 ? AMDGPU::S_OR_B64 : AMDGPU::S_OR_B32;
393 return Is64 ? AMDGPU::S_XOR_B64 : AMDGPU::S_XOR_B32;
399bool AMDGPUInstructionSelector::selectG_AND_OR_XOR(
MachineInstr &
I)
const {
400 Register DstReg =
I.getOperand(0).getReg();
401 unsigned Size = RBI.getSizeInBits(DstReg, *MRI, TRI);
403 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
404 if (DstRB->
getID() != AMDGPU::SGPRRegBankID &&
405 DstRB->
getID() != AMDGPU::VCCRegBankID)
408 bool Is64 =
Size > 32 || (DstRB->
getID() == AMDGPU::VCCRegBankID &&
421bool AMDGPUInstructionSelector::selectG_ADD_SUB(
MachineInstr &
I)
const {
424 Register DstReg =
I.getOperand(0).getReg();
426 LLT Ty = MRI->getType(DstReg);
431 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
432 const bool IsSALU = DstRB->
getID() == AMDGPU::SGPRRegBankID;
433 const bool Sub =
I.getOpcode() == TargetOpcode::G_SUB;
437 const unsigned Opc =
Sub ? AMDGPU::S_SUB_U32 : AMDGPU::S_ADD_U32;
440 .
add(
I.getOperand(1))
441 .
add(
I.getOperand(2))
448 if (STI.hasAddNoCarryInsts()) {
449 const unsigned Opc =
Sub ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_ADD_U32_e64;
450 I.setDesc(TII.get(
Opc));
457 const unsigned Opc =
Sub ? AMDGPU::V_SUB_CO_U32_e64 : AMDGPU::V_ADD_CO_U32_e64;
459 Register UnusedCarry = MRI->createVirtualRegister(TRI.getWaveMaskRegClass());
463 .
add(
I.getOperand(1))
464 .
add(
I.getOperand(2))
471 assert(!
Sub &&
"illegal sub should not reach here");
474 = IsSALU ? AMDGPU::SReg_64_XEXECRegClass : AMDGPU::VReg_64RegClass;
476 = IsSALU ? AMDGPU::SReg_32RegClass : AMDGPU::VGPR_32RegClass;
478 MachineOperand Lo1(getSubOperand64(
I.getOperand(1), HalfRC, AMDGPU::sub0));
479 MachineOperand Lo2(getSubOperand64(
I.getOperand(2), HalfRC, AMDGPU::sub0));
480 MachineOperand Hi1(getSubOperand64(
I.getOperand(1), HalfRC, AMDGPU::sub1));
481 MachineOperand Hi2(getSubOperand64(
I.getOperand(2), HalfRC, AMDGPU::sub1));
483 Register DstLo = MRI->createVirtualRegister(&HalfRC);
484 Register DstHi = MRI->createVirtualRegister(&HalfRC);
487 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_ADD_U32), DstLo)
490 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_ADDC_U32), DstHi)
496 Register CarryReg = MRI->createVirtualRegister(CarryRC);
497 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::V_ADD_CO_U32_e64), DstLo)
503 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::V_ADDC_U32_e64), DstHi)
513 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
520 if (!RBI.constrainGenericRegister(DstReg, RC, *MRI))
527bool AMDGPUInstructionSelector::selectG_UADDO_USUBO_UADDE_USUBE(
532 Register Dst0Reg =
I.getOperand(0).getReg();
533 Register Dst1Reg =
I.getOperand(1).getReg();
534 const bool IsAdd =
I.getOpcode() == AMDGPU::G_UADDO ||
535 I.getOpcode() == AMDGPU::G_UADDE;
536 const bool HasCarryIn =
I.getOpcode() == AMDGPU::G_UADDE ||
537 I.getOpcode() == AMDGPU::G_USUBE;
539 if (isVCC(Dst1Reg, *MRI)) {
540 unsigned NoCarryOpc =
541 IsAdd ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_SUB_CO_U32_e64;
542 unsigned CarryOpc = IsAdd ? AMDGPU::V_ADDC_U32_e64 : AMDGPU::V_SUBB_U32_e64;
543 I.setDesc(TII.get(HasCarryIn ? CarryOpc : NoCarryOpc));
550 Register Src0Reg =
I.getOperand(2).getReg();
551 Register Src1Reg =
I.getOperand(3).getReg();
554 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::SCC)
555 .
addReg(
I.getOperand(4).getReg());
558 unsigned NoCarryOpc = IsAdd ? AMDGPU::S_ADD_U32 : AMDGPU::S_SUB_U32;
559 unsigned CarryOpc = IsAdd ? AMDGPU::S_ADDC_U32 : AMDGPU::S_SUBB_U32;
561 auto CarryInst =
BuildMI(*BB, &
I,
DL, TII.get(HasCarryIn ? CarryOpc : NoCarryOpc), Dst0Reg)
562 .
add(
I.getOperand(2))
563 .
add(
I.getOperand(3));
565 if (MRI->use_nodbg_empty(Dst1Reg)) {
566 CarryInst.setOperandDead(3);
568 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), Dst1Reg)
570 if (!MRI->getRegClassOrNull(Dst1Reg))
571 MRI->setRegClass(Dst1Reg, &AMDGPU::SReg_32RegClass);
574 if (!RBI.constrainGenericRegister(Dst0Reg, AMDGPU::SReg_32RegClass, *MRI) ||
575 !RBI.constrainGenericRegister(Src0Reg, AMDGPU::SReg_32RegClass, *MRI) ||
576 !RBI.constrainGenericRegister(Src1Reg, AMDGPU::SReg_32RegClass, *MRI))
580 !RBI.constrainGenericRegister(
I.getOperand(4).getReg(),
581 AMDGPU::SReg_32RegClass, *MRI))
588bool AMDGPUInstructionSelector::selectG_AMDGPU_MAD_64_32(
592 const bool IsUnsigned =
I.getOpcode() == AMDGPU::G_AMDGPU_MAD_U64_U32;
593 bool UseNoCarry = Subtarget->hasMadNC64_32Insts() &&
594 MRI->use_nodbg_empty(
I.getOperand(1).getReg());
597 if (Subtarget->hasMADIntraFwdBug())
598 Opc = IsUnsigned ? AMDGPU::V_MAD_U64_U32_gfx11_e64
599 : AMDGPU::V_MAD_I64_I32_gfx11_e64;
601 Opc = IsUnsigned ? AMDGPU::V_MAD_NC_U64_U32_e64
602 : AMDGPU::V_MAD_NC_I64_I32_e64;
604 Opc = IsUnsigned ? AMDGPU::V_MAD_U64_U32_e64 : AMDGPU::V_MAD_I64_I32_e64;
609 I.setDesc(TII.get(
Opc));
611 I.addImplicitDefUseOperands(*
MF);
612 I.getOperand(0).setIsEarlyClobber(
true);
618bool AMDGPUInstructionSelector::selectG_EXTRACT(
MachineInstr &
I)
const {
620 Register DstReg =
I.getOperand(0).getReg();
621 Register SrcReg =
I.getOperand(1).getReg();
622 LLT DstTy = MRI->getType(DstReg);
623 LLT SrcTy = MRI->getType(SrcReg);
628 unsigned Offset =
I.getOperand(2).getImm();
629 if (
Offset % 32 != 0 || DstSize > 128)
638 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
639 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
642 const RegisterBank *SrcBank = RBI.getRegBank(SrcReg, *MRI, TRI);
644 TRI.getRegClassForSizeOnBank(SrcSize, *SrcBank);
649 SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubReg);
654 *SrcRC,
I.getOperand(1));
656 BuildMI(*BB, &
I,
DL, TII.get(TargetOpcode::COPY), DstReg)
657 .
addReg(SrcReg, {}, SubReg);
663bool AMDGPUInstructionSelector::selectS16MergeToS32(
MachineInstr &
MI)
const {
668 LLT Src0Ty = MRI->getType(Src0);
669 LLT Src1Ty = MRI->getType(Src1);
671 const RegisterBank *DstBank = RBI.getRegBank(Dst, *MRI, TRI);
672 const RegisterBank *Src0Bank = RBI.getRegBank(Src0, *MRI, TRI);
673 const RegisterBank *Src1Bank = RBI.getRegBank(Src1, *MRI, TRI);
674 const bool IsVector = DstBank->
getID() == AMDGPU::VGPRRegBankID;
685 if (Src0Bank->
getID() == AMDGPU::VGPRRegBankID &&
686 Src1Bank->
getID() == AMDGPU::VGPRRegBankID &&
688 BuildMI(*BB,
MI,
DL, TII.get(TargetOpcode::REG_SEQUENCE), Dst)
694 if (!RBI.constrainGenericRegister(Dst, AMDGPU::VGPR_32RegClass, *MRI))
697 MI.eraseFromParent();
702 Register TmpReg = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
703 auto MIB =
BuildMI(*BB,
MI,
DL, TII.get(AMDGPU::V_AND_B32_e32), TmpReg)
708 MIB =
BuildMI(*BB,
MI,
DL, TII.get(AMDGPU::V_LSHL_OR_B32_e64), Dst)
714 MI.eraseFromParent();
737 unsigned Opc = AMDGPU::S_PACK_LL_B32_B16;
738 if (Shift0 && Shift1) {
739 Opc = AMDGPU::S_PACK_HH_B32_B16;
740 MI.getOperand(1).setReg(ShiftSrc0);
741 MI.getOperand(2).setReg(ShiftSrc1);
743 Opc = AMDGPU::S_PACK_LH_B32_B16;
744 MI.getOperand(2).setReg(ShiftSrc1);
748 if (ConstSrc1 && ConstSrc1->Value == 0) {
750 auto MIB =
BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_LSHR_B32), Dst)
755 MI.eraseFromParent();
759 if (STI.hasSPackHL()) {
760 Opc = AMDGPU::S_PACK_HL_B32_B16;
761 MI.getOperand(1).setReg(ShiftSrc0);
765 MI.setDesc(TII.get(
Opc));
772bool AMDGPUInstructionSelector::selectS16MergeToWide(
MachineInstr &
MI)
const {
776 const unsigned DstSize = MRI->getType(DstReg).getSizeInBits();
777 const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
778 const unsigned NumSrc =
MI.getNumOperands() - 1;
782 for (
unsigned I = 0;
I != NumSrc;
I += 2) {
783 Register S32 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
793 TRI.getRegClassForSizeOnBank(DstSize, *DstBank);
794 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
796 ArrayRef<int16_t> SubRegs = TRI.getRegSplitParts(DstRC, 4);
797 auto MIB =
BuildMI(*BB,
MI,
DL, TII.get(TargetOpcode::REG_SEQUENCE), DstReg);
798 for (
unsigned I = 0,
E = S32Regs.
size();
I !=
E; ++
I)
799 MIB.addReg(S32Regs[
I]).addImm(SubRegs[
I]);
801 MI.eraseFromParent();
805bool AMDGPUInstructionSelector::selectG_MERGE_VALUES(
MachineInstr &
MI)
const {
808 LLT DstTy = MRI->getType(DstReg);
809 LLT SrcTy = MRI->getType(
MI.getOperand(1).getReg());
815 MI.getNumOperands() == 3) {
816 return selectS16MergeToS32(
MI);
820 bool IsWideS16Merge = SrcSize == 16 && DstTy.
getSizeInBits() > 32 &&
824 if (IsWideS16Merge &&
825 RBI.getRegBank(DstReg, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID)
826 return selectS16MergeToWide(
MI);
834 const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
837 TRI.getRegClassForSizeOnBank(DstSize, *DstBank);
841 ArrayRef<int16_t> SubRegs = TRI.getRegSplitParts(DstRC, SrcSize / 8);
842 MachineInstrBuilder MIB =
843 BuildMI(*BB, &
MI,
DL, TII.get(TargetOpcode::REG_SEQUENCE), DstReg);
844 for (
int I = 0,
E =
MI.getNumOperands() - 1;
I !=
E; ++
I) {
845 MachineOperand &Src =
MI.getOperand(
I + 1);
851 TRI.getConstrainedRegClassForReg(SrcReg, *MRI);
852 if (SrcRC && !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI))
856 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
859 MI.eraseFromParent();
863bool AMDGPUInstructionSelector::selectG_UNMERGE_VALUES(
MachineInstr &
MI)
const {
865 const int NumDst =
MI.getNumOperands() - 1;
867 MachineOperand &Src =
MI.getOperand(NumDst);
871 LLT DstTy = MRI->getType(DstReg0);
872 LLT SrcTy = MRI->getType(SrcReg);
877 const RegisterBank *SrcBank = RBI.getRegBank(SrcReg, *MRI, TRI);
880 TRI.getRegClassForSizeOnBank(SrcSize, *SrcBank);
885 ArrayRef<int16_t> SubRegs = TRI.getRegSplitParts(SrcRC, DstSize / 8);
886 for (
int I = 0,
E = NumDst;
I !=
E; ++
I) {
889 if (SrcBank->
getID() == AMDGPU::SGPRRegBankID &&
890 SubRegs[
I] == AMDGPU::hi16) {
891 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_LSHR_B32), DstReg)
895 BuildMI(*BB, &
MI,
DL, TII.get(TargetOpcode::COPY), DstReg)
896 .
addReg(SrcReg, {}, SubRegs[
I]);
899 SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubRegs[
I]);
902 if (!SrcRC || !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI))
906 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
907 if (DstRC && !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
911 MI.eraseFromParent();
915bool AMDGPUInstructionSelector::selectG_BUILD_VECTOR(
MachineInstr &
MI)
const {
916 assert(
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC ||
917 MI.getOpcode() == AMDGPU::G_BUILD_VECTOR);
921 LLT SrcTy = MRI->getType(Src0);
925 if (
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR && SrcSize >= 32) {
926 return selectG_MERGE_VALUES(
MI);
933 (
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC &&
937 const RegisterBank *DstBank = RBI.getRegBank(Dst, *MRI, TRI);
938 if (DstBank->
getID() == AMDGPU::AGPRRegBankID)
941 assert(DstBank->
getID() == AMDGPU::SGPRRegBankID ||
942 DstBank->
getID() == AMDGPU::VGPRRegBankID);
943 const bool IsVector = DstBank->
getID() == AMDGPU::VGPRRegBankID;
956 const int64_t K0 = ConstSrc0->Value.getSExtValue();
957 const int64_t K1 = ConstSrc1->Value.getSExtValue();
958 uint32_t
Lo16 =
static_cast<uint32_t
>(K0) & 0xffff;
959 uint32_t
Hi16 =
static_cast<uint32_t
>(K1) & 0xffff;
965 MI.eraseFromParent();
966 return RBI.constrainGenericRegister(Dst, AMDGPU::VGPR_32RegClass, *MRI);
971 MI.eraseFromParent();
972 return RBI.constrainGenericRegister(Dst, AMDGPU::SReg_32RegClass, *MRI);
983 if (Src1Def->
getOpcode() == AMDGPU::G_IMPLICIT_DEF) {
984 MI.setDesc(TII.get(AMDGPU::COPY));
987 IsVector ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
988 return RBI.constrainGenericRegister(Dst, RC, *MRI) &&
989 RBI.constrainGenericRegister(Src0, RC, *MRI);
992 return selectS16MergeToS32(
MI);
995bool AMDGPUInstructionSelector::selectG_IMPLICIT_DEF(
MachineInstr &
I)
const {
996 const MachineOperand &MO =
I.getOperand(0);
1001 TRI.getConstrainedRegClassForReg(MO.
getReg(), *MRI);
1002 if ((!RC && !MRI->getRegBankOrNull(MO.
getReg())) ||
1003 (RC && RBI.constrainGenericRegister(MO.
getReg(), *RC, *MRI))) {
1004 I.setDesc(TII.get(TargetOpcode::IMPLICIT_DEF));
1011bool AMDGPUInstructionSelector::selectG_INSERT(
MachineInstr &
I)
const {
1014 Register DstReg =
I.getOperand(0).getReg();
1015 Register Src0Reg =
I.getOperand(1).getReg();
1016 Register Src1Reg =
I.getOperand(2).getReg();
1017 LLT Src1Ty = MRI->getType(Src1Reg);
1019 unsigned DstSize = MRI->getType(DstReg).getSizeInBits();
1022 int64_t
Offset =
I.getOperand(3).getImm();
1025 if (
Offset % 32 != 0 || InsSize % 32 != 0)
1032 unsigned SubReg = TRI.getSubRegFromChannel(
Offset / 32, InsSize / 32);
1033 if (SubReg == AMDGPU::NoSubRegister)
1036 const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
1038 TRI.getRegClassForSizeOnBank(DstSize, *DstBank);
1042 const RegisterBank *Src0Bank = RBI.getRegBank(Src0Reg, *MRI, TRI);
1043 const RegisterBank *Src1Bank = RBI.getRegBank(Src1Reg, *MRI, TRI);
1045 TRI.getRegClassForSizeOnBank(DstSize, *Src0Bank);
1047 TRI.getRegClassForSizeOnBank(InsSize, *Src1Bank);
1051 Src0RC = TRI.getSubClassWithSubReg(Src0RC, SubReg);
1052 if (!Src0RC || !Src1RC)
1055 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
1056 !RBI.constrainGenericRegister(Src0Reg, *Src0RC, *MRI) ||
1057 !RBI.constrainGenericRegister(Src1Reg, *Src1RC, *MRI))
1061 BuildMI(*BB, &
I,
DL, TII.get(TargetOpcode::INSERT_SUBREG), DstReg)
1066 I.eraseFromParent();
1070bool AMDGPUInstructionSelector::selectG_SBFX_UBFX(
MachineInstr &
MI)
const {
1073 Register OffsetReg =
MI.getOperand(2).getReg();
1074 Register WidthReg =
MI.getOperand(3).getReg();
1076 assert(RBI.getRegBank(DstReg, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID &&
1077 "scalar BFX instructions are expanded in regbankselect");
1078 assert(MRI->getType(
MI.getOperand(0).getReg()).getSizeInBits() == 32 &&
1079 "64-bit vector BFX instructions are expanded in regbankselect");
1084 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SBFX;
1085 unsigned Opc = IsSigned ? AMDGPU::V_BFE_I32_e64 : AMDGPU::V_BFE_U32_e64;
1090 MI.eraseFromParent();
1095bool AMDGPUInstructionSelector::selectInterpP1F16(
MachineInstr &
MI)
const {
1096 if (STI.getLDSBankCount() != 16)
1102 if (!RBI.constrainGenericRegister(M0Val, AMDGPU::SReg_32RegClass, *MRI) ||
1103 !RBI.constrainGenericRegister(Dst, AMDGPU::VGPR_32RegClass, *MRI) ||
1104 !RBI.constrainGenericRegister(Src0, AMDGPU::VGPR_32RegClass, *MRI))
1114 Register InterpMov = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
1120 BuildMI(*
MBB, &
MI,
DL, TII.get(AMDGPU::V_INTERP_MOV_F32), InterpMov)
1123 .
addImm(
MI.getOperand(3).getImm());
1136 MI.eraseFromParent();
1145bool AMDGPUInstructionSelector::selectWritelane(
MachineInstr &
MI)
const {
1147 if (STI.getConstantBusLimit(AMDGPU::V_WRITELANE_B32) > 1)
1154 Register LaneSelect =
MI.getOperand(3).getReg();
1157 auto MIB =
BuildMI(*
MBB, &
MI,
DL, TII.get(AMDGPU::V_WRITELANE_B32), VDst);
1159 std::optional<ValueAndVReg> ConstSelect =
1165 MIB.
addImm(ConstSelect->Value.getSExtValue() &
1168 std::optional<ValueAndVReg> ConstVal =
1174 STI.hasInv2PiInlineImm())) {
1175 MIB.
addImm(ConstVal->Value.getSExtValue());
1183 RBI.constrainGenericRegister(LaneSelect, AMDGPU::SReg_32_XM0RegClass, *MRI);
1185 BuildMI(*
MBB, *MIB,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
1193 MI.eraseFromParent();
1200bool AMDGPUInstructionSelector::selectDivScale(
MachineInstr &
MI)
const {
1204 LLT Ty = MRI->getType(Dst0);
1207 Opc = AMDGPU::V_DIV_SCALE_F32_e64;
1209 Opc = AMDGPU::V_DIV_SCALE_F64_e64;
1220 unsigned ChooseDenom =
MI.getOperand(5).getImm();
1235 MI.eraseFromParent();
1240bool AMDGPUInstructionSelector::selectG_INTRINSIC(
MachineInstr &
I)
const {
1242 switch (IntrinsicID) {
1243 case Intrinsic::amdgcn_if_break: {
1248 BuildMI(*BB, &
I,
I.getDebugLoc(), TII.get(AMDGPU::SI_IF_BREAK))
1249 .
add(
I.getOperand(0))
1250 .
add(
I.getOperand(2))
1251 .
add(
I.getOperand(3))
1254 Register DstReg =
I.getOperand(0).getReg();
1255 Register Src0Reg =
I.getOperand(2).getReg();
1256 Register Src1Reg =
I.getOperand(3).getReg();
1258 I.eraseFromParent();
1261 MRI->setRegClass(
Reg, TRI.getWaveMaskRegClass());
1265 case Intrinsic::amdgcn_interp_p1_f16:
1266 return selectInterpP1F16(
I);
1267 case Intrinsic::amdgcn_wqm:
1268 return constrainCopyLikeIntrin(
I, AMDGPU::WQM);
1269 case Intrinsic::amdgcn_softwqm:
1270 return constrainCopyLikeIntrin(
I, AMDGPU::SOFT_WQM);
1271 case Intrinsic::amdgcn_strict_wwm:
1272 case Intrinsic::amdgcn_wwm:
1273 return constrainCopyLikeIntrin(
I, AMDGPU::STRICT_WWM);
1274 case Intrinsic::amdgcn_strict_wqm:
1275 return constrainCopyLikeIntrin(
I, AMDGPU::STRICT_WQM);
1276 case Intrinsic::amdgcn_writelane:
1277 return selectWritelane(
I);
1278 case Intrinsic::amdgcn_div_scale:
1279 return selectDivScale(
I);
1280 case Intrinsic::amdgcn_ballot:
1281 return selectBallot(
I);
1282 case Intrinsic::amdgcn_reloc_constant:
1283 return selectRelocConstant(
I);
1284 case Intrinsic::amdgcn_groupstaticsize:
1285 return selectGroupStaticSize(
I);
1286 case Intrinsic::returnaddress:
1287 return selectReturnAddress(
I);
1288 case Intrinsic::amdgcn_smfmac_f32_16x16x32_f16:
1289 case Intrinsic::amdgcn_smfmac_f32_32x32x16_f16:
1290 case Intrinsic::amdgcn_smfmac_f32_16x16x32_bf16:
1291 case Intrinsic::amdgcn_smfmac_f32_32x32x16_bf16:
1292 case Intrinsic::amdgcn_smfmac_i32_16x16x64_i8:
1293 case Intrinsic::amdgcn_smfmac_i32_32x32x32_i8:
1294 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_bf8:
1295 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_fp8:
1296 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_bf8:
1297 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_fp8:
1298 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_bf8:
1299 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_fp8:
1300 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_bf8:
1301 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_fp8:
1302 case Intrinsic::amdgcn_smfmac_f32_16x16x64_f16:
1303 case Intrinsic::amdgcn_smfmac_f32_32x32x32_f16:
1304 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf16:
1305 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf16:
1306 case Intrinsic::amdgcn_smfmac_i32_16x16x128_i8:
1307 case Intrinsic::amdgcn_smfmac_i32_32x32x64_i8:
1308 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_bf8:
1309 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_fp8:
1310 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_bf8:
1311 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_fp8:
1312 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_bf8:
1313 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_fp8:
1314 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_bf8:
1315 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_fp8:
1316 return selectSMFMACIntrin(
I);
1317 case Intrinsic::amdgcn_permlane16_swap:
1318 case Intrinsic::amdgcn_permlane32_swap:
1319 return selectPermlaneSwapIntrin(
I, IntrinsicID);
1320 case Intrinsic::amdgcn_wave_shuffle:
1321 return selectWaveShuffleIntrin(
I);
1332 if (
Size == 16 && !ST.has16BitInsts())
1335 const auto Select = [&](
unsigned S16Opc,
unsigned TrueS16Opc,
1336 unsigned FakeS16Opc,
unsigned S32Opc,
1339 return ST.hasTrue16BitInsts()
1340 ? ST.useRealTrue16Insts() ? TrueS16Opc : FakeS16Opc
1351 return Select(AMDGPU::V_CMP_NE_U16_e64, AMDGPU::V_CMP_NE_U16_t16_e64,
1352 AMDGPU::V_CMP_NE_U16_fake16_e64, AMDGPU::V_CMP_NE_U32_e64,
1353 AMDGPU::V_CMP_NE_U64_e64);
1355 return Select(AMDGPU::V_CMP_EQ_U16_e64, AMDGPU::V_CMP_EQ_U16_t16_e64,
1356 AMDGPU::V_CMP_EQ_U16_fake16_e64, AMDGPU::V_CMP_EQ_U32_e64,
1357 AMDGPU::V_CMP_EQ_U64_e64);
1359 return Select(AMDGPU::V_CMP_GT_I16_e64, AMDGPU::V_CMP_GT_I16_t16_e64,
1360 AMDGPU::V_CMP_GT_I16_fake16_e64, AMDGPU::V_CMP_GT_I32_e64,
1361 AMDGPU::V_CMP_GT_I64_e64);
1363 return Select(AMDGPU::V_CMP_GE_I16_e64, AMDGPU::V_CMP_GE_I16_t16_e64,
1364 AMDGPU::V_CMP_GE_I16_fake16_e64, AMDGPU::V_CMP_GE_I32_e64,
1365 AMDGPU::V_CMP_GE_I64_e64);
1367 return Select(AMDGPU::V_CMP_LT_I16_e64, AMDGPU::V_CMP_LT_I16_t16_e64,
1368 AMDGPU::V_CMP_LT_I16_fake16_e64, AMDGPU::V_CMP_LT_I32_e64,
1369 AMDGPU::V_CMP_LT_I64_e64);
1371 return Select(AMDGPU::V_CMP_LE_I16_e64, AMDGPU::V_CMP_LE_I16_t16_e64,
1372 AMDGPU::V_CMP_LE_I16_fake16_e64, AMDGPU::V_CMP_LE_I32_e64,
1373 AMDGPU::V_CMP_LE_I64_e64);
1375 return Select(AMDGPU::V_CMP_GT_U16_e64, AMDGPU::V_CMP_GT_U16_t16_e64,
1376 AMDGPU::V_CMP_GT_U16_fake16_e64, AMDGPU::V_CMP_GT_U32_e64,
1377 AMDGPU::V_CMP_GT_U64_e64);
1379 return Select(AMDGPU::V_CMP_GE_U16_e64, AMDGPU::V_CMP_GE_U16_t16_e64,
1380 AMDGPU::V_CMP_GE_U16_fake16_e64, AMDGPU::V_CMP_GE_U32_e64,
1381 AMDGPU::V_CMP_GE_U64_e64);
1383 return Select(AMDGPU::V_CMP_LT_U16_e64, AMDGPU::V_CMP_LT_U16_t16_e64,
1384 AMDGPU::V_CMP_LT_U16_fake16_e64, AMDGPU::V_CMP_LT_U32_e64,
1385 AMDGPU::V_CMP_LT_U64_e64);
1387 return Select(AMDGPU::V_CMP_LE_U16_e64, AMDGPU::V_CMP_LE_U16_t16_e64,
1388 AMDGPU::V_CMP_LE_U16_fake16_e64, AMDGPU::V_CMP_LE_U32_e64,
1389 AMDGPU::V_CMP_LE_U64_e64);
1392 return Select(AMDGPU::V_CMP_EQ_F16_e64, AMDGPU::V_CMP_EQ_F16_t16_e64,
1393 AMDGPU::V_CMP_EQ_F16_fake16_e64, AMDGPU::V_CMP_EQ_F32_e64,
1394 AMDGPU::V_CMP_EQ_F64_e64);
1396 return Select(AMDGPU::V_CMP_GT_F16_e64, AMDGPU::V_CMP_GT_F16_t16_e64,
1397 AMDGPU::V_CMP_GT_F16_fake16_e64, AMDGPU::V_CMP_GT_F32_e64,
1398 AMDGPU::V_CMP_GT_F64_e64);
1400 return Select(AMDGPU::V_CMP_GE_F16_e64, AMDGPU::V_CMP_GE_F16_t16_e64,
1401 AMDGPU::V_CMP_GE_F16_fake16_e64, AMDGPU::V_CMP_GE_F32_e64,
1402 AMDGPU::V_CMP_GE_F64_e64);
1404 return Select(AMDGPU::V_CMP_LT_F16_e64, AMDGPU::V_CMP_LT_F16_t16_e64,
1405 AMDGPU::V_CMP_LT_F16_fake16_e64, AMDGPU::V_CMP_LT_F32_e64,
1406 AMDGPU::V_CMP_LT_F64_e64);
1408 return Select(AMDGPU::V_CMP_LE_F16_e64, AMDGPU::V_CMP_LE_F16_t16_e64,
1409 AMDGPU::V_CMP_LE_F16_fake16_e64, AMDGPU::V_CMP_LE_F32_e64,
1410 AMDGPU::V_CMP_LE_F64_e64);
1412 return Select(AMDGPU::V_CMP_NEQ_F16_e64, AMDGPU::V_CMP_NEQ_F16_t16_e64,
1413 AMDGPU::V_CMP_NEQ_F16_fake16_e64, AMDGPU::V_CMP_NEQ_F32_e64,
1414 AMDGPU::V_CMP_NEQ_F64_e64);
1416 return Select(AMDGPU::V_CMP_O_F16_e64, AMDGPU::V_CMP_O_F16_t16_e64,
1417 AMDGPU::V_CMP_O_F16_fake16_e64, AMDGPU::V_CMP_O_F32_e64,
1418 AMDGPU::V_CMP_O_F64_e64);
1420 return Select(AMDGPU::V_CMP_U_F16_e64, AMDGPU::V_CMP_U_F16_t16_e64,
1421 AMDGPU::V_CMP_U_F16_fake16_e64, AMDGPU::V_CMP_U_F32_e64,
1422 AMDGPU::V_CMP_U_F64_e64);
1424 return Select(AMDGPU::V_CMP_NLG_F16_e64, AMDGPU::V_CMP_NLG_F16_t16_e64,
1425 AMDGPU::V_CMP_NLG_F16_fake16_e64, AMDGPU::V_CMP_NLG_F32_e64,
1426 AMDGPU::V_CMP_NLG_F64_e64);
1428 return Select(AMDGPU::V_CMP_NLE_F16_e64, AMDGPU::V_CMP_NLE_F16_t16_e64,
1429 AMDGPU::V_CMP_NLE_F16_fake16_e64, AMDGPU::V_CMP_NLE_F32_e64,
1430 AMDGPU::V_CMP_NLE_F64_e64);
1432 return Select(AMDGPU::V_CMP_NLT_F16_e64, AMDGPU::V_CMP_NLT_F16_t16_e64,
1433 AMDGPU::V_CMP_NLT_F16_fake16_e64, AMDGPU::V_CMP_NLT_F32_e64,
1434 AMDGPU::V_CMP_NLT_F64_e64);
1436 return Select(AMDGPU::V_CMP_NGE_F16_e64, AMDGPU::V_CMP_NGE_F16_t16_e64,
1437 AMDGPU::V_CMP_NGE_F16_fake16_e64, AMDGPU::V_CMP_NGE_F32_e64,
1438 AMDGPU::V_CMP_NGE_F64_e64);
1440 return Select(AMDGPU::V_CMP_NGT_F16_e64, AMDGPU::V_CMP_NGT_F16_t16_e64,
1441 AMDGPU::V_CMP_NGT_F16_fake16_e64, AMDGPU::V_CMP_NGT_F32_e64,
1442 AMDGPU::V_CMP_NGT_F64_e64);
1444 return Select(AMDGPU::V_CMP_NEQ_F16_e64, AMDGPU::V_CMP_NEQ_F16_t16_e64,
1445 AMDGPU::V_CMP_NEQ_F16_fake16_e64, AMDGPU::V_CMP_NEQ_F32_e64,
1446 AMDGPU::V_CMP_NEQ_F64_e64);
1448 return Select(AMDGPU::V_CMP_TRU_F16_e64, AMDGPU::V_CMP_TRU_F16_t16_e64,
1449 AMDGPU::V_CMP_TRU_F16_fake16_e64, AMDGPU::V_CMP_TRU_F32_e64,
1450 AMDGPU::V_CMP_TRU_F64_e64);
1452 return Select(AMDGPU::V_CMP_F_F16_e64, AMDGPU::V_CMP_F_F16_t16_e64,
1453 AMDGPU::V_CMP_F_F16_fake16_e64, AMDGPU::V_CMP_F_F32_e64,
1454 AMDGPU::V_CMP_F_F64_e64);
1459 unsigned Size)
const {
1461 if (!STI.hasScalarCompareEq64())
1466 return AMDGPU::S_CMP_LG_U64;
1468 return AMDGPU::S_CMP_EQ_U64;
1477 return AMDGPU::S_CMP_LG_U32;
1479 return AMDGPU::S_CMP_EQ_U32;
1481 return AMDGPU::S_CMP_GT_I32;
1483 return AMDGPU::S_CMP_GE_I32;
1485 return AMDGPU::S_CMP_LT_I32;
1487 return AMDGPU::S_CMP_LE_I32;
1489 return AMDGPU::S_CMP_GT_U32;
1491 return AMDGPU::S_CMP_GE_U32;
1493 return AMDGPU::S_CMP_LT_U32;
1495 return AMDGPU::S_CMP_LE_U32;
1497 return AMDGPU::S_CMP_EQ_F32;
1499 return AMDGPU::S_CMP_GT_F32;
1501 return AMDGPU::S_CMP_GE_F32;
1503 return AMDGPU::S_CMP_LT_F32;
1505 return AMDGPU::S_CMP_LE_F32;
1507 return AMDGPU::S_CMP_LG_F32;
1509 return AMDGPU::S_CMP_O_F32;
1511 return AMDGPU::S_CMP_U_F32;
1513 return AMDGPU::S_CMP_NLG_F32;
1515 return AMDGPU::S_CMP_NLE_F32;
1517 return AMDGPU::S_CMP_NLT_F32;
1519 return AMDGPU::S_CMP_NGE_F32;
1521 return AMDGPU::S_CMP_NGT_F32;
1523 return AMDGPU::S_CMP_NEQ_F32;
1530 if (!STI.hasSALUFloatInsts())
1535 return AMDGPU::S_CMP_EQ_F16;
1537 return AMDGPU::S_CMP_GT_F16;
1539 return AMDGPU::S_CMP_GE_F16;
1541 return AMDGPU::S_CMP_LT_F16;
1543 return AMDGPU::S_CMP_LE_F16;
1545 return AMDGPU::S_CMP_LG_F16;
1547 return AMDGPU::S_CMP_O_F16;
1549 return AMDGPU::S_CMP_U_F16;
1551 return AMDGPU::S_CMP_NLG_F16;
1553 return AMDGPU::S_CMP_NLE_F16;
1555 return AMDGPU::S_CMP_NLT_F16;
1557 return AMDGPU::S_CMP_NGE_F16;
1559 return AMDGPU::S_CMP_NGT_F16;
1561 return AMDGPU::S_CMP_NEQ_F16;
1570bool AMDGPUInstructionSelector::selectG_ICMP_or_FCMP(
MachineInstr &
I)
const {
1575 Register SrcReg =
I.getOperand(2).getReg();
1576 unsigned Size = RBI.getSizeInBits(SrcReg, *MRI, TRI);
1580 Register CCReg =
I.getOperand(0).getReg();
1581 if (!isVCC(CCReg, *MRI)) {
1582 int Opcode = getS_CMPOpcode(Pred,
Size);
1585 MachineInstr *ICmp =
BuildMI(*BB, &
I,
DL, TII.get(Opcode))
1586 .
add(
I.getOperand(2))
1587 .
add(
I.getOperand(3));
1588 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), CCReg)
1592 RBI.constrainGenericRegister(CCReg, AMDGPU::SReg_32RegClass, *MRI);
1593 I.eraseFromParent();
1597 if (
I.getOpcode() == AMDGPU::G_FCMP)
1604 MachineInstrBuilder ICmp;
1607 ICmp =
BuildMI(*BB, &
I,
DL, TII.get(Opcode),
I.getOperand(0).getReg())
1609 .
add(
I.getOperand(2))
1611 .
add(
I.getOperand(3))
1614 ICmp =
BuildMI(*BB, &
I,
DL, TII.get(Opcode),
I.getOperand(0).getReg())
1615 .
add(
I.getOperand(2))
1616 .
add(
I.getOperand(3));
1620 *TRI.getBoolRC(), *MRI);
1622 I.eraseFromParent();
1633 if (
MI->getParent() !=
MBB)
1637 if (
MI->getOpcode() == AMDGPU::COPY) {
1640 if (DstRB && SrcRB && DstRB->
getID() == AMDGPU::VCCRegBankID &&
1641 SrcRB->getID() == AMDGPU::SGPRRegBankID)
1646 if (
MI->getOpcode() == AMDGPU::G_AMDGPU_COPY_VCC_SCC)
1662bool AMDGPUInstructionSelector::selectBallot(
MachineInstr &
I)
const {
1665 Register DstReg =
I.getOperand(0).getReg();
1666 Register SrcReg =
I.getOperand(2).getReg();
1667 const unsigned BallotSize = MRI->getType(DstReg).getSizeInBits();
1668 const unsigned WaveSize = STI.getWavefrontSize();
1672 if (BallotSize != WaveSize && (BallotSize != 64 || WaveSize != 32))
1675 std::optional<ValueAndVReg> Arg =
1680 if (BallotSize != WaveSize) {
1681 Dst = MRI->createVirtualRegister(TRI.getBoolRC());
1685 const int64_t
Value = Arg->Value.getZExtValue();
1688 unsigned Opcode = WaveSize == 64 ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
1695 if (!RBI.constrainGenericRegister(Dst, *TRI.getBoolRC(), *MRI))
1701 if (!RBI.constrainGenericRegister(Dst, *TRI.getBoolRC(), *MRI))
1705 unsigned AndOpc = WaveSize == 64 ? AMDGPU::S_AND_B64 : AMDGPU::S_AND_B32;
1715 if (BallotSize != WaveSize) {
1716 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
1718 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
1725 I.eraseFromParent();
1729bool AMDGPUInstructionSelector::selectRelocConstant(
MachineInstr &
I)
const {
1730 Register DstReg =
I.getOperand(0).getReg();
1731 const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
1733 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
1736 const bool IsVALU = DstBank->
getID() == AMDGPU::VGPRRegBankID;
1738 Module *
M =
MF->getFunction().getParent();
1739 const MDNode *
Metadata =
I.getOperand(2).getMetadata();
1746 TII.get(IsVALU ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32), DstReg)
1749 I.eraseFromParent();
1753bool AMDGPUInstructionSelector::selectGroupStaticSize(
MachineInstr &
I)
const {
1756 Register DstReg =
I.getOperand(0).getReg();
1757 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
1758 unsigned Mov = DstRB->
getID() == AMDGPU::SGPRRegBankID ?
1759 AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1767 const SIMachineFunctionInfo *MFI =
MF->getInfo<SIMachineFunctionInfo>();
1770 Module *
M =
MF->getFunction().getParent();
1771 const GlobalValue *GV =
1776 I.eraseFromParent();
1781bool AMDGPUInstructionSelector::selectReturnAddress(
MachineInstr &
I)
const {
1786 Register DstReg =
I.getOperand(0).getReg();
1787 unsigned Depth =
I.getOperand(2).getImm();
1790 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
1792 !RBI.constrainGenericRegister(DstReg, *RC, *MRI))
1797 MF.getInfo<SIMachineFunctionInfo>()->isEntryFunction()) {
1800 I.eraseFromParent();
1804 MachineFrameInfo &MFI =
MF.getFrameInfo();
1809 Register ReturnAddrReg = TRI.getReturnAddressReg(
MF);
1811 AMDGPU::SReg_64RegClass,
DL);
1814 I.eraseFromParent();
1818bool AMDGPUInstructionSelector::selectEndCfIntrinsic(
MachineInstr &
MI)
const {
1822 BuildMI(*BB, &
MI,
MI.getDebugLoc(), TII.get(AMDGPU::SI_END_CF))
1823 .
add(
MI.getOperand(1))
1827 MI.eraseFromParent();
1829 if (!MRI->getRegClassOrNull(
Reg))
1830 MRI->setRegClass(
Reg, TRI.getWaveMaskRegClass());
1834bool AMDGPUInstructionSelector::selectDSOrderedIntrinsic(
1840 unsigned IndexOperand =
MI.getOperand(7).getImm();
1841 bool WaveRelease =
MI.getOperand(8).getImm() != 0;
1842 bool WaveDone =
MI.getOperand(9).getImm() != 0;
1844 if (WaveDone && !WaveRelease) {
1848 Fn,
"ds_ordered_count: wave_done requires wave_release",
DL));
1851 unsigned OrderedCountIndex = IndexOperand & 0x3f;
1852 IndexOperand &= ~0x3f;
1853 unsigned CountDw = 0;
1856 CountDw = (IndexOperand >> 24) & 0xf;
1857 IndexOperand &= ~(0xf << 24);
1859 if (CountDw < 1 || CountDw > 4) {
1862 Fn,
"ds_ordered_count: dword count must be between 1 and 4",
DL));
1870 Fn,
"ds_ordered_count: bad index operand",
DL));
1873 unsigned Instruction = IntrID == Intrinsic::amdgcn_ds_ordered_add ? 0 : 1;
1876 unsigned Offset0 = OrderedCountIndex << 2;
1877 unsigned Offset1 = WaveRelease | (WaveDone << 1) | (Instruction << 4);
1880 Offset1 |= (CountDw - 1) << 6;
1883 Offset1 |= ShaderType << 2;
1885 unsigned Offset = Offset0 | (Offset1 << 8);
1893 MachineInstrBuilder
DS =
1894 BuildMI(*
MBB, &
MI,
DL, TII.get(AMDGPU::DS_ORDERED_COUNT), DstReg)
1899 if (!RBI.constrainGenericRegister(M0Val, AMDGPU::SReg_32RegClass, *MRI))
1903 MI.eraseFromParent();
1909 case Intrinsic::amdgcn_ds_gws_init:
1910 return AMDGPU::DS_GWS_INIT;
1911 case Intrinsic::amdgcn_ds_gws_barrier:
1912 return AMDGPU::DS_GWS_BARRIER;
1913 case Intrinsic::amdgcn_ds_gws_sema_v:
1914 return AMDGPU::DS_GWS_SEMA_V;
1915 case Intrinsic::amdgcn_ds_gws_sema_br:
1916 return AMDGPU::DS_GWS_SEMA_BR;
1917 case Intrinsic::amdgcn_ds_gws_sema_p:
1918 return AMDGPU::DS_GWS_SEMA_P;
1919 case Intrinsic::amdgcn_ds_gws_sema_release_all:
1920 return AMDGPU::DS_GWS_SEMA_RELEASE_ALL;
1926bool AMDGPUInstructionSelector::selectDSGWSIntrinsic(
MachineInstr &
MI,
1928 if (!STI.hasGWS() || (IID == Intrinsic::amdgcn_ds_gws_sema_release_all &&
1929 !STI.hasGWSSemaReleaseAll()))
1933 const bool HasVSrc =
MI.getNumOperands() == 3;
1934 assert(HasVSrc ||
MI.getNumOperands() == 2);
1936 Register BaseOffset =
MI.getOperand(HasVSrc ? 2 : 1).getReg();
1937 const RegisterBank *OffsetRB = RBI.getRegBank(BaseOffset, *MRI, TRI);
1938 if (OffsetRB->
getID() != AMDGPU::SGPRRegBankID)
1947 MachineInstr *Readfirstlane =
nullptr;
1952 if (OffsetDef->
getOpcode() == AMDGPU::V_READFIRSTLANE_B32) {
1953 Readfirstlane = OffsetDef;
1958 if (OffsetDef->
getOpcode() == AMDGPU::G_CONSTANT) {
1968 std::tie(BaseOffset, ImmOffset) =
1971 if (Readfirstlane) {
1974 if (!RBI.constrainGenericRegister(BaseOffset, AMDGPU::VGPR_32RegClass, *MRI))
1980 if (!RBI.constrainGenericRegister(BaseOffset,
1981 AMDGPU::SReg_32RegClass, *MRI))
1985 Register M0Base = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2000 const MCInstrDesc &InstrDesc = TII.get(
Opc);
2005 int Data0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
2008 TRI.getSubRegisterClass(DataRC, AMDGPU::sub0);
2012 if (!RBI.constrainGenericRegister(VSrc, *DataRC, *MRI))
2022 Register DataReg = MRI->createVirtualRegister(DataRC);
2023 if (!RBI.constrainGenericRegister(VSrc, *SubRC, *MRI))
2026 Register UndefReg = MRI->createVirtualRegister(SubRC);
2045 MI.eraseFromParent();
2049bool AMDGPUInstructionSelector::selectDSAppendConsume(
MachineInstr &
MI,
2050 bool IsAppend)
const {
2051 Register PtrBase =
MI.getOperand(2).getReg();
2052 LLT PtrTy = MRI->getType(PtrBase);
2056 std::tie(PtrBase,
Offset) = selectDS1Addr1OffsetImpl(
MI.getOperand(2));
2059 if (!isDSOffsetLegal(PtrBase,
Offset)) {
2060 PtrBase =
MI.getOperand(2).getReg();
2066 const unsigned Opc = IsAppend ? AMDGPU::DS_APPEND : AMDGPU::DS_CONSUME;
2070 if (!RBI.constrainGenericRegister(PtrBase, AMDGPU::SReg_32RegClass, *MRI))
2077 MI.eraseFromParent();
2082bool AMDGPUInstructionSelector::selectInitWholeWave(
MachineInstr &
MI)
const {
2084 SIMachineFunctionInfo *MFInfo =
MF->getInfo<SIMachineFunctionInfo>();
2095 TFE = TexFailCtrl & 0x1;
2097 LWE = TexFailCtrl & 0x2;
2100 return TexFailCtrl == 0;
2103bool AMDGPUInstructionSelector::selectImageIntrinsic(
2111 Register ResultDef =
MI.getOperand(0).getReg();
2112 if (MRI->use_nodbg_empty(ResultDef))
2116 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
2125 const unsigned ArgOffset =
MI.getNumExplicitDefs() + 1;
2127 Register VDataIn = AMDGPU::NoRegister;
2128 Register VDataOut = AMDGPU::NoRegister;
2130 int NumVDataDwords = -1;
2131 bool IsD16 =
MI.getOpcode() == AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16 ||
2132 MI.getOpcode() == AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16;
2138 Unorm =
MI.getOperand(ArgOffset + Intr->
UnormIndex).getImm() != 0;
2142 bool IsTexFail =
false;
2144 TFE, LWE, IsTexFail))
2147 const int Flags =
MI.getOperand(ArgOffset + Intr->
NumArgs).getImm();
2148 const bool IsA16 = (
Flags & 1) != 0;
2149 const bool IsG16 = (
Flags & 2) != 0;
2152 if (IsA16 && !STI.hasG16() && !IsG16)
2156 unsigned DMaskLanes = 0;
2158 if (BaseOpcode->
Atomic) {
2160 VDataOut =
MI.getOperand(0).getReg();
2161 VDataIn =
MI.getOperand(2).getReg();
2162 LLT Ty = MRI->getType(VDataIn);
2165 const bool Is64Bit = BaseOpcode->
AtomicX2 ?
2170 assert(
MI.getOperand(3).getReg() == AMDGPU::NoRegister);
2172 DMask = Is64Bit ? 0xf : 0x3;
2173 NumVDataDwords = Is64Bit ? 4 : 2;
2175 DMask = Is64Bit ? 0x3 : 0x1;
2176 NumVDataDwords = Is64Bit ? 2 : 1;
2179 DMask =
MI.getOperand(ArgOffset + Intr->
DMaskIndex).getImm();
2182 if (BaseOpcode->
Store) {
2183 VDataIn =
MI.getOperand(1).getReg();
2184 VDataTy = MRI->getType(VDataIn);
2189 VDataOut =
MI.getOperand(0).getReg();
2190 VDataTy = MRI->getType(VDataOut);
2191 NumVDataDwords = DMaskLanes;
2193 if (IsD16 && !STI.hasUnpackedD16VMem())
2194 NumVDataDwords = (DMaskLanes + 1) / 2;
2199 if (Subtarget->hasG16() && IsG16) {
2200 const AMDGPU::MIMGG16MappingInfo *G16MappingInfo =
2203 IntrOpcode = G16MappingInfo->
G16;
2207 assert((!IsTexFail || DMaskLanes >= 1) &&
"should have legalized this");
2217 int NumVAddrRegs = 0;
2218 int NumVAddrDwords = 0;
2221 MachineOperand &AddrOp =
MI.getOperand(ArgOffset +
I);
2222 if (!AddrOp.
isReg())
2230 NumVAddrDwords += (MRI->getType(Addr).getSizeInBits() + 31) / 32;
2237 NumVAddrRegs != 1 &&
2238 (STI.hasPartialNSAEncoding() ? NumVAddrDwords >= NumVAddrRegs
2239 : NumVAddrDwords == NumVAddrRegs);
2240 if (UseNSA && !STI.hasFeature(AMDGPU::FeatureNSAEncoding)) {
2252 bool IndexedRsrc = MRI->getType(RsrcReg) ==
I32;
2253 bool IndexedSamp =
false;
2256 IndexedSamp = MRI->getType(SampReg) ==
I32;
2260 NumVAddrDwords, IndexedRsrc, IndexedSamp);
2261 }
else if (IsGFX12Plus) {
2263 NumVDataDwords, NumVAddrDwords);
2264 }
else if (IsGFX11Plus) {
2266 UseNSA ? AMDGPU::MIMGEncGfx11NSA
2267 : AMDGPU::MIMGEncGfx11Default,
2268 NumVDataDwords, NumVAddrDwords);
2269 }
else if (IsGFX10Plus) {
2271 UseNSA ? AMDGPU::MIMGEncGfx10NSA
2272 : AMDGPU::MIMGEncGfx10Default,
2273 NumVDataDwords, NumVAddrDwords);
2275 if (Subtarget->hasGFX90AInsts()) {
2277 NumVDataDwords, NumVAddrDwords);
2281 <<
"requested image instruction is not supported on this GPU\n");
2288 NumVDataDwords, NumVAddrDwords);
2291 NumVDataDwords, NumVAddrDwords);
2301 const bool Is64 = MRI->getType(VDataOut).getSizeInBits() == 64;
2303 Register TmpReg = MRI->createVirtualRegister(
2304 Is64 ? &AMDGPU::VReg_128RegClass : &AMDGPU::VReg_64RegClass);
2305 unsigned SubReg = Is64 ? AMDGPU::sub0_sub1 : AMDGPU::sub0;
2308 if (!MRI->use_empty(VDataOut)) {
2310 .
addReg(TmpReg, {}, SubReg);
2321 for (
int I = 0;
I != NumVAddrRegs; ++
I) {
2322 MachineOperand &SrcOp =
MI.getOperand(ArgOffset + Intr->
VAddrStart +
I);
2323 if (SrcOp.
isReg()) {
2342 STI.hasFeature(AMDGPU::FeatureR128A16) ? -1 : 0);
2344 MIB.
addImm(IsA16 ? -1 : 0);
2346 if (!Subtarget->hasGFX90AInsts()) {
2358 MIB.
addImm(IsD16 ? -1 : 0);
2360 MI.eraseFromParent();
2362 TII.enforceOperandRCAlignment(*MIB, AMDGPU::OpName::vaddr);
2368bool AMDGPUInstructionSelector::selectDSBvhStackIntrinsic(
2379 unsigned Offset =
MI.getOperand(6).getImm();
2383 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
2384 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
2385 Opc = AMDGPU::DS_BVH_STACK_RTN_B32;
2387 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
2388 Opc = AMDGPU::DS_BVH_STACK_PUSH8_POP1_RTN_B32;
2390 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn:
2391 Opc = AMDGPU::DS_BVH_STACK_PUSH8_POP2_RTN_B64;
2403 MI.eraseFromParent();
2408bool AMDGPUInstructionSelector::selectG_INTRINSIC_W_SIDE_EFFECTS(
2411 switch (IntrinsicID) {
2412 case Intrinsic::amdgcn_end_cf:
2413 return selectEndCfIntrinsic(
I);
2414 case Intrinsic::amdgcn_ds_ordered_add:
2415 case Intrinsic::amdgcn_ds_ordered_swap:
2416 return selectDSOrderedIntrinsic(
I, IntrinsicID);
2417 case Intrinsic::amdgcn_ds_gws_init:
2418 case Intrinsic::amdgcn_ds_gws_barrier:
2419 case Intrinsic::amdgcn_ds_gws_sema_v:
2420 case Intrinsic::amdgcn_ds_gws_sema_br:
2421 case Intrinsic::amdgcn_ds_gws_sema_p:
2422 case Intrinsic::amdgcn_ds_gws_sema_release_all:
2423 return selectDSGWSIntrinsic(
I, IntrinsicID);
2424 case Intrinsic::amdgcn_ds_append:
2425 return selectDSAppendConsume(
I,
true);
2426 case Intrinsic::amdgcn_ds_consume:
2427 return selectDSAppendConsume(
I,
false);
2428 case Intrinsic::amdgcn_init_whole_wave:
2429 return selectInitWholeWave(
I);
2430 case Intrinsic::amdgcn_raw_buffer_load_lds:
2431 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
2432 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
2433 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
2434 case Intrinsic::amdgcn_struct_buffer_load_lds:
2435 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
2436 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
2437 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
2438 return selectBufferLoadLds(
I);
2443 case Intrinsic::amdgcn_load_to_lds:
2444 case Intrinsic::amdgcn_load_async_to_lds:
2445 case Intrinsic::amdgcn_global_load_lds:
2446 case Intrinsic::amdgcn_global_load_async_lds:
2447 return selectGlobalLoadLds(
I);
2448 case Intrinsic::amdgcn_tensor_load_to_lds:
2449 case Intrinsic::amdgcn_tensor_store_from_lds:
2450 return selectTensorLoadStore(
I, IntrinsicID);
2451 case Intrinsic::amdgcn_asyncmark:
2452 case Intrinsic::amdgcn_wait_asyncmark:
2453 if (!Subtarget->hasAsyncMark())
2456 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
2457 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
2458 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
2459 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn:
2460 return selectDSBvhStackIntrinsic(
I);
2461 case Intrinsic::amdgcn_s_alloc_vgpr: {
2467 Register ResReg =
I.getOperand(0).getReg();
2469 MachineInstr *AllocMI =
BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::S_ALLOC_VGPR))
2470 .
add(
I.getOperand(2));
2473 I.eraseFromParent();
2475 return RBI.constrainGenericRegister(ResReg, AMDGPU::SReg_32RegClass, *MRI);
2477 case Intrinsic::amdgcn_s_barrier_init:
2478 case Intrinsic::amdgcn_s_barrier_signal_var:
2479 return selectNamedBarrierInit(
I, IntrinsicID);
2480 case Intrinsic::amdgcn_s_wakeup_barrier:
2481 case Intrinsic::amdgcn_s_barrier_join:
2482 case Intrinsic::amdgcn_s_get_named_barrier_state:
2483 return selectNamedBarrierInst(
I, IntrinsicID);
2484 case Intrinsic::amdgcn_s_get_barrier_state:
2485 return selectSGetBarrierState(
I, IntrinsicID);
2486 case Intrinsic::amdgcn_s_barrier_signal_isfirst:
2487 return selectSBarrierSignalIsfirst(
I, IntrinsicID);
2492bool AMDGPUInstructionSelector::selectG_SELECT(
MachineInstr &
I)
const {
2499 Register DstReg =
I.getOperand(0).getReg();
2500 unsigned Size = RBI.getSizeInBits(DstReg, *MRI, TRI);
2502 const MachineOperand &CCOp =
I.getOperand(1);
2504 if (!isVCC(CCReg, *MRI)) {
2505 unsigned SelectOpcode =
Size == 64 ? AMDGPU::S_CSELECT_B64 :
2506 AMDGPU::S_CSELECT_B32;
2507 MachineInstr *CopySCC =
BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::SCC)
2513 if (!MRI->getRegClassOrNull(CCReg))
2514 MRI->setRegClass(CCReg, TRI.getConstrainedRegClassForReg(CCReg, *MRI));
2516 .
add(
I.getOperand(2))
2517 .
add(
I.getOperand(3));
2521 I.eraseFromParent();
2530 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
2532 .
add(
I.getOperand(3))
2534 .
add(
I.getOperand(2))
2535 .
add(
I.getOperand(1));
2538 I.eraseFromParent();
2542bool AMDGPUInstructionSelector::selectG_TRUNC(
MachineInstr &
I)
const {
2543 Register DstReg =
I.getOperand(0).getReg();
2544 Register SrcReg =
I.getOperand(1).getReg();
2545 const LLT DstTy = MRI->getType(DstReg);
2546 const LLT SrcTy = MRI->getType(SrcReg);
2549 const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
2550 const RegisterBank *DstRB;
2556 DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
2561 const bool IsVALU = DstRB->
getID() == AMDGPU::VGPRRegBankID;
2567 TRI.getRegClassForSizeOnBank(SrcSize, *SrcRB);
2569 TRI.getRegClassForSizeOnBank(DstSize, *DstRB);
2570 if (!SrcRC || !DstRC)
2573 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
2574 !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI)) {
2579 if (DstRC == &AMDGPU::VGPR_16RegClass && SrcSize == 32) {
2580 assert(STI.useRealTrue16Insts());
2584 .
addReg(SrcReg, {}, AMDGPU::lo16);
2585 I.eraseFromParent();
2593 Register LoReg = MRI->createVirtualRegister(DstRC);
2594 Register HiReg = MRI->createVirtualRegister(DstRC);
2596 .
addReg(SrcReg, {}, AMDGPU::sub0);
2598 .
addReg(SrcReg, {}, AMDGPU::sub1);
2600 if (IsVALU && STI.hasSDWA()) {
2603 MachineInstr *MovSDWA =
2604 BuildMI(*
MBB,
I,
DL, TII.get(AMDGPU::V_MOV_B32_sdwa), DstReg)
2614 Register TmpReg0 = MRI->createVirtualRegister(DstRC);
2615 Register TmpReg1 = MRI->createVirtualRegister(DstRC);
2616 Register ImmReg = MRI->createVirtualRegister(DstRC);
2618 BuildMI(*
MBB,
I,
DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), TmpReg0)
2628 unsigned MovOpc = IsVALU ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32;
2629 unsigned AndOpc = IsVALU ? AMDGPU::V_AND_B32_e64 : AMDGPU::S_AND_B32;
2630 unsigned OrOpc = IsVALU ? AMDGPU::V_OR_B32_e64 : AMDGPU::S_OR_B32;
2642 And.setOperandDead(3);
2643 Or.setOperandDead(3);
2647 I.eraseFromParent();
2655 unsigned SubRegIdx = DstSize < 32
2656 ?
static_cast<unsigned>(AMDGPU::sub0)
2657 : TRI.getSubRegFromChannel(0, DstSize / 32);
2658 if (SubRegIdx == AMDGPU::NoSubRegister)
2664 = TRI.getSubClassWithSubReg(SrcRC, SubRegIdx);
2668 if (SrcWithSubRC != SrcRC) {
2669 if (!RBI.constrainGenericRegister(SrcReg, *SrcWithSubRC, *MRI))
2673 I.getOperand(1).setSubReg(SubRegIdx);
2676 I.setDesc(TII.get(TargetOpcode::COPY));
2683 int SignedMask =
static_cast<int>(Mask);
2684 return SignedMask >= -16 && SignedMask <= 64;
2688const RegisterBank *AMDGPUInstructionSelector::getArtifactRegBank(
2697 return &RBI.getRegBankFromRegClass(*RC, LLT());
2701bool AMDGPUInstructionSelector::selectG_SZA_EXT(
MachineInstr &
I)
const {
2702 bool InReg =
I.getOpcode() == AMDGPU::G_SEXT_INREG;
2703 bool Signed =
I.getOpcode() == AMDGPU::G_SEXT || InReg;
2706 const Register DstReg =
I.getOperand(0).getReg();
2707 const Register SrcReg =
I.getOperand(1).getReg();
2709 const LLT DstTy = MRI->getType(DstReg);
2710 const LLT SrcTy = MRI->getType(SrcReg);
2711 const unsigned SrcSize =
I.getOpcode() == AMDGPU::G_SEXT_INREG ?
2718 const RegisterBank *SrcBank = getArtifactRegBank(SrcReg, *MRI, TRI);
2721 if (
I.getOpcode() == AMDGPU::G_ANYEXT) {
2723 return selectCOPY(
I);
2726 TRI.getRegClassForTypeOnBank(SrcTy, *SrcBank);
2727 const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
2729 TRI.getRegClassForSizeOnBank(DstSize, *DstBank);
2731 Register UndefReg = MRI->createVirtualRegister(SrcRC);
2732 BuildMI(
MBB,
I,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefReg);
2738 I.eraseFromParent();
2740 return RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) &&
2741 RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI);
2744 if (SrcBank->
getID() == AMDGPU::VGPRRegBankID && DstSize <= 32) {
2750 MachineInstr *ExtI =
2754 I.eraseFromParent();
2759 const unsigned BFE =
Signed ? AMDGPU::V_BFE_I32_e64 : AMDGPU::V_BFE_U32_e64;
2760 MachineInstr *ExtI =
2765 I.eraseFromParent();
2770 if (SrcBank->
getID() == AMDGPU::SGPRRegBankID && DstSize <= 64) {
2772 AMDGPU::SReg_64RegClass : AMDGPU::SReg_32RegClass;
2773 if (!RBI.constrainGenericRegister(SrcReg, SrcRC, *MRI))
2776 if (
Signed && DstSize == 32 && (SrcSize == 8 || SrcSize == 16)) {
2777 const unsigned SextOpc = SrcSize == 8 ?
2778 AMDGPU::S_SEXT_I32_I8 : AMDGPU::S_SEXT_I32_I16;
2781 I.eraseFromParent();
2782 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_32RegClass, *MRI);
2787 if (DstSize > 32 && SrcSize == 32) {
2788 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2789 unsigned SubReg = InReg ? AMDGPU::sub0 : AMDGPU::NoSubRegister;
2792 .
addReg(SrcReg, {}, SubReg)
2800 .
addReg(SrcReg, {}, SubReg)
2801 .addImm(AMDGPU::sub0)
2804 I.eraseFromParent();
2805 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_64RegClass,
2809 const unsigned BFE64 =
Signed ? AMDGPU::S_BFE_I64 : AMDGPU::S_BFE_U64;
2810 const unsigned BFE32 =
Signed ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32;
2813 if (DstSize > 32 && (SrcSize <= 32 || InReg)) {
2815 Register ExtReg = MRI->createVirtualRegister(&AMDGPU::SReg_64RegClass);
2816 Register UndefReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2817 unsigned SubReg = InReg ? AMDGPU::sub0 : AMDGPU::NoSubRegister;
2819 BuildMI(
MBB,
I,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefReg);
2821 .
addReg(SrcReg, {}, SubReg)
2822 .addImm(AMDGPU::sub0)
2830 I.eraseFromParent();
2831 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_64RegClass, *MRI);
2846 I.eraseFromParent();
2847 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_32RegClass, *MRI);
2906 assert(Mask.size() == 2);
2908 if (Mask[0] == 1 && Mask[1] <= 1) {
2923 if (Unmerge->getNumDefs() == 2 && Unmerge->getOperand(0).getReg() == In &&
2941bool AMDGPUInstructionSelector::selectG_FPEXT(
MachineInstr &
I)
const {
2942 if (!Subtarget->hasSALUFloatInsts())
2945 Register Dst =
I.getOperand(0).getReg();
2946 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
2947 if (DstRB->
getID() != AMDGPU::SGPRRegBankID)
2950 Register Src =
I.getOperand(1).getReg();
2956 BuildMI(*BB, &
I,
I.getDebugLoc(), TII.get(AMDGPU::S_CVT_HI_F32_F16), Dst)
2958 I.eraseFromParent();
2959 return RBI.constrainGenericRegister(Dst, AMDGPU::SReg_32RegClass, *MRI);
2966bool AMDGPUInstructionSelector::selectG_FNEG(
MachineInstr &
MI)
const {
2979 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
2980 if (DstRB->
getID() != AMDGPU::SGPRRegBankID ||
2985 MachineInstr *Fabs =
getOpcodeDef(TargetOpcode::G_FABS, Src, *MRI);
2989 if (!RBI.constrainGenericRegister(Src, AMDGPU::SReg_64RegClass, *MRI) ||
2990 !RBI.constrainGenericRegister(Dst, AMDGPU::SReg_64RegClass, *MRI))
2995 Register LoReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2996 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2997 Register ConstReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2998 Register OpReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3000 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), LoReg)
3001 .
addReg(Src, {}, AMDGPU::sub0);
3002 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), HiReg)
3003 .
addReg(Src, {}, AMDGPU::sub1);
3004 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_MOV_B32), ConstReg)
3008 unsigned Opc = Fabs ? AMDGPU::S_OR_B32 : AMDGPU::S_XOR_B32;
3013 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::REG_SEQUENCE), Dst)
3018 MI.eraseFromParent();
3023bool AMDGPUInstructionSelector::selectG_FABS(
MachineInstr &
MI)
const {
3025 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
3026 if (DstRB->
getID() != AMDGPU::SGPRRegBankID ||
3033 Register LoReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3034 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3035 Register ConstReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3036 Register OpReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3038 if (!RBI.constrainGenericRegister(Src, AMDGPU::SReg_64RegClass, *MRI) ||
3039 !RBI.constrainGenericRegister(Dst, AMDGPU::SReg_64RegClass, *MRI))
3042 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), LoReg)
3043 .
addReg(Src, {}, AMDGPU::sub0);
3044 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), HiReg)
3045 .
addReg(Src, {}, AMDGPU::sub1);
3046 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_MOV_B32), ConstReg)
3051 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_AND_B32), OpReg)
3055 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::REG_SEQUENCE), Dst)
3061 MI.eraseFromParent();
3066 return MI.getOpcode() == TargetOpcode::G_CONSTANT;
3072 unsigned OpNo =
Load.getOpcode() == AMDGPU::G_PREFETCH ? 0 : 1;
3073 const MachineInstr *PtrMI =
3074 MRI.getUniqueVRegDef(
Load.getOperand(OpNo).getReg());
3078 if (PtrMI->
getOpcode() != TargetOpcode::G_PTR_ADD)
3083 for (
unsigned i = 1; i != 3; ++i) {
3084 const MachineOperand &GEPOp = PtrMI->
getOperand(i);
3085 const MachineInstr *OpDef = MRI.getUniqueVRegDef(GEPOp.
getReg());
3090 assert(GEPInfo.Imm == 0);
3094 const RegisterBank *OpBank = RBI.getRegBank(GEPOp.
getReg(), MRI, TRI);
3095 if (OpBank->
getID() == AMDGPU::SGPRRegBankID)
3096 GEPInfo.SgprParts.push_back(GEPOp.
getReg());
3098 GEPInfo.VgprParts.push_back(GEPOp.
getReg());
3102 getAddrModeInfo(*PtrMI, MRI, AddrInfo);
3105bool AMDGPUInstructionSelector::isSGPR(
Register Reg)
const {
3106 return RBI.getRegBank(
Reg, *MRI, TRI)->getID() == AMDGPU::SGPRRegBankID;
3109bool AMDGPUInstructionSelector::isInstrUniform(
const MachineInstr &
MI)
const {
3110 if (!
MI.hasOneMemOperand())
3113 const MachineMemOperand *MMO = *
MI.memoperands_begin();
3126 if (
MI.getOpcode() == AMDGPU::G_PREFETCH)
3127 return RBI.getRegBank(
MI.getOperand(0).getReg(), *MRI, TRI)->getID() ==
3128 AMDGPU::SGPRRegBankID;
3131 return I &&
I->getMetadata(
"amdgpu.uniform");
3135 for (
const GEPInfo &GEPInfo : AddrInfo) {
3136 if (!GEPInfo.VgprParts.empty())
3142void AMDGPUInstructionSelector::initM0(
MachineInstr &
I)
const {
3143 const LLT PtrTy = MRI->getType(
I.getOperand(1).getReg());
3146 STI.ldsRequiresM0Init()) {
3150 BuildMI(*BB, &
I,
I.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), AMDGPU::M0)
3155bool AMDGPUInstructionSelector::selectG_LOAD_STORE_ATOMICRMW(
3162 if (
Reg.isPhysical())
3166 const unsigned Opcode =
MI.getOpcode();
3168 if (Opcode == AMDGPU::COPY)
3171 if (Opcode == AMDGPU::G_AND || Opcode == AMDGPU::G_OR ||
3172 Opcode == AMDGPU::G_XOR)
3177 return GI->is(Intrinsic::amdgcn_class);
3179 return Opcode == AMDGPU::G_ICMP || Opcode == AMDGPU::G_FCMP;
3182bool AMDGPUInstructionSelector::selectG_BRCOND(
MachineInstr &
I)
const {
3184 MachineOperand &CondOp =
I.getOperand(0);
3197 if (!isVCC(CondReg, *MRI)) {
3201 CondPhysReg = AMDGPU::SCC;
3202 BrOpcode = AMDGPU::S_CBRANCH_SCC1;
3203 ConstrainRC = &AMDGPU::SReg_32RegClass;
3210 const bool Is64 = STI.isWave64();
3211 const unsigned Opcode = Is64 ? AMDGPU::S_AND_B64 : AMDGPU::S_AND_B32;
3212 const Register Exec = Is64 ? AMDGPU::EXEC : AMDGPU::EXEC_LO;
3214 Register TmpReg = MRI->createVirtualRegister(TRI.getBoolRC());
3215 BuildMI(*BB, &
I,
DL, TII.get(Opcode), TmpReg)
3222 CondPhysReg = TRI.getVCC();
3223 BrOpcode = AMDGPU::S_CBRANCH_VCCNZ;
3224 ConstrainRC = TRI.getBoolRC();
3227 if (!MRI->getRegClassOrNull(CondReg))
3228 MRI->setRegClass(CondReg, ConstrainRC);
3230 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), CondPhysReg)
3233 .
addMBB(
I.getOperand(1).getMBB());
3235 I.eraseFromParent();
3239bool AMDGPUInstructionSelector::selectG_GLOBAL_VALUE(
3241 Register DstReg =
I.getOperand(0).getReg();
3242 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3243 const bool IsVGPR = DstRB->
getID() == AMDGPU::VGPRRegBankID;
3244 I.setDesc(TII.get(IsVGPR ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32));
3248 return RBI.constrainGenericRegister(
3249 DstReg, IsVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass, *MRI);
3252bool AMDGPUInstructionSelector::selectG_PTRMASK(
MachineInstr &
I)
const {
3253 Register DstReg =
I.getOperand(0).getReg();
3254 Register SrcReg =
I.getOperand(1).getReg();
3255 Register MaskReg =
I.getOperand(2).getReg();
3256 LLT Ty = MRI->getType(DstReg);
3257 LLT MaskTy = MRI->getType(MaskReg);
3261 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3262 const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
3263 const RegisterBank *MaskRB = RBI.getRegBank(MaskReg, *MRI, TRI);
3264 const bool IsVGPR = DstRB->
getID() == AMDGPU::VGPRRegBankID;
3270 APInt MaskOnes =
VT->getKnownOnes(MaskReg).zext(64);
3274 const bool CanCopyLow32 = (MaskOnes & MaskLo32) == MaskLo32;
3275 const bool CanCopyHi32 = (MaskOnes & MaskHi32) == MaskHi32;
3278 !CanCopyLow32 && !CanCopyHi32) {
3279 auto MIB =
BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_AND_B64), DstReg)
3283 I.eraseFromParent();
3288 unsigned NewOpc = IsVGPR ? AMDGPU::V_AND_B32_e64 : AMDGPU::S_AND_B32;
3290 = IsVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
3295 TRI.getRegClassForTypeOnBank(MaskTy, *MaskRB);
3297 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
3298 !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
3299 !RBI.constrainGenericRegister(MaskReg, *MaskRC, *MRI))
3304 "ptrmask should have been narrowed during legalize");
3306 auto NewOp =
BuildMI(*BB, &
I,
DL, TII.get(NewOpc), DstReg)
3312 I.eraseFromParent();
3316 Register HiReg = MRI->createVirtualRegister(&RegRC);
3317 Register LoReg = MRI->createVirtualRegister(&RegRC);
3320 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), LoReg)
3321 .
addReg(SrcReg, {}, AMDGPU::sub0);
3322 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), HiReg)
3323 .
addReg(SrcReg, {}, AMDGPU::sub1);
3332 Register MaskLo = MRI->createVirtualRegister(&RegRC);
3333 MaskedLo = MRI->createVirtualRegister(&RegRC);
3335 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), MaskLo)
3336 .
addReg(MaskReg, {}, AMDGPU::sub0);
3337 BuildMI(*BB, &
I,
DL, TII.get(NewOpc), MaskedLo)
3346 Register MaskHi = MRI->createVirtualRegister(&RegRC);
3347 MaskedHi = MRI->createVirtualRegister(&RegRC);
3349 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), MaskHi)
3350 .
addReg(MaskReg, {}, AMDGPU::sub1);
3351 BuildMI(*BB, &
I,
DL, TII.get(NewOpc), MaskedHi)
3356 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
3361 I.eraseFromParent();
3367static std::pair<Register, unsigned>
3374 std::tie(IdxBaseReg,
Offset) =
3376 if (IdxBaseReg == AMDGPU::NoRegister) {
3380 IdxBaseReg = IdxReg;
3387 if (
static_cast<unsigned>(
Offset) >= SubRegs.
size())
3388 return std::pair(IdxReg, SubRegs[0]);
3389 return std::pair(IdxBaseReg, SubRegs[
Offset]);
3392bool AMDGPUInstructionSelector::selectG_EXTRACT_VECTOR_ELT(
3398 LLT DstTy = MRI->getType(DstReg);
3399 LLT SrcTy = MRI->getType(SrcReg);
3401 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3402 const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
3403 const RegisterBank *IdxRB = RBI.getRegBank(IdxReg, *MRI, TRI);
3407 if (IdxRB->
getID() != AMDGPU::SGPRRegBankID)
3411 TRI.getRegClassForTypeOnBank(SrcTy, *SrcRB);
3413 TRI.getRegClassForTypeOnBank(DstTy, *DstRB);
3414 if (!SrcRC || !DstRC)
3416 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
3417 !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
3418 !RBI.constrainGenericRegister(IdxReg, AMDGPU::SReg_32RegClass, *MRI))
3429 if (SrcRB->
getID() == AMDGPU::SGPRRegBankID) {
3433 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3436 unsigned Opc = Is64 ? AMDGPU::S_MOVRELS_B64 : AMDGPU::S_MOVRELS_B32;
3438 .
addReg(SrcReg, {}, SubReg)
3440 MI.eraseFromParent();
3447 if (!STI.useVGPRIndexMode()) {
3448 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3450 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::V_MOVRELS_B32_e32), DstReg)
3451 .
addReg(SrcReg, {}, SubReg)
3453 MI.eraseFromParent();
3457 const MCInstrDesc &GPRIDXDesc =
3458 TII.getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*SrcRC),
true);
3464 MI.eraseFromParent();
3469bool AMDGPUInstructionSelector::selectG_INSERT_VECTOR_ELT(
3476 LLT VecTy = MRI->getType(DstReg);
3477 LLT ValTy = MRI->getType(ValReg);
3481 const RegisterBank *VecRB = RBI.getRegBank(VecReg, *MRI, TRI);
3482 const RegisterBank *ValRB = RBI.getRegBank(ValReg, *MRI, TRI);
3483 const RegisterBank *IdxRB = RBI.getRegBank(IdxReg, *MRI, TRI);
3489 if (IdxRB->
getID() != AMDGPU::SGPRRegBankID)
3493 TRI.getRegClassForTypeOnBank(VecTy, *VecRB);
3495 TRI.getRegClassForTypeOnBank(ValTy, *ValRB);
3497 if (!RBI.constrainGenericRegister(VecReg, *VecRC, *MRI) ||
3498 !RBI.constrainGenericRegister(DstReg, *VecRC, *MRI) ||
3499 !RBI.constrainGenericRegister(ValReg, *ValRC, *MRI) ||
3500 !RBI.constrainGenericRegister(IdxReg, AMDGPU::SReg_32RegClass, *MRI))
3503 if (VecRB->
getID() == AMDGPU::VGPRRegBankID && ValSize != 32)
3507 std::tie(IdxReg, SubReg) =
3510 const bool IndexMode = VecRB->
getID() == AMDGPU::VGPRRegBankID &&
3511 STI.useVGPRIndexMode();
3517 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3520 const MCInstrDesc &RegWriteOp = TII.getIndirectRegWriteMovRelPseudo(
3521 VecSize, ValSize, VecRB->
getID() == AMDGPU::SGPRRegBankID);
3526 MI.eraseFromParent();
3530 const MCInstrDesc &GPRIDXDesc =
3531 TII.getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC),
false);
3538 MI.eraseFromParent();
3544 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
3545 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
3546 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
3547 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
3548 case Intrinsic::amdgcn_load_async_to_lds:
3549 case Intrinsic::amdgcn_global_load_async_lds:
3555bool AMDGPUInstructionSelector::selectBufferLoadLds(
MachineInstr &
MI)
const {
3556 if (!Subtarget->hasVMemToLDSLoad())
3559 unsigned Size =
MI.getOperand(3).getImm();
3563 const bool HasVIndex =
MI.getNumOperands() == 9;
3567 VIndex =
MI.getOperand(4).getReg();
3571 Register VOffset =
MI.getOperand(4 + OpOffset).getReg();
3572 std::optional<ValueAndVReg> MaybeVOffset =
3574 const bool HasVOffset = !MaybeVOffset || MaybeVOffset->Value.getZExtValue();
3580 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_BOTHEN
3581 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_IDXEN
3582 : HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFEN
3583 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFSET;
3586 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_BOTHEN
3587 : AMDGPU::BUFFER_LOAD_USHORT_LDS_IDXEN
3588 : HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFEN
3589 : AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFSET;
3592 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_BOTHEN
3593 : AMDGPU::BUFFER_LOAD_DWORD_LDS_IDXEN
3594 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFEN
3595 : AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFSET;
3598 if (!Subtarget->hasLDSLoadB96_B128())
3601 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_BOTHEN
3602 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_IDXEN
3603 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFEN
3604 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFSET;
3607 if (!Subtarget->hasLDSLoadB96_B128())
3610 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_BOTHEN
3611 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_IDXEN
3612 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFEN
3613 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFSET;
3620 .
add(
MI.getOperand(2));
3624 if (HasVIndex && HasVOffset) {
3625 Register IdxReg = MRI->createVirtualRegister(TRI.getVGPR64Class());
3626 BuildMI(*
MBB, &*MIB,
DL, TII.get(AMDGPU::REG_SEQUENCE), IdxReg)
3633 }
else if (HasVIndex) {
3635 }
else if (HasVOffset) {
3639 MIB.
add(
MI.getOperand(1));
3640 MIB.
add(
MI.getOperand(5 + OpOffset));
3641 MIB.
add(
MI.getOperand(6 + OpOffset));
3643 unsigned Aux =
MI.getOperand(7 + OpOffset).getImm();
3652 MachineMemOperand *LoadMMO = *
MI.memoperands_begin();
3657 MachinePointerInfo StorePtrI = LoadPtrI;
3668 MachineMemOperand *StoreMMO =
3674 MI.eraseFromParent();
3687 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3693 return Def->getOperand(1).getReg();
3707 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3715 return Def->getOperand(1).getReg();
3718 if (ZextSrc &&
VT->signBitIsZero(ZextSrc))
3727AMDGPUInstructionSelector::matchZeroExtendFromS32OrS32(
Register Reg)
const {
3729 : matchZeroExtendFromS32(
Reg);
3735AMDGPUInstructionSelector::matchSignExtendFromS32OrS32(
Register Reg)
const {
3737 : matchSignExtendFromS32(
Reg);
3741AMDGPUInstructionSelector::matchExtendFromS32OrS32(
Register Reg,
3742 bool IsSigned)
const {
3744 return matchSignExtendFromS32OrS32(
Reg);
3746 return matchZeroExtendFromS32OrS32(
Reg);
3756 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3763 return Def->getOperand(1).getReg();
3768bool AMDGPUInstructionSelector::selectGlobalLoadLds(
MachineInstr &
MI)
const{
3769 if (!Subtarget->hasVMemToLDSLoad())
3773 unsigned Size =
MI.getOperand(3).getImm();
3780 Opc = AMDGPU::GLOBAL_LOAD_LDS_UBYTE;
3783 Opc = AMDGPU::GLOBAL_LOAD_LDS_USHORT;
3786 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORD;
3789 if (!Subtarget->hasLDSLoadB96_B128())
3791 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX3;
3794 if (!Subtarget->hasLDSLoadB96_B128())
3796 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX4;
3803 .
add(
MI.getOperand(2));
3809 if (!isSGPR(Addr)) {
3811 if (isSGPR(AddrDef->Reg)) {
3812 Addr = AddrDef->Reg;
3813 }
else if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
3816 if (isSGPR(SAddr)) {
3817 Register PtrBaseOffset = AddrDef->MI->getOperand(2).getReg();
3818 if (
Register Off = matchZeroExtendFromS32(PtrBaseOffset)) {
3829 VOffset = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
3841 MIB.
add(
MI.getOperand(4));
3843 unsigned Aux =
MI.getOperand(5).getImm();
3847 MachineMemOperand *LoadMMO = *
MI.memoperands_begin();
3849 LoadPtrI.
Offset =
MI.getOperand(4).getImm();
3850 MachinePointerInfo StorePtrI = LoadPtrI;
3859 MachineMemOperand *StoreMMO =
3861 sizeof(int32_t),
Align(4));
3865 MI.eraseFromParent();
3870bool AMDGPUInstructionSelector::selectTensorLoadStore(
MachineInstr &
MI,
3872 bool IsLoad = IID == Intrinsic::amdgcn_tensor_load_to_lds;
3874 IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d4 : AMDGPU::TENSOR_STORE_FROM_LDS_d4;
3878 const auto isAllZeros = [&](MachineOperand &Opnd) {
3879 const MachineInstr *
DefMI = MRI->getVRegDef(Opnd.getReg());
3888 Opc = IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d2
3889 : AMDGPU::TENSOR_STORE_FROM_LDS_d2;
3896 .
add(
MI.getOperand(1))
3897 .
add(
MI.getOperand(2));
3899 if (NumGroups >= 4) {
3900 MIB.
add(
MI.getOperand(3))
3901 .
add(
MI.getOperand(4));
3905 .
add(
MI.getOperand(6));
3907 MI.eraseFromParent();
3911bool AMDGPUInstructionSelector::selectBVHIntersectRayIntrinsic(
3913 unsigned OpcodeOpIdx =
3914 MI.getOpcode() == AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY ? 1 : 3;
3915 MI.setDesc(TII.get(
MI.getOperand(OpcodeOpIdx).getImm()));
3916 MI.removeOperand(OpcodeOpIdx);
3917 MI.addImplicitDefUseOperands(*
MI.getMF());
3924bool AMDGPUInstructionSelector::selectSMFMACIntrin(
MachineInstr &
MI)
const {
3927 case Intrinsic::amdgcn_smfmac_f32_16x16x32_f16:
3928 Opc = AMDGPU::V_SMFMAC_F32_16X16X32_F16_e64;
3930 case Intrinsic::amdgcn_smfmac_f32_32x32x16_f16:
3931 Opc = AMDGPU::V_SMFMAC_F32_32X32X16_F16_e64;
3933 case Intrinsic::amdgcn_smfmac_f32_16x16x32_bf16:
3934 Opc = AMDGPU::V_SMFMAC_F32_16X16X32_BF16_e64;
3936 case Intrinsic::amdgcn_smfmac_f32_32x32x16_bf16:
3937 Opc = AMDGPU::V_SMFMAC_F32_32X32X16_BF16_e64;
3939 case Intrinsic::amdgcn_smfmac_i32_16x16x64_i8:
3940 Opc = AMDGPU::V_SMFMAC_I32_16X16X64_I8_e64;
3942 case Intrinsic::amdgcn_smfmac_i32_32x32x32_i8:
3943 Opc = AMDGPU::V_SMFMAC_I32_32X32X32_I8_e64;
3945 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_bf8:
3946 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF8_BF8_e64;
3948 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_fp8:
3949 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF8_FP8_e64;
3951 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_bf8:
3952 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_FP8_BF8_e64;
3954 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_fp8:
3955 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_FP8_FP8_e64;
3957 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_bf8:
3958 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF8_BF8_e64;
3960 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_fp8:
3961 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF8_FP8_e64;
3963 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_bf8:
3964 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_FP8_BF8_e64;
3966 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_fp8:
3967 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_FP8_FP8_e64;
3969 case Intrinsic::amdgcn_smfmac_f32_16x16x64_f16:
3970 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_F16_e64;
3972 case Intrinsic::amdgcn_smfmac_f32_32x32x32_f16:
3973 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_F16_e64;
3975 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf16:
3976 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF16_e64;
3978 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf16:
3979 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF16_e64;
3981 case Intrinsic::amdgcn_smfmac_i32_16x16x128_i8:
3982 Opc = AMDGPU::V_SMFMAC_I32_16X16X128_I8_e64;
3984 case Intrinsic::amdgcn_smfmac_i32_32x32x64_i8:
3985 Opc = AMDGPU::V_SMFMAC_I32_32X32X64_I8_e64;
3987 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_bf8:
3988 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_BF8_BF8_e64;
3990 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_fp8:
3991 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_BF8_FP8_e64;
3993 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_bf8:
3994 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_FP8_BF8_e64;
3996 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_fp8:
3997 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_FP8_FP8_e64;
3999 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_bf8:
4000 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_BF8_BF8_e64;
4002 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_fp8:
4003 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_BF8_FP8_e64;
4005 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_bf8:
4006 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_FP8_BF8_e64;
4008 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_fp8:
4009 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_FP8_FP8_e64;
4015 auto VDst_In =
MI.getOperand(4);
4017 MI.setDesc(TII.get(
Opc));
4018 MI.removeOperand(4);
4019 MI.removeOperand(1);
4020 MI.addOperand(VDst_In);
4021 MI.addImplicitDefUseOperands(*
MI.getMF());
4022 const MCInstrDesc &MCID =
MI.getDesc();
4024 MI.getOperand(0).setIsEarlyClobber(
true);
4029bool AMDGPUInstructionSelector::selectPermlaneSwapIntrin(
4031 if (IntrID == Intrinsic::amdgcn_permlane16_swap &&
4032 !Subtarget->hasPermlane16Swap())
4034 if (IntrID == Intrinsic::amdgcn_permlane32_swap &&
4035 !Subtarget->hasPermlane32Swap())
4038 unsigned Opcode = IntrID == Intrinsic::amdgcn_permlane16_swap
4039 ? AMDGPU::V_PERMLANE16_SWAP_B32_e64
4040 : AMDGPU::V_PERMLANE32_SWAP_B32_e64;
4042 MI.removeOperand(2);
4043 MI.setDesc(TII.get(Opcode));
4046 MachineOperand &FI =
MI.getOperand(4);
4053bool AMDGPUInstructionSelector::selectWaveAddress(
MachineInstr &
MI)
const {
4056 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4057 const bool IsVALU = DstRB->
getID() == AMDGPU::VGPRRegBankID;
4062 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHRREV_B32_e64), DstReg)
4063 .
addImm(Subtarget->getWavefrontSizeLog2())
4068 .
addImm(Subtarget->getWavefrontSizeLog2())
4073 IsVALU ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
4074 if (!RBI.constrainGenericRegister(DstReg, RC, *MRI))
4077 MI.eraseFromParent();
4081bool AMDGPUInstructionSelector::selectWaveShuffleIntrin(
4091 const LLT DstTy = MRI->getType(DstReg);
4093 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4095 TRI.getRegClassForSizeOnBank(DstSize, *DstRB);
4100 if (!Subtarget->supportsBPermute())
4104 if (Subtarget->supportsWaveWideBPermute()) {
4105 Register ShiftIdxReg = MRI->createVirtualRegister(DstRC);
4106 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), ShiftIdxReg)
4116 assert(Subtarget->isWave64());
4120 MRI->createVirtualRegister(TRI.getRegClass(AMDGPU::SReg_32RegClassID));
4121 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefValReg);
4123 Register UndefExecReg = MRI->createVirtualRegister(
4124 TRI.getRegClass(AMDGPU::SReg_64_XEXECRegClassID));
4125 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefExecReg);
4127 Register PoisonValReg = MRI->createVirtualRegister(DstRC);
4128 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_SET_INACTIVE_B32), PoisonValReg)
4136 Register ShiftIdxReg = MRI->createVirtualRegister(DstRC);
4137 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), ShiftIdxReg)
4141 Register PoisonIdxReg = MRI->createVirtualRegister(DstRC);
4142 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_SET_INACTIVE_B32), PoisonIdxReg)
4149 Register PoisonUnshiftedIdxReg = MRI->createVirtualRegister(DstRC);
4151 PoisonUnshiftedIdxReg)
4159 Register SameSidePermReg = MRI->createVirtualRegister(DstRC);
4160 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::DS_BPERMUTE_B32), SameSidePermReg)
4165 Register SwappedValReg = MRI->createVirtualRegister(DstRC);
4166 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_PERMLANE64_B32), SwappedValReg)
4169 Register OppSidePermReg = MRI->createVirtualRegister(DstRC);
4170 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::DS_BPERMUTE_B32), OppSidePermReg)
4175 Register WWMSwapPermReg = MRI->createVirtualRegister(DstRC);
4176 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::STRICT_WWM), WWMSwapPermReg)
4183 Register ThreadIDReg = MRI->createVirtualRegister(DstRC);
4184 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_MBCNT_LO_U32_B32_e64), ThreadIDReg)
4188 Register XORReg = MRI->createVirtualRegister(DstRC);
4191 .
addReg(PoisonUnshiftedIdxReg);
4193 Register ANDReg = MRI->createVirtualRegister(DstRC);
4198 Register CompareReg = MRI->createVirtualRegister(
4199 TRI.getRegClass(AMDGPU::SReg_64_XEXECRegClassID));
4200 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_CMP_EQ_U32_e64), CompareReg)
4205 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
4213 MI.eraseFromParent();
4222 unsigned NumOpcodes = 0;
4235 const uint8_t SrcBits[3] = { 0xf0, 0xcc, 0xaa };
4246 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4260 if (Src.size() == 3) {
4267 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4268 if (Src[
I] ==
LHS) {
4278 Bits = SrcBits[Src.size()];
4284 switch (
MI->getOpcode()) {
4285 case TargetOpcode::G_AND:
4286 case TargetOpcode::G_OR:
4287 case TargetOpcode::G_XOR: {
4292 if (!getOperandBits(
LHS, LHSBits) ||
4293 !getOperandBits(
RHS, RHSBits)) {
4294 Src = std::move(Backup);
4295 return std::make_pair(0, 0);
4316 uint8_t LHSBitsOrig = LHSBits;
4317 uint8_t RHSBitsOrig = RHSBits;
4321 NumOpcodes += LHSOp.first;
4322 LHSBits = LHSOp.second;
4329 NumOpcodes += RHSOp.first;
4330 RHSBits = RHSOp.second;
4334 auto dependsOnSlot = [](
uint8_t TT,
int Slot) ->
bool {
4335 if (Slot < 0 || Slot > 2)
4337 const uint8_t Masks[3] = {0x0f, 0x33, 0x55};
4338 const int Shifts[3] = {4, 2, 1};
4339 return ((TT ^ (TT >> Shifts[Slot])) & Masks[Slot]) != 0;
4345 const uint8_t SrcBitsConst[3] = {0xf0, 0xcc, 0xaa};
4352 for (
int I = 0;
I < (int)S.size();
I++) {
4353 if (Bits == SrcBitsConst[
I] && S[
I] ==
Op)
4355 if (IsNegationOp && Bits == (
uint8_t)~SrcBitsConst[
I] &&
4356 S[
I] == NegatedInner)
4367 for (
int I = 0;
I < (int)SrcAfterLHS.
size() &&
I < 3;
I++) {
4368 if (
I < (
int)Src.size() && Src[
I] != SrcAfterLHS[
I] &&
4369 dependsOnSlot(LHSBits,
I)) {
4378 if (!Stale && !RHSOp.first) {
4379 int Slot = findSlot(RHSBitsOrig,
RHS, SrcBeforeRecurse);
4381 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4387 if (!Stale && !LHSOp.first) {
4388 int Slot = findSlot(LHSBitsOrig,
LHS, SrcBeforeRecurse);
4390 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4395 Src = std::move(SrcBeforeRecurse);
4396 LHSBits = LHSBitsOrig;
4397 RHSBits = RHSBitsOrig;
4403 return std::make_pair(0, 0);
4407 switch (
MI->getOpcode()) {
4408 case TargetOpcode::G_AND:
4409 TTbl = LHSBits & RHSBits;
4411 case TargetOpcode::G_OR:
4412 TTbl = LHSBits | RHSBits;
4414 case TargetOpcode::G_XOR:
4415 TTbl = LHSBits ^ RHSBits;
4421 return std::make_pair(NumOpcodes + 1, TTbl);
4424bool AMDGPUInstructionSelector::selectBITOP3(
MachineInstr &
MI)
const {
4425 if (!Subtarget->hasBitOp3Insts())
4429 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4430 const bool IsVALU = DstRB->
getID() == AMDGPU::VGPRRegBankID;
4436 unsigned NumOpcodes;
4438 std::tie(NumOpcodes, TTbl) =
BitOp3_Op(DstReg, Src, *MRI);
4442 if (NumOpcodes < 2 || Src.empty())
4447 unsigned Size = MRI->getType(DstReg).getSizeInBits();
4448 assert((
Size == 16 ||
Size == 32) &&
"unexpected VALU logic op size");
4449 const bool IsB32 =
Size == 32;
4450 if (NumOpcodes == 2 && IsB32) {
4458 }
else if (NumOpcodes < 4) {
4465 unsigned Opc = IsB32 ? AMDGPU::V_BITOP3_B32_e64 : AMDGPU::V_BITOP3_B16_e64;
4466 if (!IsB32 && STI.hasTrue16BitInsts())
4467 Opc = STI.useRealTrue16Insts() ? AMDGPU::V_BITOP3_B16_gfx1250_t16_e64
4468 : AMDGPU::V_BITOP3_B16_gfx1250_fake16_e64;
4469 unsigned CBL = STI.getConstantBusLimit(
Opc);
4473 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4474 const RegisterBank *RB = RBI.getRegBank(Src[
I], *MRI, TRI);
4475 if (RB->
getID() != AMDGPU::SGPRRegBankID)
4481 Register NewReg = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
4492 while (Src.size() < 3)
4493 Src.push_back(Src[0]);
4510 MI.eraseFromParent();
4515bool AMDGPUInstructionSelector::selectWriteRegister(
MachineInstr &
MI)
const {
4516 const MDString *RegStr =
4519 LLT Ty = MRI->getType(SrcReg);
4521 Register PhysReg = Subtarget->getTargetLowering()->getRegisterByName(
4526 "invalid register \"" + Twine(RegStr->
getString()) +
4527 "\" for llvm.write_register",
4528 Fn,
MI.getDebugLoc()));
4529 MI.eraseFromParent();
4533 if (!RBI.constrainGenericRegister(
4534 SrcReg, *TRI.getSGPRClassForBitWidth(Ty.
getSizeInBits()), *MRI))
4537 BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(), TII.get(AMDGPU::COPY), PhysReg)
4539 MI.eraseFromParent();
4543bool AMDGPUInstructionSelector::selectStackRestore(
MachineInstr &
MI)
const {
4545 if (!RBI.constrainGenericRegister(SrcReg, AMDGPU::SReg_32RegClass, *MRI))
4548 MachineInstr *
DefMI = MRI->getVRegDef(SrcReg);
4550 Subtarget->getTargetLowering()->getStackPointerRegisterToSaveRestore();
4556 WaveAddr = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
4559 .
addImm(Subtarget->getWavefrontSizeLog2())
4566 MI.eraseFromParent();
4572 if (!
I.isPreISelOpcode()) {
4574 return selectCOPY(
I);
4578 switch (
I.getOpcode()) {
4579 case TargetOpcode::G_AND:
4580 case TargetOpcode::G_OR:
4581 case TargetOpcode::G_XOR:
4582 if (selectBITOP3(
I))
4586 return selectG_AND_OR_XOR(
I);
4587 case TargetOpcode::G_ADD:
4588 case TargetOpcode::G_SUB:
4589 case TargetOpcode::G_PTR_ADD:
4592 return selectG_ADD_SUB(
I);
4593 case TargetOpcode::G_UADDO:
4594 case TargetOpcode::G_USUBO:
4595 case TargetOpcode::G_UADDE:
4596 case TargetOpcode::G_USUBE:
4597 return selectG_UADDO_USUBO_UADDE_USUBE(
I);
4598 case AMDGPU::G_AMDGPU_MAD_U64_U32:
4599 case AMDGPU::G_AMDGPU_MAD_I64_I32:
4600 return selectG_AMDGPU_MAD_64_32(
I);
4601 case TargetOpcode::G_INTTOPTR:
4602 case TargetOpcode::G_BITCAST:
4603 case TargetOpcode::G_PTRTOINT:
4604 case TargetOpcode::G_FREEZE:
4605 return selectCOPY(
I);
4606 case TargetOpcode::G_FNEG:
4609 return selectG_FNEG(
I);
4610 case TargetOpcode::G_FABS:
4613 return selectG_FABS(
I);
4614 case TargetOpcode::G_EXTRACT:
4615 return selectG_EXTRACT(
I);
4616 case TargetOpcode::G_MERGE_VALUES:
4617 case TargetOpcode::G_CONCAT_VECTORS:
4618 return selectG_MERGE_VALUES(
I);
4619 case TargetOpcode::G_UNMERGE_VALUES:
4620 return selectG_UNMERGE_VALUES(
I);
4621 case TargetOpcode::G_BUILD_VECTOR:
4622 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
4623 return selectG_BUILD_VECTOR(
I);
4624 case TargetOpcode::G_IMPLICIT_DEF:
4625 return selectG_IMPLICIT_DEF(
I);
4626 case TargetOpcode::G_INSERT:
4627 return selectG_INSERT(
I);
4628 case TargetOpcode::G_INTRINSIC:
4629 case TargetOpcode::G_INTRINSIC_CONVERGENT:
4630 return selectG_INTRINSIC(
I);
4631 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
4632 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
4633 return selectG_INTRINSIC_W_SIDE_EFFECTS(
I);
4634 case TargetOpcode::G_ICMP:
4635 case TargetOpcode::G_FCMP:
4636 if (selectG_ICMP_or_FCMP(
I))
4639 case TargetOpcode::G_LOAD:
4640 case TargetOpcode::G_ZEXTLOAD:
4641 case TargetOpcode::G_SEXTLOAD:
4642 case TargetOpcode::G_STORE:
4643 case TargetOpcode::G_ATOMIC_CMPXCHG:
4644 case TargetOpcode::G_ATOMICRMW_XCHG:
4645 case TargetOpcode::G_ATOMICRMW_ADD:
4646 case TargetOpcode::G_ATOMICRMW_SUB:
4647 case TargetOpcode::G_ATOMICRMW_AND:
4648 case TargetOpcode::G_ATOMICRMW_OR:
4649 case TargetOpcode::G_ATOMICRMW_XOR:
4650 case TargetOpcode::G_ATOMICRMW_MIN:
4651 case TargetOpcode::G_ATOMICRMW_MAX:
4652 case TargetOpcode::G_ATOMICRMW_UMIN:
4653 case TargetOpcode::G_ATOMICRMW_UMAX:
4654 case TargetOpcode::G_ATOMICRMW_UINC_WRAP:
4655 case TargetOpcode::G_ATOMICRMW_UDEC_WRAP:
4656 case TargetOpcode::G_ATOMICRMW_USUB_COND:
4657 case TargetOpcode::G_ATOMICRMW_USUB_SAT:
4658 case TargetOpcode::G_ATOMICRMW_FADD:
4659 case TargetOpcode::G_ATOMICRMW_FMIN:
4660 case TargetOpcode::G_ATOMICRMW_FMAX:
4661 return selectG_LOAD_STORE_ATOMICRMW(
I);
4662 case TargetOpcode::G_SELECT:
4663 return selectG_SELECT(
I);
4664 case TargetOpcode::G_TRUNC:
4665 return selectG_TRUNC(
I);
4666 case TargetOpcode::G_SEXT:
4667 case TargetOpcode::G_ZEXT:
4668 case TargetOpcode::G_ANYEXT:
4669 case TargetOpcode::G_SEXT_INREG:
4673 if (MRI->getType(
I.getOperand(1).getReg()) !=
LLT::scalar(1) &&
4676 return selectG_SZA_EXT(
I);
4677 case TargetOpcode::G_FPEXT:
4678 if (selectG_FPEXT(
I))
4681 case TargetOpcode::G_BRCOND:
4682 return selectG_BRCOND(
I);
4683 case TargetOpcode::G_GLOBAL_VALUE:
4684 return selectG_GLOBAL_VALUE(
I);
4685 case TargetOpcode::G_PTRMASK:
4686 return selectG_PTRMASK(
I);
4687 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4688 return selectG_EXTRACT_VECTOR_ELT(
I);
4689 case TargetOpcode::G_INSERT_VECTOR_ELT:
4690 return selectG_INSERT_VECTOR_ELT(
I);
4691 case TargetOpcode::G_FMA: {
4692 if (!STI.hasPkF32InvalidOpSel())
4695 Register VReg =
I.getOperand(0).getReg();
4701 if (Sel && Sel->
getOpcode() == AMDGPU::V_PK_FMA_F32 &&
4702 !TII.isLegalPkFMAF32OpSel(*Sel))
4703 TII.decomposePkFMAF32(*Sel, *MRI);
4707 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD:
4708 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16:
4709 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET:
4710 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE:
4711 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16: {
4714 assert(Intr &&
"not an image intrinsic with image pseudo");
4715 return selectImageIntrinsic(
I, Intr);
4717 case AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY:
4718 case AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY:
4719 case AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY:
4720 return selectBVHIntersectRayIntrinsic(
I);
4721 case AMDGPU::G_SBFX:
4722 case AMDGPU::G_UBFX:
4723 return selectG_SBFX_UBFX(
I);
4724 case AMDGPU::G_SI_CALL:
4725 I.setDesc(TII.get(AMDGPU::SI_CALL));
4727 case AMDGPU::G_AMDGPU_WAVE_ADDRESS:
4728 return selectWaveAddress(
I);
4729 case AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_RETURN: {
4730 I.setDesc(TII.get(AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN));
4733 case AMDGPU::G_STACKRESTORE:
4734 return selectStackRestore(
I);
4735 case TargetOpcode::G_WRITE_REGISTER:
4736 return selectWriteRegister(
I);
4738 return selectPHI(
I);
4739 case AMDGPU::G_AMDGPU_COPY_SCC_VCC:
4740 return selectCOPY_SCC_VCC(
I);
4741 case AMDGPU::G_AMDGPU_COPY_VCC_SCC:
4742 return selectCOPY_VCC_SCC(
I);
4743 case AMDGPU::G_AMDGPU_READANYLANE:
4744 return selectReadAnyLane(
I);
4745 case TargetOpcode::G_CONSTANT:
4746 case TargetOpcode::G_FCONSTANT:
4754AMDGPUInstructionSelector::selectVCSRC(
MachineOperand &Root)
const {
4761std::pair<Register, unsigned> AMDGPUInstructionSelector::selectVOP3ModsImpl(
4762 Register Src,
bool IsCanonicalizing,
bool AllowAbs,
bool OpSel)
const {
4766 if (
MI->getOpcode() == AMDGPU::G_FNEG) {
4767 Src =
MI->getOperand(1).getReg();
4770 }
else if (
MI->getOpcode() == AMDGPU::G_FSUB && IsCanonicalizing) {
4775 if (
LHS &&
LHS->isZero()) {
4777 Src =
MI->getOperand(2).getReg();
4781 if (AllowAbs &&
MI->getOpcode() == AMDGPU::G_FABS) {
4782 Src =
MI->getOperand(1).getReg();
4789 return std::pair(Src, Mods);
4792std::pair<Register, unsigned>
4793AMDGPUInstructionSelector::selectVOP3PModsF32Impl(
Register Src)
const {
4795 std::tie(Src, Mods) = selectVOP3ModsImpl(Src);
4797 return std::pair(Src, Mods);
4800Register AMDGPUInstructionSelector::copyToVGPRIfSrcFolded(
4802 bool ForceVGPR)
const {
4803 if ((Mods != 0 || ForceVGPR) &&
4804 RBI.getRegBank(Src, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID) {
4811 TII.
get(AMDGPU::COPY), VGPRSrc)
4823AMDGPUInstructionSelector::widenSrcIfVGPR16(
Register Src,
4825 if (!Subtarget->useRealTrue16Insts() || MRI->getType(Src) !=
LLT::scalar(16))
4828 const RegisterBank *SrcRB = RBI.getRegBank(Src, *MRI, TRI);
4829 if (!SrcRB || SrcRB->
getID() != AMDGPU::VGPRRegBankID)
4832 MachineIRBuilder
B(*InsertPt);
4834 Register ImpDefReg = MRI->createVirtualRegister(&AMDGPU::VGPR_16RegClass);
4835 B.buildInstr(TargetOpcode::IMPLICIT_DEF).addDef(ImpDefReg);
4837 Register DstReg = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
4838 B.buildInstr(AMDGPU::REG_SEQUENCE)
4841 .addImm(AMDGPU::lo16)
4843 .addImm(AMDGPU::hi16);
4852AMDGPUInstructionSelector::selectVSRC0(
MachineOperand &Root)
const {
4854 [=](MachineInstrBuilder &MIB) { MIB.
add(Root); }
4859AMDGPUInstructionSelector::selectVOP3Mods0(
MachineOperand &Root)
const {
4862 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
4865 [=](MachineInstrBuilder &MIB) {
4866 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4868 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
4869 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4870 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4875AMDGPUInstructionSelector::selectVOP3BMods0(
MachineOperand &Root)
const {
4878 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
4883 [=](MachineInstrBuilder &MIB) {
4884 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4886 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
4887 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4888 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4893AMDGPUInstructionSelector::selectVOP3OMods(
MachineOperand &Root)
const {
4895 [=](MachineInstrBuilder &MIB) { MIB.
add(Root); },
4896 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4897 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4902AMDGPUInstructionSelector::selectVOP3Mods(
MachineOperand &Root)
const {
4905 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
4908 [=](MachineInstrBuilder &MIB) {
4909 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4911 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4916AMDGPUInstructionSelector::selectVOP3ModsNonCanonicalizing(
4920 std::tie(Src, Mods) =
4921 selectVOP3ModsImpl(Root.
getReg(),
false);
4924 [=](MachineInstrBuilder &MIB) {
4925 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4927 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4932AMDGPUInstructionSelector::selectVOP3BMods(
MachineOperand &Root)
const {
4935 std::tie(Src, Mods) =
4936 selectVOP3ModsImpl(Root.
getReg(),
true,
4940 [=](MachineInstrBuilder &MIB) {
4941 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4943 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4948AMDGPUInstructionSelector::selectVOP3NoMods(
MachineOperand &Root)
const {
4951 if (
Def->getOpcode() == AMDGPU::G_FNEG ||
Def->getOpcode() == AMDGPU::G_FABS)
4954 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
4979 if (
MI->getOpcode() != AMDGPU::G_TRUNC)
4984 return DstSize * 2 == SrcSize;
4990 if (
MI->getOpcode() != AMDGPU::G_LSHR)
4994 std::optional<ValueAndVReg> ShiftAmt;
4995 if (
mi_match(
MI->getOperand(0).getReg(), MRI,
4998 unsigned Shift = ShiftAmt->Value.getZExtValue();
4999 return Shift * 2 == SrcSize;
5007 if (
MI->getOpcode() != AMDGPU::G_SHL)
5011 std::optional<ValueAndVReg> ShiftAmt;
5012 if (
mi_match(
MI->getOperand(0).getReg(), MRI,
5015 unsigned Shift = ShiftAmt->Value.getZExtValue();
5016 return Shift * 2 == SrcSize;
5024 if (
MI->getOpcode() != AMDGPU::G_UNMERGE_VALUES)
5026 return MI->getNumOperands() == 3 &&
MI->getOperand(0).isDef() &&
5027 MI->getOperand(1).isDef() && !
MI->getOperand(2).isDef();
5035 if (
OpTy.isScalar())
5037 if (
OpTy.isVector() &&
OpTy.getNumElements() == 2)
5197static std::optional<std::pair<Register, SrcStatus>>
5202 unsigned Opc =
MI->getOpcode();
5206 case AMDGPU::G_BITCAST:
5207 return std::optional<std::pair<Register, SrcStatus>>(
5208 {
MI->getOperand(1).getReg(), Curr.second});
5210 if (
MI->getOperand(1).getReg().isPhysical())
5211 return std::nullopt;
5212 return std::optional<std::pair<Register, SrcStatus>>(
5213 {
MI->getOperand(1).getReg(), Curr.second});
5214 case AMDGPU::G_FNEG: {
5217 return std::nullopt;
5218 return std::optional<std::pair<Register, SrcStatus>>(
5219 {
MI->getOperand(1).getReg(), Stat});
5226 switch (Curr.second) {
5229 return std::optional<std::pair<Register, SrcStatus>>(
5232 if (Curr.first ==
MI->getOperand(0).getReg())
5233 return std::optional<std::pair<Register, SrcStatus>>(
5235 return std::optional<std::pair<Register, SrcStatus>>(
5247 return std::optional<std::pair<Register, SrcStatus>>(
5251 if (Curr.first ==
MI->getOperand(0).getReg())
5252 return std::optional<std::pair<Register, SrcStatus>>(
5254 return std::optional<std::pair<Register, SrcStatus>>(
5260 return std::optional<std::pair<Register, SrcStatus>>(
5265 return std::optional<std::pair<Register, SrcStatus>>(
5270 return std::optional<std::pair<Register, SrcStatus>>(
5275 return std::optional<std::pair<Register, SrcStatus>>(
5281 return std::nullopt;
5291 bool HasNeg =
false;
5293 bool HasOpsel =
true;
5298 unsigned Opc =
MI->getOpcode();
5300 if (
Opc == TargetOpcode::G_INTRINSIC) {
5303 if (IntrinsicID == Intrinsic::amdgcn_fdot2)
5330 while (
Depth <= MaxDepth && Curr.has_value()) {
5333 Statlist.push_back(Curr.value());
5340static std::pair<Register, SrcStatus>
5347 while (
Depth <= MaxDepth && Curr.has_value()) {
5353 LastSameOrNeg = Curr.value();
5358 return LastSameOrNeg;
5365 return Width1 == Width2;
5400 return isSameBitWidth(NewReg, RootReg, MRI) && IsHalfState(LoStat) &&
5401 IsHalfState(HiStat);
5404std::pair<Register, unsigned> AMDGPUInstructionSelector::selectVOP3PModsImpl(
5410 return {RootReg, Mods};
5413 SearchOptions SO(RootReg, MRI);
5426 if (MRI.getType(RootReg).getSizeInBits() == 128) {
5428 return {Stat.first, Mods};
5433 MI->getNumOperands() != 3 || (IsDOT && Subtarget->hasDOTOpSelHazard())) {
5435 return {Stat.first, Mods};
5441 if (StatlistHi.
empty()) {
5443 return {Stat.first, Mods};
5449 if (StatlistLo.
empty()) {
5451 return {Stat.first, Mods};
5454 for (
int I = StatlistHi.
size() - 1;
I >= 0;
I--) {
5455 for (
int J = StatlistLo.
size() - 1; J >= 0; J--) {
5456 if (StatlistHi[
I].first == StatlistLo[J].first &&
5458 StatlistHi[
I].first, RootReg, TII, MRI))
5459 return {StatlistHi[
I].first,
5460 updateMods(StatlistHi[
I].second, StatlistLo[J].second, Mods)};
5466 return {Stat.first, Mods};
5476 return RB->
getID() == RBNo;
5492 if (
checkRB(RootReg, AMDGPU::SGPRRegBankID, RBI, MRI,
TRI) ||
5493 checkRB(NewReg, AMDGPU::VGPRRegBankID, RBI, MRI,
TRI))
5503 TII.get(AMDGPU::COPY), DstReg)
5511AMDGPUInstructionSelector::selectVOP3PRetHelper(
MachineOperand &Root,
5516 std::tie(
Reg, Mods) = selectVOP3PModsImpl(Root.
getReg(), MRI, IsDOT);
5521 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
5522 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5527AMDGPUInstructionSelector::selectVOP3PMods(
MachineOperand &Root)
const {
5529 return selectVOP3PRetHelper(Root);
5533AMDGPUInstructionSelector::selectVOP3PModsDOT(
MachineOperand &Root)
const {
5535 return selectVOP3PRetHelper(Root,
true);
5539AMDGPUInstructionSelector::selectVOP3PNoModsDOT(
MachineOperand &Root)
const {
5543 std::tie(Src, Mods) = selectVOP3PModsImpl(Root.
getReg(), MRI,
true );
5547 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); }}};
5551AMDGPUInstructionSelector::selectVOP3PModsF32(
MachineOperand &Root)
const {
5554 std::tie(Src, Mods) = selectVOP3PModsF32Impl(Root.
getReg());
5557 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5558 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5563AMDGPUInstructionSelector::selectVOP3PNoModsF32(
MachineOperand &Root)
const {
5566 std::tie(Src, Mods) = selectVOP3PModsF32Impl(Root.
getReg());
5570 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); }}};
5574AMDGPUInstructionSelector::selectWMMAOpSelVOP3PMods(
5577 "expected i1 value");
5583 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5591 switch (Elts.
size()) {
5593 DstRegClass = &AMDGPU::VReg_256RegClass;
5596 DstRegClass = &AMDGPU::VReg_128RegClass;
5599 DstRegClass = &AMDGPU::VReg_64RegClass;
5606 auto MIB =
B.buildInstr(AMDGPU::REG_SEQUENCE)
5608 for (
unsigned i = 0; i < Elts.
size(); ++i) {
5619 if (ModOpcode == TargetOpcode::G_FNEG) {
5623 for (
auto El : Elts) {
5629 if (Elts.size() != NegAbsElts.
size()) {
5638 assert(ModOpcode == TargetOpcode::G_FABS);
5646AMDGPUInstructionSelector::selectWMMAModsF32NegAbs(
MachineOperand &Root)
const {
5655 MachineInstr *ElF32 = MRI->getVRegDef(BV->
getSourceReg(0));
5656 unsigned ModOpcode = (ElF32->
getOpcode() == AMDGPU::G_FNEG)
5673 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5674 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5678AMDGPUInstructionSelector::selectWMMAModsF16Neg(
MachineOperand &Root)
const {
5700 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5701 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5705AMDGPUInstructionSelector::selectWMMAModsF16NegAbs(
MachineOperand &Root)
const {
5713 MachineInstr *ElV2F16 = MRI->getVRegDef(CV->
getSourceReg(0));
5715 unsigned ModOpcode = (ElV2F16->
getOpcode() == AMDGPU::G_FNEG)
5734 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5735 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5739AMDGPUInstructionSelector::selectWMMAVISrc(
MachineOperand &Root)
const {
5740 std::optional<FPValueAndVReg> FPValReg;
5742 if (TII.isInlineConstant(FPValReg->Value)) {
5743 return {{[=](MachineInstrBuilder &MIB) {
5744 MIB.
addImm(FPValReg->Value.bitcastToAPInt().getSExtValue());
5754 if (TII.isInlineConstant(ICst)) {
5764AMDGPUInstructionSelector::selectSWMMACIndex8(
MachineOperand &Root)
const {
5770 std::optional<ValueAndVReg> ShiftAmt;
5772 MRI->getType(ShiftSrc).getSizeInBits() == 32 &&
5773 ShiftAmt->Value.getZExtValue() % 8 == 0) {
5774 Key = ShiftAmt->Value.getZExtValue() / 8;
5779 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5780 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5785AMDGPUInstructionSelector::selectSWMMACIndex16(
MachineOperand &Root)
const {
5792 std::optional<ValueAndVReg> ShiftAmt;
5794 MRI->getType(ShiftSrc).getSizeInBits() == 32 &&
5795 ShiftAmt->Value.getZExtValue() == 16) {
5801 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5802 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5807AMDGPUInstructionSelector::selectSWMMACIndex32(
MachineOperand &Root)
const {
5814 S32 = matchAnyExtendFromS32(Src);
5818 if (
Def->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) {
5823 Src =
Def->getOperand(2).getReg();
5830 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5831 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5836AMDGPUInstructionSelector::selectVOP3OpSelMods(
MachineOperand &Root)
const {
5839 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
5842 if (!Subtarget->useRealTrue16Insts() &&
5843 MRI->getType(Root.
getReg()).getSizeInBits() == 16 &&
5850 [=](MachineInstrBuilder &MIB) {
5851 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
5853 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5859AMDGPUInstructionSelector::selectVINTERPMods(
MachineOperand &Root)
const {
5862 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
5868 [=](MachineInstrBuilder &MIB) {
5870 copyToVGPRIfSrcFolded(Src, Mods, Root, MIB,
true));
5872 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
5877AMDGPUInstructionSelector::selectVINTERPModsHi(
MachineOperand &Root)
const {
5880 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
5886 [=](MachineInstrBuilder &MIB) {
5888 copyToVGPRIfSrcFolded(Src, Mods, Root, MIB,
true));
5890 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
5897bool AMDGPUInstructionSelector::selectScaleOffset(
MachineOperand &Root,
5899 bool IsSigned)
const {
5900 if (!Subtarget->hasScaleOffset())
5904 MachineMemOperand *MMO = *
MI.memoperands_begin();
5916 OffsetReg =
Def->Reg;
5931 m_BinOp(IsSigned ? AMDGPU::S_MUL_I64_I32_PSEUDO : AMDGPU::S_MUL_U64,
5935 (
Mul->getOpcode() == (IsSigned ? AMDGPU::G_AMDGPU_MAD_I64_I32
5936 : AMDGPU::G_AMDGPU_MAD_U64_U32) ||
5937 (IsSigned &&
Mul->getOpcode() == AMDGPU::G_AMDGPU_MAD_U64_U32 &&
5938 VT->signBitIsZero(
Mul->getOperand(2).getReg()))) &&
5951bool AMDGPUInstructionSelector::selectSmrdOffset(
MachineOperand &Root,
5955 bool *ScaleOffset)
const {
5962 getAddrModeInfo(*
MI, *MRI, AddrInfo);
5964 if (AddrInfo.
empty())
5967 const GEPInfo &GEPI = AddrInfo[0];
5968 std::optional<int64_t> EncodedImm;
5971 *ScaleOffset =
false;
5976 if (GEPI.SgprParts.size() == 1 && GEPI.Imm != 0 && EncodedImm &&
5977 AddrInfo.
size() > 1) {
5978 const GEPInfo &GEPI2 = AddrInfo[1];
5979 if (GEPI2.SgprParts.size() == 2 && GEPI2.Imm == 0) {
5980 Register OffsetReg = GEPI2.SgprParts[1];
5983 selectScaleOffset(Root, OffsetReg,
false );
5984 OffsetReg = matchZeroExtendFromS32OrS32(OffsetReg);
5986 Base = GEPI2.SgprParts[0];
5987 *SOffset = OffsetReg;
5996 auto SKnown =
VT->getKnownBits(*SOffset);
5997 if (*
Offset + SKnown.getMinValue().getSExtValue() < 0)
6009 if (
Offset && GEPI.SgprParts.size() == 1 && EncodedImm) {
6010 Base = GEPI.SgprParts[0];
6016 if (SOffset && GEPI.SgprParts.size() == 1 &&
isUInt<32>(GEPI.Imm) &&
6022 Base = GEPI.SgprParts[0];
6023 *SOffset = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
6024 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), *SOffset)
6029 if (SOffset && GEPI.SgprParts.size() && GEPI.Imm == 0) {
6030 Register OffsetReg = GEPI.SgprParts[1];
6032 *ScaleOffset = selectScaleOffset(Root, OffsetReg,
false );
6033 OffsetReg = matchZeroExtendFromS32OrS32(OffsetReg);
6035 Base = GEPI.SgprParts[0];
6036 *SOffset = OffsetReg;
6045AMDGPUInstructionSelector::selectSmrdImm(
MachineOperand &Root)
const {
6048 if (!selectSmrdOffset(Root,
Base,
nullptr, &
Offset,
6050 return std::nullopt;
6052 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
6053 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Offset); }}};
6057AMDGPUInstructionSelector::selectSmrdImm32(
MachineOperand &Root)
const {
6059 getAddrModeInfo(*Root.
getParent(), *MRI, AddrInfo);
6061 if (AddrInfo.
empty() || AddrInfo[0].SgprParts.size() != 1)
6062 return std::nullopt;
6064 const GEPInfo &GEPInfo = AddrInfo[0];
6065 Register PtrReg = GEPInfo.SgprParts[0];
6066 std::optional<int64_t> EncodedImm =
6069 return std::nullopt;
6072 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrReg); },
6073 [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); }
6078AMDGPUInstructionSelector::selectSmrdSgpr(
MachineOperand &Root)
const {
6081 if (!selectSmrdOffset(Root,
Base, &SOffset,
nullptr,
6083 return std::nullopt;
6086 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
6087 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
6088 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }}};
6092AMDGPUInstructionSelector::selectSmrdSgprImm(
MachineOperand &Root)
const {
6096 if (!selectSmrdOffset(Root,
Base, &SOffset, &
Offset, &ScaleOffset))
6097 return std::nullopt;
6100 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
6101 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
6103 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }}};
6106std::pair<Register, int> AMDGPUInstructionSelector::selectFlatOffsetImpl(
6112 if (!STI.hasFlatInstOffsets())
6116 int64_t ConstOffset;
6118 std::tie(PtrBase, ConstOffset, IsInBounds) =
6119 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
6125 if (ConstOffset == 0 ||
6127 !isFlatScratchBaseLegal(Root.
getReg())) ||
6131 unsigned AddrSpace = (*
MI->memoperands_begin())->getAddrSpace();
6132 if (!TII.isLegalFLATOffset(ConstOffset, AddrSpace, FlatVariant))
6135 return std::pair(PtrBase, ConstOffset);
6139AMDGPUInstructionSelector::selectFlatOffset(
MachineOperand &Root)
const {
6143 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6144 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6149AMDGPUInstructionSelector::selectGlobalOffset(
MachineOperand &Root)
const {
6150 auto PtrWithOffset =
6154 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6155 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6160AMDGPUInstructionSelector::selectScratchOffset(
MachineOperand &Root)
const {
6161 auto PtrWithOffset =
6165 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6166 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6172AMDGPUInstructionSelector::selectGlobalSAddr(
MachineOperand &Root,
6174 bool NeedIOffset)
const {
6177 int64_t ConstOffset;
6178 int64_t ImmOffset = 0;
6182 std::tie(PtrBase, ConstOffset, std::ignore) =
6183 getPtrBaseWithConstantOffset(Addr, *MRI);
6185 if (ConstOffset != 0) {
6190 ImmOffset = ConstOffset;
6193 if (isSGPR(PtrBaseDef->Reg)) {
6199 int64_t SplitImmOffset = 0, RemainderOffset = ConstOffset;
6201 std::tie(SplitImmOffset, RemainderOffset) =
6206 if (Subtarget->hasSignedGVSOffset() ?
isInt<32>(RemainderOffset)
6211 MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6213 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32),
6215 .
addImm(RemainderOffset);
6219 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrBase); },
6220 [=](MachineInstrBuilder &MIB) {
6223 [=](MachineInstrBuilder &MIB) { MIB.
addImm(SplitImmOffset); },
6224 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); },
6227 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrBase); },
6228 [=](MachineInstrBuilder &MIB) {
6231 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); },
6240 unsigned NumLiterals =
6241 !TII.isInlineConstant(APInt(32,
Lo_32(ConstOffset))) +
6242 !TII.isInlineConstant(APInt(32,
Hi_32(ConstOffset)));
6243 if (STI.getConstantBusLimit(AMDGPU::V_ADD_U32_e64) > NumLiterals)
6244 return std::nullopt;
6251 if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
6256 if (isSGPR(SAddr)) {
6257 Register PtrBaseOffset = AddrDef->MI->getOperand(2).getReg();
6261 bool ScaleOffset = selectScaleOffset(Root, PtrBaseOffset,
6262 Subtarget->hasSignedGVSOffset());
6263 if (
Register VOffset = matchExtendFromS32OrS32(
6264 PtrBaseOffset, Subtarget->hasSignedGVSOffset())) {
6266 return {{[=](MachineInstrBuilder &MIB) {
6269 [=](MachineInstrBuilder &MIB) {
6272 [=](MachineInstrBuilder &MIB) {
6275 [=](MachineInstrBuilder &MIB) {
6279 return {{[=](MachineInstrBuilder &MIB) {
6282 [=](MachineInstrBuilder &MIB) {
6285 [=](MachineInstrBuilder &MIB) {
6295 if (AddrDef->MI->getOpcode() == AMDGPU::G_IMPLICIT_DEF ||
6296 AddrDef->MI->getOpcode() == AMDGPU::G_CONSTANT || !isSGPR(AddrDef->Reg))
6297 return std::nullopt;
6303 Register VOffset = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6305 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32), VOffset)
6310 [=](MachineInstrBuilder &MIB) { MIB.
addReg(AddrDef->Reg); },
6311 [=](MachineInstrBuilder &MIB) { MIB.
addReg(VOffset); },
6312 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6313 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); }
6316 [=](MachineInstrBuilder &MIB) { MIB.
addReg(AddrDef->Reg); },
6317 [=](MachineInstrBuilder &MIB) { MIB.
addReg(VOffset); },
6318 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); }
6323AMDGPUInstructionSelector::selectGlobalSAddr(
MachineOperand &Root)
const {
6324 return selectGlobalSAddr(Root, 0);
6328AMDGPUInstructionSelector::selectGlobalSAddrCPol(
MachineOperand &Root)
const {
6334 return selectGlobalSAddr(Root, PassedCPol);
6338AMDGPUInstructionSelector::selectGlobalSAddrCPolM0(
MachineOperand &Root)
const {
6344 return selectGlobalSAddr(Root, PassedCPol);
6348AMDGPUInstructionSelector::selectGlobalSAddrGLC(
MachineOperand &Root)
const {
6353AMDGPUInstructionSelector::selectGlobalSAddrNoIOffset(
6360 return selectGlobalSAddr(Root, PassedCPol,
false);
6364AMDGPUInstructionSelector::selectGlobalSAddrNoIOffsetM0(
6371 return selectGlobalSAddr(Root, PassedCPol,
false);
6375AMDGPUInstructionSelector::selectScratchSAddr(
MachineOperand &Root)
const {
6378 int64_t ConstOffset;
6379 int64_t ImmOffset = 0;
6383 std::tie(PtrBase, ConstOffset, std::ignore) =
6384 getPtrBaseWithConstantOffset(Addr, *MRI);
6386 if (ConstOffset != 0 && isFlatScratchBaseLegal(Addr) &&
6390 ImmOffset = ConstOffset;
6394 if (AddrDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX) {
6395 int FI = AddrDef->MI->getOperand(1).
getIndex();
6398 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); }
6404 if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
6405 Register LHS = AddrDef->MI->getOperand(1).getReg();
6406 Register RHS = AddrDef->MI->getOperand(2).getReg();
6410 if (LHSDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX &&
6411 isSGPR(RHSDef->Reg)) {
6412 int FI = LHSDef->MI->getOperand(1).getIndex();
6416 SAddr = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
6418 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_ADD_I32), SAddr)
6426 return std::nullopt;
6429 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SAddr); },
6430 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); }
6435bool AMDGPUInstructionSelector::checkFlatScratchSVSSwizzleBug(
6437 if (!Subtarget->hasFlatScratchSVSSwizzleBug())
6443 auto VKnown =
VT->getKnownBits(VAddr);
6446 uint64_t VMax = VKnown.getMaxValue().getZExtValue();
6448 return (VMax & 3) + (
SMax & 3) >= 4;
6452AMDGPUInstructionSelector::selectScratchSVAddr(
MachineOperand &Root)
const {
6455 int64_t ConstOffset;
6456 int64_t ImmOffset = 0;
6460 std::tie(PtrBase, ConstOffset, std::ignore) =
6461 getPtrBaseWithConstantOffset(Addr, *MRI);
6464 if (ConstOffset != 0 &&
6468 ImmOffset = ConstOffset;
6472 if (AddrDef->MI->getOpcode() != AMDGPU::G_PTR_ADD)
6473 return std::nullopt;
6475 Register RHS = AddrDef->MI->getOperand(2).getReg();
6476 if (RBI.getRegBank(
RHS, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID)
6477 return std::nullopt;
6479 Register LHS = AddrDef->MI->getOperand(1).getReg();
6482 if (OrigAddr != Addr) {
6483 if (!isFlatScratchBaseLegalSVImm(OrigAddr))
6484 return std::nullopt;
6486 if (!isFlatScratchBaseLegalSV(OrigAddr))
6487 return std::nullopt;
6490 if (checkFlatScratchSVSSwizzleBug(
RHS,
LHS, ImmOffset))
6491 return std::nullopt;
6493 unsigned CPol = selectScaleOffset(Root,
RHS,
true )
6497 if (LHSDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX) {
6498 int FI = LHSDef->MI->getOperand(1).getIndex();
6500 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
RHS); },
6502 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6503 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }
6512 return std::nullopt;
6515 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
RHS); },
6516 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
LHS); },
6517 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6518 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }
6523AMDGPUInstructionSelector::selectMUBUFScratchOffen(
MachineOperand &Root)
const {
6527 const SIMachineFunctionInfo *
Info =
MF->getInfo<SIMachineFunctionInfo>();
6532 Register HighBits = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6537 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32),
6541 return {{[=](MachineInstrBuilder &MIB) {
6544 [=](MachineInstrBuilder &MIB) {
6547 [=](MachineInstrBuilder &MIB) {
6552 [=](MachineInstrBuilder &MIB) {
6561 std::optional<int> FI;
6565 int64_t ConstOffset;
6566 std::tie(PtrBase, ConstOffset, std::ignore) =
6567 getPtrBaseWithConstantOffset(VAddr, *MRI);
6569 if (ConstOffset != 0) {
6570 if (TII.isLegalMUBUFImmOffset(ConstOffset) &&
6571 (!STI.privateMemoryResourceIsRangeChecked() ||
6572 VT->signBitIsZero(PtrBase))) {
6583 return {{[=](MachineInstrBuilder &MIB) {
6586 [=](MachineInstrBuilder &MIB) {
6592 [=](MachineInstrBuilder &MIB) {
6597 [=](MachineInstrBuilder &MIB) {
6602bool AMDGPUInstructionSelector::isDSOffsetLegal(
Register Base,
6607 if (STI.hasUsableDSOffset() || STI.unsafeDSOffsetFoldingEnabled())
6612 return VT->signBitIsZero(
Base);
6615bool AMDGPUInstructionSelector::isDSOffset2Legal(
Register Base, int64_t Offset0,
6617 unsigned Size)
const {
6618 if (Offset0 %
Size != 0 || Offset1 %
Size != 0)
6623 if (STI.hasUsableDSOffset() || STI.unsafeDSOffsetFoldingEnabled())
6628 return VT->signBitIsZero(
Base);
6633 return Addr->
getOpcode() == TargetOpcode::G_OR ||
6634 (Addr->
getOpcode() == TargetOpcode::G_PTR_ADD &&
6641bool AMDGPUInstructionSelector::isFlatScratchBaseLegal(
Register Addr)
const {
6649 if (STI.hasSignedScratchOffsets())
6655 if (AddrMI->
getOpcode() == TargetOpcode::G_PTR_ADD) {
6656 std::optional<ValueAndVReg> RhsValReg =
6662 if (RhsValReg && RhsValReg->Value.getSExtValue() < 0 &&
6663 RhsValReg->Value.getSExtValue() > -0x40000000)
6667 return VT->signBitIsZero(
LHS);
6672bool AMDGPUInstructionSelector::isFlatScratchBaseLegalSV(
Register Addr)
const {
6680 if (STI.hasSignedScratchOffsets())
6685 return VT->signBitIsZero(
RHS) &&
VT->signBitIsZero(
LHS);
6690bool AMDGPUInstructionSelector::isFlatScratchBaseLegalSVImm(
6694 if (STI.hasSignedScratchOffsets())
6699 std::optional<DefinitionAndSourceRegister> BaseDef =
6701 std::optional<ValueAndVReg> RHSOffset =
6711 (RHSOffset->Value.getSExtValue() < 0 &&
6712 RHSOffset->Value.getSExtValue() > -0x40000000)))
6715 Register LHS = BaseDef->MI->getOperand(1).getReg();
6716 Register RHS = BaseDef->MI->getOperand(2).getReg();
6717 return VT->signBitIsZero(
RHS) &&
VT->signBitIsZero(
LHS);
6720bool AMDGPUInstructionSelector::isUnneededShiftMask(
const MachineInstr &
MI,
6721 unsigned ShAmtBits)
const {
6722 assert(
MI.getOpcode() == TargetOpcode::G_AND);
6726 std::optional<ValueAndVReg>
RHS =
6731 if (
RHS->
Value.countr_one() >= ShAmtBits)
6734 const APInt &LHSKnownZeros =
VT->getKnownZeroes(
MI.getOperand(1).getReg());
6735 return (LHSKnownZeros |
RHS->
Value).countr_one() >= ShAmtBits;
6739AMDGPUInstructionSelector::selectMUBUFScratchOffset(
6742 const SIMachineFunctionInfo *
Info =
MF->getInfo<SIMachineFunctionInfo>();
6744 std::optional<DefinitionAndSourceRegister>
Def =
6746 assert(Def &&
"this shouldn't be an optional result");
6751 [=](MachineInstrBuilder &MIB) {
6754 [=](MachineInstrBuilder &MIB) {
6757 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
6768 if (!TII.isLegalMUBUFImmOffset(
Offset))
6776 [=](MachineInstrBuilder &MIB) {
6779 [=](MachineInstrBuilder &MIB) {
6787 !TII.isLegalMUBUFImmOffset(
Offset))
6791 [=](MachineInstrBuilder &MIB) {
6794 [=](MachineInstrBuilder &MIB) {
6801std::pair<Register, unsigned>
6802AMDGPUInstructionSelector::selectDS1Addr1OffsetImpl(
6804 int64_t ConstAddr = 0;
6808 std::tie(PtrBase,
Offset, std::ignore) =
6809 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
6812 if (isDSOffsetLegal(PtrBase,
Offset)) {
6814 return std::pair(PtrBase,
Offset);
6823 return std::pair(Root.
getReg(), 0);
6827AMDGPUInstructionSelector::selectDS1Addr1Offset(
MachineOperand &Root)
const {
6830 std::tie(
Reg,
Offset) = selectDS1Addr1OffsetImpl(Root);
6832 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
6838AMDGPUInstructionSelector::selectDS64Bit4ByteAligned(
MachineOperand &Root)
const {
6839 return selectDSReadWrite2(Root, 4);
6843AMDGPUInstructionSelector::selectDS128Bit8ByteAligned(
MachineOperand &Root)
const {
6844 return selectDSReadWrite2(Root, 8);
6848AMDGPUInstructionSelector::selectDSReadWrite2(
MachineOperand &Root,
6849 unsigned Size)
const {
6854 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
6856 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Offset+1); }
6860std::pair<Register, unsigned>
6861AMDGPUInstructionSelector::selectDSReadWrite2Impl(
MachineOperand &Root,
6862 unsigned Size)
const {
6863 int64_t ConstAddr = 0;
6867 std::tie(PtrBase,
Offset, std::ignore) =
6868 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
6871 int64_t OffsetValue0 =
Offset;
6873 if (isDSOffset2Legal(PtrBase, OffsetValue0, OffsetValue1,
Size)) {
6875 return std::pair(PtrBase, OffsetValue0 /
Size);
6884 return std::pair(Root.
getReg(), 0);
6892std::tuple<Register, int64_t, bool>
6893AMDGPUInstructionSelector::getPtrBaseWithConstantOffset(
6896 if (RootI->
getOpcode() != TargetOpcode::G_PTR_ADD)
6897 return {Root, 0,
false};
6900 std::optional<ValueAndVReg> MaybeOffset =
6903 return {Root, 0,
false};
6923 B.buildInstr(AMDGPU::S_MOV_B32)
6926 B.buildInstr(AMDGPU::S_MOV_B32)
6933 B.buildInstr(AMDGPU::REG_SEQUENCE)
6936 .addImm(AMDGPU::sub0)
6938 .addImm(AMDGPU::sub1);
6943 B.buildInstr(AMDGPU::S_MOV_B64)
6948 B.buildInstr(AMDGPU::REG_SEQUENCE)
6951 .addImm(AMDGPU::sub0_sub1)
6953 .addImm(AMDGPU::sub2_sub3);
6960 uint64_t DefaultFormat =
TII.getDefaultRsrcDataFormat();
6969 uint64_t DefaultFormat =
TII.getDefaultRsrcDataFormat();
6976AMDGPUInstructionSelector::MUBUFAddressData
6977AMDGPUInstructionSelector::parseMUBUFAddress(
Register Src)
const {
6978 MUBUFAddressData
Data;
6984 std::tie(PtrBase,
Offset, std::ignore) =
6985 getPtrBaseWithConstantOffset(Src, *MRI);
6991 if (MachineInstr *InputAdd
6993 Data.N2 = InputAdd->getOperand(1).getReg();
6994 Data.N3 = InputAdd->getOperand(2).getReg();
7009bool AMDGPUInstructionSelector::shouldUseAddr64(MUBUFAddressData Addr)
const {
7015 const RegisterBank *N0Bank = RBI.getRegBank(Addr.N0, *MRI, TRI);
7016 return N0Bank->
getID() == AMDGPU::VGPRRegBankID;
7022void AMDGPUInstructionSelector::splitIllegalMUBUFOffset(
7024 if (TII.isLegalMUBUFImmOffset(ImmOffset))
7028 SOffset = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7029 B.buildInstr(AMDGPU::S_MOV_B32)
7035bool AMDGPUInstructionSelector::selectMUBUFAddr64Impl(
7040 if (!STI.hasAddr64() || STI.useFlatForGlobal())
7043 MUBUFAddressData AddrData = parseMUBUFAddress(Root.
getReg());
7044 if (!shouldUseAddr64(AddrData))
7050 Offset = AddrData.Offset;
7056 if (RBI.getRegBank(N2, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
7058 if (RBI.getRegBank(N3, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
7071 }
else if (RBI.getRegBank(N0, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
7082 splitIllegalMUBUFOffset(
B, SOffset,
Offset);
7086bool AMDGPUInstructionSelector::selectMUBUFOffsetImpl(
7091 if (STI.useFlatForGlobal())
7094 MUBUFAddressData AddrData = parseMUBUFAddress(Root.
getReg());
7095 if (shouldUseAddr64(AddrData))
7101 Offset = AddrData.Offset;
7107 splitIllegalMUBUFOffset(
B, SOffset,
Offset);
7112AMDGPUInstructionSelector::selectMUBUFAddr64(
MachineOperand &Root)
const {
7118 if (!selectMUBUFAddr64Impl(Root, VAddr, RSrcReg, SOffset,
Offset))
7124 [=](MachineInstrBuilder &MIB) {
7127 [=](MachineInstrBuilder &MIB) {
7130 [=](MachineInstrBuilder &MIB) {
7133 else if (STI.hasRestrictedSOffset())
7134 MIB.
addReg(AMDGPU::SGPR_NULL);
7138 [=](MachineInstrBuilder &MIB) {
7148AMDGPUInstructionSelector::selectMUBUFOffset(
MachineOperand &Root)
const {
7153 if (!selectMUBUFOffsetImpl(Root, RSrcReg, SOffset,
Offset))
7157 [=](MachineInstrBuilder &MIB) {
7160 [=](MachineInstrBuilder &MIB) {
7163 else if (STI.hasRestrictedSOffset())
7164 MIB.
addReg(AMDGPU::SGPR_NULL);
7176AMDGPUInstructionSelector::selectBUFSOffset(
MachineOperand &Root)
const {
7181 SOffset = AMDGPU::SGPR_NULL;
7183 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); }}};
7187static std::optional<uint64_t>
7191 if (!OffsetVal || !
isInt<32>(*OffsetVal))
7192 return std::nullopt;
7193 return Lo_32(*OffsetVal);
7197AMDGPUInstructionSelector::selectSMRDBufferImm(
MachineOperand &Root)
const {
7198 std::optional<uint64_t> OffsetVal =
7203 std::optional<int64_t> EncodedImm =
7208 return {{ [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); } }};
7212AMDGPUInstructionSelector::selectSMRDBufferImm32(
MachineOperand &Root)
const {
7219 std::optional<int64_t> EncodedImm =
7224 return {{ [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); } }};
7228AMDGPUInstructionSelector::selectSMRDBufferSgprImm(
MachineOperand &Root)
const {
7236 return std::nullopt;
7238 std::optional<int64_t> EncodedOffset =
7241 return std::nullopt;
7243 assert(MRI->getType(SOffset).getSizeInBits() == 32);
7244 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
7245 [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedOffset); }}};
7248std::pair<Register, unsigned>
7249AMDGPUInstructionSelector::selectVOP3PMadMixModsImpl(
MachineOperand &Root,
7250 bool &Matched)
const {
7255 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
7265 const auto CheckAbsNeg = [&]() {
7270 std::tie(Src, ModsTmp) = selectVOP3ModsImpl(Src);
7300 if (MRI->getType(Src).isFixedVector(2, 16))
7313AMDGPUInstructionSelector::selectVOP3PMadMixModsExt(
7318 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7323 [=](MachineInstrBuilder &MIB) { MIB.
addReg(widenSrcIfVGPR16(Src, MIB)); },
7324 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
7329AMDGPUInstructionSelector::selectVOP3PMadMixMods(
MachineOperand &Root)
const {
7333 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7336 [=](MachineInstrBuilder &MIB) { MIB.
addReg(widenSrcIfVGPR16(Src, MIB)); },
7337 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
7342AMDGPUInstructionSelector::selectVOP3PMadMixModsExtNeg(
7347 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7352 [=](MachineInstrBuilder &MIB) { MIB.
addReg(widenSrcIfVGPR16(Src, MIB)); },
7353 [=](MachineInstrBuilder &MIB) {
7360AMDGPUInstructionSelector::selectVOP3PMadMixModsNeg(
7365 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7368 [=](MachineInstrBuilder &MIB) { MIB.
addReg(widenSrcIfVGPR16(Src, MIB)); },
7369 [=](MachineInstrBuilder &MIB) {
7375bool AMDGPUInstructionSelector::selectSBarrierSignalIsfirst(
7379 Register CCReg =
I.getOperand(0).getReg();
7384 BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM))
7385 .
addImm(
I.getOperand(2).getImm());
7389 I.eraseFromParent();
7390 return RBI.constrainGenericRegister(CCReg, AMDGPU::SReg_32_XM0_XEXECRegClass,
7394bool AMDGPUInstructionSelector::selectSGetBarrierState(
7398 const MachineOperand &BarOp =
I.getOperand(2);
7399 std::optional<int64_t> BarValImm =
7403 auto CopyMIB =
BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
7407 MachineInstrBuilder MIB;
7408 unsigned Opc = BarValImm ? AMDGPU::S_GET_BARRIER_STATE_IMM
7409 : AMDGPU::S_GET_BARRIER_STATE_M0;
7412 auto DstReg =
I.getOperand(0).getReg();
7414 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
7415 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
7421 I.eraseFromParent();
7426 if (HasInlineConst) {
7430 case Intrinsic::amdgcn_s_barrier_join:
7431 return AMDGPU::S_BARRIER_JOIN_IMM;
7432 case Intrinsic::amdgcn_s_wakeup_barrier:
7433 return AMDGPU::S_WAKEUP_BARRIER_IMM;
7434 case Intrinsic::amdgcn_s_get_named_barrier_state:
7435 return AMDGPU::S_GET_BARRIER_STATE_IMM;
7441 case Intrinsic::amdgcn_s_barrier_join:
7442 return AMDGPU::S_BARRIER_JOIN_M0;
7443 case Intrinsic::amdgcn_s_wakeup_barrier:
7444 return AMDGPU::S_WAKEUP_BARRIER_M0;
7445 case Intrinsic::amdgcn_s_get_named_barrier_state:
7446 return AMDGPU::S_GET_BARRIER_STATE_M0;
7451bool AMDGPUInstructionSelector::selectNamedBarrierInit(
7455 const MachineOperand &BarOp =
I.getOperand(1);
7456 const MachineOperand &CntOp =
I.getOperand(2);
7460 if (IntrID == Intrinsic::amdgcn_s_barrier_signal_var) {
7461 std::optional<int64_t> CntImm =
7463 if (CntImm && *CntImm == 0) {
7464 std::optional<int64_t> BarValImm =
7467 uint32_t BarID = *BarValImm & 0x3F;
7468 BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::S_BARRIER_SIGNAL_IMM))
7470 I.eraseFromParent();
7477 Register TmpReg1 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7486 Register TmpReg2 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7492 Register TmpReg3 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7493 constexpr unsigned ShAmt = 16;
7499 Register TmpReg4 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7509 unsigned Opc = IntrID == Intrinsic::amdgcn_s_barrier_init
7510 ? AMDGPU::S_BARRIER_INIT_M0
7511 : AMDGPU::S_BARRIER_SIGNAL_M0;
7512 MachineInstrBuilder MIB;
7515 I.eraseFromParent();
7519bool AMDGPUInstructionSelector::selectNamedBarrierInst(
7523 MachineOperand BarOp = IntrID == Intrinsic::amdgcn_s_get_named_barrier_state
7526 std::optional<int64_t> BarValImm =
7531 Register TmpReg1 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7537 auto CopyMIB =
BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
7542 MachineInstrBuilder MIB;
7546 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state) {
7547 auto DstReg =
I.getOperand(0).getReg();
7549 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
7550 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
7556 uint32_t BarId = *BarValImm & 0x3F;
7560 I.eraseFromParent();
7567 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
7568 "Expected G_CONSTANT");
7569 MIB.
addImm(-
MI.getOperand(1).getCImm()->getSExtValue());
7575 const MachineOperand &
Op =
MI.getOperand(1);
7576 assert(
MI.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1);
7577 MIB.
addImm(
Op.getFPImm()->getValueAPF().bitcastToAPInt().getZExtValue());
7580void AMDGPUInstructionSelector::renderCountTrailingOnesImm(
7582 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
7583 "Expected G_CONSTANT");
7584 MIB.
addImm(
MI.getOperand(1).getCImm()->getValue().countTrailingOnes());
7592 const MachineOperand &
Op =
MI.getOperand(OpIdx);
7603 MIB.
addImm(
MI.getOperand(OpIdx).getImm() != 0);
7609 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7613void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_0_0(
7615 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7620void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_0_1(
7622 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7623 MIB.
addImm((
MI.getOperand(OpIdx).getImm() & 0x1)
7628void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_1_0(
7630 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7635void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_1_1(
7637 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7638 MIB.
addImm((
MI.getOperand(OpIdx).getImm() & 0x2)
7643void AMDGPUInstructionSelector::renderDstSelToOpSelXForm(
7645 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7650void AMDGPUInstructionSelector::renderSrcSelToOpSelXForm(
7652 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7657void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_2_0(
7659 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7664void AMDGPUInstructionSelector::renderDstSelToOpSel3XFormXForm(
7666 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7667 MIB.
addImm((
MI.getOperand(OpIdx).getImm() & 0x2)
7675 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7676 MIB.
addImm(
MI.getOperand(OpIdx).getImm() &
7684 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7685 const bool Swizzle =
MI.getOperand(OpIdx).getImm() &
7691void AMDGPUInstructionSelector::renderExtractCpolSetGLC(
7693 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7694 const uint32_t Cpol =
MI.getOperand(OpIdx).getImm() &
7703 const APFloat &APF =
MI.getOperand(1).getFPImm()->getValueAPF();
7705 assert(ExpVal != INT_MIN);
7716 MIB.
addImm((
MI.getOperand(OpIdx).getImm() + 3) % 4);
7723 if (
MI.getOperand(OpIdx).getImm())
7725 MIB.
addImm((int64_t)Mods);
7732 if (
MI.getOperand(OpIdx).getImm())
7734 MIB.
addImm((int64_t)Mods);
7740 unsigned Val =
MI.getOperand(OpIdx).getImm();
7748 MIB.
addImm((int64_t)Mods);
7754 uint32_t
V =
MI.getOperand(2).getImm();
7757 if (!Subtarget->hasSafeCUPrefetch())
7763void AMDGPUInstructionSelector::renderScaledMAIIntrinsicOperand(
7765 unsigned Val =
MI.getOperand(OpIdx).getImm();
7774bool AMDGPUInstructionSelector::isInlineImmediate(
const APInt &
Imm)
const {
7775 return TII.isInlineConstant(
Imm);
7778bool AMDGPUInstructionSelector::isInlineImmediate(
const APFloat &
Imm)
const {
7779 return TII.isInlineConstant(
Imm);
MachineInstrBuilder MachineInstrBuilder & DefMI
static unsigned getIntrinsicID(const SDNode *N)
#define GET_GLOBALISEL_PREDICATES_INIT
#define GET_GLOBALISEL_TEMPORARIES_INIT
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
static bool isShlHalf(const MachineInstr *MI, const MachineRegisterInfo &MRI)
Test if the MI is shift left with half bits, such as reg0:2n =G_SHL reg1:2n, CONST(n)
static bool isNoUnsignedWrap(MachineInstr *Addr)
static Register buildOffsetSrc(MachineIRBuilder &B, MachineRegisterInfo &MRI, const SIInstrInfo &TII, Register BasePtr)
unsigned getNamedBarrierOp(bool HasInlineConst, Intrinsic::ID IntrID)
static Register getLegalRegBank(Register NewReg, Register RootReg, MachineInstr &Use, const AMDGPURegisterBankInfo &RBI, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const SIInstrInfo &TII)
static bool checkRB(Register Reg, unsigned int RBNo, const AMDGPURegisterBankInfo &RBI, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI)
static unsigned updateMods(SrcStatus HiStat, SrcStatus LoStat, unsigned Mods)
static bool isTruncHalf(const MachineInstr *MI, const MachineRegisterInfo &MRI)
Test if the MI is truncating to half, such as reg0:n = G_TRUNC reg1:2n
static Register getWaveAddress(const MachineInstr *Def)
static bool isExtractHiElt(MachineRegisterInfo &MRI, Register In, Register &Out)
static bool shouldUseAndMask(unsigned Size, unsigned &Mask)
static std::pair< unsigned, uint8_t > BitOp3_Op(Register R, SmallVectorImpl< Register > &Src, const MachineRegisterInfo &MRI)
static TypeClass isVectorOfTwoOrScalar(Register Reg, const MachineRegisterInfo &MRI)
static bool isLaneMaskFromSameBlock(Register Reg, MachineRegisterInfo &MRI, MachineBasicBlock *MBB)
static bool isExtractLoElt(MachineRegisterInfo &MRI, Register In, Register &Out)
static bool parseTexFail(uint64_t TexFailCtrl, bool &TFE, bool &LWE, bool &IsTexFail)
static void addZeroImm(MachineInstrBuilder &MIB)
static unsigned gwsIntrinToOpcode(unsigned IntrID)
static bool isConstant(const MachineInstr &MI)
static bool isSameBitWidth(Register Reg1, Register Reg2, const MachineRegisterInfo &MRI)
static Register buildRegSequence(SmallVectorImpl< Register > &Elts, MachineInstr *InsertPt, MachineRegisterInfo &MRI)
static Register buildRSRC(MachineIRBuilder &B, MachineRegisterInfo &MRI, uint32_t FormatLo, uint32_t FormatHi, Register BasePtr)
Return a resource descriptor for use with an arbitrary 64-bit pointer.
static bool isAsyncLDSDMA(Intrinsic::ID Intr)
static std::pair< Register, unsigned > computeIndirectRegIndex(MachineRegisterInfo &MRI, const SIRegisterInfo &TRI, const TargetRegisterClass *SuperRC, Register IdxReg, unsigned EltSize, GISelValueTracking &ValueTracking)
Return the register to use for the index value, and the subregister to use for the indirectly accesse...
static unsigned getLogicalBitOpcode(unsigned Opc, bool Is64)
static std::pair< Register, SrcStatus > getLastSameOrNeg(Register Reg, const MachineRegisterInfo &MRI, SearchOptions SO, int MaxDepth=3)
static Register stripCopy(Register Reg, MachineRegisterInfo &MRI)
static std::optional< std::pair< Register, SrcStatus > > calcNextStatus(std::pair< Register, SrcStatus > Curr, const MachineRegisterInfo &MRI)
static Register stripBitCast(Register Reg, MachineRegisterInfo &MRI)
static std::optional< uint64_t > getConstantZext32Val(Register Reg, const MachineRegisterInfo &MRI)
Get an immediate that must be 32-bits, and treated as zero extended.
static bool isValidToPack(SrcStatus HiStat, SrcStatus LoStat, Register NewReg, Register RootReg, const SIInstrInfo &TII, const MachineRegisterInfo &MRI)
static int getV_CMPOpcode(CmpInst::Predicate P, unsigned Size, const GCNSubtarget &ST)
static SmallVector< std::pair< Register, SrcStatus > > getSrcStats(Register Reg, const MachineRegisterInfo &MRI, SearchOptions SO, int MaxDepth=3)
static bool isUnmergeHalf(const MachineInstr *MI, const MachineRegisterInfo &MRI)
Test function, if the MI is reg0:n, reg1:n = G_UNMERGE_VALUES reg2:2n
static SrcStatus getNegStatus(Register Reg, SrcStatus S, const MachineRegisterInfo &MRI)
static bool isVCmpResult(Register Reg, MachineRegisterInfo &MRI)
static Register buildAddr64RSrc(MachineIRBuilder &B, MachineRegisterInfo &MRI, const SIInstrInfo &TII, Register BasePtr)
static bool isLshrHalf(const MachineInstr *MI, const MachineRegisterInfo &MRI)
Test if the MI is logic shift right with half bits, such as reg0:2n =G_LSHR reg1:2n,...
static void selectWMMAModsNegAbs(unsigned ModOpcode, unsigned &Mods, SmallVectorImpl< Register > &Elts, Register &Src, MachineInstr *InsertPt, MachineRegisterInfo &MRI)
This file declares the targeting of the InstructionSelector class for AMDGPU.
AMDGPU Register Bank Select
This file declares the targeting of the RegisterBankInfo class for AMDGPU.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool isAllZeros(StringRef Arr)
Return true if the array is empty or all zeros.
Provides analysis for querying information about KnownBits during GISel passes.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static std::vector< std::pair< int, unsigned > > Swizzle(std::vector< std::pair< int, unsigned > > Src, R600InstrInfo::BankSwizzle Swz)
This is used to control valid status that current MI supports.
bool checkOptions(SrcStatus Stat) const
SearchOptions(Register Reg, const MachineRegisterInfo &MRI)
AMDGPUInstructionSelector(const GCNSubtarget &STI, const AMDGPURegisterBankInfo &RBI)
static const char * getName()
bool select(MachineInstr &I) override
Select the (possibly generic) instruction I to only use target-specific opcodes.
void setupMF(MachineFunction &MF, GISelValueTracking *VT, CodeGenCoverage *CoverageInfo, ProfileSummaryInfo *PSI, BlockFrequencyInfo *BFI) override
Setup per-MF executor state.
uint32_t getLDSSize() const
LLVM_READONLY int getExactLog2Abs() const
Class for arbitrary precision integers.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
int64_t getSExtValue() const
Get sign extended value.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ FCMP_TRUE
1 1 1 1 Always true (always folded)
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ ICMP_ULT
unsigned less than
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ ICMP_ULE
unsigned less or equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ FCMP_FALSE
0 0 0 0 Always false (always folded)
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
DILocation * get() const
Get the underlying DILocation.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
void checkSubtargetFeatures(const Function &F) const
Diagnose inconsistent subtarget features before attempting to codegen function F.
std::optional< SmallVector< std::function< void(MachineInstrBuilder &)>, 4 > > ComplexRendererFns
virtual void setupMF(MachineFunction &mf, GISelValueTracking *vt, CodeGenCoverage *covinfo=nullptr, ProfileSummaryInfo *psi=nullptr, BlockFrequencyInfo *bfi=nullptr)
Setup per-MF executor state.
CodeGenCoverage * CoverageInfo
Register getSourceReg(unsigned I) const
Returns the I'th source register.
unsigned getNumSources() const
Returns the number of source registers.
Represents a G_UNMERGE_VALUES.
unsigned getNumDefs() const
Returns the number of def registers.
Register getSourceReg() const
Get the unmerge source register.
constexpr bool isScalar() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
constexpr bool isVector() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr unsigned getAddressSpace() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
static LLT integer(unsigned SizeInBits)
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
TypeSize getValue() const
int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const
Returns the value of the specified operand constraint if it is present.
bool hasSuperClassEq(const MCRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
unsigned getID() const
getID() - Return the register class ID number.
bool hasSubClassEq(const MCRegisterClass *RC) const
Returns true if RC is a sub-class of or equal to this class.
LLVM_ABI StringRef getString() const
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void setReturnAddressIsTaken(bool s)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Helper class to build MachineInstr.
const MachineInstrBuilder & setMemRefs(ArrayRef< MachineMemOperand * > MMOs) const
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 & 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
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
bool getFlag(MIFlag Flag) const
Return whether an MI flag is set.
unsigned getNumOperands() const
Retuns the total number of operands.
LLVM_ABI void tieOperands(unsigned DefIdx, unsigned UseIdx)
Add a tie between the register operands at DefIdx and UseIdx.
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
LocationSize getSize() const
Return the size in bytes of the memory reference.
unsigned getAddrSpace() const
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
const MachinePointerInfo & getPointerInfo() const
Flags getFlags() const
Return the raw flags of the source value,.
const Value * getValue() const
Return the base address of the memory access.
Align getBaseAlign() const
Return the minimum known alignment in bytes of the base address, without the offset.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
const ConstantInt * getCImm() const
void setImm(int64_t immVal)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
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.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
static MachineOperand CreateImm(int64_t Val)
bool isEarlyClobber() const
Register getReg() const
getReg - Returns the register number.
bool isInternalRead() const
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)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
const RegisterBank * getRegBankOrNull(Register Reg) const
Return the register bank of Reg, or null if Reg has not been assigned a register bank or has been ass...
LLVM_ABI Register cloneVirtualRegister(Register VReg, StringRef Name="")
Create and return a new virtual register in the function with the same attributes as the given regist...
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Analysis providing profile information.
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.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
static unsigned getDSShaderTypeValue(const MachineFunction &MF)
static unsigned getSubRegFromChannel(unsigned Channel, unsigned NumRegs=1)
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.
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
static bool isGenericOpcode(unsigned Opc)
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
A Use represents the edge between a Value definition and its users.
LLVM_ABI Value(Type *Ty, unsigned scid)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ PRIVATE_ADDRESS
Address space for private memory.
@ BUFFER_RESOURCE
Address space for 128-bit buffer resources.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
LLVM_READONLY const MIMGG16MappingInfo * getMIMGG16MappingInfo(unsigned G)
std::optional< int64_t > getSMRDEncodedLiteralOffset32(const MCSubtargetInfo &ST, int64_t ByteOffset)
bool isGFX12Plus(const MCSubtargetInfo &STI)
constexpr int64_t getNullPointerValue(unsigned AS)
Get the null pointer value for the given address space.
LLVM_ABI IsaVersion getIsaVersion(StringRef GPU)
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
LLVM_READONLY bool hasNamedOperand(uint32_t Opcode, OpName NamedIdx)
int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding, unsigned VDataDwords, unsigned VAddrDwords, bool IndexedRsrc, bool IndexedSamp)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
bool hasSMRDSignedImmOffset(const MCSubtargetInfo &ST)
LLVM_READONLY int32_t getGlobalSaddrOp(uint32_t Opcode)
bool isGFX13Plus(const MCSubtargetInfo &STI)
bool isGFX11Plus(const MCSubtargetInfo &STI)
bool isGFX10Plus(const MCSubtargetInfo &STI)
std::optional< int64_t > getSMRDEncodedOffset(const MCSubtargetInfo &ST, int64_t ByteOffset, bool IsBuffer, bool HasSOffset)
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfo(unsigned DimEnum)
unsigned getBarrierMemberCountBitMask(const IsaVersion &Version)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
Intrinsic::ID getIntrinsicID(const MachineInstr &I)
Return the intrinsic ID for opcodes with the G_AMDGPU_INTRIN_ prefix.
std::pair< Register, unsigned > getBaseWithConstantOffset(MachineRegisterInfo &MRI, Register Reg, GISelValueTracking *ValueTracking=nullptr, bool CheckNUW=false)
Returns base register and constant offset.
const ImageDimIntrinsicInfo * getImageDimIntrinsicInfo(unsigned Intr)
IndexMode
ARM Index Modes.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
operand_type_match m_Reg()
SpecificConstantMatch m_SpecificICst(const APInt &RequestedValue)
Matches a constant equal to RequestedValue.
GInstrBind< GBuildVector > m_GBuildVector(GBuildVector *&Inst)
GCstAndRegMatch m_GCst(std::optional< ValueAndVReg > &ValReg)
UnaryOp_match< SrcTy, TargetOpcode::COPY > m_Copy(SrcTy &&Src)
UnaryOp_match< SrcTy, TargetOpcode::G_ZEXT > m_GZExt(const SrcTy &Src)
BinaryOp_match< LHS, RHS, TargetOpcode::G_XOR, true > m_GXor(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_SEXT > m_GSExt(const SrcTy &Src)
UnaryOp_match< SrcTy, TargetOpcode::G_FPEXT > m_GFPExt(const SrcTy &Src)
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
ConstantMatch< APInt > m_ICst(APInt &Cst)
SpecificConstantMatch m_AllOnesInt()
BinaryOp_match< LHS, RHS, TargetOpcode::G_OR, true > m_GOr(const LHS &L, const RHS &R)
ICstOrSplatMatch< APInt > m_ICstOrSplat(APInt &Cst)
ImplicitDefMatch m_GImplicitDef()
GInstrBind< GConcatVectors > m_GConcatVectors(GConcatVectors *&Inst)
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
GInstrBind< GUnmerge > m_GUnmerge(GUnmerge *&Inst)
Instruction binders for ops with no operand-form matcher (constant-immediate or variadic-source ops).
BinaryOp_match< LHS, RHS, TargetOpcode::G_SUB > m_GSub(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_ASHR, false > m_GAShr(const LHS &L, const RHS &R)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
BinaryOp_match< LHS, RHS, TargetOpcode::G_PTR_ADD, false > m_GPtrAdd(const LHS &L, const RHS &R)
SpecificRegisterMatch m_SpecificReg(Register RequestedReg)
Matches a register only if it is equal to RequestedReg.
BinaryOp_match< LHS, RHS, TargetOpcode::G_SHL, false > m_GShl(const LHS &L, const RHS &R)
GFrameIndexMatch m_GFrameIndex(int &FI)
Or< Preds... > m_any_of(Preds &&... preds)
BinaryOp_match< LHS, RHS, TargetOpcode::G_AND, true > m_GAnd(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_BITCAST > m_GBitcast(const SrcTy &Src)
bind_ty< MachineInstr * > m_MInstr(MachineInstr *&MI)
UnaryOp_match< SrcTy, TargetOpcode::G_FNEG > m_GFNeg(const SrcTy &Src)
GFCstOrSplatGFCstMatch m_GFCstOrSplat(std::optional< FPValueAndVReg > &FPValReg)
UnaryOp_match< SrcTy, TargetOpcode::G_FABS > m_GFabs(const SrcTy &Src)
BinaryOp_match< LHS, RHS, TargetOpcode::G_LSHR, false > m_GLShr(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_ANYEXT > m_GAnyExt(const SrcTy &Src)
ShuffleVectorMatch< Src1Ty, Src2Ty > m_GShuffleVector(const Src1Ty &Src1, const Src2Ty &Src2, ArrayRef< int > &Mask)
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
BinaryOp_match< LHS, RHS, TargetOpcode::G_MUL, true > m_GMul(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_TRUNC > m_GTrunc(const SrcTy &Src)
auto m_BinOp()
Match an arbitrary binary operation and ignore it.
@ Lo16
Fixup[15:0] <- Target + Addend.
@ Hi16
Fixup[15:0] <- (Target + Addend + 0x8000) >> 16.
NodeAddr< DefNode * > Def
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI Register getFunctionLiveInPhysReg(MachineFunction &MF, const TargetInstrInfo &TII, MCRegister PhysReg, const TargetRegisterClass &RC, const DebugLoc &DL, LLT RegTy=LLT())
Return a virtual register corresponding to the incoming argument register PhysReg.
LLVM_ABI bool isBuildVectorAllZeros(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndef=false)
Return true if the specified instruction is a G_BUILD_VECTOR or G_BUILD_VECTOR_TRUNC where all of the...
LLVM_ABI Register constrainOperandRegClass(const MachineFunction &MF, const TargetRegisterInfo &TRI, MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const RegisterBankInfo &RBI, MachineInstr &InsertPt, const TargetRegisterClass &RegClass, MachineOperand &RegMO)
Constrain the Register operand OpIdx, so that it is now constrained to the TargetRegisterClass passed...
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
PointerUnion< const TargetRegisterClass *, const RegisterBank * > RegClassOrRegBank
Convenient type to represent either a register class or a register bank.
LLVM_ABI const ConstantFP * getConstantFPVRegVal(Register VReg, const MachineRegisterInfo &MRI)
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.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI void constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
@ Load
The value being inserted comes from a load (InsertElement only).
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI MachineInstr * getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, folding away any trivial copies.
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI std::optional< int64_t > getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT fits in int64_t returns it.
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.
LLVM_ABI std::optional< ValueAndVReg > getAnyConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true, bool LookThroughAnyExt=false)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT or G_FCONST...
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
@ Or
Bitwise or logical OR of integers.
@ Mul
Product of integers.
@ SMax
Signed integer max implemented in terms of select(cmp()).
@ And
Bitwise or logical AND of integers.
@ Sub
Subtraction of integers.
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
LLVM_ABI std::optional< DefinitionAndSourceRegister > getDefSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, and underlying value Register folding away any copies.
LLVM_ABI Register getSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the source register for Reg, folding away any trivial copies.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
constexpr RegState getUndefRegState(bool B)
MCRegisterClass TargetRegisterClass
unsigned AtomicNoRetBaseOpcode
static KnownBits makeConstant(const APInt &C)
Create known bits from a known constant.
static KnownBits add(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false, bool SelfAdd=false)
Compute knownbits resulting from addition of LHS and RHS.
int64_t Offset
Offset - This is an offset from the base Value*.
PointerUnion< const Value *, const PseudoSourceValue * > V
This is the IR pointer value for the access, or it is null if unknown.