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)) {
2251 NumVDataDwords, NumVAddrDwords);
2252 }
else if (IsGFX12Plus) {
2254 NumVDataDwords, NumVAddrDwords);
2255 }
else if (IsGFX11Plus) {
2257 UseNSA ? AMDGPU::MIMGEncGfx11NSA
2258 : AMDGPU::MIMGEncGfx11Default,
2259 NumVDataDwords, NumVAddrDwords);
2260 }
else if (IsGFX10Plus) {
2262 UseNSA ? AMDGPU::MIMGEncGfx10NSA
2263 : AMDGPU::MIMGEncGfx10Default,
2264 NumVDataDwords, NumVAddrDwords);
2266 if (Subtarget->hasGFX90AInsts()) {
2268 NumVDataDwords, NumVAddrDwords);
2272 <<
"requested image instruction is not supported on this GPU\n");
2279 NumVDataDwords, NumVAddrDwords);
2282 NumVDataDwords, NumVAddrDwords);
2292 const bool Is64 = MRI->getType(VDataOut).getSizeInBits() == 64;
2294 Register TmpReg = MRI->createVirtualRegister(
2295 Is64 ? &AMDGPU::VReg_128RegClass : &AMDGPU::VReg_64RegClass);
2296 unsigned SubReg = Is64 ? AMDGPU::sub0_sub1 : AMDGPU::sub0;
2299 if (!MRI->use_empty(VDataOut)) {
2301 .
addReg(TmpReg, {}, SubReg);
2312 for (
int I = 0;
I != NumVAddrRegs; ++
I) {
2313 MachineOperand &SrcOp =
MI.getOperand(ArgOffset + Intr->
VAddrStart +
I);
2314 if (SrcOp.
isReg()) {
2333 STI.hasFeature(AMDGPU::FeatureR128A16) ? -1 : 0);
2335 MIB.
addImm(IsA16 ? -1 : 0);
2337 if (!Subtarget->hasGFX90AInsts()) {
2349 MIB.
addImm(IsD16 ? -1 : 0);
2351 MI.eraseFromParent();
2353 TII.enforceOperandRCAlignment(*MIB, AMDGPU::OpName::vaddr);
2359bool AMDGPUInstructionSelector::selectDSBvhStackIntrinsic(
2370 unsigned Offset =
MI.getOperand(6).getImm();
2374 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
2375 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
2376 Opc = AMDGPU::DS_BVH_STACK_RTN_B32;
2378 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
2379 Opc = AMDGPU::DS_BVH_STACK_PUSH8_POP1_RTN_B32;
2381 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn:
2382 Opc = AMDGPU::DS_BVH_STACK_PUSH8_POP2_RTN_B64;
2394 MI.eraseFromParent();
2399bool AMDGPUInstructionSelector::selectG_INTRINSIC_W_SIDE_EFFECTS(
2402 switch (IntrinsicID) {
2403 case Intrinsic::amdgcn_end_cf:
2404 return selectEndCfIntrinsic(
I);
2405 case Intrinsic::amdgcn_ds_ordered_add:
2406 case Intrinsic::amdgcn_ds_ordered_swap:
2407 return selectDSOrderedIntrinsic(
I, IntrinsicID);
2408 case Intrinsic::amdgcn_ds_gws_init:
2409 case Intrinsic::amdgcn_ds_gws_barrier:
2410 case Intrinsic::amdgcn_ds_gws_sema_v:
2411 case Intrinsic::amdgcn_ds_gws_sema_br:
2412 case Intrinsic::amdgcn_ds_gws_sema_p:
2413 case Intrinsic::amdgcn_ds_gws_sema_release_all:
2414 return selectDSGWSIntrinsic(
I, IntrinsicID);
2415 case Intrinsic::amdgcn_ds_append:
2416 return selectDSAppendConsume(
I,
true);
2417 case Intrinsic::amdgcn_ds_consume:
2418 return selectDSAppendConsume(
I,
false);
2419 case Intrinsic::amdgcn_init_whole_wave:
2420 return selectInitWholeWave(
I);
2421 case Intrinsic::amdgcn_raw_buffer_load_lds:
2422 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
2423 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
2424 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
2425 case Intrinsic::amdgcn_struct_buffer_load_lds:
2426 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
2427 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
2428 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
2429 return selectBufferLoadLds(
I);
2434 case Intrinsic::amdgcn_load_to_lds:
2435 case Intrinsic::amdgcn_load_async_to_lds:
2436 case Intrinsic::amdgcn_global_load_lds:
2437 case Intrinsic::amdgcn_global_load_async_lds:
2438 return selectGlobalLoadLds(
I);
2439 case Intrinsic::amdgcn_tensor_load_to_lds:
2440 case Intrinsic::amdgcn_tensor_store_from_lds:
2441 return selectTensorLoadStore(
I, IntrinsicID);
2442 case Intrinsic::amdgcn_asyncmark:
2443 case Intrinsic::amdgcn_wait_asyncmark:
2444 if (!Subtarget->hasAsyncMark())
2447 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
2448 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
2449 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
2450 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn:
2451 return selectDSBvhStackIntrinsic(
I);
2452 case Intrinsic::amdgcn_s_alloc_vgpr: {
2458 Register ResReg =
I.getOperand(0).getReg();
2460 MachineInstr *AllocMI =
BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::S_ALLOC_VGPR))
2461 .
add(
I.getOperand(2));
2464 I.eraseFromParent();
2466 return RBI.constrainGenericRegister(ResReg, AMDGPU::SReg_32RegClass, *MRI);
2468 case Intrinsic::amdgcn_s_barrier_init:
2469 case Intrinsic::amdgcn_s_barrier_signal_var:
2470 return selectNamedBarrierInit(
I, IntrinsicID);
2471 case Intrinsic::amdgcn_s_wakeup_barrier:
2472 case Intrinsic::amdgcn_s_barrier_join:
2473 case Intrinsic::amdgcn_s_get_named_barrier_state:
2474 return selectNamedBarrierInst(
I, IntrinsicID);
2475 case Intrinsic::amdgcn_s_get_barrier_state:
2476 return selectSGetBarrierState(
I, IntrinsicID);
2477 case Intrinsic::amdgcn_s_barrier_signal_isfirst:
2478 return selectSBarrierSignalIsfirst(
I, IntrinsicID);
2483bool AMDGPUInstructionSelector::selectG_SELECT(
MachineInstr &
I)
const {
2490 Register DstReg =
I.getOperand(0).getReg();
2491 unsigned Size = RBI.getSizeInBits(DstReg, *MRI, TRI);
2493 const MachineOperand &CCOp =
I.getOperand(1);
2495 if (!isVCC(CCReg, *MRI)) {
2496 unsigned SelectOpcode =
Size == 64 ? AMDGPU::S_CSELECT_B64 :
2497 AMDGPU::S_CSELECT_B32;
2498 MachineInstr *CopySCC =
BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::SCC)
2504 if (!MRI->getRegClassOrNull(CCReg))
2505 MRI->setRegClass(CCReg, TRI.getConstrainedRegClassForReg(CCReg, *MRI));
2507 .
add(
I.getOperand(2))
2508 .
add(
I.getOperand(3));
2512 I.eraseFromParent();
2521 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
2523 .
add(
I.getOperand(3))
2525 .
add(
I.getOperand(2))
2526 .
add(
I.getOperand(1));
2529 I.eraseFromParent();
2533bool AMDGPUInstructionSelector::selectG_TRUNC(
MachineInstr &
I)
const {
2534 Register DstReg =
I.getOperand(0).getReg();
2535 Register SrcReg =
I.getOperand(1).getReg();
2536 const LLT DstTy = MRI->getType(DstReg);
2537 const LLT SrcTy = MRI->getType(SrcReg);
2540 const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
2541 const RegisterBank *DstRB;
2547 DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
2552 const bool IsVALU = DstRB->
getID() == AMDGPU::VGPRRegBankID;
2558 TRI.getRegClassForSizeOnBank(SrcSize, *SrcRB);
2560 TRI.getRegClassForSizeOnBank(DstSize, *DstRB);
2561 if (!SrcRC || !DstRC)
2564 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
2565 !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI)) {
2570 if (DstRC == &AMDGPU::VGPR_16RegClass && SrcSize == 32) {
2571 assert(STI.useRealTrue16Insts());
2575 .
addReg(SrcReg, {}, AMDGPU::lo16);
2576 I.eraseFromParent();
2584 Register LoReg = MRI->createVirtualRegister(DstRC);
2585 Register HiReg = MRI->createVirtualRegister(DstRC);
2587 .
addReg(SrcReg, {}, AMDGPU::sub0);
2589 .
addReg(SrcReg, {}, AMDGPU::sub1);
2591 if (IsVALU && STI.hasSDWA()) {
2594 MachineInstr *MovSDWA =
2595 BuildMI(*
MBB,
I,
DL, TII.get(AMDGPU::V_MOV_B32_sdwa), DstReg)
2605 Register TmpReg0 = MRI->createVirtualRegister(DstRC);
2606 Register TmpReg1 = MRI->createVirtualRegister(DstRC);
2607 Register ImmReg = MRI->createVirtualRegister(DstRC);
2609 BuildMI(*
MBB,
I,
DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), TmpReg0)
2619 unsigned MovOpc = IsVALU ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32;
2620 unsigned AndOpc = IsVALU ? AMDGPU::V_AND_B32_e64 : AMDGPU::S_AND_B32;
2621 unsigned OrOpc = IsVALU ? AMDGPU::V_OR_B32_e64 : AMDGPU::S_OR_B32;
2633 And.setOperandDead(3);
2634 Or.setOperandDead(3);
2638 I.eraseFromParent();
2646 unsigned SubRegIdx = DstSize < 32
2647 ?
static_cast<unsigned>(AMDGPU::sub0)
2648 : TRI.getSubRegFromChannel(0, DstSize / 32);
2649 if (SubRegIdx == AMDGPU::NoSubRegister)
2655 = TRI.getSubClassWithSubReg(SrcRC, SubRegIdx);
2659 if (SrcWithSubRC != SrcRC) {
2660 if (!RBI.constrainGenericRegister(SrcReg, *SrcWithSubRC, *MRI))
2664 I.getOperand(1).setSubReg(SubRegIdx);
2667 I.setDesc(TII.get(TargetOpcode::COPY));
2674 int SignedMask =
static_cast<int>(Mask);
2675 return SignedMask >= -16 && SignedMask <= 64;
2679const RegisterBank *AMDGPUInstructionSelector::getArtifactRegBank(
2688 return &RBI.getRegBankFromRegClass(*RC, LLT());
2692bool AMDGPUInstructionSelector::selectG_SZA_EXT(
MachineInstr &
I)
const {
2693 bool InReg =
I.getOpcode() == AMDGPU::G_SEXT_INREG;
2694 bool Signed =
I.getOpcode() == AMDGPU::G_SEXT || InReg;
2697 const Register DstReg =
I.getOperand(0).getReg();
2698 const Register SrcReg =
I.getOperand(1).getReg();
2700 const LLT DstTy = MRI->getType(DstReg);
2701 const LLT SrcTy = MRI->getType(SrcReg);
2702 const unsigned SrcSize =
I.getOpcode() == AMDGPU::G_SEXT_INREG ?
2709 const RegisterBank *SrcBank = getArtifactRegBank(SrcReg, *MRI, TRI);
2712 if (
I.getOpcode() == AMDGPU::G_ANYEXT) {
2714 return selectCOPY(
I);
2717 TRI.getRegClassForTypeOnBank(SrcTy, *SrcBank);
2718 const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
2720 TRI.getRegClassForSizeOnBank(DstSize, *DstBank);
2722 Register UndefReg = MRI->createVirtualRegister(SrcRC);
2723 BuildMI(
MBB,
I,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefReg);
2729 I.eraseFromParent();
2731 return RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) &&
2732 RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI);
2735 if (SrcBank->
getID() == AMDGPU::VGPRRegBankID && DstSize <= 32) {
2741 MachineInstr *ExtI =
2745 I.eraseFromParent();
2750 const unsigned BFE =
Signed ? AMDGPU::V_BFE_I32_e64 : AMDGPU::V_BFE_U32_e64;
2751 MachineInstr *ExtI =
2756 I.eraseFromParent();
2761 if (SrcBank->
getID() == AMDGPU::SGPRRegBankID && DstSize <= 64) {
2763 AMDGPU::SReg_64RegClass : AMDGPU::SReg_32RegClass;
2764 if (!RBI.constrainGenericRegister(SrcReg, SrcRC, *MRI))
2767 if (
Signed && DstSize == 32 && (SrcSize == 8 || SrcSize == 16)) {
2768 const unsigned SextOpc = SrcSize == 8 ?
2769 AMDGPU::S_SEXT_I32_I8 : AMDGPU::S_SEXT_I32_I16;
2772 I.eraseFromParent();
2773 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_32RegClass, *MRI);
2778 if (DstSize > 32 && SrcSize == 32) {
2779 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2780 unsigned SubReg = InReg ? AMDGPU::sub0 : AMDGPU::NoSubRegister;
2783 .
addReg(SrcReg, {}, SubReg)
2791 .
addReg(SrcReg, {}, SubReg)
2792 .addImm(AMDGPU::sub0)
2795 I.eraseFromParent();
2796 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_64RegClass,
2800 const unsigned BFE64 =
Signed ? AMDGPU::S_BFE_I64 : AMDGPU::S_BFE_U64;
2801 const unsigned BFE32 =
Signed ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32;
2804 if (DstSize > 32 && (SrcSize <= 32 || InReg)) {
2806 Register ExtReg = MRI->createVirtualRegister(&AMDGPU::SReg_64RegClass);
2807 Register UndefReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2808 unsigned SubReg = InReg ? AMDGPU::sub0 : AMDGPU::NoSubRegister;
2810 BuildMI(
MBB,
I,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefReg);
2812 .
addReg(SrcReg, {}, SubReg)
2813 .addImm(AMDGPU::sub0)
2821 I.eraseFromParent();
2822 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_64RegClass, *MRI);
2837 I.eraseFromParent();
2838 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_32RegClass, *MRI);
2890 assert(Mask.size() == 2);
2892 if (Mask[0] == 1 && Mask[1] <= 1) {
2907 if (Unmerge->getNumDefs() == 2 && Unmerge->getOperand(0).getReg() == In &&
2925bool AMDGPUInstructionSelector::selectG_FPEXT(
MachineInstr &
I)
const {
2926 if (!Subtarget->hasSALUFloatInsts())
2929 Register Dst =
I.getOperand(0).getReg();
2930 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
2931 if (DstRB->
getID() != AMDGPU::SGPRRegBankID)
2934 Register Src =
I.getOperand(1).getReg();
2940 BuildMI(*BB, &
I,
I.getDebugLoc(), TII.get(AMDGPU::S_CVT_HI_F32_F16), Dst)
2942 I.eraseFromParent();
2943 return RBI.constrainGenericRegister(Dst, AMDGPU::SReg_32RegClass, *MRI);
2950bool AMDGPUInstructionSelector::selectG_FNEG(
MachineInstr &
MI)
const {
2963 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
2964 if (DstRB->
getID() != AMDGPU::SGPRRegBankID ||
2969 MachineInstr *Fabs =
getOpcodeDef(TargetOpcode::G_FABS, Src, *MRI);
2973 if (!RBI.constrainGenericRegister(Src, AMDGPU::SReg_64RegClass, *MRI) ||
2974 !RBI.constrainGenericRegister(Dst, AMDGPU::SReg_64RegClass, *MRI))
2979 Register LoReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2980 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2981 Register ConstReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2982 Register OpReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2984 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), LoReg)
2985 .
addReg(Src, {}, AMDGPU::sub0);
2986 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), HiReg)
2987 .
addReg(Src, {}, AMDGPU::sub1);
2988 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_MOV_B32), ConstReg)
2992 unsigned Opc = Fabs ? AMDGPU::S_OR_B32 : AMDGPU::S_XOR_B32;
2997 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::REG_SEQUENCE), Dst)
3002 MI.eraseFromParent();
3007bool AMDGPUInstructionSelector::selectG_FABS(
MachineInstr &
MI)
const {
3009 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
3010 if (DstRB->
getID() != AMDGPU::SGPRRegBankID ||
3017 Register LoReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3018 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3019 Register ConstReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3020 Register OpReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3022 if (!RBI.constrainGenericRegister(Src, AMDGPU::SReg_64RegClass, *MRI) ||
3023 !RBI.constrainGenericRegister(Dst, AMDGPU::SReg_64RegClass, *MRI))
3026 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), LoReg)
3027 .
addReg(Src, {}, AMDGPU::sub0);
3028 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), HiReg)
3029 .
addReg(Src, {}, AMDGPU::sub1);
3030 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_MOV_B32), ConstReg)
3035 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_AND_B32), OpReg)
3039 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::REG_SEQUENCE), Dst)
3045 MI.eraseFromParent();
3050 return MI.getOpcode() == TargetOpcode::G_CONSTANT;
3056 unsigned OpNo =
Load.getOpcode() == AMDGPU::G_PREFETCH ? 0 : 1;
3057 const MachineInstr *PtrMI =
3058 MRI.getUniqueVRegDef(
Load.getOperand(OpNo).getReg());
3062 if (PtrMI->
getOpcode() != TargetOpcode::G_PTR_ADD)
3067 for (
unsigned i = 1; i != 3; ++i) {
3068 const MachineOperand &GEPOp = PtrMI->
getOperand(i);
3069 const MachineInstr *OpDef = MRI.getUniqueVRegDef(GEPOp.
getReg());
3074 assert(GEPInfo.Imm == 0);
3078 const RegisterBank *OpBank = RBI.getRegBank(GEPOp.
getReg(), MRI, TRI);
3079 if (OpBank->
getID() == AMDGPU::SGPRRegBankID)
3080 GEPInfo.SgprParts.push_back(GEPOp.
getReg());
3082 GEPInfo.VgprParts.push_back(GEPOp.
getReg());
3086 getAddrModeInfo(*PtrMI, MRI, AddrInfo);
3089bool AMDGPUInstructionSelector::isSGPR(
Register Reg)
const {
3090 return RBI.getRegBank(
Reg, *MRI, TRI)->getID() == AMDGPU::SGPRRegBankID;
3093bool AMDGPUInstructionSelector::isInstrUniform(
const MachineInstr &
MI)
const {
3094 if (!
MI.hasOneMemOperand())
3097 const MachineMemOperand *MMO = *
MI.memoperands_begin();
3110 if (
MI.getOpcode() == AMDGPU::G_PREFETCH)
3111 return RBI.getRegBank(
MI.getOperand(0).getReg(), *MRI, TRI)->getID() ==
3112 AMDGPU::SGPRRegBankID;
3115 return I &&
I->getMetadata(
"amdgpu.uniform");
3119 for (
const GEPInfo &GEPInfo : AddrInfo) {
3120 if (!GEPInfo.VgprParts.empty())
3126void AMDGPUInstructionSelector::initM0(
MachineInstr &
I)
const {
3127 const LLT PtrTy = MRI->getType(
I.getOperand(1).getReg());
3130 STI.ldsRequiresM0Init()) {
3134 BuildMI(*BB, &
I,
I.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), AMDGPU::M0)
3139bool AMDGPUInstructionSelector::selectG_LOAD_STORE_ATOMICRMW(
3146 if (
Reg.isPhysical())
3150 const unsigned Opcode =
MI.getOpcode();
3152 if (Opcode == AMDGPU::COPY)
3155 if (Opcode == AMDGPU::G_AND || Opcode == AMDGPU::G_OR ||
3156 Opcode == AMDGPU::G_XOR)
3161 return GI->is(Intrinsic::amdgcn_class);
3163 return Opcode == AMDGPU::G_ICMP || Opcode == AMDGPU::G_FCMP;
3166bool AMDGPUInstructionSelector::selectG_BRCOND(
MachineInstr &
I)
const {
3168 MachineOperand &CondOp =
I.getOperand(0);
3181 if (!isVCC(CondReg, *MRI)) {
3185 CondPhysReg = AMDGPU::SCC;
3186 BrOpcode = AMDGPU::S_CBRANCH_SCC1;
3187 ConstrainRC = &AMDGPU::SReg_32RegClass;
3194 const bool Is64 = STI.isWave64();
3195 const unsigned Opcode = Is64 ? AMDGPU::S_AND_B64 : AMDGPU::S_AND_B32;
3196 const Register Exec = Is64 ? AMDGPU::EXEC : AMDGPU::EXEC_LO;
3198 Register TmpReg = MRI->createVirtualRegister(TRI.getBoolRC());
3199 BuildMI(*BB, &
I,
DL, TII.get(Opcode), TmpReg)
3206 CondPhysReg = TRI.getVCC();
3207 BrOpcode = AMDGPU::S_CBRANCH_VCCNZ;
3208 ConstrainRC = TRI.getBoolRC();
3211 if (!MRI->getRegClassOrNull(CondReg))
3212 MRI->setRegClass(CondReg, ConstrainRC);
3214 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), CondPhysReg)
3217 .
addMBB(
I.getOperand(1).getMBB());
3219 I.eraseFromParent();
3223bool AMDGPUInstructionSelector::selectG_GLOBAL_VALUE(
3225 Register DstReg =
I.getOperand(0).getReg();
3226 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3227 const bool IsVGPR = DstRB->
getID() == AMDGPU::VGPRRegBankID;
3228 I.setDesc(TII.get(IsVGPR ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32));
3232 return RBI.constrainGenericRegister(
3233 DstReg, IsVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass, *MRI);
3236bool AMDGPUInstructionSelector::selectG_PTRMASK(
MachineInstr &
I)
const {
3237 Register DstReg =
I.getOperand(0).getReg();
3238 Register SrcReg =
I.getOperand(1).getReg();
3239 Register MaskReg =
I.getOperand(2).getReg();
3240 LLT Ty = MRI->getType(DstReg);
3241 LLT MaskTy = MRI->getType(MaskReg);
3245 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3246 const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
3247 const RegisterBank *MaskRB = RBI.getRegBank(MaskReg, *MRI, TRI);
3248 const bool IsVGPR = DstRB->
getID() == AMDGPU::VGPRRegBankID;
3254 APInt MaskOnes =
VT->getKnownOnes(MaskReg).zext(64);
3258 const bool CanCopyLow32 = (MaskOnes & MaskLo32) == MaskLo32;
3259 const bool CanCopyHi32 = (MaskOnes & MaskHi32) == MaskHi32;
3262 !CanCopyLow32 && !CanCopyHi32) {
3263 auto MIB =
BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_AND_B64), DstReg)
3267 I.eraseFromParent();
3272 unsigned NewOpc = IsVGPR ? AMDGPU::V_AND_B32_e64 : AMDGPU::S_AND_B32;
3274 = IsVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
3279 TRI.getRegClassForTypeOnBank(MaskTy, *MaskRB);
3281 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
3282 !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
3283 !RBI.constrainGenericRegister(MaskReg, *MaskRC, *MRI))
3288 "ptrmask should have been narrowed during legalize");
3290 auto NewOp =
BuildMI(*BB, &
I,
DL, TII.get(NewOpc), DstReg)
3296 I.eraseFromParent();
3300 Register HiReg = MRI->createVirtualRegister(&RegRC);
3301 Register LoReg = MRI->createVirtualRegister(&RegRC);
3304 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), LoReg)
3305 .
addReg(SrcReg, {}, AMDGPU::sub0);
3306 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), HiReg)
3307 .
addReg(SrcReg, {}, AMDGPU::sub1);
3316 Register MaskLo = MRI->createVirtualRegister(&RegRC);
3317 MaskedLo = MRI->createVirtualRegister(&RegRC);
3319 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), MaskLo)
3320 .
addReg(MaskReg, {}, AMDGPU::sub0);
3321 BuildMI(*BB, &
I,
DL, TII.get(NewOpc), MaskedLo)
3330 Register MaskHi = MRI->createVirtualRegister(&RegRC);
3331 MaskedHi = MRI->createVirtualRegister(&RegRC);
3333 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), MaskHi)
3334 .
addReg(MaskReg, {}, AMDGPU::sub1);
3335 BuildMI(*BB, &
I,
DL, TII.get(NewOpc), MaskedHi)
3340 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
3345 I.eraseFromParent();
3351static std::pair<Register, unsigned>
3358 std::tie(IdxBaseReg,
Offset) =
3360 if (IdxBaseReg == AMDGPU::NoRegister) {
3364 IdxBaseReg = IdxReg;
3371 if (
static_cast<unsigned>(
Offset) >= SubRegs.
size())
3372 return std::pair(IdxReg, SubRegs[0]);
3373 return std::pair(IdxBaseReg, SubRegs[
Offset]);
3376bool AMDGPUInstructionSelector::selectG_EXTRACT_VECTOR_ELT(
3382 LLT DstTy = MRI->getType(DstReg);
3383 LLT SrcTy = MRI->getType(SrcReg);
3385 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3386 const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
3387 const RegisterBank *IdxRB = RBI.getRegBank(IdxReg, *MRI, TRI);
3391 if (IdxRB->
getID() != AMDGPU::SGPRRegBankID)
3395 TRI.getRegClassForTypeOnBank(SrcTy, *SrcRB);
3397 TRI.getRegClassForTypeOnBank(DstTy, *DstRB);
3398 if (!SrcRC || !DstRC)
3400 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
3401 !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
3402 !RBI.constrainGenericRegister(IdxReg, AMDGPU::SReg_32RegClass, *MRI))
3413 if (SrcRB->
getID() == AMDGPU::SGPRRegBankID) {
3417 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3420 unsigned Opc = Is64 ? AMDGPU::S_MOVRELS_B64 : AMDGPU::S_MOVRELS_B32;
3422 .
addReg(SrcReg, {}, SubReg)
3424 MI.eraseFromParent();
3431 if (!STI.useVGPRIndexMode()) {
3432 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3434 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::V_MOVRELS_B32_e32), DstReg)
3435 .
addReg(SrcReg, {}, SubReg)
3437 MI.eraseFromParent();
3441 const MCInstrDesc &GPRIDXDesc =
3442 TII.getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*SrcRC),
true);
3448 MI.eraseFromParent();
3453bool AMDGPUInstructionSelector::selectG_INSERT_VECTOR_ELT(
3460 LLT VecTy = MRI->getType(DstReg);
3461 LLT ValTy = MRI->getType(ValReg);
3465 const RegisterBank *VecRB = RBI.getRegBank(VecReg, *MRI, TRI);
3466 const RegisterBank *ValRB = RBI.getRegBank(ValReg, *MRI, TRI);
3467 const RegisterBank *IdxRB = RBI.getRegBank(IdxReg, *MRI, TRI);
3473 if (IdxRB->
getID() != AMDGPU::SGPRRegBankID)
3477 TRI.getRegClassForTypeOnBank(VecTy, *VecRB);
3479 TRI.getRegClassForTypeOnBank(ValTy, *ValRB);
3481 if (!RBI.constrainGenericRegister(VecReg, *VecRC, *MRI) ||
3482 !RBI.constrainGenericRegister(DstReg, *VecRC, *MRI) ||
3483 !RBI.constrainGenericRegister(ValReg, *ValRC, *MRI) ||
3484 !RBI.constrainGenericRegister(IdxReg, AMDGPU::SReg_32RegClass, *MRI))
3487 if (VecRB->
getID() == AMDGPU::VGPRRegBankID && ValSize != 32)
3491 std::tie(IdxReg, SubReg) =
3494 const bool IndexMode = VecRB->
getID() == AMDGPU::VGPRRegBankID &&
3495 STI.useVGPRIndexMode();
3501 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3504 const MCInstrDesc &RegWriteOp = TII.getIndirectRegWriteMovRelPseudo(
3505 VecSize, ValSize, VecRB->
getID() == AMDGPU::SGPRRegBankID);
3510 MI.eraseFromParent();
3514 const MCInstrDesc &GPRIDXDesc =
3515 TII.getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC),
false);
3522 MI.eraseFromParent();
3528 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
3529 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
3530 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
3531 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
3532 case Intrinsic::amdgcn_load_async_to_lds:
3533 case Intrinsic::amdgcn_global_load_async_lds:
3539bool AMDGPUInstructionSelector::selectBufferLoadLds(
MachineInstr &
MI)
const {
3540 if (!Subtarget->hasVMemToLDSLoad())
3543 unsigned Size =
MI.getOperand(3).getImm();
3547 const bool HasVIndex =
MI.getNumOperands() == 9;
3551 VIndex =
MI.getOperand(4).getReg();
3555 Register VOffset =
MI.getOperand(4 + OpOffset).getReg();
3556 std::optional<ValueAndVReg> MaybeVOffset =
3558 const bool HasVOffset = !MaybeVOffset || MaybeVOffset->Value.getZExtValue();
3564 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_BOTHEN
3565 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_IDXEN
3566 : HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFEN
3567 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFSET;
3570 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_BOTHEN
3571 : AMDGPU::BUFFER_LOAD_USHORT_LDS_IDXEN
3572 : HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFEN
3573 : AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFSET;
3576 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_BOTHEN
3577 : AMDGPU::BUFFER_LOAD_DWORD_LDS_IDXEN
3578 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFEN
3579 : AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFSET;
3582 if (!Subtarget->hasLDSLoadB96_B128())
3585 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_BOTHEN
3586 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_IDXEN
3587 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFEN
3588 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFSET;
3591 if (!Subtarget->hasLDSLoadB96_B128())
3594 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_BOTHEN
3595 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_IDXEN
3596 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFEN
3597 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFSET;
3604 .
add(
MI.getOperand(2));
3608 if (HasVIndex && HasVOffset) {
3609 Register IdxReg = MRI->createVirtualRegister(TRI.getVGPR64Class());
3610 BuildMI(*
MBB, &*MIB,
DL, TII.get(AMDGPU::REG_SEQUENCE), IdxReg)
3617 }
else if (HasVIndex) {
3619 }
else if (HasVOffset) {
3623 MIB.
add(
MI.getOperand(1));
3624 MIB.
add(
MI.getOperand(5 + OpOffset));
3625 MIB.
add(
MI.getOperand(6 + OpOffset));
3627 unsigned Aux =
MI.getOperand(7 + OpOffset).getImm();
3636 MachineMemOperand *LoadMMO = *
MI.memoperands_begin();
3641 MachinePointerInfo StorePtrI = LoadPtrI;
3652 MachineMemOperand *StoreMMO =
3658 MI.eraseFromParent();
3671 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3677 return Def->getOperand(1).getReg();
3691 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3699 return Def->getOperand(1).getReg();
3702 if (ZextSrc &&
VT->signBitIsZero(ZextSrc))
3711AMDGPUInstructionSelector::matchZeroExtendFromS32OrS32(
Register Reg)
const {
3713 : matchZeroExtendFromS32(
Reg);
3719AMDGPUInstructionSelector::matchSignExtendFromS32OrS32(
Register Reg)
const {
3721 : matchSignExtendFromS32(
Reg);
3725AMDGPUInstructionSelector::matchExtendFromS32OrS32(
Register Reg,
3726 bool IsSigned)
const {
3728 return matchSignExtendFromS32OrS32(
Reg);
3730 return matchZeroExtendFromS32OrS32(
Reg);
3740 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3747 return Def->getOperand(1).getReg();
3752bool AMDGPUInstructionSelector::selectGlobalLoadLds(
MachineInstr &
MI)
const{
3753 if (!Subtarget->hasVMemToLDSLoad())
3757 unsigned Size =
MI.getOperand(3).getImm();
3764 Opc = AMDGPU::GLOBAL_LOAD_LDS_UBYTE;
3767 Opc = AMDGPU::GLOBAL_LOAD_LDS_USHORT;
3770 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORD;
3773 if (!Subtarget->hasLDSLoadB96_B128())
3775 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX3;
3778 if (!Subtarget->hasLDSLoadB96_B128())
3780 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX4;
3787 .
add(
MI.getOperand(2));
3793 if (!isSGPR(Addr)) {
3795 if (isSGPR(AddrDef->Reg)) {
3796 Addr = AddrDef->Reg;
3797 }
else if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
3800 if (isSGPR(SAddr)) {
3801 Register PtrBaseOffset = AddrDef->MI->getOperand(2).getReg();
3802 if (
Register Off = matchZeroExtendFromS32(PtrBaseOffset)) {
3813 VOffset = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
3825 MIB.
add(
MI.getOperand(4));
3827 unsigned Aux =
MI.getOperand(5).getImm();
3831 MachineMemOperand *LoadMMO = *
MI.memoperands_begin();
3833 LoadPtrI.
Offset =
MI.getOperand(4).getImm();
3834 MachinePointerInfo StorePtrI = LoadPtrI;
3843 MachineMemOperand *StoreMMO =
3845 sizeof(int32_t),
Align(4));
3849 MI.eraseFromParent();
3854bool AMDGPUInstructionSelector::selectTensorLoadStore(
MachineInstr &
MI,
3856 bool IsLoad = IID == Intrinsic::amdgcn_tensor_load_to_lds;
3858 IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d4 : AMDGPU::TENSOR_STORE_FROM_LDS_d4;
3862 const auto isAllZeros = [&](MachineOperand &Opnd) {
3863 const MachineInstr *
DefMI = MRI->getVRegDef(Opnd.getReg());
3872 Opc = IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d2
3873 : AMDGPU::TENSOR_STORE_FROM_LDS_d2;
3880 .
add(
MI.getOperand(1))
3881 .
add(
MI.getOperand(2));
3883 if (NumGroups >= 4) {
3884 MIB.
add(
MI.getOperand(3))
3885 .
add(
MI.getOperand(4));
3889 .
add(
MI.getOperand(6));
3891 MI.eraseFromParent();
3895bool AMDGPUInstructionSelector::selectBVHIntersectRayIntrinsic(
3897 unsigned OpcodeOpIdx =
3898 MI.getOpcode() == AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY ? 1 : 3;
3899 MI.setDesc(TII.get(
MI.getOperand(OpcodeOpIdx).getImm()));
3900 MI.removeOperand(OpcodeOpIdx);
3901 MI.addImplicitDefUseOperands(*
MI.getMF());
3908bool AMDGPUInstructionSelector::selectSMFMACIntrin(
MachineInstr &
MI)
const {
3911 case Intrinsic::amdgcn_smfmac_f32_16x16x32_f16:
3912 Opc = AMDGPU::V_SMFMAC_F32_16X16X32_F16_e64;
3914 case Intrinsic::amdgcn_smfmac_f32_32x32x16_f16:
3915 Opc = AMDGPU::V_SMFMAC_F32_32X32X16_F16_e64;
3917 case Intrinsic::amdgcn_smfmac_f32_16x16x32_bf16:
3918 Opc = AMDGPU::V_SMFMAC_F32_16X16X32_BF16_e64;
3920 case Intrinsic::amdgcn_smfmac_f32_32x32x16_bf16:
3921 Opc = AMDGPU::V_SMFMAC_F32_32X32X16_BF16_e64;
3923 case Intrinsic::amdgcn_smfmac_i32_16x16x64_i8:
3924 Opc = AMDGPU::V_SMFMAC_I32_16X16X64_I8_e64;
3926 case Intrinsic::amdgcn_smfmac_i32_32x32x32_i8:
3927 Opc = AMDGPU::V_SMFMAC_I32_32X32X32_I8_e64;
3929 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_bf8:
3930 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF8_BF8_e64;
3932 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_fp8:
3933 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF8_FP8_e64;
3935 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_bf8:
3936 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_FP8_BF8_e64;
3938 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_fp8:
3939 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_FP8_FP8_e64;
3941 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_bf8:
3942 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF8_BF8_e64;
3944 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_fp8:
3945 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF8_FP8_e64;
3947 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_bf8:
3948 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_FP8_BF8_e64;
3950 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_fp8:
3951 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_FP8_FP8_e64;
3953 case Intrinsic::amdgcn_smfmac_f32_16x16x64_f16:
3954 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_F16_e64;
3956 case Intrinsic::amdgcn_smfmac_f32_32x32x32_f16:
3957 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_F16_e64;
3959 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf16:
3960 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF16_e64;
3962 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf16:
3963 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF16_e64;
3965 case Intrinsic::amdgcn_smfmac_i32_16x16x128_i8:
3966 Opc = AMDGPU::V_SMFMAC_I32_16X16X128_I8_e64;
3968 case Intrinsic::amdgcn_smfmac_i32_32x32x64_i8:
3969 Opc = AMDGPU::V_SMFMAC_I32_32X32X64_I8_e64;
3971 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_bf8:
3972 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_BF8_BF8_e64;
3974 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_fp8:
3975 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_BF8_FP8_e64;
3977 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_bf8:
3978 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_FP8_BF8_e64;
3980 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_fp8:
3981 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_FP8_FP8_e64;
3983 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_bf8:
3984 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_BF8_BF8_e64;
3986 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_fp8:
3987 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_BF8_FP8_e64;
3989 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_bf8:
3990 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_FP8_BF8_e64;
3992 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_fp8:
3993 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_FP8_FP8_e64;
3999 auto VDst_In =
MI.getOperand(4);
4001 MI.setDesc(TII.get(
Opc));
4002 MI.removeOperand(4);
4003 MI.removeOperand(1);
4004 MI.addOperand(VDst_In);
4005 MI.addImplicitDefUseOperands(*
MI.getMF());
4006 const MCInstrDesc &MCID =
MI.getDesc();
4008 MI.getOperand(0).setIsEarlyClobber(
true);
4013bool AMDGPUInstructionSelector::selectPermlaneSwapIntrin(
4015 if (IntrID == Intrinsic::amdgcn_permlane16_swap &&
4016 !Subtarget->hasPermlane16Swap())
4018 if (IntrID == Intrinsic::amdgcn_permlane32_swap &&
4019 !Subtarget->hasPermlane32Swap())
4022 unsigned Opcode = IntrID == Intrinsic::amdgcn_permlane16_swap
4023 ? AMDGPU::V_PERMLANE16_SWAP_B32_e64
4024 : AMDGPU::V_PERMLANE32_SWAP_B32_e64;
4026 MI.removeOperand(2);
4027 MI.setDesc(TII.get(Opcode));
4030 MachineOperand &FI =
MI.getOperand(4);
4037bool AMDGPUInstructionSelector::selectWaveAddress(
MachineInstr &
MI)
const {
4040 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4041 const bool IsVALU = DstRB->
getID() == AMDGPU::VGPRRegBankID;
4046 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHRREV_B32_e64), DstReg)
4047 .
addImm(Subtarget->getWavefrontSizeLog2())
4052 .
addImm(Subtarget->getWavefrontSizeLog2())
4057 IsVALU ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
4058 if (!RBI.constrainGenericRegister(DstReg, RC, *MRI))
4061 MI.eraseFromParent();
4065bool AMDGPUInstructionSelector::selectWaveShuffleIntrin(
4075 const LLT DstTy = MRI->getType(DstReg);
4077 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4079 TRI.getRegClassForSizeOnBank(DstSize, *DstRB);
4084 if (!Subtarget->supportsBPermute())
4088 if (Subtarget->supportsWaveWideBPermute()) {
4089 Register ShiftIdxReg = MRI->createVirtualRegister(DstRC);
4090 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), ShiftIdxReg)
4100 assert(Subtarget->isWave64());
4104 MRI->createVirtualRegister(TRI.getRegClass(AMDGPU::SReg_32RegClassID));
4105 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefValReg);
4107 Register UndefExecReg = MRI->createVirtualRegister(
4108 TRI.getRegClass(AMDGPU::SReg_64_XEXECRegClassID));
4109 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefExecReg);
4111 Register PoisonValReg = MRI->createVirtualRegister(DstRC);
4112 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_SET_INACTIVE_B32), PoisonValReg)
4120 Register ShiftIdxReg = MRI->createVirtualRegister(DstRC);
4121 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), ShiftIdxReg)
4125 Register PoisonIdxReg = MRI->createVirtualRegister(DstRC);
4126 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_SET_INACTIVE_B32), PoisonIdxReg)
4133 Register PoisonUnshiftedIdxReg = MRI->createVirtualRegister(DstRC);
4135 PoisonUnshiftedIdxReg)
4143 Register SameSidePermReg = MRI->createVirtualRegister(DstRC);
4144 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::DS_BPERMUTE_B32), SameSidePermReg)
4149 Register SwappedValReg = MRI->createVirtualRegister(DstRC);
4150 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_PERMLANE64_B32), SwappedValReg)
4153 Register OppSidePermReg = MRI->createVirtualRegister(DstRC);
4154 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::DS_BPERMUTE_B32), OppSidePermReg)
4159 Register WWMSwapPermReg = MRI->createVirtualRegister(DstRC);
4160 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::STRICT_WWM), WWMSwapPermReg)
4167 Register ThreadIDReg = MRI->createVirtualRegister(DstRC);
4168 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_MBCNT_LO_U32_B32_e64), ThreadIDReg)
4172 Register XORReg = MRI->createVirtualRegister(DstRC);
4175 .
addReg(PoisonUnshiftedIdxReg);
4177 Register ANDReg = MRI->createVirtualRegister(DstRC);
4182 Register CompareReg = MRI->createVirtualRegister(
4183 TRI.getRegClass(AMDGPU::SReg_64_XEXECRegClassID));
4184 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_CMP_EQ_U32_e64), CompareReg)
4189 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
4197 MI.eraseFromParent();
4206 unsigned NumOpcodes = 0;
4219 const uint8_t SrcBits[3] = { 0xf0, 0xcc, 0xaa };
4230 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4244 if (Src.size() == 3) {
4251 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4252 if (Src[
I] ==
LHS) {
4262 Bits = SrcBits[Src.size()];
4268 switch (
MI->getOpcode()) {
4269 case TargetOpcode::G_AND:
4270 case TargetOpcode::G_OR:
4271 case TargetOpcode::G_XOR: {
4276 if (!getOperandBits(
LHS, LHSBits) ||
4277 !getOperandBits(
RHS, RHSBits)) {
4278 Src = std::move(Backup);
4279 return std::make_pair(0, 0);
4300 uint8_t LHSBitsOrig = LHSBits;
4301 uint8_t RHSBitsOrig = RHSBits;
4305 NumOpcodes += LHSOp.first;
4306 LHSBits = LHSOp.second;
4313 NumOpcodes += RHSOp.first;
4314 RHSBits = RHSOp.second;
4318 auto dependsOnSlot = [](
uint8_t TT,
int Slot) ->
bool {
4319 if (Slot < 0 || Slot > 2)
4321 const uint8_t Masks[3] = {0x0f, 0x33, 0x55};
4322 const int Shifts[3] = {4, 2, 1};
4323 return ((TT ^ (TT >> Shifts[Slot])) & Masks[Slot]) != 0;
4329 const uint8_t SrcBitsConst[3] = {0xf0, 0xcc, 0xaa};
4336 for (
int I = 0;
I < (int)S.size();
I++) {
4337 if (Bits == SrcBitsConst[
I] && S[
I] ==
Op)
4339 if (IsNegationOp && Bits == (
uint8_t)~SrcBitsConst[
I] &&
4340 S[
I] == NegatedInner)
4351 for (
int I = 0;
I < (int)SrcAfterLHS.
size() &&
I < 3;
I++) {
4352 if (
I < (
int)Src.size() && Src[
I] != SrcAfterLHS[
I] &&
4353 dependsOnSlot(LHSBits,
I)) {
4362 if (!Stale && !RHSOp.first) {
4363 int Slot = findSlot(RHSBitsOrig,
RHS, SrcBeforeRecurse);
4365 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4371 if (!Stale && !LHSOp.first) {
4372 int Slot = findSlot(LHSBitsOrig,
LHS, SrcBeforeRecurse);
4374 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4379 Src = std::move(SrcBeforeRecurse);
4380 LHSBits = LHSBitsOrig;
4381 RHSBits = RHSBitsOrig;
4387 return std::make_pair(0, 0);
4391 switch (
MI->getOpcode()) {
4392 case TargetOpcode::G_AND:
4393 TTbl = LHSBits & RHSBits;
4395 case TargetOpcode::G_OR:
4396 TTbl = LHSBits | RHSBits;
4398 case TargetOpcode::G_XOR:
4399 TTbl = LHSBits ^ RHSBits;
4405 return std::make_pair(NumOpcodes + 1, TTbl);
4408bool AMDGPUInstructionSelector::selectBITOP3(
MachineInstr &
MI)
const {
4409 if (!Subtarget->hasBitOp3Insts())
4413 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4414 const bool IsVALU = DstRB->
getID() == AMDGPU::VGPRRegBankID;
4420 unsigned NumOpcodes;
4422 std::tie(NumOpcodes, TTbl) =
BitOp3_Op(DstReg, Src, *MRI);
4426 if (NumOpcodes < 2 || Src.empty())
4431 unsigned Size = MRI->getType(DstReg).getSizeInBits();
4432 assert((
Size == 16 ||
Size == 32) &&
"unexpected VALU logic op size");
4433 const bool IsB32 =
Size == 32;
4434 if (NumOpcodes == 2 && IsB32) {
4442 }
else if (NumOpcodes < 4) {
4449 unsigned Opc = IsB32 ? AMDGPU::V_BITOP3_B32_e64 : AMDGPU::V_BITOP3_B16_e64;
4450 if (!IsB32 && STI.hasTrue16BitInsts())
4451 Opc = STI.useRealTrue16Insts() ? AMDGPU::V_BITOP3_B16_gfx1250_t16_e64
4452 : AMDGPU::V_BITOP3_B16_gfx1250_fake16_e64;
4453 unsigned CBL = STI.getConstantBusLimit(
Opc);
4457 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4458 const RegisterBank *RB = RBI.getRegBank(Src[
I], *MRI, TRI);
4459 if (RB->
getID() != AMDGPU::SGPRRegBankID)
4465 Register NewReg = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
4476 while (Src.size() < 3)
4477 Src.push_back(Src[0]);
4494 MI.eraseFromParent();
4499bool AMDGPUInstructionSelector::selectWriteRegister(
MachineInstr &
MI)
const {
4500 const MDString *RegStr =
4503 LLT Ty = MRI->getType(SrcReg);
4505 Register PhysReg = Subtarget->getTargetLowering()->getRegisterByName(
4510 "invalid register \"" + Twine(RegStr->
getString()) +
4511 "\" for llvm.write_register",
4512 Fn,
MI.getDebugLoc()));
4513 MI.eraseFromParent();
4517 if (!RBI.constrainGenericRegister(
4518 SrcReg, *TRI.getSGPRClassForBitWidth(Ty.
getSizeInBits()), *MRI))
4521 BuildMI(*
MI.getParent(),
MI,
MI.getDebugLoc(), TII.get(AMDGPU::COPY), PhysReg)
4523 MI.eraseFromParent();
4527bool AMDGPUInstructionSelector::selectStackRestore(
MachineInstr &
MI)
const {
4529 if (!RBI.constrainGenericRegister(SrcReg, AMDGPU::SReg_32RegClass, *MRI))
4532 MachineInstr *
DefMI = MRI->getVRegDef(SrcReg);
4534 Subtarget->getTargetLowering()->getStackPointerRegisterToSaveRestore();
4540 WaveAddr = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
4543 .
addImm(Subtarget->getWavefrontSizeLog2())
4550 MI.eraseFromParent();
4556 if (!
I.isPreISelOpcode()) {
4558 return selectCOPY(
I);
4562 switch (
I.getOpcode()) {
4563 case TargetOpcode::G_AND:
4564 case TargetOpcode::G_OR:
4565 case TargetOpcode::G_XOR:
4566 if (selectBITOP3(
I))
4570 return selectG_AND_OR_XOR(
I);
4571 case TargetOpcode::G_ADD:
4572 case TargetOpcode::G_SUB:
4573 case TargetOpcode::G_PTR_ADD:
4576 return selectG_ADD_SUB(
I);
4577 case TargetOpcode::G_UADDO:
4578 case TargetOpcode::G_USUBO:
4579 case TargetOpcode::G_UADDE:
4580 case TargetOpcode::G_USUBE:
4581 return selectG_UADDO_USUBO_UADDE_USUBE(
I);
4582 case AMDGPU::G_AMDGPU_MAD_U64_U32:
4583 case AMDGPU::G_AMDGPU_MAD_I64_I32:
4584 return selectG_AMDGPU_MAD_64_32(
I);
4585 case TargetOpcode::G_INTTOPTR:
4586 case TargetOpcode::G_BITCAST:
4587 case TargetOpcode::G_PTRTOINT:
4588 case TargetOpcode::G_FREEZE:
4589 return selectCOPY(
I);
4590 case TargetOpcode::G_FNEG:
4593 return selectG_FNEG(
I);
4594 case TargetOpcode::G_FABS:
4597 return selectG_FABS(
I);
4598 case TargetOpcode::G_EXTRACT:
4599 return selectG_EXTRACT(
I);
4600 case TargetOpcode::G_MERGE_VALUES:
4601 case TargetOpcode::G_CONCAT_VECTORS:
4602 return selectG_MERGE_VALUES(
I);
4603 case TargetOpcode::G_UNMERGE_VALUES:
4604 return selectG_UNMERGE_VALUES(
I);
4605 case TargetOpcode::G_BUILD_VECTOR:
4606 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
4607 return selectG_BUILD_VECTOR(
I);
4608 case TargetOpcode::G_IMPLICIT_DEF:
4609 return selectG_IMPLICIT_DEF(
I);
4610 case TargetOpcode::G_INSERT:
4611 return selectG_INSERT(
I);
4612 case TargetOpcode::G_INTRINSIC:
4613 case TargetOpcode::G_INTRINSIC_CONVERGENT:
4614 return selectG_INTRINSIC(
I);
4615 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
4616 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
4617 return selectG_INTRINSIC_W_SIDE_EFFECTS(
I);
4618 case TargetOpcode::G_ICMP:
4619 case TargetOpcode::G_FCMP:
4620 if (selectG_ICMP_or_FCMP(
I))
4623 case TargetOpcode::G_LOAD:
4624 case TargetOpcode::G_ZEXTLOAD:
4625 case TargetOpcode::G_SEXTLOAD:
4626 case TargetOpcode::G_STORE:
4627 case TargetOpcode::G_ATOMIC_CMPXCHG:
4628 case TargetOpcode::G_ATOMICRMW_XCHG:
4629 case TargetOpcode::G_ATOMICRMW_ADD:
4630 case TargetOpcode::G_ATOMICRMW_SUB:
4631 case TargetOpcode::G_ATOMICRMW_AND:
4632 case TargetOpcode::G_ATOMICRMW_OR:
4633 case TargetOpcode::G_ATOMICRMW_XOR:
4634 case TargetOpcode::G_ATOMICRMW_MIN:
4635 case TargetOpcode::G_ATOMICRMW_MAX:
4636 case TargetOpcode::G_ATOMICRMW_UMIN:
4637 case TargetOpcode::G_ATOMICRMW_UMAX:
4638 case TargetOpcode::G_ATOMICRMW_UINC_WRAP:
4639 case TargetOpcode::G_ATOMICRMW_UDEC_WRAP:
4640 case TargetOpcode::G_ATOMICRMW_USUB_COND:
4641 case TargetOpcode::G_ATOMICRMW_USUB_SAT:
4642 case TargetOpcode::G_ATOMICRMW_FADD:
4643 case TargetOpcode::G_ATOMICRMW_FMIN:
4644 case TargetOpcode::G_ATOMICRMW_FMAX:
4645 return selectG_LOAD_STORE_ATOMICRMW(
I);
4646 case TargetOpcode::G_SELECT:
4647 return selectG_SELECT(
I);
4648 case TargetOpcode::G_TRUNC:
4649 return selectG_TRUNC(
I);
4650 case TargetOpcode::G_SEXT:
4651 case TargetOpcode::G_ZEXT:
4652 case TargetOpcode::G_ANYEXT:
4653 case TargetOpcode::G_SEXT_INREG:
4657 if (MRI->getType(
I.getOperand(1).getReg()) !=
LLT::scalar(1) &&
4660 return selectG_SZA_EXT(
I);
4661 case TargetOpcode::G_FPEXT:
4662 if (selectG_FPEXT(
I))
4665 case TargetOpcode::G_BRCOND:
4666 return selectG_BRCOND(
I);
4667 case TargetOpcode::G_GLOBAL_VALUE:
4668 return selectG_GLOBAL_VALUE(
I);
4669 case TargetOpcode::G_PTRMASK:
4670 return selectG_PTRMASK(
I);
4671 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4672 return selectG_EXTRACT_VECTOR_ELT(
I);
4673 case TargetOpcode::G_INSERT_VECTOR_ELT:
4674 return selectG_INSERT_VECTOR_ELT(
I);
4675 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD:
4676 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16:
4677 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET:
4678 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE:
4679 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16: {
4682 assert(Intr &&
"not an image intrinsic with image pseudo");
4683 return selectImageIntrinsic(
I, Intr);
4685 case AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY:
4686 case AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY:
4687 case AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY:
4688 return selectBVHIntersectRayIntrinsic(
I);
4689 case AMDGPU::G_SBFX:
4690 case AMDGPU::G_UBFX:
4691 return selectG_SBFX_UBFX(
I);
4692 case AMDGPU::G_SI_CALL:
4693 I.setDesc(TII.get(AMDGPU::SI_CALL));
4695 case AMDGPU::G_AMDGPU_WAVE_ADDRESS:
4696 return selectWaveAddress(
I);
4697 case AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_RETURN: {
4698 I.setDesc(TII.get(AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN));
4701 case AMDGPU::G_STACKRESTORE:
4702 return selectStackRestore(
I);
4703 case TargetOpcode::G_WRITE_REGISTER:
4704 return selectWriteRegister(
I);
4706 return selectPHI(
I);
4707 case AMDGPU::G_AMDGPU_COPY_SCC_VCC:
4708 return selectCOPY_SCC_VCC(
I);
4709 case AMDGPU::G_AMDGPU_COPY_VCC_SCC:
4710 return selectCOPY_VCC_SCC(
I);
4711 case AMDGPU::G_AMDGPU_READANYLANE:
4712 return selectReadAnyLane(
I);
4713 case TargetOpcode::G_CONSTANT:
4714 case TargetOpcode::G_FCONSTANT:
4722AMDGPUInstructionSelector::selectVCSRC(
MachineOperand &Root)
const {
4729std::pair<Register, unsigned> AMDGPUInstructionSelector::selectVOP3ModsImpl(
4730 Register Src,
bool IsCanonicalizing,
bool AllowAbs,
bool OpSel)
const {
4734 if (
MI->getOpcode() == AMDGPU::G_FNEG) {
4735 Src =
MI->getOperand(1).getReg();
4738 }
else if (
MI->getOpcode() == AMDGPU::G_FSUB && IsCanonicalizing) {
4743 if (
LHS &&
LHS->isZero()) {
4745 Src =
MI->getOperand(2).getReg();
4749 if (AllowAbs &&
MI->getOpcode() == AMDGPU::G_FABS) {
4750 Src =
MI->getOperand(1).getReg();
4757 return std::pair(Src, Mods);
4760std::pair<Register, unsigned>
4761AMDGPUInstructionSelector::selectVOP3PModsF32Impl(
Register Src)
const {
4763 std::tie(Src, Mods) = selectVOP3ModsImpl(Src);
4765 return std::pair(Src, Mods);
4768Register AMDGPUInstructionSelector::copyToVGPRIfSrcFolded(
4770 bool ForceVGPR)
const {
4771 if ((Mods != 0 || ForceVGPR) &&
4772 RBI.getRegBank(Src, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID) {
4779 TII.
get(AMDGPU::COPY), VGPRSrc)
4791AMDGPUInstructionSelector::widenSrcIfVGPR16(
Register Src,
4793 if (!Subtarget->useRealTrue16Insts() || MRI->getType(Src) !=
LLT::scalar(16))
4796 const RegisterBank *SrcRB = RBI.getRegBank(Src, *MRI, TRI);
4797 if (!SrcRB || SrcRB->
getID() != AMDGPU::VGPRRegBankID)
4800 MachineIRBuilder
B(*InsertPt);
4802 Register ImpDefReg = MRI->createVirtualRegister(&AMDGPU::VGPR_16RegClass);
4803 B.buildInstr(TargetOpcode::IMPLICIT_DEF).addDef(ImpDefReg);
4805 Register DstReg = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
4806 B.buildInstr(AMDGPU::REG_SEQUENCE)
4809 .addImm(AMDGPU::lo16)
4811 .addImm(AMDGPU::hi16);
4820AMDGPUInstructionSelector::selectVSRC0(
MachineOperand &Root)
const {
4822 [=](MachineInstrBuilder &MIB) { MIB.
add(Root); }
4827AMDGPUInstructionSelector::selectVOP3Mods0(
MachineOperand &Root)
const {
4830 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
4833 [=](MachineInstrBuilder &MIB) {
4834 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4836 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
4837 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4838 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4843AMDGPUInstructionSelector::selectVOP3BMods0(
MachineOperand &Root)
const {
4846 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
4851 [=](MachineInstrBuilder &MIB) {
4852 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4854 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
4855 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4856 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4861AMDGPUInstructionSelector::selectVOP3OMods(
MachineOperand &Root)
const {
4863 [=](MachineInstrBuilder &MIB) { MIB.
add(Root); },
4864 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4865 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4870AMDGPUInstructionSelector::selectVOP3Mods(
MachineOperand &Root)
const {
4873 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
4876 [=](MachineInstrBuilder &MIB) {
4877 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4879 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4884AMDGPUInstructionSelector::selectVOP3ModsNonCanonicalizing(
4888 std::tie(Src, Mods) =
4889 selectVOP3ModsImpl(Root.
getReg(),
false);
4892 [=](MachineInstrBuilder &MIB) {
4893 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4895 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4900AMDGPUInstructionSelector::selectVOP3BMods(
MachineOperand &Root)
const {
4903 std::tie(Src, Mods) =
4904 selectVOP3ModsImpl(Root.
getReg(),
true,
4908 [=](MachineInstrBuilder &MIB) {
4909 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4911 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4916AMDGPUInstructionSelector::selectVOP3NoMods(
MachineOperand &Root)
const {
4919 if (
Def->getOpcode() == AMDGPU::G_FNEG ||
Def->getOpcode() == AMDGPU::G_FABS)
4922 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
4947 if (
MI->getOpcode() != AMDGPU::G_TRUNC)
4952 return DstSize * 2 == SrcSize;
4958 if (
MI->getOpcode() != AMDGPU::G_LSHR)
4962 std::optional<ValueAndVReg> ShiftAmt;
4963 if (
mi_match(
MI->getOperand(0).getReg(), MRI,
4966 unsigned Shift = ShiftAmt->Value.getZExtValue();
4967 return Shift * 2 == SrcSize;
4975 if (
MI->getOpcode() != AMDGPU::G_SHL)
4979 std::optional<ValueAndVReg> ShiftAmt;
4980 if (
mi_match(
MI->getOperand(0).getReg(), MRI,
4983 unsigned Shift = ShiftAmt->Value.getZExtValue();
4984 return Shift * 2 == SrcSize;
4992 if (
MI->getOpcode() != AMDGPU::G_UNMERGE_VALUES)
4994 return MI->getNumOperands() == 3 &&
MI->getOperand(0).isDef() &&
4995 MI->getOperand(1).isDef() && !
MI->getOperand(2).isDef();
5003 if (
OpTy.isScalar())
5005 if (
OpTy.isVector() &&
OpTy.getNumElements() == 2)
5165static std::optional<std::pair<Register, SrcStatus>>
5170 unsigned Opc =
MI->getOpcode();
5174 case AMDGPU::G_BITCAST:
5175 return std::optional<std::pair<Register, SrcStatus>>(
5176 {
MI->getOperand(1).getReg(), Curr.second});
5178 if (
MI->getOperand(1).getReg().isPhysical())
5179 return std::nullopt;
5180 return std::optional<std::pair<Register, SrcStatus>>(
5181 {
MI->getOperand(1).getReg(), Curr.second});
5182 case AMDGPU::G_FNEG: {
5185 return std::nullopt;
5186 return std::optional<std::pair<Register, SrcStatus>>(
5187 {
MI->getOperand(1).getReg(), Stat});
5194 switch (Curr.second) {
5197 return std::optional<std::pair<Register, SrcStatus>>(
5200 if (Curr.first ==
MI->getOperand(0).getReg())
5201 return std::optional<std::pair<Register, SrcStatus>>(
5203 return std::optional<std::pair<Register, SrcStatus>>(
5215 return std::optional<std::pair<Register, SrcStatus>>(
5219 if (Curr.first ==
MI->getOperand(0).getReg())
5220 return std::optional<std::pair<Register, SrcStatus>>(
5222 return std::optional<std::pair<Register, SrcStatus>>(
5228 return std::optional<std::pair<Register, SrcStatus>>(
5233 return std::optional<std::pair<Register, SrcStatus>>(
5238 return std::optional<std::pair<Register, SrcStatus>>(
5243 return std::optional<std::pair<Register, SrcStatus>>(
5249 return std::nullopt;
5259 bool HasNeg =
false;
5261 bool HasOpsel =
true;
5266 unsigned Opc =
MI->getOpcode();
5268 if (
Opc == TargetOpcode::G_INTRINSIC) {
5271 if (IntrinsicID == Intrinsic::amdgcn_fdot2)
5298 while (
Depth <= MaxDepth && Curr.has_value()) {
5301 Statlist.push_back(Curr.value());
5308static std::pair<Register, SrcStatus>
5315 while (
Depth <= MaxDepth && Curr.has_value()) {
5321 LastSameOrNeg = Curr.value();
5326 return LastSameOrNeg;
5333 return Width1 == Width2;
5368 return isSameBitWidth(NewReg, RootReg, MRI) && IsHalfState(LoStat) &&
5369 IsHalfState(HiStat);
5372std::pair<Register, unsigned> AMDGPUInstructionSelector::selectVOP3PModsImpl(
5378 return {RootReg, Mods};
5381 SearchOptions SO(RootReg, MRI);
5394 if (MRI.getType(RootReg).getSizeInBits() == 128) {
5396 return {Stat.first, Mods};
5401 MI->getNumOperands() != 3 || (IsDOT && Subtarget->hasDOTOpSelHazard())) {
5403 return {Stat.first, Mods};
5409 if (StatlistHi.
empty()) {
5411 return {Stat.first, Mods};
5417 if (StatlistLo.
empty()) {
5419 return {Stat.first, Mods};
5422 for (
int I = StatlistHi.
size() - 1;
I >= 0;
I--) {
5423 for (
int J = StatlistLo.
size() - 1; J >= 0; J--) {
5424 if (StatlistHi[
I].first == StatlistLo[J].first &&
5426 StatlistHi[
I].first, RootReg, TII, MRI))
5427 return {StatlistHi[
I].first,
5428 updateMods(StatlistHi[
I].second, StatlistLo[J].second, Mods)};
5434 return {Stat.first, Mods};
5444 return RB->
getID() == RBNo;
5460 if (
checkRB(RootReg, AMDGPU::SGPRRegBankID, RBI, MRI,
TRI) ||
5461 checkRB(NewReg, AMDGPU::VGPRRegBankID, RBI, MRI,
TRI))
5471 TII.get(AMDGPU::COPY), DstReg)
5479AMDGPUInstructionSelector::selectVOP3PRetHelper(
MachineOperand &Root,
5484 std::tie(
Reg, Mods) = selectVOP3PModsImpl(Root.
getReg(), MRI, IsDOT);
5489 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
5490 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5495AMDGPUInstructionSelector::selectVOP3PMods(
MachineOperand &Root)
const {
5497 return selectVOP3PRetHelper(Root);
5501AMDGPUInstructionSelector::selectVOP3PModsDOT(
MachineOperand &Root)
const {
5503 return selectVOP3PRetHelper(Root,
true);
5507AMDGPUInstructionSelector::selectVOP3PNoModsDOT(
MachineOperand &Root)
const {
5511 std::tie(Src, Mods) = selectVOP3PModsImpl(Root.
getReg(), MRI,
true );
5515 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); }}};
5519AMDGPUInstructionSelector::selectVOP3PModsF32(
MachineOperand &Root)
const {
5522 std::tie(Src, Mods) = selectVOP3PModsF32Impl(Root.
getReg());
5525 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5526 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5531AMDGPUInstructionSelector::selectVOP3PNoModsF32(
MachineOperand &Root)
const {
5534 std::tie(Src, Mods) = selectVOP3PModsF32Impl(Root.
getReg());
5538 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); }}};
5542AMDGPUInstructionSelector::selectWMMAOpSelVOP3PMods(
5545 "expected i1 value");
5551 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5559 switch (Elts.
size()) {
5561 DstRegClass = &AMDGPU::VReg_256RegClass;
5564 DstRegClass = &AMDGPU::VReg_128RegClass;
5567 DstRegClass = &AMDGPU::VReg_64RegClass;
5574 auto MIB =
B.buildInstr(AMDGPU::REG_SEQUENCE)
5576 for (
unsigned i = 0; i < Elts.
size(); ++i) {
5587 if (ModOpcode == TargetOpcode::G_FNEG) {
5591 for (
auto El : Elts) {
5597 if (Elts.size() != NegAbsElts.
size()) {
5606 assert(ModOpcode == TargetOpcode::G_FABS);
5614AMDGPUInstructionSelector::selectWMMAModsF32NegAbs(
MachineOperand &Root)
const {
5623 MachineInstr *ElF32 = MRI->getVRegDef(BV->
getSourceReg(0));
5624 unsigned ModOpcode = (ElF32->
getOpcode() == AMDGPU::G_FNEG)
5641 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5642 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5646AMDGPUInstructionSelector::selectWMMAModsF16Neg(
MachineOperand &Root)
const {
5668 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5669 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5673AMDGPUInstructionSelector::selectWMMAModsF16NegAbs(
MachineOperand &Root)
const {
5681 MachineInstr *ElV2F16 = MRI->getVRegDef(CV->
getSourceReg(0));
5683 unsigned ModOpcode = (ElV2F16->
getOpcode() == AMDGPU::G_FNEG)
5702 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5703 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5707AMDGPUInstructionSelector::selectWMMAVISrc(
MachineOperand &Root)
const {
5708 std::optional<FPValueAndVReg> FPValReg;
5710 if (TII.isInlineConstant(FPValReg->Value)) {
5711 return {{[=](MachineInstrBuilder &MIB) {
5712 MIB.
addImm(FPValReg->Value.bitcastToAPInt().getSExtValue());
5722 if (TII.isInlineConstant(ICst)) {
5732AMDGPUInstructionSelector::selectSWMMACIndex8(
MachineOperand &Root)
const {
5738 std::optional<ValueAndVReg> ShiftAmt;
5740 MRI->getType(ShiftSrc).getSizeInBits() == 32 &&
5741 ShiftAmt->Value.getZExtValue() % 8 == 0) {
5742 Key = ShiftAmt->Value.getZExtValue() / 8;
5747 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5748 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5753AMDGPUInstructionSelector::selectSWMMACIndex16(
MachineOperand &Root)
const {
5760 std::optional<ValueAndVReg> ShiftAmt;
5762 MRI->getType(ShiftSrc).getSizeInBits() == 32 &&
5763 ShiftAmt->Value.getZExtValue() == 16) {
5769 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5770 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5775AMDGPUInstructionSelector::selectSWMMACIndex32(
MachineOperand &Root)
const {
5782 S32 = matchAnyExtendFromS32(Src);
5786 if (
Def->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) {
5791 Src =
Def->getOperand(2).getReg();
5798 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5799 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5804AMDGPUInstructionSelector::selectVOP3OpSelMods(
MachineOperand &Root)
const {
5807 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
5810 if (!Subtarget->useRealTrue16Insts() &&
5811 MRI->getType(Root.
getReg()).getSizeInBits() == 16 &&
5818 [=](MachineInstrBuilder &MIB) {
5819 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
5821 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5827AMDGPUInstructionSelector::selectVINTERPMods(
MachineOperand &Root)
const {
5830 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
5836 [=](MachineInstrBuilder &MIB) {
5838 copyToVGPRIfSrcFolded(Src, Mods, Root, MIB,
true));
5840 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
5845AMDGPUInstructionSelector::selectVINTERPModsHi(
MachineOperand &Root)
const {
5848 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
5854 [=](MachineInstrBuilder &MIB) {
5856 copyToVGPRIfSrcFolded(Src, Mods, Root, MIB,
true));
5858 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
5865bool AMDGPUInstructionSelector::selectScaleOffset(
MachineOperand &Root,
5867 bool IsSigned)
const {
5868 if (!Subtarget->hasScaleOffset())
5872 MachineMemOperand *MMO = *
MI.memoperands_begin();
5884 OffsetReg =
Def->Reg;
5899 m_BinOp(IsSigned ? AMDGPU::S_MUL_I64_I32_PSEUDO : AMDGPU::S_MUL_U64,
5903 (
Mul->getOpcode() == (IsSigned ? AMDGPU::G_AMDGPU_MAD_I64_I32
5904 : AMDGPU::G_AMDGPU_MAD_U64_U32) ||
5905 (IsSigned &&
Mul->getOpcode() == AMDGPU::G_AMDGPU_MAD_U64_U32 &&
5906 VT->signBitIsZero(
Mul->getOperand(2).getReg()))) &&
5919bool AMDGPUInstructionSelector::selectSmrdOffset(
MachineOperand &Root,
5923 bool *ScaleOffset)
const {
5930 getAddrModeInfo(*
MI, *MRI, AddrInfo);
5932 if (AddrInfo.
empty())
5935 const GEPInfo &GEPI = AddrInfo[0];
5936 std::optional<int64_t> EncodedImm;
5939 *ScaleOffset =
false;
5944 if (GEPI.SgprParts.size() == 1 && GEPI.Imm != 0 && EncodedImm &&
5945 AddrInfo.
size() > 1) {
5946 const GEPInfo &GEPI2 = AddrInfo[1];
5947 if (GEPI2.SgprParts.size() == 2 && GEPI2.Imm == 0) {
5948 Register OffsetReg = GEPI2.SgprParts[1];
5951 selectScaleOffset(Root, OffsetReg,
false );
5952 OffsetReg = matchZeroExtendFromS32OrS32(OffsetReg);
5954 Base = GEPI2.SgprParts[0];
5955 *SOffset = OffsetReg;
5964 auto SKnown =
VT->getKnownBits(*SOffset);
5965 if (*
Offset + SKnown.getMinValue().getSExtValue() < 0)
5977 if (
Offset && GEPI.SgprParts.size() == 1 && EncodedImm) {
5978 Base = GEPI.SgprParts[0];
5984 if (SOffset && GEPI.SgprParts.size() == 1 &&
isUInt<32>(GEPI.Imm) &&
5990 Base = GEPI.SgprParts[0];
5991 *SOffset = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
5992 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), *SOffset)
5997 if (SOffset && GEPI.SgprParts.size() && GEPI.Imm == 0) {
5998 Register OffsetReg = GEPI.SgprParts[1];
6000 *ScaleOffset = selectScaleOffset(Root, OffsetReg,
false );
6001 OffsetReg = matchZeroExtendFromS32OrS32(OffsetReg);
6003 Base = GEPI.SgprParts[0];
6004 *SOffset = OffsetReg;
6013AMDGPUInstructionSelector::selectSmrdImm(
MachineOperand &Root)
const {
6016 if (!selectSmrdOffset(Root,
Base,
nullptr, &
Offset,
6018 return std::nullopt;
6020 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
6021 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Offset); }}};
6025AMDGPUInstructionSelector::selectSmrdImm32(
MachineOperand &Root)
const {
6027 getAddrModeInfo(*Root.
getParent(), *MRI, AddrInfo);
6029 if (AddrInfo.
empty() || AddrInfo[0].SgprParts.size() != 1)
6030 return std::nullopt;
6032 const GEPInfo &GEPInfo = AddrInfo[0];
6033 Register PtrReg = GEPInfo.SgprParts[0];
6034 std::optional<int64_t> EncodedImm =
6037 return std::nullopt;
6040 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrReg); },
6041 [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); }
6046AMDGPUInstructionSelector::selectSmrdSgpr(
MachineOperand &Root)
const {
6049 if (!selectSmrdOffset(Root,
Base, &SOffset,
nullptr,
6051 return std::nullopt;
6054 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
6055 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
6056 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }}};
6060AMDGPUInstructionSelector::selectSmrdSgprImm(
MachineOperand &Root)
const {
6064 if (!selectSmrdOffset(Root,
Base, &SOffset, &
Offset, &ScaleOffset))
6065 return std::nullopt;
6068 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
6069 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
6071 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }}};
6074std::pair<Register, int> AMDGPUInstructionSelector::selectFlatOffsetImpl(
6080 if (!STI.hasFlatInstOffsets())
6084 int64_t ConstOffset;
6086 std::tie(PtrBase, ConstOffset, IsInBounds) =
6087 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
6093 if (ConstOffset == 0 ||
6095 !isFlatScratchBaseLegal(Root.
getReg())) ||
6099 unsigned AddrSpace = (*
MI->memoperands_begin())->getAddrSpace();
6100 if (!TII.isLegalFLATOffset(ConstOffset, AddrSpace, FlatVariant))
6103 return std::pair(PtrBase, ConstOffset);
6107AMDGPUInstructionSelector::selectFlatOffset(
MachineOperand &Root)
const {
6111 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6112 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6117AMDGPUInstructionSelector::selectGlobalOffset(
MachineOperand &Root)
const {
6118 auto PtrWithOffset =
6122 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6123 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6128AMDGPUInstructionSelector::selectScratchOffset(
MachineOperand &Root)
const {
6129 auto PtrWithOffset =
6133 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6134 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6140AMDGPUInstructionSelector::selectGlobalSAddr(
MachineOperand &Root,
6142 bool NeedIOffset)
const {
6145 int64_t ConstOffset;
6146 int64_t ImmOffset = 0;
6150 std::tie(PtrBase, ConstOffset, std::ignore) =
6151 getPtrBaseWithConstantOffset(Addr, *MRI);
6153 if (ConstOffset != 0) {
6158 ImmOffset = ConstOffset;
6161 if (isSGPR(PtrBaseDef->Reg)) {
6167 int64_t SplitImmOffset = 0, RemainderOffset = ConstOffset;
6169 std::tie(SplitImmOffset, RemainderOffset) =
6174 if (Subtarget->hasSignedGVSOffset() ?
isInt<32>(RemainderOffset)
6179 MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6181 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32),
6183 .
addImm(RemainderOffset);
6187 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrBase); },
6188 [=](MachineInstrBuilder &MIB) {
6191 [=](MachineInstrBuilder &MIB) { MIB.
addImm(SplitImmOffset); },
6192 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); },
6195 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrBase); },
6196 [=](MachineInstrBuilder &MIB) {
6199 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); },
6208 unsigned NumLiterals =
6209 !TII.isInlineConstant(APInt(32,
Lo_32(ConstOffset))) +
6210 !TII.isInlineConstant(APInt(32,
Hi_32(ConstOffset)));
6211 if (STI.getConstantBusLimit(AMDGPU::V_ADD_U32_e64) > NumLiterals)
6212 return std::nullopt;
6219 if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
6224 if (isSGPR(SAddr)) {
6225 Register PtrBaseOffset = AddrDef->MI->getOperand(2).getReg();
6229 bool ScaleOffset = selectScaleOffset(Root, PtrBaseOffset,
6230 Subtarget->hasSignedGVSOffset());
6231 if (
Register VOffset = matchExtendFromS32OrS32(
6232 PtrBaseOffset, Subtarget->hasSignedGVSOffset())) {
6234 return {{[=](MachineInstrBuilder &MIB) {
6237 [=](MachineInstrBuilder &MIB) {
6240 [=](MachineInstrBuilder &MIB) {
6243 [=](MachineInstrBuilder &MIB) {
6247 return {{[=](MachineInstrBuilder &MIB) {
6250 [=](MachineInstrBuilder &MIB) {
6253 [=](MachineInstrBuilder &MIB) {
6263 if (AddrDef->MI->getOpcode() == AMDGPU::G_IMPLICIT_DEF ||
6264 AddrDef->MI->getOpcode() == AMDGPU::G_CONSTANT || !isSGPR(AddrDef->Reg))
6265 return std::nullopt;
6271 Register VOffset = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6273 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32), VOffset)
6278 [=](MachineInstrBuilder &MIB) { MIB.
addReg(AddrDef->Reg); },
6279 [=](MachineInstrBuilder &MIB) { MIB.
addReg(VOffset); },
6280 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6281 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); }
6284 [=](MachineInstrBuilder &MIB) { MIB.
addReg(AddrDef->Reg); },
6285 [=](MachineInstrBuilder &MIB) { MIB.
addReg(VOffset); },
6286 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); }
6291AMDGPUInstructionSelector::selectGlobalSAddr(
MachineOperand &Root)
const {
6292 return selectGlobalSAddr(Root, 0);
6296AMDGPUInstructionSelector::selectGlobalSAddrCPol(
MachineOperand &Root)
const {
6302 return selectGlobalSAddr(Root, PassedCPol);
6306AMDGPUInstructionSelector::selectGlobalSAddrCPolM0(
MachineOperand &Root)
const {
6312 return selectGlobalSAddr(Root, PassedCPol);
6316AMDGPUInstructionSelector::selectGlobalSAddrGLC(
MachineOperand &Root)
const {
6321AMDGPUInstructionSelector::selectGlobalSAddrNoIOffset(
6328 return selectGlobalSAddr(Root, PassedCPol,
false);
6332AMDGPUInstructionSelector::selectGlobalSAddrNoIOffsetM0(
6339 return selectGlobalSAddr(Root, PassedCPol,
false);
6343AMDGPUInstructionSelector::selectScratchSAddr(
MachineOperand &Root)
const {
6346 int64_t ConstOffset;
6347 int64_t ImmOffset = 0;
6351 std::tie(PtrBase, ConstOffset, std::ignore) =
6352 getPtrBaseWithConstantOffset(Addr, *MRI);
6354 if (ConstOffset != 0 && isFlatScratchBaseLegal(Addr) &&
6358 ImmOffset = ConstOffset;
6362 if (AddrDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX) {
6363 int FI = AddrDef->MI->getOperand(1).
getIndex();
6366 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); }
6372 if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
6373 Register LHS = AddrDef->MI->getOperand(1).getReg();
6374 Register RHS = AddrDef->MI->getOperand(2).getReg();
6378 if (LHSDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX &&
6379 isSGPR(RHSDef->Reg)) {
6380 int FI = LHSDef->MI->getOperand(1).getIndex();
6384 SAddr = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
6386 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_ADD_I32), SAddr)
6394 return std::nullopt;
6397 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SAddr); },
6398 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); }
6403bool AMDGPUInstructionSelector::checkFlatScratchSVSSwizzleBug(
6405 if (!Subtarget->hasFlatScratchSVSSwizzleBug())
6411 auto VKnown =
VT->getKnownBits(VAddr);
6414 uint64_t VMax = VKnown.getMaxValue().getZExtValue();
6416 return (VMax & 3) + (
SMax & 3) >= 4;
6420AMDGPUInstructionSelector::selectScratchSVAddr(
MachineOperand &Root)
const {
6423 int64_t ConstOffset;
6424 int64_t ImmOffset = 0;
6428 std::tie(PtrBase, ConstOffset, std::ignore) =
6429 getPtrBaseWithConstantOffset(Addr, *MRI);
6432 if (ConstOffset != 0 &&
6436 ImmOffset = ConstOffset;
6440 if (AddrDef->MI->getOpcode() != AMDGPU::G_PTR_ADD)
6441 return std::nullopt;
6443 Register RHS = AddrDef->MI->getOperand(2).getReg();
6444 if (RBI.getRegBank(
RHS, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID)
6445 return std::nullopt;
6447 Register LHS = AddrDef->MI->getOperand(1).getReg();
6450 if (OrigAddr != Addr) {
6451 if (!isFlatScratchBaseLegalSVImm(OrigAddr))
6452 return std::nullopt;
6454 if (!isFlatScratchBaseLegalSV(OrigAddr))
6455 return std::nullopt;
6458 if (checkFlatScratchSVSSwizzleBug(
RHS,
LHS, ImmOffset))
6459 return std::nullopt;
6461 unsigned CPol = selectScaleOffset(Root,
RHS,
true )
6465 if (LHSDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX) {
6466 int FI = LHSDef->MI->getOperand(1).getIndex();
6468 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
RHS); },
6470 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6471 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }
6480 return std::nullopt;
6483 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
RHS); },
6484 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
LHS); },
6485 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6486 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }
6491AMDGPUInstructionSelector::selectMUBUFScratchOffen(
MachineOperand &Root)
const {
6495 const SIMachineFunctionInfo *
Info =
MF->getInfo<SIMachineFunctionInfo>();
6500 Register HighBits = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6505 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32),
6509 return {{[=](MachineInstrBuilder &MIB) {
6512 [=](MachineInstrBuilder &MIB) {
6515 [=](MachineInstrBuilder &MIB) {
6520 [=](MachineInstrBuilder &MIB) {
6529 std::optional<int> FI;
6533 int64_t ConstOffset;
6534 std::tie(PtrBase, ConstOffset, std::ignore) =
6535 getPtrBaseWithConstantOffset(VAddr, *MRI);
6537 if (ConstOffset != 0) {
6538 if (TII.isLegalMUBUFImmOffset(ConstOffset) &&
6539 (!STI.privateMemoryResourceIsRangeChecked() ||
6540 VT->signBitIsZero(PtrBase))) {
6551 return {{[=](MachineInstrBuilder &MIB) {
6554 [=](MachineInstrBuilder &MIB) {
6560 [=](MachineInstrBuilder &MIB) {
6565 [=](MachineInstrBuilder &MIB) {
6570bool AMDGPUInstructionSelector::isDSOffsetLegal(
Register Base,
6575 if (STI.hasUsableDSOffset() || STI.unsafeDSOffsetFoldingEnabled())
6580 return VT->signBitIsZero(
Base);
6583bool AMDGPUInstructionSelector::isDSOffset2Legal(
Register Base, int64_t Offset0,
6585 unsigned Size)
const {
6586 if (Offset0 %
Size != 0 || Offset1 %
Size != 0)
6591 if (STI.hasUsableDSOffset() || STI.unsafeDSOffsetFoldingEnabled())
6596 return VT->signBitIsZero(
Base);
6601 return Addr->
getOpcode() == TargetOpcode::G_OR ||
6602 (Addr->
getOpcode() == TargetOpcode::G_PTR_ADD &&
6609bool AMDGPUInstructionSelector::isFlatScratchBaseLegal(
Register Addr)
const {
6617 if (STI.hasSignedScratchOffsets())
6623 if (AddrMI->
getOpcode() == TargetOpcode::G_PTR_ADD) {
6624 std::optional<ValueAndVReg> RhsValReg =
6630 if (RhsValReg && RhsValReg->Value.getSExtValue() < 0 &&
6631 RhsValReg->Value.getSExtValue() > -0x40000000)
6635 return VT->signBitIsZero(
LHS);
6640bool AMDGPUInstructionSelector::isFlatScratchBaseLegalSV(
Register Addr)
const {
6648 if (STI.hasSignedScratchOffsets())
6653 return VT->signBitIsZero(
RHS) &&
VT->signBitIsZero(
LHS);
6658bool AMDGPUInstructionSelector::isFlatScratchBaseLegalSVImm(
6662 if (STI.hasSignedScratchOffsets())
6667 std::optional<DefinitionAndSourceRegister> BaseDef =
6669 std::optional<ValueAndVReg> RHSOffset =
6679 (RHSOffset->Value.getSExtValue() < 0 &&
6680 RHSOffset->Value.getSExtValue() > -0x40000000)))
6683 Register LHS = BaseDef->MI->getOperand(1).getReg();
6684 Register RHS = BaseDef->MI->getOperand(2).getReg();
6685 return VT->signBitIsZero(
RHS) &&
VT->signBitIsZero(
LHS);
6688bool AMDGPUInstructionSelector::isUnneededShiftMask(
const MachineInstr &
MI,
6689 unsigned ShAmtBits)
const {
6690 assert(
MI.getOpcode() == TargetOpcode::G_AND);
6692 std::optional<APInt>
RHS =
6697 if (
RHS->countr_one() >= ShAmtBits)
6700 const APInt &LHSKnownZeros =
VT->getKnownZeroes(
MI.getOperand(1).getReg());
6701 return (LHSKnownZeros | *
RHS).countr_one() >= ShAmtBits;
6705AMDGPUInstructionSelector::selectMUBUFScratchOffset(
6708 const SIMachineFunctionInfo *
Info =
MF->getInfo<SIMachineFunctionInfo>();
6710 std::optional<DefinitionAndSourceRegister>
Def =
6712 assert(Def &&
"this shouldn't be an optional result");
6717 [=](MachineInstrBuilder &MIB) {
6720 [=](MachineInstrBuilder &MIB) {
6723 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
6734 if (!TII.isLegalMUBUFImmOffset(
Offset))
6742 [=](MachineInstrBuilder &MIB) {
6745 [=](MachineInstrBuilder &MIB) {
6753 !TII.isLegalMUBUFImmOffset(
Offset))
6757 [=](MachineInstrBuilder &MIB) {
6760 [=](MachineInstrBuilder &MIB) {
6767std::pair<Register, unsigned>
6768AMDGPUInstructionSelector::selectDS1Addr1OffsetImpl(
6770 int64_t ConstAddr = 0;
6774 std::tie(PtrBase,
Offset, std::ignore) =
6775 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
6778 if (isDSOffsetLegal(PtrBase,
Offset)) {
6780 return std::pair(PtrBase,
Offset);
6789 return std::pair(Root.
getReg(), 0);
6793AMDGPUInstructionSelector::selectDS1Addr1Offset(
MachineOperand &Root)
const {
6796 std::tie(
Reg,
Offset) = selectDS1Addr1OffsetImpl(Root);
6798 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
6804AMDGPUInstructionSelector::selectDS64Bit4ByteAligned(
MachineOperand &Root)
const {
6805 return selectDSReadWrite2(Root, 4);
6809AMDGPUInstructionSelector::selectDS128Bit8ByteAligned(
MachineOperand &Root)
const {
6810 return selectDSReadWrite2(Root, 8);
6814AMDGPUInstructionSelector::selectDSReadWrite2(
MachineOperand &Root,
6815 unsigned Size)
const {
6820 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
6822 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Offset+1); }
6826std::pair<Register, unsigned>
6827AMDGPUInstructionSelector::selectDSReadWrite2Impl(
MachineOperand &Root,
6828 unsigned Size)
const {
6829 int64_t ConstAddr = 0;
6833 std::tie(PtrBase,
Offset, std::ignore) =
6834 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
6837 int64_t OffsetValue0 =
Offset;
6839 if (isDSOffset2Legal(PtrBase, OffsetValue0, OffsetValue1,
Size)) {
6841 return std::pair(PtrBase, OffsetValue0 /
Size);
6850 return std::pair(Root.
getReg(), 0);
6858std::tuple<Register, int64_t, bool>
6859AMDGPUInstructionSelector::getPtrBaseWithConstantOffset(
6862 if (RootI->
getOpcode() != TargetOpcode::G_PTR_ADD)
6863 return {Root, 0,
false};
6866 std::optional<ValueAndVReg> MaybeOffset =
6869 return {Root, 0,
false};
6889 B.buildInstr(AMDGPU::S_MOV_B32)
6892 B.buildInstr(AMDGPU::S_MOV_B32)
6899 B.buildInstr(AMDGPU::REG_SEQUENCE)
6902 .addImm(AMDGPU::sub0)
6904 .addImm(AMDGPU::sub1);
6909 B.buildInstr(AMDGPU::S_MOV_B64)
6914 B.buildInstr(AMDGPU::REG_SEQUENCE)
6917 .addImm(AMDGPU::sub0_sub1)
6919 .addImm(AMDGPU::sub2_sub3);
6926 uint64_t DefaultFormat =
TII.getDefaultRsrcDataFormat();
6935 uint64_t DefaultFormat =
TII.getDefaultRsrcDataFormat();
6942AMDGPUInstructionSelector::MUBUFAddressData
6943AMDGPUInstructionSelector::parseMUBUFAddress(
Register Src)
const {
6944 MUBUFAddressData
Data;
6950 std::tie(PtrBase,
Offset, std::ignore) =
6951 getPtrBaseWithConstantOffset(Src, *MRI);
6957 if (MachineInstr *InputAdd
6959 Data.N2 = InputAdd->getOperand(1).getReg();
6960 Data.N3 = InputAdd->getOperand(2).getReg();
6975bool AMDGPUInstructionSelector::shouldUseAddr64(MUBUFAddressData Addr)
const {
6981 const RegisterBank *N0Bank = RBI.getRegBank(Addr.N0, *MRI, TRI);
6982 return N0Bank->
getID() == AMDGPU::VGPRRegBankID;
6988void AMDGPUInstructionSelector::splitIllegalMUBUFOffset(
6990 if (TII.isLegalMUBUFImmOffset(ImmOffset))
6994 SOffset = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
6995 B.buildInstr(AMDGPU::S_MOV_B32)
7001bool AMDGPUInstructionSelector::selectMUBUFAddr64Impl(
7006 if (!STI.hasAddr64() || STI.useFlatForGlobal())
7009 MUBUFAddressData AddrData = parseMUBUFAddress(Root.
getReg());
7010 if (!shouldUseAddr64(AddrData))
7016 Offset = AddrData.Offset;
7022 if (RBI.getRegBank(N2, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
7024 if (RBI.getRegBank(N3, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
7037 }
else if (RBI.getRegBank(N0, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
7048 splitIllegalMUBUFOffset(
B, SOffset,
Offset);
7052bool AMDGPUInstructionSelector::selectMUBUFOffsetImpl(
7057 if (STI.useFlatForGlobal())
7060 MUBUFAddressData AddrData = parseMUBUFAddress(Root.
getReg());
7061 if (shouldUseAddr64(AddrData))
7067 Offset = AddrData.Offset;
7073 splitIllegalMUBUFOffset(
B, SOffset,
Offset);
7078AMDGPUInstructionSelector::selectMUBUFAddr64(
MachineOperand &Root)
const {
7084 if (!selectMUBUFAddr64Impl(Root, VAddr, RSrcReg, SOffset,
Offset))
7090 [=](MachineInstrBuilder &MIB) {
7093 [=](MachineInstrBuilder &MIB) {
7096 [=](MachineInstrBuilder &MIB) {
7099 else if (STI.hasRestrictedSOffset())
7100 MIB.
addReg(AMDGPU::SGPR_NULL);
7104 [=](MachineInstrBuilder &MIB) {
7114AMDGPUInstructionSelector::selectMUBUFOffset(
MachineOperand &Root)
const {
7119 if (!selectMUBUFOffsetImpl(Root, RSrcReg, SOffset,
Offset))
7123 [=](MachineInstrBuilder &MIB) {
7126 [=](MachineInstrBuilder &MIB) {
7129 else if (STI.hasRestrictedSOffset())
7130 MIB.
addReg(AMDGPU::SGPR_NULL);
7142AMDGPUInstructionSelector::selectBUFSOffset(
MachineOperand &Root)
const {
7147 SOffset = AMDGPU::SGPR_NULL;
7149 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); }}};
7153static std::optional<uint64_t>
7157 if (!OffsetVal || !
isInt<32>(*OffsetVal))
7158 return std::nullopt;
7159 return Lo_32(*OffsetVal);
7163AMDGPUInstructionSelector::selectSMRDBufferImm(
MachineOperand &Root)
const {
7164 std::optional<uint64_t> OffsetVal =
7169 std::optional<int64_t> EncodedImm =
7174 return {{ [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); } }};
7178AMDGPUInstructionSelector::selectSMRDBufferImm32(
MachineOperand &Root)
const {
7185 std::optional<int64_t> EncodedImm =
7190 return {{ [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); } }};
7194AMDGPUInstructionSelector::selectSMRDBufferSgprImm(
MachineOperand &Root)
const {
7202 return std::nullopt;
7204 std::optional<int64_t> EncodedOffset =
7207 return std::nullopt;
7209 assert(MRI->getType(SOffset).getSizeInBits() == 32);
7210 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
7211 [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedOffset); }}};
7214std::pair<Register, unsigned>
7215AMDGPUInstructionSelector::selectVOP3PMadMixModsImpl(
MachineOperand &Root,
7216 bool &Matched)
const {
7221 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
7231 const auto CheckAbsNeg = [&]() {
7236 std::tie(Src, ModsTmp) = selectVOP3ModsImpl(Src);
7266 if (MRI->getType(Src).isFixedVector(2, 16))
7279AMDGPUInstructionSelector::selectVOP3PMadMixModsExt(
7284 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7289 [=](MachineInstrBuilder &MIB) { MIB.
addReg(widenSrcIfVGPR16(Src, MIB)); },
7290 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
7295AMDGPUInstructionSelector::selectVOP3PMadMixMods(
MachineOperand &Root)
const {
7299 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7302 [=](MachineInstrBuilder &MIB) { MIB.
addReg(widenSrcIfVGPR16(Src, MIB)); },
7303 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
7308AMDGPUInstructionSelector::selectVOP3PMadMixModsExtNeg(
7313 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7318 [=](MachineInstrBuilder &MIB) { MIB.
addReg(widenSrcIfVGPR16(Src, MIB)); },
7319 [=](MachineInstrBuilder &MIB) {
7326AMDGPUInstructionSelector::selectVOP3PMadMixModsNeg(
7331 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7334 [=](MachineInstrBuilder &MIB) { MIB.
addReg(widenSrcIfVGPR16(Src, MIB)); },
7335 [=](MachineInstrBuilder &MIB) {
7341bool AMDGPUInstructionSelector::selectSBarrierSignalIsfirst(
7345 Register CCReg =
I.getOperand(0).getReg();
7350 BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM))
7351 .
addImm(
I.getOperand(2).getImm());
7355 I.eraseFromParent();
7356 return RBI.constrainGenericRegister(CCReg, AMDGPU::SReg_32_XM0_XEXECRegClass,
7360bool AMDGPUInstructionSelector::selectSGetBarrierState(
7364 const MachineOperand &BarOp =
I.getOperand(2);
7365 std::optional<int64_t> BarValImm =
7369 auto CopyMIB =
BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
7373 MachineInstrBuilder MIB;
7374 unsigned Opc = BarValImm ? AMDGPU::S_GET_BARRIER_STATE_IMM
7375 : AMDGPU::S_GET_BARRIER_STATE_M0;
7378 auto DstReg =
I.getOperand(0).getReg();
7380 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
7381 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
7387 I.eraseFromParent();
7392 if (HasInlineConst) {
7396 case Intrinsic::amdgcn_s_barrier_join:
7397 return AMDGPU::S_BARRIER_JOIN_IMM;
7398 case Intrinsic::amdgcn_s_wakeup_barrier:
7399 return AMDGPU::S_WAKEUP_BARRIER_IMM;
7400 case Intrinsic::amdgcn_s_get_named_barrier_state:
7401 return AMDGPU::S_GET_BARRIER_STATE_IMM;
7407 case Intrinsic::amdgcn_s_barrier_join:
7408 return AMDGPU::S_BARRIER_JOIN_M0;
7409 case Intrinsic::amdgcn_s_wakeup_barrier:
7410 return AMDGPU::S_WAKEUP_BARRIER_M0;
7411 case Intrinsic::amdgcn_s_get_named_barrier_state:
7412 return AMDGPU::S_GET_BARRIER_STATE_M0;
7417bool AMDGPUInstructionSelector::selectNamedBarrierInit(
7421 const MachineOperand &BarOp =
I.getOperand(1);
7422 const MachineOperand &CntOp =
I.getOperand(2);
7426 if (IntrID == Intrinsic::amdgcn_s_barrier_signal_var) {
7427 std::optional<int64_t> CntImm =
7429 if (CntImm && *CntImm == 0) {
7430 std::optional<int64_t> BarValImm =
7433 uint32_t BarID = *BarValImm & 0x3F;
7434 BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::S_BARRIER_SIGNAL_IMM))
7436 I.eraseFromParent();
7443 Register TmpReg1 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7452 Register TmpReg2 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7458 Register TmpReg3 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7459 constexpr unsigned ShAmt = 16;
7465 Register TmpReg4 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7475 unsigned Opc = IntrID == Intrinsic::amdgcn_s_barrier_init
7476 ? AMDGPU::S_BARRIER_INIT_M0
7477 : AMDGPU::S_BARRIER_SIGNAL_M0;
7478 MachineInstrBuilder MIB;
7481 I.eraseFromParent();
7485bool AMDGPUInstructionSelector::selectNamedBarrierInst(
7489 MachineOperand BarOp = IntrID == Intrinsic::amdgcn_s_get_named_barrier_state
7492 std::optional<int64_t> BarValImm =
7497 Register TmpReg1 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7503 auto CopyMIB =
BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
7508 MachineInstrBuilder MIB;
7512 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state) {
7513 auto DstReg =
I.getOperand(0).getReg();
7515 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
7516 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
7522 uint32_t BarId = *BarValImm & 0x3F;
7526 I.eraseFromParent();
7533 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
7534 "Expected G_CONSTANT");
7535 MIB.
addImm(-
MI.getOperand(1).getCImm()->getSExtValue());
7541 const MachineOperand &
Op =
MI.getOperand(1);
7542 assert(
MI.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1);
7543 MIB.
addImm(
Op.getFPImm()->getValueAPF().bitcastToAPInt().getZExtValue());
7546void AMDGPUInstructionSelector::renderCountTrailingOnesImm(
7548 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
7549 "Expected G_CONSTANT");
7550 MIB.
addImm(
MI.getOperand(1).getCImm()->getValue().countTrailingOnes());
7558 const MachineOperand &
Op =
MI.getOperand(OpIdx);
7569 MIB.
addImm(
MI.getOperand(OpIdx).getImm() != 0);
7575 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7579void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_0_0(
7581 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7586void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_0_1(
7588 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7589 MIB.
addImm((
MI.getOperand(OpIdx).getImm() & 0x1)
7594void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_1_0(
7596 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7601void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_1_1(
7603 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7604 MIB.
addImm((
MI.getOperand(OpIdx).getImm() & 0x2)
7609void AMDGPUInstructionSelector::renderDstSelToOpSelXForm(
7611 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7616void AMDGPUInstructionSelector::renderSrcSelToOpSelXForm(
7618 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7623void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_2_0(
7625 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7630void AMDGPUInstructionSelector::renderDstSelToOpSel3XFormXForm(
7632 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7633 MIB.
addImm((
MI.getOperand(OpIdx).getImm() & 0x2)
7641 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7642 MIB.
addImm(
MI.getOperand(OpIdx).getImm() &
7650 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7651 const bool Swizzle =
MI.getOperand(OpIdx).getImm() &
7657void AMDGPUInstructionSelector::renderExtractCpolSetGLC(
7659 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7660 const uint32_t Cpol =
MI.getOperand(OpIdx).getImm() &
7669 const APFloat &APF =
MI.getOperand(1).getFPImm()->getValueAPF();
7671 assert(ExpVal != INT_MIN);
7682 MIB.
addImm((
MI.getOperand(OpIdx).getImm() + 3) % 4);
7689 if (
MI.getOperand(OpIdx).getImm())
7691 MIB.
addImm((int64_t)Mods);
7698 if (
MI.getOperand(OpIdx).getImm())
7700 MIB.
addImm((int64_t)Mods);
7706 unsigned Val =
MI.getOperand(OpIdx).getImm();
7714 MIB.
addImm((int64_t)Mods);
7720 uint32_t
V =
MI.getOperand(2).getImm();
7723 if (!Subtarget->hasSafeCUPrefetch())
7729void AMDGPUInstructionSelector::renderScaledMAIIntrinsicOperand(
7731 unsigned Val =
MI.getOperand(OpIdx).getImm();
7740bool AMDGPUInstructionSelector::isInlineImmediate(
const APInt &
Imm)
const {
7741 return TII.isInlineConstant(
Imm);
7744bool AMDGPUInstructionSelector::isInlineImmediate(
const APFloat &
Imm)
const {
7745 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.
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.
#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.
LLVM_ABI std::optional< APInt > getIConstantVRegVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT, return the corresponding value.
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.