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);
2899 assert(Mask.size() == 2);
2901 if (Mask[0] == 1 && Mask[1] <= 1) {
2916 if (Unmerge->getNumDefs() == 2 && Unmerge->getOperand(0).getReg() == In &&
2934bool AMDGPUInstructionSelector::selectG_FPEXT(
MachineInstr &
I)
const {
2935 if (!Subtarget->hasSALUFloatInsts())
2938 Register Dst =
I.getOperand(0).getReg();
2939 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
2940 if (DstRB->
getID() != AMDGPU::SGPRRegBankID)
2943 Register Src =
I.getOperand(1).getReg();
2949 BuildMI(*BB, &
I,
I.getDebugLoc(), TII.get(AMDGPU::S_CVT_HI_F32_F16), Dst)
2951 I.eraseFromParent();
2952 return RBI.constrainGenericRegister(Dst, AMDGPU::SReg_32RegClass, *MRI);
2959bool AMDGPUInstructionSelector::selectG_FNEG(
MachineInstr &
MI)
const {
2972 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
2973 if (DstRB->
getID() != AMDGPU::SGPRRegBankID ||
2978 MachineInstr *Fabs =
getOpcodeDef(TargetOpcode::G_FABS, Src, *MRI);
2982 if (!RBI.constrainGenericRegister(Src, AMDGPU::SReg_64RegClass, *MRI) ||
2983 !RBI.constrainGenericRegister(Dst, AMDGPU::SReg_64RegClass, *MRI))
2988 Register LoReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2989 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2990 Register ConstReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2991 Register OpReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2993 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), LoReg)
2994 .
addReg(Src, {}, AMDGPU::sub0);
2995 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), HiReg)
2996 .
addReg(Src, {}, AMDGPU::sub1);
2997 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_MOV_B32), ConstReg)
3001 unsigned Opc = Fabs ? AMDGPU::S_OR_B32 : AMDGPU::S_XOR_B32;
3006 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::REG_SEQUENCE), Dst)
3011 MI.eraseFromParent();
3016bool AMDGPUInstructionSelector::selectG_FABS(
MachineInstr &
MI)
const {
3018 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
3019 if (DstRB->
getID() != AMDGPU::SGPRRegBankID ||
3026 Register LoReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3027 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3028 Register ConstReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3029 Register OpReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3031 if (!RBI.constrainGenericRegister(Src, AMDGPU::SReg_64RegClass, *MRI) ||
3032 !RBI.constrainGenericRegister(Dst, AMDGPU::SReg_64RegClass, *MRI))
3035 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), LoReg)
3036 .
addReg(Src, {}, AMDGPU::sub0);
3037 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), HiReg)
3038 .
addReg(Src, {}, AMDGPU::sub1);
3039 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_MOV_B32), ConstReg)
3044 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_AND_B32), OpReg)
3048 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::REG_SEQUENCE), Dst)
3054 MI.eraseFromParent();
3059 return MI.getOpcode() == TargetOpcode::G_CONSTANT;
3065 unsigned OpNo =
Load.getOpcode() == AMDGPU::G_PREFETCH ? 0 : 1;
3066 const MachineInstr *PtrMI =
3067 MRI.getUniqueVRegDef(
Load.getOperand(OpNo).getReg());
3071 if (PtrMI->
getOpcode() != TargetOpcode::G_PTR_ADD)
3076 for (
unsigned i = 1; i != 3; ++i) {
3077 const MachineOperand &GEPOp = PtrMI->
getOperand(i);
3078 const MachineInstr *OpDef = MRI.getUniqueVRegDef(GEPOp.
getReg());
3083 assert(GEPInfo.Imm == 0);
3087 const RegisterBank *OpBank = RBI.getRegBank(GEPOp.
getReg(), MRI, TRI);
3088 if (OpBank->
getID() == AMDGPU::SGPRRegBankID)
3089 GEPInfo.SgprParts.push_back(GEPOp.
getReg());
3091 GEPInfo.VgprParts.push_back(GEPOp.
getReg());
3095 getAddrModeInfo(*PtrMI, MRI, AddrInfo);
3098bool AMDGPUInstructionSelector::isSGPR(
Register Reg)
const {
3099 return RBI.getRegBank(
Reg, *MRI, TRI)->getID() == AMDGPU::SGPRRegBankID;
3102bool AMDGPUInstructionSelector::isInstrUniform(
const MachineInstr &
MI)
const {
3103 if (!
MI.hasOneMemOperand())
3106 const MachineMemOperand *MMO = *
MI.memoperands_begin();
3119 if (
MI.getOpcode() == AMDGPU::G_PREFETCH)
3120 return RBI.getRegBank(
MI.getOperand(0).getReg(), *MRI, TRI)->getID() ==
3121 AMDGPU::SGPRRegBankID;
3124 return I &&
I->getMetadata(
"amdgpu.uniform");
3128 for (
const GEPInfo &GEPInfo : AddrInfo) {
3129 if (!GEPInfo.VgprParts.empty())
3135void AMDGPUInstructionSelector::initM0(
MachineInstr &
I)
const {
3136 const LLT PtrTy = MRI->getType(
I.getOperand(1).getReg());
3139 STI.ldsRequiresM0Init()) {
3143 BuildMI(*BB, &
I,
I.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), AMDGPU::M0)
3148bool AMDGPUInstructionSelector::selectG_LOAD_STORE_ATOMICRMW(
3155 if (
Reg.isPhysical())
3159 const unsigned Opcode =
MI.getOpcode();
3161 if (Opcode == AMDGPU::COPY)
3164 if (Opcode == AMDGPU::G_AND || Opcode == AMDGPU::G_OR ||
3165 Opcode == AMDGPU::G_XOR)
3170 return GI->is(Intrinsic::amdgcn_class);
3172 return Opcode == AMDGPU::G_ICMP || Opcode == AMDGPU::G_FCMP;
3175bool AMDGPUInstructionSelector::selectG_BRCOND(
MachineInstr &
I)
const {
3177 MachineOperand &CondOp =
I.getOperand(0);
3190 if (!isVCC(CondReg, *MRI)) {
3194 CondPhysReg = AMDGPU::SCC;
3195 BrOpcode = AMDGPU::S_CBRANCH_SCC1;
3196 ConstrainRC = &AMDGPU::SReg_32RegClass;
3203 const bool Is64 = STI.isWave64();
3204 const unsigned Opcode = Is64 ? AMDGPU::S_AND_B64 : AMDGPU::S_AND_B32;
3205 const Register Exec = Is64 ? AMDGPU::EXEC : AMDGPU::EXEC_LO;
3207 Register TmpReg = MRI->createVirtualRegister(TRI.getBoolRC());
3208 BuildMI(*BB, &
I,
DL, TII.get(Opcode), TmpReg)
3215 CondPhysReg = TRI.getVCC();
3216 BrOpcode = AMDGPU::S_CBRANCH_VCCNZ;
3217 ConstrainRC = TRI.getBoolRC();
3220 if (!MRI->getRegClassOrNull(CondReg))
3221 MRI->setRegClass(CondReg, ConstrainRC);
3223 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), CondPhysReg)
3226 .
addMBB(
I.getOperand(1).getMBB());
3228 I.eraseFromParent();
3232bool AMDGPUInstructionSelector::selectG_GLOBAL_VALUE(
3234 Register DstReg =
I.getOperand(0).getReg();
3235 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3236 const bool IsVGPR = DstRB->
getID() == AMDGPU::VGPRRegBankID;
3237 I.setDesc(TII.get(IsVGPR ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32));
3241 return RBI.constrainGenericRegister(
3242 DstReg, IsVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass, *MRI);
3245bool AMDGPUInstructionSelector::selectG_PTRMASK(
MachineInstr &
I)
const {
3246 Register DstReg =
I.getOperand(0).getReg();
3247 Register SrcReg =
I.getOperand(1).getReg();
3248 Register MaskReg =
I.getOperand(2).getReg();
3249 LLT Ty = MRI->getType(DstReg);
3250 LLT MaskTy = MRI->getType(MaskReg);
3254 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3255 const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
3256 const RegisterBank *MaskRB = RBI.getRegBank(MaskReg, *MRI, TRI);
3257 const bool IsVGPR = DstRB->
getID() == AMDGPU::VGPRRegBankID;
3263 APInt MaskOnes =
VT->getKnownOnes(MaskReg).zext(64);
3267 const bool CanCopyLow32 = (MaskOnes & MaskLo32) == MaskLo32;
3268 const bool CanCopyHi32 = (MaskOnes & MaskHi32) == MaskHi32;
3271 !CanCopyLow32 && !CanCopyHi32) {
3272 auto MIB =
BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_AND_B64), DstReg)
3276 I.eraseFromParent();
3281 unsigned NewOpc = IsVGPR ? AMDGPU::V_AND_B32_e64 : AMDGPU::S_AND_B32;
3283 = IsVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
3288 TRI.getRegClassForTypeOnBank(MaskTy, *MaskRB);
3290 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
3291 !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
3292 !RBI.constrainGenericRegister(MaskReg, *MaskRC, *MRI))
3297 "ptrmask should have been narrowed during legalize");
3299 auto NewOp =
BuildMI(*BB, &
I,
DL, TII.get(NewOpc), DstReg)
3305 I.eraseFromParent();
3309 Register HiReg = MRI->createVirtualRegister(&RegRC);
3310 Register LoReg = MRI->createVirtualRegister(&RegRC);
3313 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), LoReg)
3314 .
addReg(SrcReg, {}, AMDGPU::sub0);
3315 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), HiReg)
3316 .
addReg(SrcReg, {}, AMDGPU::sub1);
3325 Register MaskLo = MRI->createVirtualRegister(&RegRC);
3326 MaskedLo = MRI->createVirtualRegister(&RegRC);
3328 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), MaskLo)
3329 .
addReg(MaskReg, {}, AMDGPU::sub0);
3330 BuildMI(*BB, &
I,
DL, TII.get(NewOpc), MaskedLo)
3339 Register MaskHi = MRI->createVirtualRegister(&RegRC);
3340 MaskedHi = MRI->createVirtualRegister(&RegRC);
3342 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), MaskHi)
3343 .
addReg(MaskReg, {}, AMDGPU::sub1);
3344 BuildMI(*BB, &
I,
DL, TII.get(NewOpc), MaskedHi)
3349 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
3354 I.eraseFromParent();
3360static std::pair<Register, unsigned>
3367 std::tie(IdxBaseReg,
Offset) =
3369 if (IdxBaseReg == AMDGPU::NoRegister) {
3373 IdxBaseReg = IdxReg;
3380 if (
static_cast<unsigned>(
Offset) >= SubRegs.
size())
3381 return std::pair(IdxReg, SubRegs[0]);
3382 return std::pair(IdxBaseReg, SubRegs[
Offset]);
3385bool AMDGPUInstructionSelector::selectG_EXTRACT_VECTOR_ELT(
3391 LLT DstTy = MRI->getType(DstReg);
3392 LLT SrcTy = MRI->getType(SrcReg);
3394 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3395 const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
3396 const RegisterBank *IdxRB = RBI.getRegBank(IdxReg, *MRI, TRI);
3400 if (IdxRB->
getID() != AMDGPU::SGPRRegBankID)
3404 TRI.getRegClassForTypeOnBank(SrcTy, *SrcRB);
3406 TRI.getRegClassForTypeOnBank(DstTy, *DstRB);
3407 if (!SrcRC || !DstRC)
3409 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
3410 !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
3411 !RBI.constrainGenericRegister(IdxReg, AMDGPU::SReg_32RegClass, *MRI))
3422 if (SrcRB->
getID() == AMDGPU::SGPRRegBankID) {
3426 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3429 unsigned Opc = Is64 ? AMDGPU::S_MOVRELS_B64 : AMDGPU::S_MOVRELS_B32;
3431 .
addReg(SrcReg, {}, SubReg)
3433 MI.eraseFromParent();
3440 if (!STI.useVGPRIndexMode()) {
3441 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3443 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::V_MOVRELS_B32_e32), DstReg)
3444 .
addReg(SrcReg, {}, SubReg)
3446 MI.eraseFromParent();
3450 const MCInstrDesc &GPRIDXDesc =
3451 TII.getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*SrcRC),
true);
3457 MI.eraseFromParent();
3462bool AMDGPUInstructionSelector::selectG_INSERT_VECTOR_ELT(
3469 LLT VecTy = MRI->getType(DstReg);
3470 LLT ValTy = MRI->getType(ValReg);
3474 const RegisterBank *VecRB = RBI.getRegBank(VecReg, *MRI, TRI);
3475 const RegisterBank *ValRB = RBI.getRegBank(ValReg, *MRI, TRI);
3476 const RegisterBank *IdxRB = RBI.getRegBank(IdxReg, *MRI, TRI);
3482 if (IdxRB->
getID() != AMDGPU::SGPRRegBankID)
3486 TRI.getRegClassForTypeOnBank(VecTy, *VecRB);
3488 TRI.getRegClassForTypeOnBank(ValTy, *ValRB);
3490 if (!RBI.constrainGenericRegister(VecReg, *VecRC, *MRI) ||
3491 !RBI.constrainGenericRegister(DstReg, *VecRC, *MRI) ||
3492 !RBI.constrainGenericRegister(ValReg, *ValRC, *MRI) ||
3493 !RBI.constrainGenericRegister(IdxReg, AMDGPU::SReg_32RegClass, *MRI))
3496 if (VecRB->
getID() == AMDGPU::VGPRRegBankID && ValSize != 32)
3500 std::tie(IdxReg, SubReg) =
3503 const bool IndexMode = VecRB->
getID() == AMDGPU::VGPRRegBankID &&
3504 STI.useVGPRIndexMode();
3510 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3513 const MCInstrDesc &RegWriteOp = TII.getIndirectRegWriteMovRelPseudo(
3514 VecSize, ValSize, VecRB->
getID() == AMDGPU::SGPRRegBankID);
3519 MI.eraseFromParent();
3523 const MCInstrDesc &GPRIDXDesc =
3524 TII.getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC),
false);
3531 MI.eraseFromParent();
3537 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
3538 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
3539 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
3540 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
3541 case Intrinsic::amdgcn_load_async_to_lds:
3542 case Intrinsic::amdgcn_global_load_async_lds:
3548bool AMDGPUInstructionSelector::selectBufferLoadLds(
MachineInstr &
MI)
const {
3549 if (!Subtarget->hasVMemToLDSLoad())
3552 unsigned Size =
MI.getOperand(3).getImm();
3556 const bool HasVIndex =
MI.getNumOperands() == 9;
3560 VIndex =
MI.getOperand(4).getReg();
3564 Register VOffset =
MI.getOperand(4 + OpOffset).getReg();
3565 std::optional<ValueAndVReg> MaybeVOffset =
3567 const bool HasVOffset = !MaybeVOffset || MaybeVOffset->Value.getZExtValue();
3573 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_BOTHEN
3574 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_IDXEN
3575 : HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFEN
3576 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFSET;
3579 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_BOTHEN
3580 : AMDGPU::BUFFER_LOAD_USHORT_LDS_IDXEN
3581 : HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFEN
3582 : AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFSET;
3585 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_BOTHEN
3586 : AMDGPU::BUFFER_LOAD_DWORD_LDS_IDXEN
3587 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFEN
3588 : AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFSET;
3591 if (!Subtarget->hasLDSLoadB96_B128())
3594 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_BOTHEN
3595 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_IDXEN
3596 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFEN
3597 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFSET;
3600 if (!Subtarget->hasLDSLoadB96_B128())
3603 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_BOTHEN
3604 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_IDXEN
3605 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFEN
3606 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFSET;
3613 .
add(
MI.getOperand(2));
3617 if (HasVIndex && HasVOffset) {
3618 Register IdxReg = MRI->createVirtualRegister(TRI.getVGPR64Class());
3619 BuildMI(*
MBB, &*MIB,
DL, TII.get(AMDGPU::REG_SEQUENCE), IdxReg)
3626 }
else if (HasVIndex) {
3628 }
else if (HasVOffset) {
3632 MIB.
add(
MI.getOperand(1));
3633 MIB.
add(
MI.getOperand(5 + OpOffset));
3634 MIB.
add(
MI.getOperand(6 + OpOffset));
3636 unsigned Aux =
MI.getOperand(7 + OpOffset).getImm();
3645 MachineMemOperand *LoadMMO = *
MI.memoperands_begin();
3650 MachinePointerInfo StorePtrI = LoadPtrI;
3661 MachineMemOperand *StoreMMO =
3667 MI.eraseFromParent();
3680 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3686 return Def->getOperand(1).getReg();
3700 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3708 return Def->getOperand(1).getReg();
3711 if (ZextSrc &&
VT->signBitIsZero(ZextSrc))
3720AMDGPUInstructionSelector::matchZeroExtendFromS32OrS32(
Register Reg)
const {
3722 : matchZeroExtendFromS32(
Reg);
3728AMDGPUInstructionSelector::matchSignExtendFromS32OrS32(
Register Reg)
const {
3730 : matchSignExtendFromS32(
Reg);
3734AMDGPUInstructionSelector::matchExtendFromS32OrS32(
Register Reg,
3735 bool IsSigned)
const {
3737 return matchSignExtendFromS32OrS32(
Reg);
3739 return matchZeroExtendFromS32OrS32(
Reg);
3749 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3756 return Def->getOperand(1).getReg();
3761bool AMDGPUInstructionSelector::selectGlobalLoadLds(
MachineInstr &
MI)
const{
3762 if (!Subtarget->hasVMemToLDSLoad())
3766 unsigned Size =
MI.getOperand(3).getImm();
3773 Opc = AMDGPU::GLOBAL_LOAD_LDS_UBYTE;
3776 Opc = AMDGPU::GLOBAL_LOAD_LDS_USHORT;
3779 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORD;
3782 if (!Subtarget->hasLDSLoadB96_B128())
3784 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX3;
3787 if (!Subtarget->hasLDSLoadB96_B128())
3789 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX4;
3796 .
add(
MI.getOperand(2));
3802 if (!isSGPR(Addr)) {
3804 if (isSGPR(AddrDef->Reg)) {
3805 Addr = AddrDef->Reg;
3806 }
else if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
3809 if (isSGPR(SAddr)) {
3810 Register PtrBaseOffset = AddrDef->MI->getOperand(2).getReg();
3811 if (
Register Off = matchZeroExtendFromS32(PtrBaseOffset)) {
3822 VOffset = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
3834 MIB.
add(
MI.getOperand(4));
3836 unsigned Aux =
MI.getOperand(5).getImm();
3840 MachineMemOperand *LoadMMO = *
MI.memoperands_begin();
3842 LoadPtrI.
Offset =
MI.getOperand(4).getImm();
3843 MachinePointerInfo StorePtrI = LoadPtrI;
3852 MachineMemOperand *StoreMMO =
3854 sizeof(int32_t),
Align(4));
3858 MI.eraseFromParent();
3863bool AMDGPUInstructionSelector::selectTensorLoadStore(
MachineInstr &
MI,
3865 bool IsLoad = IID == Intrinsic::amdgcn_tensor_load_to_lds;
3867 IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d4 : AMDGPU::TENSOR_STORE_FROM_LDS_d4;
3871 const auto isAllZeros = [&](MachineOperand &Opnd) {
3872 const MachineInstr *
DefMI = MRI->getVRegDef(Opnd.getReg());
3881 Opc = IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d2
3882 : AMDGPU::TENSOR_STORE_FROM_LDS_d2;
3889 .
add(
MI.getOperand(1))
3890 .
add(
MI.getOperand(2));
3892 if (NumGroups >= 4) {
3893 MIB.
add(
MI.getOperand(3))
3894 .
add(
MI.getOperand(4));
3898 .
add(
MI.getOperand(6));
3900 MI.eraseFromParent();
3904bool AMDGPUInstructionSelector::selectBVHIntersectRayIntrinsic(
3906 unsigned OpcodeOpIdx =
3907 MI.getOpcode() == AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY ? 1 : 3;
3908 MI.setDesc(TII.get(
MI.getOperand(OpcodeOpIdx).getImm()));
3909 MI.removeOperand(OpcodeOpIdx);
3910 MI.addImplicitDefUseOperands(*
MI.getMF());
3917bool AMDGPUInstructionSelector::selectSMFMACIntrin(
MachineInstr &
MI)
const {
3920 case Intrinsic::amdgcn_smfmac_f32_16x16x32_f16:
3921 Opc = AMDGPU::V_SMFMAC_F32_16X16X32_F16_e64;
3923 case Intrinsic::amdgcn_smfmac_f32_32x32x16_f16:
3924 Opc = AMDGPU::V_SMFMAC_F32_32X32X16_F16_e64;
3926 case Intrinsic::amdgcn_smfmac_f32_16x16x32_bf16:
3927 Opc = AMDGPU::V_SMFMAC_F32_16X16X32_BF16_e64;
3929 case Intrinsic::amdgcn_smfmac_f32_32x32x16_bf16:
3930 Opc = AMDGPU::V_SMFMAC_F32_32X32X16_BF16_e64;
3932 case Intrinsic::amdgcn_smfmac_i32_16x16x64_i8:
3933 Opc = AMDGPU::V_SMFMAC_I32_16X16X64_I8_e64;
3935 case Intrinsic::amdgcn_smfmac_i32_32x32x32_i8:
3936 Opc = AMDGPU::V_SMFMAC_I32_32X32X32_I8_e64;
3938 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_bf8:
3939 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF8_BF8_e64;
3941 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_fp8:
3942 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF8_FP8_e64;
3944 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_bf8:
3945 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_FP8_BF8_e64;
3947 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_fp8:
3948 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_FP8_FP8_e64;
3950 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_bf8:
3951 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF8_BF8_e64;
3953 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_fp8:
3954 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF8_FP8_e64;
3956 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_bf8:
3957 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_FP8_BF8_e64;
3959 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_fp8:
3960 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_FP8_FP8_e64;
3962 case Intrinsic::amdgcn_smfmac_f32_16x16x64_f16:
3963 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_F16_e64;
3965 case Intrinsic::amdgcn_smfmac_f32_32x32x32_f16:
3966 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_F16_e64;
3968 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf16:
3969 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF16_e64;
3971 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf16:
3972 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF16_e64;
3974 case Intrinsic::amdgcn_smfmac_i32_16x16x128_i8:
3975 Opc = AMDGPU::V_SMFMAC_I32_16X16X128_I8_e64;
3977 case Intrinsic::amdgcn_smfmac_i32_32x32x64_i8:
3978 Opc = AMDGPU::V_SMFMAC_I32_32X32X64_I8_e64;
3980 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_bf8:
3981 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_BF8_BF8_e64;
3983 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_fp8:
3984 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_BF8_FP8_e64;
3986 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_bf8:
3987 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_FP8_BF8_e64;
3989 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_fp8:
3990 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_FP8_FP8_e64;
3992 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_bf8:
3993 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_BF8_BF8_e64;
3995 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_fp8:
3996 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_BF8_FP8_e64;
3998 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_bf8:
3999 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_FP8_BF8_e64;
4001 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_fp8:
4002 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_FP8_FP8_e64;
4008 auto VDst_In =
MI.getOperand(4);
4010 MI.setDesc(TII.get(
Opc));
4011 MI.removeOperand(4);
4012 MI.removeOperand(1);
4013 MI.addOperand(VDst_In);
4014 MI.addImplicitDefUseOperands(*
MI.getMF());
4015 const MCInstrDesc &MCID =
MI.getDesc();
4017 MI.getOperand(0).setIsEarlyClobber(
true);
4022bool AMDGPUInstructionSelector::selectPermlaneSwapIntrin(
4024 if (IntrID == Intrinsic::amdgcn_permlane16_swap &&
4025 !Subtarget->hasPermlane16Swap())
4027 if (IntrID == Intrinsic::amdgcn_permlane32_swap &&
4028 !Subtarget->hasPermlane32Swap())
4031 unsigned Opcode = IntrID == Intrinsic::amdgcn_permlane16_swap
4032 ? AMDGPU::V_PERMLANE16_SWAP_B32_e64
4033 : AMDGPU::V_PERMLANE32_SWAP_B32_e64;
4035 MI.removeOperand(2);
4036 MI.setDesc(TII.get(Opcode));
4039 MachineOperand &FI =
MI.getOperand(4);
4046bool AMDGPUInstructionSelector::selectWaveAddress(
MachineInstr &
MI)
const {
4049 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4050 const bool IsVALU = DstRB->
getID() == AMDGPU::VGPRRegBankID;
4055 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHRREV_B32_e64), DstReg)
4056 .
addImm(Subtarget->getWavefrontSizeLog2())
4061 .
addImm(Subtarget->getWavefrontSizeLog2())
4066 IsVALU ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
4067 if (!RBI.constrainGenericRegister(DstReg, RC, *MRI))
4070 MI.eraseFromParent();
4074bool AMDGPUInstructionSelector::selectWaveShuffleIntrin(
4084 const LLT DstTy = MRI->getType(DstReg);
4086 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4088 TRI.getRegClassForSizeOnBank(DstSize, *DstRB);
4093 if (!Subtarget->supportsBPermute())
4097 if (Subtarget->supportsWaveWideBPermute()) {
4098 Register ShiftIdxReg = MRI->createVirtualRegister(DstRC);
4099 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), ShiftIdxReg)
4109 assert(Subtarget->isWave64());
4113 MRI->createVirtualRegister(TRI.getRegClass(AMDGPU::SReg_32RegClassID));
4114 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefValReg);
4116 Register UndefExecReg = MRI->createVirtualRegister(
4117 TRI.getRegClass(AMDGPU::SReg_64_XEXECRegClassID));
4118 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefExecReg);
4120 Register PoisonValReg = MRI->createVirtualRegister(DstRC);
4121 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_SET_INACTIVE_B32), PoisonValReg)
4129 Register ShiftIdxReg = MRI->createVirtualRegister(DstRC);
4130 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), ShiftIdxReg)
4134 Register PoisonIdxReg = MRI->createVirtualRegister(DstRC);
4135 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_SET_INACTIVE_B32), PoisonIdxReg)
4142 Register PoisonUnshiftedIdxReg = MRI->createVirtualRegister(DstRC);
4144 PoisonUnshiftedIdxReg)
4152 Register SameSidePermReg = MRI->createVirtualRegister(DstRC);
4153 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::DS_BPERMUTE_B32), SameSidePermReg)
4158 Register SwappedValReg = MRI->createVirtualRegister(DstRC);
4159 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_PERMLANE64_B32), SwappedValReg)
4162 Register OppSidePermReg = MRI->createVirtualRegister(DstRC);
4163 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::DS_BPERMUTE_B32), OppSidePermReg)
4168 Register WWMSwapPermReg = MRI->createVirtualRegister(DstRC);
4169 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::STRICT_WWM), WWMSwapPermReg)
4176 Register ThreadIDReg = MRI->createVirtualRegister(DstRC);
4177 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_MBCNT_LO_U32_B32_e64), ThreadIDReg)
4181 Register XORReg = MRI->createVirtualRegister(DstRC);
4184 .
addReg(PoisonUnshiftedIdxReg);
4186 Register ANDReg = MRI->createVirtualRegister(DstRC);
4191 Register CompareReg = MRI->createVirtualRegister(
4192 TRI.getRegClass(AMDGPU::SReg_64_XEXECRegClassID));
4193 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_CMP_EQ_U32_e64), CompareReg)
4198 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
4206 MI.eraseFromParent();
4215 unsigned NumOpcodes = 0;
4228 const uint8_t SrcBits[3] = { 0xf0, 0xcc, 0xaa };
4239 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4253 if (Src.size() == 3) {
4260 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4261 if (Src[
I] ==
LHS) {
4271 Bits = SrcBits[Src.size()];
4277 switch (
MI->getOpcode()) {
4278 case TargetOpcode::G_AND:
4279 case TargetOpcode::G_OR:
4280 case TargetOpcode::G_XOR: {
4285 if (!getOperandBits(
LHS, LHSBits) ||
4286 !getOperandBits(
RHS, RHSBits)) {
4287 Src = std::move(Backup);
4288 return std::make_pair(0, 0);
4309 uint8_t LHSBitsOrig = LHSBits;
4310 uint8_t RHSBitsOrig = RHSBits;
4314 NumOpcodes += LHSOp.first;
4315 LHSBits = LHSOp.second;
4322 NumOpcodes += RHSOp.first;
4323 RHSBits = RHSOp.second;
4327 auto dependsOnSlot = [](
uint8_t TT,
int Slot) ->
bool {
4328 if (Slot < 0 || Slot > 2)
4330 const uint8_t Masks[3] = {0x0f, 0x33, 0x55};
4331 const int Shifts[3] = {4, 2, 1};
4332 return ((TT ^ (TT >> Shifts[Slot])) & Masks[Slot]) != 0;
4338 const uint8_t SrcBitsConst[3] = {0xf0, 0xcc, 0xaa};
4345 for (
int I = 0;
I < (int)S.size();
I++) {
4346 if (Bits == SrcBitsConst[
I] && S[
I] ==
Op)
4348 if (IsNegationOp && Bits == (
uint8_t)~SrcBitsConst[
I] &&
4349 S[
I] == NegatedInner)
4360 for (
int I = 0;
I < (int)SrcAfterLHS.
size() &&
I < 3;
I++) {
4361 if (
I < (
int)Src.size() && Src[
I] != SrcAfterLHS[
I] &&
4362 dependsOnSlot(LHSBits,
I)) {
4371 if (!Stale && !RHSOp.first) {
4372 int Slot = findSlot(RHSBitsOrig,
RHS, SrcBeforeRecurse);
4374 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4380 if (!Stale && !LHSOp.first) {
4381 int Slot = findSlot(LHSBitsOrig,
LHS, SrcBeforeRecurse);
4383 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4388 Src = std::move(SrcBeforeRecurse);
4389 LHSBits = LHSBitsOrig;
4390 RHSBits = RHSBitsOrig;
4396 return std::make_pair(0, 0);
4400 switch (
MI->getOpcode()) {
4401 case TargetOpcode::G_AND:
4402 TTbl = LHSBits & RHSBits;
4404 case TargetOpcode::G_OR:
4405 TTbl = LHSBits | RHSBits;
4407 case TargetOpcode::G_XOR:
4408 TTbl = LHSBits ^ RHSBits;
4414 return std::make_pair(NumOpcodes + 1, TTbl);
4417bool AMDGPUInstructionSelector::selectBITOP3(
MachineInstr &
MI)
const {
4418 if (!Subtarget->hasBitOp3Insts())
4422 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4423 const bool IsVALU = DstRB->
getID() == AMDGPU::VGPRRegBankID;
4429 unsigned NumOpcodes;
4431 std::tie(NumOpcodes, TTbl) =
BitOp3_Op(DstReg, Src, *MRI);
4435 if (NumOpcodes < 2 || Src.empty())
4440 unsigned Size = MRI->getType(DstReg).getSizeInBits();
4441 assert((
Size == 16 ||
Size == 32) &&
"unexpected VALU logic op size");
4442 const bool IsB32 =
Size == 32;
4443 if (NumOpcodes == 2 && IsB32) {
4451 }
else if (NumOpcodes < 4) {
4458 unsigned Opc = IsB32 ? AMDGPU::V_BITOP3_B32_e64 : AMDGPU::V_BITOP3_B16_e64;
4459 if (!IsB32 && STI.hasTrue16BitInsts())
4460 Opc = STI.useRealTrue16Insts() ? AMDGPU::V_BITOP3_B16_gfx1250_t16_e64
4461 : AMDGPU::V_BITOP3_B16_gfx1250_fake16_e64;
4462 unsigned CBL = STI.getConstantBusLimit(
Opc);
4466 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4467 const RegisterBank *RB = RBI.getRegBank(Src[
I], *MRI, TRI);
4468 if (RB->
getID() != AMDGPU::SGPRRegBankID)
4474 Register NewReg = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
4485 while (Src.size() < 3)
4486 Src.push_back(Src[0]);
4503 MI.eraseFromParent();
4508bool AMDGPUInstructionSelector::selectWriteRegister(
MachineInstr &
MI)
const {
4509 const MDString *RegStr =
4512 LLT Ty = MRI->getType(SrcReg);
4514 Register PhysReg = Subtarget->getTargetLowering()->getRegisterByName(
4519 "invalid register \"" + Twine(RegStr->
getString()) +
4520 "\" for llvm.write_register",
4521 Fn,
MI.getDebugLoc()));
4522 MI.eraseFromParent();
4526 if (!RBI.constrainGenericRegister(
4527 SrcReg, *TRI.getSGPRClassForBitWidth(Ty.
getSizeInBits()), *MRI))
4530 BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(), TII.get(AMDGPU::COPY), PhysReg)
4532 MI.eraseFromParent();
4536bool AMDGPUInstructionSelector::selectStackRestore(
MachineInstr &
MI)
const {
4538 if (!RBI.constrainGenericRegister(SrcReg, AMDGPU::SReg_32RegClass, *MRI))
4541 MachineInstr *
DefMI = MRI->getVRegDef(SrcReg);
4543 Subtarget->getTargetLowering()->getStackPointerRegisterToSaveRestore();
4549 WaveAddr = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
4552 .
addImm(Subtarget->getWavefrontSizeLog2())
4559 MI.eraseFromParent();
4565 if (!
I.isPreISelOpcode()) {
4567 return selectCOPY(
I);
4571 switch (
I.getOpcode()) {
4572 case TargetOpcode::G_AND:
4573 case TargetOpcode::G_OR:
4574 case TargetOpcode::G_XOR:
4575 if (selectBITOP3(
I))
4579 return selectG_AND_OR_XOR(
I);
4580 case TargetOpcode::G_ADD:
4581 case TargetOpcode::G_SUB:
4582 case TargetOpcode::G_PTR_ADD:
4585 return selectG_ADD_SUB(
I);
4586 case TargetOpcode::G_UADDO:
4587 case TargetOpcode::G_USUBO:
4588 case TargetOpcode::G_UADDE:
4589 case TargetOpcode::G_USUBE:
4590 return selectG_UADDO_USUBO_UADDE_USUBE(
I);
4591 case AMDGPU::G_AMDGPU_MAD_U64_U32:
4592 case AMDGPU::G_AMDGPU_MAD_I64_I32:
4593 return selectG_AMDGPU_MAD_64_32(
I);
4594 case TargetOpcode::G_INTTOPTR:
4595 case TargetOpcode::G_BITCAST:
4596 case TargetOpcode::G_PTRTOINT:
4597 case TargetOpcode::G_FREEZE:
4598 return selectCOPY(
I);
4599 case TargetOpcode::G_FNEG:
4602 return selectG_FNEG(
I);
4603 case TargetOpcode::G_FABS:
4606 return selectG_FABS(
I);
4607 case TargetOpcode::G_EXTRACT:
4608 return selectG_EXTRACT(
I);
4609 case TargetOpcode::G_MERGE_VALUES:
4610 case TargetOpcode::G_CONCAT_VECTORS:
4611 return selectG_MERGE_VALUES(
I);
4612 case TargetOpcode::G_UNMERGE_VALUES:
4613 return selectG_UNMERGE_VALUES(
I);
4614 case TargetOpcode::G_BUILD_VECTOR:
4615 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
4616 return selectG_BUILD_VECTOR(
I);
4617 case TargetOpcode::G_IMPLICIT_DEF:
4618 return selectG_IMPLICIT_DEF(
I);
4619 case TargetOpcode::G_INSERT:
4620 return selectG_INSERT(
I);
4621 case TargetOpcode::G_INTRINSIC:
4622 case TargetOpcode::G_INTRINSIC_CONVERGENT:
4623 return selectG_INTRINSIC(
I);
4624 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
4625 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
4626 return selectG_INTRINSIC_W_SIDE_EFFECTS(
I);
4627 case TargetOpcode::G_ICMP:
4628 case TargetOpcode::G_FCMP:
4629 if (selectG_ICMP_or_FCMP(
I))
4632 case TargetOpcode::G_LOAD:
4633 case TargetOpcode::G_ZEXTLOAD:
4634 case TargetOpcode::G_SEXTLOAD:
4635 case TargetOpcode::G_STORE:
4636 case TargetOpcode::G_ATOMIC_CMPXCHG:
4637 case TargetOpcode::G_ATOMICRMW_XCHG:
4638 case TargetOpcode::G_ATOMICRMW_ADD:
4639 case TargetOpcode::G_ATOMICRMW_SUB:
4640 case TargetOpcode::G_ATOMICRMW_AND:
4641 case TargetOpcode::G_ATOMICRMW_OR:
4642 case TargetOpcode::G_ATOMICRMW_XOR:
4643 case TargetOpcode::G_ATOMICRMW_MIN:
4644 case TargetOpcode::G_ATOMICRMW_MAX:
4645 case TargetOpcode::G_ATOMICRMW_UMIN:
4646 case TargetOpcode::G_ATOMICRMW_UMAX:
4647 case TargetOpcode::G_ATOMICRMW_UINC_WRAP:
4648 case TargetOpcode::G_ATOMICRMW_UDEC_WRAP:
4649 case TargetOpcode::G_ATOMICRMW_USUB_COND:
4650 case TargetOpcode::G_ATOMICRMW_USUB_SAT:
4651 case TargetOpcode::G_ATOMICRMW_FADD:
4652 case TargetOpcode::G_ATOMICRMW_FMIN:
4653 case TargetOpcode::G_ATOMICRMW_FMAX:
4654 return selectG_LOAD_STORE_ATOMICRMW(
I);
4655 case TargetOpcode::G_SELECT:
4656 return selectG_SELECT(
I);
4657 case TargetOpcode::G_TRUNC:
4658 return selectG_TRUNC(
I);
4659 case TargetOpcode::G_SEXT:
4660 case TargetOpcode::G_ZEXT:
4661 case TargetOpcode::G_ANYEXT:
4662 case TargetOpcode::G_SEXT_INREG:
4666 if (MRI->getType(
I.getOperand(1).getReg()) !=
LLT::scalar(1) &&
4669 return selectG_SZA_EXT(
I);
4670 case TargetOpcode::G_FPEXT:
4671 if (selectG_FPEXT(
I))
4674 case TargetOpcode::G_BRCOND:
4675 return selectG_BRCOND(
I);
4676 case TargetOpcode::G_GLOBAL_VALUE:
4677 return selectG_GLOBAL_VALUE(
I);
4678 case TargetOpcode::G_PTRMASK:
4679 return selectG_PTRMASK(
I);
4680 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4681 return selectG_EXTRACT_VECTOR_ELT(
I);
4682 case TargetOpcode::G_INSERT_VECTOR_ELT:
4683 return selectG_INSERT_VECTOR_ELT(
I);
4684 case TargetOpcode::G_FMA: {
4685 if (!STI.hasPkF32InvalidOpSel())
4688 Register VReg =
I.getOperand(0).getReg();
4694 if (Sel && Sel->
getOpcode() == AMDGPU::V_PK_FMA_F32 &&
4695 !TII.isLegalPkFMAF32OpSel(*Sel))
4696 TII.decomposePkFMAF32(*Sel, *MRI);
4700 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD:
4701 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16:
4702 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET:
4703 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE:
4704 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16: {
4707 assert(Intr &&
"not an image intrinsic with image pseudo");
4708 return selectImageIntrinsic(
I, Intr);
4710 case AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY:
4711 case AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY:
4712 case AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY:
4713 return selectBVHIntersectRayIntrinsic(
I);
4714 case AMDGPU::G_SBFX:
4715 case AMDGPU::G_UBFX:
4716 return selectG_SBFX_UBFX(
I);
4717 case AMDGPU::G_SI_CALL:
4718 I.setDesc(TII.get(AMDGPU::SI_CALL));
4720 case AMDGPU::G_AMDGPU_WAVE_ADDRESS:
4721 return selectWaveAddress(
I);
4722 case AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_RETURN: {
4723 I.setDesc(TII.get(AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN));
4726 case AMDGPU::G_STACKRESTORE:
4727 return selectStackRestore(
I);
4728 case TargetOpcode::G_WRITE_REGISTER:
4729 return selectWriteRegister(
I);
4731 return selectPHI(
I);
4732 case AMDGPU::G_AMDGPU_COPY_SCC_VCC:
4733 return selectCOPY_SCC_VCC(
I);
4734 case AMDGPU::G_AMDGPU_COPY_VCC_SCC:
4735 return selectCOPY_VCC_SCC(
I);
4736 case AMDGPU::G_AMDGPU_READANYLANE:
4737 return selectReadAnyLane(
I);
4738 case TargetOpcode::G_CONSTANT:
4739 case TargetOpcode::G_FCONSTANT:
4747AMDGPUInstructionSelector::selectVCSRC(
MachineOperand &Root)
const {
4754std::pair<Register, unsigned> AMDGPUInstructionSelector::selectVOP3ModsImpl(
4755 Register Src,
bool IsCanonicalizing,
bool AllowAbs,
bool OpSel)
const {
4759 if (
MI->getOpcode() == AMDGPU::G_FNEG) {
4760 Src =
MI->getOperand(1).getReg();
4763 }
else if (
MI->getOpcode() == AMDGPU::G_FSUB && IsCanonicalizing) {
4768 if (
LHS &&
LHS->isZero()) {
4770 Src =
MI->getOperand(2).getReg();
4774 if (AllowAbs &&
MI->getOpcode() == AMDGPU::G_FABS) {
4775 Src =
MI->getOperand(1).getReg();
4782 return std::pair(Src, Mods);
4785std::pair<Register, unsigned>
4786AMDGPUInstructionSelector::selectVOP3PModsF32Impl(
Register Src)
const {
4788 std::tie(Src, Mods) = selectVOP3ModsImpl(Src);
4790 return std::pair(Src, Mods);
4793Register AMDGPUInstructionSelector::copyToVGPRIfSrcFolded(
4795 bool ForceVGPR)
const {
4796 if ((Mods != 0 || ForceVGPR) &&
4797 RBI.getRegBank(Src, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID) {
4804 TII.
get(AMDGPU::COPY), VGPRSrc)
4816AMDGPUInstructionSelector::widenSrcIfVGPR16(
Register Src,
4818 if (!Subtarget->useRealTrue16Insts() || MRI->getType(Src) !=
LLT::scalar(16))
4821 const RegisterBank *SrcRB = RBI.getRegBank(Src, *MRI, TRI);
4822 if (!SrcRB || SrcRB->
getID() != AMDGPU::VGPRRegBankID)
4825 MachineIRBuilder
B(*InsertPt);
4827 Register ImpDefReg = MRI->createVirtualRegister(&AMDGPU::VGPR_16RegClass);
4828 B.buildInstr(TargetOpcode::IMPLICIT_DEF).addDef(ImpDefReg);
4830 Register DstReg = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
4831 B.buildInstr(AMDGPU::REG_SEQUENCE)
4834 .addImm(AMDGPU::lo16)
4836 .addImm(AMDGPU::hi16);
4845AMDGPUInstructionSelector::selectVSRC0(
MachineOperand &Root)
const {
4847 [=](MachineInstrBuilder &MIB) { MIB.
add(Root); }
4852AMDGPUInstructionSelector::selectVOP3Mods0(
MachineOperand &Root)
const {
4855 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
4858 [=](MachineInstrBuilder &MIB) {
4859 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4861 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
4862 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4863 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4868AMDGPUInstructionSelector::selectVOP3BMods0(
MachineOperand &Root)
const {
4871 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
4876 [=](MachineInstrBuilder &MIB) {
4877 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4879 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
4880 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4881 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4886AMDGPUInstructionSelector::selectVOP3OMods(
MachineOperand &Root)
const {
4888 [=](MachineInstrBuilder &MIB) { MIB.
add(Root); },
4889 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4890 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4895AMDGPUInstructionSelector::selectVOP3Mods(
MachineOperand &Root)
const {
4898 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
4901 [=](MachineInstrBuilder &MIB) {
4902 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4904 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4909AMDGPUInstructionSelector::selectVOP3ModsNonCanonicalizing(
4913 std::tie(Src, Mods) =
4914 selectVOP3ModsImpl(Root.
getReg(),
false);
4917 [=](MachineInstrBuilder &MIB) {
4918 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4920 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4925AMDGPUInstructionSelector::selectVOP3BMods(
MachineOperand &Root)
const {
4928 std::tie(Src, Mods) =
4929 selectVOP3ModsImpl(Root.
getReg(),
true,
4933 [=](MachineInstrBuilder &MIB) {
4934 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4936 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4941AMDGPUInstructionSelector::selectVOP3NoMods(
MachineOperand &Root)
const {
4944 if (
Def->getOpcode() == AMDGPU::G_FNEG ||
Def->getOpcode() == AMDGPU::G_FABS)
4947 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
4972 if (
MI->getOpcode() != AMDGPU::G_TRUNC)
4977 return DstSize * 2 == SrcSize;
4983 if (
MI->getOpcode() != AMDGPU::G_LSHR)
4987 std::optional<ValueAndVReg> ShiftAmt;
4988 if (
mi_match(
MI->getOperand(0).getReg(), MRI,
4991 unsigned Shift = ShiftAmt->Value.getZExtValue();
4992 return Shift * 2 == SrcSize;
5000 if (
MI->getOpcode() != AMDGPU::G_SHL)
5004 std::optional<ValueAndVReg> ShiftAmt;
5005 if (
mi_match(
MI->getOperand(0).getReg(), MRI,
5008 unsigned Shift = ShiftAmt->Value.getZExtValue();
5009 return Shift * 2 == SrcSize;
5017 if (
MI->getOpcode() != AMDGPU::G_UNMERGE_VALUES)
5019 return MI->getNumOperands() == 3 &&
MI->getOperand(0).isDef() &&
5020 MI->getOperand(1).isDef() && !
MI->getOperand(2).isDef();
5028 if (
OpTy.isScalar())
5030 if (
OpTy.isVector() &&
OpTy.getNumElements() == 2)
5190static std::optional<std::pair<Register, SrcStatus>>
5195 unsigned Opc =
MI->getOpcode();
5199 case AMDGPU::G_BITCAST:
5200 return std::optional<std::pair<Register, SrcStatus>>(
5201 {
MI->getOperand(1).getReg(), Curr.second});
5203 if (
MI->getOperand(1).getReg().isPhysical())
5204 return std::nullopt;
5205 return std::optional<std::pair<Register, SrcStatus>>(
5206 {
MI->getOperand(1).getReg(), Curr.second});
5207 case AMDGPU::G_FNEG: {
5210 return std::nullopt;
5211 return std::optional<std::pair<Register, SrcStatus>>(
5212 {
MI->getOperand(1).getReg(), Stat});
5219 switch (Curr.second) {
5222 return std::optional<std::pair<Register, SrcStatus>>(
5225 if (Curr.first ==
MI->getOperand(0).getReg())
5226 return std::optional<std::pair<Register, SrcStatus>>(
5228 return std::optional<std::pair<Register, SrcStatus>>(
5240 return std::optional<std::pair<Register, SrcStatus>>(
5244 if (Curr.first ==
MI->getOperand(0).getReg())
5245 return std::optional<std::pair<Register, SrcStatus>>(
5247 return std::optional<std::pair<Register, SrcStatus>>(
5253 return std::optional<std::pair<Register, SrcStatus>>(
5258 return std::optional<std::pair<Register, SrcStatus>>(
5263 return std::optional<std::pair<Register, SrcStatus>>(
5268 return std::optional<std::pair<Register, SrcStatus>>(
5274 return std::nullopt;
5284 bool HasNeg =
false;
5286 bool HasOpsel =
true;
5291 unsigned Opc =
MI->getOpcode();
5293 if (
Opc == TargetOpcode::G_INTRINSIC) {
5296 if (IntrinsicID == Intrinsic::amdgcn_fdot2)
5323 while (
Depth <= MaxDepth && Curr.has_value()) {
5326 Statlist.push_back(Curr.value());
5333static std::pair<Register, SrcStatus>
5340 while (
Depth <= MaxDepth && Curr.has_value()) {
5346 LastSameOrNeg = Curr.value();
5351 return LastSameOrNeg;
5358 return Width1 == Width2;
5393 return isSameBitWidth(NewReg, RootReg, MRI) && IsHalfState(LoStat) &&
5394 IsHalfState(HiStat);
5397std::pair<Register, unsigned> AMDGPUInstructionSelector::selectVOP3PModsImpl(
5403 return {RootReg, Mods};
5406 SearchOptions SO(RootReg, MRI);
5419 if (MRI.getType(RootReg).getSizeInBits() == 128) {
5421 return {Stat.first, Mods};
5426 MI->getNumOperands() != 3 || (IsDOT && Subtarget->hasDOTOpSelHazard())) {
5428 return {Stat.first, Mods};
5434 if (StatlistHi.
empty()) {
5436 return {Stat.first, Mods};
5442 if (StatlistLo.
empty()) {
5444 return {Stat.first, Mods};
5447 for (
int I = StatlistHi.
size() - 1;
I >= 0;
I--) {
5448 for (
int J = StatlistLo.
size() - 1; J >= 0; J--) {
5449 if (StatlistHi[
I].first == StatlistLo[J].first &&
5451 StatlistHi[
I].first, RootReg, TII, MRI))
5452 return {StatlistHi[
I].first,
5453 updateMods(StatlistHi[
I].second, StatlistLo[J].second, Mods)};
5459 return {Stat.first, Mods};
5469 return RB->
getID() == RBNo;
5485 if (
checkRB(RootReg, AMDGPU::SGPRRegBankID, RBI, MRI,
TRI) ||
5486 checkRB(NewReg, AMDGPU::VGPRRegBankID, RBI, MRI,
TRI))
5496 TII.get(AMDGPU::COPY), DstReg)
5504AMDGPUInstructionSelector::selectVOP3PRetHelper(
MachineOperand &Root,
5509 std::tie(
Reg, Mods) = selectVOP3PModsImpl(Root.
getReg(), MRI, IsDOT);
5514 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
5515 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5520AMDGPUInstructionSelector::selectVOP3PMods(
MachineOperand &Root)
const {
5522 return selectVOP3PRetHelper(Root);
5526AMDGPUInstructionSelector::selectVOP3PModsDOT(
MachineOperand &Root)
const {
5528 return selectVOP3PRetHelper(Root,
true);
5532AMDGPUInstructionSelector::selectVOP3PNoModsDOT(
MachineOperand &Root)
const {
5536 std::tie(Src, Mods) = selectVOP3PModsImpl(Root.
getReg(), MRI,
true );
5540 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); }}};
5544AMDGPUInstructionSelector::selectVOP3PModsF32(
MachineOperand &Root)
const {
5547 std::tie(Src, Mods) = selectVOP3PModsF32Impl(Root.
getReg());
5550 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5551 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5556AMDGPUInstructionSelector::selectVOP3PNoModsF32(
MachineOperand &Root)
const {
5559 std::tie(Src, Mods) = selectVOP3PModsF32Impl(Root.
getReg());
5563 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); }}};
5567AMDGPUInstructionSelector::selectWMMAOpSelVOP3PMods(
5570 "expected i1 value");
5576 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5584 switch (Elts.
size()) {
5586 DstRegClass = &AMDGPU::VReg_256RegClass;
5589 DstRegClass = &AMDGPU::VReg_128RegClass;
5592 DstRegClass = &AMDGPU::VReg_64RegClass;
5599 auto MIB =
B.buildInstr(AMDGPU::REG_SEQUENCE)
5601 for (
unsigned i = 0; i < Elts.
size(); ++i) {
5612 if (ModOpcode == TargetOpcode::G_FNEG) {
5616 for (
auto El : Elts) {
5622 if (Elts.size() != NegAbsElts.
size()) {
5631 assert(ModOpcode == TargetOpcode::G_FABS);
5639AMDGPUInstructionSelector::selectWMMAModsF32NegAbs(
MachineOperand &Root)
const {
5648 MachineInstr *ElF32 = MRI->getVRegDef(BV->
getSourceReg(0));
5649 unsigned ModOpcode = (ElF32->
getOpcode() == AMDGPU::G_FNEG)
5666 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5667 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5671AMDGPUInstructionSelector::selectWMMAModsF16Neg(
MachineOperand &Root)
const {
5693 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5694 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5698AMDGPUInstructionSelector::selectWMMAModsF16NegAbs(
MachineOperand &Root)
const {
5706 MachineInstr *ElV2F16 = MRI->getVRegDef(CV->
getSourceReg(0));
5708 unsigned ModOpcode = (ElV2F16->
getOpcode() == AMDGPU::G_FNEG)
5727 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5728 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5732AMDGPUInstructionSelector::selectWMMAVISrc(
MachineOperand &Root)
const {
5733 std::optional<FPValueAndVReg> FPValReg;
5735 if (TII.isInlineConstant(FPValReg->Value)) {
5736 return {{[=](MachineInstrBuilder &MIB) {
5737 MIB.
addImm(FPValReg->Value.bitcastToAPInt().getSExtValue());
5747 if (TII.isInlineConstant(ICst)) {
5757AMDGPUInstructionSelector::selectSWMMACIndex8(
MachineOperand &Root)
const {
5763 std::optional<ValueAndVReg> ShiftAmt;
5765 MRI->getType(ShiftSrc).getSizeInBits() == 32 &&
5766 ShiftAmt->Value.getZExtValue() % 8 == 0) {
5767 Key = ShiftAmt->Value.getZExtValue() / 8;
5772 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5773 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5778AMDGPUInstructionSelector::selectSWMMACIndex16(
MachineOperand &Root)
const {
5785 std::optional<ValueAndVReg> ShiftAmt;
5787 MRI->getType(ShiftSrc).getSizeInBits() == 32 &&
5788 ShiftAmt->Value.getZExtValue() == 16) {
5794 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5795 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5800AMDGPUInstructionSelector::selectSWMMACIndex32(
MachineOperand &Root)
const {
5807 S32 = matchAnyExtendFromS32(Src);
5811 if (
Def->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) {
5816 Src =
Def->getOperand(2).getReg();
5823 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5824 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5829AMDGPUInstructionSelector::selectVOP3OpSelMods(
MachineOperand &Root)
const {
5832 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
5835 if (!Subtarget->useRealTrue16Insts() &&
5836 MRI->getType(Root.
getReg()).getSizeInBits() == 16 &&
5843 [=](MachineInstrBuilder &MIB) {
5844 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
5846 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5852AMDGPUInstructionSelector::selectVINTERPMods(
MachineOperand &Root)
const {
5855 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
5861 [=](MachineInstrBuilder &MIB) {
5863 copyToVGPRIfSrcFolded(Src, Mods, Root, MIB,
true));
5865 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
5870AMDGPUInstructionSelector::selectVINTERPModsHi(
MachineOperand &Root)
const {
5873 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
5879 [=](MachineInstrBuilder &MIB) {
5881 copyToVGPRIfSrcFolded(Src, Mods, Root, MIB,
true));
5883 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
5890bool AMDGPUInstructionSelector::selectScaleOffset(
MachineOperand &Root,
5892 bool IsSigned)
const {
5893 if (!Subtarget->hasScaleOffset())
5897 MachineMemOperand *MMO = *
MI.memoperands_begin();
5909 OffsetReg =
Def->Reg;
5924 m_BinOp(IsSigned ? AMDGPU::S_MUL_I64_I32_PSEUDO : AMDGPU::S_MUL_U64,
5928 (
Mul->getOpcode() == (IsSigned ? AMDGPU::G_AMDGPU_MAD_I64_I32
5929 : AMDGPU::G_AMDGPU_MAD_U64_U32) ||
5930 (IsSigned &&
Mul->getOpcode() == AMDGPU::G_AMDGPU_MAD_U64_U32 &&
5931 VT->signBitIsZero(
Mul->getOperand(2).getReg()))) &&
5944bool AMDGPUInstructionSelector::selectSmrdOffset(
MachineOperand &Root,
5948 bool *ScaleOffset)
const {
5955 getAddrModeInfo(*
MI, *MRI, AddrInfo);
5957 if (AddrInfo.
empty())
5960 const GEPInfo &GEPI = AddrInfo[0];
5961 std::optional<int64_t> EncodedImm;
5964 *ScaleOffset =
false;
5969 if (GEPI.SgprParts.size() == 1 && GEPI.Imm != 0 && EncodedImm &&
5970 AddrInfo.
size() > 1) {
5971 const GEPInfo &GEPI2 = AddrInfo[1];
5972 if (GEPI2.SgprParts.size() == 2 && GEPI2.Imm == 0) {
5973 Register OffsetReg = GEPI2.SgprParts[1];
5976 selectScaleOffset(Root, OffsetReg,
false );
5977 OffsetReg = matchZeroExtendFromS32OrS32(OffsetReg);
5979 Base = GEPI2.SgprParts[0];
5980 *SOffset = OffsetReg;
5989 auto SKnown =
VT->getKnownBits(*SOffset);
5990 if (*
Offset + SKnown.getMinValue().getSExtValue() < 0)
6002 if (
Offset && GEPI.SgprParts.size() == 1 && EncodedImm) {
6003 Base = GEPI.SgprParts[0];
6009 if (SOffset && GEPI.SgprParts.size() == 1 &&
isUInt<32>(GEPI.Imm) &&
6015 Base = GEPI.SgprParts[0];
6016 *SOffset = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
6017 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), *SOffset)
6022 if (SOffset && GEPI.SgprParts.size() && GEPI.Imm == 0) {
6023 Register OffsetReg = GEPI.SgprParts[1];
6025 *ScaleOffset = selectScaleOffset(Root, OffsetReg,
false );
6026 OffsetReg = matchZeroExtendFromS32OrS32(OffsetReg);
6028 Base = GEPI.SgprParts[0];
6029 *SOffset = OffsetReg;
6038AMDGPUInstructionSelector::selectSmrdImm(
MachineOperand &Root)
const {
6041 if (!selectSmrdOffset(Root,
Base,
nullptr, &
Offset,
6043 return std::nullopt;
6045 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
6046 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Offset); }}};
6050AMDGPUInstructionSelector::selectSmrdImm32(
MachineOperand &Root)
const {
6052 getAddrModeInfo(*Root.
getParent(), *MRI, AddrInfo);
6054 if (AddrInfo.
empty() || AddrInfo[0].SgprParts.size() != 1)
6055 return std::nullopt;
6057 const GEPInfo &GEPInfo = AddrInfo[0];
6058 Register PtrReg = GEPInfo.SgprParts[0];
6059 std::optional<int64_t> EncodedImm =
6062 return std::nullopt;
6065 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrReg); },
6066 [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); }
6071AMDGPUInstructionSelector::selectSmrdSgpr(
MachineOperand &Root)
const {
6074 if (!selectSmrdOffset(Root,
Base, &SOffset,
nullptr,
6076 return std::nullopt;
6079 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
6080 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
6081 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }}};
6085AMDGPUInstructionSelector::selectSmrdSgprImm(
MachineOperand &Root)
const {
6089 if (!selectSmrdOffset(Root,
Base, &SOffset, &
Offset, &ScaleOffset))
6090 return std::nullopt;
6093 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
6094 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
6096 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }}};
6099std::pair<Register, int> AMDGPUInstructionSelector::selectFlatOffsetImpl(
6105 if (!STI.hasFlatInstOffsets())
6109 int64_t ConstOffset;
6111 std::tie(PtrBase, ConstOffset, IsInBounds) =
6112 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
6118 if (ConstOffset == 0 ||
6120 !isFlatScratchBaseLegal(Root.
getReg())) ||
6124 unsigned AddrSpace = (*
MI->memoperands_begin())->getAddrSpace();
6125 if (!TII.isLegalFLATOffset(ConstOffset, AddrSpace, FlatVariant))
6128 return std::pair(PtrBase, ConstOffset);
6132AMDGPUInstructionSelector::selectFlatOffset(
MachineOperand &Root)
const {
6136 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6137 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6142AMDGPUInstructionSelector::selectGlobalOffset(
MachineOperand &Root)
const {
6143 auto PtrWithOffset =
6147 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6148 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6153AMDGPUInstructionSelector::selectScratchOffset(
MachineOperand &Root)
const {
6154 auto PtrWithOffset =
6158 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6159 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6165AMDGPUInstructionSelector::selectGlobalSAddr(
MachineOperand &Root,
6167 bool NeedIOffset)
const {
6170 int64_t ConstOffset;
6171 int64_t ImmOffset = 0;
6175 std::tie(PtrBase, ConstOffset, std::ignore) =
6176 getPtrBaseWithConstantOffset(Addr, *MRI);
6178 if (ConstOffset != 0) {
6183 ImmOffset = ConstOffset;
6186 if (isSGPR(PtrBaseDef->Reg)) {
6192 int64_t SplitImmOffset = 0, RemainderOffset = ConstOffset;
6194 std::tie(SplitImmOffset, RemainderOffset) =
6199 if (Subtarget->hasSignedGVSOffset() ?
isInt<32>(RemainderOffset)
6204 MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6206 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32),
6208 .
addImm(RemainderOffset);
6212 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrBase); },
6213 [=](MachineInstrBuilder &MIB) {
6216 [=](MachineInstrBuilder &MIB) { MIB.
addImm(SplitImmOffset); },
6217 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); },
6220 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrBase); },
6221 [=](MachineInstrBuilder &MIB) {
6224 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); },
6233 unsigned NumLiterals =
6234 !TII.isInlineConstant(APInt(32,
Lo_32(ConstOffset))) +
6235 !TII.isInlineConstant(APInt(32,
Hi_32(ConstOffset)));
6236 if (STI.getConstantBusLimit(AMDGPU::V_ADD_U32_e64) > NumLiterals)
6237 return std::nullopt;
6244 if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
6249 if (isSGPR(SAddr)) {
6250 Register PtrBaseOffset = AddrDef->MI->getOperand(2).getReg();
6254 bool ScaleOffset = selectScaleOffset(Root, PtrBaseOffset,
6255 Subtarget->hasSignedGVSOffset());
6256 if (
Register VOffset = matchExtendFromS32OrS32(
6257 PtrBaseOffset, Subtarget->hasSignedGVSOffset())) {
6259 return {{[=](MachineInstrBuilder &MIB) {
6262 [=](MachineInstrBuilder &MIB) {
6265 [=](MachineInstrBuilder &MIB) {
6268 [=](MachineInstrBuilder &MIB) {
6272 return {{[=](MachineInstrBuilder &MIB) {
6275 [=](MachineInstrBuilder &MIB) {
6278 [=](MachineInstrBuilder &MIB) {
6288 if (AddrDef->MI->getOpcode() == AMDGPU::G_IMPLICIT_DEF ||
6289 AddrDef->MI->getOpcode() == AMDGPU::G_CONSTANT || !isSGPR(AddrDef->Reg))
6290 return std::nullopt;
6296 Register VOffset = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6298 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32), VOffset)
6303 [=](MachineInstrBuilder &MIB) { MIB.
addReg(AddrDef->Reg); },
6304 [=](MachineInstrBuilder &MIB) { MIB.
addReg(VOffset); },
6305 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6306 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); }
6309 [=](MachineInstrBuilder &MIB) { MIB.
addReg(AddrDef->Reg); },
6310 [=](MachineInstrBuilder &MIB) { MIB.
addReg(VOffset); },
6311 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); }
6316AMDGPUInstructionSelector::selectGlobalSAddr(
MachineOperand &Root)
const {
6317 return selectGlobalSAddr(Root, 0);
6321AMDGPUInstructionSelector::selectGlobalSAddrCPol(
MachineOperand &Root)
const {
6327 return selectGlobalSAddr(Root, PassedCPol);
6331AMDGPUInstructionSelector::selectGlobalSAddrCPolM0(
MachineOperand &Root)
const {
6337 return selectGlobalSAddr(Root, PassedCPol);
6341AMDGPUInstructionSelector::selectGlobalSAddrGLC(
MachineOperand &Root)
const {
6346AMDGPUInstructionSelector::selectGlobalSAddrNoIOffset(
6353 return selectGlobalSAddr(Root, PassedCPol,
false);
6357AMDGPUInstructionSelector::selectGlobalSAddrNoIOffsetM0(
6364 return selectGlobalSAddr(Root, PassedCPol,
false);
6368AMDGPUInstructionSelector::selectScratchSAddr(
MachineOperand &Root)
const {
6371 int64_t ConstOffset;
6372 int64_t ImmOffset = 0;
6376 std::tie(PtrBase, ConstOffset, std::ignore) =
6377 getPtrBaseWithConstantOffset(Addr, *MRI);
6379 if (ConstOffset != 0 && isFlatScratchBaseLegal(Addr) &&
6383 ImmOffset = ConstOffset;
6387 if (AddrDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX) {
6388 int FI = AddrDef->MI->getOperand(1).
getIndex();
6391 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); }
6397 if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
6398 Register LHS = AddrDef->MI->getOperand(1).getReg();
6399 Register RHS = AddrDef->MI->getOperand(2).getReg();
6403 if (LHSDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX &&
6404 isSGPR(RHSDef->Reg)) {
6405 int FI = LHSDef->MI->getOperand(1).getIndex();
6409 SAddr = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
6411 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_ADD_I32), SAddr)
6419 return std::nullopt;
6422 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SAddr); },
6423 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); }
6428bool AMDGPUInstructionSelector::checkFlatScratchSVSSwizzleBug(
6430 if (!Subtarget->hasFlatScratchSVSSwizzleBug())
6436 auto VKnown =
VT->getKnownBits(VAddr);
6439 uint64_t VMax = VKnown.getMaxValue().getZExtValue();
6441 return (VMax & 3) + (
SMax & 3) >= 4;
6445AMDGPUInstructionSelector::selectScratchSVAddr(
MachineOperand &Root)
const {
6448 int64_t ConstOffset;
6449 int64_t ImmOffset = 0;
6453 std::tie(PtrBase, ConstOffset, std::ignore) =
6454 getPtrBaseWithConstantOffset(Addr, *MRI);
6457 if (ConstOffset != 0 &&
6461 ImmOffset = ConstOffset;
6465 if (AddrDef->MI->getOpcode() != AMDGPU::G_PTR_ADD)
6466 return std::nullopt;
6468 Register RHS = AddrDef->MI->getOperand(2).getReg();
6469 if (RBI.getRegBank(
RHS, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID)
6470 return std::nullopt;
6472 Register LHS = AddrDef->MI->getOperand(1).getReg();
6475 if (OrigAddr != Addr) {
6476 if (!isFlatScratchBaseLegalSVImm(OrigAddr))
6477 return std::nullopt;
6479 if (!isFlatScratchBaseLegalSV(OrigAddr))
6480 return std::nullopt;
6483 if (checkFlatScratchSVSSwizzleBug(
RHS,
LHS, ImmOffset))
6484 return std::nullopt;
6486 unsigned CPol = selectScaleOffset(Root,
RHS,
true )
6490 if (LHSDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX) {
6491 int FI = LHSDef->MI->getOperand(1).getIndex();
6493 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
RHS); },
6495 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6496 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }
6505 return std::nullopt;
6508 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
RHS); },
6509 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
LHS); },
6510 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6511 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }
6516AMDGPUInstructionSelector::selectMUBUFScratchOffen(
MachineOperand &Root)
const {
6520 const SIMachineFunctionInfo *
Info =
MF->getInfo<SIMachineFunctionInfo>();
6525 Register HighBits = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6530 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32),
6534 return {{[=](MachineInstrBuilder &MIB) {
6537 [=](MachineInstrBuilder &MIB) {
6540 [=](MachineInstrBuilder &MIB) {
6545 [=](MachineInstrBuilder &MIB) {
6554 std::optional<int> FI;
6558 int64_t ConstOffset;
6559 std::tie(PtrBase, ConstOffset, std::ignore) =
6560 getPtrBaseWithConstantOffset(VAddr, *MRI);
6562 if (ConstOffset != 0) {
6563 if (TII.isLegalMUBUFImmOffset(ConstOffset) &&
6564 (!STI.privateMemoryResourceIsRangeChecked() ||
6565 VT->signBitIsZero(PtrBase))) {
6576 return {{[=](MachineInstrBuilder &MIB) {
6579 [=](MachineInstrBuilder &MIB) {
6585 [=](MachineInstrBuilder &MIB) {
6590 [=](MachineInstrBuilder &MIB) {
6595bool AMDGPUInstructionSelector::isDSOffsetLegal(
Register Base,
6600 if (STI.hasUsableDSOffset() || STI.unsafeDSOffsetFoldingEnabled())
6605 return VT->signBitIsZero(
Base);
6608bool AMDGPUInstructionSelector::isDSOffset2Legal(
Register Base, int64_t Offset0,
6610 unsigned Size)
const {
6611 if (Offset0 %
Size != 0 || Offset1 %
Size != 0)
6616 if (STI.hasUsableDSOffset() || STI.unsafeDSOffsetFoldingEnabled())
6621 return VT->signBitIsZero(
Base);
6626 return Addr->
getOpcode() == TargetOpcode::G_OR ||
6627 (Addr->
getOpcode() == TargetOpcode::G_PTR_ADD &&
6634bool AMDGPUInstructionSelector::isFlatScratchBaseLegal(
Register Addr)
const {
6642 if (STI.hasSignedScratchOffsets())
6648 if (AddrMI->
getOpcode() == TargetOpcode::G_PTR_ADD) {
6649 std::optional<ValueAndVReg> RhsValReg =
6655 if (RhsValReg && RhsValReg->Value.getSExtValue() < 0 &&
6656 RhsValReg->Value.getSExtValue() > -0x40000000)
6660 return VT->signBitIsZero(
LHS);
6665bool AMDGPUInstructionSelector::isFlatScratchBaseLegalSV(
Register Addr)
const {
6673 if (STI.hasSignedScratchOffsets())
6678 return VT->signBitIsZero(
RHS) &&
VT->signBitIsZero(
LHS);
6683bool AMDGPUInstructionSelector::isFlatScratchBaseLegalSVImm(
6687 if (STI.hasSignedScratchOffsets())
6692 std::optional<DefinitionAndSourceRegister> BaseDef =
6694 std::optional<ValueAndVReg> RHSOffset =
6704 (RHSOffset->Value.getSExtValue() < 0 &&
6705 RHSOffset->Value.getSExtValue() > -0x40000000)))
6708 Register LHS = BaseDef->MI->getOperand(1).getReg();
6709 Register RHS = BaseDef->MI->getOperand(2).getReg();
6710 return VT->signBitIsZero(
RHS) &&
VT->signBitIsZero(
LHS);
6713bool AMDGPUInstructionSelector::isUnneededShiftMask(
const MachineInstr &
MI,
6714 unsigned ShAmtBits)
const {
6715 assert(
MI.getOpcode() == TargetOpcode::G_AND);
6719 std::optional<ValueAndVReg>
RHS =
6724 if (
RHS->
Value.countr_one() >= ShAmtBits)
6727 const APInt &LHSKnownZeros =
VT->getKnownZeroes(
MI.getOperand(1).getReg());
6728 return (LHSKnownZeros |
RHS->
Value).countr_one() >= ShAmtBits;
6732AMDGPUInstructionSelector::selectMUBUFScratchOffset(
6735 const SIMachineFunctionInfo *
Info =
MF->getInfo<SIMachineFunctionInfo>();
6737 std::optional<DefinitionAndSourceRegister>
Def =
6739 assert(Def &&
"this shouldn't be an optional result");
6744 [=](MachineInstrBuilder &MIB) {
6747 [=](MachineInstrBuilder &MIB) {
6750 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
6761 if (!TII.isLegalMUBUFImmOffset(
Offset))
6769 [=](MachineInstrBuilder &MIB) {
6772 [=](MachineInstrBuilder &MIB) {
6780 !TII.isLegalMUBUFImmOffset(
Offset))
6784 [=](MachineInstrBuilder &MIB) {
6787 [=](MachineInstrBuilder &MIB) {
6794std::pair<Register, unsigned>
6795AMDGPUInstructionSelector::selectDS1Addr1OffsetImpl(
6797 int64_t ConstAddr = 0;
6801 std::tie(PtrBase,
Offset, std::ignore) =
6802 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
6805 if (isDSOffsetLegal(PtrBase,
Offset)) {
6807 return std::pair(PtrBase,
Offset);
6816 return std::pair(Root.
getReg(), 0);
6820AMDGPUInstructionSelector::selectDS1Addr1Offset(
MachineOperand &Root)
const {
6823 std::tie(
Reg,
Offset) = selectDS1Addr1OffsetImpl(Root);
6825 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
6831AMDGPUInstructionSelector::selectDS64Bit4ByteAligned(
MachineOperand &Root)
const {
6832 return selectDSReadWrite2(Root, 4);
6836AMDGPUInstructionSelector::selectDS128Bit8ByteAligned(
MachineOperand &Root)
const {
6837 return selectDSReadWrite2(Root, 8);
6841AMDGPUInstructionSelector::selectDSReadWrite2(
MachineOperand &Root,
6842 unsigned Size)
const {
6847 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
6849 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Offset+1); }
6853std::pair<Register, unsigned>
6854AMDGPUInstructionSelector::selectDSReadWrite2Impl(
MachineOperand &Root,
6855 unsigned Size)
const {
6856 int64_t ConstAddr = 0;
6860 std::tie(PtrBase,
Offset, std::ignore) =
6861 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
6864 int64_t OffsetValue0 =
Offset;
6866 if (isDSOffset2Legal(PtrBase, OffsetValue0, OffsetValue1,
Size)) {
6868 return std::pair(PtrBase, OffsetValue0 /
Size);
6877 return std::pair(Root.
getReg(), 0);
6885std::tuple<Register, int64_t, bool>
6886AMDGPUInstructionSelector::getPtrBaseWithConstantOffset(
6889 if (RootI->
getOpcode() != TargetOpcode::G_PTR_ADD)
6890 return {Root, 0,
false};
6893 std::optional<ValueAndVReg> MaybeOffset =
6896 return {Root, 0,
false};
6916 B.buildInstr(AMDGPU::S_MOV_B32)
6919 B.buildInstr(AMDGPU::S_MOV_B32)
6926 B.buildInstr(AMDGPU::REG_SEQUENCE)
6929 .addImm(AMDGPU::sub0)
6931 .addImm(AMDGPU::sub1);
6936 B.buildInstr(AMDGPU::S_MOV_B64)
6941 B.buildInstr(AMDGPU::REG_SEQUENCE)
6944 .addImm(AMDGPU::sub0_sub1)
6946 .addImm(AMDGPU::sub2_sub3);
6953 uint64_t DefaultFormat =
TII.getDefaultRsrcDataFormat();
6962 uint64_t DefaultFormat =
TII.getDefaultRsrcDataFormat();
6969AMDGPUInstructionSelector::MUBUFAddressData
6970AMDGPUInstructionSelector::parseMUBUFAddress(
Register Src)
const {
6971 MUBUFAddressData
Data;
6977 std::tie(PtrBase,
Offset, std::ignore) =
6978 getPtrBaseWithConstantOffset(Src, *MRI);
6984 if (MachineInstr *InputAdd
6986 Data.N2 = InputAdd->getOperand(1).getReg();
6987 Data.N3 = InputAdd->getOperand(2).getReg();
7002bool AMDGPUInstructionSelector::shouldUseAddr64(MUBUFAddressData Addr)
const {
7008 const RegisterBank *N0Bank = RBI.getRegBank(Addr.N0, *MRI, TRI);
7009 return N0Bank->
getID() == AMDGPU::VGPRRegBankID;
7015void AMDGPUInstructionSelector::splitIllegalMUBUFOffset(
7017 if (TII.isLegalMUBUFImmOffset(ImmOffset))
7021 SOffset = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7022 B.buildInstr(AMDGPU::S_MOV_B32)
7028bool AMDGPUInstructionSelector::selectMUBUFAddr64Impl(
7033 if (!STI.hasAddr64() || STI.useFlatForGlobal())
7036 MUBUFAddressData AddrData = parseMUBUFAddress(Root.
getReg());
7037 if (!shouldUseAddr64(AddrData))
7043 Offset = AddrData.Offset;
7049 if (RBI.getRegBank(N2, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
7051 if (RBI.getRegBank(N3, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
7064 }
else if (RBI.getRegBank(N0, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
7075 splitIllegalMUBUFOffset(
B, SOffset,
Offset);
7079bool AMDGPUInstructionSelector::selectMUBUFOffsetImpl(
7084 if (STI.useFlatForGlobal())
7087 MUBUFAddressData AddrData = parseMUBUFAddress(Root.
getReg());
7088 if (shouldUseAddr64(AddrData))
7094 Offset = AddrData.Offset;
7100 splitIllegalMUBUFOffset(
B, SOffset,
Offset);
7105AMDGPUInstructionSelector::selectMUBUFAddr64(
MachineOperand &Root)
const {
7111 if (!selectMUBUFAddr64Impl(Root, VAddr, RSrcReg, SOffset,
Offset))
7117 [=](MachineInstrBuilder &MIB) {
7120 [=](MachineInstrBuilder &MIB) {
7123 [=](MachineInstrBuilder &MIB) {
7126 else if (STI.hasRestrictedSOffset())
7127 MIB.
addReg(AMDGPU::SGPR_NULL);
7131 [=](MachineInstrBuilder &MIB) {
7141AMDGPUInstructionSelector::selectMUBUFOffset(
MachineOperand &Root)
const {
7146 if (!selectMUBUFOffsetImpl(Root, RSrcReg, SOffset,
Offset))
7150 [=](MachineInstrBuilder &MIB) {
7153 [=](MachineInstrBuilder &MIB) {
7156 else if (STI.hasRestrictedSOffset())
7157 MIB.
addReg(AMDGPU::SGPR_NULL);
7169AMDGPUInstructionSelector::selectBUFSOffset(
MachineOperand &Root)
const {
7174 SOffset = AMDGPU::SGPR_NULL;
7176 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); }}};
7180static std::optional<uint64_t>
7184 if (!OffsetVal || !
isInt<32>(*OffsetVal))
7185 return std::nullopt;
7186 return Lo_32(*OffsetVal);
7190AMDGPUInstructionSelector::selectSMRDBufferImm(
MachineOperand &Root)
const {
7191 std::optional<uint64_t> OffsetVal =
7196 std::optional<int64_t> EncodedImm =
7201 return {{ [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); } }};
7205AMDGPUInstructionSelector::selectSMRDBufferImm32(
MachineOperand &Root)
const {
7212 std::optional<int64_t> EncodedImm =
7217 return {{ [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); } }};
7221AMDGPUInstructionSelector::selectSMRDBufferSgprImm(
MachineOperand &Root)
const {
7229 return std::nullopt;
7231 std::optional<int64_t> EncodedOffset =
7234 return std::nullopt;
7236 assert(MRI->getType(SOffset).getSizeInBits() == 32);
7237 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
7238 [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedOffset); }}};
7241std::pair<Register, unsigned>
7242AMDGPUInstructionSelector::selectVOP3PMadMixModsImpl(
MachineOperand &Root,
7243 bool &Matched)
const {
7248 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
7258 const auto CheckAbsNeg = [&]() {
7263 std::tie(Src, ModsTmp) = selectVOP3ModsImpl(Src);
7293 if (MRI->getType(Src).isFixedVector(2, 16))
7306AMDGPUInstructionSelector::selectVOP3PMadMixModsExt(
7311 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7316 [=](MachineInstrBuilder &MIB) { MIB.
addReg(widenSrcIfVGPR16(Src, MIB)); },
7317 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
7322AMDGPUInstructionSelector::selectVOP3PMadMixMods(
MachineOperand &Root)
const {
7326 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7329 [=](MachineInstrBuilder &MIB) { MIB.
addReg(widenSrcIfVGPR16(Src, MIB)); },
7330 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
7335AMDGPUInstructionSelector::selectVOP3PMadMixModsExtNeg(
7340 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7345 [=](MachineInstrBuilder &MIB) { MIB.
addReg(widenSrcIfVGPR16(Src, MIB)); },
7346 [=](MachineInstrBuilder &MIB) {
7353AMDGPUInstructionSelector::selectVOP3PMadMixModsNeg(
7358 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7361 [=](MachineInstrBuilder &MIB) { MIB.
addReg(widenSrcIfVGPR16(Src, MIB)); },
7362 [=](MachineInstrBuilder &MIB) {
7368bool AMDGPUInstructionSelector::selectSBarrierSignalIsfirst(
7372 Register CCReg =
I.getOperand(0).getReg();
7377 BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM))
7378 .
addImm(
I.getOperand(2).getImm());
7382 I.eraseFromParent();
7383 return RBI.constrainGenericRegister(CCReg, AMDGPU::SReg_32_XM0_XEXECRegClass,
7387bool AMDGPUInstructionSelector::selectSGetBarrierState(
7391 const MachineOperand &BarOp =
I.getOperand(2);
7392 std::optional<int64_t> BarValImm =
7396 auto CopyMIB =
BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
7400 MachineInstrBuilder MIB;
7401 unsigned Opc = BarValImm ? AMDGPU::S_GET_BARRIER_STATE_IMM
7402 : AMDGPU::S_GET_BARRIER_STATE_M0;
7405 auto DstReg =
I.getOperand(0).getReg();
7407 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
7408 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
7414 I.eraseFromParent();
7419 if (HasInlineConst) {
7423 case Intrinsic::amdgcn_s_barrier_join:
7424 return AMDGPU::S_BARRIER_JOIN_IMM;
7425 case Intrinsic::amdgcn_s_wakeup_barrier:
7426 return AMDGPU::S_WAKEUP_BARRIER_IMM;
7427 case Intrinsic::amdgcn_s_get_named_barrier_state:
7428 return AMDGPU::S_GET_BARRIER_STATE_IMM;
7434 case Intrinsic::amdgcn_s_barrier_join:
7435 return AMDGPU::S_BARRIER_JOIN_M0;
7436 case Intrinsic::amdgcn_s_wakeup_barrier:
7437 return AMDGPU::S_WAKEUP_BARRIER_M0;
7438 case Intrinsic::amdgcn_s_get_named_barrier_state:
7439 return AMDGPU::S_GET_BARRIER_STATE_M0;
7444bool AMDGPUInstructionSelector::selectNamedBarrierInit(
7448 const MachineOperand &BarOp =
I.getOperand(1);
7449 const MachineOperand &CntOp =
I.getOperand(2);
7453 if (IntrID == Intrinsic::amdgcn_s_barrier_signal_var) {
7454 std::optional<int64_t> CntImm =
7456 if (CntImm && *CntImm == 0) {
7457 std::optional<int64_t> BarValImm =
7460 uint32_t BarID = *BarValImm & 0x3F;
7461 BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::S_BARRIER_SIGNAL_IMM))
7463 I.eraseFromParent();
7470 Register TmpReg1 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7479 Register TmpReg2 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7485 Register TmpReg3 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7486 constexpr unsigned ShAmt = 16;
7492 Register TmpReg4 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7502 unsigned Opc = IntrID == Intrinsic::amdgcn_s_barrier_init
7503 ? AMDGPU::S_BARRIER_INIT_M0
7504 : AMDGPU::S_BARRIER_SIGNAL_M0;
7505 MachineInstrBuilder MIB;
7508 I.eraseFromParent();
7512bool AMDGPUInstructionSelector::selectNamedBarrierInst(
7516 MachineOperand BarOp = IntrID == Intrinsic::amdgcn_s_get_named_barrier_state
7519 std::optional<int64_t> BarValImm =
7524 Register TmpReg1 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7530 auto CopyMIB =
BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
7535 MachineInstrBuilder MIB;
7539 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state) {
7540 auto DstReg =
I.getOperand(0).getReg();
7542 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
7543 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
7549 uint32_t BarId = *BarValImm & 0x3F;
7553 I.eraseFromParent();
7560 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
7561 "Expected G_CONSTANT");
7562 MIB.
addImm(-
MI.getOperand(1).getCImm()->getSExtValue());
7568 const MachineOperand &
Op =
MI.getOperand(1);
7569 assert(
MI.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1);
7570 MIB.
addImm(
Op.getFPImm()->getValueAPF().bitcastToAPInt().getZExtValue());
7573void AMDGPUInstructionSelector::renderCountTrailingOnesImm(
7575 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
7576 "Expected G_CONSTANT");
7577 MIB.
addImm(
MI.getOperand(1).getCImm()->getValue().countTrailingOnes());
7585 const MachineOperand &
Op =
MI.getOperand(OpIdx);
7596 MIB.
addImm(
MI.getOperand(OpIdx).getImm() != 0);
7602 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7606void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_0_0(
7608 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7613void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_0_1(
7615 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7616 MIB.
addImm((
MI.getOperand(OpIdx).getImm() & 0x1)
7621void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_1_0(
7623 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7628void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_1_1(
7630 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7631 MIB.
addImm((
MI.getOperand(OpIdx).getImm() & 0x2)
7636void AMDGPUInstructionSelector::renderDstSelToOpSelXForm(
7638 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7643void AMDGPUInstructionSelector::renderSrcSelToOpSelXForm(
7645 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7650void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_2_0(
7652 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7657void AMDGPUInstructionSelector::renderDstSelToOpSel3XFormXForm(
7659 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7660 MIB.
addImm((
MI.getOperand(OpIdx).getImm() & 0x2)
7668 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7669 MIB.
addImm(
MI.getOperand(OpIdx).getImm() &
7677 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7678 const bool Swizzle =
MI.getOperand(OpIdx).getImm() &
7684void AMDGPUInstructionSelector::renderExtractCpolSetGLC(
7686 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7687 const uint32_t Cpol =
MI.getOperand(OpIdx).getImm() &
7696 const APFloat &APF =
MI.getOperand(1).getFPImm()->getValueAPF();
7698 assert(ExpVal != INT_MIN);
7709 MIB.
addImm((
MI.getOperand(OpIdx).getImm() + 3) % 4);
7716 if (
MI.getOperand(OpIdx).getImm())
7718 MIB.
addImm((int64_t)Mods);
7725 if (
MI.getOperand(OpIdx).getImm())
7727 MIB.
addImm((int64_t)Mods);
7733 unsigned Val =
MI.getOperand(OpIdx).getImm();
7741 MIB.
addImm((int64_t)Mods);
7747 uint32_t
V =
MI.getOperand(2).getImm();
7750 if (!Subtarget->hasSafeCUPrefetch())
7756void AMDGPUInstructionSelector::renderScaledMAIIntrinsicOperand(
7758 unsigned Val =
MI.getOperand(OpIdx).getImm();
7767bool AMDGPUInstructionSelector::isInlineImmediate(
const APInt &
Imm)
const {
7768 return TII.isInlineConstant(
Imm);
7771bool AMDGPUInstructionSelector::isInlineImmediate(
const APFloat &
Imm)
const {
7772 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.