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) {
2898bool AMDGPUInstructionSelector::selectG_FPEXT(
MachineInstr &
I)
const {
2899 if (!Subtarget->hasSALUFloatInsts())
2902 Register Dst =
I.getOperand(0).getReg();
2903 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
2904 if (DstRB->
getID() != AMDGPU::SGPRRegBankID)
2907 Register Src =
I.getOperand(1).getReg();
2913 BuildMI(*BB, &
I,
I.getDebugLoc(), TII.get(AMDGPU::S_CVT_HI_F32_F16), Dst)
2915 I.eraseFromParent();
2916 return RBI.constrainGenericRegister(Dst, AMDGPU::SReg_32RegClass, *MRI);
2923bool AMDGPUInstructionSelector::selectG_FNEG(
MachineInstr &
MI)
const {
2936 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
2937 if (DstRB->
getID() != AMDGPU::SGPRRegBankID ||
2942 MachineInstr *Fabs =
getOpcodeDef(TargetOpcode::G_FABS, Src, *MRI);
2946 if (!RBI.constrainGenericRegister(Src, AMDGPU::SReg_64RegClass, *MRI) ||
2947 !RBI.constrainGenericRegister(Dst, AMDGPU::SReg_64RegClass, *MRI))
2952 Register LoReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2953 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2954 Register ConstReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2955 Register OpReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2957 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), LoReg)
2958 .
addReg(Src, {}, AMDGPU::sub0);
2959 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), HiReg)
2960 .
addReg(Src, {}, AMDGPU::sub1);
2961 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_MOV_B32), ConstReg)
2965 unsigned Opc = Fabs ? AMDGPU::S_OR_B32 : AMDGPU::S_XOR_B32;
2970 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::REG_SEQUENCE), Dst)
2975 MI.eraseFromParent();
2980bool AMDGPUInstructionSelector::selectG_FABS(
MachineInstr &
MI)
const {
2982 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
2983 if (DstRB->
getID() != AMDGPU::SGPRRegBankID ||
2990 Register LoReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2991 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2992 Register ConstReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2993 Register OpReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2995 if (!RBI.constrainGenericRegister(Src, AMDGPU::SReg_64RegClass, *MRI) ||
2996 !RBI.constrainGenericRegister(Dst, AMDGPU::SReg_64RegClass, *MRI))
2999 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), LoReg)
3000 .
addReg(Src, {}, AMDGPU::sub0);
3001 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), HiReg)
3002 .
addReg(Src, {}, AMDGPU::sub1);
3003 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_MOV_B32), ConstReg)
3008 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_AND_B32), OpReg)
3012 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::REG_SEQUENCE), Dst)
3018 MI.eraseFromParent();
3023 return MI.getOpcode() == TargetOpcode::G_CONSTANT;
3029 unsigned OpNo =
Load.getOpcode() == AMDGPU::G_PREFETCH ? 0 : 1;
3030 const MachineInstr *PtrMI =
3031 MRI.getUniqueVRegDef(
Load.getOperand(OpNo).getReg());
3035 if (PtrMI->
getOpcode() != TargetOpcode::G_PTR_ADD)
3040 for (
unsigned i = 1; i != 3; ++i) {
3041 const MachineOperand &GEPOp = PtrMI->
getOperand(i);
3042 const MachineInstr *OpDef = MRI.getUniqueVRegDef(GEPOp.
getReg());
3047 assert(GEPInfo.Imm == 0);
3051 const RegisterBank *OpBank = RBI.getRegBank(GEPOp.
getReg(), MRI, TRI);
3052 if (OpBank->
getID() == AMDGPU::SGPRRegBankID)
3053 GEPInfo.SgprParts.push_back(GEPOp.
getReg());
3055 GEPInfo.VgprParts.push_back(GEPOp.
getReg());
3059 getAddrModeInfo(*PtrMI, MRI, AddrInfo);
3062bool AMDGPUInstructionSelector::isSGPR(
Register Reg)
const {
3063 return RBI.getRegBank(
Reg, *MRI, TRI)->getID() == AMDGPU::SGPRRegBankID;
3066bool AMDGPUInstructionSelector::isInstrUniform(
const MachineInstr &
MI)
const {
3067 if (!
MI.hasOneMemOperand())
3070 const MachineMemOperand *MMO = *
MI.memoperands_begin();
3083 if (
MI.getOpcode() == AMDGPU::G_PREFETCH)
3084 return RBI.getRegBank(
MI.getOperand(0).getReg(), *MRI, TRI)->getID() ==
3085 AMDGPU::SGPRRegBankID;
3088 return I &&
I->getMetadata(
"amdgpu.uniform");
3092 for (
const GEPInfo &GEPInfo : AddrInfo) {
3093 if (!GEPInfo.VgprParts.empty())
3099void AMDGPUInstructionSelector::initM0(
MachineInstr &
I)
const {
3100 const LLT PtrTy = MRI->getType(
I.getOperand(1).getReg());
3103 STI.ldsRequiresM0Init()) {
3107 BuildMI(*BB, &
I,
I.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), AMDGPU::M0)
3112bool AMDGPUInstructionSelector::selectG_LOAD_STORE_ATOMICRMW(
3119 if (
Reg.isPhysical())
3123 const unsigned Opcode =
MI.getOpcode();
3125 if (Opcode == AMDGPU::COPY)
3128 if (Opcode == AMDGPU::G_AND || Opcode == AMDGPU::G_OR ||
3129 Opcode == AMDGPU::G_XOR)
3134 return GI->is(Intrinsic::amdgcn_class);
3136 return Opcode == AMDGPU::G_ICMP || Opcode == AMDGPU::G_FCMP;
3139bool AMDGPUInstructionSelector::selectG_BRCOND(
MachineInstr &
I)
const {
3141 MachineOperand &CondOp =
I.getOperand(0);
3154 if (!isVCC(CondReg, *MRI)) {
3158 CondPhysReg = AMDGPU::SCC;
3159 BrOpcode = AMDGPU::S_CBRANCH_SCC1;
3160 ConstrainRC = &AMDGPU::SReg_32RegClass;
3167 const bool Is64 = STI.isWave64();
3168 const unsigned Opcode = Is64 ? AMDGPU::S_AND_B64 : AMDGPU::S_AND_B32;
3169 const Register Exec = Is64 ? AMDGPU::EXEC : AMDGPU::EXEC_LO;
3171 Register TmpReg = MRI->createVirtualRegister(TRI.getBoolRC());
3172 BuildMI(*BB, &
I,
DL, TII.get(Opcode), TmpReg)
3179 CondPhysReg = TRI.getVCC();
3180 BrOpcode = AMDGPU::S_CBRANCH_VCCNZ;
3181 ConstrainRC = TRI.getBoolRC();
3184 if (!MRI->getRegClassOrNull(CondReg))
3185 MRI->setRegClass(CondReg, ConstrainRC);
3187 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), CondPhysReg)
3190 .
addMBB(
I.getOperand(1).getMBB());
3192 I.eraseFromParent();
3196bool AMDGPUInstructionSelector::selectG_GLOBAL_VALUE(
3198 Register DstReg =
I.getOperand(0).getReg();
3199 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3200 const bool IsVGPR = DstRB->
getID() == AMDGPU::VGPRRegBankID;
3201 I.setDesc(TII.get(IsVGPR ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32));
3205 return RBI.constrainGenericRegister(
3206 DstReg, IsVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass, *MRI);
3209bool AMDGPUInstructionSelector::selectG_PTRMASK(
MachineInstr &
I)
const {
3210 Register DstReg =
I.getOperand(0).getReg();
3211 Register SrcReg =
I.getOperand(1).getReg();
3212 Register MaskReg =
I.getOperand(2).getReg();
3213 LLT Ty = MRI->getType(DstReg);
3214 LLT MaskTy = MRI->getType(MaskReg);
3218 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3219 const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
3220 const RegisterBank *MaskRB = RBI.getRegBank(MaskReg, *MRI, TRI);
3221 const bool IsVGPR = DstRB->
getID() == AMDGPU::VGPRRegBankID;
3227 APInt MaskOnes =
VT->getKnownOnes(MaskReg).zext(64);
3231 const bool CanCopyLow32 = (MaskOnes & MaskLo32) == MaskLo32;
3232 const bool CanCopyHi32 = (MaskOnes & MaskHi32) == MaskHi32;
3235 !CanCopyLow32 && !CanCopyHi32) {
3236 auto MIB =
BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_AND_B64), DstReg)
3240 I.eraseFromParent();
3245 unsigned NewOpc = IsVGPR ? AMDGPU::V_AND_B32_e64 : AMDGPU::S_AND_B32;
3247 = IsVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
3252 TRI.getRegClassForTypeOnBank(MaskTy, *MaskRB);
3254 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
3255 !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
3256 !RBI.constrainGenericRegister(MaskReg, *MaskRC, *MRI))
3261 "ptrmask should have been narrowed during legalize");
3263 auto NewOp =
BuildMI(*BB, &
I,
DL, TII.get(NewOpc), DstReg)
3269 I.eraseFromParent();
3273 Register HiReg = MRI->createVirtualRegister(&RegRC);
3274 Register LoReg = MRI->createVirtualRegister(&RegRC);
3277 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), LoReg)
3278 .
addReg(SrcReg, {}, AMDGPU::sub0);
3279 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), HiReg)
3280 .
addReg(SrcReg, {}, AMDGPU::sub1);
3289 Register MaskLo = MRI->createVirtualRegister(&RegRC);
3290 MaskedLo = MRI->createVirtualRegister(&RegRC);
3292 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), MaskLo)
3293 .
addReg(MaskReg, {}, AMDGPU::sub0);
3294 BuildMI(*BB, &
I,
DL, TII.get(NewOpc), MaskedLo)
3303 Register MaskHi = MRI->createVirtualRegister(&RegRC);
3304 MaskedHi = MRI->createVirtualRegister(&RegRC);
3306 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), MaskHi)
3307 .
addReg(MaskReg, {}, AMDGPU::sub1);
3308 BuildMI(*BB, &
I,
DL, TII.get(NewOpc), MaskedHi)
3313 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
3318 I.eraseFromParent();
3324static std::pair<Register, unsigned>
3331 std::tie(IdxBaseReg,
Offset) =
3333 if (IdxBaseReg == AMDGPU::NoRegister) {
3337 IdxBaseReg = IdxReg;
3344 if (
static_cast<unsigned>(
Offset) >= SubRegs.
size())
3345 return std::pair(IdxReg, SubRegs[0]);
3346 return std::pair(IdxBaseReg, SubRegs[
Offset]);
3349bool AMDGPUInstructionSelector::selectG_EXTRACT_VECTOR_ELT(
3355 LLT DstTy = MRI->getType(DstReg);
3356 LLT SrcTy = MRI->getType(SrcReg);
3358 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3359 const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
3360 const RegisterBank *IdxRB = RBI.getRegBank(IdxReg, *MRI, TRI);
3364 if (IdxRB->
getID() != AMDGPU::SGPRRegBankID)
3368 TRI.getRegClassForTypeOnBank(SrcTy, *SrcRB);
3370 TRI.getRegClassForTypeOnBank(DstTy, *DstRB);
3371 if (!SrcRC || !DstRC)
3373 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
3374 !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
3375 !RBI.constrainGenericRegister(IdxReg, AMDGPU::SReg_32RegClass, *MRI))
3386 if (SrcRB->
getID() == AMDGPU::SGPRRegBankID) {
3390 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3393 unsigned Opc = Is64 ? AMDGPU::S_MOVRELS_B64 : AMDGPU::S_MOVRELS_B32;
3395 .
addReg(SrcReg, {}, SubReg)
3397 MI.eraseFromParent();
3404 if (!STI.useVGPRIndexMode()) {
3405 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3407 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::V_MOVRELS_B32_e32), DstReg)
3408 .
addReg(SrcReg, {}, SubReg)
3410 MI.eraseFromParent();
3414 const MCInstrDesc &GPRIDXDesc =
3415 TII.getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*SrcRC),
true);
3421 MI.eraseFromParent();
3426bool AMDGPUInstructionSelector::selectG_INSERT_VECTOR_ELT(
3433 LLT VecTy = MRI->getType(DstReg);
3434 LLT ValTy = MRI->getType(ValReg);
3438 const RegisterBank *VecRB = RBI.getRegBank(VecReg, *MRI, TRI);
3439 const RegisterBank *ValRB = RBI.getRegBank(ValReg, *MRI, TRI);
3440 const RegisterBank *IdxRB = RBI.getRegBank(IdxReg, *MRI, TRI);
3446 if (IdxRB->
getID() != AMDGPU::SGPRRegBankID)
3450 TRI.getRegClassForTypeOnBank(VecTy, *VecRB);
3452 TRI.getRegClassForTypeOnBank(ValTy, *ValRB);
3454 if (!RBI.constrainGenericRegister(VecReg, *VecRC, *MRI) ||
3455 !RBI.constrainGenericRegister(DstReg, *VecRC, *MRI) ||
3456 !RBI.constrainGenericRegister(ValReg, *ValRC, *MRI) ||
3457 !RBI.constrainGenericRegister(IdxReg, AMDGPU::SReg_32RegClass, *MRI))
3460 if (VecRB->
getID() == AMDGPU::VGPRRegBankID && ValSize != 32)
3464 std::tie(IdxReg, SubReg) =
3467 const bool IndexMode = VecRB->
getID() == AMDGPU::VGPRRegBankID &&
3468 STI.useVGPRIndexMode();
3474 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3477 const MCInstrDesc &RegWriteOp = TII.getIndirectRegWriteMovRelPseudo(
3478 VecSize, ValSize, VecRB->
getID() == AMDGPU::SGPRRegBankID);
3483 MI.eraseFromParent();
3487 const MCInstrDesc &GPRIDXDesc =
3488 TII.getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC),
false);
3495 MI.eraseFromParent();
3501 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
3502 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
3503 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
3504 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
3505 case Intrinsic::amdgcn_load_async_to_lds:
3506 case Intrinsic::amdgcn_global_load_async_lds:
3512bool AMDGPUInstructionSelector::selectBufferLoadLds(
MachineInstr &
MI)
const {
3513 if (!Subtarget->hasVMemToLDSLoad())
3516 unsigned Size =
MI.getOperand(3).getImm();
3520 const bool HasVIndex =
MI.getNumOperands() == 9;
3524 VIndex =
MI.getOperand(4).getReg();
3528 Register VOffset =
MI.getOperand(4 + OpOffset).getReg();
3529 std::optional<ValueAndVReg> MaybeVOffset =
3531 const bool HasVOffset = !MaybeVOffset || MaybeVOffset->Value.getZExtValue();
3537 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_BOTHEN
3538 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_IDXEN
3539 : HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFEN
3540 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFSET;
3543 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_BOTHEN
3544 : AMDGPU::BUFFER_LOAD_USHORT_LDS_IDXEN
3545 : HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFEN
3546 : AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFSET;
3549 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_BOTHEN
3550 : AMDGPU::BUFFER_LOAD_DWORD_LDS_IDXEN
3551 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFEN
3552 : AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFSET;
3555 if (!Subtarget->hasLDSLoadB96_B128())
3558 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_BOTHEN
3559 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_IDXEN
3560 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFEN
3561 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFSET;
3564 if (!Subtarget->hasLDSLoadB96_B128())
3567 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_BOTHEN
3568 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_IDXEN
3569 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFEN
3570 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFSET;
3577 .
add(
MI.getOperand(2));
3581 if (HasVIndex && HasVOffset) {
3582 Register IdxReg = MRI->createVirtualRegister(TRI.getVGPR64Class());
3583 BuildMI(*
MBB, &*MIB,
DL, TII.get(AMDGPU::REG_SEQUENCE), IdxReg)
3590 }
else if (HasVIndex) {
3592 }
else if (HasVOffset) {
3596 MIB.
add(
MI.getOperand(1));
3597 MIB.
add(
MI.getOperand(5 + OpOffset));
3598 MIB.
add(
MI.getOperand(6 + OpOffset));
3600 unsigned Aux =
MI.getOperand(7 + OpOffset).getImm();
3609 MachineMemOperand *LoadMMO = *
MI.memoperands_begin();
3614 MachinePointerInfo StorePtrI = LoadPtrI;
3625 MachineMemOperand *StoreMMO =
3631 MI.eraseFromParent();
3644 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3650 return Def->getOperand(1).getReg();
3664 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3672 return Def->getOperand(1).getReg();
3675 if (ZextSrc &&
VT->signBitIsZero(ZextSrc))
3684AMDGPUInstructionSelector::matchZeroExtendFromS32OrS32(
Register Reg)
const {
3686 : matchZeroExtendFromS32(
Reg);
3692AMDGPUInstructionSelector::matchSignExtendFromS32OrS32(
Register Reg)
const {
3694 : matchSignExtendFromS32(
Reg);
3698AMDGPUInstructionSelector::matchExtendFromS32OrS32(
Register Reg,
3699 bool IsSigned)
const {
3701 return matchSignExtendFromS32OrS32(
Reg);
3703 return matchZeroExtendFromS32OrS32(
Reg);
3713 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3720 return Def->getOperand(1).getReg();
3725bool AMDGPUInstructionSelector::selectGlobalLoadLds(
MachineInstr &
MI)
const{
3726 if (!Subtarget->hasVMemToLDSLoad())
3730 unsigned Size =
MI.getOperand(3).getImm();
3737 Opc = AMDGPU::GLOBAL_LOAD_LDS_UBYTE;
3740 Opc = AMDGPU::GLOBAL_LOAD_LDS_USHORT;
3743 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORD;
3746 if (!Subtarget->hasLDSLoadB96_B128())
3748 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX3;
3751 if (!Subtarget->hasLDSLoadB96_B128())
3753 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX4;
3760 .
add(
MI.getOperand(2));
3766 if (!isSGPR(Addr)) {
3768 if (isSGPR(AddrDef->Reg)) {
3769 Addr = AddrDef->Reg;
3770 }
else if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
3773 if (isSGPR(SAddr)) {
3774 Register PtrBaseOffset = AddrDef->MI->getOperand(2).getReg();
3775 if (
Register Off = matchZeroExtendFromS32(PtrBaseOffset)) {
3786 VOffset = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
3798 MIB.
add(
MI.getOperand(4));
3800 unsigned Aux =
MI.getOperand(5).getImm();
3804 MachineMemOperand *LoadMMO = *
MI.memoperands_begin();
3806 LoadPtrI.
Offset =
MI.getOperand(4).getImm();
3807 MachinePointerInfo StorePtrI = LoadPtrI;
3816 MachineMemOperand *StoreMMO =
3818 sizeof(int32_t),
Align(4));
3822 MI.eraseFromParent();
3827bool AMDGPUInstructionSelector::selectTensorLoadStore(
MachineInstr &
MI,
3829 bool IsLoad = IID == Intrinsic::amdgcn_tensor_load_to_lds;
3831 IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d4 : AMDGPU::TENSOR_STORE_FROM_LDS_d4;
3835 const auto isAllZeros = [&](MachineOperand &Opnd) {
3836 const MachineInstr *
DefMI = MRI->getVRegDef(Opnd.getReg());
3845 Opc = IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d2
3846 : AMDGPU::TENSOR_STORE_FROM_LDS_d2;
3853 .
add(
MI.getOperand(1))
3854 .
add(
MI.getOperand(2));
3856 if (NumGroups >= 4) {
3857 MIB.
add(
MI.getOperand(3))
3858 .
add(
MI.getOperand(4));
3862 .
add(
MI.getOperand(6));
3864 MI.eraseFromParent();
3868bool AMDGPUInstructionSelector::selectBVHIntersectRayIntrinsic(
3870 unsigned OpcodeOpIdx =
3871 MI.getOpcode() == AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY ? 1 : 3;
3872 MI.setDesc(TII.get(
MI.getOperand(OpcodeOpIdx).getImm()));
3873 MI.removeOperand(OpcodeOpIdx);
3874 MI.addImplicitDefUseOperands(*
MI.getMF());
3881bool AMDGPUInstructionSelector::selectSMFMACIntrin(
MachineInstr &
MI)
const {
3884 case Intrinsic::amdgcn_smfmac_f32_16x16x32_f16:
3885 Opc = AMDGPU::V_SMFMAC_F32_16X16X32_F16_e64;
3887 case Intrinsic::amdgcn_smfmac_f32_32x32x16_f16:
3888 Opc = AMDGPU::V_SMFMAC_F32_32X32X16_F16_e64;
3890 case Intrinsic::amdgcn_smfmac_f32_16x16x32_bf16:
3891 Opc = AMDGPU::V_SMFMAC_F32_16X16X32_BF16_e64;
3893 case Intrinsic::amdgcn_smfmac_f32_32x32x16_bf16:
3894 Opc = AMDGPU::V_SMFMAC_F32_32X32X16_BF16_e64;
3896 case Intrinsic::amdgcn_smfmac_i32_16x16x64_i8:
3897 Opc = AMDGPU::V_SMFMAC_I32_16X16X64_I8_e64;
3899 case Intrinsic::amdgcn_smfmac_i32_32x32x32_i8:
3900 Opc = AMDGPU::V_SMFMAC_I32_32X32X32_I8_e64;
3902 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_bf8:
3903 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF8_BF8_e64;
3905 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_fp8:
3906 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF8_FP8_e64;
3908 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_bf8:
3909 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_FP8_BF8_e64;
3911 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_fp8:
3912 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_FP8_FP8_e64;
3914 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_bf8:
3915 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF8_BF8_e64;
3917 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_fp8:
3918 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF8_FP8_e64;
3920 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_bf8:
3921 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_FP8_BF8_e64;
3923 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_fp8:
3924 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_FP8_FP8_e64;
3926 case Intrinsic::amdgcn_smfmac_f32_16x16x64_f16:
3927 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_F16_e64;
3929 case Intrinsic::amdgcn_smfmac_f32_32x32x32_f16:
3930 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_F16_e64;
3932 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf16:
3933 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF16_e64;
3935 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf16:
3936 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF16_e64;
3938 case Intrinsic::amdgcn_smfmac_i32_16x16x128_i8:
3939 Opc = AMDGPU::V_SMFMAC_I32_16X16X128_I8_e64;
3941 case Intrinsic::amdgcn_smfmac_i32_32x32x64_i8:
3942 Opc = AMDGPU::V_SMFMAC_I32_32X32X64_I8_e64;
3944 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_bf8:
3945 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_BF8_BF8_e64;
3947 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_fp8:
3948 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_BF8_FP8_e64;
3950 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_bf8:
3951 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_FP8_BF8_e64;
3953 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_fp8:
3954 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_FP8_FP8_e64;
3956 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_bf8:
3957 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_BF8_BF8_e64;
3959 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_fp8:
3960 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_BF8_FP8_e64;
3962 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_bf8:
3963 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_FP8_BF8_e64;
3965 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_fp8:
3966 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_FP8_FP8_e64;
3972 auto VDst_In =
MI.getOperand(4);
3974 MI.setDesc(TII.get(
Opc));
3975 MI.removeOperand(4);
3976 MI.removeOperand(1);
3977 MI.addOperand(VDst_In);
3978 MI.addImplicitDefUseOperands(*
MI.getMF());
3979 const MCInstrDesc &MCID =
MI.getDesc();
3981 MI.getOperand(0).setIsEarlyClobber(
true);
3986bool AMDGPUInstructionSelector::selectPermlaneSwapIntrin(
3988 if (IntrID == Intrinsic::amdgcn_permlane16_swap &&
3989 !Subtarget->hasPermlane16Swap())
3991 if (IntrID == Intrinsic::amdgcn_permlane32_swap &&
3992 !Subtarget->hasPermlane32Swap())
3995 unsigned Opcode = IntrID == Intrinsic::amdgcn_permlane16_swap
3996 ? AMDGPU::V_PERMLANE16_SWAP_B32_e64
3997 : AMDGPU::V_PERMLANE32_SWAP_B32_e64;
3999 MI.removeOperand(2);
4000 MI.setDesc(TII.get(Opcode));
4003 MachineOperand &FI =
MI.getOperand(4);
4010bool AMDGPUInstructionSelector::selectWaveAddress(
MachineInstr &
MI)
const {
4013 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4014 const bool IsVALU = DstRB->
getID() == AMDGPU::VGPRRegBankID;
4019 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHRREV_B32_e64), DstReg)
4020 .
addImm(Subtarget->getWavefrontSizeLog2())
4025 .
addImm(Subtarget->getWavefrontSizeLog2())
4030 IsVALU ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
4031 if (!RBI.constrainGenericRegister(DstReg, RC, *MRI))
4034 MI.eraseFromParent();
4038bool AMDGPUInstructionSelector::selectWaveShuffleIntrin(
4048 const LLT DstTy = MRI->getType(DstReg);
4050 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4052 TRI.getRegClassForSizeOnBank(DstSize, *DstRB);
4057 if (!Subtarget->supportsBPermute())
4061 if (Subtarget->supportsWaveWideBPermute()) {
4062 Register ShiftIdxReg = MRI->createVirtualRegister(DstRC);
4063 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), ShiftIdxReg)
4073 assert(Subtarget->isWave64());
4077 MRI->createVirtualRegister(TRI.getRegClass(AMDGPU::SReg_32RegClassID));
4078 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefValReg);
4080 Register UndefExecReg = MRI->createVirtualRegister(
4081 TRI.getRegClass(AMDGPU::SReg_64_XEXECRegClassID));
4082 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefExecReg);
4084 Register PoisonValReg = MRI->createVirtualRegister(DstRC);
4085 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_SET_INACTIVE_B32), PoisonValReg)
4093 Register ShiftIdxReg = MRI->createVirtualRegister(DstRC);
4094 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), ShiftIdxReg)
4098 Register PoisonIdxReg = MRI->createVirtualRegister(DstRC);
4099 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_SET_INACTIVE_B32), PoisonIdxReg)
4106 Register PoisonUnshiftedIdxReg = MRI->createVirtualRegister(DstRC);
4108 PoisonUnshiftedIdxReg)
4116 Register SameSidePermReg = MRI->createVirtualRegister(DstRC);
4117 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::DS_BPERMUTE_B32), SameSidePermReg)
4122 Register SwappedValReg = MRI->createVirtualRegister(DstRC);
4123 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_PERMLANE64_B32), SwappedValReg)
4126 Register OppSidePermReg = MRI->createVirtualRegister(DstRC);
4127 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::DS_BPERMUTE_B32), OppSidePermReg)
4132 Register WWMSwapPermReg = MRI->createVirtualRegister(DstRC);
4133 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::STRICT_WWM), WWMSwapPermReg)
4140 Register ThreadIDReg = MRI->createVirtualRegister(DstRC);
4141 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_MBCNT_LO_U32_B32_e64), ThreadIDReg)
4145 Register XORReg = MRI->createVirtualRegister(DstRC);
4148 .
addReg(PoisonUnshiftedIdxReg);
4150 Register ANDReg = MRI->createVirtualRegister(DstRC);
4155 Register CompareReg = MRI->createVirtualRegister(
4156 TRI.getRegClass(AMDGPU::SReg_64_XEXECRegClassID));
4157 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_CMP_EQ_U32_e64), CompareReg)
4162 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
4170 MI.eraseFromParent();
4179 unsigned NumOpcodes = 0;
4192 const uint8_t SrcBits[3] = { 0xf0, 0xcc, 0xaa };
4203 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4217 if (Src.size() == 3) {
4224 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4225 if (Src[
I] ==
LHS) {
4235 Bits = SrcBits[Src.size()];
4241 switch (
MI->getOpcode()) {
4242 case TargetOpcode::G_AND:
4243 case TargetOpcode::G_OR:
4244 case TargetOpcode::G_XOR: {
4249 if (!getOperandBits(
LHS, LHSBits) ||
4250 !getOperandBits(
RHS, RHSBits)) {
4251 Src = std::move(Backup);
4252 return std::make_pair(0, 0);
4273 uint8_t LHSBitsOrig = LHSBits;
4274 uint8_t RHSBitsOrig = RHSBits;
4278 NumOpcodes += LHSOp.first;
4279 LHSBits = LHSOp.second;
4286 NumOpcodes += RHSOp.first;
4287 RHSBits = RHSOp.second;
4291 auto dependsOnSlot = [](
uint8_t TT,
int Slot) ->
bool {
4292 if (Slot < 0 || Slot > 2)
4294 const uint8_t Masks[3] = {0x0f, 0x33, 0x55};
4295 const int Shifts[3] = {4, 2, 1};
4296 return ((TT ^ (TT >> Shifts[Slot])) & Masks[Slot]) != 0;
4302 const uint8_t SrcBitsConst[3] = {0xf0, 0xcc, 0xaa};
4309 for (
int I = 0;
I < (int)S.size();
I++) {
4310 if (Bits == SrcBitsConst[
I] && S[
I] ==
Op)
4312 if (IsNegationOp && Bits == (
uint8_t)~SrcBitsConst[
I] &&
4313 S[
I] == NegatedInner)
4324 for (
int I = 0;
I < (int)SrcAfterLHS.
size() &&
I < 3;
I++) {
4325 if (
I < (
int)Src.size() && Src[
I] != SrcAfterLHS[
I] &&
4326 dependsOnSlot(LHSBits,
I)) {
4335 if (!Stale && !RHSOp.first) {
4336 int Slot = findSlot(RHSBitsOrig,
RHS, SrcBeforeRecurse);
4338 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4344 if (!Stale && !LHSOp.first) {
4345 int Slot = findSlot(LHSBitsOrig,
LHS, SrcBeforeRecurse);
4347 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4352 Src = std::move(SrcBeforeRecurse);
4353 LHSBits = LHSBitsOrig;
4354 RHSBits = RHSBitsOrig;
4360 return std::make_pair(0, 0);
4364 switch (
MI->getOpcode()) {
4365 case TargetOpcode::G_AND:
4366 TTbl = LHSBits & RHSBits;
4368 case TargetOpcode::G_OR:
4369 TTbl = LHSBits | RHSBits;
4371 case TargetOpcode::G_XOR:
4372 TTbl = LHSBits ^ RHSBits;
4378 return std::make_pair(NumOpcodes + 1, TTbl);
4381bool AMDGPUInstructionSelector::selectBITOP3(
MachineInstr &
MI)
const {
4382 if (!Subtarget->hasBitOp3Insts())
4386 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4387 const bool IsVALU = DstRB->
getID() == AMDGPU::VGPRRegBankID;
4393 unsigned NumOpcodes;
4395 std::tie(NumOpcodes, TTbl) =
BitOp3_Op(DstReg, Src, *MRI);
4399 if (NumOpcodes < 2 || Src.empty())
4404 unsigned Size = MRI->getType(DstReg).getSizeInBits();
4405 assert((
Size == 16 ||
Size == 32) &&
"unexpected VALU logic op size");
4406 const bool IsB32 =
Size == 32;
4407 if (NumOpcodes == 2 && IsB32) {
4415 }
else if (NumOpcodes < 4) {
4422 unsigned Opc = IsB32 ? AMDGPU::V_BITOP3_B32_e64 : AMDGPU::V_BITOP3_B16_e64;
4423 if (!IsB32 && STI.hasTrue16BitInsts())
4424 Opc = STI.useRealTrue16Insts() ? AMDGPU::V_BITOP3_B16_gfx1250_t16_e64
4425 : AMDGPU::V_BITOP3_B16_gfx1250_fake16_e64;
4426 unsigned CBL = STI.getConstantBusLimit(
Opc);
4430 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4431 const RegisterBank *RB = RBI.getRegBank(Src[
I], *MRI, TRI);
4432 if (RB->
getID() != AMDGPU::SGPRRegBankID)
4438 Register NewReg = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
4449 while (Src.size() < 3)
4450 Src.push_back(Src[0]);
4467 MI.eraseFromParent();
4472bool AMDGPUInstructionSelector::selectStackRestore(
MachineInstr &
MI)
const {
4474 if (!RBI.constrainGenericRegister(SrcReg, AMDGPU::SReg_32RegClass, *MRI))
4477 MachineInstr *
DefMI = MRI->getVRegDef(SrcReg);
4479 Subtarget->getTargetLowering()->getStackPointerRegisterToSaveRestore();
4485 WaveAddr = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
4488 .
addImm(Subtarget->getWavefrontSizeLog2())
4495 MI.eraseFromParent();
4501 if (!
I.isPreISelOpcode()) {
4503 return selectCOPY(
I);
4507 switch (
I.getOpcode()) {
4508 case TargetOpcode::G_AND:
4509 case TargetOpcode::G_OR:
4510 case TargetOpcode::G_XOR:
4511 if (selectBITOP3(
I))
4515 return selectG_AND_OR_XOR(
I);
4516 case TargetOpcode::G_ADD:
4517 case TargetOpcode::G_SUB:
4518 case TargetOpcode::G_PTR_ADD:
4521 return selectG_ADD_SUB(
I);
4522 case TargetOpcode::G_UADDO:
4523 case TargetOpcode::G_USUBO:
4524 case TargetOpcode::G_UADDE:
4525 case TargetOpcode::G_USUBE:
4526 return selectG_UADDO_USUBO_UADDE_USUBE(
I);
4527 case AMDGPU::G_AMDGPU_MAD_U64_U32:
4528 case AMDGPU::G_AMDGPU_MAD_I64_I32:
4529 return selectG_AMDGPU_MAD_64_32(
I);
4530 case TargetOpcode::G_INTTOPTR:
4531 case TargetOpcode::G_BITCAST:
4532 case TargetOpcode::G_PTRTOINT:
4533 case TargetOpcode::G_FREEZE:
4534 return selectCOPY(
I);
4535 case TargetOpcode::G_FNEG:
4538 return selectG_FNEG(
I);
4539 case TargetOpcode::G_FABS:
4542 return selectG_FABS(
I);
4543 case TargetOpcode::G_EXTRACT:
4544 return selectG_EXTRACT(
I);
4545 case TargetOpcode::G_MERGE_VALUES:
4546 case TargetOpcode::G_CONCAT_VECTORS:
4547 return selectG_MERGE_VALUES(
I);
4548 case TargetOpcode::G_UNMERGE_VALUES:
4549 return selectG_UNMERGE_VALUES(
I);
4550 case TargetOpcode::G_BUILD_VECTOR:
4551 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
4552 return selectG_BUILD_VECTOR(
I);
4553 case TargetOpcode::G_IMPLICIT_DEF:
4554 return selectG_IMPLICIT_DEF(
I);
4555 case TargetOpcode::G_INSERT:
4556 return selectG_INSERT(
I);
4557 case TargetOpcode::G_INTRINSIC:
4558 case TargetOpcode::G_INTRINSIC_CONVERGENT:
4559 return selectG_INTRINSIC(
I);
4560 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
4561 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
4562 return selectG_INTRINSIC_W_SIDE_EFFECTS(
I);
4563 case TargetOpcode::G_ICMP:
4564 case TargetOpcode::G_FCMP:
4565 if (selectG_ICMP_or_FCMP(
I))
4568 case TargetOpcode::G_LOAD:
4569 case TargetOpcode::G_ZEXTLOAD:
4570 case TargetOpcode::G_SEXTLOAD:
4571 case TargetOpcode::G_STORE:
4572 case TargetOpcode::G_ATOMIC_CMPXCHG:
4573 case TargetOpcode::G_ATOMICRMW_XCHG:
4574 case TargetOpcode::G_ATOMICRMW_ADD:
4575 case TargetOpcode::G_ATOMICRMW_SUB:
4576 case TargetOpcode::G_ATOMICRMW_AND:
4577 case TargetOpcode::G_ATOMICRMW_OR:
4578 case TargetOpcode::G_ATOMICRMW_XOR:
4579 case TargetOpcode::G_ATOMICRMW_MIN:
4580 case TargetOpcode::G_ATOMICRMW_MAX:
4581 case TargetOpcode::G_ATOMICRMW_UMIN:
4582 case TargetOpcode::G_ATOMICRMW_UMAX:
4583 case TargetOpcode::G_ATOMICRMW_UINC_WRAP:
4584 case TargetOpcode::G_ATOMICRMW_UDEC_WRAP:
4585 case TargetOpcode::G_ATOMICRMW_USUB_COND:
4586 case TargetOpcode::G_ATOMICRMW_USUB_SAT:
4587 case TargetOpcode::G_ATOMICRMW_FADD:
4588 case TargetOpcode::G_ATOMICRMW_FMIN:
4589 case TargetOpcode::G_ATOMICRMW_FMAX:
4590 return selectG_LOAD_STORE_ATOMICRMW(
I);
4591 case TargetOpcode::G_SELECT:
4592 return selectG_SELECT(
I);
4593 case TargetOpcode::G_TRUNC:
4594 return selectG_TRUNC(
I);
4595 case TargetOpcode::G_SEXT:
4596 case TargetOpcode::G_ZEXT:
4597 case TargetOpcode::G_ANYEXT:
4598 case TargetOpcode::G_SEXT_INREG:
4602 if (MRI->getType(
I.getOperand(1).getReg()) !=
LLT::scalar(1) &&
4605 return selectG_SZA_EXT(
I);
4606 case TargetOpcode::G_FPEXT:
4607 if (selectG_FPEXT(
I))
4610 case TargetOpcode::G_BRCOND:
4611 return selectG_BRCOND(
I);
4612 case TargetOpcode::G_GLOBAL_VALUE:
4613 return selectG_GLOBAL_VALUE(
I);
4614 case TargetOpcode::G_PTRMASK:
4615 return selectG_PTRMASK(
I);
4616 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4617 return selectG_EXTRACT_VECTOR_ELT(
I);
4618 case TargetOpcode::G_INSERT_VECTOR_ELT:
4619 return selectG_INSERT_VECTOR_ELT(
I);
4620 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD:
4621 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16:
4622 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET:
4623 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE:
4624 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16: {
4627 assert(Intr &&
"not an image intrinsic with image pseudo");
4628 return selectImageIntrinsic(
I, Intr);
4630 case AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY:
4631 case AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY:
4632 case AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY:
4633 return selectBVHIntersectRayIntrinsic(
I);
4634 case AMDGPU::G_SBFX:
4635 case AMDGPU::G_UBFX:
4636 return selectG_SBFX_UBFX(
I);
4637 case AMDGPU::G_SI_CALL:
4638 I.setDesc(TII.get(AMDGPU::SI_CALL));
4640 case AMDGPU::G_AMDGPU_WAVE_ADDRESS:
4641 return selectWaveAddress(
I);
4642 case AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_RETURN: {
4643 I.setDesc(TII.get(AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN));
4646 case AMDGPU::G_STACKRESTORE:
4647 return selectStackRestore(
I);
4649 return selectPHI(
I);
4650 case AMDGPU::G_AMDGPU_COPY_SCC_VCC:
4651 return selectCOPY_SCC_VCC(
I);
4652 case AMDGPU::G_AMDGPU_COPY_VCC_SCC:
4653 return selectCOPY_VCC_SCC(
I);
4654 case AMDGPU::G_AMDGPU_READANYLANE:
4655 return selectReadAnyLane(
I);
4656 case TargetOpcode::G_CONSTANT:
4657 case TargetOpcode::G_FCONSTANT:
4665AMDGPUInstructionSelector::selectVCSRC(
MachineOperand &Root)
const {
4672std::pair<Register, unsigned> AMDGPUInstructionSelector::selectVOP3ModsImpl(
4673 Register Src,
bool IsCanonicalizing,
bool AllowAbs,
bool OpSel)
const {
4677 if (
MI->getOpcode() == AMDGPU::G_FNEG) {
4678 Src =
MI->getOperand(1).getReg();
4681 }
else if (
MI->getOpcode() == AMDGPU::G_FSUB && IsCanonicalizing) {
4686 if (
LHS &&
LHS->isZero()) {
4688 Src =
MI->getOperand(2).getReg();
4692 if (AllowAbs &&
MI->getOpcode() == AMDGPU::G_FABS) {
4693 Src =
MI->getOperand(1).getReg();
4700 return std::pair(Src, Mods);
4703std::pair<Register, unsigned>
4704AMDGPUInstructionSelector::selectVOP3PModsF32Impl(
Register Src)
const {
4706 std::tie(Src, Mods) = selectVOP3ModsImpl(Src);
4708 return std::pair(Src, Mods);
4711Register AMDGPUInstructionSelector::copyToVGPRIfSrcFolded(
4713 bool ForceVGPR)
const {
4714 if ((Mods != 0 || ForceVGPR) &&
4715 RBI.getRegBank(Src, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID) {
4722 TII.
get(AMDGPU::COPY), VGPRSrc)
4734AMDGPUInstructionSelector::selectVSRC0(
MachineOperand &Root)
const {
4736 [=](MachineInstrBuilder &MIB) { MIB.
add(Root); }
4741AMDGPUInstructionSelector::selectVOP3Mods0(
MachineOperand &Root)
const {
4744 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
4747 [=](MachineInstrBuilder &MIB) {
4748 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4750 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
4751 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4752 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4757AMDGPUInstructionSelector::selectVOP3BMods0(
MachineOperand &Root)
const {
4760 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
4765 [=](MachineInstrBuilder &MIB) {
4766 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4768 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
4769 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4770 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4775AMDGPUInstructionSelector::selectVOP3OMods(
MachineOperand &Root)
const {
4777 [=](MachineInstrBuilder &MIB) { MIB.
add(Root); },
4778 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4779 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4784AMDGPUInstructionSelector::selectVOP3Mods(
MachineOperand &Root)
const {
4787 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
4790 [=](MachineInstrBuilder &MIB) {
4791 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4793 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4798AMDGPUInstructionSelector::selectVOP3ModsNonCanonicalizing(
4802 std::tie(Src, Mods) =
4803 selectVOP3ModsImpl(Root.
getReg(),
false);
4806 [=](MachineInstrBuilder &MIB) {
4807 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4809 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4814AMDGPUInstructionSelector::selectVOP3BMods(
MachineOperand &Root)
const {
4817 std::tie(Src, Mods) =
4818 selectVOP3ModsImpl(Root.
getReg(),
true,
4822 [=](MachineInstrBuilder &MIB) {
4823 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4825 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4830AMDGPUInstructionSelector::selectVOP3NoMods(
MachineOperand &Root)
const {
4833 if (
Def->getOpcode() == AMDGPU::G_FNEG ||
Def->getOpcode() == AMDGPU::G_FABS)
4836 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
4861 if (
MI->getOpcode() != AMDGPU::G_TRUNC)
4866 return DstSize * 2 == SrcSize;
4872 if (
MI->getOpcode() != AMDGPU::G_LSHR)
4876 std::optional<ValueAndVReg> ShiftAmt;
4877 if (
mi_match(
MI->getOperand(0).getReg(), MRI,
4880 unsigned Shift = ShiftAmt->Value.getZExtValue();
4881 return Shift * 2 == SrcSize;
4889 if (
MI->getOpcode() != AMDGPU::G_SHL)
4893 std::optional<ValueAndVReg> ShiftAmt;
4894 if (
mi_match(
MI->getOperand(0).getReg(), MRI,
4897 unsigned Shift = ShiftAmt->Value.getZExtValue();
4898 return Shift * 2 == SrcSize;
4906 if (
MI->getOpcode() != AMDGPU::G_UNMERGE_VALUES)
4908 return MI->getNumOperands() == 3 &&
MI->getOperand(0).isDef() &&
4909 MI->getOperand(1).isDef() && !
MI->getOperand(2).isDef();
4917 if (
OpTy.isScalar())
4919 if (
OpTy.isVector() &&
OpTy.getNumElements() == 2)
5079static std::optional<std::pair<Register, SrcStatus>>
5084 unsigned Opc =
MI->getOpcode();
5088 case AMDGPU::G_BITCAST:
5089 return std::optional<std::pair<Register, SrcStatus>>(
5090 {
MI->getOperand(1).getReg(), Curr.second});
5092 if (
MI->getOperand(1).getReg().isPhysical())
5093 return std::nullopt;
5094 return std::optional<std::pair<Register, SrcStatus>>(
5095 {
MI->getOperand(1).getReg(), Curr.second});
5096 case AMDGPU::G_FNEG: {
5099 return std::nullopt;
5100 return std::optional<std::pair<Register, SrcStatus>>(
5101 {
MI->getOperand(1).getReg(), Stat});
5108 switch (Curr.second) {
5111 return std::optional<std::pair<Register, SrcStatus>>(
5114 if (Curr.first ==
MI->getOperand(0).getReg())
5115 return std::optional<std::pair<Register, SrcStatus>>(
5117 return std::optional<std::pair<Register, SrcStatus>>(
5129 return std::optional<std::pair<Register, SrcStatus>>(
5133 if (Curr.first ==
MI->getOperand(0).getReg())
5134 return std::optional<std::pair<Register, SrcStatus>>(
5136 return std::optional<std::pair<Register, SrcStatus>>(
5142 return std::optional<std::pair<Register, SrcStatus>>(
5147 return std::optional<std::pair<Register, SrcStatus>>(
5152 return std::optional<std::pair<Register, SrcStatus>>(
5157 return std::optional<std::pair<Register, SrcStatus>>(
5163 return std::nullopt;
5173 bool HasNeg =
false;
5175 bool HasOpsel =
true;
5180 unsigned Opc =
MI->getOpcode();
5182 if (
Opc == TargetOpcode::G_INTRINSIC) {
5185 if (IntrinsicID == Intrinsic::amdgcn_fdot2)
5212 while (
Depth <= MaxDepth && Curr.has_value()) {
5215 Statlist.push_back(Curr.value());
5222static std::pair<Register, SrcStatus>
5229 while (
Depth <= MaxDepth && Curr.has_value()) {
5235 LastSameOrNeg = Curr.value();
5240 return LastSameOrNeg;
5247 return Width1 == Width2;
5282 return isSameBitWidth(NewReg, RootReg, MRI) && IsHalfState(LoStat) &&
5283 IsHalfState(HiStat);
5286std::pair<Register, unsigned> AMDGPUInstructionSelector::selectVOP3PModsImpl(
5292 return {RootReg, Mods};
5295 SearchOptions SO(RootReg, MRI);
5308 if (MRI.getType(RootReg).getSizeInBits() == 128) {
5310 return {Stat.first, Mods};
5315 MI->getNumOperands() != 3 || (IsDOT && Subtarget->hasDOTOpSelHazard())) {
5317 return {Stat.first, Mods};
5323 if (StatlistHi.
empty()) {
5325 return {Stat.first, Mods};
5331 if (StatlistLo.
empty()) {
5333 return {Stat.first, Mods};
5336 for (
int I = StatlistHi.
size() - 1;
I >= 0;
I--) {
5337 for (
int J = StatlistLo.
size() - 1; J >= 0; J--) {
5338 if (StatlistHi[
I].first == StatlistLo[J].first &&
5340 StatlistHi[
I].first, RootReg, TII, MRI))
5341 return {StatlistHi[
I].first,
5342 updateMods(StatlistHi[
I].second, StatlistLo[J].second, Mods)};
5348 return {Stat.first, Mods};
5358 return RB->
getID() == RBNo;
5374 if (
checkRB(RootReg, AMDGPU::SGPRRegBankID, RBI, MRI,
TRI) ||
5375 checkRB(NewReg, AMDGPU::VGPRRegBankID, RBI, MRI,
TRI))
5385 TII.get(AMDGPU::COPY), DstReg)
5393AMDGPUInstructionSelector::selectVOP3PRetHelper(
MachineOperand &Root,
5398 std::tie(
Reg, Mods) = selectVOP3PModsImpl(Root.
getReg(), MRI, IsDOT);
5403 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
5404 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5409AMDGPUInstructionSelector::selectVOP3PMods(
MachineOperand &Root)
const {
5411 return selectVOP3PRetHelper(Root);
5415AMDGPUInstructionSelector::selectVOP3PModsDOT(
MachineOperand &Root)
const {
5417 return selectVOP3PRetHelper(Root,
true);
5421AMDGPUInstructionSelector::selectVOP3PNoModsDOT(
MachineOperand &Root)
const {
5425 std::tie(Src, Mods) = selectVOP3PModsImpl(Root.
getReg(), MRI,
true );
5429 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); }}};
5433AMDGPUInstructionSelector::selectVOP3PModsF32(
MachineOperand &Root)
const {
5436 std::tie(Src, Mods) = selectVOP3PModsF32Impl(Root.
getReg());
5439 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5440 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5445AMDGPUInstructionSelector::selectVOP3PNoModsF32(
MachineOperand &Root)
const {
5448 std::tie(Src, Mods) = selectVOP3PModsF32Impl(Root.
getReg());
5452 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); }}};
5456AMDGPUInstructionSelector::selectWMMAOpSelVOP3PMods(
5459 "expected i1 value");
5465 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5473 switch (Elts.
size()) {
5475 DstRegClass = &AMDGPU::VReg_256RegClass;
5478 DstRegClass = &AMDGPU::VReg_128RegClass;
5481 DstRegClass = &AMDGPU::VReg_64RegClass;
5488 auto MIB =
B.buildInstr(AMDGPU::REG_SEQUENCE)
5490 for (
unsigned i = 0; i < Elts.
size(); ++i) {
5501 if (ModOpcode == TargetOpcode::G_FNEG) {
5505 for (
auto El : Elts) {
5511 if (Elts.size() != NegAbsElts.
size()) {
5520 assert(ModOpcode == TargetOpcode::G_FABS);
5528AMDGPUInstructionSelector::selectWMMAModsF32NegAbs(
MachineOperand &Root)
const {
5537 MachineInstr *ElF32 = MRI->getVRegDef(BV->
getSourceReg(0));
5538 unsigned ModOpcode = (ElF32->
getOpcode() == AMDGPU::G_FNEG)
5555 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5556 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5560AMDGPUInstructionSelector::selectWMMAModsF16Neg(
MachineOperand &Root)
const {
5582 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5583 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5587AMDGPUInstructionSelector::selectWMMAModsF16NegAbs(
MachineOperand &Root)
const {
5595 MachineInstr *ElV2F16 = MRI->getVRegDef(CV->
getSourceReg(0));
5597 unsigned ModOpcode = (ElV2F16->
getOpcode() == AMDGPU::G_FNEG)
5616 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5617 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5621AMDGPUInstructionSelector::selectWMMAVISrc(
MachineOperand &Root)
const {
5622 std::optional<FPValueAndVReg> FPValReg;
5624 if (TII.isInlineConstant(FPValReg->Value)) {
5625 return {{[=](MachineInstrBuilder &MIB) {
5626 MIB.
addImm(FPValReg->Value.bitcastToAPInt().getSExtValue());
5636 if (TII.isInlineConstant(ICst)) {
5646AMDGPUInstructionSelector::selectSWMMACIndex8(
MachineOperand &Root)
const {
5652 std::optional<ValueAndVReg> ShiftAmt;
5654 MRI->getType(ShiftSrc).getSizeInBits() == 32 &&
5655 ShiftAmt->Value.getZExtValue() % 8 == 0) {
5656 Key = ShiftAmt->Value.getZExtValue() / 8;
5661 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5662 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5667AMDGPUInstructionSelector::selectSWMMACIndex16(
MachineOperand &Root)
const {
5674 std::optional<ValueAndVReg> ShiftAmt;
5676 MRI->getType(ShiftSrc).getSizeInBits() == 32 &&
5677 ShiftAmt->Value.getZExtValue() == 16) {
5683 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5684 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5689AMDGPUInstructionSelector::selectSWMMACIndex32(
MachineOperand &Root)
const {
5696 S32 = matchAnyExtendFromS32(Src);
5700 if (
Def->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) {
5705 Src =
Def->getOperand(2).getReg();
5712 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5713 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5718AMDGPUInstructionSelector::selectVOP3OpSelMods(
MachineOperand &Root)
const {
5721 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
5725 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5726 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5732AMDGPUInstructionSelector::selectVINTERPMods(
MachineOperand &Root)
const {
5735 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
5741 [=](MachineInstrBuilder &MIB) {
5743 copyToVGPRIfSrcFolded(Src, Mods, Root, MIB,
true));
5745 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
5750AMDGPUInstructionSelector::selectVINTERPModsHi(
MachineOperand &Root)
const {
5753 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
5759 [=](MachineInstrBuilder &MIB) {
5761 copyToVGPRIfSrcFolded(Src, Mods, Root, MIB,
true));
5763 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
5770bool AMDGPUInstructionSelector::selectScaleOffset(
MachineOperand &Root,
5772 bool IsSigned)
const {
5773 if (!Subtarget->hasScaleOffset())
5777 MachineMemOperand *MMO = *
MI.memoperands_begin();
5789 OffsetReg =
Def->Reg;
5804 m_BinOp(IsSigned ? AMDGPU::S_MUL_I64_I32_PSEUDO : AMDGPU::S_MUL_U64,
5808 (
Mul->getOpcode() == (IsSigned ? AMDGPU::G_AMDGPU_MAD_I64_I32
5809 : AMDGPU::G_AMDGPU_MAD_U64_U32) ||
5810 (IsSigned &&
Mul->getOpcode() == AMDGPU::G_AMDGPU_MAD_U64_U32 &&
5811 VT->signBitIsZero(
Mul->getOperand(2).getReg()))) &&
5824bool AMDGPUInstructionSelector::selectSmrdOffset(
MachineOperand &Root,
5828 bool *ScaleOffset)
const {
5835 getAddrModeInfo(*
MI, *MRI, AddrInfo);
5837 if (AddrInfo.
empty())
5840 const GEPInfo &GEPI = AddrInfo[0];
5841 std::optional<int64_t> EncodedImm;
5844 *ScaleOffset =
false;
5849 if (GEPI.SgprParts.size() == 1 && GEPI.Imm != 0 && EncodedImm &&
5850 AddrInfo.
size() > 1) {
5851 const GEPInfo &GEPI2 = AddrInfo[1];
5852 if (GEPI2.SgprParts.size() == 2 && GEPI2.Imm == 0) {
5853 Register OffsetReg = GEPI2.SgprParts[1];
5856 selectScaleOffset(Root, OffsetReg,
false );
5857 OffsetReg = matchZeroExtendFromS32OrS32(OffsetReg);
5859 Base = GEPI2.SgprParts[0];
5860 *SOffset = OffsetReg;
5869 auto SKnown =
VT->getKnownBits(*SOffset);
5870 if (*
Offset + SKnown.getMinValue().getSExtValue() < 0)
5882 if (
Offset && GEPI.SgprParts.size() == 1 && EncodedImm) {
5883 Base = GEPI.SgprParts[0];
5889 if (SOffset && GEPI.SgprParts.size() == 1 &&
isUInt<32>(GEPI.Imm) &&
5895 Base = GEPI.SgprParts[0];
5896 *SOffset = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
5897 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), *SOffset)
5902 if (SOffset && GEPI.SgprParts.size() && GEPI.Imm == 0) {
5903 Register OffsetReg = GEPI.SgprParts[1];
5905 *ScaleOffset = selectScaleOffset(Root, OffsetReg,
false );
5906 OffsetReg = matchZeroExtendFromS32OrS32(OffsetReg);
5908 Base = GEPI.SgprParts[0];
5909 *SOffset = OffsetReg;
5918AMDGPUInstructionSelector::selectSmrdImm(
MachineOperand &Root)
const {
5921 if (!selectSmrdOffset(Root,
Base,
nullptr, &
Offset,
5923 return std::nullopt;
5925 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
5926 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Offset); }}};
5930AMDGPUInstructionSelector::selectSmrdImm32(
MachineOperand &Root)
const {
5932 getAddrModeInfo(*Root.
getParent(), *MRI, AddrInfo);
5934 if (AddrInfo.
empty() || AddrInfo[0].SgprParts.size() != 1)
5935 return std::nullopt;
5937 const GEPInfo &GEPInfo = AddrInfo[0];
5938 Register PtrReg = GEPInfo.SgprParts[0];
5939 std::optional<int64_t> EncodedImm =
5942 return std::nullopt;
5945 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrReg); },
5946 [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); }
5951AMDGPUInstructionSelector::selectSmrdSgpr(
MachineOperand &Root)
const {
5954 if (!selectSmrdOffset(Root,
Base, &SOffset,
nullptr,
5956 return std::nullopt;
5959 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
5960 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
5961 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }}};
5965AMDGPUInstructionSelector::selectSmrdSgprImm(
MachineOperand &Root)
const {
5969 if (!selectSmrdOffset(Root,
Base, &SOffset, &
Offset, &ScaleOffset))
5970 return std::nullopt;
5973 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
5974 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
5976 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }}};
5979std::pair<Register, int> AMDGPUInstructionSelector::selectFlatOffsetImpl(
5985 if (!STI.hasFlatInstOffsets())
5989 int64_t ConstOffset;
5991 std::tie(PtrBase, ConstOffset, IsInBounds) =
5992 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
5998 if (ConstOffset == 0 ||
6000 !isFlatScratchBaseLegal(Root.
getReg())) ||
6004 unsigned AddrSpace = (*
MI->memoperands_begin())->getAddrSpace();
6005 if (!TII.isLegalFLATOffset(ConstOffset, AddrSpace, FlatVariant))
6008 return std::pair(PtrBase, ConstOffset);
6012AMDGPUInstructionSelector::selectFlatOffset(
MachineOperand &Root)
const {
6016 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6017 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6022AMDGPUInstructionSelector::selectGlobalOffset(
MachineOperand &Root)
const {
6023 auto PtrWithOffset =
6027 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6028 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6033AMDGPUInstructionSelector::selectScratchOffset(
MachineOperand &Root)
const {
6034 auto PtrWithOffset =
6038 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6039 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6045AMDGPUInstructionSelector::selectGlobalSAddr(
MachineOperand &Root,
6047 bool NeedIOffset)
const {
6050 int64_t ConstOffset;
6051 int64_t ImmOffset = 0;
6055 std::tie(PtrBase, ConstOffset, std::ignore) =
6056 getPtrBaseWithConstantOffset(Addr, *MRI);
6058 if (ConstOffset != 0) {
6063 ImmOffset = ConstOffset;
6066 if (isSGPR(PtrBaseDef->Reg)) {
6067 if (ConstOffset > 0) {
6073 int64_t SplitImmOffset = 0, RemainderOffset = ConstOffset;
6075 std::tie(SplitImmOffset, RemainderOffset) =
6080 if (Subtarget->hasSignedGVSOffset() ?
isInt<32>(RemainderOffset)
6085 MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6087 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32),
6089 .
addImm(RemainderOffset);
6093 [=](MachineInstrBuilder &MIB) {
6096 [=](MachineInstrBuilder &MIB) {
6099 [=](MachineInstrBuilder &MIB) { MIB.
addImm(SplitImmOffset); },
6100 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); },
6103 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrBase); },
6104 [=](MachineInstrBuilder &MIB) {
6107 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); },
6117 unsigned NumLiterals =
6118 !TII.isInlineConstant(APInt(32,
Lo_32(ConstOffset))) +
6119 !TII.isInlineConstant(APInt(32,
Hi_32(ConstOffset)));
6120 if (STI.getConstantBusLimit(AMDGPU::V_ADD_U32_e64) > NumLiterals)
6121 return std::nullopt;
6128 if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
6133 if (isSGPR(SAddr)) {
6134 Register PtrBaseOffset = AddrDef->MI->getOperand(2).getReg();
6138 bool ScaleOffset = selectScaleOffset(Root, PtrBaseOffset,
6139 Subtarget->hasSignedGVSOffset());
6140 if (
Register VOffset = matchExtendFromS32OrS32(
6141 PtrBaseOffset, Subtarget->hasSignedGVSOffset())) {
6143 return {{[=](MachineInstrBuilder &MIB) {
6146 [=](MachineInstrBuilder &MIB) {
6149 [=](MachineInstrBuilder &MIB) {
6152 [=](MachineInstrBuilder &MIB) {
6156 return {{[=](MachineInstrBuilder &MIB) {
6159 [=](MachineInstrBuilder &MIB) {
6162 [=](MachineInstrBuilder &MIB) {
6172 if (AddrDef->MI->getOpcode() == AMDGPU::G_IMPLICIT_DEF ||
6173 AddrDef->MI->getOpcode() == AMDGPU::G_CONSTANT || !isSGPR(AddrDef->Reg))
6174 return std::nullopt;
6180 Register VOffset = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6182 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32), VOffset)
6187 [=](MachineInstrBuilder &MIB) { MIB.
addReg(AddrDef->Reg); },
6188 [=](MachineInstrBuilder &MIB) { MIB.
addReg(VOffset); },
6189 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6190 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); }
6193 [=](MachineInstrBuilder &MIB) { MIB.
addReg(AddrDef->Reg); },
6194 [=](MachineInstrBuilder &MIB) { MIB.
addReg(VOffset); },
6195 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); }
6200AMDGPUInstructionSelector::selectGlobalSAddr(
MachineOperand &Root)
const {
6201 return selectGlobalSAddr(Root, 0);
6205AMDGPUInstructionSelector::selectGlobalSAddrCPol(
MachineOperand &Root)
const {
6211 return selectGlobalSAddr(Root, PassedCPol);
6215AMDGPUInstructionSelector::selectGlobalSAddrCPolM0(
MachineOperand &Root)
const {
6221 return selectGlobalSAddr(Root, PassedCPol);
6225AMDGPUInstructionSelector::selectGlobalSAddrGLC(
MachineOperand &Root)
const {
6230AMDGPUInstructionSelector::selectGlobalSAddrNoIOffset(
6237 return selectGlobalSAddr(Root, PassedCPol,
false);
6241AMDGPUInstructionSelector::selectGlobalSAddrNoIOffsetM0(
6248 return selectGlobalSAddr(Root, PassedCPol,
false);
6252AMDGPUInstructionSelector::selectScratchSAddr(
MachineOperand &Root)
const {
6255 int64_t ConstOffset;
6256 int64_t ImmOffset = 0;
6260 std::tie(PtrBase, ConstOffset, std::ignore) =
6261 getPtrBaseWithConstantOffset(Addr, *MRI);
6263 if (ConstOffset != 0 && isFlatScratchBaseLegal(Addr) &&
6267 ImmOffset = ConstOffset;
6271 if (AddrDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX) {
6272 int FI = AddrDef->MI->getOperand(1).
getIndex();
6275 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); }
6281 if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
6282 Register LHS = AddrDef->MI->getOperand(1).getReg();
6283 Register RHS = AddrDef->MI->getOperand(2).getReg();
6287 if (LHSDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX &&
6288 isSGPR(RHSDef->Reg)) {
6289 int FI = LHSDef->MI->getOperand(1).getIndex();
6293 SAddr = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
6295 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_ADD_I32), SAddr)
6303 return std::nullopt;
6306 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SAddr); },
6307 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); }
6312bool AMDGPUInstructionSelector::checkFlatScratchSVSSwizzleBug(
6314 if (!Subtarget->hasFlatScratchSVSSwizzleBug())
6320 auto VKnown =
VT->getKnownBits(VAddr);
6323 uint64_t VMax = VKnown.getMaxValue().getZExtValue();
6325 return (VMax & 3) + (
SMax & 3) >= 4;
6329AMDGPUInstructionSelector::selectScratchSVAddr(
MachineOperand &Root)
const {
6332 int64_t ConstOffset;
6333 int64_t ImmOffset = 0;
6337 std::tie(PtrBase, ConstOffset, std::ignore) =
6338 getPtrBaseWithConstantOffset(Addr, *MRI);
6341 if (ConstOffset != 0 &&
6345 ImmOffset = ConstOffset;
6349 if (AddrDef->MI->getOpcode() != AMDGPU::G_PTR_ADD)
6350 return std::nullopt;
6352 Register RHS = AddrDef->MI->getOperand(2).getReg();
6353 if (RBI.getRegBank(
RHS, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID)
6354 return std::nullopt;
6356 Register LHS = AddrDef->MI->getOperand(1).getReg();
6359 if (OrigAddr != Addr) {
6360 if (!isFlatScratchBaseLegalSVImm(OrigAddr))
6361 return std::nullopt;
6363 if (!isFlatScratchBaseLegalSV(OrigAddr))
6364 return std::nullopt;
6367 if (checkFlatScratchSVSSwizzleBug(
RHS,
LHS, ImmOffset))
6368 return std::nullopt;
6370 unsigned CPol = selectScaleOffset(Root,
RHS,
true )
6374 if (LHSDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX) {
6375 int FI = LHSDef->MI->getOperand(1).getIndex();
6377 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
RHS); },
6379 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6380 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }
6389 return std::nullopt;
6392 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
RHS); },
6393 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
LHS); },
6394 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6395 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }
6400AMDGPUInstructionSelector::selectMUBUFScratchOffen(
MachineOperand &Root)
const {
6404 const SIMachineFunctionInfo *
Info =
MF->getInfo<SIMachineFunctionInfo>();
6409 Register HighBits = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6414 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32),
6418 return {{[=](MachineInstrBuilder &MIB) {
6421 [=](MachineInstrBuilder &MIB) {
6424 [=](MachineInstrBuilder &MIB) {
6429 [=](MachineInstrBuilder &MIB) {
6438 std::optional<int> FI;
6442 int64_t ConstOffset;
6443 std::tie(PtrBase, ConstOffset, std::ignore) =
6444 getPtrBaseWithConstantOffset(VAddr, *MRI);
6446 if (ConstOffset != 0) {
6447 if (TII.isLegalMUBUFImmOffset(ConstOffset) &&
6448 (!STI.privateMemoryResourceIsRangeChecked() ||
6449 VT->signBitIsZero(PtrBase))) {
6460 return {{[=](MachineInstrBuilder &MIB) {
6463 [=](MachineInstrBuilder &MIB) {
6469 [=](MachineInstrBuilder &MIB) {
6474 [=](MachineInstrBuilder &MIB) {
6479bool AMDGPUInstructionSelector::isDSOffsetLegal(
Register Base,
6484 if (STI.hasUsableDSOffset() || STI.unsafeDSOffsetFoldingEnabled())
6489 return VT->signBitIsZero(
Base);
6492bool AMDGPUInstructionSelector::isDSOffset2Legal(
Register Base, int64_t Offset0,
6494 unsigned Size)
const {
6495 if (Offset0 %
Size != 0 || Offset1 %
Size != 0)
6500 if (STI.hasUsableDSOffset() || STI.unsafeDSOffsetFoldingEnabled())
6505 return VT->signBitIsZero(
Base);
6510 return Addr->
getOpcode() == TargetOpcode::G_OR ||
6511 (Addr->
getOpcode() == TargetOpcode::G_PTR_ADD &&
6518bool AMDGPUInstructionSelector::isFlatScratchBaseLegal(
Register Addr)
const {
6526 if (STI.hasSignedScratchOffsets())
6532 if (AddrMI->
getOpcode() == TargetOpcode::G_PTR_ADD) {
6533 std::optional<ValueAndVReg> RhsValReg =
6539 if (RhsValReg && RhsValReg->Value.getSExtValue() < 0 &&
6540 RhsValReg->Value.getSExtValue() > -0x40000000)
6544 return VT->signBitIsZero(
LHS);
6549bool AMDGPUInstructionSelector::isFlatScratchBaseLegalSV(
Register Addr)
const {
6557 if (STI.hasSignedScratchOffsets())
6562 return VT->signBitIsZero(
RHS) &&
VT->signBitIsZero(
LHS);
6567bool AMDGPUInstructionSelector::isFlatScratchBaseLegalSVImm(
6571 if (STI.hasSignedScratchOffsets())
6576 std::optional<DefinitionAndSourceRegister> BaseDef =
6578 std::optional<ValueAndVReg> RHSOffset =
6588 (RHSOffset->Value.getSExtValue() < 0 &&
6589 RHSOffset->Value.getSExtValue() > -0x40000000)))
6592 Register LHS = BaseDef->MI->getOperand(1).getReg();
6593 Register RHS = BaseDef->MI->getOperand(2).getReg();
6594 return VT->signBitIsZero(
RHS) &&
VT->signBitIsZero(
LHS);
6597bool AMDGPUInstructionSelector::isUnneededShiftMask(
const MachineInstr &
MI,
6598 unsigned ShAmtBits)
const {
6599 assert(
MI.getOpcode() == TargetOpcode::G_AND);
6601 std::optional<APInt>
RHS =
6606 if (
RHS->countr_one() >= ShAmtBits)
6609 const APInt &LHSKnownZeros =
VT->getKnownZeroes(
MI.getOperand(1).getReg());
6610 return (LHSKnownZeros | *
RHS).countr_one() >= ShAmtBits;
6614AMDGPUInstructionSelector::selectMUBUFScratchOffset(
6617 const SIMachineFunctionInfo *
Info =
MF->getInfo<SIMachineFunctionInfo>();
6619 std::optional<DefinitionAndSourceRegister>
Def =
6621 assert(Def &&
"this shouldn't be an optional result");
6626 [=](MachineInstrBuilder &MIB) {
6629 [=](MachineInstrBuilder &MIB) {
6632 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
6643 if (!TII.isLegalMUBUFImmOffset(
Offset))
6651 [=](MachineInstrBuilder &MIB) {
6654 [=](MachineInstrBuilder &MIB) {
6662 !TII.isLegalMUBUFImmOffset(
Offset))
6666 [=](MachineInstrBuilder &MIB) {
6669 [=](MachineInstrBuilder &MIB) {
6676std::pair<Register, unsigned>
6677AMDGPUInstructionSelector::selectDS1Addr1OffsetImpl(
6679 int64_t ConstAddr = 0;
6683 std::tie(PtrBase,
Offset, std::ignore) =
6684 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
6687 if (isDSOffsetLegal(PtrBase,
Offset)) {
6689 return std::pair(PtrBase,
Offset);
6698 return std::pair(Root.
getReg(), 0);
6702AMDGPUInstructionSelector::selectDS1Addr1Offset(
MachineOperand &Root)
const {
6705 std::tie(
Reg,
Offset) = selectDS1Addr1OffsetImpl(Root);
6707 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
6713AMDGPUInstructionSelector::selectDS64Bit4ByteAligned(
MachineOperand &Root)
const {
6714 return selectDSReadWrite2(Root, 4);
6718AMDGPUInstructionSelector::selectDS128Bit8ByteAligned(
MachineOperand &Root)
const {
6719 return selectDSReadWrite2(Root, 8);
6723AMDGPUInstructionSelector::selectDSReadWrite2(
MachineOperand &Root,
6724 unsigned Size)
const {
6729 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
6731 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Offset+1); }
6735std::pair<Register, unsigned>
6736AMDGPUInstructionSelector::selectDSReadWrite2Impl(
MachineOperand &Root,
6737 unsigned Size)
const {
6738 int64_t ConstAddr = 0;
6742 std::tie(PtrBase,
Offset, std::ignore) =
6743 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
6746 int64_t OffsetValue0 =
Offset;
6748 if (isDSOffset2Legal(PtrBase, OffsetValue0, OffsetValue1,
Size)) {
6750 return std::pair(PtrBase, OffsetValue0 /
Size);
6759 return std::pair(Root.
getReg(), 0);
6767std::tuple<Register, int64_t, bool>
6768AMDGPUInstructionSelector::getPtrBaseWithConstantOffset(
6771 if (RootI->
getOpcode() != TargetOpcode::G_PTR_ADD)
6772 return {Root, 0,
false};
6775 std::optional<ValueAndVReg> MaybeOffset =
6778 return {Root, 0,
false};
6798 B.buildInstr(AMDGPU::S_MOV_B32)
6801 B.buildInstr(AMDGPU::S_MOV_B32)
6808 B.buildInstr(AMDGPU::REG_SEQUENCE)
6811 .addImm(AMDGPU::sub0)
6813 .addImm(AMDGPU::sub1);
6818 B.buildInstr(AMDGPU::S_MOV_B64)
6823 B.buildInstr(AMDGPU::REG_SEQUENCE)
6826 .addImm(AMDGPU::sub0_sub1)
6828 .addImm(AMDGPU::sub2_sub3);
6835 uint64_t DefaultFormat =
TII.getDefaultRsrcDataFormat();
6844 uint64_t DefaultFormat =
TII.getDefaultRsrcDataFormat();
6851AMDGPUInstructionSelector::MUBUFAddressData
6852AMDGPUInstructionSelector::parseMUBUFAddress(
Register Src)
const {
6853 MUBUFAddressData
Data;
6859 std::tie(PtrBase,
Offset, std::ignore) =
6860 getPtrBaseWithConstantOffset(Src, *MRI);
6866 if (MachineInstr *InputAdd
6868 Data.N2 = InputAdd->getOperand(1).getReg();
6869 Data.N3 = InputAdd->getOperand(2).getReg();
6884bool AMDGPUInstructionSelector::shouldUseAddr64(MUBUFAddressData Addr)
const {
6890 const RegisterBank *N0Bank = RBI.getRegBank(Addr.N0, *MRI, TRI);
6891 return N0Bank->
getID() == AMDGPU::VGPRRegBankID;
6897void AMDGPUInstructionSelector::splitIllegalMUBUFOffset(
6899 if (TII.isLegalMUBUFImmOffset(ImmOffset))
6903 SOffset = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
6904 B.buildInstr(AMDGPU::S_MOV_B32)
6910bool AMDGPUInstructionSelector::selectMUBUFAddr64Impl(
6915 if (!STI.hasAddr64() || STI.useFlatForGlobal())
6918 MUBUFAddressData AddrData = parseMUBUFAddress(Root.
getReg());
6919 if (!shouldUseAddr64(AddrData))
6925 Offset = AddrData.Offset;
6931 if (RBI.getRegBank(N2, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
6933 if (RBI.getRegBank(N3, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
6946 }
else if (RBI.getRegBank(N0, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
6957 splitIllegalMUBUFOffset(
B, SOffset,
Offset);
6961bool AMDGPUInstructionSelector::selectMUBUFOffsetImpl(
6966 if (STI.useFlatForGlobal())
6969 MUBUFAddressData AddrData = parseMUBUFAddress(Root.
getReg());
6970 if (shouldUseAddr64(AddrData))
6976 Offset = AddrData.Offset;
6982 splitIllegalMUBUFOffset(
B, SOffset,
Offset);
6987AMDGPUInstructionSelector::selectMUBUFAddr64(
MachineOperand &Root)
const {
6993 if (!selectMUBUFAddr64Impl(Root, VAddr, RSrcReg, SOffset,
Offset))
6999 [=](MachineInstrBuilder &MIB) {
7002 [=](MachineInstrBuilder &MIB) {
7005 [=](MachineInstrBuilder &MIB) {
7008 else if (STI.hasRestrictedSOffset())
7009 MIB.
addReg(AMDGPU::SGPR_NULL);
7013 [=](MachineInstrBuilder &MIB) {
7023AMDGPUInstructionSelector::selectMUBUFOffset(
MachineOperand &Root)
const {
7028 if (!selectMUBUFOffsetImpl(Root, RSrcReg, SOffset,
Offset))
7032 [=](MachineInstrBuilder &MIB) {
7035 [=](MachineInstrBuilder &MIB) {
7038 else if (STI.hasRestrictedSOffset())
7039 MIB.
addReg(AMDGPU::SGPR_NULL);
7051AMDGPUInstructionSelector::selectBUFSOffset(
MachineOperand &Root)
const {
7056 SOffset = AMDGPU::SGPR_NULL;
7058 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); }}};
7062static std::optional<uint64_t>
7066 if (!OffsetVal || !
isInt<32>(*OffsetVal))
7067 return std::nullopt;
7068 return Lo_32(*OffsetVal);
7072AMDGPUInstructionSelector::selectSMRDBufferImm(
MachineOperand &Root)
const {
7073 std::optional<uint64_t> OffsetVal =
7078 std::optional<int64_t> EncodedImm =
7083 return {{ [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); } }};
7087AMDGPUInstructionSelector::selectSMRDBufferImm32(
MachineOperand &Root)
const {
7094 std::optional<int64_t> EncodedImm =
7099 return {{ [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); } }};
7103AMDGPUInstructionSelector::selectSMRDBufferSgprImm(
MachineOperand &Root)
const {
7111 return std::nullopt;
7113 std::optional<int64_t> EncodedOffset =
7116 return std::nullopt;
7118 assert(MRI->getType(SOffset).getSizeInBits() == 32);
7119 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
7120 [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedOffset); }}};
7123std::pair<Register, unsigned>
7124AMDGPUInstructionSelector::selectVOP3PMadMixModsImpl(
MachineOperand &Root,
7125 bool &Matched)
const {
7130 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
7140 const auto CheckAbsNeg = [&]() {
7145 std::tie(Src, ModsTmp) = selectVOP3ModsImpl(Src);
7176AMDGPUInstructionSelector::selectVOP3PMadMixModsExt(
7181 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7186 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
7187 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
7192AMDGPUInstructionSelector::selectVOP3PMadMixMods(
MachineOperand &Root)
const {
7196 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7199 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
7200 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
7205AMDGPUInstructionSelector::selectVOP3PMadMixModsExtNeg(
7210 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7215 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
7216 [=](MachineInstrBuilder &MIB) {
7223AMDGPUInstructionSelector::selectVOP3PMadMixModsNeg(
7228 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7231 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
7232 [=](MachineInstrBuilder &MIB) {
7238bool AMDGPUInstructionSelector::selectSBarrierSignalIsfirst(
7242 Register CCReg =
I.getOperand(0).getReg();
7247 BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM))
7248 .
addImm(
I.getOperand(2).getImm());
7252 I.eraseFromParent();
7253 return RBI.constrainGenericRegister(CCReg, AMDGPU::SReg_32_XM0_XEXECRegClass,
7257bool AMDGPUInstructionSelector::selectSGetBarrierState(
7261 const MachineOperand &BarOp =
I.getOperand(2);
7262 std::optional<int64_t> BarValImm =
7266 auto CopyMIB =
BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
7270 MachineInstrBuilder MIB;
7271 unsigned Opc = BarValImm ? AMDGPU::S_GET_BARRIER_STATE_IMM
7272 : AMDGPU::S_GET_BARRIER_STATE_M0;
7275 auto DstReg =
I.getOperand(0).getReg();
7277 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
7278 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
7284 I.eraseFromParent();
7289 if (HasInlineConst) {
7293 case Intrinsic::amdgcn_s_barrier_join:
7294 return AMDGPU::S_BARRIER_JOIN_IMM;
7295 case Intrinsic::amdgcn_s_wakeup_barrier:
7296 return AMDGPU::S_WAKEUP_BARRIER_IMM;
7297 case Intrinsic::amdgcn_s_get_named_barrier_state:
7298 return AMDGPU::S_GET_BARRIER_STATE_IMM;
7304 case Intrinsic::amdgcn_s_barrier_join:
7305 return AMDGPU::S_BARRIER_JOIN_M0;
7306 case Intrinsic::amdgcn_s_wakeup_barrier:
7307 return AMDGPU::S_WAKEUP_BARRIER_M0;
7308 case Intrinsic::amdgcn_s_get_named_barrier_state:
7309 return AMDGPU::S_GET_BARRIER_STATE_M0;
7314bool AMDGPUInstructionSelector::selectNamedBarrierInit(
7318 const MachineOperand &BarOp =
I.getOperand(1);
7319 const MachineOperand &CntOp =
I.getOperand(2);
7323 if (IntrID == Intrinsic::amdgcn_s_barrier_signal_var) {
7324 std::optional<int64_t> CntImm =
7326 if (CntImm && *CntImm == 0) {
7327 std::optional<int64_t> BarValImm =
7330 auto BarID = ((*BarValImm) >> 4) & 0x3F;
7331 BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::S_BARRIER_SIGNAL_IMM))
7333 I.eraseFromParent();
7340 Register TmpReg0 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7346 Register TmpReg1 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7353 Register TmpReg2 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7359 Register TmpReg3 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7360 constexpr unsigned ShAmt = 16;
7366 Register TmpReg4 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7376 unsigned Opc = IntrID == Intrinsic::amdgcn_s_barrier_init
7377 ? AMDGPU::S_BARRIER_INIT_M0
7378 : AMDGPU::S_BARRIER_SIGNAL_M0;
7379 MachineInstrBuilder MIB;
7382 I.eraseFromParent();
7386bool AMDGPUInstructionSelector::selectNamedBarrierInst(
7390 MachineOperand BarOp = IntrID == Intrinsic::amdgcn_s_get_named_barrier_state
7393 std::optional<int64_t> BarValImm =
7398 Register TmpReg0 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7404 Register TmpReg1 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7410 auto CopyMIB =
BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
7415 MachineInstrBuilder MIB;
7419 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state) {
7420 auto DstReg =
I.getOperand(0).getReg();
7422 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
7423 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
7429 auto BarId = ((*BarValImm) >> 4) & 0x3F;
7433 I.eraseFromParent();
7440 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
7441 "Expected G_CONSTANT");
7442 MIB.
addImm(
MI.getOperand(1).getCImm()->getSExtValue());
7448 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
7449 "Expected G_CONSTANT");
7450 MIB.
addImm(-
MI.getOperand(1).getCImm()->getSExtValue());
7456 const MachineOperand &
Op =
MI.getOperand(1);
7457 assert(
MI.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1);
7458 MIB.
addImm(
Op.getFPImm()->getValueAPF().bitcastToAPInt().getZExtValue());
7461void AMDGPUInstructionSelector::renderCountTrailingOnesImm(
7463 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
7464 "Expected G_CONSTANT");
7465 MIB.
addImm(
MI.getOperand(1).getCImm()->getValue().countTrailingOnes());
7473 const MachineOperand &
Op =
MI.getOperand(OpIdx);
7484 MIB.
addImm(
MI.getOperand(OpIdx).getImm() != 0);
7490 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7494void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_0_0(
7496 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7501void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_0_1(
7503 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7504 MIB.
addImm((
MI.getOperand(OpIdx).getImm() & 0x1)
7509void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_1_0(
7511 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7516void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_1_1(
7518 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7519 MIB.
addImm((
MI.getOperand(OpIdx).getImm() & 0x2)
7524void AMDGPUInstructionSelector::renderDstSelToOpSelXForm(
7526 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7531void AMDGPUInstructionSelector::renderSrcSelToOpSelXForm(
7533 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7538void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_2_0(
7540 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7545void AMDGPUInstructionSelector::renderDstSelToOpSel3XFormXForm(
7547 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7548 MIB.
addImm((
MI.getOperand(OpIdx).getImm() & 0x2)
7556 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7557 MIB.
addImm(
MI.getOperand(OpIdx).getImm() &
7565 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7566 const bool Swizzle =
MI.getOperand(OpIdx).getImm() &
7572void AMDGPUInstructionSelector::renderExtractCpolSetGLC(
7574 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7575 const uint32_t Cpol =
MI.getOperand(OpIdx).getImm() &
7584 const APFloat &APF =
MI.getOperand(1).getFPImm()->getValueAPF();
7586 assert(ExpVal != INT_MIN);
7597 MIB.
addImm((
MI.getOperand(OpIdx).getImm() + 3) % 4);
7604 if (
MI.getOperand(OpIdx).getImm())
7606 MIB.
addImm((int64_t)Mods);
7613 if (
MI.getOperand(OpIdx).getImm())
7615 MIB.
addImm((int64_t)Mods);
7621 unsigned Val =
MI.getOperand(OpIdx).getImm();
7629 MIB.
addImm((int64_t)Mods);
7635 uint32_t
V =
MI.getOperand(2).getImm();
7638 if (!Subtarget->hasSafeCUPrefetch())
7644void AMDGPUInstructionSelector::renderScaledMAIIntrinsicOperand(
7646 unsigned Val =
MI.getOperand(OpIdx).getImm();
7655bool AMDGPUInstructionSelector::isInlineImmediate(
const APInt &
Imm)
const {
7656 return TII.isInlineConstant(
Imm);
7659bool AMDGPUInstructionSelector::isInlineImmediate(
const APFloat &
Imm)
const {
7660 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 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)
int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding, unsigned VDataDwords, unsigned VAddrDwords)
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)
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.