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)
502 MachineInstr *Addc =
BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::V_ADDC_U32_e64), DstHi)
512 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
519 if (!RBI.constrainGenericRegister(DstReg, RC, *MRI))
526bool AMDGPUInstructionSelector::selectG_UADDO_USUBO_UADDE_USUBE(
531 Register Dst0Reg =
I.getOperand(0).getReg();
532 Register Dst1Reg =
I.getOperand(1).getReg();
533 const bool IsAdd =
I.getOpcode() == AMDGPU::G_UADDO ||
534 I.getOpcode() == AMDGPU::G_UADDE;
535 const bool HasCarryIn =
I.getOpcode() == AMDGPU::G_UADDE ||
536 I.getOpcode() == AMDGPU::G_USUBE;
538 if (isVCC(Dst1Reg, *MRI)) {
539 unsigned NoCarryOpc =
540 IsAdd ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_SUB_CO_U32_e64;
541 unsigned CarryOpc = IsAdd ? AMDGPU::V_ADDC_U32_e64 : AMDGPU::V_SUBB_U32_e64;
542 I.setDesc(TII.get(HasCarryIn ? CarryOpc : NoCarryOpc));
549 Register Src0Reg =
I.getOperand(2).getReg();
550 Register Src1Reg =
I.getOperand(3).getReg();
553 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::SCC)
554 .
addReg(
I.getOperand(4).getReg());
557 unsigned NoCarryOpc = IsAdd ? AMDGPU::S_ADD_U32 : AMDGPU::S_SUB_U32;
558 unsigned CarryOpc = IsAdd ? AMDGPU::S_ADDC_U32 : AMDGPU::S_SUBB_U32;
560 auto CarryInst =
BuildMI(*BB, &
I,
DL, TII.get(HasCarryIn ? CarryOpc : NoCarryOpc), Dst0Reg)
561 .
add(
I.getOperand(2))
562 .
add(
I.getOperand(3));
564 if (MRI->use_nodbg_empty(Dst1Reg)) {
565 CarryInst.setOperandDead(3);
567 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), Dst1Reg)
569 if (!MRI->getRegClassOrNull(Dst1Reg))
570 MRI->setRegClass(Dst1Reg, &AMDGPU::SReg_32RegClass);
573 if (!RBI.constrainGenericRegister(Dst0Reg, AMDGPU::SReg_32RegClass, *MRI) ||
574 !RBI.constrainGenericRegister(Src0Reg, AMDGPU::SReg_32RegClass, *MRI) ||
575 !RBI.constrainGenericRegister(Src1Reg, AMDGPU::SReg_32RegClass, *MRI))
579 !RBI.constrainGenericRegister(
I.getOperand(4).getReg(),
580 AMDGPU::SReg_32RegClass, *MRI))
587bool AMDGPUInstructionSelector::selectG_AMDGPU_MAD_64_32(
591 const bool IsUnsigned =
I.getOpcode() == AMDGPU::G_AMDGPU_MAD_U64_U32;
592 bool UseNoCarry = Subtarget->hasMadNC64_32Insts() &&
593 MRI->use_nodbg_empty(
I.getOperand(1).getReg());
596 if (Subtarget->hasMADIntraFwdBug())
597 Opc = IsUnsigned ? AMDGPU::V_MAD_U64_U32_gfx11_e64
598 : AMDGPU::V_MAD_I64_I32_gfx11_e64;
600 Opc = IsUnsigned ? AMDGPU::V_MAD_NC_U64_U32_e64
601 : AMDGPU::V_MAD_NC_I64_I32_e64;
603 Opc = IsUnsigned ? AMDGPU::V_MAD_U64_U32_e64 : AMDGPU::V_MAD_I64_I32_e64;
608 I.setDesc(TII.get(
Opc));
610 I.addImplicitDefUseOperands(*
MF);
611 I.getOperand(0).setIsEarlyClobber(
true);
617bool AMDGPUInstructionSelector::selectG_EXTRACT(
MachineInstr &
I)
const {
619 Register DstReg =
I.getOperand(0).getReg();
620 Register SrcReg =
I.getOperand(1).getReg();
621 LLT DstTy = MRI->getType(DstReg);
622 LLT SrcTy = MRI->getType(SrcReg);
627 unsigned Offset =
I.getOperand(2).getImm();
628 if (
Offset % 32 != 0 || DstSize > 128)
637 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
638 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
641 const RegisterBank *SrcBank = RBI.getRegBank(SrcReg, *MRI, TRI);
643 TRI.getRegClassForSizeOnBank(SrcSize, *SrcBank);
648 SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubReg);
653 *SrcRC,
I.getOperand(1));
655 BuildMI(*BB, &
I,
DL, TII.get(TargetOpcode::COPY), DstReg)
656 .
addReg(SrcReg, {}, SubReg);
662bool AMDGPUInstructionSelector::selectS16MergeToS32(
MachineInstr &
MI)
const {
667 LLT Src0Ty = MRI->getType(Src0);
668 LLT Src1Ty = MRI->getType(Src1);
670 const RegisterBank *DstBank = RBI.getRegBank(Dst, *MRI, TRI);
671 const RegisterBank *Src0Bank = RBI.getRegBank(Src0, *MRI, TRI);
672 const RegisterBank *Src1Bank = RBI.getRegBank(Src1, *MRI, TRI);
673 const bool IsVector = DstBank->
getID() == AMDGPU::VGPRRegBankID;
684 if (Src0Bank->
getID() == AMDGPU::VGPRRegBankID &&
685 Src1Bank->
getID() == AMDGPU::VGPRRegBankID &&
687 BuildMI(*BB,
MI,
DL, TII.get(TargetOpcode::REG_SEQUENCE), Dst)
693 if (!RBI.constrainGenericRegister(Dst, AMDGPU::VGPR_32RegClass, *MRI))
696 MI.eraseFromParent();
701 Register TmpReg = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
702 auto MIB =
BuildMI(*BB,
MI,
DL, TII.get(AMDGPU::V_AND_B32_e32), TmpReg)
707 MIB =
BuildMI(*BB,
MI,
DL, TII.get(AMDGPU::V_LSHL_OR_B32_e64), Dst)
713 MI.eraseFromParent();
736 unsigned Opc = AMDGPU::S_PACK_LL_B32_B16;
737 if (Shift0 && Shift1) {
738 Opc = AMDGPU::S_PACK_HH_B32_B16;
739 MI.getOperand(1).setReg(ShiftSrc0);
740 MI.getOperand(2).setReg(ShiftSrc1);
742 Opc = AMDGPU::S_PACK_LH_B32_B16;
743 MI.getOperand(2).setReg(ShiftSrc1);
747 if (ConstSrc1 && ConstSrc1->Value == 0) {
749 auto MIB =
BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_LSHR_B32), Dst)
754 MI.eraseFromParent();
758 if (STI.hasSPackHL()) {
759 Opc = AMDGPU::S_PACK_HL_B32_B16;
760 MI.getOperand(1).setReg(ShiftSrc0);
764 MI.setDesc(TII.get(
Opc));
771bool AMDGPUInstructionSelector::selectS16MergeToWide(
MachineInstr &
MI)
const {
775 const unsigned DstSize = MRI->getType(DstReg).getSizeInBits();
776 const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
777 const unsigned NumSrc =
MI.getNumOperands() - 1;
781 for (
unsigned I = 0;
I != NumSrc;
I += 2) {
782 Register S32 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
792 TRI.getRegClassForSizeOnBank(DstSize, *DstBank);
793 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
795 ArrayRef<int16_t> SubRegs = TRI.getRegSplitParts(DstRC, 4);
796 auto MIB =
BuildMI(*BB,
MI,
DL, TII.get(TargetOpcode::REG_SEQUENCE), DstReg);
797 for (
unsigned I = 0,
E = S32Regs.
size();
I !=
E; ++
I)
798 MIB.addReg(S32Regs[
I]).addImm(SubRegs[
I]);
800 MI.eraseFromParent();
804bool AMDGPUInstructionSelector::selectG_MERGE_VALUES(
MachineInstr &
MI)
const {
807 LLT DstTy = MRI->getType(DstReg);
808 LLT SrcTy = MRI->getType(
MI.getOperand(1).getReg());
814 MI.getNumOperands() == 3) {
815 return selectS16MergeToS32(
MI);
819 bool IsWideS16Merge = SrcSize == 16 && DstTy.
getSizeInBits() > 32 &&
823 if (IsWideS16Merge &&
824 RBI.getRegBank(DstReg, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID)
825 return selectS16MergeToWide(
MI);
833 const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
836 TRI.getRegClassForSizeOnBank(DstSize, *DstBank);
840 ArrayRef<int16_t> SubRegs = TRI.getRegSplitParts(DstRC, SrcSize / 8);
841 MachineInstrBuilder MIB =
842 BuildMI(*BB, &
MI,
DL, TII.get(TargetOpcode::REG_SEQUENCE), DstReg);
843 for (
int I = 0,
E =
MI.getNumOperands() - 1;
I !=
E; ++
I) {
844 MachineOperand &Src =
MI.getOperand(
I + 1);
850 TRI.getConstrainedRegClassForReg(SrcReg, *MRI);
851 if (SrcRC && !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI))
855 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
858 MI.eraseFromParent();
862bool AMDGPUInstructionSelector::selectG_UNMERGE_VALUES(
MachineInstr &
MI)
const {
864 const int NumDst =
MI.getNumOperands() - 1;
866 MachineOperand &Src =
MI.getOperand(NumDst);
870 LLT DstTy = MRI->getType(DstReg0);
871 LLT SrcTy = MRI->getType(SrcReg);
876 const RegisterBank *SrcBank = RBI.getRegBank(SrcReg, *MRI, TRI);
879 TRI.getRegClassForSizeOnBank(SrcSize, *SrcBank);
880 if (!SrcRC || !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI))
886 ArrayRef<int16_t> SubRegs = TRI.getRegSplitParts(SrcRC, DstSize / 8);
887 for (
int I = 0,
E = NumDst;
I !=
E; ++
I) {
890 if (SrcBank->
getID() == AMDGPU::SGPRRegBankID &&
891 SubRegs[
I] == AMDGPU::hi16) {
892 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_LSHR_B32), DstReg)
896 BuildMI(*BB, &
MI,
DL, TII.get(TargetOpcode::COPY), DstReg)
897 .
addReg(SrcReg, {}, SubRegs[
I]);
901 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;
960 uint32_t
Imm = Lo16 | (Hi16 << 16);
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();
1222 Register Src0 = ChooseDenom != 0 ? Numer : Denom;
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));
1253 Register DstReg =
I.getOperand(0).getReg();
1254 Register Src0Reg =
I.getOperand(2).getReg();
1255 Register Src1Reg =
I.getOperand(3).getReg();
1257 I.eraseFromParent();
1260 MRI->setRegClass(
Reg, TRI.getWaveMaskRegClass());
1264 case Intrinsic::amdgcn_interp_p1_f16:
1265 return selectInterpP1F16(
I);
1266 case Intrinsic::amdgcn_wqm:
1267 return constrainCopyLikeIntrin(
I, AMDGPU::WQM);
1268 case Intrinsic::amdgcn_softwqm:
1269 return constrainCopyLikeIntrin(
I, AMDGPU::SOFT_WQM);
1270 case Intrinsic::amdgcn_strict_wwm:
1271 case Intrinsic::amdgcn_wwm:
1272 return constrainCopyLikeIntrin(
I, AMDGPU::STRICT_WWM);
1273 case Intrinsic::amdgcn_strict_wqm:
1274 return constrainCopyLikeIntrin(
I, AMDGPU::STRICT_WQM);
1275 case Intrinsic::amdgcn_writelane:
1276 return selectWritelane(
I);
1277 case Intrinsic::amdgcn_div_scale:
1278 return selectDivScale(
I);
1279 case Intrinsic::amdgcn_ballot:
1280 return selectBallot(
I);
1281 case Intrinsic::amdgcn_reloc_constant:
1282 return selectRelocConstant(
I);
1283 case Intrinsic::amdgcn_groupstaticsize:
1284 return selectGroupStaticSize(
I);
1285 case Intrinsic::returnaddress:
1286 return selectReturnAddress(
I);
1287 case Intrinsic::amdgcn_smfmac_f32_16x16x32_f16:
1288 case Intrinsic::amdgcn_smfmac_f32_32x32x16_f16:
1289 case Intrinsic::amdgcn_smfmac_f32_16x16x32_bf16:
1290 case Intrinsic::amdgcn_smfmac_f32_32x32x16_bf16:
1291 case Intrinsic::amdgcn_smfmac_i32_16x16x64_i8:
1292 case Intrinsic::amdgcn_smfmac_i32_32x32x32_i8:
1293 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_bf8:
1294 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_fp8:
1295 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_bf8:
1296 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_fp8:
1297 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_bf8:
1298 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_fp8:
1299 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_bf8:
1300 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_fp8:
1301 case Intrinsic::amdgcn_smfmac_f32_16x16x64_f16:
1302 case Intrinsic::amdgcn_smfmac_f32_32x32x32_f16:
1303 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf16:
1304 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf16:
1305 case Intrinsic::amdgcn_smfmac_i32_16x16x128_i8:
1306 case Intrinsic::amdgcn_smfmac_i32_32x32x64_i8:
1307 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_bf8:
1308 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_fp8:
1309 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_bf8:
1310 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_fp8:
1311 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_bf8:
1312 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_fp8:
1313 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_bf8:
1314 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_fp8:
1315 return selectSMFMACIntrin(
I);
1316 case Intrinsic::amdgcn_permlane16_swap:
1317 case Intrinsic::amdgcn_permlane32_swap:
1318 return selectPermlaneSwapIntrin(
I, IntrinsicID);
1319 case Intrinsic::amdgcn_wave_shuffle:
1320 return selectWaveShuffleIntrin(
I);
1331 if (
Size == 16 && !ST.has16BitInsts())
1334 const auto Select = [&](
unsigned S16Opc,
unsigned TrueS16Opc,
1335 unsigned FakeS16Opc,
unsigned S32Opc,
1338 return ST.hasTrue16BitInsts()
1339 ? ST.useRealTrue16Insts() ? TrueS16Opc : FakeS16Opc
1350 return Select(AMDGPU::V_CMP_NE_U16_e64, AMDGPU::V_CMP_NE_U16_t16_e64,
1351 AMDGPU::V_CMP_NE_U16_fake16_e64, AMDGPU::V_CMP_NE_U32_e64,
1352 AMDGPU::V_CMP_NE_U64_e64);
1354 return Select(AMDGPU::V_CMP_EQ_U16_e64, AMDGPU::V_CMP_EQ_U16_t16_e64,
1355 AMDGPU::V_CMP_EQ_U16_fake16_e64, AMDGPU::V_CMP_EQ_U32_e64,
1356 AMDGPU::V_CMP_EQ_U64_e64);
1358 return Select(AMDGPU::V_CMP_GT_I16_e64, AMDGPU::V_CMP_GT_I16_t16_e64,
1359 AMDGPU::V_CMP_GT_I16_fake16_e64, AMDGPU::V_CMP_GT_I32_e64,
1360 AMDGPU::V_CMP_GT_I64_e64);
1362 return Select(AMDGPU::V_CMP_GE_I16_e64, AMDGPU::V_CMP_GE_I16_t16_e64,
1363 AMDGPU::V_CMP_GE_I16_fake16_e64, AMDGPU::V_CMP_GE_I32_e64,
1364 AMDGPU::V_CMP_GE_I64_e64);
1366 return Select(AMDGPU::V_CMP_LT_I16_e64, AMDGPU::V_CMP_LT_I16_t16_e64,
1367 AMDGPU::V_CMP_LT_I16_fake16_e64, AMDGPU::V_CMP_LT_I32_e64,
1368 AMDGPU::V_CMP_LT_I64_e64);
1370 return Select(AMDGPU::V_CMP_LE_I16_e64, AMDGPU::V_CMP_LE_I16_t16_e64,
1371 AMDGPU::V_CMP_LE_I16_fake16_e64, AMDGPU::V_CMP_LE_I32_e64,
1372 AMDGPU::V_CMP_LE_I64_e64);
1374 return Select(AMDGPU::V_CMP_GT_U16_e64, AMDGPU::V_CMP_GT_U16_t16_e64,
1375 AMDGPU::V_CMP_GT_U16_fake16_e64, AMDGPU::V_CMP_GT_U32_e64,
1376 AMDGPU::V_CMP_GT_U64_e64);
1378 return Select(AMDGPU::V_CMP_GE_U16_e64, AMDGPU::V_CMP_GE_U16_t16_e64,
1379 AMDGPU::V_CMP_GE_U16_fake16_e64, AMDGPU::V_CMP_GE_U32_e64,
1380 AMDGPU::V_CMP_GE_U64_e64);
1382 return Select(AMDGPU::V_CMP_LT_U16_e64, AMDGPU::V_CMP_LT_U16_t16_e64,
1383 AMDGPU::V_CMP_LT_U16_fake16_e64, AMDGPU::V_CMP_LT_U32_e64,
1384 AMDGPU::V_CMP_LT_U64_e64);
1386 return Select(AMDGPU::V_CMP_LE_U16_e64, AMDGPU::V_CMP_LE_U16_t16_e64,
1387 AMDGPU::V_CMP_LE_U16_fake16_e64, AMDGPU::V_CMP_LE_U32_e64,
1388 AMDGPU::V_CMP_LE_U64_e64);
1391 return Select(AMDGPU::V_CMP_EQ_F16_e64, AMDGPU::V_CMP_EQ_F16_t16_e64,
1392 AMDGPU::V_CMP_EQ_F16_fake16_e64, AMDGPU::V_CMP_EQ_F32_e64,
1393 AMDGPU::V_CMP_EQ_F64_e64);
1395 return Select(AMDGPU::V_CMP_GT_F16_e64, AMDGPU::V_CMP_GT_F16_t16_e64,
1396 AMDGPU::V_CMP_GT_F16_fake16_e64, AMDGPU::V_CMP_GT_F32_e64,
1397 AMDGPU::V_CMP_GT_F64_e64);
1399 return Select(AMDGPU::V_CMP_GE_F16_e64, AMDGPU::V_CMP_GE_F16_t16_e64,
1400 AMDGPU::V_CMP_GE_F16_fake16_e64, AMDGPU::V_CMP_GE_F32_e64,
1401 AMDGPU::V_CMP_GE_F64_e64);
1403 return Select(AMDGPU::V_CMP_LT_F16_e64, AMDGPU::V_CMP_LT_F16_t16_e64,
1404 AMDGPU::V_CMP_LT_F16_fake16_e64, AMDGPU::V_CMP_LT_F32_e64,
1405 AMDGPU::V_CMP_LT_F64_e64);
1407 return Select(AMDGPU::V_CMP_LE_F16_e64, AMDGPU::V_CMP_LE_F16_t16_e64,
1408 AMDGPU::V_CMP_LE_F16_fake16_e64, AMDGPU::V_CMP_LE_F32_e64,
1409 AMDGPU::V_CMP_LE_F64_e64);
1411 return Select(AMDGPU::V_CMP_NEQ_F16_e64, AMDGPU::V_CMP_NEQ_F16_t16_e64,
1412 AMDGPU::V_CMP_NEQ_F16_fake16_e64, AMDGPU::V_CMP_NEQ_F32_e64,
1413 AMDGPU::V_CMP_NEQ_F64_e64);
1415 return Select(AMDGPU::V_CMP_O_F16_e64, AMDGPU::V_CMP_O_F16_t16_e64,
1416 AMDGPU::V_CMP_O_F16_fake16_e64, AMDGPU::V_CMP_O_F32_e64,
1417 AMDGPU::V_CMP_O_F64_e64);
1419 return Select(AMDGPU::V_CMP_U_F16_e64, AMDGPU::V_CMP_U_F16_t16_e64,
1420 AMDGPU::V_CMP_U_F16_fake16_e64, AMDGPU::V_CMP_U_F32_e64,
1421 AMDGPU::V_CMP_U_F64_e64);
1423 return Select(AMDGPU::V_CMP_NLG_F16_e64, AMDGPU::V_CMP_NLG_F16_t16_e64,
1424 AMDGPU::V_CMP_NLG_F16_fake16_e64, AMDGPU::V_CMP_NLG_F32_e64,
1425 AMDGPU::V_CMP_NLG_F64_e64);
1427 return Select(AMDGPU::V_CMP_NLE_F16_e64, AMDGPU::V_CMP_NLE_F16_t16_e64,
1428 AMDGPU::V_CMP_NLE_F16_fake16_e64, AMDGPU::V_CMP_NLE_F32_e64,
1429 AMDGPU::V_CMP_NLE_F64_e64);
1431 return Select(AMDGPU::V_CMP_NLT_F16_e64, AMDGPU::V_CMP_NLT_F16_t16_e64,
1432 AMDGPU::V_CMP_NLT_F16_fake16_e64, AMDGPU::V_CMP_NLT_F32_e64,
1433 AMDGPU::V_CMP_NLT_F64_e64);
1435 return Select(AMDGPU::V_CMP_NGE_F16_e64, AMDGPU::V_CMP_NGE_F16_t16_e64,
1436 AMDGPU::V_CMP_NGE_F16_fake16_e64, AMDGPU::V_CMP_NGE_F32_e64,
1437 AMDGPU::V_CMP_NGE_F64_e64);
1439 return Select(AMDGPU::V_CMP_NGT_F16_e64, AMDGPU::V_CMP_NGT_F16_t16_e64,
1440 AMDGPU::V_CMP_NGT_F16_fake16_e64, AMDGPU::V_CMP_NGT_F32_e64,
1441 AMDGPU::V_CMP_NGT_F64_e64);
1443 return Select(AMDGPU::V_CMP_NEQ_F16_e64, AMDGPU::V_CMP_NEQ_F16_t16_e64,
1444 AMDGPU::V_CMP_NEQ_F16_fake16_e64, AMDGPU::V_CMP_NEQ_F32_e64,
1445 AMDGPU::V_CMP_NEQ_F64_e64);
1447 return Select(AMDGPU::V_CMP_TRU_F16_e64, AMDGPU::V_CMP_TRU_F16_t16_e64,
1448 AMDGPU::V_CMP_TRU_F16_fake16_e64, AMDGPU::V_CMP_TRU_F32_e64,
1449 AMDGPU::V_CMP_TRU_F64_e64);
1451 return Select(AMDGPU::V_CMP_F_F16_e64, AMDGPU::V_CMP_F_F16_t16_e64,
1452 AMDGPU::V_CMP_F_F16_fake16_e64, AMDGPU::V_CMP_F_F32_e64,
1453 AMDGPU::V_CMP_F_F64_e64);
1458 unsigned Size)
const {
1460 if (!STI.hasScalarCompareEq64())
1465 return AMDGPU::S_CMP_LG_U64;
1467 return AMDGPU::S_CMP_EQ_U64;
1476 return AMDGPU::S_CMP_LG_U32;
1478 return AMDGPU::S_CMP_EQ_U32;
1480 return AMDGPU::S_CMP_GT_I32;
1482 return AMDGPU::S_CMP_GE_I32;
1484 return AMDGPU::S_CMP_LT_I32;
1486 return AMDGPU::S_CMP_LE_I32;
1488 return AMDGPU::S_CMP_GT_U32;
1490 return AMDGPU::S_CMP_GE_U32;
1492 return AMDGPU::S_CMP_LT_U32;
1494 return AMDGPU::S_CMP_LE_U32;
1496 return AMDGPU::S_CMP_EQ_F32;
1498 return AMDGPU::S_CMP_GT_F32;
1500 return AMDGPU::S_CMP_GE_F32;
1502 return AMDGPU::S_CMP_LT_F32;
1504 return AMDGPU::S_CMP_LE_F32;
1506 return AMDGPU::S_CMP_LG_F32;
1508 return AMDGPU::S_CMP_O_F32;
1510 return AMDGPU::S_CMP_U_F32;
1512 return AMDGPU::S_CMP_NLG_F32;
1514 return AMDGPU::S_CMP_NLE_F32;
1516 return AMDGPU::S_CMP_NLT_F32;
1518 return AMDGPU::S_CMP_NGE_F32;
1520 return AMDGPU::S_CMP_NGT_F32;
1522 return AMDGPU::S_CMP_NEQ_F32;
1529 if (!STI.hasSALUFloatInsts())
1534 return AMDGPU::S_CMP_EQ_F16;
1536 return AMDGPU::S_CMP_GT_F16;
1538 return AMDGPU::S_CMP_GE_F16;
1540 return AMDGPU::S_CMP_LT_F16;
1542 return AMDGPU::S_CMP_LE_F16;
1544 return AMDGPU::S_CMP_LG_F16;
1546 return AMDGPU::S_CMP_O_F16;
1548 return AMDGPU::S_CMP_U_F16;
1550 return AMDGPU::S_CMP_NLG_F16;
1552 return AMDGPU::S_CMP_NLE_F16;
1554 return AMDGPU::S_CMP_NLT_F16;
1556 return AMDGPU::S_CMP_NGE_F16;
1558 return AMDGPU::S_CMP_NGT_F16;
1560 return AMDGPU::S_CMP_NEQ_F16;
1569bool AMDGPUInstructionSelector::selectG_ICMP_or_FCMP(
MachineInstr &
I)
const {
1574 Register SrcReg =
I.getOperand(2).getReg();
1575 unsigned Size = RBI.getSizeInBits(SrcReg, *MRI, TRI);
1579 Register CCReg =
I.getOperand(0).getReg();
1580 if (!isVCC(CCReg, *MRI)) {
1581 int Opcode = getS_CMPOpcode(Pred,
Size);
1584 MachineInstr *ICmp =
BuildMI(*BB, &
I,
DL, TII.get(Opcode))
1585 .
add(
I.getOperand(2))
1586 .
add(
I.getOperand(3));
1587 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), CCReg)
1591 RBI.constrainGenericRegister(CCReg, AMDGPU::SReg_32RegClass, *MRI);
1592 I.eraseFromParent();
1596 if (
I.getOpcode() == AMDGPU::G_FCMP)
1603 MachineInstrBuilder ICmp;
1606 ICmp =
BuildMI(*BB, &
I,
DL, TII.get(Opcode),
I.getOperand(0).getReg())
1608 .
add(
I.getOperand(2))
1610 .
add(
I.getOperand(3))
1613 ICmp =
BuildMI(*BB, &
I,
DL, TII.get(Opcode),
I.getOperand(0).getReg())
1614 .
add(
I.getOperand(2))
1615 .
add(
I.getOperand(3));
1619 *TRI.getBoolRC(), *MRI);
1621 I.eraseFromParent();
1632 if (
MI->getParent() !=
MBB)
1636 if (
MI->getOpcode() == AMDGPU::COPY) {
1639 if (DstRB && SrcRB && DstRB->
getID() == AMDGPU::VCCRegBankID &&
1640 SrcRB->getID() == AMDGPU::SGPRRegBankID)
1645 if (
MI->getOpcode() == AMDGPU::G_AMDGPU_COPY_VCC_SCC)
1661bool AMDGPUInstructionSelector::selectBallot(
MachineInstr &
I)
const {
1664 Register DstReg =
I.getOperand(0).getReg();
1665 Register SrcReg =
I.getOperand(2).getReg();
1666 const unsigned BallotSize = MRI->getType(DstReg).getSizeInBits();
1667 const unsigned WaveSize = STI.getWavefrontSize();
1671 if (BallotSize != WaveSize && (BallotSize != 64 || WaveSize != 32))
1674 std::optional<ValueAndVReg> Arg =
1679 if (BallotSize != WaveSize) {
1680 Dst = MRI->createVirtualRegister(TRI.getBoolRC());
1684 const int64_t
Value = Arg->Value.getZExtValue();
1687 unsigned Opcode = WaveSize == 64 ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
1694 if (!RBI.constrainGenericRegister(Dst, *TRI.getBoolRC(), *MRI))
1700 if (!RBI.constrainGenericRegister(Dst, *TRI.getBoolRC(), *MRI))
1704 unsigned AndOpc = WaveSize == 64 ? AMDGPU::S_AND_B64 : AMDGPU::S_AND_B32;
1714 if (BallotSize != WaveSize) {
1715 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
1717 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
1724 I.eraseFromParent();
1728bool AMDGPUInstructionSelector::selectRelocConstant(
MachineInstr &
I)
const {
1729 Register DstReg =
I.getOperand(0).getReg();
1730 const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
1732 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
1735 const bool IsVALU = DstBank->
getID() == AMDGPU::VGPRRegBankID;
1737 Module *
M =
MF->getFunction().getParent();
1738 const MDNode *
Metadata =
I.getOperand(2).getMetadata();
1745 TII.get(IsVALU ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32), DstReg)
1748 I.eraseFromParent();
1752bool AMDGPUInstructionSelector::selectGroupStaticSize(
MachineInstr &
I)
const {
1755 Register DstReg =
I.getOperand(0).getReg();
1756 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
1757 unsigned Mov = DstRB->
getID() == AMDGPU::SGPRRegBankID ?
1758 AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1766 const SIMachineFunctionInfo *MFI =
MF->getInfo<SIMachineFunctionInfo>();
1769 Module *
M =
MF->getFunction().getParent();
1770 const GlobalValue *GV =
1775 I.eraseFromParent();
1780bool AMDGPUInstructionSelector::selectReturnAddress(
MachineInstr &
I)
const {
1785 Register DstReg =
I.getOperand(0).getReg();
1786 unsigned Depth =
I.getOperand(2).getImm();
1789 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
1791 !RBI.constrainGenericRegister(DstReg, *RC, *MRI))
1796 MF.getInfo<SIMachineFunctionInfo>()->isEntryFunction()) {
1799 I.eraseFromParent();
1803 MachineFrameInfo &MFI =
MF.getFrameInfo();
1808 Register ReturnAddrReg = TRI.getReturnAddressReg(
MF);
1810 AMDGPU::SReg_64RegClass,
DL);
1813 I.eraseFromParent();
1817bool AMDGPUInstructionSelector::selectEndCfIntrinsic(
MachineInstr &
MI)
const {
1821 BuildMI(*BB, &
MI,
MI.getDebugLoc(), TII.get(AMDGPU::SI_END_CF))
1822 .
add(
MI.getOperand(1));
1825 MI.eraseFromParent();
1827 if (!MRI->getRegClassOrNull(
Reg))
1828 MRI->setRegClass(
Reg, TRI.getWaveMaskRegClass());
1832bool AMDGPUInstructionSelector::selectDSOrderedIntrinsic(
1838 unsigned IndexOperand =
MI.getOperand(7).getImm();
1839 bool WaveRelease =
MI.getOperand(8).getImm() != 0;
1840 bool WaveDone =
MI.getOperand(9).getImm() != 0;
1842 if (WaveDone && !WaveRelease) {
1846 Fn,
"ds_ordered_count: wave_done requires wave_release",
DL));
1849 unsigned OrderedCountIndex = IndexOperand & 0x3f;
1850 IndexOperand &= ~0x3f;
1851 unsigned CountDw = 0;
1854 CountDw = (IndexOperand >> 24) & 0xf;
1855 IndexOperand &= ~(0xf << 24);
1857 if (CountDw < 1 || CountDw > 4) {
1860 Fn,
"ds_ordered_count: dword count must be between 1 and 4",
DL));
1868 Fn,
"ds_ordered_count: bad index operand",
DL));
1871 unsigned Instruction = IntrID == Intrinsic::amdgcn_ds_ordered_add ? 0 : 1;
1874 unsigned Offset0 = OrderedCountIndex << 2;
1875 unsigned Offset1 = WaveRelease | (WaveDone << 1) | (Instruction << 4);
1878 Offset1 |= (CountDw - 1) << 6;
1881 Offset1 |= ShaderType << 2;
1883 unsigned Offset = Offset0 | (Offset1 << 8);
1891 MachineInstrBuilder
DS =
1892 BuildMI(*
MBB, &
MI,
DL, TII.get(AMDGPU::DS_ORDERED_COUNT), DstReg)
1897 if (!RBI.constrainGenericRegister(M0Val, AMDGPU::SReg_32RegClass, *MRI))
1901 MI.eraseFromParent();
1907 case Intrinsic::amdgcn_ds_gws_init:
1908 return AMDGPU::DS_GWS_INIT;
1909 case Intrinsic::amdgcn_ds_gws_barrier:
1910 return AMDGPU::DS_GWS_BARRIER;
1911 case Intrinsic::amdgcn_ds_gws_sema_v:
1912 return AMDGPU::DS_GWS_SEMA_V;
1913 case Intrinsic::amdgcn_ds_gws_sema_br:
1914 return AMDGPU::DS_GWS_SEMA_BR;
1915 case Intrinsic::amdgcn_ds_gws_sema_p:
1916 return AMDGPU::DS_GWS_SEMA_P;
1917 case Intrinsic::amdgcn_ds_gws_sema_release_all:
1918 return AMDGPU::DS_GWS_SEMA_RELEASE_ALL;
1924bool AMDGPUInstructionSelector::selectDSGWSIntrinsic(
MachineInstr &
MI,
1926 if (!STI.hasGWS() || (IID == Intrinsic::amdgcn_ds_gws_sema_release_all &&
1927 !STI.hasGWSSemaReleaseAll()))
1931 const bool HasVSrc =
MI.getNumOperands() == 3;
1932 assert(HasVSrc ||
MI.getNumOperands() == 2);
1934 Register BaseOffset =
MI.getOperand(HasVSrc ? 2 : 1).getReg();
1935 const RegisterBank *OffsetRB = RBI.getRegBank(BaseOffset, *MRI, TRI);
1936 if (OffsetRB->
getID() != AMDGPU::SGPRRegBankID)
1945 MachineInstr *Readfirstlane =
nullptr;
1950 if (OffsetDef->
getOpcode() == AMDGPU::V_READFIRSTLANE_B32) {
1951 Readfirstlane = OffsetDef;
1956 if (OffsetDef->
getOpcode() == AMDGPU::G_CONSTANT) {
1966 std::tie(BaseOffset, ImmOffset) =
1969 if (Readfirstlane) {
1972 if (!RBI.constrainGenericRegister(BaseOffset, AMDGPU::VGPR_32RegClass, *MRI))
1978 if (!RBI.constrainGenericRegister(BaseOffset,
1979 AMDGPU::SReg_32RegClass, *MRI))
1983 Register M0Base = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
1998 const MCInstrDesc &InstrDesc = TII.get(
Opc);
2003 int Data0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
2006 TRI.getSubRegisterClass(DataRC, AMDGPU::sub0);
2010 if (!RBI.constrainGenericRegister(VSrc, *DataRC, *MRI))
2020 Register DataReg = MRI->createVirtualRegister(DataRC);
2021 if (!RBI.constrainGenericRegister(VSrc, *SubRC, *MRI))
2024 Register UndefReg = MRI->createVirtualRegister(SubRC);
2043 MI.eraseFromParent();
2047bool AMDGPUInstructionSelector::selectDSAppendConsume(
MachineInstr &
MI,
2048 bool IsAppend)
const {
2049 Register PtrBase =
MI.getOperand(2).getReg();
2050 LLT PtrTy = MRI->getType(PtrBase);
2054 std::tie(PtrBase,
Offset) = selectDS1Addr1OffsetImpl(
MI.getOperand(2));
2057 if (!isDSOffsetLegal(PtrBase,
Offset)) {
2058 PtrBase =
MI.getOperand(2).getReg();
2064 const unsigned Opc = IsAppend ? AMDGPU::DS_APPEND : AMDGPU::DS_CONSUME;
2068 if (!RBI.constrainGenericRegister(PtrBase, AMDGPU::SReg_32RegClass, *MRI))
2075 MI.eraseFromParent();
2080bool AMDGPUInstructionSelector::selectInitWholeWave(
MachineInstr &
MI)
const {
2082 SIMachineFunctionInfo *MFInfo =
MF->getInfo<SIMachineFunctionInfo>();
2093 TFE = TexFailCtrl & 0x1;
2095 LWE = TexFailCtrl & 0x2;
2098 return TexFailCtrl == 0;
2101bool AMDGPUInstructionSelector::selectImageIntrinsic(
2109 Register ResultDef =
MI.getOperand(0).getReg();
2110 if (MRI->use_nodbg_empty(ResultDef))
2114 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
2123 const unsigned ArgOffset =
MI.getNumExplicitDefs() + 1;
2125 Register VDataIn = AMDGPU::NoRegister;
2126 Register VDataOut = AMDGPU::NoRegister;
2128 int NumVDataDwords = -1;
2129 bool IsD16 =
MI.getOpcode() == AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16 ||
2130 MI.getOpcode() == AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16;
2136 Unorm =
MI.getOperand(ArgOffset + Intr->
UnormIndex).getImm() != 0;
2140 bool IsTexFail =
false;
2142 TFE, LWE, IsTexFail))
2145 const int Flags =
MI.getOperand(ArgOffset + Intr->
NumArgs).getImm();
2146 const bool IsA16 = (
Flags & 1) != 0;
2147 const bool IsG16 = (
Flags & 2) != 0;
2150 if (IsA16 && !STI.hasG16() && !IsG16)
2154 unsigned DMaskLanes = 0;
2156 if (BaseOpcode->
Atomic) {
2158 VDataOut =
MI.getOperand(0).getReg();
2159 VDataIn =
MI.getOperand(2).getReg();
2160 LLT Ty = MRI->getType(VDataIn);
2163 const bool Is64Bit = BaseOpcode->
AtomicX2 ?
2168 assert(
MI.getOperand(3).getReg() == AMDGPU::NoRegister);
2170 DMask = Is64Bit ? 0xf : 0x3;
2171 NumVDataDwords = Is64Bit ? 4 : 2;
2173 DMask = Is64Bit ? 0x3 : 0x1;
2174 NumVDataDwords = Is64Bit ? 2 : 1;
2177 DMask =
MI.getOperand(ArgOffset + Intr->
DMaskIndex).getImm();
2180 if (BaseOpcode->
Store) {
2181 VDataIn =
MI.getOperand(1).getReg();
2182 VDataTy = MRI->getType(VDataIn);
2187 VDataOut =
MI.getOperand(0).getReg();
2188 VDataTy = MRI->getType(VDataOut);
2189 NumVDataDwords = DMaskLanes;
2191 if (IsD16 && !STI.hasUnpackedD16VMem())
2192 NumVDataDwords = (DMaskLanes + 1) / 2;
2197 if (Subtarget->hasG16() && IsG16) {
2198 const AMDGPU::MIMGG16MappingInfo *G16MappingInfo =
2201 IntrOpcode = G16MappingInfo->
G16;
2205 assert((!IsTexFail || DMaskLanes >= 1) &&
"should have legalized this");
2215 int NumVAddrRegs = 0;
2216 int NumVAddrDwords = 0;
2219 MachineOperand &AddrOp =
MI.getOperand(ArgOffset +
I);
2220 if (!AddrOp.
isReg())
2228 NumVAddrDwords += (MRI->getType(Addr).getSizeInBits() + 31) / 32;
2235 NumVAddrRegs != 1 &&
2236 (STI.hasPartialNSAEncoding() ? NumVAddrDwords >= NumVAddrRegs
2237 : NumVAddrDwords == NumVAddrRegs);
2238 if (UseNSA && !STI.hasFeature(AMDGPU::FeatureNSAEncoding)) {
2249 NumVDataDwords, NumVAddrDwords);
2250 }
else if (IsGFX12Plus) {
2252 NumVDataDwords, NumVAddrDwords);
2253 }
else if (IsGFX11Plus) {
2255 UseNSA ? AMDGPU::MIMGEncGfx11NSA
2256 : AMDGPU::MIMGEncGfx11Default,
2257 NumVDataDwords, NumVAddrDwords);
2258 }
else if (IsGFX10Plus) {
2260 UseNSA ? AMDGPU::MIMGEncGfx10NSA
2261 : AMDGPU::MIMGEncGfx10Default,
2262 NumVDataDwords, NumVAddrDwords);
2264 if (Subtarget->hasGFX90AInsts()) {
2266 NumVDataDwords, NumVAddrDwords);
2270 <<
"requested image instruction is not supported on this GPU\n");
2277 NumVDataDwords, NumVAddrDwords);
2280 NumVDataDwords, NumVAddrDwords);
2290 const bool Is64 = MRI->getType(VDataOut).getSizeInBits() == 64;
2292 Register TmpReg = MRI->createVirtualRegister(
2293 Is64 ? &AMDGPU::VReg_128RegClass : &AMDGPU::VReg_64RegClass);
2294 unsigned SubReg = Is64 ? AMDGPU::sub0_sub1 : AMDGPU::sub0;
2297 if (!MRI->use_empty(VDataOut)) {
2310 for (
int I = 0;
I != NumVAddrRegs; ++
I) {
2311 MachineOperand &SrcOp =
MI.getOperand(ArgOffset + Intr->
VAddrStart +
I);
2312 if (SrcOp.
isReg()) {
2331 STI.hasFeature(AMDGPU::FeatureR128A16) ? -1 : 0);
2333 MIB.
addImm(IsA16 ? -1 : 0);
2335 if (!Subtarget->hasGFX90AInsts()) {
2347 MIB.
addImm(IsD16 ? -1 : 0);
2349 MI.eraseFromParent();
2351 TII.enforceOperandRCAlignment(*MIB, AMDGPU::OpName::vaddr);
2357bool AMDGPUInstructionSelector::selectDSBvhStackIntrinsic(
2368 unsigned Offset =
MI.getOperand(6).getImm();
2372 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
2373 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
2374 Opc = AMDGPU::DS_BVH_STACK_RTN_B32;
2376 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
2377 Opc = AMDGPU::DS_BVH_STACK_PUSH8_POP1_RTN_B32;
2379 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn:
2380 Opc = AMDGPU::DS_BVH_STACK_PUSH8_POP2_RTN_B64;
2392 MI.eraseFromParent();
2397bool AMDGPUInstructionSelector::selectG_INTRINSIC_W_SIDE_EFFECTS(
2400 switch (IntrinsicID) {
2401 case Intrinsic::amdgcn_end_cf:
2402 return selectEndCfIntrinsic(
I);
2403 case Intrinsic::amdgcn_ds_ordered_add:
2404 case Intrinsic::amdgcn_ds_ordered_swap:
2405 return selectDSOrderedIntrinsic(
I, IntrinsicID);
2406 case Intrinsic::amdgcn_ds_gws_init:
2407 case Intrinsic::amdgcn_ds_gws_barrier:
2408 case Intrinsic::amdgcn_ds_gws_sema_v:
2409 case Intrinsic::amdgcn_ds_gws_sema_br:
2410 case Intrinsic::amdgcn_ds_gws_sema_p:
2411 case Intrinsic::amdgcn_ds_gws_sema_release_all:
2412 return selectDSGWSIntrinsic(
I, IntrinsicID);
2413 case Intrinsic::amdgcn_ds_append:
2414 return selectDSAppendConsume(
I,
true);
2415 case Intrinsic::amdgcn_ds_consume:
2416 return selectDSAppendConsume(
I,
false);
2417 case Intrinsic::amdgcn_init_whole_wave:
2418 return selectInitWholeWave(
I);
2419 case Intrinsic::amdgcn_raw_buffer_load_lds:
2420 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
2421 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
2422 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
2423 case Intrinsic::amdgcn_struct_buffer_load_lds:
2424 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
2425 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
2426 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
2427 return selectBufferLoadLds(
I);
2432 case Intrinsic::amdgcn_load_to_lds:
2433 case Intrinsic::amdgcn_load_async_to_lds:
2434 case Intrinsic::amdgcn_global_load_lds:
2435 case Intrinsic::amdgcn_global_load_async_lds:
2436 return selectGlobalLoadLds(
I);
2437 case Intrinsic::amdgcn_tensor_load_to_lds:
2438 case Intrinsic::amdgcn_tensor_store_from_lds:
2439 return selectTensorLoadStore(
I, IntrinsicID);
2440 case Intrinsic::amdgcn_asyncmark:
2441 case Intrinsic::amdgcn_wait_asyncmark:
2442 if (!Subtarget->hasAsyncMark())
2445 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
2446 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
2447 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
2448 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn:
2449 return selectDSBvhStackIntrinsic(
I);
2450 case Intrinsic::amdgcn_s_alloc_vgpr: {
2456 Register ResReg =
I.getOperand(0).getReg();
2458 MachineInstr *AllocMI =
BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::S_ALLOC_VGPR))
2459 .
add(
I.getOperand(2));
2462 I.eraseFromParent();
2464 return RBI.constrainGenericRegister(ResReg, AMDGPU::SReg_32RegClass, *MRI);
2466 case Intrinsic::amdgcn_s_barrier_init:
2467 case Intrinsic::amdgcn_s_barrier_signal_var:
2468 return selectNamedBarrierInit(
I, IntrinsicID);
2469 case Intrinsic::amdgcn_s_wakeup_barrier:
2470 case Intrinsic::amdgcn_s_barrier_join:
2471 case Intrinsic::amdgcn_s_get_named_barrier_state:
2472 return selectNamedBarrierInst(
I, IntrinsicID);
2473 case Intrinsic::amdgcn_s_get_barrier_state:
2474 return selectSGetBarrierState(
I, IntrinsicID);
2475 case Intrinsic::amdgcn_s_barrier_signal_isfirst:
2476 return selectSBarrierSignalIsfirst(
I, IntrinsicID);
2481bool AMDGPUInstructionSelector::selectG_SELECT(
MachineInstr &
I)
const {
2488 Register DstReg =
I.getOperand(0).getReg();
2489 unsigned Size = RBI.getSizeInBits(DstReg, *MRI, TRI);
2491 const MachineOperand &CCOp =
I.getOperand(1);
2493 if (!isVCC(CCReg, *MRI)) {
2494 unsigned SelectOpcode =
Size == 64 ? AMDGPU::S_CSELECT_B64 :
2495 AMDGPU::S_CSELECT_B32;
2496 MachineInstr *CopySCC =
BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::SCC)
2502 if (!MRI->getRegClassOrNull(CCReg))
2503 MRI->setRegClass(CCReg, TRI.getConstrainedRegClassForReg(CCReg, *MRI));
2505 .
add(
I.getOperand(2))
2506 .
add(
I.getOperand(3));
2510 I.eraseFromParent();
2519 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
2521 .
add(
I.getOperand(3))
2523 .
add(
I.getOperand(2))
2524 .
add(
I.getOperand(1));
2527 I.eraseFromParent();
2531bool AMDGPUInstructionSelector::selectG_TRUNC(
MachineInstr &
I)
const {
2532 Register DstReg =
I.getOperand(0).getReg();
2533 Register SrcReg =
I.getOperand(1).getReg();
2534 const LLT DstTy = MRI->getType(DstReg);
2535 const LLT SrcTy = MRI->getType(SrcReg);
2538 const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
2539 const RegisterBank *DstRB;
2545 DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
2550 const bool IsVALU = DstRB->
getID() == AMDGPU::VGPRRegBankID;
2556 TRI.getRegClassForSizeOnBank(SrcSize, *SrcRB);
2558 TRI.getRegClassForSizeOnBank(DstSize, *DstRB);
2559 if (!SrcRC || !DstRC)
2562 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
2563 !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI)) {
2568 if (DstRC == &AMDGPU::VGPR_16RegClass && SrcSize == 32) {
2569 assert(STI.useRealTrue16Insts());
2573 .
addReg(SrcReg, {}, AMDGPU::lo16);
2574 I.eraseFromParent();
2582 Register LoReg = MRI->createVirtualRegister(DstRC);
2583 Register HiReg = MRI->createVirtualRegister(DstRC);
2585 .
addReg(SrcReg, {}, AMDGPU::sub0);
2587 .
addReg(SrcReg, {}, AMDGPU::sub1);
2589 if (IsVALU && STI.hasSDWA()) {
2592 MachineInstr *MovSDWA =
2593 BuildMI(*
MBB,
I,
DL, TII.get(AMDGPU::V_MOV_B32_sdwa), DstReg)
2603 Register TmpReg0 = MRI->createVirtualRegister(DstRC);
2604 Register TmpReg1 = MRI->createVirtualRegister(DstRC);
2605 Register ImmReg = MRI->createVirtualRegister(DstRC);
2607 BuildMI(*
MBB,
I,
DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), TmpReg0)
2617 unsigned MovOpc = IsVALU ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32;
2618 unsigned AndOpc = IsVALU ? AMDGPU::V_AND_B32_e64 : AMDGPU::S_AND_B32;
2619 unsigned OrOpc = IsVALU ? AMDGPU::V_OR_B32_e64 : AMDGPU::S_OR_B32;
2631 And.setOperandDead(3);
2632 Or.setOperandDead(3);
2636 I.eraseFromParent();
2644 unsigned SubRegIdx = DstSize < 32
2645 ?
static_cast<unsigned>(AMDGPU::sub0)
2646 : TRI.getSubRegFromChannel(0, DstSize / 32);
2647 if (SubRegIdx == AMDGPU::NoSubRegister)
2653 = TRI.getSubClassWithSubReg(SrcRC, SubRegIdx);
2657 if (SrcWithSubRC != SrcRC) {
2658 if (!RBI.constrainGenericRegister(SrcReg, *SrcWithSubRC, *MRI))
2662 I.getOperand(1).setSubReg(SubRegIdx);
2665 I.setDesc(TII.get(TargetOpcode::COPY));
2672 int SignedMask =
static_cast<int>(Mask);
2673 return SignedMask >= -16 && SignedMask <= 64;
2677const RegisterBank *AMDGPUInstructionSelector::getArtifactRegBank(
2686 return &RBI.getRegBankFromRegClass(*RC, LLT());
2690bool AMDGPUInstructionSelector::selectG_SZA_EXT(
MachineInstr &
I)
const {
2691 bool InReg =
I.getOpcode() == AMDGPU::G_SEXT_INREG;
2692 bool Signed =
I.getOpcode() == AMDGPU::G_SEXT || InReg;
2695 const Register DstReg =
I.getOperand(0).getReg();
2696 const Register SrcReg =
I.getOperand(1).getReg();
2698 const LLT DstTy = MRI->getType(DstReg);
2699 const LLT SrcTy = MRI->getType(SrcReg);
2700 const unsigned SrcSize =
I.getOpcode() == AMDGPU::G_SEXT_INREG ?
2707 const RegisterBank *SrcBank = getArtifactRegBank(SrcReg, *MRI, TRI);
2710 if (
I.getOpcode() == AMDGPU::G_ANYEXT) {
2712 return selectCOPY(
I);
2715 TRI.getRegClassForTypeOnBank(SrcTy, *SrcBank);
2716 const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
2718 TRI.getRegClassForSizeOnBank(DstSize, *DstBank);
2720 Register UndefReg = MRI->createVirtualRegister(SrcRC);
2721 BuildMI(
MBB,
I,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefReg);
2727 I.eraseFromParent();
2729 return RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) &&
2730 RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI);
2733 if (SrcBank->
getID() == AMDGPU::VGPRRegBankID && DstSize <= 32) {
2739 MachineInstr *ExtI =
2743 I.eraseFromParent();
2748 const unsigned BFE =
Signed ? AMDGPU::V_BFE_I32_e64 : AMDGPU::V_BFE_U32_e64;
2749 MachineInstr *ExtI =
2754 I.eraseFromParent();
2759 if (SrcBank->
getID() == AMDGPU::SGPRRegBankID && DstSize <= 64) {
2761 AMDGPU::SReg_64RegClass : AMDGPU::SReg_32RegClass;
2762 if (!RBI.constrainGenericRegister(SrcReg, SrcRC, *MRI))
2765 if (
Signed && DstSize == 32 && (SrcSize == 8 || SrcSize == 16)) {
2766 const unsigned SextOpc = SrcSize == 8 ?
2767 AMDGPU::S_SEXT_I32_I8 : AMDGPU::S_SEXT_I32_I16;
2770 I.eraseFromParent();
2771 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_32RegClass, *MRI);
2776 if (DstSize > 32 && SrcSize == 32) {
2777 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2778 unsigned SubReg = InReg ? AMDGPU::sub0 : AMDGPU::NoSubRegister;
2781 .
addReg(SrcReg, {}, SubReg)
2789 .
addReg(SrcReg, {}, SubReg)
2790 .addImm(AMDGPU::sub0)
2793 I.eraseFromParent();
2794 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_64RegClass,
2798 const unsigned BFE64 =
Signed ? AMDGPU::S_BFE_I64 : AMDGPU::S_BFE_U64;
2799 const unsigned BFE32 =
Signed ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32;
2802 if (DstSize > 32 && (SrcSize <= 32 || InReg)) {
2804 Register ExtReg = MRI->createVirtualRegister(&AMDGPU::SReg_64RegClass);
2805 Register UndefReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2806 unsigned SubReg = InReg ? AMDGPU::sub0 : AMDGPU::NoSubRegister;
2808 BuildMI(
MBB,
I,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefReg);
2810 .
addReg(SrcReg, {}, SubReg)
2811 .addImm(AMDGPU::sub0)
2819 I.eraseFromParent();
2820 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_64RegClass, *MRI);
2835 I.eraseFromParent();
2836 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_32RegClass, *MRI);
2888 assert(Mask.size() == 2);
2890 if (Mask[0] == 1 && Mask[1] <= 1) {
2905 if (Unmerge->getNumDefs() == 2 && Unmerge->getOperand(0).getReg() == In &&
2923bool AMDGPUInstructionSelector::selectG_FPEXT(
MachineInstr &
I)
const {
2924 if (!Subtarget->hasSALUFloatInsts())
2927 Register Dst =
I.getOperand(0).getReg();
2928 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
2929 if (DstRB->
getID() != AMDGPU::SGPRRegBankID)
2932 Register Src =
I.getOperand(1).getReg();
2938 BuildMI(*BB, &
I,
I.getDebugLoc(), TII.get(AMDGPU::S_CVT_HI_F32_F16), Dst)
2940 I.eraseFromParent();
2941 return RBI.constrainGenericRegister(Dst, AMDGPU::SReg_32RegClass, *MRI);
2948bool AMDGPUInstructionSelector::selectG_FNEG(
MachineInstr &
MI)
const {
2961 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
2962 if (DstRB->
getID() != AMDGPU::SGPRRegBankID ||
2967 MachineInstr *Fabs =
getOpcodeDef(TargetOpcode::G_FABS, Src, *MRI);
2971 if (!RBI.constrainGenericRegister(Src, AMDGPU::SReg_64RegClass, *MRI) ||
2972 !RBI.constrainGenericRegister(Dst, AMDGPU::SReg_64RegClass, *MRI))
2977 Register LoReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2978 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2979 Register ConstReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2980 Register OpReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2982 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), LoReg)
2983 .
addReg(Src, {}, AMDGPU::sub0);
2984 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), HiReg)
2985 .
addReg(Src, {}, AMDGPU::sub1);
2986 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_MOV_B32), ConstReg)
2990 unsigned Opc = Fabs ? AMDGPU::S_OR_B32 : AMDGPU::S_XOR_B32;
2995 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::REG_SEQUENCE), Dst)
3000 MI.eraseFromParent();
3005bool AMDGPUInstructionSelector::selectG_FABS(
MachineInstr &
MI)
const {
3007 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
3008 if (DstRB->
getID() != AMDGPU::SGPRRegBankID ||
3015 Register LoReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3016 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3017 Register ConstReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3018 Register OpReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3020 if (!RBI.constrainGenericRegister(Src, AMDGPU::SReg_64RegClass, *MRI) ||
3021 !RBI.constrainGenericRegister(Dst, AMDGPU::SReg_64RegClass, *MRI))
3024 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), LoReg)
3025 .
addReg(Src, {}, AMDGPU::sub0);
3026 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), HiReg)
3027 .
addReg(Src, {}, AMDGPU::sub1);
3028 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_MOV_B32), ConstReg)
3033 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_AND_B32), OpReg)
3037 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::REG_SEQUENCE), Dst)
3043 MI.eraseFromParent();
3048 return MI.getOpcode() == TargetOpcode::G_CONSTANT;
3054 unsigned OpNo =
Load.getOpcode() == AMDGPU::G_PREFETCH ? 0 : 1;
3055 const MachineInstr *PtrMI =
3056 MRI.getUniqueVRegDef(
Load.getOperand(OpNo).getReg());
3060 if (PtrMI->
getOpcode() != TargetOpcode::G_PTR_ADD)
3065 for (
unsigned i = 1; i != 3; ++i) {
3066 const MachineOperand &GEPOp = PtrMI->
getOperand(i);
3067 const MachineInstr *OpDef = MRI.getUniqueVRegDef(GEPOp.
getReg());
3072 assert(GEPInfo.Imm == 0);
3076 const RegisterBank *OpBank = RBI.getRegBank(GEPOp.
getReg(), MRI, TRI);
3077 if (OpBank->
getID() == AMDGPU::SGPRRegBankID)
3078 GEPInfo.SgprParts.push_back(GEPOp.
getReg());
3080 GEPInfo.VgprParts.push_back(GEPOp.
getReg());
3084 getAddrModeInfo(*PtrMI, MRI, AddrInfo);
3087bool AMDGPUInstructionSelector::isSGPR(
Register Reg)
const {
3088 return RBI.getRegBank(
Reg, *MRI, TRI)->getID() == AMDGPU::SGPRRegBankID;
3091bool AMDGPUInstructionSelector::isInstrUniform(
const MachineInstr &
MI)
const {
3092 if (!
MI.hasOneMemOperand())
3095 const MachineMemOperand *MMO = *
MI.memoperands_begin();
3108 if (
MI.getOpcode() == AMDGPU::G_PREFETCH)
3109 return RBI.getRegBank(
MI.getOperand(0).getReg(), *MRI, TRI)->getID() ==
3110 AMDGPU::SGPRRegBankID;
3113 return I &&
I->getMetadata(
"amdgpu.uniform");
3117 for (
const GEPInfo &GEPInfo : AddrInfo) {
3118 if (!GEPInfo.VgprParts.empty())
3124void AMDGPUInstructionSelector::initM0(
MachineInstr &
I)
const {
3125 const LLT PtrTy = MRI->getType(
I.getOperand(1).getReg());
3128 STI.ldsRequiresM0Init()) {
3132 BuildMI(*BB, &
I,
I.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), AMDGPU::M0)
3137bool AMDGPUInstructionSelector::selectG_LOAD_STORE_ATOMICRMW(
3144 if (
Reg.isPhysical())
3148 const unsigned Opcode =
MI.getOpcode();
3150 if (Opcode == AMDGPU::COPY)
3153 if (Opcode == AMDGPU::G_AND || Opcode == AMDGPU::G_OR ||
3154 Opcode == AMDGPU::G_XOR)
3159 return GI->is(Intrinsic::amdgcn_class);
3161 return Opcode == AMDGPU::G_ICMP || Opcode == AMDGPU::G_FCMP;
3164bool AMDGPUInstructionSelector::selectG_BRCOND(
MachineInstr &
I)
const {
3166 MachineOperand &CondOp =
I.getOperand(0);
3179 if (!isVCC(CondReg, *MRI)) {
3183 CondPhysReg = AMDGPU::SCC;
3184 BrOpcode = AMDGPU::S_CBRANCH_SCC1;
3185 ConstrainRC = &AMDGPU::SReg_32RegClass;
3192 const bool Is64 = STI.isWave64();
3193 const unsigned Opcode = Is64 ? AMDGPU::S_AND_B64 : AMDGPU::S_AND_B32;
3194 const Register Exec = Is64 ? AMDGPU::EXEC : AMDGPU::EXEC_LO;
3196 Register TmpReg = MRI->createVirtualRegister(TRI.getBoolRC());
3197 BuildMI(*BB, &
I,
DL, TII.get(Opcode), TmpReg)
3204 CondPhysReg = TRI.getVCC();
3205 BrOpcode = AMDGPU::S_CBRANCH_VCCNZ;
3206 ConstrainRC = TRI.getBoolRC();
3209 if (!MRI->getRegClassOrNull(CondReg))
3210 MRI->setRegClass(CondReg, ConstrainRC);
3212 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), CondPhysReg)
3215 .
addMBB(
I.getOperand(1).getMBB());
3217 I.eraseFromParent();
3221bool AMDGPUInstructionSelector::selectG_GLOBAL_VALUE(
3223 Register DstReg =
I.getOperand(0).getReg();
3224 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3225 const bool IsVGPR = DstRB->
getID() == AMDGPU::VGPRRegBankID;
3226 I.setDesc(TII.get(IsVGPR ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32));
3230 return RBI.constrainGenericRegister(
3231 DstReg, IsVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass, *MRI);
3234bool AMDGPUInstructionSelector::selectG_PTRMASK(
MachineInstr &
I)
const {
3235 Register DstReg =
I.getOperand(0).getReg();
3236 Register SrcReg =
I.getOperand(1).getReg();
3237 Register MaskReg =
I.getOperand(2).getReg();
3238 LLT Ty = MRI->getType(DstReg);
3239 LLT MaskTy = MRI->getType(MaskReg);
3243 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3244 const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
3245 const RegisterBank *MaskRB = RBI.getRegBank(MaskReg, *MRI, TRI);
3246 const bool IsVGPR = DstRB->
getID() == AMDGPU::VGPRRegBankID;
3252 APInt MaskOnes =
VT->getKnownOnes(MaskReg).zext(64);
3256 const bool CanCopyLow32 = (MaskOnes & MaskLo32) == MaskLo32;
3257 const bool CanCopyHi32 = (MaskOnes & MaskHi32) == MaskHi32;
3260 !CanCopyLow32 && !CanCopyHi32) {
3261 auto MIB =
BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_AND_B64), DstReg)
3265 I.eraseFromParent();
3270 unsigned NewOpc = IsVGPR ? AMDGPU::V_AND_B32_e64 : AMDGPU::S_AND_B32;
3272 = IsVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
3277 TRI.getRegClassForTypeOnBank(MaskTy, *MaskRB);
3279 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
3280 !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
3281 !RBI.constrainGenericRegister(MaskReg, *MaskRC, *MRI))
3286 "ptrmask should have been narrowed during legalize");
3288 auto NewOp =
BuildMI(*BB, &
I,
DL, TII.get(NewOpc), DstReg)
3294 I.eraseFromParent();
3298 Register HiReg = MRI->createVirtualRegister(&RegRC);
3299 Register LoReg = MRI->createVirtualRegister(&RegRC);
3302 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), LoReg)
3303 .
addReg(SrcReg, {}, AMDGPU::sub0);
3304 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), HiReg)
3305 .
addReg(SrcReg, {}, AMDGPU::sub1);
3314 Register MaskLo = MRI->createVirtualRegister(&RegRC);
3315 MaskedLo = MRI->createVirtualRegister(&RegRC);
3317 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), MaskLo)
3318 .
addReg(MaskReg, {}, AMDGPU::sub0);
3319 BuildMI(*BB, &
I,
DL, TII.get(NewOpc), MaskedLo)
3328 Register MaskHi = MRI->createVirtualRegister(&RegRC);
3329 MaskedHi = MRI->createVirtualRegister(&RegRC);
3331 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), MaskHi)
3332 .
addReg(MaskReg, {}, AMDGPU::sub1);
3333 BuildMI(*BB, &
I,
DL, TII.get(NewOpc), MaskedHi)
3338 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
3343 I.eraseFromParent();
3349static std::pair<Register, unsigned>
3356 std::tie(IdxBaseReg,
Offset) =
3358 if (IdxBaseReg == AMDGPU::NoRegister) {
3362 IdxBaseReg = IdxReg;
3369 if (
static_cast<unsigned>(
Offset) >= SubRegs.
size())
3370 return std::pair(IdxReg, SubRegs[0]);
3371 return std::pair(IdxBaseReg, SubRegs[
Offset]);
3374bool AMDGPUInstructionSelector::selectG_EXTRACT_VECTOR_ELT(
3380 LLT DstTy = MRI->getType(DstReg);
3381 LLT SrcTy = MRI->getType(SrcReg);
3383 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3384 const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
3385 const RegisterBank *IdxRB = RBI.getRegBank(IdxReg, *MRI, TRI);
3389 if (IdxRB->
getID() != AMDGPU::SGPRRegBankID)
3393 TRI.getRegClassForTypeOnBank(SrcTy, *SrcRB);
3395 TRI.getRegClassForTypeOnBank(DstTy, *DstRB);
3396 if (!SrcRC || !DstRC)
3398 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
3399 !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
3400 !RBI.constrainGenericRegister(IdxReg, AMDGPU::SReg_32RegClass, *MRI))
3411 if (SrcRB->
getID() == AMDGPU::SGPRRegBankID) {
3415 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3418 unsigned Opc = Is64 ? AMDGPU::S_MOVRELS_B64 : AMDGPU::S_MOVRELS_B32;
3420 .
addReg(SrcReg, {}, SubReg)
3422 MI.eraseFromParent();
3429 if (!STI.useVGPRIndexMode()) {
3430 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3432 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::V_MOVRELS_B32_e32), DstReg)
3433 .
addReg(SrcReg, {}, SubReg)
3435 MI.eraseFromParent();
3439 const MCInstrDesc &GPRIDXDesc =
3440 TII.getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*SrcRC),
true);
3446 MI.eraseFromParent();
3451bool AMDGPUInstructionSelector::selectG_INSERT_VECTOR_ELT(
3458 LLT VecTy = MRI->getType(DstReg);
3459 LLT ValTy = MRI->getType(ValReg);
3463 const RegisterBank *VecRB = RBI.getRegBank(VecReg, *MRI, TRI);
3464 const RegisterBank *ValRB = RBI.getRegBank(ValReg, *MRI, TRI);
3465 const RegisterBank *IdxRB = RBI.getRegBank(IdxReg, *MRI, TRI);
3471 if (IdxRB->
getID() != AMDGPU::SGPRRegBankID)
3475 TRI.getRegClassForTypeOnBank(VecTy, *VecRB);
3477 TRI.getRegClassForTypeOnBank(ValTy, *ValRB);
3479 if (!RBI.constrainGenericRegister(VecReg, *VecRC, *MRI) ||
3480 !RBI.constrainGenericRegister(DstReg, *VecRC, *MRI) ||
3481 !RBI.constrainGenericRegister(ValReg, *ValRC, *MRI) ||
3482 !RBI.constrainGenericRegister(IdxReg, AMDGPU::SReg_32RegClass, *MRI))
3485 if (VecRB->
getID() == AMDGPU::VGPRRegBankID && ValSize != 32)
3489 std::tie(IdxReg, SubReg) =
3492 const bool IndexMode = VecRB->
getID() == AMDGPU::VGPRRegBankID &&
3493 STI.useVGPRIndexMode();
3499 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3502 const MCInstrDesc &RegWriteOp = TII.getIndirectRegWriteMovRelPseudo(
3503 VecSize, ValSize, VecRB->
getID() == AMDGPU::SGPRRegBankID);
3508 MI.eraseFromParent();
3512 const MCInstrDesc &GPRIDXDesc =
3513 TII.getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC),
false);
3520 MI.eraseFromParent();
3526 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
3527 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
3528 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
3529 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
3530 case Intrinsic::amdgcn_load_async_to_lds:
3531 case Intrinsic::amdgcn_global_load_async_lds:
3537bool AMDGPUInstructionSelector::selectBufferLoadLds(
MachineInstr &
MI)
const {
3538 if (!Subtarget->hasVMemToLDSLoad())
3541 unsigned Size =
MI.getOperand(3).getImm();
3545 const bool HasVIndex =
MI.getNumOperands() == 9;
3549 VIndex =
MI.getOperand(4).getReg();
3553 Register VOffset =
MI.getOperand(4 + OpOffset).getReg();
3554 std::optional<ValueAndVReg> MaybeVOffset =
3556 const bool HasVOffset = !MaybeVOffset || MaybeVOffset->Value.getZExtValue();
3562 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_BOTHEN
3563 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_IDXEN
3564 : HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFEN
3565 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFSET;
3568 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_BOTHEN
3569 : AMDGPU::BUFFER_LOAD_USHORT_LDS_IDXEN
3570 : HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFEN
3571 : AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFSET;
3574 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_BOTHEN
3575 : AMDGPU::BUFFER_LOAD_DWORD_LDS_IDXEN
3576 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFEN
3577 : AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFSET;
3580 if (!Subtarget->hasLDSLoadB96_B128())
3583 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_BOTHEN
3584 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_IDXEN
3585 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFEN
3586 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFSET;
3589 if (!Subtarget->hasLDSLoadB96_B128())
3592 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_BOTHEN
3593 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_IDXEN
3594 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFEN
3595 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFSET;
3602 .
add(
MI.getOperand(2));
3606 if (HasVIndex && HasVOffset) {
3607 Register IdxReg = MRI->createVirtualRegister(TRI.getVGPR64Class());
3608 BuildMI(*
MBB, &*MIB,
DL, TII.get(AMDGPU::REG_SEQUENCE), IdxReg)
3615 }
else if (HasVIndex) {
3617 }
else if (HasVOffset) {
3621 MIB.
add(
MI.getOperand(1));
3622 MIB.
add(
MI.getOperand(5 + OpOffset));
3623 MIB.
add(
MI.getOperand(6 + OpOffset));
3625 unsigned Aux =
MI.getOperand(7 + OpOffset).getImm();
3634 MachineMemOperand *LoadMMO = *
MI.memoperands_begin();
3639 MachinePointerInfo StorePtrI = LoadPtrI;
3650 MachineMemOperand *StoreMMO =
3656 MI.eraseFromParent();
3669 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3675 return Def->getOperand(1).getReg();
3689 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3697 return Def->getOperand(1).getReg();
3700 if (ZextSrc &&
VT->signBitIsZero(ZextSrc))
3709AMDGPUInstructionSelector::matchZeroExtendFromS32OrS32(
Register Reg)
const {
3711 : matchZeroExtendFromS32(
Reg);
3717AMDGPUInstructionSelector::matchSignExtendFromS32OrS32(
Register Reg)
const {
3719 : matchSignExtendFromS32(
Reg);
3723AMDGPUInstructionSelector::matchExtendFromS32OrS32(
Register Reg,
3724 bool IsSigned)
const {
3726 return matchSignExtendFromS32OrS32(
Reg);
3728 return matchZeroExtendFromS32OrS32(
Reg);
3738 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3745 return Def->getOperand(1).getReg();
3750bool AMDGPUInstructionSelector::selectGlobalLoadLds(
MachineInstr &
MI)
const{
3751 if (!Subtarget->hasVMemToLDSLoad())
3755 unsigned Size =
MI.getOperand(3).getImm();
3762 Opc = AMDGPU::GLOBAL_LOAD_LDS_UBYTE;
3765 Opc = AMDGPU::GLOBAL_LOAD_LDS_USHORT;
3768 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORD;
3771 if (!Subtarget->hasLDSLoadB96_B128())
3773 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX3;
3776 if (!Subtarget->hasLDSLoadB96_B128())
3778 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX4;
3785 .
add(
MI.getOperand(2));
3791 if (!isSGPR(Addr)) {
3793 if (isSGPR(AddrDef->Reg)) {
3794 Addr = AddrDef->Reg;
3795 }
else if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
3798 if (isSGPR(SAddr)) {
3799 Register PtrBaseOffset = AddrDef->MI->getOperand(2).getReg();
3800 if (
Register Off = matchZeroExtendFromS32(PtrBaseOffset)) {
3811 VOffset = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
3823 MIB.
add(
MI.getOperand(4));
3825 unsigned Aux =
MI.getOperand(5).getImm();
3829 MachineMemOperand *LoadMMO = *
MI.memoperands_begin();
3831 LoadPtrI.
Offset =
MI.getOperand(4).getImm();
3832 MachinePointerInfo StorePtrI = LoadPtrI;
3841 MachineMemOperand *StoreMMO =
3843 sizeof(int32_t),
Align(4));
3847 MI.eraseFromParent();
3852bool AMDGPUInstructionSelector::selectTensorLoadStore(
MachineInstr &
MI,
3854 bool IsLoad = IID == Intrinsic::amdgcn_tensor_load_to_lds;
3856 IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d4 : AMDGPU::TENSOR_STORE_FROM_LDS_d4;
3860 const auto isAllZeros = [&](MachineOperand &Opnd) {
3861 const MachineInstr *
DefMI = MRI->getVRegDef(Opnd.getReg());
3870 Opc = IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d2
3871 : AMDGPU::TENSOR_STORE_FROM_LDS_d2;
3878 .
add(
MI.getOperand(1))
3879 .
add(
MI.getOperand(2));
3881 if (NumGroups >= 4) {
3882 MIB.
add(
MI.getOperand(3))
3883 .
add(
MI.getOperand(4));
3887 .
add(
MI.getOperand(6));
3889 MI.eraseFromParent();
3893bool AMDGPUInstructionSelector::selectBVHIntersectRayIntrinsic(
3895 unsigned OpcodeOpIdx =
3896 MI.getOpcode() == AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY ? 1 : 3;
3897 MI.setDesc(TII.get(
MI.getOperand(OpcodeOpIdx).getImm()));
3898 MI.removeOperand(OpcodeOpIdx);
3899 MI.addImplicitDefUseOperands(*
MI.getMF());
3906bool AMDGPUInstructionSelector::selectSMFMACIntrin(
MachineInstr &
MI)
const {
3909 case Intrinsic::amdgcn_smfmac_f32_16x16x32_f16:
3910 Opc = AMDGPU::V_SMFMAC_F32_16X16X32_F16_e64;
3912 case Intrinsic::amdgcn_smfmac_f32_32x32x16_f16:
3913 Opc = AMDGPU::V_SMFMAC_F32_32X32X16_F16_e64;
3915 case Intrinsic::amdgcn_smfmac_f32_16x16x32_bf16:
3916 Opc = AMDGPU::V_SMFMAC_F32_16X16X32_BF16_e64;
3918 case Intrinsic::amdgcn_smfmac_f32_32x32x16_bf16:
3919 Opc = AMDGPU::V_SMFMAC_F32_32X32X16_BF16_e64;
3921 case Intrinsic::amdgcn_smfmac_i32_16x16x64_i8:
3922 Opc = AMDGPU::V_SMFMAC_I32_16X16X64_I8_e64;
3924 case Intrinsic::amdgcn_smfmac_i32_32x32x32_i8:
3925 Opc = AMDGPU::V_SMFMAC_I32_32X32X32_I8_e64;
3927 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_bf8:
3928 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF8_BF8_e64;
3930 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_fp8:
3931 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF8_FP8_e64;
3933 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_bf8:
3934 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_FP8_BF8_e64;
3936 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_fp8:
3937 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_FP8_FP8_e64;
3939 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_bf8:
3940 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF8_BF8_e64;
3942 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_fp8:
3943 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF8_FP8_e64;
3945 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_bf8:
3946 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_FP8_BF8_e64;
3948 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_fp8:
3949 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_FP8_FP8_e64;
3951 case Intrinsic::amdgcn_smfmac_f32_16x16x64_f16:
3952 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_F16_e64;
3954 case Intrinsic::amdgcn_smfmac_f32_32x32x32_f16:
3955 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_F16_e64;
3957 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf16:
3958 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF16_e64;
3960 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf16:
3961 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF16_e64;
3963 case Intrinsic::amdgcn_smfmac_i32_16x16x128_i8:
3964 Opc = AMDGPU::V_SMFMAC_I32_16X16X128_I8_e64;
3966 case Intrinsic::amdgcn_smfmac_i32_32x32x64_i8:
3967 Opc = AMDGPU::V_SMFMAC_I32_32X32X64_I8_e64;
3969 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_bf8:
3970 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_BF8_BF8_e64;
3972 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_fp8:
3973 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_BF8_FP8_e64;
3975 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_bf8:
3976 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_FP8_BF8_e64;
3978 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_fp8:
3979 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_FP8_FP8_e64;
3981 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_bf8:
3982 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_BF8_BF8_e64;
3984 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_fp8:
3985 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_BF8_FP8_e64;
3987 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_bf8:
3988 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_FP8_BF8_e64;
3990 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_fp8:
3991 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_FP8_FP8_e64;
3997 auto VDst_In =
MI.getOperand(4);
3999 MI.setDesc(TII.get(
Opc));
4000 MI.removeOperand(4);
4001 MI.removeOperand(1);
4002 MI.addOperand(VDst_In);
4003 MI.addImplicitDefUseOperands(*
MI.getMF());
4004 const MCInstrDesc &MCID =
MI.getDesc();
4006 MI.getOperand(0).setIsEarlyClobber(
true);
4011bool AMDGPUInstructionSelector::selectPermlaneSwapIntrin(
4013 if (IntrID == Intrinsic::amdgcn_permlane16_swap &&
4014 !Subtarget->hasPermlane16Swap())
4016 if (IntrID == Intrinsic::amdgcn_permlane32_swap &&
4017 !Subtarget->hasPermlane32Swap())
4020 unsigned Opcode = IntrID == Intrinsic::amdgcn_permlane16_swap
4021 ? AMDGPU::V_PERMLANE16_SWAP_B32_e64
4022 : AMDGPU::V_PERMLANE32_SWAP_B32_e64;
4024 MI.removeOperand(2);
4025 MI.setDesc(TII.get(Opcode));
4028 MachineOperand &FI =
MI.getOperand(4);
4035bool AMDGPUInstructionSelector::selectWaveAddress(
MachineInstr &
MI)
const {
4038 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4039 const bool IsVALU = DstRB->
getID() == AMDGPU::VGPRRegBankID;
4044 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHRREV_B32_e64), DstReg)
4045 .
addImm(Subtarget->getWavefrontSizeLog2())
4050 .
addImm(Subtarget->getWavefrontSizeLog2())
4055 IsVALU ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
4056 if (!RBI.constrainGenericRegister(DstReg, RC, *MRI))
4059 MI.eraseFromParent();
4063bool AMDGPUInstructionSelector::selectWaveShuffleIntrin(
4073 const LLT DstTy = MRI->getType(DstReg);
4075 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4077 TRI.getRegClassForSizeOnBank(DstSize, *DstRB);
4082 if (!Subtarget->supportsBPermute())
4086 if (Subtarget->supportsWaveWideBPermute()) {
4087 Register ShiftIdxReg = MRI->createVirtualRegister(DstRC);
4088 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), ShiftIdxReg)
4098 assert(Subtarget->isWave64());
4102 MRI->createVirtualRegister(TRI.getRegClass(AMDGPU::SReg_32RegClassID));
4103 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefValReg);
4105 Register UndefExecReg = MRI->createVirtualRegister(
4106 TRI.getRegClass(AMDGPU::SReg_64_XEXECRegClassID));
4107 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefExecReg);
4109 Register PoisonValReg = MRI->createVirtualRegister(DstRC);
4110 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_SET_INACTIVE_B32), PoisonValReg)
4118 Register ShiftIdxReg = MRI->createVirtualRegister(DstRC);
4119 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), ShiftIdxReg)
4123 Register PoisonIdxReg = MRI->createVirtualRegister(DstRC);
4124 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_SET_INACTIVE_B32), PoisonIdxReg)
4131 Register PoisonUnshiftedIdxReg = MRI->createVirtualRegister(DstRC);
4133 PoisonUnshiftedIdxReg)
4141 Register SameSidePermReg = MRI->createVirtualRegister(DstRC);
4142 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::DS_BPERMUTE_B32), SameSidePermReg)
4147 Register SwappedValReg = MRI->createVirtualRegister(DstRC);
4148 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_PERMLANE64_B32), SwappedValReg)
4151 Register OppSidePermReg = MRI->createVirtualRegister(DstRC);
4152 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::DS_BPERMUTE_B32), OppSidePermReg)
4157 Register WWMSwapPermReg = MRI->createVirtualRegister(DstRC);
4158 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::STRICT_WWM), WWMSwapPermReg)
4165 Register ThreadIDReg = MRI->createVirtualRegister(DstRC);
4166 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_MBCNT_LO_U32_B32_e64), ThreadIDReg)
4170 Register XORReg = MRI->createVirtualRegister(DstRC);
4173 .
addReg(PoisonUnshiftedIdxReg);
4175 Register ANDReg = MRI->createVirtualRegister(DstRC);
4180 Register CompareReg = MRI->createVirtualRegister(
4181 TRI.getRegClass(AMDGPU::SReg_64_XEXECRegClassID));
4182 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_CMP_EQ_U32_e64), CompareReg)
4187 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
4195 MI.eraseFromParent();
4204 unsigned NumOpcodes = 0;
4217 const uint8_t SrcBits[3] = { 0xf0, 0xcc, 0xaa };
4228 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4242 if (Src.size() == 3) {
4249 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4250 if (Src[
I] ==
LHS) {
4260 Bits = SrcBits[Src.size()];
4266 switch (
MI->getOpcode()) {
4267 case TargetOpcode::G_AND:
4268 case TargetOpcode::G_OR:
4269 case TargetOpcode::G_XOR: {
4274 if (!getOperandBits(
LHS, LHSBits) ||
4275 !getOperandBits(
RHS, RHSBits)) {
4276 Src = std::move(Backup);
4277 return std::make_pair(0, 0);
4298 uint8_t LHSBitsOrig = LHSBits;
4299 uint8_t RHSBitsOrig = RHSBits;
4303 NumOpcodes += LHSOp.first;
4304 LHSBits = LHSOp.second;
4311 NumOpcodes += RHSOp.first;
4312 RHSBits = RHSOp.second;
4316 auto dependsOnSlot = [](
uint8_t TT,
int Slot) ->
bool {
4317 if (Slot < 0 || Slot > 2)
4319 const uint8_t Masks[3] = {0x0f, 0x33, 0x55};
4320 const int Shifts[3] = {4, 2, 1};
4321 return ((TT ^ (TT >> Shifts[Slot])) & Masks[Slot]) != 0;
4327 const uint8_t SrcBitsConst[3] = {0xf0, 0xcc, 0xaa};
4334 for (
int I = 0;
I < (int)S.size();
I++) {
4335 if (Bits == SrcBitsConst[
I] && S[
I] ==
Op)
4337 if (IsNegationOp && Bits == (
uint8_t)~SrcBitsConst[
I] &&
4338 S[
I] == NegatedInner)
4349 for (
int I = 0;
I < (int)SrcAfterLHS.
size() &&
I < 3;
I++) {
4350 if (
I < (
int)Src.size() && Src[
I] != SrcAfterLHS[
I] &&
4351 dependsOnSlot(LHSBits,
I)) {
4360 if (!Stale && !RHSOp.first) {
4361 int Slot = findSlot(RHSBitsOrig,
RHS, SrcBeforeRecurse);
4363 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4369 if (!Stale && !LHSOp.first) {
4370 int Slot = findSlot(LHSBitsOrig,
LHS, SrcBeforeRecurse);
4372 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4377 Src = std::move(SrcBeforeRecurse);
4378 LHSBits = LHSBitsOrig;
4379 RHSBits = RHSBitsOrig;
4385 return std::make_pair(0, 0);
4389 switch (
MI->getOpcode()) {
4390 case TargetOpcode::G_AND:
4391 TTbl = LHSBits & RHSBits;
4393 case TargetOpcode::G_OR:
4394 TTbl = LHSBits | RHSBits;
4396 case TargetOpcode::G_XOR:
4397 TTbl = LHSBits ^ RHSBits;
4403 return std::make_pair(NumOpcodes + 1, TTbl);
4406bool AMDGPUInstructionSelector::selectBITOP3(
MachineInstr &
MI)
const {
4407 if (!Subtarget->hasBitOp3Insts())
4411 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4412 const bool IsVALU = DstRB->
getID() == AMDGPU::VGPRRegBankID;
4418 unsigned NumOpcodes;
4420 std::tie(NumOpcodes, TTbl) =
BitOp3_Op(DstReg, Src, *MRI);
4424 if (NumOpcodes < 2 || Src.empty())
4429 unsigned Size = MRI->getType(DstReg).getSizeInBits();
4430 assert((
Size == 16 ||
Size == 32) &&
"unexpected VALU logic op size");
4431 const bool IsB32 =
Size == 32;
4432 if (NumOpcodes == 2 && IsB32) {
4440 }
else if (NumOpcodes < 4) {
4447 unsigned Opc = IsB32 ? AMDGPU::V_BITOP3_B32_e64 : AMDGPU::V_BITOP3_B16_e64;
4448 if (!IsB32 && STI.hasTrue16BitInsts())
4449 Opc = STI.useRealTrue16Insts() ? AMDGPU::V_BITOP3_B16_gfx1250_t16_e64
4450 : AMDGPU::V_BITOP3_B16_gfx1250_fake16_e64;
4451 unsigned CBL = STI.getConstantBusLimit(
Opc);
4455 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4456 const RegisterBank *RB = RBI.getRegBank(Src[
I], *MRI, TRI);
4457 if (RB->
getID() != AMDGPU::SGPRRegBankID)
4463 Register NewReg = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
4474 while (Src.size() < 3)
4475 Src.push_back(Src[0]);
4492 MI.eraseFromParent();
4497bool AMDGPUInstructionSelector::selectStackRestore(
MachineInstr &
MI)
const {
4499 if (!RBI.constrainGenericRegister(SrcReg, AMDGPU::SReg_32RegClass, *MRI))
4502 MachineInstr *
DefMI = MRI->getVRegDef(SrcReg);
4504 Subtarget->getTargetLowering()->getStackPointerRegisterToSaveRestore();
4510 WaveAddr = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
4513 .
addImm(Subtarget->getWavefrontSizeLog2())
4520 MI.eraseFromParent();
4526 if (!
I.isPreISelOpcode()) {
4528 return selectCOPY(
I);
4532 switch (
I.getOpcode()) {
4533 case TargetOpcode::G_AND:
4534 case TargetOpcode::G_OR:
4535 case TargetOpcode::G_XOR:
4536 if (selectBITOP3(
I))
4540 return selectG_AND_OR_XOR(
I);
4541 case TargetOpcode::G_ADD:
4542 case TargetOpcode::G_SUB:
4543 case TargetOpcode::G_PTR_ADD:
4546 return selectG_ADD_SUB(
I);
4547 case TargetOpcode::G_UADDO:
4548 case TargetOpcode::G_USUBO:
4549 case TargetOpcode::G_UADDE:
4550 case TargetOpcode::G_USUBE:
4551 return selectG_UADDO_USUBO_UADDE_USUBE(
I);
4552 case AMDGPU::G_AMDGPU_MAD_U64_U32:
4553 case AMDGPU::G_AMDGPU_MAD_I64_I32:
4554 return selectG_AMDGPU_MAD_64_32(
I);
4555 case TargetOpcode::G_INTTOPTR:
4556 case TargetOpcode::G_BITCAST:
4557 case TargetOpcode::G_PTRTOINT:
4558 case TargetOpcode::G_FREEZE:
4559 return selectCOPY(
I);
4560 case TargetOpcode::G_FNEG:
4563 return selectG_FNEG(
I);
4564 case TargetOpcode::G_FABS:
4567 return selectG_FABS(
I);
4568 case TargetOpcode::G_EXTRACT:
4569 return selectG_EXTRACT(
I);
4570 case TargetOpcode::G_MERGE_VALUES:
4571 case TargetOpcode::G_CONCAT_VECTORS:
4572 return selectG_MERGE_VALUES(
I);
4573 case TargetOpcode::G_UNMERGE_VALUES:
4574 return selectG_UNMERGE_VALUES(
I);
4575 case TargetOpcode::G_BUILD_VECTOR:
4576 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
4577 return selectG_BUILD_VECTOR(
I);
4578 case TargetOpcode::G_IMPLICIT_DEF:
4579 return selectG_IMPLICIT_DEF(
I);
4580 case TargetOpcode::G_INSERT:
4581 return selectG_INSERT(
I);
4582 case TargetOpcode::G_INTRINSIC:
4583 case TargetOpcode::G_INTRINSIC_CONVERGENT:
4584 return selectG_INTRINSIC(
I);
4585 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
4586 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
4587 return selectG_INTRINSIC_W_SIDE_EFFECTS(
I);
4588 case TargetOpcode::G_ICMP:
4589 case TargetOpcode::G_FCMP:
4590 if (selectG_ICMP_or_FCMP(
I))
4593 case TargetOpcode::G_LOAD:
4594 case TargetOpcode::G_ZEXTLOAD:
4595 case TargetOpcode::G_SEXTLOAD:
4596 case TargetOpcode::G_STORE:
4597 case TargetOpcode::G_ATOMIC_CMPXCHG:
4598 case TargetOpcode::G_ATOMICRMW_XCHG:
4599 case TargetOpcode::G_ATOMICRMW_ADD:
4600 case TargetOpcode::G_ATOMICRMW_SUB:
4601 case TargetOpcode::G_ATOMICRMW_AND:
4602 case TargetOpcode::G_ATOMICRMW_OR:
4603 case TargetOpcode::G_ATOMICRMW_XOR:
4604 case TargetOpcode::G_ATOMICRMW_MIN:
4605 case TargetOpcode::G_ATOMICRMW_MAX:
4606 case TargetOpcode::G_ATOMICRMW_UMIN:
4607 case TargetOpcode::G_ATOMICRMW_UMAX:
4608 case TargetOpcode::G_ATOMICRMW_UINC_WRAP:
4609 case TargetOpcode::G_ATOMICRMW_UDEC_WRAP:
4610 case TargetOpcode::G_ATOMICRMW_USUB_COND:
4611 case TargetOpcode::G_ATOMICRMW_USUB_SAT:
4612 case TargetOpcode::G_ATOMICRMW_FADD:
4613 case TargetOpcode::G_ATOMICRMW_FMIN:
4614 case TargetOpcode::G_ATOMICRMW_FMAX:
4615 return selectG_LOAD_STORE_ATOMICRMW(
I);
4616 case TargetOpcode::G_SELECT:
4617 return selectG_SELECT(
I);
4618 case TargetOpcode::G_TRUNC:
4619 return selectG_TRUNC(
I);
4620 case TargetOpcode::G_SEXT:
4621 case TargetOpcode::G_ZEXT:
4622 case TargetOpcode::G_ANYEXT:
4623 case TargetOpcode::G_SEXT_INREG:
4627 if (MRI->getType(
I.getOperand(1).getReg()) !=
LLT::scalar(1) &&
4630 return selectG_SZA_EXT(
I);
4631 case TargetOpcode::G_FPEXT:
4632 if (selectG_FPEXT(
I))
4635 case TargetOpcode::G_BRCOND:
4636 return selectG_BRCOND(
I);
4637 case TargetOpcode::G_GLOBAL_VALUE:
4638 return selectG_GLOBAL_VALUE(
I);
4639 case TargetOpcode::G_PTRMASK:
4640 return selectG_PTRMASK(
I);
4641 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4642 return selectG_EXTRACT_VECTOR_ELT(
I);
4643 case TargetOpcode::G_INSERT_VECTOR_ELT:
4644 return selectG_INSERT_VECTOR_ELT(
I);
4645 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD:
4646 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16:
4647 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET:
4648 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE:
4649 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16: {
4652 assert(Intr &&
"not an image intrinsic with image pseudo");
4653 return selectImageIntrinsic(
I, Intr);
4655 case AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY:
4656 case AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY:
4657 case AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY:
4658 return selectBVHIntersectRayIntrinsic(
I);
4659 case AMDGPU::G_SBFX:
4660 case AMDGPU::G_UBFX:
4661 return selectG_SBFX_UBFX(
I);
4662 case AMDGPU::G_SI_CALL:
4663 I.setDesc(TII.get(AMDGPU::SI_CALL));
4665 case AMDGPU::G_AMDGPU_WAVE_ADDRESS:
4666 return selectWaveAddress(
I);
4667 case AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_RETURN: {
4668 I.setDesc(TII.get(AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN));
4671 case AMDGPU::G_STACKRESTORE:
4672 return selectStackRestore(
I);
4674 return selectPHI(
I);
4675 case AMDGPU::G_AMDGPU_COPY_SCC_VCC:
4676 return selectCOPY_SCC_VCC(
I);
4677 case AMDGPU::G_AMDGPU_COPY_VCC_SCC:
4678 return selectCOPY_VCC_SCC(
I);
4679 case AMDGPU::G_AMDGPU_READANYLANE:
4680 return selectReadAnyLane(
I);
4681 case TargetOpcode::G_CONSTANT:
4682 case TargetOpcode::G_FCONSTANT:
4690AMDGPUInstructionSelector::selectVCSRC(
MachineOperand &Root)
const {
4697std::pair<Register, unsigned> AMDGPUInstructionSelector::selectVOP3ModsImpl(
4698 Register Src,
bool IsCanonicalizing,
bool AllowAbs,
bool OpSel)
const {
4702 if (
MI->getOpcode() == AMDGPU::G_FNEG) {
4703 Src =
MI->getOperand(1).getReg();
4706 }
else if (
MI->getOpcode() == AMDGPU::G_FSUB && IsCanonicalizing) {
4711 if (
LHS &&
LHS->isZero()) {
4713 Src =
MI->getOperand(2).getReg();
4717 if (AllowAbs &&
MI->getOpcode() == AMDGPU::G_FABS) {
4718 Src =
MI->getOperand(1).getReg();
4725 return std::pair(Src, Mods);
4728std::pair<Register, unsigned>
4729AMDGPUInstructionSelector::selectVOP3PModsF32Impl(
Register Src)
const {
4731 std::tie(Src, Mods) = selectVOP3ModsImpl(Src);
4733 return std::pair(Src, Mods);
4736Register AMDGPUInstructionSelector::copyToVGPRIfSrcFolded(
4738 bool ForceVGPR)
const {
4739 if ((Mods != 0 || ForceVGPR) &&
4740 RBI.getRegBank(Src, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID) {
4747 TII.
get(AMDGPU::COPY), VGPRSrc)
4759AMDGPUInstructionSelector::widenSrcIfVGPR16(
Register Src,
4761 if (!Subtarget->useRealTrue16Insts() || MRI->getType(Src) !=
LLT::scalar(16))
4764 const RegisterBank *SrcRB = RBI.getRegBank(Src, *MRI, TRI);
4765 if (!SrcRB || SrcRB->
getID() != AMDGPU::VGPRRegBankID)
4768 MachineIRBuilder
B(*InsertPt);
4770 Register ImpDefReg = MRI->createVirtualRegister(&AMDGPU::VGPR_16RegClass);
4771 B.buildInstr(TargetOpcode::IMPLICIT_DEF).addDef(ImpDefReg);
4773 Register DstReg = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
4774 B.buildInstr(AMDGPU::REG_SEQUENCE)
4777 .addImm(AMDGPU::lo16)
4779 .addImm(AMDGPU::hi16);
4788AMDGPUInstructionSelector::selectVSRC0(
MachineOperand &Root)
const {
4790 [=](MachineInstrBuilder &MIB) { MIB.
add(Root); }
4795AMDGPUInstructionSelector::selectVOP3Mods0(
MachineOperand &Root)
const {
4798 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
4801 [=](MachineInstrBuilder &MIB) {
4802 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4804 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
4805 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4806 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4811AMDGPUInstructionSelector::selectVOP3BMods0(
MachineOperand &Root)
const {
4814 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
4819 [=](MachineInstrBuilder &MIB) {
4820 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4822 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
4823 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4824 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4829AMDGPUInstructionSelector::selectVOP3OMods(
MachineOperand &Root)
const {
4831 [=](MachineInstrBuilder &MIB) { MIB.
add(Root); },
4832 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4833 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4838AMDGPUInstructionSelector::selectVOP3Mods(
MachineOperand &Root)
const {
4841 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
4844 [=](MachineInstrBuilder &MIB) {
4845 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4847 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4852AMDGPUInstructionSelector::selectVOP3ModsNonCanonicalizing(
4856 std::tie(Src, Mods) =
4857 selectVOP3ModsImpl(Root.
getReg(),
false);
4860 [=](MachineInstrBuilder &MIB) {
4861 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4863 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4868AMDGPUInstructionSelector::selectVOP3BMods(
MachineOperand &Root)
const {
4871 std::tie(Src, Mods) =
4872 selectVOP3ModsImpl(Root.
getReg(),
true,
4876 [=](MachineInstrBuilder &MIB) {
4877 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4879 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4884AMDGPUInstructionSelector::selectVOP3NoMods(
MachineOperand &Root)
const {
4887 if (
Def->getOpcode() == AMDGPU::G_FNEG ||
Def->getOpcode() == AMDGPU::G_FABS)
4890 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
4915 if (
MI->getOpcode() != AMDGPU::G_TRUNC)
4920 return DstSize * 2 == SrcSize;
4926 if (
MI->getOpcode() != AMDGPU::G_LSHR)
4930 std::optional<ValueAndVReg> ShiftAmt;
4931 if (
mi_match(
MI->getOperand(0).getReg(), MRI,
4934 unsigned Shift = ShiftAmt->Value.getZExtValue();
4935 return Shift * 2 == SrcSize;
4943 if (
MI->getOpcode() != AMDGPU::G_SHL)
4947 std::optional<ValueAndVReg> ShiftAmt;
4948 if (
mi_match(
MI->getOperand(0).getReg(), MRI,
4951 unsigned Shift = ShiftAmt->Value.getZExtValue();
4952 return Shift * 2 == SrcSize;
4960 if (
MI->getOpcode() != AMDGPU::G_UNMERGE_VALUES)
4962 return MI->getNumOperands() == 3 &&
MI->getOperand(0).isDef() &&
4963 MI->getOperand(1).isDef() && !
MI->getOperand(2).isDef();
4971 if (
OpTy.isScalar())
4973 if (
OpTy.isVector() &&
OpTy.getNumElements() == 2)
5133static std::optional<std::pair<Register, SrcStatus>>
5138 unsigned Opc =
MI->getOpcode();
5142 case AMDGPU::G_BITCAST:
5143 return std::optional<std::pair<Register, SrcStatus>>(
5144 {
MI->getOperand(1).getReg(), Curr.second});
5146 if (
MI->getOperand(1).getReg().isPhysical())
5147 return std::nullopt;
5148 return std::optional<std::pair<Register, SrcStatus>>(
5149 {
MI->getOperand(1).getReg(), Curr.second});
5150 case AMDGPU::G_FNEG: {
5153 return std::nullopt;
5154 return std::optional<std::pair<Register, SrcStatus>>(
5155 {
MI->getOperand(1).getReg(), Stat});
5162 switch (Curr.second) {
5165 return std::optional<std::pair<Register, SrcStatus>>(
5168 if (Curr.first ==
MI->getOperand(0).getReg())
5169 return std::optional<std::pair<Register, SrcStatus>>(
5171 return std::optional<std::pair<Register, SrcStatus>>(
5183 return std::optional<std::pair<Register, SrcStatus>>(
5187 if (Curr.first ==
MI->getOperand(0).getReg())
5188 return std::optional<std::pair<Register, SrcStatus>>(
5190 return std::optional<std::pair<Register, SrcStatus>>(
5196 return std::optional<std::pair<Register, SrcStatus>>(
5201 return std::optional<std::pair<Register, SrcStatus>>(
5206 return std::optional<std::pair<Register, SrcStatus>>(
5211 return std::optional<std::pair<Register, SrcStatus>>(
5217 return std::nullopt;
5227 bool HasNeg =
false;
5229 bool HasOpsel =
true;
5234 unsigned Opc =
MI->getOpcode();
5236 if (
Opc == TargetOpcode::G_INTRINSIC) {
5239 if (IntrinsicID == Intrinsic::amdgcn_fdot2)
5266 while (
Depth <= MaxDepth && Curr.has_value()) {
5269 Statlist.push_back(Curr.value());
5276static std::pair<Register, SrcStatus>
5283 while (
Depth <= MaxDepth && Curr.has_value()) {
5289 LastSameOrNeg = Curr.value();
5294 return LastSameOrNeg;
5301 return Width1 == Width2;
5336 return isSameBitWidth(NewReg, RootReg, MRI) && IsHalfState(LoStat) &&
5337 IsHalfState(HiStat);
5340std::pair<Register, unsigned> AMDGPUInstructionSelector::selectVOP3PModsImpl(
5346 return {RootReg, Mods};
5349 SearchOptions SO(RootReg, MRI);
5362 if (MRI.getType(RootReg).getSizeInBits() == 128) {
5364 return {Stat.first, Mods};
5369 MI->getNumOperands() != 3 || (IsDOT && Subtarget->hasDOTOpSelHazard())) {
5371 return {Stat.first, Mods};
5377 if (StatlistHi.
empty()) {
5379 return {Stat.first, Mods};
5385 if (StatlistLo.
empty()) {
5387 return {Stat.first, Mods};
5390 for (
int I = StatlistHi.
size() - 1;
I >= 0;
I--) {
5391 for (
int J = StatlistLo.
size() - 1; J >= 0; J--) {
5392 if (StatlistHi[
I].first == StatlistLo[J].first &&
5394 StatlistHi[
I].first, RootReg, TII, MRI))
5395 return {StatlistHi[
I].first,
5396 updateMods(StatlistHi[
I].second, StatlistLo[J].second, Mods)};
5402 return {Stat.first, Mods};
5412 return RB->
getID() == RBNo;
5428 if (
checkRB(RootReg, AMDGPU::SGPRRegBankID, RBI, MRI,
TRI) ||
5429 checkRB(NewReg, AMDGPU::VGPRRegBankID, RBI, MRI,
TRI))
5439 TII.get(AMDGPU::COPY), DstReg)
5447AMDGPUInstructionSelector::selectVOP3PRetHelper(
MachineOperand &Root,
5452 std::tie(
Reg, Mods) = selectVOP3PModsImpl(Root.
getReg(), MRI, IsDOT);
5457 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
5458 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5463AMDGPUInstructionSelector::selectVOP3PMods(
MachineOperand &Root)
const {
5465 return selectVOP3PRetHelper(Root);
5469AMDGPUInstructionSelector::selectVOP3PModsDOT(
MachineOperand &Root)
const {
5471 return selectVOP3PRetHelper(Root,
true);
5475AMDGPUInstructionSelector::selectVOP3PNoModsDOT(
MachineOperand &Root)
const {
5479 std::tie(Src, Mods) = selectVOP3PModsImpl(Root.
getReg(), MRI,
true );
5483 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); }}};
5487AMDGPUInstructionSelector::selectVOP3PModsF32(
MachineOperand &Root)
const {
5490 std::tie(Src, Mods) = selectVOP3PModsF32Impl(Root.
getReg());
5493 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5494 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5499AMDGPUInstructionSelector::selectVOP3PNoModsF32(
MachineOperand &Root)
const {
5502 std::tie(Src, Mods) = selectVOP3PModsF32Impl(Root.
getReg());
5506 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); }}};
5510AMDGPUInstructionSelector::selectWMMAOpSelVOP3PMods(
5513 "expected i1 value");
5519 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5527 switch (Elts.
size()) {
5529 DstRegClass = &AMDGPU::VReg_256RegClass;
5532 DstRegClass = &AMDGPU::VReg_128RegClass;
5535 DstRegClass = &AMDGPU::VReg_64RegClass;
5542 auto MIB =
B.buildInstr(AMDGPU::REG_SEQUENCE)
5544 for (
unsigned i = 0; i < Elts.
size(); ++i) {
5555 if (ModOpcode == TargetOpcode::G_FNEG) {
5559 for (
auto El : Elts) {
5565 if (Elts.size() != NegAbsElts.
size()) {
5574 assert(ModOpcode == TargetOpcode::G_FABS);
5582AMDGPUInstructionSelector::selectWMMAModsF32NegAbs(
MachineOperand &Root)
const {
5591 MachineInstr *ElF32 = MRI->getVRegDef(BV->
getSourceReg(0));
5592 unsigned ModOpcode = (ElF32->
getOpcode() == AMDGPU::G_FNEG)
5609 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5610 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5614AMDGPUInstructionSelector::selectWMMAModsF16Neg(
MachineOperand &Root)
const {
5636 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5637 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5641AMDGPUInstructionSelector::selectWMMAModsF16NegAbs(
MachineOperand &Root)
const {
5649 MachineInstr *ElV2F16 = MRI->getVRegDef(CV->
getSourceReg(0));
5651 unsigned ModOpcode = (ElV2F16->
getOpcode() == AMDGPU::G_FNEG)
5670 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5671 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5675AMDGPUInstructionSelector::selectWMMAVISrc(
MachineOperand &Root)
const {
5676 std::optional<FPValueAndVReg> FPValReg;
5678 if (TII.isInlineConstant(FPValReg->Value)) {
5679 return {{[=](MachineInstrBuilder &MIB) {
5680 MIB.
addImm(FPValReg->Value.bitcastToAPInt().getSExtValue());
5690 if (TII.isInlineConstant(ICst)) {
5700AMDGPUInstructionSelector::selectSWMMACIndex8(
MachineOperand &Root)
const {
5706 std::optional<ValueAndVReg> ShiftAmt;
5708 MRI->getType(ShiftSrc).getSizeInBits() == 32 &&
5709 ShiftAmt->Value.getZExtValue() % 8 == 0) {
5710 Key = ShiftAmt->Value.getZExtValue() / 8;
5715 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5716 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5721AMDGPUInstructionSelector::selectSWMMACIndex16(
MachineOperand &Root)
const {
5728 std::optional<ValueAndVReg> ShiftAmt;
5730 MRI->getType(ShiftSrc).getSizeInBits() == 32 &&
5731 ShiftAmt->Value.getZExtValue() == 16) {
5737 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5738 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5743AMDGPUInstructionSelector::selectSWMMACIndex32(
MachineOperand &Root)
const {
5750 S32 = matchAnyExtendFromS32(Src);
5754 if (
Def->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) {
5759 Src =
Def->getOperand(2).getReg();
5766 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5767 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5772AMDGPUInstructionSelector::selectVOP3OpSelMods(
MachineOperand &Root)
const {
5775 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
5779 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5780 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5786AMDGPUInstructionSelector::selectVINTERPMods(
MachineOperand &Root)
const {
5789 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
5795 [=](MachineInstrBuilder &MIB) {
5797 copyToVGPRIfSrcFolded(Src, Mods, Root, MIB,
true));
5799 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
5804AMDGPUInstructionSelector::selectVINTERPModsHi(
MachineOperand &Root)
const {
5807 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
5813 [=](MachineInstrBuilder &MIB) {
5815 copyToVGPRIfSrcFolded(Src, Mods, Root, MIB,
true));
5817 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
5824bool AMDGPUInstructionSelector::selectScaleOffset(
MachineOperand &Root,
5826 bool IsSigned)
const {
5827 if (!Subtarget->hasScaleOffset())
5831 MachineMemOperand *MMO = *
MI.memoperands_begin();
5843 OffsetReg =
Def->Reg;
5858 m_BinOp(IsSigned ? AMDGPU::S_MUL_I64_I32_PSEUDO : AMDGPU::S_MUL_U64,
5862 (
Mul->getOpcode() == (IsSigned ? AMDGPU::G_AMDGPU_MAD_I64_I32
5863 : AMDGPU::G_AMDGPU_MAD_U64_U32) ||
5864 (IsSigned &&
Mul->getOpcode() == AMDGPU::G_AMDGPU_MAD_U64_U32 &&
5865 VT->signBitIsZero(
Mul->getOperand(2).getReg()))) &&
5878bool AMDGPUInstructionSelector::selectSmrdOffset(
MachineOperand &Root,
5882 bool *ScaleOffset)
const {
5889 getAddrModeInfo(*
MI, *MRI, AddrInfo);
5891 if (AddrInfo.
empty())
5894 const GEPInfo &GEPI = AddrInfo[0];
5895 std::optional<int64_t> EncodedImm;
5898 *ScaleOffset =
false;
5903 if (GEPI.SgprParts.size() == 1 && GEPI.Imm != 0 && EncodedImm &&
5904 AddrInfo.
size() > 1) {
5905 const GEPInfo &GEPI2 = AddrInfo[1];
5906 if (GEPI2.SgprParts.size() == 2 && GEPI2.Imm == 0) {
5907 Register OffsetReg = GEPI2.SgprParts[1];
5910 selectScaleOffset(Root, OffsetReg,
false );
5911 OffsetReg = matchZeroExtendFromS32OrS32(OffsetReg);
5913 Base = GEPI2.SgprParts[0];
5914 *SOffset = OffsetReg;
5923 auto SKnown =
VT->getKnownBits(*SOffset);
5924 if (*
Offset + SKnown.getMinValue().getSExtValue() < 0)
5936 if (
Offset && GEPI.SgprParts.size() == 1 && EncodedImm) {
5937 Base = GEPI.SgprParts[0];
5943 if (SOffset && GEPI.SgprParts.size() == 1 &&
isUInt<32>(GEPI.Imm) &&
5949 Base = GEPI.SgprParts[0];
5950 *SOffset = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
5951 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), *SOffset)
5956 if (SOffset && GEPI.SgprParts.size() && GEPI.Imm == 0) {
5957 Register OffsetReg = GEPI.SgprParts[1];
5959 *ScaleOffset = selectScaleOffset(Root, OffsetReg,
false );
5960 OffsetReg = matchZeroExtendFromS32OrS32(OffsetReg);
5962 Base = GEPI.SgprParts[0];
5963 *SOffset = OffsetReg;
5972AMDGPUInstructionSelector::selectSmrdImm(
MachineOperand &Root)
const {
5975 if (!selectSmrdOffset(Root,
Base,
nullptr, &
Offset,
5977 return std::nullopt;
5979 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
5980 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Offset); }}};
5984AMDGPUInstructionSelector::selectSmrdImm32(
MachineOperand &Root)
const {
5986 getAddrModeInfo(*Root.
getParent(), *MRI, AddrInfo);
5988 if (AddrInfo.
empty() || AddrInfo[0].SgprParts.size() != 1)
5989 return std::nullopt;
5991 const GEPInfo &GEPInfo = AddrInfo[0];
5992 Register PtrReg = GEPInfo.SgprParts[0];
5993 std::optional<int64_t> EncodedImm =
5996 return std::nullopt;
5999 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrReg); },
6000 [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); }
6005AMDGPUInstructionSelector::selectSmrdSgpr(
MachineOperand &Root)
const {
6008 if (!selectSmrdOffset(Root,
Base, &SOffset,
nullptr,
6010 return std::nullopt;
6013 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
6014 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
6015 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }}};
6019AMDGPUInstructionSelector::selectSmrdSgprImm(
MachineOperand &Root)
const {
6023 if (!selectSmrdOffset(Root,
Base, &SOffset, &
Offset, &ScaleOffset))
6024 return std::nullopt;
6027 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
6028 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
6030 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }}};
6033std::pair<Register, int> AMDGPUInstructionSelector::selectFlatOffsetImpl(
6039 if (!STI.hasFlatInstOffsets())
6043 int64_t ConstOffset;
6045 std::tie(PtrBase, ConstOffset, IsInBounds) =
6046 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
6052 if (ConstOffset == 0 ||
6054 !isFlatScratchBaseLegal(Root.
getReg())) ||
6058 unsigned AddrSpace = (*
MI->memoperands_begin())->getAddrSpace();
6059 if (!TII.isLegalFLATOffset(ConstOffset, AddrSpace, FlatVariant))
6062 return std::pair(PtrBase, ConstOffset);
6066AMDGPUInstructionSelector::selectFlatOffset(
MachineOperand &Root)
const {
6070 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6071 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6076AMDGPUInstructionSelector::selectGlobalOffset(
MachineOperand &Root)
const {
6077 auto PtrWithOffset =
6081 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6082 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6087AMDGPUInstructionSelector::selectScratchOffset(
MachineOperand &Root)
const {
6088 auto PtrWithOffset =
6092 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6093 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6099AMDGPUInstructionSelector::selectGlobalSAddr(
MachineOperand &Root,
6101 bool NeedIOffset)
const {
6104 int64_t ConstOffset;
6105 int64_t ImmOffset = 0;
6109 std::tie(PtrBase, ConstOffset, std::ignore) =
6110 getPtrBaseWithConstantOffset(Addr, *MRI);
6112 if (ConstOffset != 0) {
6117 ImmOffset = ConstOffset;
6120 if (isSGPR(PtrBaseDef->Reg)) {
6121 if (ConstOffset > 0) {
6127 int64_t SplitImmOffset = 0, RemainderOffset = ConstOffset;
6129 std::tie(SplitImmOffset, RemainderOffset) =
6134 if (Subtarget->hasSignedGVSOffset() ?
isInt<32>(RemainderOffset)
6139 MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6141 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32),
6143 .
addImm(RemainderOffset);
6147 [=](MachineInstrBuilder &MIB) {
6150 [=](MachineInstrBuilder &MIB) {
6153 [=](MachineInstrBuilder &MIB) { MIB.
addImm(SplitImmOffset); },
6154 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); },
6157 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrBase); },
6158 [=](MachineInstrBuilder &MIB) {
6161 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); },
6171 unsigned NumLiterals =
6172 !TII.isInlineConstant(APInt(32,
Lo_32(ConstOffset))) +
6173 !TII.isInlineConstant(APInt(32,
Hi_32(ConstOffset)));
6174 if (STI.getConstantBusLimit(AMDGPU::V_ADD_U32_e64) > NumLiterals)
6175 return std::nullopt;
6182 if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
6187 if (isSGPR(SAddr)) {
6188 Register PtrBaseOffset = AddrDef->MI->getOperand(2).getReg();
6192 bool ScaleOffset = selectScaleOffset(Root, PtrBaseOffset,
6193 Subtarget->hasSignedGVSOffset());
6194 if (
Register VOffset = matchExtendFromS32OrS32(
6195 PtrBaseOffset, Subtarget->hasSignedGVSOffset())) {
6197 return {{[=](MachineInstrBuilder &MIB) {
6200 [=](MachineInstrBuilder &MIB) {
6203 [=](MachineInstrBuilder &MIB) {
6206 [=](MachineInstrBuilder &MIB) {
6210 return {{[=](MachineInstrBuilder &MIB) {
6213 [=](MachineInstrBuilder &MIB) {
6216 [=](MachineInstrBuilder &MIB) {
6226 if (AddrDef->MI->getOpcode() == AMDGPU::G_IMPLICIT_DEF ||
6227 AddrDef->MI->getOpcode() == AMDGPU::G_CONSTANT || !isSGPR(AddrDef->Reg))
6228 return std::nullopt;
6234 Register VOffset = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6236 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32), VOffset)
6241 [=](MachineInstrBuilder &MIB) { MIB.
addReg(AddrDef->Reg); },
6242 [=](MachineInstrBuilder &MIB) { MIB.
addReg(VOffset); },
6243 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6244 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); }
6247 [=](MachineInstrBuilder &MIB) { MIB.
addReg(AddrDef->Reg); },
6248 [=](MachineInstrBuilder &MIB) { MIB.
addReg(VOffset); },
6249 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); }
6254AMDGPUInstructionSelector::selectGlobalSAddr(
MachineOperand &Root)
const {
6255 return selectGlobalSAddr(Root, 0);
6259AMDGPUInstructionSelector::selectGlobalSAddrCPol(
MachineOperand &Root)
const {
6265 return selectGlobalSAddr(Root, PassedCPol);
6269AMDGPUInstructionSelector::selectGlobalSAddrCPolM0(
MachineOperand &Root)
const {
6275 return selectGlobalSAddr(Root, PassedCPol);
6279AMDGPUInstructionSelector::selectGlobalSAddrGLC(
MachineOperand &Root)
const {
6284AMDGPUInstructionSelector::selectGlobalSAddrNoIOffset(
6291 return selectGlobalSAddr(Root, PassedCPol,
false);
6295AMDGPUInstructionSelector::selectGlobalSAddrNoIOffsetM0(
6302 return selectGlobalSAddr(Root, PassedCPol,
false);
6306AMDGPUInstructionSelector::selectScratchSAddr(
MachineOperand &Root)
const {
6309 int64_t ConstOffset;
6310 int64_t ImmOffset = 0;
6314 std::tie(PtrBase, ConstOffset, std::ignore) =
6315 getPtrBaseWithConstantOffset(Addr, *MRI);
6317 if (ConstOffset != 0 && isFlatScratchBaseLegal(Addr) &&
6321 ImmOffset = ConstOffset;
6325 if (AddrDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX) {
6326 int FI = AddrDef->MI->getOperand(1).
getIndex();
6329 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); }
6335 if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
6336 Register LHS = AddrDef->MI->getOperand(1).getReg();
6337 Register RHS = AddrDef->MI->getOperand(2).getReg();
6341 if (LHSDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX &&
6342 isSGPR(RHSDef->Reg)) {
6343 int FI = LHSDef->MI->getOperand(1).getIndex();
6347 SAddr = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
6349 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_ADD_I32), SAddr)
6357 return std::nullopt;
6360 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SAddr); },
6361 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); }
6366bool AMDGPUInstructionSelector::checkFlatScratchSVSSwizzleBug(
6368 if (!Subtarget->hasFlatScratchSVSSwizzleBug())
6374 auto VKnown =
VT->getKnownBits(VAddr);
6377 uint64_t VMax = VKnown.getMaxValue().getZExtValue();
6379 return (VMax & 3) + (
SMax & 3) >= 4;
6383AMDGPUInstructionSelector::selectScratchSVAddr(
MachineOperand &Root)
const {
6386 int64_t ConstOffset;
6387 int64_t ImmOffset = 0;
6391 std::tie(PtrBase, ConstOffset, std::ignore) =
6392 getPtrBaseWithConstantOffset(Addr, *MRI);
6395 if (ConstOffset != 0 &&
6399 ImmOffset = ConstOffset;
6403 if (AddrDef->MI->getOpcode() != AMDGPU::G_PTR_ADD)
6404 return std::nullopt;
6406 Register RHS = AddrDef->MI->getOperand(2).getReg();
6407 if (RBI.getRegBank(
RHS, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID)
6408 return std::nullopt;
6410 Register LHS = AddrDef->MI->getOperand(1).getReg();
6413 if (OrigAddr != Addr) {
6414 if (!isFlatScratchBaseLegalSVImm(OrigAddr))
6415 return std::nullopt;
6417 if (!isFlatScratchBaseLegalSV(OrigAddr))
6418 return std::nullopt;
6421 if (checkFlatScratchSVSSwizzleBug(
RHS,
LHS, ImmOffset))
6422 return std::nullopt;
6424 unsigned CPol = selectScaleOffset(Root,
RHS,
true )
6428 if (LHSDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX) {
6429 int FI = LHSDef->MI->getOperand(1).getIndex();
6431 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
RHS); },
6433 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6434 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }
6443 return std::nullopt;
6446 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
RHS); },
6447 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
LHS); },
6448 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6449 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }
6454AMDGPUInstructionSelector::selectMUBUFScratchOffen(
MachineOperand &Root)
const {
6458 const SIMachineFunctionInfo *
Info =
MF->getInfo<SIMachineFunctionInfo>();
6463 Register HighBits = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6468 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32),
6472 return {{[=](MachineInstrBuilder &MIB) {
6475 [=](MachineInstrBuilder &MIB) {
6478 [=](MachineInstrBuilder &MIB) {
6483 [=](MachineInstrBuilder &MIB) {
6492 std::optional<int> FI;
6496 int64_t ConstOffset;
6497 std::tie(PtrBase, ConstOffset, std::ignore) =
6498 getPtrBaseWithConstantOffset(VAddr, *MRI);
6500 if (ConstOffset != 0) {
6501 if (TII.isLegalMUBUFImmOffset(ConstOffset) &&
6502 (!STI.privateMemoryResourceIsRangeChecked() ||
6503 VT->signBitIsZero(PtrBase))) {
6514 return {{[=](MachineInstrBuilder &MIB) {
6517 [=](MachineInstrBuilder &MIB) {
6523 [=](MachineInstrBuilder &MIB) {
6528 [=](MachineInstrBuilder &MIB) {
6533bool AMDGPUInstructionSelector::isDSOffsetLegal(
Register Base,
6538 if (STI.hasUsableDSOffset() || STI.unsafeDSOffsetFoldingEnabled())
6543 return VT->signBitIsZero(
Base);
6546bool AMDGPUInstructionSelector::isDSOffset2Legal(
Register Base, int64_t Offset0,
6548 unsigned Size)
const {
6549 if (Offset0 %
Size != 0 || Offset1 %
Size != 0)
6554 if (STI.hasUsableDSOffset() || STI.unsafeDSOffsetFoldingEnabled())
6559 return VT->signBitIsZero(
Base);
6564 return Addr->
getOpcode() == TargetOpcode::G_OR ||
6565 (Addr->
getOpcode() == TargetOpcode::G_PTR_ADD &&
6572bool AMDGPUInstructionSelector::isFlatScratchBaseLegal(
Register Addr)
const {
6580 if (STI.hasSignedScratchOffsets())
6586 if (AddrMI->
getOpcode() == TargetOpcode::G_PTR_ADD) {
6587 std::optional<ValueAndVReg> RhsValReg =
6593 if (RhsValReg && RhsValReg->Value.getSExtValue() < 0 &&
6594 RhsValReg->Value.getSExtValue() > -0x40000000)
6598 return VT->signBitIsZero(
LHS);
6603bool AMDGPUInstructionSelector::isFlatScratchBaseLegalSV(
Register Addr)
const {
6611 if (STI.hasSignedScratchOffsets())
6616 return VT->signBitIsZero(
RHS) &&
VT->signBitIsZero(
LHS);
6621bool AMDGPUInstructionSelector::isFlatScratchBaseLegalSVImm(
6625 if (STI.hasSignedScratchOffsets())
6630 std::optional<DefinitionAndSourceRegister> BaseDef =
6632 std::optional<ValueAndVReg> RHSOffset =
6642 (RHSOffset->Value.getSExtValue() < 0 &&
6643 RHSOffset->Value.getSExtValue() > -0x40000000)))
6646 Register LHS = BaseDef->MI->getOperand(1).getReg();
6647 Register RHS = BaseDef->MI->getOperand(2).getReg();
6648 return VT->signBitIsZero(
RHS) &&
VT->signBitIsZero(
LHS);
6651bool AMDGPUInstructionSelector::isUnneededShiftMask(
const MachineInstr &
MI,
6652 unsigned ShAmtBits)
const {
6653 assert(
MI.getOpcode() == TargetOpcode::G_AND);
6655 std::optional<APInt>
RHS =
6660 if (
RHS->countr_one() >= ShAmtBits)
6663 const APInt &LHSKnownZeros =
VT->getKnownZeroes(
MI.getOperand(1).getReg());
6664 return (LHSKnownZeros | *
RHS).countr_one() >= ShAmtBits;
6668AMDGPUInstructionSelector::selectMUBUFScratchOffset(
6671 const SIMachineFunctionInfo *
Info =
MF->getInfo<SIMachineFunctionInfo>();
6673 std::optional<DefinitionAndSourceRegister>
Def =
6675 assert(Def &&
"this shouldn't be an optional result");
6680 [=](MachineInstrBuilder &MIB) {
6683 [=](MachineInstrBuilder &MIB) {
6686 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
6697 if (!TII.isLegalMUBUFImmOffset(
Offset))
6705 [=](MachineInstrBuilder &MIB) {
6708 [=](MachineInstrBuilder &MIB) {
6716 !TII.isLegalMUBUFImmOffset(
Offset))
6720 [=](MachineInstrBuilder &MIB) {
6723 [=](MachineInstrBuilder &MIB) {
6730std::pair<Register, unsigned>
6731AMDGPUInstructionSelector::selectDS1Addr1OffsetImpl(
6733 int64_t ConstAddr = 0;
6737 std::tie(PtrBase,
Offset, std::ignore) =
6738 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
6741 if (isDSOffsetLegal(PtrBase,
Offset)) {
6743 return std::pair(PtrBase,
Offset);
6752 return std::pair(Root.
getReg(), 0);
6756AMDGPUInstructionSelector::selectDS1Addr1Offset(
MachineOperand &Root)
const {
6759 std::tie(
Reg,
Offset) = selectDS1Addr1OffsetImpl(Root);
6761 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
6767AMDGPUInstructionSelector::selectDS64Bit4ByteAligned(
MachineOperand &Root)
const {
6768 return selectDSReadWrite2(Root, 4);
6772AMDGPUInstructionSelector::selectDS128Bit8ByteAligned(
MachineOperand &Root)
const {
6773 return selectDSReadWrite2(Root, 8);
6777AMDGPUInstructionSelector::selectDSReadWrite2(
MachineOperand &Root,
6778 unsigned Size)
const {
6783 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
6785 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Offset+1); }
6789std::pair<Register, unsigned>
6790AMDGPUInstructionSelector::selectDSReadWrite2Impl(
MachineOperand &Root,
6791 unsigned Size)
const {
6792 int64_t ConstAddr = 0;
6796 std::tie(PtrBase,
Offset, std::ignore) =
6797 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
6800 int64_t OffsetValue0 =
Offset;
6802 if (isDSOffset2Legal(PtrBase, OffsetValue0, OffsetValue1,
Size)) {
6804 return std::pair(PtrBase, OffsetValue0 /
Size);
6813 return std::pair(Root.
getReg(), 0);
6821std::tuple<Register, int64_t, bool>
6822AMDGPUInstructionSelector::getPtrBaseWithConstantOffset(
6825 if (RootI->
getOpcode() != TargetOpcode::G_PTR_ADD)
6826 return {Root, 0,
false};
6829 std::optional<ValueAndVReg> MaybeOffset =
6832 return {Root, 0,
false};
6852 B.buildInstr(AMDGPU::S_MOV_B32)
6855 B.buildInstr(AMDGPU::S_MOV_B32)
6862 B.buildInstr(AMDGPU::REG_SEQUENCE)
6865 .addImm(AMDGPU::sub0)
6867 .addImm(AMDGPU::sub1);
6872 B.buildInstr(AMDGPU::S_MOV_B64)
6877 B.buildInstr(AMDGPU::REG_SEQUENCE)
6880 .addImm(AMDGPU::sub0_sub1)
6882 .addImm(AMDGPU::sub2_sub3);
6889 uint64_t DefaultFormat =
TII.getDefaultRsrcDataFormat();
6898 uint64_t DefaultFormat =
TII.getDefaultRsrcDataFormat();
6905AMDGPUInstructionSelector::MUBUFAddressData
6906AMDGPUInstructionSelector::parseMUBUFAddress(
Register Src)
const {
6907 MUBUFAddressData
Data;
6913 std::tie(PtrBase,
Offset, std::ignore) =
6914 getPtrBaseWithConstantOffset(Src, *MRI);
6920 if (MachineInstr *InputAdd
6922 Data.N2 = InputAdd->getOperand(1).getReg();
6923 Data.N3 = InputAdd->getOperand(2).getReg();
6938bool AMDGPUInstructionSelector::shouldUseAddr64(MUBUFAddressData Addr)
const {
6944 const RegisterBank *N0Bank = RBI.getRegBank(Addr.N0, *MRI, TRI);
6945 return N0Bank->
getID() == AMDGPU::VGPRRegBankID;
6951void AMDGPUInstructionSelector::splitIllegalMUBUFOffset(
6953 if (TII.isLegalMUBUFImmOffset(ImmOffset))
6957 SOffset = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
6958 B.buildInstr(AMDGPU::S_MOV_B32)
6964bool AMDGPUInstructionSelector::selectMUBUFAddr64Impl(
6969 if (!STI.hasAddr64() || STI.useFlatForGlobal())
6972 MUBUFAddressData AddrData = parseMUBUFAddress(Root.
getReg());
6973 if (!shouldUseAddr64(AddrData))
6979 Offset = AddrData.Offset;
6985 if (RBI.getRegBank(N2, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
6987 if (RBI.getRegBank(N3, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
7000 }
else if (RBI.getRegBank(N0, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
7011 splitIllegalMUBUFOffset(
B, SOffset,
Offset);
7015bool AMDGPUInstructionSelector::selectMUBUFOffsetImpl(
7020 if (STI.useFlatForGlobal())
7023 MUBUFAddressData AddrData = parseMUBUFAddress(Root.
getReg());
7024 if (shouldUseAddr64(AddrData))
7030 Offset = AddrData.Offset;
7036 splitIllegalMUBUFOffset(
B, SOffset,
Offset);
7041AMDGPUInstructionSelector::selectMUBUFAddr64(
MachineOperand &Root)
const {
7047 if (!selectMUBUFAddr64Impl(Root, VAddr, RSrcReg, SOffset,
Offset))
7053 [=](MachineInstrBuilder &MIB) {
7056 [=](MachineInstrBuilder &MIB) {
7059 [=](MachineInstrBuilder &MIB) {
7062 else if (STI.hasRestrictedSOffset())
7063 MIB.
addReg(AMDGPU::SGPR_NULL);
7067 [=](MachineInstrBuilder &MIB) {
7077AMDGPUInstructionSelector::selectMUBUFOffset(
MachineOperand &Root)
const {
7082 if (!selectMUBUFOffsetImpl(Root, RSrcReg, SOffset,
Offset))
7086 [=](MachineInstrBuilder &MIB) {
7089 [=](MachineInstrBuilder &MIB) {
7092 else if (STI.hasRestrictedSOffset())
7093 MIB.
addReg(AMDGPU::SGPR_NULL);
7105AMDGPUInstructionSelector::selectBUFSOffset(
MachineOperand &Root)
const {
7110 SOffset = AMDGPU::SGPR_NULL;
7112 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); }}};
7116static std::optional<uint64_t>
7120 if (!OffsetVal || !
isInt<32>(*OffsetVal))
7121 return std::nullopt;
7122 return Lo_32(*OffsetVal);
7126AMDGPUInstructionSelector::selectSMRDBufferImm(
MachineOperand &Root)
const {
7127 std::optional<uint64_t> OffsetVal =
7132 std::optional<int64_t> EncodedImm =
7137 return {{ [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); } }};
7141AMDGPUInstructionSelector::selectSMRDBufferImm32(
MachineOperand &Root)
const {
7148 std::optional<int64_t> EncodedImm =
7153 return {{ [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); } }};
7157AMDGPUInstructionSelector::selectSMRDBufferSgprImm(
MachineOperand &Root)
const {
7165 return std::nullopt;
7167 std::optional<int64_t> EncodedOffset =
7170 return std::nullopt;
7172 assert(MRI->getType(SOffset).getSizeInBits() == 32);
7173 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
7174 [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedOffset); }}};
7177std::pair<Register, unsigned>
7178AMDGPUInstructionSelector::selectVOP3PMadMixModsImpl(
MachineOperand &Root,
7179 bool &Matched)
const {
7184 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
7194 const auto CheckAbsNeg = [&]() {
7199 std::tie(Src, ModsTmp) = selectVOP3ModsImpl(Src);
7239AMDGPUInstructionSelector::selectVOP3PMadMixModsExt(
7244 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7249 [=](MachineInstrBuilder &MIB) { MIB.
addReg(widenSrcIfVGPR16(Src, MIB)); },
7250 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
7255AMDGPUInstructionSelector::selectVOP3PMadMixMods(
MachineOperand &Root)
const {
7259 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7262 [=](MachineInstrBuilder &MIB) { MIB.
addReg(widenSrcIfVGPR16(Src, MIB)); },
7263 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
7268AMDGPUInstructionSelector::selectVOP3PMadMixModsExtNeg(
7273 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7278 [=](MachineInstrBuilder &MIB) { MIB.
addReg(widenSrcIfVGPR16(Src, MIB)); },
7279 [=](MachineInstrBuilder &MIB) {
7286AMDGPUInstructionSelector::selectVOP3PMadMixModsNeg(
7291 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7294 [=](MachineInstrBuilder &MIB) { MIB.
addReg(widenSrcIfVGPR16(Src, MIB)); },
7295 [=](MachineInstrBuilder &MIB) {
7301bool AMDGPUInstructionSelector::selectSBarrierSignalIsfirst(
7305 Register CCReg =
I.getOperand(0).getReg();
7310 BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM))
7311 .
addImm(
I.getOperand(2).getImm());
7315 I.eraseFromParent();
7316 return RBI.constrainGenericRegister(CCReg, AMDGPU::SReg_32_XM0_XEXECRegClass,
7320bool AMDGPUInstructionSelector::selectSGetBarrierState(
7324 const MachineOperand &BarOp =
I.getOperand(2);
7325 std::optional<int64_t> BarValImm =
7329 auto CopyMIB =
BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
7333 MachineInstrBuilder MIB;
7334 unsigned Opc = BarValImm ? AMDGPU::S_GET_BARRIER_STATE_IMM
7335 : AMDGPU::S_GET_BARRIER_STATE_M0;
7338 auto DstReg =
I.getOperand(0).getReg();
7340 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
7341 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
7347 I.eraseFromParent();
7352 if (HasInlineConst) {
7356 case Intrinsic::amdgcn_s_barrier_join:
7357 return AMDGPU::S_BARRIER_JOIN_IMM;
7358 case Intrinsic::amdgcn_s_wakeup_barrier:
7359 return AMDGPU::S_WAKEUP_BARRIER_IMM;
7360 case Intrinsic::amdgcn_s_get_named_barrier_state:
7361 return AMDGPU::S_GET_BARRIER_STATE_IMM;
7367 case Intrinsic::amdgcn_s_barrier_join:
7368 return AMDGPU::S_BARRIER_JOIN_M0;
7369 case Intrinsic::amdgcn_s_wakeup_barrier:
7370 return AMDGPU::S_WAKEUP_BARRIER_M0;
7371 case Intrinsic::amdgcn_s_get_named_barrier_state:
7372 return AMDGPU::S_GET_BARRIER_STATE_M0;
7377bool AMDGPUInstructionSelector::selectNamedBarrierInit(
7381 const MachineOperand &BarOp =
I.getOperand(1);
7382 const MachineOperand &CntOp =
I.getOperand(2);
7386 if (IntrID == Intrinsic::amdgcn_s_barrier_signal_var) {
7387 std::optional<int64_t> CntImm =
7389 if (CntImm && *CntImm == 0) {
7390 std::optional<int64_t> BarValImm =
7393 uint32_t BarID = *BarValImm & 0x3F;
7394 BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::S_BARRIER_SIGNAL_IMM))
7396 I.eraseFromParent();
7403 Register TmpReg1 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7410 Register TmpReg2 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7416 Register TmpReg3 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7417 constexpr unsigned ShAmt = 16;
7423 Register TmpReg4 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7433 unsigned Opc = IntrID == Intrinsic::amdgcn_s_barrier_init
7434 ? AMDGPU::S_BARRIER_INIT_M0
7435 : AMDGPU::S_BARRIER_SIGNAL_M0;
7436 MachineInstrBuilder MIB;
7439 I.eraseFromParent();
7443bool AMDGPUInstructionSelector::selectNamedBarrierInst(
7447 MachineOperand BarOp = IntrID == Intrinsic::amdgcn_s_get_named_barrier_state
7450 std::optional<int64_t> BarValImm =
7455 Register TmpReg1 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7461 auto CopyMIB =
BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
7466 MachineInstrBuilder MIB;
7470 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state) {
7471 auto DstReg =
I.getOperand(0).getReg();
7473 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
7474 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
7480 uint32_t BarId = *BarValImm & 0x3F;
7484 I.eraseFromParent();
7491 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
7492 "Expected G_CONSTANT");
7493 MIB.
addImm(
MI.getOperand(1).getCImm()->getSExtValue());
7499 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
7500 "Expected G_CONSTANT");
7501 MIB.
addImm(-
MI.getOperand(1).getCImm()->getSExtValue());
7507 const MachineOperand &
Op =
MI.getOperand(1);
7508 assert(
MI.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1);
7509 MIB.
addImm(
Op.getFPImm()->getValueAPF().bitcastToAPInt().getZExtValue());
7512void AMDGPUInstructionSelector::renderCountTrailingOnesImm(
7514 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
7515 "Expected G_CONSTANT");
7516 MIB.
addImm(
MI.getOperand(1).getCImm()->getValue().countTrailingOnes());
7524 const MachineOperand &
Op =
MI.getOperand(OpIdx);
7535 MIB.
addImm(
MI.getOperand(OpIdx).getImm() != 0);
7541 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7545void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_0_0(
7547 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7552void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_0_1(
7554 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7555 MIB.
addImm((
MI.getOperand(OpIdx).getImm() & 0x1)
7560void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_1_0(
7562 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7567void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_1_1(
7569 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7570 MIB.
addImm((
MI.getOperand(OpIdx).getImm() & 0x2)
7575void AMDGPUInstructionSelector::renderDstSelToOpSelXForm(
7577 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7582void AMDGPUInstructionSelector::renderSrcSelToOpSelXForm(
7584 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7589void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_2_0(
7591 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7596void AMDGPUInstructionSelector::renderDstSelToOpSel3XFormXForm(
7598 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7599 MIB.
addImm((
MI.getOperand(OpIdx).getImm() & 0x2)
7607 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7608 MIB.
addImm(
MI.getOperand(OpIdx).getImm() &
7616 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7617 const bool Swizzle =
MI.getOperand(OpIdx).getImm() &
7623void AMDGPUInstructionSelector::renderExtractCpolSetGLC(
7625 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7626 const uint32_t Cpol =
MI.getOperand(OpIdx).getImm() &
7635 const APFloat &APF =
MI.getOperand(1).getFPImm()->getValueAPF();
7637 assert(ExpVal != INT_MIN);
7648 MIB.
addImm((
MI.getOperand(OpIdx).getImm() + 3) % 4);
7655 if (
MI.getOperand(OpIdx).getImm())
7657 MIB.
addImm((int64_t)Mods);
7664 if (
MI.getOperand(OpIdx).getImm())
7666 MIB.
addImm((int64_t)Mods);
7672 unsigned Val =
MI.getOperand(OpIdx).getImm();
7680 MIB.
addImm((int64_t)Mods);
7686 uint32_t
V =
MI.getOperand(2).getImm();
7689 if (!Subtarget->hasSafeCUPrefetch())
7695void AMDGPUInstructionSelector::renderScaledMAIIntrinsicOperand(
7697 unsigned Val =
MI.getOperand(OpIdx).getImm();
7706bool AMDGPUInstructionSelector::isInlineImmediate(
const APInt &
Imm)
const {
7707 return TII.isInlineConstant(
Imm);
7710bool AMDGPUInstructionSelector::isInlineImmediate(
const APFloat &
Imm)
const {
7711 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.
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.
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.
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
LLVM_READONLY bool hasNamedOperand(uint64_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)
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.
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).
@ Kill
The last use of a register.
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)
@ Default
The result value is uniform if and only if all operands are uniform.
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.