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);
884 ArrayRef<int16_t> SubRegs = TRI.getRegSplitParts(SrcRC, DstSize / 8);
885 for (
int I = 0,
E = NumDst;
I !=
E; ++
I) {
888 if (SrcBank->
getID() == AMDGPU::SGPRRegBankID &&
889 SubRegs[
I] == AMDGPU::hi16) {
890 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_LSHR_B32), DstReg)
894 BuildMI(*BB, &
MI,
DL, TII.get(TargetOpcode::COPY), DstReg)
895 .
addReg(SrcReg, {}, SubRegs[
I]);
898 SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubRegs[
I]);
901 if (!SrcRC || !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI))
905 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
906 if (DstRC && !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
910 MI.eraseFromParent();
914bool AMDGPUInstructionSelector::selectG_BUILD_VECTOR(
MachineInstr &
MI)
const {
915 assert(
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC ||
916 MI.getOpcode() == AMDGPU::G_BUILD_VECTOR);
920 LLT SrcTy = MRI->getType(Src0);
924 if (
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR && SrcSize >= 32) {
925 return selectG_MERGE_VALUES(
MI);
932 (
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC &&
936 const RegisterBank *DstBank = RBI.getRegBank(Dst, *MRI, TRI);
937 if (DstBank->
getID() == AMDGPU::AGPRRegBankID)
940 assert(DstBank->
getID() == AMDGPU::SGPRRegBankID ||
941 DstBank->
getID() == AMDGPU::VGPRRegBankID);
942 const bool IsVector = DstBank->
getID() == AMDGPU::VGPRRegBankID;
955 const int64_t K0 = ConstSrc0->Value.getSExtValue();
956 const int64_t K1 = ConstSrc1->Value.getSExtValue();
957 uint32_t
Lo16 =
static_cast<uint32_t
>(K0) & 0xffff;
958 uint32_t
Hi16 =
static_cast<uint32_t
>(K1) & 0xffff;
964 MI.eraseFromParent();
965 return RBI.constrainGenericRegister(Dst, AMDGPU::VGPR_32RegClass, *MRI);
970 MI.eraseFromParent();
971 return RBI.constrainGenericRegister(Dst, AMDGPU::SReg_32RegClass, *MRI);
982 if (Src1Def->
getOpcode() == AMDGPU::G_IMPLICIT_DEF) {
983 MI.setDesc(TII.get(AMDGPU::COPY));
986 IsVector ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
987 return RBI.constrainGenericRegister(Dst, RC, *MRI) &&
988 RBI.constrainGenericRegister(Src0, RC, *MRI);
991 return selectS16MergeToS32(
MI);
994bool AMDGPUInstructionSelector::selectG_IMPLICIT_DEF(
MachineInstr &
I)
const {
995 const MachineOperand &MO =
I.getOperand(0);
1000 TRI.getConstrainedRegClassForReg(MO.
getReg(), *MRI);
1001 if ((!RC && !MRI->getRegBankOrNull(MO.
getReg())) ||
1002 (RC && RBI.constrainGenericRegister(MO.
getReg(), *RC, *MRI))) {
1003 I.setDesc(TII.get(TargetOpcode::IMPLICIT_DEF));
1010bool AMDGPUInstructionSelector::selectG_INSERT(
MachineInstr &
I)
const {
1013 Register DstReg =
I.getOperand(0).getReg();
1014 Register Src0Reg =
I.getOperand(1).getReg();
1015 Register Src1Reg =
I.getOperand(2).getReg();
1016 LLT Src1Ty = MRI->getType(Src1Reg);
1018 unsigned DstSize = MRI->getType(DstReg).getSizeInBits();
1021 int64_t
Offset =
I.getOperand(3).getImm();
1024 if (
Offset % 32 != 0 || InsSize % 32 != 0)
1031 unsigned SubReg = TRI.getSubRegFromChannel(
Offset / 32, InsSize / 32);
1032 if (SubReg == AMDGPU::NoSubRegister)
1035 const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
1037 TRI.getRegClassForSizeOnBank(DstSize, *DstBank);
1041 const RegisterBank *Src0Bank = RBI.getRegBank(Src0Reg, *MRI, TRI);
1042 const RegisterBank *Src1Bank = RBI.getRegBank(Src1Reg, *MRI, TRI);
1044 TRI.getRegClassForSizeOnBank(DstSize, *Src0Bank);
1046 TRI.getRegClassForSizeOnBank(InsSize, *Src1Bank);
1050 Src0RC = TRI.getSubClassWithSubReg(Src0RC, SubReg);
1051 if (!Src0RC || !Src1RC)
1054 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
1055 !RBI.constrainGenericRegister(Src0Reg, *Src0RC, *MRI) ||
1056 !RBI.constrainGenericRegister(Src1Reg, *Src1RC, *MRI))
1060 BuildMI(*BB, &
I,
DL, TII.get(TargetOpcode::INSERT_SUBREG), DstReg)
1065 I.eraseFromParent();
1069bool AMDGPUInstructionSelector::selectG_SBFX_UBFX(
MachineInstr &
MI)
const {
1072 Register OffsetReg =
MI.getOperand(2).getReg();
1073 Register WidthReg =
MI.getOperand(3).getReg();
1075 assert(RBI.getRegBank(DstReg, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID &&
1076 "scalar BFX instructions are expanded in regbankselect");
1077 assert(MRI->getType(
MI.getOperand(0).getReg()).getSizeInBits() == 32 &&
1078 "64-bit vector BFX instructions are expanded in regbankselect");
1083 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SBFX;
1084 unsigned Opc = IsSigned ? AMDGPU::V_BFE_I32_e64 : AMDGPU::V_BFE_U32_e64;
1089 MI.eraseFromParent();
1094bool AMDGPUInstructionSelector::selectInterpP1F16(
MachineInstr &
MI)
const {
1095 if (STI.getLDSBankCount() != 16)
1101 if (!RBI.constrainGenericRegister(M0Val, AMDGPU::SReg_32RegClass, *MRI) ||
1102 !RBI.constrainGenericRegister(Dst, AMDGPU::VGPR_32RegClass, *MRI) ||
1103 !RBI.constrainGenericRegister(Src0, AMDGPU::VGPR_32RegClass, *MRI))
1113 Register InterpMov = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
1119 BuildMI(*
MBB, &
MI,
DL, TII.get(AMDGPU::V_INTERP_MOV_F32), InterpMov)
1122 .
addImm(
MI.getOperand(3).getImm());
1135 MI.eraseFromParent();
1144bool AMDGPUInstructionSelector::selectWritelane(
MachineInstr &
MI)
const {
1146 if (STI.getConstantBusLimit(AMDGPU::V_WRITELANE_B32) > 1)
1153 Register LaneSelect =
MI.getOperand(3).getReg();
1156 auto MIB =
BuildMI(*
MBB, &
MI,
DL, TII.get(AMDGPU::V_WRITELANE_B32), VDst);
1158 std::optional<ValueAndVReg> ConstSelect =
1164 MIB.
addImm(ConstSelect->Value.getSExtValue() &
1167 std::optional<ValueAndVReg> ConstVal =
1173 STI.hasInv2PiInlineImm())) {
1174 MIB.
addImm(ConstVal->Value.getSExtValue());
1182 RBI.constrainGenericRegister(LaneSelect, AMDGPU::SReg_32_XM0RegClass, *MRI);
1184 BuildMI(*
MBB, *MIB,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
1192 MI.eraseFromParent();
1199bool AMDGPUInstructionSelector::selectDivScale(
MachineInstr &
MI)
const {
1203 LLT Ty = MRI->getType(Dst0);
1206 Opc = AMDGPU::V_DIV_SCALE_F32_e64;
1208 Opc = AMDGPU::V_DIV_SCALE_F64_e64;
1219 unsigned ChooseDenom =
MI.getOperand(5).getImm();
1221 Register Src0 = ChooseDenom != 0 ? Numer : Denom;
1234 MI.eraseFromParent();
1239bool AMDGPUInstructionSelector::selectG_INTRINSIC(
MachineInstr &
I)
const {
1241 switch (IntrinsicID) {
1242 case Intrinsic::amdgcn_if_break: {
1247 BuildMI(*BB, &
I,
I.getDebugLoc(), TII.get(AMDGPU::SI_IF_BREAK))
1248 .
add(
I.getOperand(0))
1249 .
add(
I.getOperand(2))
1250 .
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))
1826 MI.eraseFromParent();
1828 if (!MRI->getRegClassOrNull(
Reg))
1829 MRI->setRegClass(
Reg, TRI.getWaveMaskRegClass());
1833bool AMDGPUInstructionSelector::selectDSOrderedIntrinsic(
1839 unsigned IndexOperand =
MI.getOperand(7).getImm();
1840 bool WaveRelease =
MI.getOperand(8).getImm() != 0;
1841 bool WaveDone =
MI.getOperand(9).getImm() != 0;
1843 if (WaveDone && !WaveRelease) {
1847 Fn,
"ds_ordered_count: wave_done requires wave_release",
DL));
1850 unsigned OrderedCountIndex = IndexOperand & 0x3f;
1851 IndexOperand &= ~0x3f;
1852 unsigned CountDw = 0;
1855 CountDw = (IndexOperand >> 24) & 0xf;
1856 IndexOperand &= ~(0xf << 24);
1858 if (CountDw < 1 || CountDw > 4) {
1861 Fn,
"ds_ordered_count: dword count must be between 1 and 4",
DL));
1869 Fn,
"ds_ordered_count: bad index operand",
DL));
1872 unsigned Instruction = IntrID == Intrinsic::amdgcn_ds_ordered_add ? 0 : 1;
1875 unsigned Offset0 = OrderedCountIndex << 2;
1876 unsigned Offset1 = WaveRelease | (WaveDone << 1) | (Instruction << 4);
1879 Offset1 |= (CountDw - 1) << 6;
1882 Offset1 |= ShaderType << 2;
1884 unsigned Offset = Offset0 | (Offset1 << 8);
1892 MachineInstrBuilder
DS =
1893 BuildMI(*
MBB, &
MI,
DL, TII.get(AMDGPU::DS_ORDERED_COUNT), DstReg)
1898 if (!RBI.constrainGenericRegister(M0Val, AMDGPU::SReg_32RegClass, *MRI))
1902 MI.eraseFromParent();
1908 case Intrinsic::amdgcn_ds_gws_init:
1909 return AMDGPU::DS_GWS_INIT;
1910 case Intrinsic::amdgcn_ds_gws_barrier:
1911 return AMDGPU::DS_GWS_BARRIER;
1912 case Intrinsic::amdgcn_ds_gws_sema_v:
1913 return AMDGPU::DS_GWS_SEMA_V;
1914 case Intrinsic::amdgcn_ds_gws_sema_br:
1915 return AMDGPU::DS_GWS_SEMA_BR;
1916 case Intrinsic::amdgcn_ds_gws_sema_p:
1917 return AMDGPU::DS_GWS_SEMA_P;
1918 case Intrinsic::amdgcn_ds_gws_sema_release_all:
1919 return AMDGPU::DS_GWS_SEMA_RELEASE_ALL;
1925bool AMDGPUInstructionSelector::selectDSGWSIntrinsic(
MachineInstr &
MI,
1927 if (!STI.hasGWS() || (IID == Intrinsic::amdgcn_ds_gws_sema_release_all &&
1928 !STI.hasGWSSemaReleaseAll()))
1932 const bool HasVSrc =
MI.getNumOperands() == 3;
1933 assert(HasVSrc ||
MI.getNumOperands() == 2);
1935 Register BaseOffset =
MI.getOperand(HasVSrc ? 2 : 1).getReg();
1936 const RegisterBank *OffsetRB = RBI.getRegBank(BaseOffset, *MRI, TRI);
1937 if (OffsetRB->
getID() != AMDGPU::SGPRRegBankID)
1946 MachineInstr *Readfirstlane =
nullptr;
1951 if (OffsetDef->
getOpcode() == AMDGPU::V_READFIRSTLANE_B32) {
1952 Readfirstlane = OffsetDef;
1957 if (OffsetDef->
getOpcode() == AMDGPU::G_CONSTANT) {
1967 std::tie(BaseOffset, ImmOffset) =
1970 if (Readfirstlane) {
1973 if (!RBI.constrainGenericRegister(BaseOffset, AMDGPU::VGPR_32RegClass, *MRI))
1979 if (!RBI.constrainGenericRegister(BaseOffset,
1980 AMDGPU::SReg_32RegClass, *MRI))
1984 Register M0Base = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
1999 const MCInstrDesc &InstrDesc = TII.get(
Opc);
2004 int Data0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
2007 TRI.getSubRegisterClass(DataRC, AMDGPU::sub0);
2011 if (!RBI.constrainGenericRegister(VSrc, *DataRC, *MRI))
2021 Register DataReg = MRI->createVirtualRegister(DataRC);
2022 if (!RBI.constrainGenericRegister(VSrc, *SubRC, *MRI))
2025 Register UndefReg = MRI->createVirtualRegister(SubRC);
2044 MI.eraseFromParent();
2048bool AMDGPUInstructionSelector::selectDSAppendConsume(
MachineInstr &
MI,
2049 bool IsAppend)
const {
2050 Register PtrBase =
MI.getOperand(2).getReg();
2051 LLT PtrTy = MRI->getType(PtrBase);
2055 std::tie(PtrBase,
Offset) = selectDS1Addr1OffsetImpl(
MI.getOperand(2));
2058 if (!isDSOffsetLegal(PtrBase,
Offset)) {
2059 PtrBase =
MI.getOperand(2).getReg();
2065 const unsigned Opc = IsAppend ? AMDGPU::DS_APPEND : AMDGPU::DS_CONSUME;
2069 if (!RBI.constrainGenericRegister(PtrBase, AMDGPU::SReg_32RegClass, *MRI))
2076 MI.eraseFromParent();
2081bool AMDGPUInstructionSelector::selectInitWholeWave(
MachineInstr &
MI)
const {
2083 SIMachineFunctionInfo *MFInfo =
MF->getInfo<SIMachineFunctionInfo>();
2094 TFE = TexFailCtrl & 0x1;
2096 LWE = TexFailCtrl & 0x2;
2099 return TexFailCtrl == 0;
2102bool AMDGPUInstructionSelector::selectImageIntrinsic(
2110 Register ResultDef =
MI.getOperand(0).getReg();
2111 if (MRI->use_nodbg_empty(ResultDef))
2115 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
2124 const unsigned ArgOffset =
MI.getNumExplicitDefs() + 1;
2126 Register VDataIn = AMDGPU::NoRegister;
2127 Register VDataOut = AMDGPU::NoRegister;
2129 int NumVDataDwords = -1;
2130 bool IsD16 =
MI.getOpcode() == AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16 ||
2131 MI.getOpcode() == AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16;
2137 Unorm =
MI.getOperand(ArgOffset + Intr->
UnormIndex).getImm() != 0;
2141 bool IsTexFail =
false;
2143 TFE, LWE, IsTexFail))
2146 const int Flags =
MI.getOperand(ArgOffset + Intr->
NumArgs).getImm();
2147 const bool IsA16 = (
Flags & 1) != 0;
2148 const bool IsG16 = (
Flags & 2) != 0;
2151 if (IsA16 && !STI.hasG16() && !IsG16)
2155 unsigned DMaskLanes = 0;
2157 if (BaseOpcode->
Atomic) {
2159 VDataOut =
MI.getOperand(0).getReg();
2160 VDataIn =
MI.getOperand(2).getReg();
2161 LLT Ty = MRI->getType(VDataIn);
2164 const bool Is64Bit = BaseOpcode->
AtomicX2 ?
2169 assert(
MI.getOperand(3).getReg() == AMDGPU::NoRegister);
2171 DMask = Is64Bit ? 0xf : 0x3;
2172 NumVDataDwords = Is64Bit ? 4 : 2;
2174 DMask = Is64Bit ? 0x3 : 0x1;
2175 NumVDataDwords = Is64Bit ? 2 : 1;
2178 DMask =
MI.getOperand(ArgOffset + Intr->
DMaskIndex).getImm();
2181 if (BaseOpcode->
Store) {
2182 VDataIn =
MI.getOperand(1).getReg();
2183 VDataTy = MRI->getType(VDataIn);
2188 VDataOut =
MI.getOperand(0).getReg();
2189 VDataTy = MRI->getType(VDataOut);
2190 NumVDataDwords = DMaskLanes;
2192 if (IsD16 && !STI.hasUnpackedD16VMem())
2193 NumVDataDwords = (DMaskLanes + 1) / 2;
2198 if (Subtarget->hasG16() && IsG16) {
2199 const AMDGPU::MIMGG16MappingInfo *G16MappingInfo =
2202 IntrOpcode = G16MappingInfo->
G16;
2206 assert((!IsTexFail || DMaskLanes >= 1) &&
"should have legalized this");
2216 int NumVAddrRegs = 0;
2217 int NumVAddrDwords = 0;
2220 MachineOperand &AddrOp =
MI.getOperand(ArgOffset +
I);
2221 if (!AddrOp.
isReg())
2229 NumVAddrDwords += (MRI->getType(Addr).getSizeInBits() + 31) / 32;
2236 NumVAddrRegs != 1 &&
2237 (STI.hasPartialNSAEncoding() ? NumVAddrDwords >= NumVAddrRegs
2238 : NumVAddrDwords == NumVAddrRegs);
2239 if (UseNSA && !STI.hasFeature(AMDGPU::FeatureNSAEncoding)) {
2250 NumVDataDwords, NumVAddrDwords);
2251 }
else if (IsGFX12Plus) {
2253 NumVDataDwords, NumVAddrDwords);
2254 }
else if (IsGFX11Plus) {
2256 UseNSA ? AMDGPU::MIMGEncGfx11NSA
2257 : AMDGPU::MIMGEncGfx11Default,
2258 NumVDataDwords, NumVAddrDwords);
2259 }
else if (IsGFX10Plus) {
2261 UseNSA ? AMDGPU::MIMGEncGfx10NSA
2262 : AMDGPU::MIMGEncGfx10Default,
2263 NumVDataDwords, NumVAddrDwords);
2265 if (Subtarget->hasGFX90AInsts()) {
2267 NumVDataDwords, NumVAddrDwords);
2271 <<
"requested image instruction is not supported on this GPU\n");
2278 NumVDataDwords, NumVAddrDwords);
2281 NumVDataDwords, NumVAddrDwords);
2291 const bool Is64 = MRI->getType(VDataOut).getSizeInBits() == 64;
2293 Register TmpReg = MRI->createVirtualRegister(
2294 Is64 ? &AMDGPU::VReg_128RegClass : &AMDGPU::VReg_64RegClass);
2295 unsigned SubReg = Is64 ? AMDGPU::sub0_sub1 : AMDGPU::sub0;
2298 if (!MRI->use_empty(VDataOut)) {
2311 for (
int I = 0;
I != NumVAddrRegs; ++
I) {
2312 MachineOperand &SrcOp =
MI.getOperand(ArgOffset + Intr->
VAddrStart +
I);
2313 if (SrcOp.
isReg()) {
2332 STI.hasFeature(AMDGPU::FeatureR128A16) ? -1 : 0);
2334 MIB.
addImm(IsA16 ? -1 : 0);
2336 if (!Subtarget->hasGFX90AInsts()) {
2348 MIB.
addImm(IsD16 ? -1 : 0);
2350 MI.eraseFromParent();
2352 TII.enforceOperandRCAlignment(*MIB, AMDGPU::OpName::vaddr);
2358bool AMDGPUInstructionSelector::selectDSBvhStackIntrinsic(
2369 unsigned Offset =
MI.getOperand(6).getImm();
2373 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
2374 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
2375 Opc = AMDGPU::DS_BVH_STACK_RTN_B32;
2377 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
2378 Opc = AMDGPU::DS_BVH_STACK_PUSH8_POP1_RTN_B32;
2380 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn:
2381 Opc = AMDGPU::DS_BVH_STACK_PUSH8_POP2_RTN_B64;
2393 MI.eraseFromParent();
2398bool AMDGPUInstructionSelector::selectG_INTRINSIC_W_SIDE_EFFECTS(
2401 switch (IntrinsicID) {
2402 case Intrinsic::amdgcn_end_cf:
2403 return selectEndCfIntrinsic(
I);
2404 case Intrinsic::amdgcn_ds_ordered_add:
2405 case Intrinsic::amdgcn_ds_ordered_swap:
2406 return selectDSOrderedIntrinsic(
I, IntrinsicID);
2407 case Intrinsic::amdgcn_ds_gws_init:
2408 case Intrinsic::amdgcn_ds_gws_barrier:
2409 case Intrinsic::amdgcn_ds_gws_sema_v:
2410 case Intrinsic::amdgcn_ds_gws_sema_br:
2411 case Intrinsic::amdgcn_ds_gws_sema_p:
2412 case Intrinsic::amdgcn_ds_gws_sema_release_all:
2413 return selectDSGWSIntrinsic(
I, IntrinsicID);
2414 case Intrinsic::amdgcn_ds_append:
2415 return selectDSAppendConsume(
I,
true);
2416 case Intrinsic::amdgcn_ds_consume:
2417 return selectDSAppendConsume(
I,
false);
2418 case Intrinsic::amdgcn_init_whole_wave:
2419 return selectInitWholeWave(
I);
2420 case Intrinsic::amdgcn_raw_buffer_load_lds:
2421 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
2422 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
2423 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
2424 case Intrinsic::amdgcn_struct_buffer_load_lds:
2425 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
2426 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
2427 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
2428 return selectBufferLoadLds(
I);
2433 case Intrinsic::amdgcn_load_to_lds:
2434 case Intrinsic::amdgcn_load_async_to_lds:
2435 case Intrinsic::amdgcn_global_load_lds:
2436 case Intrinsic::amdgcn_global_load_async_lds:
2437 return selectGlobalLoadLds(
I);
2438 case Intrinsic::amdgcn_tensor_load_to_lds:
2439 case Intrinsic::amdgcn_tensor_store_from_lds:
2440 return selectTensorLoadStore(
I, IntrinsicID);
2441 case Intrinsic::amdgcn_asyncmark:
2442 case Intrinsic::amdgcn_wait_asyncmark:
2443 if (!Subtarget->hasAsyncMark())
2446 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
2447 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
2448 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
2449 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn:
2450 return selectDSBvhStackIntrinsic(
I);
2451 case Intrinsic::amdgcn_s_alloc_vgpr: {
2457 Register ResReg =
I.getOperand(0).getReg();
2459 MachineInstr *AllocMI =
BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::S_ALLOC_VGPR))
2460 .
add(
I.getOperand(2));
2463 I.eraseFromParent();
2465 return RBI.constrainGenericRegister(ResReg, AMDGPU::SReg_32RegClass, *MRI);
2467 case Intrinsic::amdgcn_s_barrier_init:
2468 case Intrinsic::amdgcn_s_barrier_signal_var:
2469 return selectNamedBarrierInit(
I, IntrinsicID);
2470 case Intrinsic::amdgcn_s_wakeup_barrier:
2471 case Intrinsic::amdgcn_s_barrier_join:
2472 case Intrinsic::amdgcn_s_get_named_barrier_state:
2473 return selectNamedBarrierInst(
I, IntrinsicID);
2474 case Intrinsic::amdgcn_s_get_barrier_state:
2475 return selectSGetBarrierState(
I, IntrinsicID);
2476 case Intrinsic::amdgcn_s_barrier_signal_isfirst:
2477 return selectSBarrierSignalIsfirst(
I, IntrinsicID);
2482bool AMDGPUInstructionSelector::selectG_SELECT(
MachineInstr &
I)
const {
2489 Register DstReg =
I.getOperand(0).getReg();
2490 unsigned Size = RBI.getSizeInBits(DstReg, *MRI, TRI);
2492 const MachineOperand &CCOp =
I.getOperand(1);
2494 if (!isVCC(CCReg, *MRI)) {
2495 unsigned SelectOpcode =
Size == 64 ? AMDGPU::S_CSELECT_B64 :
2496 AMDGPU::S_CSELECT_B32;
2497 MachineInstr *CopySCC =
BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::SCC)
2503 if (!MRI->getRegClassOrNull(CCReg))
2504 MRI->setRegClass(CCReg, TRI.getConstrainedRegClassForReg(CCReg, *MRI));
2506 .
add(
I.getOperand(2))
2507 .
add(
I.getOperand(3));
2511 I.eraseFromParent();
2520 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
2522 .
add(
I.getOperand(3))
2524 .
add(
I.getOperand(2))
2525 .
add(
I.getOperand(1));
2528 I.eraseFromParent();
2532bool AMDGPUInstructionSelector::selectG_TRUNC(
MachineInstr &
I)
const {
2533 Register DstReg =
I.getOperand(0).getReg();
2534 Register SrcReg =
I.getOperand(1).getReg();
2535 const LLT DstTy = MRI->getType(DstReg);
2536 const LLT SrcTy = MRI->getType(SrcReg);
2539 const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
2540 const RegisterBank *DstRB;
2546 DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
2551 const bool IsVALU = DstRB->
getID() == AMDGPU::VGPRRegBankID;
2557 TRI.getRegClassForSizeOnBank(SrcSize, *SrcRB);
2559 TRI.getRegClassForSizeOnBank(DstSize, *DstRB);
2560 if (!SrcRC || !DstRC)
2563 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
2564 !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI)) {
2569 if (DstRC == &AMDGPU::VGPR_16RegClass && SrcSize == 32) {
2570 assert(STI.useRealTrue16Insts());
2574 .
addReg(SrcReg, {}, AMDGPU::lo16);
2575 I.eraseFromParent();
2583 Register LoReg = MRI->createVirtualRegister(DstRC);
2584 Register HiReg = MRI->createVirtualRegister(DstRC);
2586 .
addReg(SrcReg, {}, AMDGPU::sub0);
2588 .
addReg(SrcReg, {}, AMDGPU::sub1);
2590 if (IsVALU && STI.hasSDWA()) {
2593 MachineInstr *MovSDWA =
2594 BuildMI(*
MBB,
I,
DL, TII.get(AMDGPU::V_MOV_B32_sdwa), DstReg)
2604 Register TmpReg0 = MRI->createVirtualRegister(DstRC);
2605 Register TmpReg1 = MRI->createVirtualRegister(DstRC);
2606 Register ImmReg = MRI->createVirtualRegister(DstRC);
2608 BuildMI(*
MBB,
I,
DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), TmpReg0)
2618 unsigned MovOpc = IsVALU ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32;
2619 unsigned AndOpc = IsVALU ? AMDGPU::V_AND_B32_e64 : AMDGPU::S_AND_B32;
2620 unsigned OrOpc = IsVALU ? AMDGPU::V_OR_B32_e64 : AMDGPU::S_OR_B32;
2632 And.setOperandDead(3);
2633 Or.setOperandDead(3);
2637 I.eraseFromParent();
2645 unsigned SubRegIdx = DstSize < 32
2646 ?
static_cast<unsigned>(AMDGPU::sub0)
2647 : TRI.getSubRegFromChannel(0, DstSize / 32);
2648 if (SubRegIdx == AMDGPU::NoSubRegister)
2654 = TRI.getSubClassWithSubReg(SrcRC, SubRegIdx);
2658 if (SrcWithSubRC != SrcRC) {
2659 if (!RBI.constrainGenericRegister(SrcReg, *SrcWithSubRC, *MRI))
2663 I.getOperand(1).setSubReg(SubRegIdx);
2666 I.setDesc(TII.get(TargetOpcode::COPY));
2673 int SignedMask =
static_cast<int>(Mask);
2674 return SignedMask >= -16 && SignedMask <= 64;
2678const RegisterBank *AMDGPUInstructionSelector::getArtifactRegBank(
2687 return &RBI.getRegBankFromRegClass(*RC, LLT());
2691bool AMDGPUInstructionSelector::selectG_SZA_EXT(
MachineInstr &
I)
const {
2692 bool InReg =
I.getOpcode() == AMDGPU::G_SEXT_INREG;
2693 bool Signed =
I.getOpcode() == AMDGPU::G_SEXT || InReg;
2696 const Register DstReg =
I.getOperand(0).getReg();
2697 const Register SrcReg =
I.getOperand(1).getReg();
2699 const LLT DstTy = MRI->getType(DstReg);
2700 const LLT SrcTy = MRI->getType(SrcReg);
2701 const unsigned SrcSize =
I.getOpcode() == AMDGPU::G_SEXT_INREG ?
2708 const RegisterBank *SrcBank = getArtifactRegBank(SrcReg, *MRI, TRI);
2711 if (
I.getOpcode() == AMDGPU::G_ANYEXT) {
2713 return selectCOPY(
I);
2716 TRI.getRegClassForTypeOnBank(SrcTy, *SrcBank);
2717 const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
2719 TRI.getRegClassForSizeOnBank(DstSize, *DstBank);
2721 Register UndefReg = MRI->createVirtualRegister(SrcRC);
2722 BuildMI(
MBB,
I,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefReg);
2728 I.eraseFromParent();
2730 return RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) &&
2731 RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI);
2734 if (SrcBank->
getID() == AMDGPU::VGPRRegBankID && DstSize <= 32) {
2740 MachineInstr *ExtI =
2744 I.eraseFromParent();
2749 const unsigned BFE =
Signed ? AMDGPU::V_BFE_I32_e64 : AMDGPU::V_BFE_U32_e64;
2750 MachineInstr *ExtI =
2755 I.eraseFromParent();
2760 if (SrcBank->
getID() == AMDGPU::SGPRRegBankID && DstSize <= 64) {
2762 AMDGPU::SReg_64RegClass : AMDGPU::SReg_32RegClass;
2763 if (!RBI.constrainGenericRegister(SrcReg, SrcRC, *MRI))
2766 if (
Signed && DstSize == 32 && (SrcSize == 8 || SrcSize == 16)) {
2767 const unsigned SextOpc = SrcSize == 8 ?
2768 AMDGPU::S_SEXT_I32_I8 : AMDGPU::S_SEXT_I32_I16;
2771 I.eraseFromParent();
2772 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_32RegClass, *MRI);
2777 if (DstSize > 32 && SrcSize == 32) {
2778 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2779 unsigned SubReg = InReg ? AMDGPU::sub0 : AMDGPU::NoSubRegister;
2782 .
addReg(SrcReg, {}, SubReg)
2790 .
addReg(SrcReg, {}, SubReg)
2791 .addImm(AMDGPU::sub0)
2794 I.eraseFromParent();
2795 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_64RegClass,
2799 const unsigned BFE64 =
Signed ? AMDGPU::S_BFE_I64 : AMDGPU::S_BFE_U64;
2800 const unsigned BFE32 =
Signed ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32;
2803 if (DstSize > 32 && (SrcSize <= 32 || InReg)) {
2805 Register ExtReg = MRI->createVirtualRegister(&AMDGPU::SReg_64RegClass);
2806 Register UndefReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2807 unsigned SubReg = InReg ? AMDGPU::sub0 : AMDGPU::NoSubRegister;
2809 BuildMI(
MBB,
I,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefReg);
2811 .
addReg(SrcReg, {}, SubReg)
2812 .addImm(AMDGPU::sub0)
2820 I.eraseFromParent();
2821 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_64RegClass, *MRI);
2836 I.eraseFromParent();
2837 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_32RegClass, *MRI);
2889 assert(Mask.size() == 2);
2891 if (Mask[0] == 1 && Mask[1] <= 1) {
2906 if (Unmerge->getNumDefs() == 2 && Unmerge->getOperand(0).getReg() == In &&
2924bool AMDGPUInstructionSelector::selectG_FPEXT(
MachineInstr &
I)
const {
2925 if (!Subtarget->hasSALUFloatInsts())
2928 Register Dst =
I.getOperand(0).getReg();
2929 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
2930 if (DstRB->
getID() != AMDGPU::SGPRRegBankID)
2933 Register Src =
I.getOperand(1).getReg();
2939 BuildMI(*BB, &
I,
I.getDebugLoc(), TII.get(AMDGPU::S_CVT_HI_F32_F16), Dst)
2941 I.eraseFromParent();
2942 return RBI.constrainGenericRegister(Dst, AMDGPU::SReg_32RegClass, *MRI);
2949bool AMDGPUInstructionSelector::selectG_FNEG(
MachineInstr &
MI)
const {
2962 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
2963 if (DstRB->
getID() != AMDGPU::SGPRRegBankID ||
2968 MachineInstr *Fabs =
getOpcodeDef(TargetOpcode::G_FABS, Src, *MRI);
2972 if (!RBI.constrainGenericRegister(Src, AMDGPU::SReg_64RegClass, *MRI) ||
2973 !RBI.constrainGenericRegister(Dst, AMDGPU::SReg_64RegClass, *MRI))
2978 Register LoReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2979 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2980 Register ConstReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2981 Register OpReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2983 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), LoReg)
2984 .
addReg(Src, {}, AMDGPU::sub0);
2985 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), HiReg)
2986 .
addReg(Src, {}, AMDGPU::sub1);
2987 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_MOV_B32), ConstReg)
2991 unsigned Opc = Fabs ? AMDGPU::S_OR_B32 : AMDGPU::S_XOR_B32;
2996 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::REG_SEQUENCE), Dst)
3001 MI.eraseFromParent();
3006bool AMDGPUInstructionSelector::selectG_FABS(
MachineInstr &
MI)
const {
3008 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
3009 if (DstRB->
getID() != AMDGPU::SGPRRegBankID ||
3016 Register LoReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3017 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3018 Register ConstReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3019 Register OpReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3021 if (!RBI.constrainGenericRegister(Src, AMDGPU::SReg_64RegClass, *MRI) ||
3022 !RBI.constrainGenericRegister(Dst, AMDGPU::SReg_64RegClass, *MRI))
3025 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), LoReg)
3026 .
addReg(Src, {}, AMDGPU::sub0);
3027 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), HiReg)
3028 .
addReg(Src, {}, AMDGPU::sub1);
3029 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_MOV_B32), ConstReg)
3034 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_AND_B32), OpReg)
3038 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::REG_SEQUENCE), Dst)
3044 MI.eraseFromParent();
3049 return MI.getOpcode() == TargetOpcode::G_CONSTANT;
3055 unsigned OpNo =
Load.getOpcode() == AMDGPU::G_PREFETCH ? 0 : 1;
3056 const MachineInstr *PtrMI =
3057 MRI.getUniqueVRegDef(
Load.getOperand(OpNo).getReg());
3061 if (PtrMI->
getOpcode() != TargetOpcode::G_PTR_ADD)
3066 for (
unsigned i = 1; i != 3; ++i) {
3067 const MachineOperand &GEPOp = PtrMI->
getOperand(i);
3068 const MachineInstr *OpDef = MRI.getUniqueVRegDef(GEPOp.
getReg());
3073 assert(GEPInfo.Imm == 0);
3077 const RegisterBank *OpBank = RBI.getRegBank(GEPOp.
getReg(), MRI, TRI);
3078 if (OpBank->
getID() == AMDGPU::SGPRRegBankID)
3079 GEPInfo.SgprParts.push_back(GEPOp.
getReg());
3081 GEPInfo.VgprParts.push_back(GEPOp.
getReg());
3085 getAddrModeInfo(*PtrMI, MRI, AddrInfo);
3088bool AMDGPUInstructionSelector::isSGPR(
Register Reg)
const {
3089 return RBI.getRegBank(
Reg, *MRI, TRI)->getID() == AMDGPU::SGPRRegBankID;
3092bool AMDGPUInstructionSelector::isInstrUniform(
const MachineInstr &
MI)
const {
3093 if (!
MI.hasOneMemOperand())
3096 const MachineMemOperand *MMO = *
MI.memoperands_begin();
3109 if (
MI.getOpcode() == AMDGPU::G_PREFETCH)
3110 return RBI.getRegBank(
MI.getOperand(0).getReg(), *MRI, TRI)->getID() ==
3111 AMDGPU::SGPRRegBankID;
3114 return I &&
I->getMetadata(
"amdgpu.uniform");
3118 for (
const GEPInfo &GEPInfo : AddrInfo) {
3119 if (!GEPInfo.VgprParts.empty())
3125void AMDGPUInstructionSelector::initM0(
MachineInstr &
I)
const {
3126 const LLT PtrTy = MRI->getType(
I.getOperand(1).getReg());
3129 STI.ldsRequiresM0Init()) {
3133 BuildMI(*BB, &
I,
I.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), AMDGPU::M0)
3138bool AMDGPUInstructionSelector::selectG_LOAD_STORE_ATOMICRMW(
3145 if (
Reg.isPhysical())
3149 const unsigned Opcode =
MI.getOpcode();
3151 if (Opcode == AMDGPU::COPY)
3154 if (Opcode == AMDGPU::G_AND || Opcode == AMDGPU::G_OR ||
3155 Opcode == AMDGPU::G_XOR)
3160 return GI->is(Intrinsic::amdgcn_class);
3162 return Opcode == AMDGPU::G_ICMP || Opcode == AMDGPU::G_FCMP;
3165bool AMDGPUInstructionSelector::selectG_BRCOND(
MachineInstr &
I)
const {
3167 MachineOperand &CondOp =
I.getOperand(0);
3180 if (!isVCC(CondReg, *MRI)) {
3184 CondPhysReg = AMDGPU::SCC;
3185 BrOpcode = AMDGPU::S_CBRANCH_SCC1;
3186 ConstrainRC = &AMDGPU::SReg_32RegClass;
3193 const bool Is64 = STI.isWave64();
3194 const unsigned Opcode = Is64 ? AMDGPU::S_AND_B64 : AMDGPU::S_AND_B32;
3195 const Register Exec = Is64 ? AMDGPU::EXEC : AMDGPU::EXEC_LO;
3197 Register TmpReg = MRI->createVirtualRegister(TRI.getBoolRC());
3198 BuildMI(*BB, &
I,
DL, TII.get(Opcode), TmpReg)
3205 CondPhysReg = TRI.getVCC();
3206 BrOpcode = AMDGPU::S_CBRANCH_VCCNZ;
3207 ConstrainRC = TRI.getBoolRC();
3210 if (!MRI->getRegClassOrNull(CondReg))
3211 MRI->setRegClass(CondReg, ConstrainRC);
3213 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), CondPhysReg)
3216 .
addMBB(
I.getOperand(1).getMBB());
3218 I.eraseFromParent();
3222bool AMDGPUInstructionSelector::selectG_GLOBAL_VALUE(
3224 Register DstReg =
I.getOperand(0).getReg();
3225 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3226 const bool IsVGPR = DstRB->
getID() == AMDGPU::VGPRRegBankID;
3227 I.setDesc(TII.get(IsVGPR ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32));
3231 return RBI.constrainGenericRegister(
3232 DstReg, IsVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass, *MRI);
3235bool AMDGPUInstructionSelector::selectG_PTRMASK(
MachineInstr &
I)
const {
3236 Register DstReg =
I.getOperand(0).getReg();
3237 Register SrcReg =
I.getOperand(1).getReg();
3238 Register MaskReg =
I.getOperand(2).getReg();
3239 LLT Ty = MRI->getType(DstReg);
3240 LLT MaskTy = MRI->getType(MaskReg);
3244 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3245 const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
3246 const RegisterBank *MaskRB = RBI.getRegBank(MaskReg, *MRI, TRI);
3247 const bool IsVGPR = DstRB->
getID() == AMDGPU::VGPRRegBankID;
3253 APInt MaskOnes =
VT->getKnownOnes(MaskReg).zext(64);
3257 const bool CanCopyLow32 = (MaskOnes & MaskLo32) == MaskLo32;
3258 const bool CanCopyHi32 = (MaskOnes & MaskHi32) == MaskHi32;
3261 !CanCopyLow32 && !CanCopyHi32) {
3262 auto MIB =
BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_AND_B64), DstReg)
3266 I.eraseFromParent();
3271 unsigned NewOpc = IsVGPR ? AMDGPU::V_AND_B32_e64 : AMDGPU::S_AND_B32;
3273 = IsVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
3278 TRI.getRegClassForTypeOnBank(MaskTy, *MaskRB);
3280 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
3281 !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
3282 !RBI.constrainGenericRegister(MaskReg, *MaskRC, *MRI))
3287 "ptrmask should have been narrowed during legalize");
3289 auto NewOp =
BuildMI(*BB, &
I,
DL, TII.get(NewOpc), DstReg)
3295 I.eraseFromParent();
3299 Register HiReg = MRI->createVirtualRegister(&RegRC);
3300 Register LoReg = MRI->createVirtualRegister(&RegRC);
3303 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), LoReg)
3304 .
addReg(SrcReg, {}, AMDGPU::sub0);
3305 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), HiReg)
3306 .
addReg(SrcReg, {}, AMDGPU::sub1);
3315 Register MaskLo = MRI->createVirtualRegister(&RegRC);
3316 MaskedLo = MRI->createVirtualRegister(&RegRC);
3318 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), MaskLo)
3319 .
addReg(MaskReg, {}, AMDGPU::sub0);
3320 BuildMI(*BB, &
I,
DL, TII.get(NewOpc), MaskedLo)
3329 Register MaskHi = MRI->createVirtualRegister(&RegRC);
3330 MaskedHi = MRI->createVirtualRegister(&RegRC);
3332 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), MaskHi)
3333 .
addReg(MaskReg, {}, AMDGPU::sub1);
3334 BuildMI(*BB, &
I,
DL, TII.get(NewOpc), MaskedHi)
3339 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
3344 I.eraseFromParent();
3350static std::pair<Register, unsigned>
3357 std::tie(IdxBaseReg,
Offset) =
3359 if (IdxBaseReg == AMDGPU::NoRegister) {
3363 IdxBaseReg = IdxReg;
3370 if (
static_cast<unsigned>(
Offset) >= SubRegs.
size())
3371 return std::pair(IdxReg, SubRegs[0]);
3372 return std::pair(IdxBaseReg, SubRegs[
Offset]);
3375bool AMDGPUInstructionSelector::selectG_EXTRACT_VECTOR_ELT(
3381 LLT DstTy = MRI->getType(DstReg);
3382 LLT SrcTy = MRI->getType(SrcReg);
3384 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3385 const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
3386 const RegisterBank *IdxRB = RBI.getRegBank(IdxReg, *MRI, TRI);
3390 if (IdxRB->
getID() != AMDGPU::SGPRRegBankID)
3394 TRI.getRegClassForTypeOnBank(SrcTy, *SrcRB);
3396 TRI.getRegClassForTypeOnBank(DstTy, *DstRB);
3397 if (!SrcRC || !DstRC)
3399 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
3400 !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
3401 !RBI.constrainGenericRegister(IdxReg, AMDGPU::SReg_32RegClass, *MRI))
3412 if (SrcRB->
getID() == AMDGPU::SGPRRegBankID) {
3416 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3419 unsigned Opc = Is64 ? AMDGPU::S_MOVRELS_B64 : AMDGPU::S_MOVRELS_B32;
3421 .
addReg(SrcReg, {}, SubReg)
3423 MI.eraseFromParent();
3430 if (!STI.useVGPRIndexMode()) {
3431 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3433 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::V_MOVRELS_B32_e32), DstReg)
3434 .
addReg(SrcReg, {}, SubReg)
3436 MI.eraseFromParent();
3440 const MCInstrDesc &GPRIDXDesc =
3441 TII.getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*SrcRC),
true);
3447 MI.eraseFromParent();
3452bool AMDGPUInstructionSelector::selectG_INSERT_VECTOR_ELT(
3459 LLT VecTy = MRI->getType(DstReg);
3460 LLT ValTy = MRI->getType(ValReg);
3464 const RegisterBank *VecRB = RBI.getRegBank(VecReg, *MRI, TRI);
3465 const RegisterBank *ValRB = RBI.getRegBank(ValReg, *MRI, TRI);
3466 const RegisterBank *IdxRB = RBI.getRegBank(IdxReg, *MRI, TRI);
3472 if (IdxRB->
getID() != AMDGPU::SGPRRegBankID)
3476 TRI.getRegClassForTypeOnBank(VecTy, *VecRB);
3478 TRI.getRegClassForTypeOnBank(ValTy, *ValRB);
3480 if (!RBI.constrainGenericRegister(VecReg, *VecRC, *MRI) ||
3481 !RBI.constrainGenericRegister(DstReg, *VecRC, *MRI) ||
3482 !RBI.constrainGenericRegister(ValReg, *ValRC, *MRI) ||
3483 !RBI.constrainGenericRegister(IdxReg, AMDGPU::SReg_32RegClass, *MRI))
3486 if (VecRB->
getID() == AMDGPU::VGPRRegBankID && ValSize != 32)
3490 std::tie(IdxReg, SubReg) =
3493 const bool IndexMode = VecRB->
getID() == AMDGPU::VGPRRegBankID &&
3494 STI.useVGPRIndexMode();
3500 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3503 const MCInstrDesc &RegWriteOp = TII.getIndirectRegWriteMovRelPseudo(
3504 VecSize, ValSize, VecRB->
getID() == AMDGPU::SGPRRegBankID);
3509 MI.eraseFromParent();
3513 const MCInstrDesc &GPRIDXDesc =
3514 TII.getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC),
false);
3521 MI.eraseFromParent();
3527 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
3528 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
3529 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
3530 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
3531 case Intrinsic::amdgcn_load_async_to_lds:
3532 case Intrinsic::amdgcn_global_load_async_lds:
3538bool AMDGPUInstructionSelector::selectBufferLoadLds(
MachineInstr &
MI)
const {
3539 if (!Subtarget->hasVMemToLDSLoad())
3542 unsigned Size =
MI.getOperand(3).getImm();
3546 const bool HasVIndex =
MI.getNumOperands() == 9;
3550 VIndex =
MI.getOperand(4).getReg();
3554 Register VOffset =
MI.getOperand(4 + OpOffset).getReg();
3555 std::optional<ValueAndVReg> MaybeVOffset =
3557 const bool HasVOffset = !MaybeVOffset || MaybeVOffset->Value.getZExtValue();
3563 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_BOTHEN
3564 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_IDXEN
3565 : HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFEN
3566 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFSET;
3569 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_BOTHEN
3570 : AMDGPU::BUFFER_LOAD_USHORT_LDS_IDXEN
3571 : HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFEN
3572 : AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFSET;
3575 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_BOTHEN
3576 : AMDGPU::BUFFER_LOAD_DWORD_LDS_IDXEN
3577 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFEN
3578 : AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFSET;
3581 if (!Subtarget->hasLDSLoadB96_B128())
3584 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_BOTHEN
3585 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_IDXEN
3586 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFEN
3587 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFSET;
3590 if (!Subtarget->hasLDSLoadB96_B128())
3593 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_BOTHEN
3594 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_IDXEN
3595 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFEN
3596 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFSET;
3603 .
add(
MI.getOperand(2));
3607 if (HasVIndex && HasVOffset) {
3608 Register IdxReg = MRI->createVirtualRegister(TRI.getVGPR64Class());
3609 BuildMI(*
MBB, &*MIB,
DL, TII.get(AMDGPU::REG_SEQUENCE), IdxReg)
3616 }
else if (HasVIndex) {
3618 }
else if (HasVOffset) {
3622 MIB.
add(
MI.getOperand(1));
3623 MIB.
add(
MI.getOperand(5 + OpOffset));
3624 MIB.
add(
MI.getOperand(6 + OpOffset));
3626 unsigned Aux =
MI.getOperand(7 + OpOffset).getImm();
3635 MachineMemOperand *LoadMMO = *
MI.memoperands_begin();
3640 MachinePointerInfo StorePtrI = LoadPtrI;
3651 MachineMemOperand *StoreMMO =
3657 MI.eraseFromParent();
3670 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3676 return Def->getOperand(1).getReg();
3690 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3698 return Def->getOperand(1).getReg();
3701 if (ZextSrc &&
VT->signBitIsZero(ZextSrc))
3710AMDGPUInstructionSelector::matchZeroExtendFromS32OrS32(
Register Reg)
const {
3712 : matchZeroExtendFromS32(
Reg);
3718AMDGPUInstructionSelector::matchSignExtendFromS32OrS32(
Register Reg)
const {
3720 : matchSignExtendFromS32(
Reg);
3724AMDGPUInstructionSelector::matchExtendFromS32OrS32(
Register Reg,
3725 bool IsSigned)
const {
3727 return matchSignExtendFromS32OrS32(
Reg);
3729 return matchZeroExtendFromS32OrS32(
Reg);
3739 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3746 return Def->getOperand(1).getReg();
3751bool AMDGPUInstructionSelector::selectGlobalLoadLds(
MachineInstr &
MI)
const{
3752 if (!Subtarget->hasVMemToLDSLoad())
3756 unsigned Size =
MI.getOperand(3).getImm();
3763 Opc = AMDGPU::GLOBAL_LOAD_LDS_UBYTE;
3766 Opc = AMDGPU::GLOBAL_LOAD_LDS_USHORT;
3769 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORD;
3772 if (!Subtarget->hasLDSLoadB96_B128())
3774 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX3;
3777 if (!Subtarget->hasLDSLoadB96_B128())
3779 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX4;
3786 .
add(
MI.getOperand(2));
3792 if (!isSGPR(Addr)) {
3794 if (isSGPR(AddrDef->Reg)) {
3795 Addr = AddrDef->Reg;
3796 }
else if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
3799 if (isSGPR(SAddr)) {
3800 Register PtrBaseOffset = AddrDef->MI->getOperand(2).getReg();
3801 if (
Register Off = matchZeroExtendFromS32(PtrBaseOffset)) {
3812 VOffset = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
3824 MIB.
add(
MI.getOperand(4));
3826 unsigned Aux =
MI.getOperand(5).getImm();
3830 MachineMemOperand *LoadMMO = *
MI.memoperands_begin();
3832 LoadPtrI.
Offset =
MI.getOperand(4).getImm();
3833 MachinePointerInfo StorePtrI = LoadPtrI;
3842 MachineMemOperand *StoreMMO =
3844 sizeof(int32_t),
Align(4));
3848 MI.eraseFromParent();
3853bool AMDGPUInstructionSelector::selectTensorLoadStore(
MachineInstr &
MI,
3855 bool IsLoad = IID == Intrinsic::amdgcn_tensor_load_to_lds;
3857 IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d4 : AMDGPU::TENSOR_STORE_FROM_LDS_d4;
3861 const auto isAllZeros = [&](MachineOperand &Opnd) {
3862 const MachineInstr *
DefMI = MRI->getVRegDef(Opnd.getReg());
3871 Opc = IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d2
3872 : AMDGPU::TENSOR_STORE_FROM_LDS_d2;
3879 .
add(
MI.getOperand(1))
3880 .
add(
MI.getOperand(2));
3882 if (NumGroups >= 4) {
3883 MIB.
add(
MI.getOperand(3))
3884 .
add(
MI.getOperand(4));
3888 .
add(
MI.getOperand(6));
3890 MI.eraseFromParent();
3894bool AMDGPUInstructionSelector::selectBVHIntersectRayIntrinsic(
3896 unsigned OpcodeOpIdx =
3897 MI.getOpcode() == AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY ? 1 : 3;
3898 MI.setDesc(TII.get(
MI.getOperand(OpcodeOpIdx).getImm()));
3899 MI.removeOperand(OpcodeOpIdx);
3900 MI.addImplicitDefUseOperands(*
MI.getMF());
3907bool AMDGPUInstructionSelector::selectSMFMACIntrin(
MachineInstr &
MI)
const {
3910 case Intrinsic::amdgcn_smfmac_f32_16x16x32_f16:
3911 Opc = AMDGPU::V_SMFMAC_F32_16X16X32_F16_e64;
3913 case Intrinsic::amdgcn_smfmac_f32_32x32x16_f16:
3914 Opc = AMDGPU::V_SMFMAC_F32_32X32X16_F16_e64;
3916 case Intrinsic::amdgcn_smfmac_f32_16x16x32_bf16:
3917 Opc = AMDGPU::V_SMFMAC_F32_16X16X32_BF16_e64;
3919 case Intrinsic::amdgcn_smfmac_f32_32x32x16_bf16:
3920 Opc = AMDGPU::V_SMFMAC_F32_32X32X16_BF16_e64;
3922 case Intrinsic::amdgcn_smfmac_i32_16x16x64_i8:
3923 Opc = AMDGPU::V_SMFMAC_I32_16X16X64_I8_e64;
3925 case Intrinsic::amdgcn_smfmac_i32_32x32x32_i8:
3926 Opc = AMDGPU::V_SMFMAC_I32_32X32X32_I8_e64;
3928 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_bf8:
3929 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF8_BF8_e64;
3931 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_fp8:
3932 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF8_FP8_e64;
3934 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_bf8:
3935 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_FP8_BF8_e64;
3937 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_fp8:
3938 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_FP8_FP8_e64;
3940 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_bf8:
3941 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF8_BF8_e64;
3943 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_fp8:
3944 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF8_FP8_e64;
3946 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_bf8:
3947 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_FP8_BF8_e64;
3949 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_fp8:
3950 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_FP8_FP8_e64;
3952 case Intrinsic::amdgcn_smfmac_f32_16x16x64_f16:
3953 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_F16_e64;
3955 case Intrinsic::amdgcn_smfmac_f32_32x32x32_f16:
3956 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_F16_e64;
3958 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf16:
3959 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF16_e64;
3961 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf16:
3962 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF16_e64;
3964 case Intrinsic::amdgcn_smfmac_i32_16x16x128_i8:
3965 Opc = AMDGPU::V_SMFMAC_I32_16X16X128_I8_e64;
3967 case Intrinsic::amdgcn_smfmac_i32_32x32x64_i8:
3968 Opc = AMDGPU::V_SMFMAC_I32_32X32X64_I8_e64;
3970 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_bf8:
3971 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_BF8_BF8_e64;
3973 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_fp8:
3974 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_BF8_FP8_e64;
3976 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_bf8:
3977 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_FP8_BF8_e64;
3979 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_fp8:
3980 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_FP8_FP8_e64;
3982 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_bf8:
3983 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_BF8_BF8_e64;
3985 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_fp8:
3986 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_BF8_FP8_e64;
3988 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_bf8:
3989 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_FP8_BF8_e64;
3991 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_fp8:
3992 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_FP8_FP8_e64;
3998 auto VDst_In =
MI.getOperand(4);
4000 MI.setDesc(TII.get(
Opc));
4001 MI.removeOperand(4);
4002 MI.removeOperand(1);
4003 MI.addOperand(VDst_In);
4004 MI.addImplicitDefUseOperands(*
MI.getMF());
4005 const MCInstrDesc &MCID =
MI.getDesc();
4007 MI.getOperand(0).setIsEarlyClobber(
true);
4012bool AMDGPUInstructionSelector::selectPermlaneSwapIntrin(
4014 if (IntrID == Intrinsic::amdgcn_permlane16_swap &&
4015 !Subtarget->hasPermlane16Swap())
4017 if (IntrID == Intrinsic::amdgcn_permlane32_swap &&
4018 !Subtarget->hasPermlane32Swap())
4021 unsigned Opcode = IntrID == Intrinsic::amdgcn_permlane16_swap
4022 ? AMDGPU::V_PERMLANE16_SWAP_B32_e64
4023 : AMDGPU::V_PERMLANE32_SWAP_B32_e64;
4025 MI.removeOperand(2);
4026 MI.setDesc(TII.get(Opcode));
4029 MachineOperand &FI =
MI.getOperand(4);
4036bool AMDGPUInstructionSelector::selectWaveAddress(
MachineInstr &
MI)
const {
4039 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4040 const bool IsVALU = DstRB->
getID() == AMDGPU::VGPRRegBankID;
4045 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHRREV_B32_e64), DstReg)
4046 .
addImm(Subtarget->getWavefrontSizeLog2())
4051 .
addImm(Subtarget->getWavefrontSizeLog2())
4056 IsVALU ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
4057 if (!RBI.constrainGenericRegister(DstReg, RC, *MRI))
4060 MI.eraseFromParent();
4064bool AMDGPUInstructionSelector::selectWaveShuffleIntrin(
4074 const LLT DstTy = MRI->getType(DstReg);
4076 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4078 TRI.getRegClassForSizeOnBank(DstSize, *DstRB);
4083 if (!Subtarget->supportsBPermute())
4087 if (Subtarget->supportsWaveWideBPermute()) {
4088 Register ShiftIdxReg = MRI->createVirtualRegister(DstRC);
4089 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), ShiftIdxReg)
4099 assert(Subtarget->isWave64());
4103 MRI->createVirtualRegister(TRI.getRegClass(AMDGPU::SReg_32RegClassID));
4104 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefValReg);
4106 Register UndefExecReg = MRI->createVirtualRegister(
4107 TRI.getRegClass(AMDGPU::SReg_64_XEXECRegClassID));
4108 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefExecReg);
4110 Register PoisonValReg = MRI->createVirtualRegister(DstRC);
4111 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_SET_INACTIVE_B32), PoisonValReg)
4119 Register ShiftIdxReg = MRI->createVirtualRegister(DstRC);
4120 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), ShiftIdxReg)
4124 Register PoisonIdxReg = MRI->createVirtualRegister(DstRC);
4125 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_SET_INACTIVE_B32), PoisonIdxReg)
4132 Register PoisonUnshiftedIdxReg = MRI->createVirtualRegister(DstRC);
4134 PoisonUnshiftedIdxReg)
4142 Register SameSidePermReg = MRI->createVirtualRegister(DstRC);
4143 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::DS_BPERMUTE_B32), SameSidePermReg)
4148 Register SwappedValReg = MRI->createVirtualRegister(DstRC);
4149 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_PERMLANE64_B32), SwappedValReg)
4152 Register OppSidePermReg = MRI->createVirtualRegister(DstRC);
4153 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::DS_BPERMUTE_B32), OppSidePermReg)
4158 Register WWMSwapPermReg = MRI->createVirtualRegister(DstRC);
4159 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::STRICT_WWM), WWMSwapPermReg)
4166 Register ThreadIDReg = MRI->createVirtualRegister(DstRC);
4167 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_MBCNT_LO_U32_B32_e64), ThreadIDReg)
4171 Register XORReg = MRI->createVirtualRegister(DstRC);
4174 .
addReg(PoisonUnshiftedIdxReg);
4176 Register ANDReg = MRI->createVirtualRegister(DstRC);
4181 Register CompareReg = MRI->createVirtualRegister(
4182 TRI.getRegClass(AMDGPU::SReg_64_XEXECRegClassID));
4183 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_CMP_EQ_U32_e64), CompareReg)
4188 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
4196 MI.eraseFromParent();
4205 unsigned NumOpcodes = 0;
4218 const uint8_t SrcBits[3] = { 0xf0, 0xcc, 0xaa };
4229 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4243 if (Src.size() == 3) {
4250 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4251 if (Src[
I] ==
LHS) {
4261 Bits = SrcBits[Src.size()];
4267 switch (
MI->getOpcode()) {
4268 case TargetOpcode::G_AND:
4269 case TargetOpcode::G_OR:
4270 case TargetOpcode::G_XOR: {
4275 if (!getOperandBits(
LHS, LHSBits) ||
4276 !getOperandBits(
RHS, RHSBits)) {
4277 Src = std::move(Backup);
4278 return std::make_pair(0, 0);
4299 uint8_t LHSBitsOrig = LHSBits;
4300 uint8_t RHSBitsOrig = RHSBits;
4304 NumOpcodes += LHSOp.first;
4305 LHSBits = LHSOp.second;
4312 NumOpcodes += RHSOp.first;
4313 RHSBits = RHSOp.second;
4317 auto dependsOnSlot = [](
uint8_t TT,
int Slot) ->
bool {
4318 if (Slot < 0 || Slot > 2)
4320 const uint8_t Masks[3] = {0x0f, 0x33, 0x55};
4321 const int Shifts[3] = {4, 2, 1};
4322 return ((TT ^ (TT >> Shifts[Slot])) & Masks[Slot]) != 0;
4328 const uint8_t SrcBitsConst[3] = {0xf0, 0xcc, 0xaa};
4335 for (
int I = 0;
I < (int)S.size();
I++) {
4336 if (Bits == SrcBitsConst[
I] && S[
I] ==
Op)
4338 if (IsNegationOp && Bits == (
uint8_t)~SrcBitsConst[
I] &&
4339 S[
I] == NegatedInner)
4350 for (
int I = 0;
I < (int)SrcAfterLHS.
size() &&
I < 3;
I++) {
4351 if (
I < (
int)Src.size() && Src[
I] != SrcAfterLHS[
I] &&
4352 dependsOnSlot(LHSBits,
I)) {
4361 if (!Stale && !RHSOp.first) {
4362 int Slot = findSlot(RHSBitsOrig,
RHS, SrcBeforeRecurse);
4364 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4370 if (!Stale && !LHSOp.first) {
4371 int Slot = findSlot(LHSBitsOrig,
LHS, SrcBeforeRecurse);
4373 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4378 Src = std::move(SrcBeforeRecurse);
4379 LHSBits = LHSBitsOrig;
4380 RHSBits = RHSBitsOrig;
4386 return std::make_pair(0, 0);
4390 switch (
MI->getOpcode()) {
4391 case TargetOpcode::G_AND:
4392 TTbl = LHSBits & RHSBits;
4394 case TargetOpcode::G_OR:
4395 TTbl = LHSBits | RHSBits;
4397 case TargetOpcode::G_XOR:
4398 TTbl = LHSBits ^ RHSBits;
4404 return std::make_pair(NumOpcodes + 1, TTbl);
4407bool AMDGPUInstructionSelector::selectBITOP3(
MachineInstr &
MI)
const {
4408 if (!Subtarget->hasBitOp3Insts())
4412 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4413 const bool IsVALU = DstRB->
getID() == AMDGPU::VGPRRegBankID;
4419 unsigned NumOpcodes;
4421 std::tie(NumOpcodes, TTbl) =
BitOp3_Op(DstReg, Src, *MRI);
4425 if (NumOpcodes < 2 || Src.empty())
4430 unsigned Size = MRI->getType(DstReg).getSizeInBits();
4431 assert((
Size == 16 ||
Size == 32) &&
"unexpected VALU logic op size");
4432 const bool IsB32 =
Size == 32;
4433 if (NumOpcodes == 2 && IsB32) {
4441 }
else if (NumOpcodes < 4) {
4448 unsigned Opc = IsB32 ? AMDGPU::V_BITOP3_B32_e64 : AMDGPU::V_BITOP3_B16_e64;
4449 if (!IsB32 && STI.hasTrue16BitInsts())
4450 Opc = STI.useRealTrue16Insts() ? AMDGPU::V_BITOP3_B16_gfx1250_t16_e64
4451 : AMDGPU::V_BITOP3_B16_gfx1250_fake16_e64;
4452 unsigned CBL = STI.getConstantBusLimit(
Opc);
4456 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4457 const RegisterBank *RB = RBI.getRegBank(Src[
I], *MRI, TRI);
4458 if (RB->
getID() != AMDGPU::SGPRRegBankID)
4464 Register NewReg = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
4475 while (Src.size() < 3)
4476 Src.push_back(Src[0]);
4493 MI.eraseFromParent();
4498bool AMDGPUInstructionSelector::selectStackRestore(
MachineInstr &
MI)
const {
4500 if (!RBI.constrainGenericRegister(SrcReg, AMDGPU::SReg_32RegClass, *MRI))
4503 MachineInstr *
DefMI = MRI->getVRegDef(SrcReg);
4505 Subtarget->getTargetLowering()->getStackPointerRegisterToSaveRestore();
4511 WaveAddr = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
4514 .
addImm(Subtarget->getWavefrontSizeLog2())
4521 MI.eraseFromParent();
4527 if (!
I.isPreISelOpcode()) {
4529 return selectCOPY(
I);
4533 switch (
I.getOpcode()) {
4534 case TargetOpcode::G_AND:
4535 case TargetOpcode::G_OR:
4536 case TargetOpcode::G_XOR:
4537 if (selectBITOP3(
I))
4541 return selectG_AND_OR_XOR(
I);
4542 case TargetOpcode::G_ADD:
4543 case TargetOpcode::G_SUB:
4544 case TargetOpcode::G_PTR_ADD:
4547 return selectG_ADD_SUB(
I);
4548 case TargetOpcode::G_UADDO:
4549 case TargetOpcode::G_USUBO:
4550 case TargetOpcode::G_UADDE:
4551 case TargetOpcode::G_USUBE:
4552 return selectG_UADDO_USUBO_UADDE_USUBE(
I);
4553 case AMDGPU::G_AMDGPU_MAD_U64_U32:
4554 case AMDGPU::G_AMDGPU_MAD_I64_I32:
4555 return selectG_AMDGPU_MAD_64_32(
I);
4556 case TargetOpcode::G_INTTOPTR:
4557 case TargetOpcode::G_BITCAST:
4558 case TargetOpcode::G_PTRTOINT:
4559 case TargetOpcode::G_FREEZE:
4560 return selectCOPY(
I);
4561 case TargetOpcode::G_FNEG:
4564 return selectG_FNEG(
I);
4565 case TargetOpcode::G_FABS:
4568 return selectG_FABS(
I);
4569 case TargetOpcode::G_EXTRACT:
4570 return selectG_EXTRACT(
I);
4571 case TargetOpcode::G_MERGE_VALUES:
4572 case TargetOpcode::G_CONCAT_VECTORS:
4573 return selectG_MERGE_VALUES(
I);
4574 case TargetOpcode::G_UNMERGE_VALUES:
4575 return selectG_UNMERGE_VALUES(
I);
4576 case TargetOpcode::G_BUILD_VECTOR:
4577 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
4578 return selectG_BUILD_VECTOR(
I);
4579 case TargetOpcode::G_IMPLICIT_DEF:
4580 return selectG_IMPLICIT_DEF(
I);
4581 case TargetOpcode::G_INSERT:
4582 return selectG_INSERT(
I);
4583 case TargetOpcode::G_INTRINSIC:
4584 case TargetOpcode::G_INTRINSIC_CONVERGENT:
4585 return selectG_INTRINSIC(
I);
4586 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
4587 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
4588 return selectG_INTRINSIC_W_SIDE_EFFECTS(
I);
4589 case TargetOpcode::G_ICMP:
4590 case TargetOpcode::G_FCMP:
4591 if (selectG_ICMP_or_FCMP(
I))
4594 case TargetOpcode::G_LOAD:
4595 case TargetOpcode::G_ZEXTLOAD:
4596 case TargetOpcode::G_SEXTLOAD:
4597 case TargetOpcode::G_STORE:
4598 case TargetOpcode::G_ATOMIC_CMPXCHG:
4599 case TargetOpcode::G_ATOMICRMW_XCHG:
4600 case TargetOpcode::G_ATOMICRMW_ADD:
4601 case TargetOpcode::G_ATOMICRMW_SUB:
4602 case TargetOpcode::G_ATOMICRMW_AND:
4603 case TargetOpcode::G_ATOMICRMW_OR:
4604 case TargetOpcode::G_ATOMICRMW_XOR:
4605 case TargetOpcode::G_ATOMICRMW_MIN:
4606 case TargetOpcode::G_ATOMICRMW_MAX:
4607 case TargetOpcode::G_ATOMICRMW_UMIN:
4608 case TargetOpcode::G_ATOMICRMW_UMAX:
4609 case TargetOpcode::G_ATOMICRMW_UINC_WRAP:
4610 case TargetOpcode::G_ATOMICRMW_UDEC_WRAP:
4611 case TargetOpcode::G_ATOMICRMW_USUB_COND:
4612 case TargetOpcode::G_ATOMICRMW_USUB_SAT:
4613 case TargetOpcode::G_ATOMICRMW_FADD:
4614 case TargetOpcode::G_ATOMICRMW_FMIN:
4615 case TargetOpcode::G_ATOMICRMW_FMAX:
4616 return selectG_LOAD_STORE_ATOMICRMW(
I);
4617 case TargetOpcode::G_SELECT:
4618 return selectG_SELECT(
I);
4619 case TargetOpcode::G_TRUNC:
4620 return selectG_TRUNC(
I);
4621 case TargetOpcode::G_SEXT:
4622 case TargetOpcode::G_ZEXT:
4623 case TargetOpcode::G_ANYEXT:
4624 case TargetOpcode::G_SEXT_INREG:
4628 if (MRI->getType(
I.getOperand(1).getReg()) !=
LLT::scalar(1) &&
4631 return selectG_SZA_EXT(
I);
4632 case TargetOpcode::G_FPEXT:
4633 if (selectG_FPEXT(
I))
4636 case TargetOpcode::G_BRCOND:
4637 return selectG_BRCOND(
I);
4638 case TargetOpcode::G_GLOBAL_VALUE:
4639 return selectG_GLOBAL_VALUE(
I);
4640 case TargetOpcode::G_PTRMASK:
4641 return selectG_PTRMASK(
I);
4642 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4643 return selectG_EXTRACT_VECTOR_ELT(
I);
4644 case TargetOpcode::G_INSERT_VECTOR_ELT:
4645 return selectG_INSERT_VECTOR_ELT(
I);
4646 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD:
4647 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16:
4648 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET:
4649 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE:
4650 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16: {
4653 assert(Intr &&
"not an image intrinsic with image pseudo");
4654 return selectImageIntrinsic(
I, Intr);
4656 case AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY:
4657 case AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY:
4658 case AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY:
4659 return selectBVHIntersectRayIntrinsic(
I);
4660 case AMDGPU::G_SBFX:
4661 case AMDGPU::G_UBFX:
4662 return selectG_SBFX_UBFX(
I);
4663 case AMDGPU::G_SI_CALL:
4664 I.setDesc(TII.get(AMDGPU::SI_CALL));
4666 case AMDGPU::G_AMDGPU_WAVE_ADDRESS:
4667 return selectWaveAddress(
I);
4668 case AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_RETURN: {
4669 I.setDesc(TII.get(AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN));
4672 case AMDGPU::G_STACKRESTORE:
4673 return selectStackRestore(
I);
4675 return selectPHI(
I);
4676 case AMDGPU::G_AMDGPU_COPY_SCC_VCC:
4677 return selectCOPY_SCC_VCC(
I);
4678 case AMDGPU::G_AMDGPU_COPY_VCC_SCC:
4679 return selectCOPY_VCC_SCC(
I);
4680 case AMDGPU::G_AMDGPU_READANYLANE:
4681 return selectReadAnyLane(
I);
4682 case TargetOpcode::G_CONSTANT:
4683 case TargetOpcode::G_FCONSTANT:
4691AMDGPUInstructionSelector::selectVCSRC(
MachineOperand &Root)
const {
4698std::pair<Register, unsigned> AMDGPUInstructionSelector::selectVOP3ModsImpl(
4699 Register Src,
bool IsCanonicalizing,
bool AllowAbs,
bool OpSel)
const {
4703 if (
MI->getOpcode() == AMDGPU::G_FNEG) {
4704 Src =
MI->getOperand(1).getReg();
4707 }
else if (
MI->getOpcode() == AMDGPU::G_FSUB && IsCanonicalizing) {
4712 if (
LHS &&
LHS->isZero()) {
4714 Src =
MI->getOperand(2).getReg();
4718 if (AllowAbs &&
MI->getOpcode() == AMDGPU::G_FABS) {
4719 Src =
MI->getOperand(1).getReg();
4726 return std::pair(Src, Mods);
4729std::pair<Register, unsigned>
4730AMDGPUInstructionSelector::selectVOP3PModsF32Impl(
Register Src)
const {
4732 std::tie(Src, Mods) = selectVOP3ModsImpl(Src);
4734 return std::pair(Src, Mods);
4737Register AMDGPUInstructionSelector::copyToVGPRIfSrcFolded(
4739 bool ForceVGPR)
const {
4740 if ((Mods != 0 || ForceVGPR) &&
4741 RBI.getRegBank(Src, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID) {
4748 TII.
get(AMDGPU::COPY), VGPRSrc)
4760AMDGPUInstructionSelector::widenSrcIfVGPR16(
Register Src,
4762 if (!Subtarget->useRealTrue16Insts() || MRI->getType(Src) !=
LLT::scalar(16))
4765 const RegisterBank *SrcRB = RBI.getRegBank(Src, *MRI, TRI);
4766 if (!SrcRB || SrcRB->
getID() != AMDGPU::VGPRRegBankID)
4769 MachineIRBuilder
B(*InsertPt);
4771 Register ImpDefReg = MRI->createVirtualRegister(&AMDGPU::VGPR_16RegClass);
4772 B.buildInstr(TargetOpcode::IMPLICIT_DEF).addDef(ImpDefReg);
4774 Register DstReg = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
4775 B.buildInstr(AMDGPU::REG_SEQUENCE)
4778 .addImm(AMDGPU::lo16)
4780 .addImm(AMDGPU::hi16);
4789AMDGPUInstructionSelector::selectVSRC0(
MachineOperand &Root)
const {
4791 [=](MachineInstrBuilder &MIB) { MIB.
add(Root); }
4796AMDGPUInstructionSelector::selectVOP3Mods0(
MachineOperand &Root)
const {
4799 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
4802 [=](MachineInstrBuilder &MIB) {
4803 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4805 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
4806 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4807 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4812AMDGPUInstructionSelector::selectVOP3BMods0(
MachineOperand &Root)
const {
4815 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
4820 [=](MachineInstrBuilder &MIB) {
4821 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4823 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
4824 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4825 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4830AMDGPUInstructionSelector::selectVOP3OMods(
MachineOperand &Root)
const {
4832 [=](MachineInstrBuilder &MIB) { MIB.
add(Root); },
4833 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4834 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4839AMDGPUInstructionSelector::selectVOP3Mods(
MachineOperand &Root)
const {
4842 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
4845 [=](MachineInstrBuilder &MIB) {
4846 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4848 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4853AMDGPUInstructionSelector::selectVOP3ModsNonCanonicalizing(
4857 std::tie(Src, Mods) =
4858 selectVOP3ModsImpl(Root.
getReg(),
false);
4861 [=](MachineInstrBuilder &MIB) {
4862 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4864 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4869AMDGPUInstructionSelector::selectVOP3BMods(
MachineOperand &Root)
const {
4872 std::tie(Src, Mods) =
4873 selectVOP3ModsImpl(Root.
getReg(),
true,
4877 [=](MachineInstrBuilder &MIB) {
4878 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4880 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4885AMDGPUInstructionSelector::selectVOP3NoMods(
MachineOperand &Root)
const {
4888 if (
Def->getOpcode() == AMDGPU::G_FNEG ||
Def->getOpcode() == AMDGPU::G_FABS)
4891 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
4916 if (
MI->getOpcode() != AMDGPU::G_TRUNC)
4921 return DstSize * 2 == SrcSize;
4927 if (
MI->getOpcode() != AMDGPU::G_LSHR)
4931 std::optional<ValueAndVReg> ShiftAmt;
4932 if (
mi_match(
MI->getOperand(0).getReg(), MRI,
4935 unsigned Shift = ShiftAmt->Value.getZExtValue();
4936 return Shift * 2 == SrcSize;
4944 if (
MI->getOpcode() != AMDGPU::G_SHL)
4948 std::optional<ValueAndVReg> ShiftAmt;
4949 if (
mi_match(
MI->getOperand(0).getReg(), MRI,
4952 unsigned Shift = ShiftAmt->Value.getZExtValue();
4953 return Shift * 2 == SrcSize;
4961 if (
MI->getOpcode() != AMDGPU::G_UNMERGE_VALUES)
4963 return MI->getNumOperands() == 3 &&
MI->getOperand(0).isDef() &&
4964 MI->getOperand(1).isDef() && !
MI->getOperand(2).isDef();
4972 if (
OpTy.isScalar())
4974 if (
OpTy.isVector() &&
OpTy.getNumElements() == 2)
5134static std::optional<std::pair<Register, SrcStatus>>
5139 unsigned Opc =
MI->getOpcode();
5143 case AMDGPU::G_BITCAST:
5144 return std::optional<std::pair<Register, SrcStatus>>(
5145 {
MI->getOperand(1).getReg(), Curr.second});
5147 if (
MI->getOperand(1).getReg().isPhysical())
5148 return std::nullopt;
5149 return std::optional<std::pair<Register, SrcStatus>>(
5150 {
MI->getOperand(1).getReg(), Curr.second});
5151 case AMDGPU::G_FNEG: {
5154 return std::nullopt;
5155 return std::optional<std::pair<Register, SrcStatus>>(
5156 {
MI->getOperand(1).getReg(), Stat});
5163 switch (Curr.second) {
5166 return std::optional<std::pair<Register, SrcStatus>>(
5169 if (Curr.first ==
MI->getOperand(0).getReg())
5170 return std::optional<std::pair<Register, SrcStatus>>(
5172 return std::optional<std::pair<Register, SrcStatus>>(
5184 return std::optional<std::pair<Register, SrcStatus>>(
5188 if (Curr.first ==
MI->getOperand(0).getReg())
5189 return std::optional<std::pair<Register, SrcStatus>>(
5191 return std::optional<std::pair<Register, SrcStatus>>(
5197 return std::optional<std::pair<Register, SrcStatus>>(
5202 return std::optional<std::pair<Register, SrcStatus>>(
5207 return std::optional<std::pair<Register, SrcStatus>>(
5212 return std::optional<std::pair<Register, SrcStatus>>(
5218 return std::nullopt;
5228 bool HasNeg =
false;
5230 bool HasOpsel =
true;
5235 unsigned Opc =
MI->getOpcode();
5237 if (
Opc == TargetOpcode::G_INTRINSIC) {
5240 if (IntrinsicID == Intrinsic::amdgcn_fdot2)
5267 while (
Depth <= MaxDepth && Curr.has_value()) {
5270 Statlist.push_back(Curr.value());
5277static std::pair<Register, SrcStatus>
5284 while (
Depth <= MaxDepth && Curr.has_value()) {
5290 LastSameOrNeg = Curr.value();
5295 return LastSameOrNeg;
5302 return Width1 == Width2;
5337 return isSameBitWidth(NewReg, RootReg, MRI) && IsHalfState(LoStat) &&
5338 IsHalfState(HiStat);
5341std::pair<Register, unsigned> AMDGPUInstructionSelector::selectVOP3PModsImpl(
5347 return {RootReg, Mods};
5350 SearchOptions SO(RootReg, MRI);
5363 if (MRI.getType(RootReg).getSizeInBits() == 128) {
5365 return {Stat.first, Mods};
5370 MI->getNumOperands() != 3 || (IsDOT && Subtarget->hasDOTOpSelHazard())) {
5372 return {Stat.first, Mods};
5378 if (StatlistHi.
empty()) {
5380 return {Stat.first, Mods};
5386 if (StatlistLo.
empty()) {
5388 return {Stat.first, Mods};
5391 for (
int I = StatlistHi.
size() - 1;
I >= 0;
I--) {
5392 for (
int J = StatlistLo.
size() - 1; J >= 0; J--) {
5393 if (StatlistHi[
I].first == StatlistLo[J].first &&
5395 StatlistHi[
I].first, RootReg, TII, MRI))
5396 return {StatlistHi[
I].first,
5397 updateMods(StatlistHi[
I].second, StatlistLo[J].second, Mods)};
5403 return {Stat.first, Mods};
5413 return RB->
getID() == RBNo;
5429 if (
checkRB(RootReg, AMDGPU::SGPRRegBankID, RBI, MRI,
TRI) ||
5430 checkRB(NewReg, AMDGPU::VGPRRegBankID, RBI, MRI,
TRI))
5440 TII.get(AMDGPU::COPY), DstReg)
5448AMDGPUInstructionSelector::selectVOP3PRetHelper(
MachineOperand &Root,
5453 std::tie(
Reg, Mods) = selectVOP3PModsImpl(Root.
getReg(), MRI, IsDOT);
5458 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
5459 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5464AMDGPUInstructionSelector::selectVOP3PMods(
MachineOperand &Root)
const {
5466 return selectVOP3PRetHelper(Root);
5470AMDGPUInstructionSelector::selectVOP3PModsDOT(
MachineOperand &Root)
const {
5472 return selectVOP3PRetHelper(Root,
true);
5476AMDGPUInstructionSelector::selectVOP3PNoModsDOT(
MachineOperand &Root)
const {
5480 std::tie(Src, Mods) = selectVOP3PModsImpl(Root.
getReg(), MRI,
true );
5484 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); }}};
5488AMDGPUInstructionSelector::selectVOP3PModsF32(
MachineOperand &Root)
const {
5491 std::tie(Src, Mods) = selectVOP3PModsF32Impl(Root.
getReg());
5494 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5495 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5500AMDGPUInstructionSelector::selectVOP3PNoModsF32(
MachineOperand &Root)
const {
5503 std::tie(Src, Mods) = selectVOP3PModsF32Impl(Root.
getReg());
5507 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); }}};
5511AMDGPUInstructionSelector::selectWMMAOpSelVOP3PMods(
5514 "expected i1 value");
5520 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5528 switch (Elts.
size()) {
5530 DstRegClass = &AMDGPU::VReg_256RegClass;
5533 DstRegClass = &AMDGPU::VReg_128RegClass;
5536 DstRegClass = &AMDGPU::VReg_64RegClass;
5543 auto MIB =
B.buildInstr(AMDGPU::REG_SEQUENCE)
5545 for (
unsigned i = 0; i < Elts.
size(); ++i) {
5556 if (ModOpcode == TargetOpcode::G_FNEG) {
5560 for (
auto El : Elts) {
5566 if (Elts.size() != NegAbsElts.
size()) {
5575 assert(ModOpcode == TargetOpcode::G_FABS);
5583AMDGPUInstructionSelector::selectWMMAModsF32NegAbs(
MachineOperand &Root)
const {
5592 MachineInstr *ElF32 = MRI->getVRegDef(BV->
getSourceReg(0));
5593 unsigned ModOpcode = (ElF32->
getOpcode() == AMDGPU::G_FNEG)
5610 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5611 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5615AMDGPUInstructionSelector::selectWMMAModsF16Neg(
MachineOperand &Root)
const {
5637 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5638 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5642AMDGPUInstructionSelector::selectWMMAModsF16NegAbs(
MachineOperand &Root)
const {
5650 MachineInstr *ElV2F16 = MRI->getVRegDef(CV->
getSourceReg(0));
5652 unsigned ModOpcode = (ElV2F16->
getOpcode() == AMDGPU::G_FNEG)
5671 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5672 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5676AMDGPUInstructionSelector::selectWMMAVISrc(
MachineOperand &Root)
const {
5677 std::optional<FPValueAndVReg> FPValReg;
5679 if (TII.isInlineConstant(FPValReg->Value)) {
5680 return {{[=](MachineInstrBuilder &MIB) {
5681 MIB.
addImm(FPValReg->Value.bitcastToAPInt().getSExtValue());
5691 if (TII.isInlineConstant(ICst)) {
5701AMDGPUInstructionSelector::selectSWMMACIndex8(
MachineOperand &Root)
const {
5707 std::optional<ValueAndVReg> ShiftAmt;
5709 MRI->getType(ShiftSrc).getSizeInBits() == 32 &&
5710 ShiftAmt->Value.getZExtValue() % 8 == 0) {
5711 Key = ShiftAmt->Value.getZExtValue() / 8;
5716 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5717 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5722AMDGPUInstructionSelector::selectSWMMACIndex16(
MachineOperand &Root)
const {
5729 std::optional<ValueAndVReg> ShiftAmt;
5731 MRI->getType(ShiftSrc).getSizeInBits() == 32 &&
5732 ShiftAmt->Value.getZExtValue() == 16) {
5738 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5739 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5744AMDGPUInstructionSelector::selectSWMMACIndex32(
MachineOperand &Root)
const {
5751 S32 = matchAnyExtendFromS32(Src);
5755 if (
Def->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) {
5760 Src =
Def->getOperand(2).getReg();
5767 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5768 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5773AMDGPUInstructionSelector::selectVOP3OpSelMods(
MachineOperand &Root)
const {
5776 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
5780 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5781 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5787AMDGPUInstructionSelector::selectVINTERPMods(
MachineOperand &Root)
const {
5790 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
5796 [=](MachineInstrBuilder &MIB) {
5798 copyToVGPRIfSrcFolded(Src, Mods, Root, MIB,
true));
5800 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
5805AMDGPUInstructionSelector::selectVINTERPModsHi(
MachineOperand &Root)
const {
5808 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
5814 [=](MachineInstrBuilder &MIB) {
5816 copyToVGPRIfSrcFolded(Src, Mods, Root, MIB,
true));
5818 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
5825bool AMDGPUInstructionSelector::selectScaleOffset(
MachineOperand &Root,
5827 bool IsSigned)
const {
5828 if (!Subtarget->hasScaleOffset())
5832 MachineMemOperand *MMO = *
MI.memoperands_begin();
5844 OffsetReg =
Def->Reg;
5859 m_BinOp(IsSigned ? AMDGPU::S_MUL_I64_I32_PSEUDO : AMDGPU::S_MUL_U64,
5863 (
Mul->getOpcode() == (IsSigned ? AMDGPU::G_AMDGPU_MAD_I64_I32
5864 : AMDGPU::G_AMDGPU_MAD_U64_U32) ||
5865 (IsSigned &&
Mul->getOpcode() == AMDGPU::G_AMDGPU_MAD_U64_U32 &&
5866 VT->signBitIsZero(
Mul->getOperand(2).getReg()))) &&
5879bool AMDGPUInstructionSelector::selectSmrdOffset(
MachineOperand &Root,
5883 bool *ScaleOffset)
const {
5890 getAddrModeInfo(*
MI, *MRI, AddrInfo);
5892 if (AddrInfo.
empty())
5895 const GEPInfo &GEPI = AddrInfo[0];
5896 std::optional<int64_t> EncodedImm;
5899 *ScaleOffset =
false;
5904 if (GEPI.SgprParts.size() == 1 && GEPI.Imm != 0 && EncodedImm &&
5905 AddrInfo.
size() > 1) {
5906 const GEPInfo &GEPI2 = AddrInfo[1];
5907 if (GEPI2.SgprParts.size() == 2 && GEPI2.Imm == 0) {
5908 Register OffsetReg = GEPI2.SgprParts[1];
5911 selectScaleOffset(Root, OffsetReg,
false );
5912 OffsetReg = matchZeroExtendFromS32OrS32(OffsetReg);
5914 Base = GEPI2.SgprParts[0];
5915 *SOffset = OffsetReg;
5924 auto SKnown =
VT->getKnownBits(*SOffset);
5925 if (*
Offset + SKnown.getMinValue().getSExtValue() < 0)
5937 if (
Offset && GEPI.SgprParts.size() == 1 && EncodedImm) {
5938 Base = GEPI.SgprParts[0];
5944 if (SOffset && GEPI.SgprParts.size() == 1 &&
isUInt<32>(GEPI.Imm) &&
5950 Base = GEPI.SgprParts[0];
5951 *SOffset = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
5952 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), *SOffset)
5957 if (SOffset && GEPI.SgprParts.size() && GEPI.Imm == 0) {
5958 Register OffsetReg = GEPI.SgprParts[1];
5960 *ScaleOffset = selectScaleOffset(Root, OffsetReg,
false );
5961 OffsetReg = matchZeroExtendFromS32OrS32(OffsetReg);
5963 Base = GEPI.SgprParts[0];
5964 *SOffset = OffsetReg;
5973AMDGPUInstructionSelector::selectSmrdImm(
MachineOperand &Root)
const {
5976 if (!selectSmrdOffset(Root,
Base,
nullptr, &
Offset,
5978 return std::nullopt;
5980 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
5981 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Offset); }}};
5985AMDGPUInstructionSelector::selectSmrdImm32(
MachineOperand &Root)
const {
5987 getAddrModeInfo(*Root.
getParent(), *MRI, AddrInfo);
5989 if (AddrInfo.
empty() || AddrInfo[0].SgprParts.size() != 1)
5990 return std::nullopt;
5992 const GEPInfo &GEPInfo = AddrInfo[0];
5993 Register PtrReg = GEPInfo.SgprParts[0];
5994 std::optional<int64_t> EncodedImm =
5997 return std::nullopt;
6000 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrReg); },
6001 [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); }
6006AMDGPUInstructionSelector::selectSmrdSgpr(
MachineOperand &Root)
const {
6009 if (!selectSmrdOffset(Root,
Base, &SOffset,
nullptr,
6011 return std::nullopt;
6014 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
6015 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
6016 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }}};
6020AMDGPUInstructionSelector::selectSmrdSgprImm(
MachineOperand &Root)
const {
6024 if (!selectSmrdOffset(Root,
Base, &SOffset, &
Offset, &ScaleOffset))
6025 return std::nullopt;
6028 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
6029 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
6031 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }}};
6034std::pair<Register, int> AMDGPUInstructionSelector::selectFlatOffsetImpl(
6040 if (!STI.hasFlatInstOffsets())
6044 int64_t ConstOffset;
6046 std::tie(PtrBase, ConstOffset, IsInBounds) =
6047 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
6053 if (ConstOffset == 0 ||
6055 !isFlatScratchBaseLegal(Root.
getReg())) ||
6059 unsigned AddrSpace = (*
MI->memoperands_begin())->getAddrSpace();
6060 if (!TII.isLegalFLATOffset(ConstOffset, AddrSpace, FlatVariant))
6063 return std::pair(PtrBase, ConstOffset);
6067AMDGPUInstructionSelector::selectFlatOffset(
MachineOperand &Root)
const {
6071 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6072 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6077AMDGPUInstructionSelector::selectGlobalOffset(
MachineOperand &Root)
const {
6078 auto PtrWithOffset =
6082 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6083 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6088AMDGPUInstructionSelector::selectScratchOffset(
MachineOperand &Root)
const {
6089 auto PtrWithOffset =
6093 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6094 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6100AMDGPUInstructionSelector::selectGlobalSAddr(
MachineOperand &Root,
6102 bool NeedIOffset)
const {
6105 int64_t ConstOffset;
6106 int64_t ImmOffset = 0;
6110 std::tie(PtrBase, ConstOffset, std::ignore) =
6111 getPtrBaseWithConstantOffset(Addr, *MRI);
6113 if (ConstOffset != 0) {
6118 ImmOffset = ConstOffset;
6121 if (isSGPR(PtrBaseDef->Reg)) {
6122 if (ConstOffset > 0) {
6128 int64_t SplitImmOffset = 0, RemainderOffset = ConstOffset;
6130 std::tie(SplitImmOffset, RemainderOffset) =
6135 if (Subtarget->hasSignedGVSOffset() ?
isInt<32>(RemainderOffset)
6140 MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6142 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32),
6144 .
addImm(RemainderOffset);
6148 [=](MachineInstrBuilder &MIB) {
6151 [=](MachineInstrBuilder &MIB) {
6154 [=](MachineInstrBuilder &MIB) { MIB.
addImm(SplitImmOffset); },
6155 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); },
6158 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrBase); },
6159 [=](MachineInstrBuilder &MIB) {
6162 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); },
6172 unsigned NumLiterals =
6173 !TII.isInlineConstant(APInt(32,
Lo_32(ConstOffset))) +
6174 !TII.isInlineConstant(APInt(32,
Hi_32(ConstOffset)));
6175 if (STI.getConstantBusLimit(AMDGPU::V_ADD_U32_e64) > NumLiterals)
6176 return std::nullopt;
6183 if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
6188 if (isSGPR(SAddr)) {
6189 Register PtrBaseOffset = AddrDef->MI->getOperand(2).getReg();
6193 bool ScaleOffset = selectScaleOffset(Root, PtrBaseOffset,
6194 Subtarget->hasSignedGVSOffset());
6195 if (
Register VOffset = matchExtendFromS32OrS32(
6196 PtrBaseOffset, Subtarget->hasSignedGVSOffset())) {
6198 return {{[=](MachineInstrBuilder &MIB) {
6201 [=](MachineInstrBuilder &MIB) {
6204 [=](MachineInstrBuilder &MIB) {
6207 [=](MachineInstrBuilder &MIB) {
6211 return {{[=](MachineInstrBuilder &MIB) {
6214 [=](MachineInstrBuilder &MIB) {
6217 [=](MachineInstrBuilder &MIB) {
6227 if (AddrDef->MI->getOpcode() == AMDGPU::G_IMPLICIT_DEF ||
6228 AddrDef->MI->getOpcode() == AMDGPU::G_CONSTANT || !isSGPR(AddrDef->Reg))
6229 return std::nullopt;
6235 Register VOffset = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6237 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32), VOffset)
6242 [=](MachineInstrBuilder &MIB) { MIB.
addReg(AddrDef->Reg); },
6243 [=](MachineInstrBuilder &MIB) { MIB.
addReg(VOffset); },
6244 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6245 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); }
6248 [=](MachineInstrBuilder &MIB) { MIB.
addReg(AddrDef->Reg); },
6249 [=](MachineInstrBuilder &MIB) { MIB.
addReg(VOffset); },
6250 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); }
6255AMDGPUInstructionSelector::selectGlobalSAddr(
MachineOperand &Root)
const {
6256 return selectGlobalSAddr(Root, 0);
6260AMDGPUInstructionSelector::selectGlobalSAddrCPol(
MachineOperand &Root)
const {
6266 return selectGlobalSAddr(Root, PassedCPol);
6270AMDGPUInstructionSelector::selectGlobalSAddrCPolM0(
MachineOperand &Root)
const {
6276 return selectGlobalSAddr(Root, PassedCPol);
6280AMDGPUInstructionSelector::selectGlobalSAddrGLC(
MachineOperand &Root)
const {
6285AMDGPUInstructionSelector::selectGlobalSAddrNoIOffset(
6292 return selectGlobalSAddr(Root, PassedCPol,
false);
6296AMDGPUInstructionSelector::selectGlobalSAddrNoIOffsetM0(
6303 return selectGlobalSAddr(Root, PassedCPol,
false);
6307AMDGPUInstructionSelector::selectScratchSAddr(
MachineOperand &Root)
const {
6310 int64_t ConstOffset;
6311 int64_t ImmOffset = 0;
6315 std::tie(PtrBase, ConstOffset, std::ignore) =
6316 getPtrBaseWithConstantOffset(Addr, *MRI);
6318 if (ConstOffset != 0 && isFlatScratchBaseLegal(Addr) &&
6322 ImmOffset = ConstOffset;
6326 if (AddrDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX) {
6327 int FI = AddrDef->MI->getOperand(1).
getIndex();
6330 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); }
6336 if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
6337 Register LHS = AddrDef->MI->getOperand(1).getReg();
6338 Register RHS = AddrDef->MI->getOperand(2).getReg();
6342 if (LHSDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX &&
6343 isSGPR(RHSDef->Reg)) {
6344 int FI = LHSDef->MI->getOperand(1).getIndex();
6348 SAddr = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
6350 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_ADD_I32), SAddr)
6358 return std::nullopt;
6361 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SAddr); },
6362 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); }
6367bool AMDGPUInstructionSelector::checkFlatScratchSVSSwizzleBug(
6369 if (!Subtarget->hasFlatScratchSVSSwizzleBug())
6375 auto VKnown =
VT->getKnownBits(VAddr);
6378 uint64_t VMax = VKnown.getMaxValue().getZExtValue();
6380 return (VMax & 3) + (
SMax & 3) >= 4;
6384AMDGPUInstructionSelector::selectScratchSVAddr(
MachineOperand &Root)
const {
6387 int64_t ConstOffset;
6388 int64_t ImmOffset = 0;
6392 std::tie(PtrBase, ConstOffset, std::ignore) =
6393 getPtrBaseWithConstantOffset(Addr, *MRI);
6396 if (ConstOffset != 0 &&
6400 ImmOffset = ConstOffset;
6404 if (AddrDef->MI->getOpcode() != AMDGPU::G_PTR_ADD)
6405 return std::nullopt;
6407 Register RHS = AddrDef->MI->getOperand(2).getReg();
6408 if (RBI.getRegBank(
RHS, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID)
6409 return std::nullopt;
6411 Register LHS = AddrDef->MI->getOperand(1).getReg();
6414 if (OrigAddr != Addr) {
6415 if (!isFlatScratchBaseLegalSVImm(OrigAddr))
6416 return std::nullopt;
6418 if (!isFlatScratchBaseLegalSV(OrigAddr))
6419 return std::nullopt;
6422 if (checkFlatScratchSVSSwizzleBug(
RHS,
LHS, ImmOffset))
6423 return std::nullopt;
6425 unsigned CPol = selectScaleOffset(Root,
RHS,
true )
6429 if (LHSDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX) {
6430 int FI = LHSDef->MI->getOperand(1).getIndex();
6432 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
RHS); },
6434 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6435 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }
6444 return std::nullopt;
6447 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
RHS); },
6448 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
LHS); },
6449 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6450 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }
6455AMDGPUInstructionSelector::selectMUBUFScratchOffen(
MachineOperand &Root)
const {
6459 const SIMachineFunctionInfo *
Info =
MF->getInfo<SIMachineFunctionInfo>();
6464 Register HighBits = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6469 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32),
6473 return {{[=](MachineInstrBuilder &MIB) {
6476 [=](MachineInstrBuilder &MIB) {
6479 [=](MachineInstrBuilder &MIB) {
6484 [=](MachineInstrBuilder &MIB) {
6493 std::optional<int> FI;
6497 int64_t ConstOffset;
6498 std::tie(PtrBase, ConstOffset, std::ignore) =
6499 getPtrBaseWithConstantOffset(VAddr, *MRI);
6501 if (ConstOffset != 0) {
6502 if (TII.isLegalMUBUFImmOffset(ConstOffset) &&
6503 (!STI.privateMemoryResourceIsRangeChecked() ||
6504 VT->signBitIsZero(PtrBase))) {
6515 return {{[=](MachineInstrBuilder &MIB) {
6518 [=](MachineInstrBuilder &MIB) {
6524 [=](MachineInstrBuilder &MIB) {
6529 [=](MachineInstrBuilder &MIB) {
6534bool AMDGPUInstructionSelector::isDSOffsetLegal(
Register Base,
6539 if (STI.hasUsableDSOffset() || STI.unsafeDSOffsetFoldingEnabled())
6544 return VT->signBitIsZero(
Base);
6547bool AMDGPUInstructionSelector::isDSOffset2Legal(
Register Base, int64_t Offset0,
6549 unsigned Size)
const {
6550 if (Offset0 %
Size != 0 || Offset1 %
Size != 0)
6555 if (STI.hasUsableDSOffset() || STI.unsafeDSOffsetFoldingEnabled())
6560 return VT->signBitIsZero(
Base);
6565 return Addr->
getOpcode() == TargetOpcode::G_OR ||
6566 (Addr->
getOpcode() == TargetOpcode::G_PTR_ADD &&
6573bool AMDGPUInstructionSelector::isFlatScratchBaseLegal(
Register Addr)
const {
6581 if (STI.hasSignedScratchOffsets())
6587 if (AddrMI->
getOpcode() == TargetOpcode::G_PTR_ADD) {
6588 std::optional<ValueAndVReg> RhsValReg =
6594 if (RhsValReg && RhsValReg->Value.getSExtValue() < 0 &&
6595 RhsValReg->Value.getSExtValue() > -0x40000000)
6599 return VT->signBitIsZero(
LHS);
6604bool AMDGPUInstructionSelector::isFlatScratchBaseLegalSV(
Register Addr)
const {
6612 if (STI.hasSignedScratchOffsets())
6617 return VT->signBitIsZero(
RHS) &&
VT->signBitIsZero(
LHS);
6622bool AMDGPUInstructionSelector::isFlatScratchBaseLegalSVImm(
6626 if (STI.hasSignedScratchOffsets())
6631 std::optional<DefinitionAndSourceRegister> BaseDef =
6633 std::optional<ValueAndVReg> RHSOffset =
6643 (RHSOffset->Value.getSExtValue() < 0 &&
6644 RHSOffset->Value.getSExtValue() > -0x40000000)))
6647 Register LHS = BaseDef->MI->getOperand(1).getReg();
6648 Register RHS = BaseDef->MI->getOperand(2).getReg();
6649 return VT->signBitIsZero(
RHS) &&
VT->signBitIsZero(
LHS);
6652bool AMDGPUInstructionSelector::isUnneededShiftMask(
const MachineInstr &
MI,
6653 unsigned ShAmtBits)
const {
6654 assert(
MI.getOpcode() == TargetOpcode::G_AND);
6656 std::optional<APInt>
RHS =
6661 if (
RHS->countr_one() >= ShAmtBits)
6664 const APInt &LHSKnownZeros =
VT->getKnownZeroes(
MI.getOperand(1).getReg());
6665 return (LHSKnownZeros | *
RHS).countr_one() >= ShAmtBits;
6669AMDGPUInstructionSelector::selectMUBUFScratchOffset(
6672 const SIMachineFunctionInfo *
Info =
MF->getInfo<SIMachineFunctionInfo>();
6674 std::optional<DefinitionAndSourceRegister>
Def =
6676 assert(Def &&
"this shouldn't be an optional result");
6681 [=](MachineInstrBuilder &MIB) {
6684 [=](MachineInstrBuilder &MIB) {
6687 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
6698 if (!TII.isLegalMUBUFImmOffset(
Offset))
6706 [=](MachineInstrBuilder &MIB) {
6709 [=](MachineInstrBuilder &MIB) {
6717 !TII.isLegalMUBUFImmOffset(
Offset))
6721 [=](MachineInstrBuilder &MIB) {
6724 [=](MachineInstrBuilder &MIB) {
6731std::pair<Register, unsigned>
6732AMDGPUInstructionSelector::selectDS1Addr1OffsetImpl(
6734 int64_t ConstAddr = 0;
6738 std::tie(PtrBase,
Offset, std::ignore) =
6739 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
6742 if (isDSOffsetLegal(PtrBase,
Offset)) {
6744 return std::pair(PtrBase,
Offset);
6753 return std::pair(Root.
getReg(), 0);
6757AMDGPUInstructionSelector::selectDS1Addr1Offset(
MachineOperand &Root)
const {
6760 std::tie(
Reg,
Offset) = selectDS1Addr1OffsetImpl(Root);
6762 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
6768AMDGPUInstructionSelector::selectDS64Bit4ByteAligned(
MachineOperand &Root)
const {
6769 return selectDSReadWrite2(Root, 4);
6773AMDGPUInstructionSelector::selectDS128Bit8ByteAligned(
MachineOperand &Root)
const {
6774 return selectDSReadWrite2(Root, 8);
6778AMDGPUInstructionSelector::selectDSReadWrite2(
MachineOperand &Root,
6779 unsigned Size)
const {
6784 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
6786 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Offset+1); }
6790std::pair<Register, unsigned>
6791AMDGPUInstructionSelector::selectDSReadWrite2Impl(
MachineOperand &Root,
6792 unsigned Size)
const {
6793 int64_t ConstAddr = 0;
6797 std::tie(PtrBase,
Offset, std::ignore) =
6798 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
6801 int64_t OffsetValue0 =
Offset;
6803 if (isDSOffset2Legal(PtrBase, OffsetValue0, OffsetValue1,
Size)) {
6805 return std::pair(PtrBase, OffsetValue0 /
Size);
6814 return std::pair(Root.
getReg(), 0);
6822std::tuple<Register, int64_t, bool>
6823AMDGPUInstructionSelector::getPtrBaseWithConstantOffset(
6826 if (RootI->
getOpcode() != TargetOpcode::G_PTR_ADD)
6827 return {Root, 0,
false};
6830 std::optional<ValueAndVReg> MaybeOffset =
6833 return {Root, 0,
false};
6853 B.buildInstr(AMDGPU::S_MOV_B32)
6856 B.buildInstr(AMDGPU::S_MOV_B32)
6863 B.buildInstr(AMDGPU::REG_SEQUENCE)
6866 .addImm(AMDGPU::sub0)
6868 .addImm(AMDGPU::sub1);
6873 B.buildInstr(AMDGPU::S_MOV_B64)
6878 B.buildInstr(AMDGPU::REG_SEQUENCE)
6881 .addImm(AMDGPU::sub0_sub1)
6883 .addImm(AMDGPU::sub2_sub3);
6890 uint64_t DefaultFormat =
TII.getDefaultRsrcDataFormat();
6899 uint64_t DefaultFormat =
TII.getDefaultRsrcDataFormat();
6906AMDGPUInstructionSelector::MUBUFAddressData
6907AMDGPUInstructionSelector::parseMUBUFAddress(
Register Src)
const {
6908 MUBUFAddressData
Data;
6914 std::tie(PtrBase,
Offset, std::ignore) =
6915 getPtrBaseWithConstantOffset(Src, *MRI);
6921 if (MachineInstr *InputAdd
6923 Data.N2 = InputAdd->getOperand(1).getReg();
6924 Data.N3 = InputAdd->getOperand(2).getReg();
6939bool AMDGPUInstructionSelector::shouldUseAddr64(MUBUFAddressData Addr)
const {
6945 const RegisterBank *N0Bank = RBI.getRegBank(Addr.N0, *MRI, TRI);
6946 return N0Bank->
getID() == AMDGPU::VGPRRegBankID;
6952void AMDGPUInstructionSelector::splitIllegalMUBUFOffset(
6954 if (TII.isLegalMUBUFImmOffset(ImmOffset))
6958 SOffset = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
6959 B.buildInstr(AMDGPU::S_MOV_B32)
6965bool AMDGPUInstructionSelector::selectMUBUFAddr64Impl(
6970 if (!STI.hasAddr64() || STI.useFlatForGlobal())
6973 MUBUFAddressData AddrData = parseMUBUFAddress(Root.
getReg());
6974 if (!shouldUseAddr64(AddrData))
6980 Offset = AddrData.Offset;
6986 if (RBI.getRegBank(N2, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
6988 if (RBI.getRegBank(N3, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
7001 }
else if (RBI.getRegBank(N0, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
7012 splitIllegalMUBUFOffset(
B, SOffset,
Offset);
7016bool AMDGPUInstructionSelector::selectMUBUFOffsetImpl(
7021 if (STI.useFlatForGlobal())
7024 MUBUFAddressData AddrData = parseMUBUFAddress(Root.
getReg());
7025 if (shouldUseAddr64(AddrData))
7031 Offset = AddrData.Offset;
7037 splitIllegalMUBUFOffset(
B, SOffset,
Offset);
7042AMDGPUInstructionSelector::selectMUBUFAddr64(
MachineOperand &Root)
const {
7048 if (!selectMUBUFAddr64Impl(Root, VAddr, RSrcReg, SOffset,
Offset))
7054 [=](MachineInstrBuilder &MIB) {
7057 [=](MachineInstrBuilder &MIB) {
7060 [=](MachineInstrBuilder &MIB) {
7063 else if (STI.hasRestrictedSOffset())
7064 MIB.
addReg(AMDGPU::SGPR_NULL);
7068 [=](MachineInstrBuilder &MIB) {
7078AMDGPUInstructionSelector::selectMUBUFOffset(
MachineOperand &Root)
const {
7083 if (!selectMUBUFOffsetImpl(Root, RSrcReg, SOffset,
Offset))
7087 [=](MachineInstrBuilder &MIB) {
7090 [=](MachineInstrBuilder &MIB) {
7093 else if (STI.hasRestrictedSOffset())
7094 MIB.
addReg(AMDGPU::SGPR_NULL);
7106AMDGPUInstructionSelector::selectBUFSOffset(
MachineOperand &Root)
const {
7111 SOffset = AMDGPU::SGPR_NULL;
7113 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); }}};
7117static std::optional<uint64_t>
7121 if (!OffsetVal || !
isInt<32>(*OffsetVal))
7122 return std::nullopt;
7123 return Lo_32(*OffsetVal);
7127AMDGPUInstructionSelector::selectSMRDBufferImm(
MachineOperand &Root)
const {
7128 std::optional<uint64_t> OffsetVal =
7133 std::optional<int64_t> EncodedImm =
7138 return {{ [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); } }};
7142AMDGPUInstructionSelector::selectSMRDBufferImm32(
MachineOperand &Root)
const {
7149 std::optional<int64_t> EncodedImm =
7154 return {{ [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); } }};
7158AMDGPUInstructionSelector::selectSMRDBufferSgprImm(
MachineOperand &Root)
const {
7166 return std::nullopt;
7168 std::optional<int64_t> EncodedOffset =
7171 return std::nullopt;
7173 assert(MRI->getType(SOffset).getSizeInBits() == 32);
7174 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
7175 [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedOffset); }}};
7178std::pair<Register, unsigned>
7179AMDGPUInstructionSelector::selectVOP3PMadMixModsImpl(
MachineOperand &Root,
7180 bool &Matched)
const {
7185 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
7195 const auto CheckAbsNeg = [&]() {
7200 std::tie(Src, ModsTmp) = selectVOP3ModsImpl(Src);
7240AMDGPUInstructionSelector::selectVOP3PMadMixModsExt(
7245 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7250 [=](MachineInstrBuilder &MIB) { MIB.
addReg(widenSrcIfVGPR16(Src, MIB)); },
7251 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
7256AMDGPUInstructionSelector::selectVOP3PMadMixMods(
MachineOperand &Root)
const {
7260 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7263 [=](MachineInstrBuilder &MIB) { MIB.
addReg(widenSrcIfVGPR16(Src, MIB)); },
7264 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
7269AMDGPUInstructionSelector::selectVOP3PMadMixModsExtNeg(
7274 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7279 [=](MachineInstrBuilder &MIB) { MIB.
addReg(widenSrcIfVGPR16(Src, MIB)); },
7280 [=](MachineInstrBuilder &MIB) {
7287AMDGPUInstructionSelector::selectVOP3PMadMixModsNeg(
7292 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7295 [=](MachineInstrBuilder &MIB) { MIB.
addReg(widenSrcIfVGPR16(Src, MIB)); },
7296 [=](MachineInstrBuilder &MIB) {
7302bool AMDGPUInstructionSelector::selectSBarrierSignalIsfirst(
7306 Register CCReg =
I.getOperand(0).getReg();
7311 BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM))
7312 .
addImm(
I.getOperand(2).getImm());
7316 I.eraseFromParent();
7317 return RBI.constrainGenericRegister(CCReg, AMDGPU::SReg_32_XM0_XEXECRegClass,
7321bool AMDGPUInstructionSelector::selectSGetBarrierState(
7325 const MachineOperand &BarOp =
I.getOperand(2);
7326 std::optional<int64_t> BarValImm =
7330 auto CopyMIB =
BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
7334 MachineInstrBuilder MIB;
7335 unsigned Opc = BarValImm ? AMDGPU::S_GET_BARRIER_STATE_IMM
7336 : AMDGPU::S_GET_BARRIER_STATE_M0;
7339 auto DstReg =
I.getOperand(0).getReg();
7341 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
7342 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
7348 I.eraseFromParent();
7353 if (HasInlineConst) {
7357 case Intrinsic::amdgcn_s_barrier_join:
7358 return AMDGPU::S_BARRIER_JOIN_IMM;
7359 case Intrinsic::amdgcn_s_wakeup_barrier:
7360 return AMDGPU::S_WAKEUP_BARRIER_IMM;
7361 case Intrinsic::amdgcn_s_get_named_barrier_state:
7362 return AMDGPU::S_GET_BARRIER_STATE_IMM;
7368 case Intrinsic::amdgcn_s_barrier_join:
7369 return AMDGPU::S_BARRIER_JOIN_M0;
7370 case Intrinsic::amdgcn_s_wakeup_barrier:
7371 return AMDGPU::S_WAKEUP_BARRIER_M0;
7372 case Intrinsic::amdgcn_s_get_named_barrier_state:
7373 return AMDGPU::S_GET_BARRIER_STATE_M0;
7378bool AMDGPUInstructionSelector::selectNamedBarrierInit(
7382 const MachineOperand &BarOp =
I.getOperand(1);
7383 const MachineOperand &CntOp =
I.getOperand(2);
7387 if (IntrID == Intrinsic::amdgcn_s_barrier_signal_var) {
7388 std::optional<int64_t> CntImm =
7390 if (CntImm && *CntImm == 0) {
7391 std::optional<int64_t> BarValImm =
7394 uint32_t BarID = *BarValImm & 0x3F;
7395 BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::S_BARRIER_SIGNAL_IMM))
7397 I.eraseFromParent();
7404 Register TmpReg1 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7411 Register TmpReg2 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7417 Register TmpReg3 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7418 constexpr unsigned ShAmt = 16;
7424 Register TmpReg4 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7434 unsigned Opc = IntrID == Intrinsic::amdgcn_s_barrier_init
7435 ? AMDGPU::S_BARRIER_INIT_M0
7436 : AMDGPU::S_BARRIER_SIGNAL_M0;
7437 MachineInstrBuilder MIB;
7440 I.eraseFromParent();
7444bool AMDGPUInstructionSelector::selectNamedBarrierInst(
7448 MachineOperand BarOp = IntrID == Intrinsic::amdgcn_s_get_named_barrier_state
7451 std::optional<int64_t> BarValImm =
7456 Register TmpReg1 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7462 auto CopyMIB =
BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
7467 MachineInstrBuilder MIB;
7471 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state) {
7472 auto DstReg =
I.getOperand(0).getReg();
7474 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
7475 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
7481 uint32_t BarId = *BarValImm & 0x3F;
7485 I.eraseFromParent();
7492 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
7493 "Expected G_CONSTANT");
7494 MIB.
addImm(
MI.getOperand(1).getCImm()->getSExtValue());
7500 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
7501 "Expected G_CONSTANT");
7502 MIB.
addImm(-
MI.getOperand(1).getCImm()->getSExtValue());
7508 const MachineOperand &
Op =
MI.getOperand(1);
7509 assert(
MI.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1);
7510 MIB.
addImm(
Op.getFPImm()->getValueAPF().bitcastToAPInt().getZExtValue());
7513void AMDGPUInstructionSelector::renderCountTrailingOnesImm(
7515 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
7516 "Expected G_CONSTANT");
7517 MIB.
addImm(
MI.getOperand(1).getCImm()->getValue().countTrailingOnes());
7525 const MachineOperand &
Op =
MI.getOperand(OpIdx);
7536 MIB.
addImm(
MI.getOperand(OpIdx).getImm() != 0);
7542 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7546void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_0_0(
7548 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7553void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_0_1(
7555 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7556 MIB.
addImm((
MI.getOperand(OpIdx).getImm() & 0x1)
7561void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_1_0(
7563 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7568void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_1_1(
7570 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7571 MIB.
addImm((
MI.getOperand(OpIdx).getImm() & 0x2)
7576void AMDGPUInstructionSelector::renderDstSelToOpSelXForm(
7578 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7583void AMDGPUInstructionSelector::renderSrcSelToOpSelXForm(
7585 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7590void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_2_0(
7592 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7597void AMDGPUInstructionSelector::renderDstSelToOpSel3XFormXForm(
7599 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7600 MIB.
addImm((
MI.getOperand(OpIdx).getImm() & 0x2)
7608 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7609 MIB.
addImm(
MI.getOperand(OpIdx).getImm() &
7617 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7618 const bool Swizzle =
MI.getOperand(OpIdx).getImm() &
7624void AMDGPUInstructionSelector::renderExtractCpolSetGLC(
7626 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7627 const uint32_t Cpol =
MI.getOperand(OpIdx).getImm() &
7636 const APFloat &APF =
MI.getOperand(1).getFPImm()->getValueAPF();
7638 assert(ExpVal != INT_MIN);
7649 MIB.
addImm((
MI.getOperand(OpIdx).getImm() + 3) % 4);
7656 if (
MI.getOperand(OpIdx).getImm())
7658 MIB.
addImm((int64_t)Mods);
7665 if (
MI.getOperand(OpIdx).getImm())
7667 MIB.
addImm((int64_t)Mods);
7673 unsigned Val =
MI.getOperand(OpIdx).getImm();
7681 MIB.
addImm((int64_t)Mods);
7687 uint32_t
V =
MI.getOperand(2).getImm();
7690 if (!Subtarget->hasSafeCUPrefetch())
7696void AMDGPUInstructionSelector::renderScaledMAIIntrinsicOperand(
7698 unsigned Val =
MI.getOperand(OpIdx).getImm();
7707bool AMDGPUInstructionSelector::isInlineImmediate(
const APInt &
Imm)
const {
7708 return TII.isInlineConstant(
Imm);
7711bool AMDGPUInstructionSelector::isInlineImmediate(
const APFloat &
Imm)
const {
7712 return TII.isInlineConstant(
Imm);
MachineInstrBuilder MachineInstrBuilder & DefMI
static unsigned getIntrinsicID(const SDNode *N)
#define GET_GLOBALISEL_PREDICATES_INIT
#define GET_GLOBALISEL_TEMPORARIES_INIT
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
static bool isShlHalf(const MachineInstr *MI, const MachineRegisterInfo &MRI)
Test if the MI is shift left with half bits, such as reg0:2n =G_SHL reg1:2n, CONST(n)
static bool isNoUnsignedWrap(MachineInstr *Addr)
static Register buildOffsetSrc(MachineIRBuilder &B, MachineRegisterInfo &MRI, const SIInstrInfo &TII, Register BasePtr)
unsigned getNamedBarrierOp(bool HasInlineConst, Intrinsic::ID IntrID)
static Register getLegalRegBank(Register NewReg, Register RootReg, MachineInstr &Use, const AMDGPURegisterBankInfo &RBI, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const SIInstrInfo &TII)
static bool checkRB(Register Reg, unsigned int RBNo, const AMDGPURegisterBankInfo &RBI, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI)
static unsigned updateMods(SrcStatus HiStat, SrcStatus LoStat, unsigned Mods)
static bool isTruncHalf(const MachineInstr *MI, const MachineRegisterInfo &MRI)
Test if the MI is truncating to half, such as reg0:n = G_TRUNC reg1:2n
static Register getWaveAddress(const MachineInstr *Def)
static bool isExtractHiElt(MachineRegisterInfo &MRI, Register In, Register &Out)
static bool shouldUseAndMask(unsigned Size, unsigned &Mask)
static std::pair< unsigned, uint8_t > BitOp3_Op(Register R, SmallVectorImpl< Register > &Src, const MachineRegisterInfo &MRI)
static TypeClass isVectorOfTwoOrScalar(Register Reg, const MachineRegisterInfo &MRI)
static bool isLaneMaskFromSameBlock(Register Reg, MachineRegisterInfo &MRI, MachineBasicBlock *MBB)
static bool isExtractLoElt(MachineRegisterInfo &MRI, Register In, Register &Out)
static bool parseTexFail(uint64_t TexFailCtrl, bool &TFE, bool &LWE, bool &IsTexFail)
static void addZeroImm(MachineInstrBuilder &MIB)
static unsigned gwsIntrinToOpcode(unsigned IntrID)
static bool isConstant(const MachineInstr &MI)
static bool isSameBitWidth(Register Reg1, Register Reg2, const MachineRegisterInfo &MRI)
static Register buildRegSequence(SmallVectorImpl< Register > &Elts, MachineInstr *InsertPt, MachineRegisterInfo &MRI)
static Register buildRSRC(MachineIRBuilder &B, MachineRegisterInfo &MRI, uint32_t FormatLo, uint32_t FormatHi, Register BasePtr)
Return a resource descriptor for use with an arbitrary 64-bit pointer.
static bool isAsyncLDSDMA(Intrinsic::ID Intr)
static std::pair< Register, unsigned > computeIndirectRegIndex(MachineRegisterInfo &MRI, const SIRegisterInfo &TRI, const TargetRegisterClass *SuperRC, Register IdxReg, unsigned EltSize, GISelValueTracking &ValueTracking)
Return the register to use for the index value, and the subregister to use for the indirectly accesse...
static unsigned getLogicalBitOpcode(unsigned Opc, bool Is64)
static std::pair< Register, SrcStatus > getLastSameOrNeg(Register Reg, const MachineRegisterInfo &MRI, SearchOptions SO, int MaxDepth=3)
static Register stripCopy(Register Reg, MachineRegisterInfo &MRI)
static std::optional< std::pair< Register, SrcStatus > > calcNextStatus(std::pair< Register, SrcStatus > Curr, const MachineRegisterInfo &MRI)
static Register stripBitCast(Register Reg, MachineRegisterInfo &MRI)
static std::optional< uint64_t > getConstantZext32Val(Register Reg, const MachineRegisterInfo &MRI)
Get an immediate that must be 32-bits, and treated as zero extended.
static bool isValidToPack(SrcStatus HiStat, SrcStatus LoStat, Register NewReg, Register RootReg, const SIInstrInfo &TII, const MachineRegisterInfo &MRI)
static int getV_CMPOpcode(CmpInst::Predicate P, unsigned Size, const GCNSubtarget &ST)
static SmallVector< std::pair< Register, SrcStatus > > getSrcStats(Register Reg, const MachineRegisterInfo &MRI, SearchOptions SO, int MaxDepth=3)
static bool isUnmergeHalf(const MachineInstr *MI, const MachineRegisterInfo &MRI)
Test function, if the MI is reg0:n, reg1:n = G_UNMERGE_VALUES reg2:2n
static SrcStatus getNegStatus(Register Reg, SrcStatus S, const MachineRegisterInfo &MRI)
static bool isVCmpResult(Register Reg, MachineRegisterInfo &MRI)
static Register buildAddr64RSrc(MachineIRBuilder &B, MachineRegisterInfo &MRI, const SIInstrInfo &TII, Register BasePtr)
static bool isLshrHalf(const MachineInstr *MI, const MachineRegisterInfo &MRI)
Test if the MI is logic shift right with half bits, such as reg0:2n =G_LSHR reg1:2n,...
static void selectWMMAModsNegAbs(unsigned ModOpcode, unsigned &Mods, SmallVectorImpl< Register > &Elts, Register &Src, MachineInstr *InsertPt, MachineRegisterInfo &MRI)
This file declares the targeting of the InstructionSelector class for AMDGPU.
AMDGPU Register Bank Select
This file declares the targeting of the RegisterBankInfo class for AMDGPU.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool isAllZeros(StringRef Arr)
Return true if the array is empty or all zeros.
Provides analysis for querying information about KnownBits during GISel passes.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static std::vector< std::pair< int, unsigned > > Swizzle(std::vector< std::pair< int, unsigned > > Src, R600InstrInfo::BankSwizzle Swz)
This is used to control valid status that current MI supports.
bool checkOptions(SrcStatus Stat) const
SearchOptions(Register Reg, const MachineRegisterInfo &MRI)
AMDGPUInstructionSelector(const GCNSubtarget &STI, const AMDGPURegisterBankInfo &RBI)
static const char * getName()
bool select(MachineInstr &I) override
Select the (possibly generic) instruction I to only use target-specific opcodes.
void setupMF(MachineFunction &MF, GISelValueTracking *VT, CodeGenCoverage *CoverageInfo, ProfileSummaryInfo *PSI, BlockFrequencyInfo *BFI) override
Setup per-MF executor state.
uint32_t getLDSSize() const
LLVM_READONLY int getExactLog2Abs() const
Class for arbitrary precision integers.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
int64_t getSExtValue() const
Get sign extended value.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ FCMP_TRUE
1 1 1 1 Always true (always folded)
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ ICMP_ULT
unsigned less than
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ ICMP_ULE
unsigned less or equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ FCMP_FALSE
0 0 0 0 Always false (always folded)
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
DILocation * get() const
Get the underlying DILocation.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
void checkSubtargetFeatures(const Function &F) const
Diagnose inconsistent subtarget features before attempting to codegen function F.
std::optional< SmallVector< std::function< void(MachineInstrBuilder &)>, 4 > > ComplexRendererFns
virtual void setupMF(MachineFunction &mf, GISelValueTracking *vt, CodeGenCoverage *covinfo=nullptr, ProfileSummaryInfo *psi=nullptr, BlockFrequencyInfo *bfi=nullptr)
Setup per-MF executor state.
CodeGenCoverage * CoverageInfo
Register getSourceReg(unsigned I) const
Returns the I'th source register.
unsigned getNumSources() const
Returns the number of source registers.
Represents a G_UNMERGE_VALUES.
unsigned getNumDefs() const
Returns the number of def registers.
Register getSourceReg() const
Get the unmerge source register.
constexpr bool isScalar() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
constexpr bool isVector() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr unsigned getAddressSpace() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
TypeSize getValue() const
int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const
Returns the value of the specified operand constraint if it is present.
bool hasSuperClassEq(const MCRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
unsigned getID() const
getID() - Return the register class ID number.
bool hasSubClassEq(const MCRegisterClass *RC) const
Returns true if RC is a sub-class of or equal to this class.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void setReturnAddressIsTaken(bool s)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Helper class to build MachineInstr.
const MachineInstrBuilder & setMemRefs(ArrayRef< MachineMemOperand * > MMOs) const
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
bool getFlag(MIFlag Flag) const
Return whether an MI flag is set.
unsigned getNumOperands() const
Retuns the total number of operands.
LLVM_ABI void tieOperands(unsigned DefIdx, unsigned UseIdx)
Add a tie between the register operands at DefIdx and UseIdx.
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
LocationSize getSize() const
Return the size in bytes of the memory reference.
unsigned getAddrSpace() const
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
const MachinePointerInfo & getPointerInfo() const
Flags getFlags() const
Return the raw flags of the source value,.
const Value * getValue() const
Return the base address of the memory access.
Align getBaseAlign() const
Return the minimum known alignment in bytes of the base address, without the offset.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
const ConstantInt * getCImm() const
void setImm(int64_t immVal)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
static MachineOperand CreateImm(int64_t Val)
bool isEarlyClobber() const
Register getReg() const
getReg - Returns the register number.
bool isInternalRead() const
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
const RegisterBank * getRegBankOrNull(Register Reg) const
Return the register bank of Reg, or null if Reg has not been assigned a register bank or has been ass...
LLVM_ABI Register cloneVirtualRegister(Register VReg, StringRef Name="")
Create and return a new virtual register in the function with the same attributes as the given regist...
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Analysis providing profile information.
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
This class implements the register bank concept.
unsigned getID() const
Get the identifier of this register bank.
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
static unsigned getDSShaderTypeValue(const MachineFunction &MF)
static unsigned getSubRegFromChannel(unsigned Channel, unsigned NumRegs=1)
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static bool isGenericOpcode(unsigned Opc)
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
A Use represents the edge between a Value definition and its users.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ PRIVATE_ADDRESS
Address space for private memory.
@ BUFFER_RESOURCE
Address space for 128-bit buffer resources.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
LLVM_READONLY const MIMGG16MappingInfo * getMIMGG16MappingInfo(unsigned G)
std::optional< int64_t > getSMRDEncodedLiteralOffset32(const MCSubtargetInfo &ST, int64_t ByteOffset)
bool isGFX12Plus(const MCSubtargetInfo &STI)
constexpr int64_t getNullPointerValue(unsigned AS)
Get the null pointer value for the given address space.
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, OpName NamedIdx)
int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding, unsigned VDataDwords, unsigned VAddrDwords, bool IndexedRsrc, bool IndexedSamp)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
bool hasSMRDSignedImmOffset(const MCSubtargetInfo &ST)
LLVM_READONLY int32_t getGlobalSaddrOp(uint32_t Opcode)
bool isGFX13Plus(const MCSubtargetInfo &STI)
bool isGFX11Plus(const MCSubtargetInfo &STI)
bool isGFX10Plus(const MCSubtargetInfo &STI)
std::optional< int64_t > getSMRDEncodedOffset(const MCSubtargetInfo &ST, int64_t ByteOffset, bool IsBuffer, bool HasSOffset)
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfo(unsigned DimEnum)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
Intrinsic::ID getIntrinsicID(const MachineInstr &I)
Return the intrinsic ID for opcodes with the G_AMDGPU_INTRIN_ prefix.
std::pair< Register, unsigned > getBaseWithConstantOffset(MachineRegisterInfo &MRI, Register Reg, GISelValueTracking *ValueTracking=nullptr, bool CheckNUW=false)
Returns base register and constant offset.
const ImageDimIntrinsicInfo * getImageDimIntrinsicInfo(unsigned Intr)
IndexMode
ARM Index Modes.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
operand_type_match m_Reg()
SpecificConstantMatch m_SpecificICst(const APInt &RequestedValue)
Matches a constant equal to RequestedValue.
GInstrBind< GBuildVector > m_GBuildVector(GBuildVector *&Inst)
GCstAndRegMatch m_GCst(std::optional< ValueAndVReg > &ValReg)
UnaryOp_match< SrcTy, TargetOpcode::COPY > m_Copy(SrcTy &&Src)
UnaryOp_match< SrcTy, TargetOpcode::G_ZEXT > m_GZExt(const SrcTy &Src)
BinaryOp_match< LHS, RHS, TargetOpcode::G_XOR, true > m_GXor(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_SEXT > m_GSExt(const SrcTy &Src)
UnaryOp_match< SrcTy, TargetOpcode::G_FPEXT > m_GFPExt(const SrcTy &Src)
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
ConstantMatch< APInt > m_ICst(APInt &Cst)
SpecificConstantMatch m_AllOnesInt()
BinaryOp_match< LHS, RHS, TargetOpcode::G_OR, true > m_GOr(const LHS &L, const RHS &R)
ICstOrSplatMatch< APInt > m_ICstOrSplat(APInt &Cst)
ImplicitDefMatch m_GImplicitDef()
GInstrBind< GConcatVectors > m_GConcatVectors(GConcatVectors *&Inst)
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
GInstrBind< GUnmerge > m_GUnmerge(GUnmerge *&Inst)
Instruction binders for ops with no operand-form matcher (constant-immediate or variadic-source ops).
BinaryOp_match< LHS, RHS, TargetOpcode::G_SUB > m_GSub(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_ASHR, false > m_GAShr(const LHS &L, const RHS &R)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
BinaryOp_match< LHS, RHS, TargetOpcode::G_PTR_ADD, false > m_GPtrAdd(const LHS &L, const RHS &R)
SpecificRegisterMatch m_SpecificReg(Register RequestedReg)
Matches a register only if it is equal to RequestedReg.
BinaryOp_match< LHS, RHS, TargetOpcode::G_SHL, false > m_GShl(const LHS &L, const RHS &R)
GFrameIndexMatch m_GFrameIndex(int &FI)
Or< Preds... > m_any_of(Preds &&... preds)
BinaryOp_match< LHS, RHS, TargetOpcode::G_AND, true > m_GAnd(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_BITCAST > m_GBitcast(const SrcTy &Src)
bind_ty< MachineInstr * > m_MInstr(MachineInstr *&MI)
UnaryOp_match< SrcTy, TargetOpcode::G_FNEG > m_GFNeg(const SrcTy &Src)
GFCstOrSplatGFCstMatch m_GFCstOrSplat(std::optional< FPValueAndVReg > &FPValReg)
UnaryOp_match< SrcTy, TargetOpcode::G_FABS > m_GFabs(const SrcTy &Src)
BinaryOp_match< LHS, RHS, TargetOpcode::G_LSHR, false > m_GLShr(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_ANYEXT > m_GAnyExt(const SrcTy &Src)
ShuffleVectorMatch< Src1Ty, Src2Ty > m_GShuffleVector(const Src1Ty &Src1, const Src2Ty &Src2, ArrayRef< int > &Mask)
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
BinaryOp_match< LHS, RHS, TargetOpcode::G_MUL, true > m_GMul(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_TRUNC > m_GTrunc(const SrcTy &Src)
auto m_BinOp()
Match an arbitrary binary operation and ignore it.
@ Lo16
Fixup[15:0] <- Target + Addend.
@ Hi16
Fixup[15:0] <- (Target + Addend + 0x8000) >> 16.
NodeAddr< DefNode * > Def
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI Register getFunctionLiveInPhysReg(MachineFunction &MF, const TargetInstrInfo &TII, MCRegister PhysReg, const TargetRegisterClass &RC, const DebugLoc &DL, LLT RegTy=LLT())
Return a virtual register corresponding to the incoming argument register PhysReg.
LLVM_ABI bool isBuildVectorAllZeros(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndef=false)
Return true if the specified instruction is a G_BUILD_VECTOR or G_BUILD_VECTOR_TRUNC where all of the...
LLVM_ABI Register constrainOperandRegClass(const MachineFunction &MF, const TargetRegisterInfo &TRI, MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const RegisterBankInfo &RBI, MachineInstr &InsertPt, const TargetRegisterClass &RegClass, MachineOperand &RegMO)
Constrain the Register operand OpIdx, so that it is now constrained to the TargetRegisterClass passed...
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
PointerUnion< const TargetRegisterClass *, const RegisterBank * > RegClassOrRegBank
Convenient type to represent either a register class or a register bank.
LLVM_ABI const ConstantFP * getConstantFPVRegVal(Register VReg, const MachineRegisterInfo &MRI)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI std::optional< APInt > getIConstantVRegVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT, return the corresponding value.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ 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.