29#include "llvm/IR/IntrinsicsAMDGPU.h"
32#define DEBUG_TYPE "amdgpu-isel"
37#define GET_GLOBALISEL_IMPL
38#define AMDGPUSubtarget GCNSubtarget
39#include "AMDGPUGenGlobalISel.inc"
40#undef GET_GLOBALISEL_IMPL
45 : TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()), RBI(RBI), STI(STI),
47#include
"AMDGPUGenGlobalISel.inc"
50#include
"AMDGPUGenGlobalISel.inc"
62 MRI = &
MF.getRegInfo();
70 return Def->getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS
71 ? Def->getOperand(1).getReg()
81 auto &RegClassOrBank = MRI.getRegClassOrRegBank(
Reg);
85 const LLT Ty = MRI.getType(
Reg);
94 return RB->
getID() == AMDGPU::VCCRegBankID;
97bool AMDGPUInstructionSelector::constrainCopyLikeIntrin(
MachineInstr &
MI,
98 unsigned NewOpc)
const {
99 MI.setDesc(TII.get(NewOpc));
111 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
113 TRI.getConstrainedRegClassForReg(SrcReg, *MRI);
114 if (!DstRC || DstRC != SrcRC)
117 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
118 !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI))
120 const MCInstrDesc &MCID =
MI.getDesc();
122 MI.getOperand(0).setIsEarlyClobber(
true);
127bool AMDGPUInstructionSelector::selectCOPY(
MachineInstr &
I)
const {
130 I.setDesc(TII.get(TargetOpcode::COPY));
132 Register DstReg =
I.getOperand(0).getReg();
133 Register SrcReg =
I.getOperand(1).getReg();
135 if (isVCC(DstReg, *MRI)) {
136 if (SrcReg == AMDGPU::SCC) {
138 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
141 return RBI.constrainGenericRegister(DstReg, *RC, *MRI);
144 if (!isVCC(SrcReg, *MRI)) {
146 if (!RBI.constrainGenericRegister(DstReg, *TRI.getBoolRC(), *MRI))
150 TRI.getConstrainedRegClassForReg(SrcReg, *MRI);
152 std::optional<ValueAndVReg> ConstVal =
156 STI.isWave64() ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
158 .
addImm(ConstVal->Value.getBoolValue() ? -1 : 0);
160 Register MaskedReg = MRI->createVirtualRegister(SrcRC);
167 assert(Subtarget->useRealTrue16Insts());
168 const int64_t NoMods = 0;
169 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::V_AND_B16_t16_e64), MaskedReg)
175 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::V_CMP_NE_U16_t16_e64), DstReg)
182 bool IsSGPR = TRI.isSGPRClass(SrcRC);
183 unsigned AndOpc = IsSGPR ? AMDGPU::S_AND_B32 : AMDGPU::V_AND_B32_e32;
190 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::V_CMP_NE_U32_e64), DstReg)
196 if (!MRI->getRegClassOrNull(SrcReg))
197 MRI->setRegClass(SrcReg, SrcRC);
203 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
204 if (RC && !RBI.constrainGenericRegister(DstReg, *RC, *MRI))
210 for (
const MachineOperand &MO :
I.operands()) {
211 if (MO.getReg().isPhysical())
215 TRI.getConstrainedRegClassForReg(MO.getReg(), *MRI);
218 RBI.constrainGenericRegister(MO.getReg(), *RC, *MRI);
223bool AMDGPUInstructionSelector::selectCOPY_SCC_VCC(
MachineInstr &
I)
const {
226 Register VCCReg =
I.getOperand(1).getReg();
230 if (STI.hasScalarCompareEq64()) {
232 STI.isWave64() ? AMDGPU::S_CMP_LG_U64 : AMDGPU::S_CMP_LG_U32;
235 Register DeadDst = MRI->createVirtualRegister(&AMDGPU::SReg_64RegClass);
236 Cmp =
BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_OR_B64), DeadDst)
243 Register DstReg =
I.getOperand(0).getReg();
247 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_32RegClass, *MRI);
250bool AMDGPUInstructionSelector::selectCOPY_VCC_SCC(
MachineInstr &
I)
const {
254 Register DstReg =
I.getOperand(0).getReg();
255 Register SrcReg =
I.getOperand(1).getReg();
256 std::optional<ValueAndVReg> Arg =
260 const int64_t
Value = Arg->Value.getZExtValue();
262 unsigned Opcode = STI.isWave64() ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
269 return RBI.constrainGenericRegister(DstReg, *TRI.getBoolRC(), *MRI);
275 unsigned SelectOpcode =
276 STI.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
286bool AMDGPUInstructionSelector::selectReadAnyLane(
MachineInstr &
I)
const {
287 Register DstReg =
I.getOperand(0).getReg();
288 Register SrcReg =
I.getOperand(1).getReg();
293 auto RFL =
BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
301bool AMDGPUInstructionSelector::selectPHI(
MachineInstr &
I)
const {
302 const Register DefReg =
I.getOperand(0).getReg();
303 const LLT DefTy = MRI->getType(DefReg);
315 MRI->getRegClassOrRegBank(DefReg);
326 DefRC = TRI.getRegClassForTypeOnBank(DefTy, RB);
335 for (
unsigned i = 1; i !=
I.getNumOperands(); i += 2) {
336 const Register SrcReg =
I.getOperand(i).getReg();
338 const RegisterBank *RB = MRI->getRegBankOrNull(SrcReg);
340 const LLT SrcTy = MRI->getType(SrcReg);
342 TRI.getRegClassForTypeOnBank(SrcTy, *RB);
343 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI))
348 I.setDesc(TII.get(TargetOpcode::PHI));
349 return RBI.constrainGenericRegister(DefReg, *DefRC, *MRI);
355 unsigned SubIdx)
const {
359 Register DstReg = MRI->createVirtualRegister(&SubRC);
362 unsigned ComposedSubIdx = TRI.composeSubRegIndices(MO.
getSubReg(), SubIdx);
364 BuildMI(*BB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::COPY), DstReg)
390 return Is64 ? AMDGPU::S_AND_B64 : AMDGPU::S_AND_B32;
392 return Is64 ? AMDGPU::S_OR_B64 : AMDGPU::S_OR_B32;
394 return Is64 ? AMDGPU::S_XOR_B64 : AMDGPU::S_XOR_B32;
400bool AMDGPUInstructionSelector::selectG_AND_OR_XOR(
MachineInstr &
I)
const {
401 Register DstReg =
I.getOperand(0).getReg();
402 unsigned Size = RBI.getSizeInBits(DstReg, *MRI, TRI);
404 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
405 if (DstRB->
getID() != AMDGPU::SGPRRegBankID &&
406 DstRB->
getID() != AMDGPU::VCCRegBankID)
409 bool Is64 =
Size > 32 || (DstRB->
getID() == AMDGPU::VCCRegBankID &&
422bool AMDGPUInstructionSelector::selectG_ADD_SUB(
MachineInstr &
I)
const {
425 Register DstReg =
I.getOperand(0).getReg();
427 LLT Ty = MRI->getType(DstReg);
432 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
433 const bool IsSALU = DstRB->
getID() == AMDGPU::SGPRRegBankID;
434 const bool Sub =
I.getOpcode() == TargetOpcode::G_SUB;
438 const unsigned Opc =
Sub ? AMDGPU::S_SUB_U32 : AMDGPU::S_ADD_U32;
441 .
add(
I.getOperand(1))
442 .
add(
I.getOperand(2))
449 if (STI.hasAddNoCarryInsts()) {
450 const unsigned Opc =
Sub ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_ADD_U32_e64;
451 I.setDesc(TII.get(
Opc));
458 const unsigned Opc =
Sub ? AMDGPU::V_SUB_CO_U32_e64 : AMDGPU::V_ADD_CO_U32_e64;
460 Register UnusedCarry = MRI->createVirtualRegister(TRI.getWaveMaskRegClass());
464 .
add(
I.getOperand(1))
465 .
add(
I.getOperand(2))
472 assert(!
Sub &&
"illegal sub should not reach here");
475 = IsSALU ? AMDGPU::SReg_64_XEXECRegClass : AMDGPU::VReg_64RegClass;
477 = IsSALU ? AMDGPU::SReg_32RegClass : AMDGPU::VGPR_32RegClass;
479 MachineOperand Lo1(getSubOperand64(
I.getOperand(1), HalfRC, AMDGPU::sub0));
480 MachineOperand Lo2(getSubOperand64(
I.getOperand(2), HalfRC, AMDGPU::sub0));
481 MachineOperand Hi1(getSubOperand64(
I.getOperand(1), HalfRC, AMDGPU::sub1));
482 MachineOperand Hi2(getSubOperand64(
I.getOperand(2), HalfRC, AMDGPU::sub1));
484 Register DstLo = MRI->createVirtualRegister(&HalfRC);
485 Register DstHi = MRI->createVirtualRegister(&HalfRC);
488 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_ADD_U32), DstLo)
491 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_ADDC_U32), DstHi)
497 Register CarryReg = MRI->createVirtualRegister(CarryRC);
498 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::V_ADD_CO_U32_e64), DstLo)
503 MachineInstr *Addc =
BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::V_ADDC_U32_e64), DstHi)
513 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
520 if (!RBI.constrainGenericRegister(DstReg, RC, *MRI))
527bool AMDGPUInstructionSelector::selectG_UADDO_USUBO_UADDE_USUBE(
532 Register Dst0Reg =
I.getOperand(0).getReg();
533 Register Dst1Reg =
I.getOperand(1).getReg();
534 const bool IsAdd =
I.getOpcode() == AMDGPU::G_UADDO ||
535 I.getOpcode() == AMDGPU::G_UADDE;
536 const bool HasCarryIn =
I.getOpcode() == AMDGPU::G_UADDE ||
537 I.getOpcode() == AMDGPU::G_USUBE;
539 if (isVCC(Dst1Reg, *MRI)) {
540 unsigned NoCarryOpc =
541 IsAdd ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_SUB_CO_U32_e64;
542 unsigned CarryOpc = IsAdd ? AMDGPU::V_ADDC_U32_e64 : AMDGPU::V_SUBB_U32_e64;
543 I.setDesc(TII.get(HasCarryIn ? CarryOpc : NoCarryOpc));
550 Register Src0Reg =
I.getOperand(2).getReg();
551 Register Src1Reg =
I.getOperand(3).getReg();
554 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::SCC)
555 .
addReg(
I.getOperand(4).getReg());
558 unsigned NoCarryOpc = IsAdd ? AMDGPU::S_ADD_U32 : AMDGPU::S_SUB_U32;
559 unsigned CarryOpc = IsAdd ? AMDGPU::S_ADDC_U32 : AMDGPU::S_SUBB_U32;
561 auto CarryInst =
BuildMI(*BB, &
I,
DL, TII.get(HasCarryIn ? CarryOpc : NoCarryOpc), Dst0Reg)
562 .
add(
I.getOperand(2))
563 .
add(
I.getOperand(3));
565 if (MRI->use_nodbg_empty(Dst1Reg)) {
566 CarryInst.setOperandDead(3);
568 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), Dst1Reg)
570 if (!MRI->getRegClassOrNull(Dst1Reg))
571 MRI->setRegClass(Dst1Reg, &AMDGPU::SReg_32RegClass);
574 if (!RBI.constrainGenericRegister(Dst0Reg, AMDGPU::SReg_32RegClass, *MRI) ||
575 !RBI.constrainGenericRegister(Src0Reg, AMDGPU::SReg_32RegClass, *MRI) ||
576 !RBI.constrainGenericRegister(Src1Reg, AMDGPU::SReg_32RegClass, *MRI))
580 !RBI.constrainGenericRegister(
I.getOperand(4).getReg(),
581 AMDGPU::SReg_32RegClass, *MRI))
588bool AMDGPUInstructionSelector::selectG_AMDGPU_MAD_64_32(
592 const bool IsUnsigned =
I.getOpcode() == AMDGPU::G_AMDGPU_MAD_U64_U32;
593 bool UseNoCarry = Subtarget->hasMadNC64_32Insts() &&
594 MRI->use_nodbg_empty(
I.getOperand(1).getReg());
597 if (Subtarget->hasMADIntraFwdBug())
598 Opc = IsUnsigned ? AMDGPU::V_MAD_U64_U32_gfx11_e64
599 : AMDGPU::V_MAD_I64_I32_gfx11_e64;
601 Opc = IsUnsigned ? AMDGPU::V_MAD_NC_U64_U32_e64
602 : AMDGPU::V_MAD_NC_I64_I32_e64;
604 Opc = IsUnsigned ? AMDGPU::V_MAD_U64_U32_e64 : AMDGPU::V_MAD_I64_I32_e64;
609 I.setDesc(TII.get(
Opc));
611 I.addImplicitDefUseOperands(*
MF);
612 I.getOperand(0).setIsEarlyClobber(
true);
618bool AMDGPUInstructionSelector::selectG_EXTRACT(
MachineInstr &
I)
const {
620 Register DstReg =
I.getOperand(0).getReg();
621 Register SrcReg =
I.getOperand(1).getReg();
622 LLT DstTy = MRI->getType(DstReg);
623 LLT SrcTy = MRI->getType(SrcReg);
628 unsigned Offset =
I.getOperand(2).getImm();
629 if (
Offset % 32 != 0 || DstSize > 128)
638 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
639 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
642 const RegisterBank *SrcBank = RBI.getRegBank(SrcReg, *MRI, TRI);
644 TRI.getRegClassForSizeOnBank(SrcSize, *SrcBank);
649 SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubReg);
654 *SrcRC,
I.getOperand(1));
656 BuildMI(*BB, &
I,
DL, TII.get(TargetOpcode::COPY), DstReg)
657 .
addReg(SrcReg, {}, SubReg);
663bool AMDGPUInstructionSelector::selectS16MergeToS32(
MachineInstr &
MI)
const {
668 LLT Src0Ty = MRI->getType(Src0);
669 LLT Src1Ty = MRI->getType(Src1);
671 const RegisterBank *DstBank = RBI.getRegBank(Dst, *MRI, TRI);
672 const RegisterBank *Src0Bank = RBI.getRegBank(Src0, *MRI, TRI);
673 const RegisterBank *Src1Bank = RBI.getRegBank(Src1, *MRI, TRI);
674 const bool IsVector = DstBank->
getID() == AMDGPU::VGPRRegBankID;
685 if (Src0Bank->
getID() == AMDGPU::VGPRRegBankID &&
686 Src1Bank->
getID() == AMDGPU::VGPRRegBankID &&
688 BuildMI(*BB,
MI,
DL, TII.get(TargetOpcode::REG_SEQUENCE), Dst)
694 if (!RBI.constrainGenericRegister(Dst, AMDGPU::VGPR_32RegClass, *MRI))
697 MI.eraseFromParent();
702 Register TmpReg = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
703 auto MIB =
BuildMI(*BB,
MI,
DL, TII.get(AMDGPU::V_AND_B32_e32), TmpReg)
708 MIB =
BuildMI(*BB,
MI,
DL, TII.get(AMDGPU::V_LSHL_OR_B32_e64), Dst)
714 MI.eraseFromParent();
737 unsigned Opc = AMDGPU::S_PACK_LL_B32_B16;
738 if (Shift0 && Shift1) {
739 Opc = AMDGPU::S_PACK_HH_B32_B16;
740 MI.getOperand(1).setReg(ShiftSrc0);
741 MI.getOperand(2).setReg(ShiftSrc1);
743 Opc = AMDGPU::S_PACK_LH_B32_B16;
744 MI.getOperand(2).setReg(ShiftSrc1);
748 if (ConstSrc1 && ConstSrc1->Value == 0) {
750 auto MIB =
BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_LSHR_B32), Dst)
755 MI.eraseFromParent();
759 if (STI.hasSPackHL()) {
760 Opc = AMDGPU::S_PACK_HL_B32_B16;
761 MI.getOperand(1).setReg(ShiftSrc0);
765 MI.setDesc(TII.get(
Opc));
772bool AMDGPUInstructionSelector::selectS16MergeToWide(
MachineInstr &
MI)
const {
776 const unsigned DstSize = MRI->getType(DstReg).getSizeInBits();
777 const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
778 const unsigned NumSrc =
MI.getNumOperands() - 1;
782 for (
unsigned I = 0;
I != NumSrc;
I += 2) {
783 Register S32 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
793 TRI.getRegClassForSizeOnBank(DstSize, *DstBank);
794 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
796 ArrayRef<int16_t> SubRegs = TRI.getRegSplitParts(DstRC, 4);
797 auto MIB =
BuildMI(*BB,
MI,
DL, TII.get(TargetOpcode::REG_SEQUENCE), DstReg);
798 for (
unsigned I = 0,
E = S32Regs.
size();
I !=
E; ++
I)
799 MIB.addReg(S32Regs[
I]).addImm(SubRegs[
I]);
801 MI.eraseFromParent();
805bool AMDGPUInstructionSelector::selectG_MERGE_VALUES(
MachineInstr &
MI)
const {
808 LLT DstTy = MRI->getType(DstReg);
809 LLT SrcTy = MRI->getType(
MI.getOperand(1).getReg());
815 MI.getNumOperands() == 3) {
816 return selectS16MergeToS32(
MI);
820 bool IsWideS16Merge = SrcSize == 16 && DstTy.
getSizeInBits() > 32 &&
824 if (IsWideS16Merge &&
825 RBI.getRegBank(DstReg, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID)
826 return selectS16MergeToWide(
MI);
834 const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
837 TRI.getRegClassForSizeOnBank(DstSize, *DstBank);
841 ArrayRef<int16_t> SubRegs = TRI.getRegSplitParts(DstRC, SrcSize / 8);
842 MachineInstrBuilder MIB =
843 BuildMI(*BB, &
MI,
DL, TII.get(TargetOpcode::REG_SEQUENCE), DstReg);
844 for (
int I = 0,
E =
MI.getNumOperands() - 1;
I !=
E; ++
I) {
845 MachineOperand &Src =
MI.getOperand(
I + 1);
851 TRI.getConstrainedRegClassForReg(SrcReg, *MRI);
852 if (SrcRC && !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI))
856 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
859 MI.eraseFromParent();
863bool AMDGPUInstructionSelector::selectG_UNMERGE_VALUES(
MachineInstr &
MI)
const {
865 const int NumDst =
MI.getNumOperands() - 1;
867 MachineOperand &Src =
MI.getOperand(NumDst);
871 LLT DstTy = MRI->getType(DstReg0);
872 LLT SrcTy = MRI->getType(SrcReg);
877 const RegisterBank *SrcBank = RBI.getRegBank(SrcReg, *MRI, TRI);
880 TRI.getRegClassForSizeOnBank(SrcSize, *SrcBank);
881 if (!SrcRC || !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI))
887 ArrayRef<int16_t> SubRegs = TRI.getRegSplitParts(SrcRC, DstSize / 8);
888 for (
int I = 0,
E = NumDst;
I !=
E; ++
I) {
891 if (SrcBank->
getID() == AMDGPU::SGPRRegBankID &&
892 SubRegs[
I] == AMDGPU::hi16) {
893 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_LSHR_B32), DstReg)
897 BuildMI(*BB, &
MI,
DL, TII.get(TargetOpcode::COPY), DstReg)
898 .
addReg(SrcReg, {}, SubRegs[
I]);
902 SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubRegs[
I]);
903 if (!SrcRC || !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI))
907 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
908 if (DstRC && !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
912 MI.eraseFromParent();
916bool AMDGPUInstructionSelector::selectG_BUILD_VECTOR(
MachineInstr &
MI)
const {
917 assert(
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC ||
918 MI.getOpcode() == AMDGPU::G_BUILD_VECTOR);
922 LLT SrcTy = MRI->getType(Src0);
926 if (
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR && SrcSize >= 32) {
927 return selectG_MERGE_VALUES(
MI);
934 (
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC &&
938 const RegisterBank *DstBank = RBI.getRegBank(Dst, *MRI, TRI);
939 if (DstBank->
getID() == AMDGPU::AGPRRegBankID)
942 assert(DstBank->
getID() == AMDGPU::SGPRRegBankID ||
943 DstBank->
getID() == AMDGPU::VGPRRegBankID);
944 const bool IsVector = DstBank->
getID() == AMDGPU::VGPRRegBankID;
957 const int64_t K0 = ConstSrc0->Value.getSExtValue();
958 const int64_t K1 = ConstSrc1->Value.getSExtValue();
959 uint32_t Lo16 =
static_cast<uint32_t
>(K0) & 0xffff;
960 uint32_t Hi16 =
static_cast<uint32_t
>(K1) & 0xffff;
961 uint32_t
Imm = Lo16 | (Hi16 << 16);
966 MI.eraseFromParent();
967 return RBI.constrainGenericRegister(Dst, AMDGPU::VGPR_32RegClass, *MRI);
972 MI.eraseFromParent();
973 return RBI.constrainGenericRegister(Dst, AMDGPU::SReg_32RegClass, *MRI);
984 if (Src1Def->
getOpcode() == AMDGPU::G_IMPLICIT_DEF) {
985 MI.setDesc(TII.get(AMDGPU::COPY));
988 IsVector ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
989 return RBI.constrainGenericRegister(Dst, RC, *MRI) &&
990 RBI.constrainGenericRegister(Src0, RC, *MRI);
993 return selectS16MergeToS32(
MI);
996bool AMDGPUInstructionSelector::selectG_IMPLICIT_DEF(
MachineInstr &
I)
const {
997 const MachineOperand &MO =
I.getOperand(0);
1002 TRI.getConstrainedRegClassForReg(MO.
getReg(), *MRI);
1003 if ((!RC && !MRI->getRegBankOrNull(MO.
getReg())) ||
1004 (RC && RBI.constrainGenericRegister(MO.
getReg(), *RC, *MRI))) {
1005 I.setDesc(TII.get(TargetOpcode::IMPLICIT_DEF));
1012bool AMDGPUInstructionSelector::selectG_INSERT(
MachineInstr &
I)
const {
1015 Register DstReg =
I.getOperand(0).getReg();
1016 Register Src0Reg =
I.getOperand(1).getReg();
1017 Register Src1Reg =
I.getOperand(2).getReg();
1018 LLT Src1Ty = MRI->getType(Src1Reg);
1020 unsigned DstSize = MRI->getType(DstReg).getSizeInBits();
1023 int64_t
Offset =
I.getOperand(3).getImm();
1026 if (
Offset % 32 != 0 || InsSize % 32 != 0)
1033 unsigned SubReg = TRI.getSubRegFromChannel(
Offset / 32, InsSize / 32);
1034 if (SubReg == AMDGPU::NoSubRegister)
1037 const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
1039 TRI.getRegClassForSizeOnBank(DstSize, *DstBank);
1043 const RegisterBank *Src0Bank = RBI.getRegBank(Src0Reg, *MRI, TRI);
1044 const RegisterBank *Src1Bank = RBI.getRegBank(Src1Reg, *MRI, TRI);
1046 TRI.getRegClassForSizeOnBank(DstSize, *Src0Bank);
1048 TRI.getRegClassForSizeOnBank(InsSize, *Src1Bank);
1052 Src0RC = TRI.getSubClassWithSubReg(Src0RC, SubReg);
1053 if (!Src0RC || !Src1RC)
1056 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
1057 !RBI.constrainGenericRegister(Src0Reg, *Src0RC, *MRI) ||
1058 !RBI.constrainGenericRegister(Src1Reg, *Src1RC, *MRI))
1062 BuildMI(*BB, &
I,
DL, TII.get(TargetOpcode::INSERT_SUBREG), DstReg)
1067 I.eraseFromParent();
1071bool AMDGPUInstructionSelector::selectG_SBFX_UBFX(
MachineInstr &
MI)
const {
1074 Register OffsetReg =
MI.getOperand(2).getReg();
1075 Register WidthReg =
MI.getOperand(3).getReg();
1077 assert(RBI.getRegBank(DstReg, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID &&
1078 "scalar BFX instructions are expanded in regbankselect");
1079 assert(MRI->getType(
MI.getOperand(0).getReg()).getSizeInBits() == 32 &&
1080 "64-bit vector BFX instructions are expanded in regbankselect");
1085 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SBFX;
1086 unsigned Opc = IsSigned ? AMDGPU::V_BFE_I32_e64 : AMDGPU::V_BFE_U32_e64;
1091 MI.eraseFromParent();
1096bool AMDGPUInstructionSelector::selectInterpP1F16(
MachineInstr &
MI)
const {
1097 if (STI.getLDSBankCount() != 16)
1103 if (!RBI.constrainGenericRegister(M0Val, AMDGPU::SReg_32RegClass, *MRI) ||
1104 !RBI.constrainGenericRegister(Dst, AMDGPU::VGPR_32RegClass, *MRI) ||
1105 !RBI.constrainGenericRegister(Src0, AMDGPU::VGPR_32RegClass, *MRI))
1115 Register InterpMov = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
1121 BuildMI(*
MBB, &
MI,
DL, TII.get(AMDGPU::V_INTERP_MOV_F32), InterpMov)
1124 .
addImm(
MI.getOperand(3).getImm());
1137 MI.eraseFromParent();
1146bool AMDGPUInstructionSelector::selectWritelane(
MachineInstr &
MI)
const {
1148 if (STI.getConstantBusLimit(AMDGPU::V_WRITELANE_B32) > 1)
1155 Register LaneSelect =
MI.getOperand(3).getReg();
1158 auto MIB =
BuildMI(*
MBB, &
MI,
DL, TII.get(AMDGPU::V_WRITELANE_B32), VDst);
1160 std::optional<ValueAndVReg> ConstSelect =
1166 MIB.
addImm(ConstSelect->Value.getSExtValue() &
1169 std::optional<ValueAndVReg> ConstVal =
1175 STI.hasInv2PiInlineImm())) {
1176 MIB.
addImm(ConstVal->Value.getSExtValue());
1184 RBI.constrainGenericRegister(LaneSelect, AMDGPU::SReg_32_XM0RegClass, *MRI);
1186 BuildMI(*
MBB, *MIB,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
1194 MI.eraseFromParent();
1201bool AMDGPUInstructionSelector::selectDivScale(
MachineInstr &
MI)
const {
1205 LLT Ty = MRI->getType(Dst0);
1208 Opc = AMDGPU::V_DIV_SCALE_F32_e64;
1210 Opc = AMDGPU::V_DIV_SCALE_F64_e64;
1221 unsigned ChooseDenom =
MI.getOperand(5).getImm();
1223 Register Src0 = ChooseDenom != 0 ? Numer : Denom;
1236 MI.eraseFromParent();
1241bool AMDGPUInstructionSelector::selectG_INTRINSIC(
MachineInstr &
I)
const {
1243 switch (IntrinsicID) {
1244 case Intrinsic::amdgcn_if_break: {
1249 BuildMI(*BB, &
I,
I.getDebugLoc(), TII.get(AMDGPU::SI_IF_BREAK))
1250 .
add(
I.getOperand(0))
1251 .
add(
I.getOperand(2))
1252 .
add(
I.getOperand(3));
1254 Register DstReg =
I.getOperand(0).getReg();
1255 Register Src0Reg =
I.getOperand(2).getReg();
1256 Register Src1Reg =
I.getOperand(3).getReg();
1258 I.eraseFromParent();
1261 MRI->setRegClass(
Reg, TRI.getWaveMaskRegClass());
1265 case Intrinsic::amdgcn_interp_p1_f16:
1266 return selectInterpP1F16(
I);
1267 case Intrinsic::amdgcn_wqm:
1268 return constrainCopyLikeIntrin(
I, AMDGPU::WQM);
1269 case Intrinsic::amdgcn_softwqm:
1270 return constrainCopyLikeIntrin(
I, AMDGPU::SOFT_WQM);
1271 case Intrinsic::amdgcn_strict_wwm:
1272 case Intrinsic::amdgcn_wwm:
1273 return constrainCopyLikeIntrin(
I, AMDGPU::STRICT_WWM);
1274 case Intrinsic::amdgcn_strict_wqm:
1275 return constrainCopyLikeIntrin(
I, AMDGPU::STRICT_WQM);
1276 case Intrinsic::amdgcn_writelane:
1277 return selectWritelane(
I);
1278 case Intrinsic::amdgcn_div_scale:
1279 return selectDivScale(
I);
1280 case Intrinsic::amdgcn_ballot:
1281 return selectBallot(
I);
1282 case Intrinsic::amdgcn_reloc_constant:
1283 return selectRelocConstant(
I);
1284 case Intrinsic::amdgcn_groupstaticsize:
1285 return selectGroupStaticSize(
I);
1286 case Intrinsic::returnaddress:
1287 return selectReturnAddress(
I);
1288 case Intrinsic::amdgcn_smfmac_f32_16x16x32_f16:
1289 case Intrinsic::amdgcn_smfmac_f32_32x32x16_f16:
1290 case Intrinsic::amdgcn_smfmac_f32_16x16x32_bf16:
1291 case Intrinsic::amdgcn_smfmac_f32_32x32x16_bf16:
1292 case Intrinsic::amdgcn_smfmac_i32_16x16x64_i8:
1293 case Intrinsic::amdgcn_smfmac_i32_32x32x32_i8:
1294 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_bf8:
1295 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_fp8:
1296 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_bf8:
1297 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_fp8:
1298 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_bf8:
1299 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_fp8:
1300 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_bf8:
1301 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_fp8:
1302 case Intrinsic::amdgcn_smfmac_f32_16x16x64_f16:
1303 case Intrinsic::amdgcn_smfmac_f32_32x32x32_f16:
1304 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf16:
1305 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf16:
1306 case Intrinsic::amdgcn_smfmac_i32_16x16x128_i8:
1307 case Intrinsic::amdgcn_smfmac_i32_32x32x64_i8:
1308 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_bf8:
1309 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_fp8:
1310 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_bf8:
1311 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_fp8:
1312 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_bf8:
1313 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_fp8:
1314 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_bf8:
1315 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_fp8:
1316 return selectSMFMACIntrin(
I);
1317 case Intrinsic::amdgcn_permlane16_swap:
1318 case Intrinsic::amdgcn_permlane32_swap:
1319 return selectPermlaneSwapIntrin(
I, IntrinsicID);
1320 case Intrinsic::amdgcn_wave_shuffle:
1321 return selectWaveShuffleIntrin(
I);
1332 if (
Size == 16 && !ST.has16BitInsts())
1335 const auto Select = [&](
unsigned S16Opc,
unsigned TrueS16Opc,
1336 unsigned FakeS16Opc,
unsigned S32Opc,
1339 return ST.hasTrue16BitInsts()
1340 ? ST.useRealTrue16Insts() ? TrueS16Opc : FakeS16Opc
1351 return Select(AMDGPU::V_CMP_NE_U16_e64, AMDGPU::V_CMP_NE_U16_t16_e64,
1352 AMDGPU::V_CMP_NE_U16_fake16_e64, AMDGPU::V_CMP_NE_U32_e64,
1353 AMDGPU::V_CMP_NE_U64_e64);
1355 return Select(AMDGPU::V_CMP_EQ_U16_e64, AMDGPU::V_CMP_EQ_U16_t16_e64,
1356 AMDGPU::V_CMP_EQ_U16_fake16_e64, AMDGPU::V_CMP_EQ_U32_e64,
1357 AMDGPU::V_CMP_EQ_U64_e64);
1359 return Select(AMDGPU::V_CMP_GT_I16_e64, AMDGPU::V_CMP_GT_I16_t16_e64,
1360 AMDGPU::V_CMP_GT_I16_fake16_e64, AMDGPU::V_CMP_GT_I32_e64,
1361 AMDGPU::V_CMP_GT_I64_e64);
1363 return Select(AMDGPU::V_CMP_GE_I16_e64, AMDGPU::V_CMP_GE_I16_t16_e64,
1364 AMDGPU::V_CMP_GE_I16_fake16_e64, AMDGPU::V_CMP_GE_I32_e64,
1365 AMDGPU::V_CMP_GE_I64_e64);
1367 return Select(AMDGPU::V_CMP_LT_I16_e64, AMDGPU::V_CMP_LT_I16_t16_e64,
1368 AMDGPU::V_CMP_LT_I16_fake16_e64, AMDGPU::V_CMP_LT_I32_e64,
1369 AMDGPU::V_CMP_LT_I64_e64);
1371 return Select(AMDGPU::V_CMP_LE_I16_e64, AMDGPU::V_CMP_LE_I16_t16_e64,
1372 AMDGPU::V_CMP_LE_I16_fake16_e64, AMDGPU::V_CMP_LE_I32_e64,
1373 AMDGPU::V_CMP_LE_I64_e64);
1375 return Select(AMDGPU::V_CMP_GT_U16_e64, AMDGPU::V_CMP_GT_U16_t16_e64,
1376 AMDGPU::V_CMP_GT_U16_fake16_e64, AMDGPU::V_CMP_GT_U32_e64,
1377 AMDGPU::V_CMP_GT_U64_e64);
1379 return Select(AMDGPU::V_CMP_GE_U16_e64, AMDGPU::V_CMP_GE_U16_t16_e64,
1380 AMDGPU::V_CMP_GE_U16_fake16_e64, AMDGPU::V_CMP_GE_U32_e64,
1381 AMDGPU::V_CMP_GE_U64_e64);
1383 return Select(AMDGPU::V_CMP_LT_U16_e64, AMDGPU::V_CMP_LT_U16_t16_e64,
1384 AMDGPU::V_CMP_LT_U16_fake16_e64, AMDGPU::V_CMP_LT_U32_e64,
1385 AMDGPU::V_CMP_LT_U64_e64);
1387 return Select(AMDGPU::V_CMP_LE_U16_e64, AMDGPU::V_CMP_LE_U16_t16_e64,
1388 AMDGPU::V_CMP_LE_U16_fake16_e64, AMDGPU::V_CMP_LE_U32_e64,
1389 AMDGPU::V_CMP_LE_U64_e64);
1392 return Select(AMDGPU::V_CMP_EQ_F16_e64, AMDGPU::V_CMP_EQ_F16_t16_e64,
1393 AMDGPU::V_CMP_EQ_F16_fake16_e64, AMDGPU::V_CMP_EQ_F32_e64,
1394 AMDGPU::V_CMP_EQ_F64_e64);
1396 return Select(AMDGPU::V_CMP_GT_F16_e64, AMDGPU::V_CMP_GT_F16_t16_e64,
1397 AMDGPU::V_CMP_GT_F16_fake16_e64, AMDGPU::V_CMP_GT_F32_e64,
1398 AMDGPU::V_CMP_GT_F64_e64);
1400 return Select(AMDGPU::V_CMP_GE_F16_e64, AMDGPU::V_CMP_GE_F16_t16_e64,
1401 AMDGPU::V_CMP_GE_F16_fake16_e64, AMDGPU::V_CMP_GE_F32_e64,
1402 AMDGPU::V_CMP_GE_F64_e64);
1404 return Select(AMDGPU::V_CMP_LT_F16_e64, AMDGPU::V_CMP_LT_F16_t16_e64,
1405 AMDGPU::V_CMP_LT_F16_fake16_e64, AMDGPU::V_CMP_LT_F32_e64,
1406 AMDGPU::V_CMP_LT_F64_e64);
1408 return Select(AMDGPU::V_CMP_LE_F16_e64, AMDGPU::V_CMP_LE_F16_t16_e64,
1409 AMDGPU::V_CMP_LE_F16_fake16_e64, AMDGPU::V_CMP_LE_F32_e64,
1410 AMDGPU::V_CMP_LE_F64_e64);
1412 return Select(AMDGPU::V_CMP_NEQ_F16_e64, AMDGPU::V_CMP_NEQ_F16_t16_e64,
1413 AMDGPU::V_CMP_NEQ_F16_fake16_e64, AMDGPU::V_CMP_NEQ_F32_e64,
1414 AMDGPU::V_CMP_NEQ_F64_e64);
1416 return Select(AMDGPU::V_CMP_O_F16_e64, AMDGPU::V_CMP_O_F16_t16_e64,
1417 AMDGPU::V_CMP_O_F16_fake16_e64, AMDGPU::V_CMP_O_F32_e64,
1418 AMDGPU::V_CMP_O_F64_e64);
1420 return Select(AMDGPU::V_CMP_U_F16_e64, AMDGPU::V_CMP_U_F16_t16_e64,
1421 AMDGPU::V_CMP_U_F16_fake16_e64, AMDGPU::V_CMP_U_F32_e64,
1422 AMDGPU::V_CMP_U_F64_e64);
1424 return Select(AMDGPU::V_CMP_NLG_F16_e64, AMDGPU::V_CMP_NLG_F16_t16_e64,
1425 AMDGPU::V_CMP_NLG_F16_fake16_e64, AMDGPU::V_CMP_NLG_F32_e64,
1426 AMDGPU::V_CMP_NLG_F64_e64);
1428 return Select(AMDGPU::V_CMP_NLE_F16_e64, AMDGPU::V_CMP_NLE_F16_t16_e64,
1429 AMDGPU::V_CMP_NLE_F16_fake16_e64, AMDGPU::V_CMP_NLE_F32_e64,
1430 AMDGPU::V_CMP_NLE_F64_e64);
1432 return Select(AMDGPU::V_CMP_NLT_F16_e64, AMDGPU::V_CMP_NLT_F16_t16_e64,
1433 AMDGPU::V_CMP_NLT_F16_fake16_e64, AMDGPU::V_CMP_NLT_F32_e64,
1434 AMDGPU::V_CMP_NLT_F64_e64);
1436 return Select(AMDGPU::V_CMP_NGE_F16_e64, AMDGPU::V_CMP_NGE_F16_t16_e64,
1437 AMDGPU::V_CMP_NGE_F16_fake16_e64, AMDGPU::V_CMP_NGE_F32_e64,
1438 AMDGPU::V_CMP_NGE_F64_e64);
1440 return Select(AMDGPU::V_CMP_NGT_F16_e64, AMDGPU::V_CMP_NGT_F16_t16_e64,
1441 AMDGPU::V_CMP_NGT_F16_fake16_e64, AMDGPU::V_CMP_NGT_F32_e64,
1442 AMDGPU::V_CMP_NGT_F64_e64);
1444 return Select(AMDGPU::V_CMP_NEQ_F16_e64, AMDGPU::V_CMP_NEQ_F16_t16_e64,
1445 AMDGPU::V_CMP_NEQ_F16_fake16_e64, AMDGPU::V_CMP_NEQ_F32_e64,
1446 AMDGPU::V_CMP_NEQ_F64_e64);
1448 return Select(AMDGPU::V_CMP_TRU_F16_e64, AMDGPU::V_CMP_TRU_F16_t16_e64,
1449 AMDGPU::V_CMP_TRU_F16_fake16_e64, AMDGPU::V_CMP_TRU_F32_e64,
1450 AMDGPU::V_CMP_TRU_F64_e64);
1452 return Select(AMDGPU::V_CMP_F_F16_e64, AMDGPU::V_CMP_F_F16_t16_e64,
1453 AMDGPU::V_CMP_F_F16_fake16_e64, AMDGPU::V_CMP_F_F32_e64,
1454 AMDGPU::V_CMP_F_F64_e64);
1459 unsigned Size)
const {
1461 if (!STI.hasScalarCompareEq64())
1466 return AMDGPU::S_CMP_LG_U64;
1468 return AMDGPU::S_CMP_EQ_U64;
1477 return AMDGPU::S_CMP_LG_U32;
1479 return AMDGPU::S_CMP_EQ_U32;
1481 return AMDGPU::S_CMP_GT_I32;
1483 return AMDGPU::S_CMP_GE_I32;
1485 return AMDGPU::S_CMP_LT_I32;
1487 return AMDGPU::S_CMP_LE_I32;
1489 return AMDGPU::S_CMP_GT_U32;
1491 return AMDGPU::S_CMP_GE_U32;
1493 return AMDGPU::S_CMP_LT_U32;
1495 return AMDGPU::S_CMP_LE_U32;
1497 return AMDGPU::S_CMP_EQ_F32;
1499 return AMDGPU::S_CMP_GT_F32;
1501 return AMDGPU::S_CMP_GE_F32;
1503 return AMDGPU::S_CMP_LT_F32;
1505 return AMDGPU::S_CMP_LE_F32;
1507 return AMDGPU::S_CMP_LG_F32;
1509 return AMDGPU::S_CMP_O_F32;
1511 return AMDGPU::S_CMP_U_F32;
1513 return AMDGPU::S_CMP_NLG_F32;
1515 return AMDGPU::S_CMP_NLE_F32;
1517 return AMDGPU::S_CMP_NLT_F32;
1519 return AMDGPU::S_CMP_NGE_F32;
1521 return AMDGPU::S_CMP_NGT_F32;
1523 return AMDGPU::S_CMP_NEQ_F32;
1530 if (!STI.hasSALUFloatInsts())
1535 return AMDGPU::S_CMP_EQ_F16;
1537 return AMDGPU::S_CMP_GT_F16;
1539 return AMDGPU::S_CMP_GE_F16;
1541 return AMDGPU::S_CMP_LT_F16;
1543 return AMDGPU::S_CMP_LE_F16;
1545 return AMDGPU::S_CMP_LG_F16;
1547 return AMDGPU::S_CMP_O_F16;
1549 return AMDGPU::S_CMP_U_F16;
1551 return AMDGPU::S_CMP_NLG_F16;
1553 return AMDGPU::S_CMP_NLE_F16;
1555 return AMDGPU::S_CMP_NLT_F16;
1557 return AMDGPU::S_CMP_NGE_F16;
1559 return AMDGPU::S_CMP_NGT_F16;
1561 return AMDGPU::S_CMP_NEQ_F16;
1570bool AMDGPUInstructionSelector::selectG_ICMP_or_FCMP(
MachineInstr &
I)
const {
1575 Register SrcReg =
I.getOperand(2).getReg();
1576 unsigned Size = RBI.getSizeInBits(SrcReg, *MRI, TRI);
1580 Register CCReg =
I.getOperand(0).getReg();
1581 if (!isVCC(CCReg, *MRI)) {
1582 int Opcode = getS_CMPOpcode(Pred,
Size);
1585 MachineInstr *ICmp =
BuildMI(*BB, &
I,
DL, TII.get(Opcode))
1586 .
add(
I.getOperand(2))
1587 .
add(
I.getOperand(3));
1588 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), CCReg)
1592 RBI.constrainGenericRegister(CCReg, AMDGPU::SReg_32RegClass, *MRI);
1593 I.eraseFromParent();
1597 if (
I.getOpcode() == AMDGPU::G_FCMP)
1604 MachineInstrBuilder ICmp;
1607 ICmp =
BuildMI(*BB, &
I,
DL, TII.get(Opcode),
I.getOperand(0).getReg())
1609 .
add(
I.getOperand(2))
1611 .
add(
I.getOperand(3))
1614 ICmp =
BuildMI(*BB, &
I,
DL, TII.get(Opcode),
I.getOperand(0).getReg())
1615 .
add(
I.getOperand(2))
1616 .
add(
I.getOperand(3));
1620 *TRI.getBoolRC(), *MRI);
1622 I.eraseFromParent();
1633 if (
MI->getParent() !=
MBB)
1637 if (
MI->getOpcode() == AMDGPU::COPY) {
1640 if (DstRB && SrcRB && DstRB->
getID() == AMDGPU::VCCRegBankID &&
1641 SrcRB->getID() == AMDGPU::SGPRRegBankID)
1646 if (
MI->getOpcode() == AMDGPU::G_AMDGPU_COPY_VCC_SCC)
1662bool AMDGPUInstructionSelector::selectBallot(
MachineInstr &
I)
const {
1665 Register DstReg =
I.getOperand(0).getReg();
1666 Register SrcReg =
I.getOperand(2).getReg();
1667 const unsigned BallotSize = MRI->getType(DstReg).getSizeInBits();
1668 const unsigned WaveSize = STI.getWavefrontSize();
1672 if (BallotSize != WaveSize && (BallotSize != 64 || WaveSize != 32))
1675 std::optional<ValueAndVReg> Arg =
1680 if (BallotSize != WaveSize) {
1681 Dst = MRI->createVirtualRegister(TRI.getBoolRC());
1685 const int64_t
Value = Arg->Value.getZExtValue();
1688 unsigned Opcode = WaveSize == 64 ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
1695 if (!RBI.constrainGenericRegister(Dst, *TRI.getBoolRC(), *MRI))
1701 if (!RBI.constrainGenericRegister(Dst, *TRI.getBoolRC(), *MRI))
1705 unsigned AndOpc = WaveSize == 64 ? AMDGPU::S_AND_B64 : AMDGPU::S_AND_B32;
1715 if (BallotSize != WaveSize) {
1716 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
1718 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
1725 I.eraseFromParent();
1729bool AMDGPUInstructionSelector::selectRelocConstant(
MachineInstr &
I)
const {
1730 Register DstReg =
I.getOperand(0).getReg();
1731 const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
1733 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
1736 const bool IsVALU = DstBank->
getID() == AMDGPU::VGPRRegBankID;
1738 Module *
M =
MF->getFunction().getParent();
1739 const MDNode *
Metadata =
I.getOperand(2).getMetadata();
1746 TII.get(IsVALU ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32), DstReg)
1749 I.eraseFromParent();
1753bool AMDGPUInstructionSelector::selectGroupStaticSize(
MachineInstr &
I)
const {
1756 Register DstReg =
I.getOperand(0).getReg();
1757 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
1758 unsigned Mov = DstRB->
getID() == AMDGPU::SGPRRegBankID ?
1759 AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1767 const SIMachineFunctionInfo *MFI =
MF->getInfo<SIMachineFunctionInfo>();
1770 Module *
M =
MF->getFunction().getParent();
1771 const GlobalValue *GV =
1776 I.eraseFromParent();
1781bool AMDGPUInstructionSelector::selectReturnAddress(
MachineInstr &
I)
const {
1786 Register DstReg =
I.getOperand(0).getReg();
1787 unsigned Depth =
I.getOperand(2).getImm();
1790 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
1792 !RBI.constrainGenericRegister(DstReg, *RC, *MRI))
1797 MF.getInfo<SIMachineFunctionInfo>()->isEntryFunction()) {
1800 I.eraseFromParent();
1804 MachineFrameInfo &MFI =
MF.getFrameInfo();
1809 Register ReturnAddrReg = TRI.getReturnAddressReg(
MF);
1811 AMDGPU::SReg_64RegClass,
DL);
1814 I.eraseFromParent();
1818bool AMDGPUInstructionSelector::selectEndCfIntrinsic(
MachineInstr &
MI)
const {
1822 BuildMI(*BB, &
MI,
MI.getDebugLoc(), TII.get(AMDGPU::SI_END_CF))
1823 .
add(
MI.getOperand(1));
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) {
2899bool AMDGPUInstructionSelector::selectG_FPEXT(
MachineInstr &
I)
const {
2900 if (!Subtarget->hasSALUFloatInsts())
2903 Register Dst =
I.getOperand(0).getReg();
2904 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
2905 if (DstRB->
getID() != AMDGPU::SGPRRegBankID)
2908 Register Src =
I.getOperand(1).getReg();
2914 BuildMI(*BB, &
I,
I.getDebugLoc(), TII.get(AMDGPU::S_CVT_HI_F32_F16), Dst)
2916 I.eraseFromParent();
2917 return RBI.constrainGenericRegister(Dst, AMDGPU::SReg_32RegClass, *MRI);
2924bool AMDGPUInstructionSelector::selectG_FNEG(
MachineInstr &
MI)
const {
2937 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
2938 if (DstRB->
getID() != AMDGPU::SGPRRegBankID ||
2943 MachineInstr *Fabs =
getOpcodeDef(TargetOpcode::G_FABS, Src, *MRI);
2947 if (!RBI.constrainGenericRegister(Src, AMDGPU::SReg_64RegClass, *MRI) ||
2948 !RBI.constrainGenericRegister(Dst, AMDGPU::SReg_64RegClass, *MRI))
2953 Register LoReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2954 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2955 Register ConstReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2956 Register OpReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2958 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), LoReg)
2959 .
addReg(Src, {}, AMDGPU::sub0);
2960 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), HiReg)
2961 .
addReg(Src, {}, AMDGPU::sub1);
2962 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_MOV_B32), ConstReg)
2966 unsigned Opc = Fabs ? AMDGPU::S_OR_B32 : AMDGPU::S_XOR_B32;
2971 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::REG_SEQUENCE), Dst)
2976 MI.eraseFromParent();
2981bool AMDGPUInstructionSelector::selectG_FABS(
MachineInstr &
MI)
const {
2983 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
2984 if (DstRB->
getID() != AMDGPU::SGPRRegBankID ||
2991 Register LoReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2992 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2993 Register ConstReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2994 Register OpReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2996 if (!RBI.constrainGenericRegister(Src, AMDGPU::SReg_64RegClass, *MRI) ||
2997 !RBI.constrainGenericRegister(Dst, AMDGPU::SReg_64RegClass, *MRI))
3000 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), LoReg)
3001 .
addReg(Src, {}, AMDGPU::sub0);
3002 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), HiReg)
3003 .
addReg(Src, {}, AMDGPU::sub1);
3004 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_MOV_B32), ConstReg)
3009 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_AND_B32), OpReg)
3013 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::REG_SEQUENCE), Dst)
3019 MI.eraseFromParent();
3024 return MI.getOpcode() == TargetOpcode::G_CONSTANT;
3030 unsigned OpNo =
Load.getOpcode() == AMDGPU::G_PREFETCH ? 0 : 1;
3031 const MachineInstr *PtrMI =
3032 MRI.getUniqueVRegDef(
Load.getOperand(OpNo).getReg());
3036 if (PtrMI->
getOpcode() != TargetOpcode::G_PTR_ADD)
3041 for (
unsigned i = 1; i != 3; ++i) {
3042 const MachineOperand &GEPOp = PtrMI->
getOperand(i);
3043 const MachineInstr *OpDef = MRI.getUniqueVRegDef(GEPOp.
getReg());
3048 assert(GEPInfo.Imm == 0);
3052 const RegisterBank *OpBank = RBI.getRegBank(GEPOp.
getReg(), MRI, TRI);
3053 if (OpBank->
getID() == AMDGPU::SGPRRegBankID)
3054 GEPInfo.SgprParts.push_back(GEPOp.
getReg());
3056 GEPInfo.VgprParts.push_back(GEPOp.
getReg());
3060 getAddrModeInfo(*PtrMI, MRI, AddrInfo);
3063bool AMDGPUInstructionSelector::isSGPR(
Register Reg)
const {
3064 return RBI.getRegBank(
Reg, *MRI, TRI)->getID() == AMDGPU::SGPRRegBankID;
3067bool AMDGPUInstructionSelector::isInstrUniform(
const MachineInstr &
MI)
const {
3068 if (!
MI.hasOneMemOperand())
3071 const MachineMemOperand *MMO = *
MI.memoperands_begin();
3084 if (
MI.getOpcode() == AMDGPU::G_PREFETCH)
3085 return RBI.getRegBank(
MI.getOperand(0).getReg(), *MRI, TRI)->getID() ==
3086 AMDGPU::SGPRRegBankID;
3089 return I &&
I->getMetadata(
"amdgpu.uniform");
3093 for (
const GEPInfo &GEPInfo : AddrInfo) {
3094 if (!GEPInfo.VgprParts.empty())
3100void AMDGPUInstructionSelector::initM0(
MachineInstr &
I)
const {
3101 const LLT PtrTy = MRI->getType(
I.getOperand(1).getReg());
3104 STI.ldsRequiresM0Init()) {
3108 BuildMI(*BB, &
I,
I.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), AMDGPU::M0)
3113bool AMDGPUInstructionSelector::selectG_LOAD_STORE_ATOMICRMW(
3120 if (
Reg.isPhysical())
3124 const unsigned Opcode =
MI.getOpcode();
3126 if (Opcode == AMDGPU::COPY)
3129 if (Opcode == AMDGPU::G_AND || Opcode == AMDGPU::G_OR ||
3130 Opcode == AMDGPU::G_XOR)
3135 return GI->is(Intrinsic::amdgcn_class);
3137 return Opcode == AMDGPU::G_ICMP || Opcode == AMDGPU::G_FCMP;
3140bool AMDGPUInstructionSelector::selectG_BRCOND(
MachineInstr &
I)
const {
3142 MachineOperand &CondOp =
I.getOperand(0);
3155 if (!isVCC(CondReg, *MRI)) {
3159 CondPhysReg = AMDGPU::SCC;
3160 BrOpcode = AMDGPU::S_CBRANCH_SCC1;
3161 ConstrainRC = &AMDGPU::SReg_32RegClass;
3168 const bool Is64 = STI.isWave64();
3169 const unsigned Opcode = Is64 ? AMDGPU::S_AND_B64 : AMDGPU::S_AND_B32;
3170 const Register Exec = Is64 ? AMDGPU::EXEC : AMDGPU::EXEC_LO;
3172 Register TmpReg = MRI->createVirtualRegister(TRI.getBoolRC());
3173 BuildMI(*BB, &
I,
DL, TII.get(Opcode), TmpReg)
3180 CondPhysReg = TRI.getVCC();
3181 BrOpcode = AMDGPU::S_CBRANCH_VCCNZ;
3182 ConstrainRC = TRI.getBoolRC();
3185 if (!MRI->getRegClassOrNull(CondReg))
3186 MRI->setRegClass(CondReg, ConstrainRC);
3188 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), CondPhysReg)
3191 .
addMBB(
I.getOperand(1).getMBB());
3193 I.eraseFromParent();
3197bool AMDGPUInstructionSelector::selectG_GLOBAL_VALUE(
3199 Register DstReg =
I.getOperand(0).getReg();
3200 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3201 const bool IsVGPR = DstRB->
getID() == AMDGPU::VGPRRegBankID;
3202 I.setDesc(TII.get(IsVGPR ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32));
3206 return RBI.constrainGenericRegister(
3207 DstReg, IsVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass, *MRI);
3210bool AMDGPUInstructionSelector::selectG_PTRMASK(
MachineInstr &
I)
const {
3211 Register DstReg =
I.getOperand(0).getReg();
3212 Register SrcReg =
I.getOperand(1).getReg();
3213 Register MaskReg =
I.getOperand(2).getReg();
3214 LLT Ty = MRI->getType(DstReg);
3215 LLT MaskTy = MRI->getType(MaskReg);
3219 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3220 const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
3221 const RegisterBank *MaskRB = RBI.getRegBank(MaskReg, *MRI, TRI);
3222 const bool IsVGPR = DstRB->
getID() == AMDGPU::VGPRRegBankID;
3228 APInt MaskOnes =
VT->getKnownOnes(MaskReg).zext(64);
3232 const bool CanCopyLow32 = (MaskOnes & MaskLo32) == MaskLo32;
3233 const bool CanCopyHi32 = (MaskOnes & MaskHi32) == MaskHi32;
3236 !CanCopyLow32 && !CanCopyHi32) {
3237 auto MIB =
BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_AND_B64), DstReg)
3241 I.eraseFromParent();
3246 unsigned NewOpc = IsVGPR ? AMDGPU::V_AND_B32_e64 : AMDGPU::S_AND_B32;
3248 = IsVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
3253 TRI.getRegClassForTypeOnBank(MaskTy, *MaskRB);
3255 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
3256 !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
3257 !RBI.constrainGenericRegister(MaskReg, *MaskRC, *MRI))
3262 "ptrmask should have been narrowed during legalize");
3264 auto NewOp =
BuildMI(*BB, &
I,
DL, TII.get(NewOpc), DstReg)
3270 I.eraseFromParent();
3274 Register HiReg = MRI->createVirtualRegister(&RegRC);
3275 Register LoReg = MRI->createVirtualRegister(&RegRC);
3278 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), LoReg)
3279 .
addReg(SrcReg, {}, AMDGPU::sub0);
3280 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), HiReg)
3281 .
addReg(SrcReg, {}, AMDGPU::sub1);
3290 Register MaskLo = MRI->createVirtualRegister(&RegRC);
3291 MaskedLo = MRI->createVirtualRegister(&RegRC);
3293 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), MaskLo)
3294 .
addReg(MaskReg, {}, AMDGPU::sub0);
3295 BuildMI(*BB, &
I,
DL, TII.get(NewOpc), MaskedLo)
3304 Register MaskHi = MRI->createVirtualRegister(&RegRC);
3305 MaskedHi = MRI->createVirtualRegister(&RegRC);
3307 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), MaskHi)
3308 .
addReg(MaskReg, {}, AMDGPU::sub1);
3309 BuildMI(*BB, &
I,
DL, TII.get(NewOpc), MaskedHi)
3314 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
3319 I.eraseFromParent();
3325static std::pair<Register, unsigned>
3332 std::tie(IdxBaseReg,
Offset) =
3334 if (IdxBaseReg == AMDGPU::NoRegister) {
3338 IdxBaseReg = IdxReg;
3345 if (
static_cast<unsigned>(
Offset) >= SubRegs.
size())
3346 return std::pair(IdxReg, SubRegs[0]);
3347 return std::pair(IdxBaseReg, SubRegs[
Offset]);
3350bool AMDGPUInstructionSelector::selectG_EXTRACT_VECTOR_ELT(
3356 LLT DstTy = MRI->getType(DstReg);
3357 LLT SrcTy = MRI->getType(SrcReg);
3359 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3360 const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
3361 const RegisterBank *IdxRB = RBI.getRegBank(IdxReg, *MRI, TRI);
3365 if (IdxRB->
getID() != AMDGPU::SGPRRegBankID)
3369 TRI.getRegClassForTypeOnBank(SrcTy, *SrcRB);
3371 TRI.getRegClassForTypeOnBank(DstTy, *DstRB);
3372 if (!SrcRC || !DstRC)
3374 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
3375 !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
3376 !RBI.constrainGenericRegister(IdxReg, AMDGPU::SReg_32RegClass, *MRI))
3387 if (SrcRB->
getID() == AMDGPU::SGPRRegBankID) {
3391 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3394 unsigned Opc = Is64 ? AMDGPU::S_MOVRELS_B64 : AMDGPU::S_MOVRELS_B32;
3396 .
addReg(SrcReg, {}, SubReg)
3398 MI.eraseFromParent();
3405 if (!STI.useVGPRIndexMode()) {
3406 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3408 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::V_MOVRELS_B32_e32), DstReg)
3409 .
addReg(SrcReg, {}, SubReg)
3411 MI.eraseFromParent();
3415 const MCInstrDesc &GPRIDXDesc =
3416 TII.getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*SrcRC),
true);
3422 MI.eraseFromParent();
3427bool AMDGPUInstructionSelector::selectG_INSERT_VECTOR_ELT(
3434 LLT VecTy = MRI->getType(DstReg);
3435 LLT ValTy = MRI->getType(ValReg);
3439 const RegisterBank *VecRB = RBI.getRegBank(VecReg, *MRI, TRI);
3440 const RegisterBank *ValRB = RBI.getRegBank(ValReg, *MRI, TRI);
3441 const RegisterBank *IdxRB = RBI.getRegBank(IdxReg, *MRI, TRI);
3447 if (IdxRB->
getID() != AMDGPU::SGPRRegBankID)
3451 TRI.getRegClassForTypeOnBank(VecTy, *VecRB);
3453 TRI.getRegClassForTypeOnBank(ValTy, *ValRB);
3455 if (!RBI.constrainGenericRegister(VecReg, *VecRC, *MRI) ||
3456 !RBI.constrainGenericRegister(DstReg, *VecRC, *MRI) ||
3457 !RBI.constrainGenericRegister(ValReg, *ValRC, *MRI) ||
3458 !RBI.constrainGenericRegister(IdxReg, AMDGPU::SReg_32RegClass, *MRI))
3461 if (VecRB->
getID() == AMDGPU::VGPRRegBankID && ValSize != 32)
3465 std::tie(IdxReg, SubReg) =
3468 const bool IndexMode = VecRB->
getID() == AMDGPU::VGPRRegBankID &&
3469 STI.useVGPRIndexMode();
3475 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3478 const MCInstrDesc &RegWriteOp = TII.getIndirectRegWriteMovRelPseudo(
3479 VecSize, ValSize, VecRB->
getID() == AMDGPU::SGPRRegBankID);
3484 MI.eraseFromParent();
3488 const MCInstrDesc &GPRIDXDesc =
3489 TII.getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC),
false);
3496 MI.eraseFromParent();
3502 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
3503 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
3504 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
3505 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
3506 case Intrinsic::amdgcn_load_async_to_lds:
3507 case Intrinsic::amdgcn_global_load_async_lds:
3513bool AMDGPUInstructionSelector::selectBufferLoadLds(
MachineInstr &
MI)
const {
3514 if (!Subtarget->hasVMemToLDSLoad())
3517 unsigned Size =
MI.getOperand(3).getImm();
3521 const bool HasVIndex =
MI.getNumOperands() == 9;
3525 VIndex =
MI.getOperand(4).getReg();
3529 Register VOffset =
MI.getOperand(4 + OpOffset).getReg();
3530 std::optional<ValueAndVReg> MaybeVOffset =
3532 const bool HasVOffset = !MaybeVOffset || MaybeVOffset->Value.getZExtValue();
3538 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_BOTHEN
3539 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_IDXEN
3540 : HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFEN
3541 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFSET;
3544 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_BOTHEN
3545 : AMDGPU::BUFFER_LOAD_USHORT_LDS_IDXEN
3546 : HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFEN
3547 : AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFSET;
3550 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_BOTHEN
3551 : AMDGPU::BUFFER_LOAD_DWORD_LDS_IDXEN
3552 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFEN
3553 : AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFSET;
3556 if (!Subtarget->hasLDSLoadB96_B128())
3559 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_BOTHEN
3560 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_IDXEN
3561 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFEN
3562 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFSET;
3565 if (!Subtarget->hasLDSLoadB96_B128())
3568 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_BOTHEN
3569 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_IDXEN
3570 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFEN
3571 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFSET;
3578 .
add(
MI.getOperand(2));
3582 if (HasVIndex && HasVOffset) {
3583 Register IdxReg = MRI->createVirtualRegister(TRI.getVGPR64Class());
3584 BuildMI(*
MBB, &*MIB,
DL, TII.get(AMDGPU::REG_SEQUENCE), IdxReg)
3591 }
else if (HasVIndex) {
3593 }
else if (HasVOffset) {
3597 MIB.
add(
MI.getOperand(1));
3598 MIB.
add(
MI.getOperand(5 + OpOffset));
3599 MIB.
add(
MI.getOperand(6 + OpOffset));
3601 unsigned Aux =
MI.getOperand(7 + OpOffset).getImm();
3610 MachineMemOperand *LoadMMO = *
MI.memoperands_begin();
3615 MachinePointerInfo StorePtrI = LoadPtrI;
3626 MachineMemOperand *StoreMMO =
3632 MI.eraseFromParent();
3645 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3651 return Def->getOperand(1).getReg();
3665 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3673 return Def->getOperand(1).getReg();
3675 if (
VT->signBitIsZero(
Reg))
3676 return matchZeroExtendFromS32(
Reg);
3684AMDGPUInstructionSelector::matchZeroExtendFromS32OrS32(
Register Reg)
const {
3686 : matchZeroExtendFromS32(
Reg);
3692AMDGPUInstructionSelector::matchSignExtendFromS32OrS32(
Register Reg)
const {
3694 : matchSignExtendFromS32(
Reg);
3698AMDGPUInstructionSelector::matchExtendFromS32OrS32(
Register Reg,
3699 bool IsSigned)
const {
3701 return matchSignExtendFromS32OrS32(
Reg);
3703 return matchZeroExtendFromS32OrS32(
Reg);
3713 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3720 return Def->getOperand(1).getReg();
3725bool AMDGPUInstructionSelector::selectGlobalLoadLds(
MachineInstr &
MI)
const{
3726 if (!Subtarget->hasVMemToLDSLoad())
3730 unsigned Size =
MI.getOperand(3).getImm();
3737 Opc = AMDGPU::GLOBAL_LOAD_LDS_UBYTE;
3740 Opc = AMDGPU::GLOBAL_LOAD_LDS_USHORT;
3743 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORD;
3746 if (!Subtarget->hasLDSLoadB96_B128())
3748 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX3;
3751 if (!Subtarget->hasLDSLoadB96_B128())
3753 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX4;
3760 .
add(
MI.getOperand(2));
3766 if (!isSGPR(Addr)) {
3768 if (isSGPR(AddrDef->Reg)) {
3769 Addr = AddrDef->Reg;
3770 }
else if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
3773 if (isSGPR(SAddr)) {
3774 Register PtrBaseOffset = AddrDef->MI->getOperand(2).getReg();
3775 if (
Register Off = matchZeroExtendFromS32(PtrBaseOffset)) {
3786 VOffset = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
3798 MIB.
add(
MI.getOperand(4));
3800 unsigned Aux =
MI.getOperand(5).getImm();
3804 MachineMemOperand *LoadMMO = *
MI.memoperands_begin();
3806 LoadPtrI.
Offset =
MI.getOperand(4).getImm();
3807 MachinePointerInfo StorePtrI = LoadPtrI;
3816 MachineMemOperand *StoreMMO =
3818 sizeof(int32_t),
Align(4));
3822 MI.eraseFromParent();
3827bool AMDGPUInstructionSelector::selectTensorLoadStore(
MachineInstr &
MI,
3829 bool IsLoad = IID == Intrinsic::amdgcn_tensor_load_to_lds;
3831 IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d4 : AMDGPU::TENSOR_STORE_FROM_LDS_d4;
3835 const auto isAllZeros = [&](MachineOperand &Opnd) {
3836 const MachineInstr *
DefMI = MRI->getVRegDef(Opnd.getReg());
3845 Opc = IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d2
3846 : AMDGPU::TENSOR_STORE_FROM_LDS_d2;
3853 .
add(
MI.getOperand(1))
3854 .
add(
MI.getOperand(2));
3856 if (NumGroups >= 4) {
3857 MIB.
add(
MI.getOperand(3))
3858 .
add(
MI.getOperand(4));
3862 .
add(
MI.getOperand(6));
3864 MI.eraseFromParent();
3868bool AMDGPUInstructionSelector::selectBVHIntersectRayIntrinsic(
3870 unsigned OpcodeOpIdx =
3871 MI.getOpcode() == AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY ? 1 : 3;
3872 MI.setDesc(TII.get(
MI.getOperand(OpcodeOpIdx).getImm()));
3873 MI.removeOperand(OpcodeOpIdx);
3874 MI.addImplicitDefUseOperands(*
MI.getMF());
3881bool AMDGPUInstructionSelector::selectSMFMACIntrin(
MachineInstr &
MI)
const {
3884 case Intrinsic::amdgcn_smfmac_f32_16x16x32_f16:
3885 Opc = AMDGPU::V_SMFMAC_F32_16X16X32_F16_e64;
3887 case Intrinsic::amdgcn_smfmac_f32_32x32x16_f16:
3888 Opc = AMDGPU::V_SMFMAC_F32_32X32X16_F16_e64;
3890 case Intrinsic::amdgcn_smfmac_f32_16x16x32_bf16:
3891 Opc = AMDGPU::V_SMFMAC_F32_16X16X32_BF16_e64;
3893 case Intrinsic::amdgcn_smfmac_f32_32x32x16_bf16:
3894 Opc = AMDGPU::V_SMFMAC_F32_32X32X16_BF16_e64;
3896 case Intrinsic::amdgcn_smfmac_i32_16x16x64_i8:
3897 Opc = AMDGPU::V_SMFMAC_I32_16X16X64_I8_e64;
3899 case Intrinsic::amdgcn_smfmac_i32_32x32x32_i8:
3900 Opc = AMDGPU::V_SMFMAC_I32_32X32X32_I8_e64;
3902 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_bf8:
3903 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF8_BF8_e64;
3905 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_fp8:
3906 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF8_FP8_e64;
3908 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_bf8:
3909 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_FP8_BF8_e64;
3911 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_fp8:
3912 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_FP8_FP8_e64;
3914 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_bf8:
3915 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF8_BF8_e64;
3917 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_fp8:
3918 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF8_FP8_e64;
3920 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_bf8:
3921 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_FP8_BF8_e64;
3923 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_fp8:
3924 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_FP8_FP8_e64;
3926 case Intrinsic::amdgcn_smfmac_f32_16x16x64_f16:
3927 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_F16_e64;
3929 case Intrinsic::amdgcn_smfmac_f32_32x32x32_f16:
3930 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_F16_e64;
3932 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf16:
3933 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF16_e64;
3935 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf16:
3936 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF16_e64;
3938 case Intrinsic::amdgcn_smfmac_i32_16x16x128_i8:
3939 Opc = AMDGPU::V_SMFMAC_I32_16X16X128_I8_e64;
3941 case Intrinsic::amdgcn_smfmac_i32_32x32x64_i8:
3942 Opc = AMDGPU::V_SMFMAC_I32_32X32X64_I8_e64;
3944 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_bf8:
3945 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_BF8_BF8_e64;
3947 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_fp8:
3948 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_BF8_FP8_e64;
3950 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_bf8:
3951 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_FP8_BF8_e64;
3953 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_fp8:
3954 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_FP8_FP8_e64;
3956 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_bf8:
3957 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_BF8_BF8_e64;
3959 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_fp8:
3960 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_BF8_FP8_e64;
3962 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_bf8:
3963 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_FP8_BF8_e64;
3965 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_fp8:
3966 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_FP8_FP8_e64;
3972 auto VDst_In =
MI.getOperand(4);
3974 MI.setDesc(TII.get(
Opc));
3975 MI.removeOperand(4);
3976 MI.removeOperand(1);
3977 MI.addOperand(VDst_In);
3978 MI.addImplicitDefUseOperands(*
MI.getMF());
3979 const MCInstrDesc &MCID =
MI.getDesc();
3981 MI.getOperand(0).setIsEarlyClobber(
true);
3986bool AMDGPUInstructionSelector::selectPermlaneSwapIntrin(
3988 if (IntrID == Intrinsic::amdgcn_permlane16_swap &&
3989 !Subtarget->hasPermlane16Swap())
3991 if (IntrID == Intrinsic::amdgcn_permlane32_swap &&
3992 !Subtarget->hasPermlane32Swap())
3995 unsigned Opcode = IntrID == Intrinsic::amdgcn_permlane16_swap
3996 ? AMDGPU::V_PERMLANE16_SWAP_B32_e64
3997 : AMDGPU::V_PERMLANE32_SWAP_B32_e64;
3999 MI.removeOperand(2);
4000 MI.setDesc(TII.get(Opcode));
4003 MachineOperand &FI =
MI.getOperand(4);
4010bool AMDGPUInstructionSelector::selectWaveAddress(
MachineInstr &
MI)
const {
4013 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4014 const bool IsVALU = DstRB->
getID() == AMDGPU::VGPRRegBankID;
4019 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHRREV_B32_e64), DstReg)
4020 .
addImm(Subtarget->getWavefrontSizeLog2())
4025 .
addImm(Subtarget->getWavefrontSizeLog2())
4030 IsVALU ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
4031 if (!RBI.constrainGenericRegister(DstReg, RC, *MRI))
4034 MI.eraseFromParent();
4038bool AMDGPUInstructionSelector::selectWaveShuffleIntrin(
4048 const LLT DstTy = MRI->getType(DstReg);
4050 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4052 TRI.getRegClassForSizeOnBank(DstSize, *DstRB);
4057 if (!Subtarget->supportsBPermute())
4061 if (Subtarget->supportsWaveWideBPermute()) {
4062 Register ShiftIdxReg = MRI->createVirtualRegister(DstRC);
4063 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), ShiftIdxReg)
4073 assert(Subtarget->isWave64());
4077 MRI->createVirtualRegister(TRI.getRegClass(AMDGPU::SReg_32RegClassID));
4078 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefValReg);
4080 Register UndefExecReg = MRI->createVirtualRegister(
4081 TRI.getRegClass(AMDGPU::SReg_64_XEXECRegClassID));
4082 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefExecReg);
4084 Register PoisonValReg = MRI->createVirtualRegister(DstRC);
4085 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_SET_INACTIVE_B32), PoisonValReg)
4093 Register ShiftIdxReg = MRI->createVirtualRegister(DstRC);
4094 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), ShiftIdxReg)
4098 Register PoisonIdxReg = MRI->createVirtualRegister(DstRC);
4099 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_SET_INACTIVE_B32), PoisonIdxReg)
4106 Register PoisonUnshiftedIdxReg = MRI->createVirtualRegister(DstRC);
4108 PoisonUnshiftedIdxReg)
4116 Register SameSidePermReg = MRI->createVirtualRegister(DstRC);
4117 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::DS_BPERMUTE_B32), SameSidePermReg)
4122 Register SwappedValReg = MRI->createVirtualRegister(DstRC);
4123 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_PERMLANE64_B32), SwappedValReg)
4126 Register OppSidePermReg = MRI->createVirtualRegister(DstRC);
4127 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::DS_BPERMUTE_B32), OppSidePermReg)
4132 Register WWMSwapPermReg = MRI->createVirtualRegister(DstRC);
4133 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::STRICT_WWM), WWMSwapPermReg)
4140 Register ThreadIDReg = MRI->createVirtualRegister(DstRC);
4141 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_MBCNT_LO_U32_B32_e64), ThreadIDReg)
4145 Register XORReg = MRI->createVirtualRegister(DstRC);
4148 .
addReg(PoisonUnshiftedIdxReg);
4150 Register ANDReg = MRI->createVirtualRegister(DstRC);
4155 Register CompareReg = MRI->createVirtualRegister(
4156 TRI.getRegClass(AMDGPU::SReg_64_XEXECRegClassID));
4157 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_CMP_EQ_U32_e64), CompareReg)
4162 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
4170 MI.eraseFromParent();
4179 unsigned NumOpcodes = 0;
4192 const uint8_t SrcBits[3] = { 0xf0, 0xcc, 0xaa };
4203 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4217 if (Src.size() == 3) {
4224 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4225 if (Src[
I] ==
LHS) {
4235 Bits = SrcBits[Src.size()];
4241 switch (
MI->getOpcode()) {
4242 case TargetOpcode::G_AND:
4243 case TargetOpcode::G_OR:
4244 case TargetOpcode::G_XOR: {
4249 if (!getOperandBits(
LHS, LHSBits) ||
4250 !getOperandBits(
RHS, RHSBits)) {
4251 Src = std::move(Backup);
4252 return std::make_pair(0, 0);
4273 uint8_t LHSBitsOrig = LHSBits;
4274 uint8_t RHSBitsOrig = RHSBits;
4278 NumOpcodes += LHSOp.first;
4279 LHSBits = LHSOp.second;
4286 NumOpcodes += RHSOp.first;
4287 RHSBits = RHSOp.second;
4291 auto dependsOnSlot = [](
uint8_t TT,
int Slot) ->
bool {
4292 if (Slot < 0 || Slot > 2)
4294 const uint8_t Masks[3] = {0x0f, 0x33, 0x55};
4295 const int Shifts[3] = {4, 2, 1};
4296 return ((TT ^ (TT >> Shifts[Slot])) & Masks[Slot]) != 0;
4302 const uint8_t SrcBitsConst[3] = {0xf0, 0xcc, 0xaa};
4309 for (
int I = 0;
I < (int)S.size();
I++) {
4310 if (Bits == SrcBitsConst[
I] && S[
I] ==
Op)
4312 if (IsNegationOp && Bits == (
uint8_t)~SrcBitsConst[
I] &&
4313 S[
I] == NegatedInner)
4324 for (
int I = 0;
I < (int)SrcAfterLHS.
size() &&
I < 3;
I++) {
4325 if (
I < (
int)Src.size() && Src[
I] != SrcAfterLHS[
I] &&
4326 dependsOnSlot(LHSBits,
I)) {
4335 if (!Stale && !RHSOp.first) {
4336 int Slot = findSlot(RHSBitsOrig,
RHS, SrcBeforeRecurse);
4338 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4344 if (!Stale && !LHSOp.first) {
4345 int Slot = findSlot(LHSBitsOrig,
LHS, SrcBeforeRecurse);
4347 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4352 Src = std::move(SrcBeforeRecurse);
4353 LHSBits = LHSBitsOrig;
4354 RHSBits = RHSBitsOrig;
4360 return std::make_pair(0, 0);
4364 switch (
MI->getOpcode()) {
4365 case TargetOpcode::G_AND:
4366 TTbl = LHSBits & RHSBits;
4368 case TargetOpcode::G_OR:
4369 TTbl = LHSBits | RHSBits;
4371 case TargetOpcode::G_XOR:
4372 TTbl = LHSBits ^ RHSBits;
4378 return std::make_pair(NumOpcodes + 1, TTbl);
4381bool AMDGPUInstructionSelector::selectBITOP3(
MachineInstr &
MI)
const {
4382 if (!Subtarget->hasBitOp3Insts())
4386 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4387 const bool IsVALU = DstRB->
getID() == AMDGPU::VGPRRegBankID;
4393 unsigned NumOpcodes;
4395 std::tie(NumOpcodes, TTbl) =
BitOp3_Op(DstReg, Src, *MRI);
4399 if (NumOpcodes < 2 || Src.empty())
4404 unsigned Size = MRI->getType(DstReg).getSizeInBits();
4405 assert((
Size == 16 ||
Size == 32) &&
"unexpected VALU logic op size");
4406 const bool IsB32 =
Size == 32;
4407 if (NumOpcodes == 2 && IsB32) {
4415 }
else if (NumOpcodes < 4) {
4422 unsigned Opc = IsB32 ? AMDGPU::V_BITOP3_B32_e64 : AMDGPU::V_BITOP3_B16_e64;
4423 if (!IsB32 && STI.hasTrue16BitInsts())
4424 Opc = STI.useRealTrue16Insts() ? AMDGPU::V_BITOP3_B16_gfx1250_t16_e64
4425 : AMDGPU::V_BITOP3_B16_gfx1250_fake16_e64;
4426 unsigned CBL = STI.getConstantBusLimit(
Opc);
4430 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4431 const RegisterBank *RB = RBI.getRegBank(Src[
I], *MRI, TRI);
4432 if (RB->
getID() != AMDGPU::SGPRRegBankID)
4438 Register NewReg = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
4449 while (Src.size() < 3)
4450 Src.push_back(Src[0]);
4467 MI.eraseFromParent();
4472bool AMDGPUInstructionSelector::selectStackRestore(
MachineInstr &
MI)
const {
4474 if (!RBI.constrainGenericRegister(SrcReg, AMDGPU::SReg_32RegClass, *MRI))
4477 MachineInstr *
DefMI = MRI->getVRegDef(SrcReg);
4479 Subtarget->getTargetLowering()->getStackPointerRegisterToSaveRestore();
4485 WaveAddr = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
4488 .
addImm(Subtarget->getWavefrontSizeLog2())
4495 MI.eraseFromParent();
4501 if (!
I.isPreISelOpcode()) {
4503 return selectCOPY(
I);
4507 switch (
I.getOpcode()) {
4508 case TargetOpcode::G_AND:
4509 case TargetOpcode::G_OR:
4510 case TargetOpcode::G_XOR:
4511 if (selectBITOP3(
I))
4515 return selectG_AND_OR_XOR(
I);
4516 case TargetOpcode::G_ADD:
4517 case TargetOpcode::G_SUB:
4518 case TargetOpcode::G_PTR_ADD:
4521 return selectG_ADD_SUB(
I);
4522 case TargetOpcode::G_UADDO:
4523 case TargetOpcode::G_USUBO:
4524 case TargetOpcode::G_UADDE:
4525 case TargetOpcode::G_USUBE:
4526 return selectG_UADDO_USUBO_UADDE_USUBE(
I);
4527 case AMDGPU::G_AMDGPU_MAD_U64_U32:
4528 case AMDGPU::G_AMDGPU_MAD_I64_I32:
4529 return selectG_AMDGPU_MAD_64_32(
I);
4530 case TargetOpcode::G_INTTOPTR:
4531 case TargetOpcode::G_BITCAST:
4532 case TargetOpcode::G_PTRTOINT:
4533 case TargetOpcode::G_FREEZE:
4534 return selectCOPY(
I);
4535 case TargetOpcode::G_FNEG:
4538 return selectG_FNEG(
I);
4539 case TargetOpcode::G_FABS:
4542 return selectG_FABS(
I);
4543 case TargetOpcode::G_EXTRACT:
4544 return selectG_EXTRACT(
I);
4545 case TargetOpcode::G_MERGE_VALUES:
4546 case TargetOpcode::G_CONCAT_VECTORS:
4547 return selectG_MERGE_VALUES(
I);
4548 case TargetOpcode::G_UNMERGE_VALUES:
4549 return selectG_UNMERGE_VALUES(
I);
4550 case TargetOpcode::G_BUILD_VECTOR:
4551 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
4552 return selectG_BUILD_VECTOR(
I);
4553 case TargetOpcode::G_IMPLICIT_DEF:
4554 return selectG_IMPLICIT_DEF(
I);
4555 case TargetOpcode::G_INSERT:
4556 return selectG_INSERT(
I);
4557 case TargetOpcode::G_INTRINSIC:
4558 case TargetOpcode::G_INTRINSIC_CONVERGENT:
4559 return selectG_INTRINSIC(
I);
4560 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
4561 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
4562 return selectG_INTRINSIC_W_SIDE_EFFECTS(
I);
4563 case TargetOpcode::G_ICMP:
4564 case TargetOpcode::G_FCMP:
4565 if (selectG_ICMP_or_FCMP(
I))
4568 case TargetOpcode::G_LOAD:
4569 case TargetOpcode::G_ZEXTLOAD:
4570 case TargetOpcode::G_SEXTLOAD:
4571 case TargetOpcode::G_STORE:
4572 case TargetOpcode::G_ATOMIC_CMPXCHG:
4573 case TargetOpcode::G_ATOMICRMW_XCHG:
4574 case TargetOpcode::G_ATOMICRMW_ADD:
4575 case TargetOpcode::G_ATOMICRMW_SUB:
4576 case TargetOpcode::G_ATOMICRMW_AND:
4577 case TargetOpcode::G_ATOMICRMW_OR:
4578 case TargetOpcode::G_ATOMICRMW_XOR:
4579 case TargetOpcode::G_ATOMICRMW_MIN:
4580 case TargetOpcode::G_ATOMICRMW_MAX:
4581 case TargetOpcode::G_ATOMICRMW_UMIN:
4582 case TargetOpcode::G_ATOMICRMW_UMAX:
4583 case TargetOpcode::G_ATOMICRMW_UINC_WRAP:
4584 case TargetOpcode::G_ATOMICRMW_UDEC_WRAP:
4585 case TargetOpcode::G_ATOMICRMW_USUB_COND:
4586 case TargetOpcode::G_ATOMICRMW_USUB_SAT:
4587 case TargetOpcode::G_ATOMICRMW_FADD:
4588 case TargetOpcode::G_ATOMICRMW_FMIN:
4589 case TargetOpcode::G_ATOMICRMW_FMAX:
4590 return selectG_LOAD_STORE_ATOMICRMW(
I);
4591 case TargetOpcode::G_SELECT:
4592 return selectG_SELECT(
I);
4593 case TargetOpcode::G_TRUNC:
4594 return selectG_TRUNC(
I);
4595 case TargetOpcode::G_SEXT:
4596 case TargetOpcode::G_ZEXT:
4597 case TargetOpcode::G_ANYEXT:
4598 case TargetOpcode::G_SEXT_INREG:
4602 if (MRI->getType(
I.getOperand(1).getReg()) !=
LLT::scalar(1) &&
4605 return selectG_SZA_EXT(
I);
4606 case TargetOpcode::G_FPEXT:
4607 if (selectG_FPEXT(
I))
4610 case TargetOpcode::G_BRCOND:
4611 return selectG_BRCOND(
I);
4612 case TargetOpcode::G_GLOBAL_VALUE:
4613 return selectG_GLOBAL_VALUE(
I);
4614 case TargetOpcode::G_PTRMASK:
4615 return selectG_PTRMASK(
I);
4616 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4617 return selectG_EXTRACT_VECTOR_ELT(
I);
4618 case TargetOpcode::G_INSERT_VECTOR_ELT:
4619 return selectG_INSERT_VECTOR_ELT(
I);
4620 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD:
4621 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16:
4622 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET:
4623 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE:
4624 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16: {
4627 assert(Intr &&
"not an image intrinsic with image pseudo");
4628 return selectImageIntrinsic(
I, Intr);
4630 case AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY:
4631 case AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY:
4632 case AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY:
4633 return selectBVHIntersectRayIntrinsic(
I);
4634 case AMDGPU::G_SBFX:
4635 case AMDGPU::G_UBFX:
4636 return selectG_SBFX_UBFX(
I);
4637 case AMDGPU::G_SI_CALL:
4638 I.setDesc(TII.get(AMDGPU::SI_CALL));
4640 case AMDGPU::G_AMDGPU_WAVE_ADDRESS:
4641 return selectWaveAddress(
I);
4642 case AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_RETURN: {
4643 I.setDesc(TII.get(AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN));
4646 case AMDGPU::G_STACKRESTORE:
4647 return selectStackRestore(
I);
4649 return selectPHI(
I);
4650 case AMDGPU::G_AMDGPU_COPY_SCC_VCC:
4651 return selectCOPY_SCC_VCC(
I);
4652 case AMDGPU::G_AMDGPU_COPY_VCC_SCC:
4653 return selectCOPY_VCC_SCC(
I);
4654 case AMDGPU::G_AMDGPU_READANYLANE:
4655 return selectReadAnyLane(
I);
4656 case TargetOpcode::G_CONSTANT:
4657 case TargetOpcode::G_FCONSTANT:
4665AMDGPUInstructionSelector::selectVCSRC(
MachineOperand &Root)
const {
4672std::pair<Register, unsigned> AMDGPUInstructionSelector::selectVOP3ModsImpl(
4673 Register Src,
bool IsCanonicalizing,
bool AllowAbs,
bool OpSel)
const {
4677 if (
MI->getOpcode() == AMDGPU::G_FNEG) {
4678 Src =
MI->getOperand(1).getReg();
4681 }
else if (
MI->getOpcode() == AMDGPU::G_FSUB && IsCanonicalizing) {
4686 if (
LHS &&
LHS->isZero()) {
4688 Src =
MI->getOperand(2).getReg();
4692 if (AllowAbs &&
MI->getOpcode() == AMDGPU::G_FABS) {
4693 Src =
MI->getOperand(1).getReg();
4700 return std::pair(Src, Mods);
4703std::pair<Register, unsigned>
4704AMDGPUInstructionSelector::selectVOP3PModsF32Impl(
Register Src)
const {
4706 std::tie(Src, Mods) = selectVOP3ModsImpl(Src);
4708 return std::pair(Src, Mods);
4711Register AMDGPUInstructionSelector::copyToVGPRIfSrcFolded(
4713 bool ForceVGPR)
const {
4714 if ((Mods != 0 || ForceVGPR) &&
4715 RBI.getRegBank(Src, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID) {
4722 TII.
get(AMDGPU::COPY), VGPRSrc)
4734AMDGPUInstructionSelector::selectVSRC0(
MachineOperand &Root)
const {
4736 [=](MachineInstrBuilder &MIB) { MIB.
add(Root); }
4741AMDGPUInstructionSelector::selectVOP3Mods0(
MachineOperand &Root)
const {
4744 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
4747 [=](MachineInstrBuilder &MIB) {
4748 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4750 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
4751 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4752 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4757AMDGPUInstructionSelector::selectVOP3BMods0(
MachineOperand &Root)
const {
4760 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
4765 [=](MachineInstrBuilder &MIB) {
4766 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4768 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
4769 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4770 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4775AMDGPUInstructionSelector::selectVOP3OMods(
MachineOperand &Root)
const {
4777 [=](MachineInstrBuilder &MIB) { MIB.
add(Root); },
4778 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4779 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4784AMDGPUInstructionSelector::selectVOP3Mods(
MachineOperand &Root)
const {
4787 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
4790 [=](MachineInstrBuilder &MIB) {
4791 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4793 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4798AMDGPUInstructionSelector::selectVOP3ModsNonCanonicalizing(
4802 std::tie(Src, Mods) =
4803 selectVOP3ModsImpl(Root.
getReg(),
false);
4806 [=](MachineInstrBuilder &MIB) {
4807 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4809 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4814AMDGPUInstructionSelector::selectVOP3BMods(
MachineOperand &Root)
const {
4817 std::tie(Src, Mods) =
4818 selectVOP3ModsImpl(Root.
getReg(),
true,
4822 [=](MachineInstrBuilder &MIB) {
4823 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4825 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4830AMDGPUInstructionSelector::selectVOP3NoMods(
MachineOperand &Root)
const {
4833 if (
Def->getOpcode() == AMDGPU::G_FNEG ||
Def->getOpcode() == AMDGPU::G_FABS)
4836 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
4861 if (
MI->getOpcode() != AMDGPU::G_TRUNC)
4866 return DstSize * 2 == SrcSize;
4872 if (
MI->getOpcode() != AMDGPU::G_LSHR)
4876 std::optional<ValueAndVReg> ShiftAmt;
4877 if (
mi_match(
MI->getOperand(0).getReg(), MRI,
4880 unsigned Shift = ShiftAmt->Value.getZExtValue();
4881 return Shift * 2 == SrcSize;
4889 if (
MI->getOpcode() != AMDGPU::G_SHL)
4893 std::optional<ValueAndVReg> ShiftAmt;
4894 if (
mi_match(
MI->getOperand(0).getReg(), MRI,
4897 unsigned Shift = ShiftAmt->Value.getZExtValue();
4898 return Shift * 2 == SrcSize;
4906 if (
MI->getOpcode() != AMDGPU::G_UNMERGE_VALUES)
4908 return MI->getNumOperands() == 3 &&
MI->getOperand(0).isDef() &&
4909 MI->getOperand(1).isDef() && !
MI->getOperand(2).isDef();
4917 if (
OpTy.isScalar())
4919 if (
OpTy.isVector() &&
OpTy.getNumElements() == 2)
5079static std::optional<std::pair<Register, SrcStatus>>
5084 unsigned Opc =
MI->getOpcode();
5088 case AMDGPU::G_BITCAST:
5089 return std::optional<std::pair<Register, SrcStatus>>(
5090 {
MI->getOperand(1).getReg(), Curr.second});
5092 if (
MI->getOperand(1).getReg().isPhysical())
5093 return std::nullopt;
5094 return std::optional<std::pair<Register, SrcStatus>>(
5095 {
MI->getOperand(1).getReg(), Curr.second});
5096 case AMDGPU::G_FNEG: {
5099 return std::nullopt;
5100 return std::optional<std::pair<Register, SrcStatus>>(
5101 {
MI->getOperand(1).getReg(), Stat});
5108 switch (Curr.second) {
5111 return std::optional<std::pair<Register, SrcStatus>>(
5114 if (Curr.first ==
MI->getOperand(0).getReg())
5115 return std::optional<std::pair<Register, SrcStatus>>(
5117 return std::optional<std::pair<Register, SrcStatus>>(
5129 return std::optional<std::pair<Register, SrcStatus>>(
5133 if (Curr.first ==
MI->getOperand(0).getReg())
5134 return std::optional<std::pair<Register, SrcStatus>>(
5136 return std::optional<std::pair<Register, SrcStatus>>(
5142 return std::optional<std::pair<Register, SrcStatus>>(
5147 return std::optional<std::pair<Register, SrcStatus>>(
5152 return std::optional<std::pair<Register, SrcStatus>>(
5157 return std::optional<std::pair<Register, SrcStatus>>(
5163 return std::nullopt;
5173 bool HasNeg =
false;
5175 bool HasOpsel =
true;
5180 unsigned Opc =
MI->getOpcode();
5182 if (
Opc == TargetOpcode::G_INTRINSIC) {
5185 if (IntrinsicID == Intrinsic::amdgcn_fdot2)
5212 while (
Depth <= MaxDepth && Curr.has_value()) {
5215 Statlist.push_back(Curr.value());
5222static std::pair<Register, SrcStatus>
5229 while (
Depth <= MaxDepth && Curr.has_value()) {
5235 LastSameOrNeg = Curr.value();
5240 return LastSameOrNeg;
5247 return Width1 == Width2;
5282 return isSameBitWidth(NewReg, RootReg, MRI) && IsHalfState(LoStat) &&
5283 IsHalfState(HiStat);
5286std::pair<Register, unsigned> AMDGPUInstructionSelector::selectVOP3PModsImpl(
5292 return {RootReg, Mods};
5295 SearchOptions SO(RootReg, MRI);
5308 if (MRI.getType(RootReg).getSizeInBits() == 128) {
5310 return {Stat.first, Mods};
5315 MI->getNumOperands() != 3 || (IsDOT && Subtarget->hasDOTOpSelHazard())) {
5317 return {Stat.first, Mods};
5323 if (StatlistHi.
empty()) {
5325 return {Stat.first, Mods};
5331 if (StatlistLo.
empty()) {
5333 return {Stat.first, Mods};
5336 for (
int I = StatlistHi.
size() - 1;
I >= 0;
I--) {
5337 for (
int J = StatlistLo.
size() - 1; J >= 0; J--) {
5338 if (StatlistHi[
I].first == StatlistLo[J].first &&
5340 StatlistHi[
I].first, RootReg, TII, MRI))
5341 return {StatlistHi[
I].first,
5342 updateMods(StatlistHi[
I].second, StatlistLo[J].second, Mods)};
5348 return {Stat.first, Mods};
5358 return RB->
getID() == RBNo;
5374 if (
checkRB(RootReg, AMDGPU::SGPRRegBankID, RBI, MRI,
TRI) ||
5375 checkRB(NewReg, AMDGPU::VGPRRegBankID, RBI, MRI,
TRI))
5385 TII.get(AMDGPU::COPY), DstReg)
5393AMDGPUInstructionSelector::selectVOP3PRetHelper(
MachineOperand &Root,
5398 std::tie(
Reg, Mods) = selectVOP3PModsImpl(Root.
getReg(), MRI, IsDOT);
5403 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
5404 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5409AMDGPUInstructionSelector::selectVOP3PMods(
MachineOperand &Root)
const {
5411 return selectVOP3PRetHelper(Root);
5415AMDGPUInstructionSelector::selectVOP3PModsDOT(
MachineOperand &Root)
const {
5417 return selectVOP3PRetHelper(Root,
true);
5421AMDGPUInstructionSelector::selectVOP3PNoModsDOT(
MachineOperand &Root)
const {
5425 std::tie(Src, Mods) = selectVOP3PModsImpl(Root.
getReg(), MRI,
true );
5429 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); }}};
5433AMDGPUInstructionSelector::selectVOP3PModsF32(
MachineOperand &Root)
const {
5436 std::tie(Src, Mods) = selectVOP3PModsF32Impl(Root.
getReg());
5439 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5440 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5445AMDGPUInstructionSelector::selectVOP3PNoModsF32(
MachineOperand &Root)
const {
5448 std::tie(Src, Mods) = selectVOP3PModsF32Impl(Root.
getReg());
5452 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); }}};
5456AMDGPUInstructionSelector::selectWMMAOpSelVOP3PMods(
5459 "expected i1 value");
5465 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5473 switch (Elts.
size()) {
5475 DstRegClass = &AMDGPU::VReg_256RegClass;
5478 DstRegClass = &AMDGPU::VReg_128RegClass;
5481 DstRegClass = &AMDGPU::VReg_64RegClass;
5488 auto MIB =
B.buildInstr(AMDGPU::REG_SEQUENCE)
5490 for (
unsigned i = 0; i < Elts.
size(); ++i) {
5501 if (ModOpcode == TargetOpcode::G_FNEG) {
5505 for (
auto El : Elts) {
5511 if (Elts.size() != NegAbsElts.
size()) {
5520 assert(ModOpcode == TargetOpcode::G_FABS);
5528AMDGPUInstructionSelector::selectWMMAModsF32NegAbs(
MachineOperand &Root)
const {
5537 MachineInstr *ElF32 = MRI->getVRegDef(BV->
getSourceReg(0));
5538 unsigned ModOpcode = (ElF32->
getOpcode() == AMDGPU::G_FNEG)
5555 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5556 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5560AMDGPUInstructionSelector::selectWMMAModsF16Neg(
MachineOperand &Root)
const {
5582 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5583 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5587AMDGPUInstructionSelector::selectWMMAModsF16NegAbs(
MachineOperand &Root)
const {
5595 MachineInstr *ElV2F16 = MRI->getVRegDef(CV->
getSourceReg(0));
5597 unsigned ModOpcode = (ElV2F16->
getOpcode() == AMDGPU::G_FNEG)
5616 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5617 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5621AMDGPUInstructionSelector::selectWMMAVISrc(
MachineOperand &Root)
const {
5622 std::optional<FPValueAndVReg> FPValReg;
5624 if (TII.isInlineConstant(FPValReg->Value)) {
5625 return {{[=](MachineInstrBuilder &MIB) {
5626 MIB.
addImm(FPValReg->Value.bitcastToAPInt().getSExtValue());
5636 if (TII.isInlineConstant(ICst)) {
5646AMDGPUInstructionSelector::selectSWMMACIndex8(
MachineOperand &Root)
const {
5652 std::optional<ValueAndVReg> ShiftAmt;
5654 MRI->getType(ShiftSrc).getSizeInBits() == 32 &&
5655 ShiftAmt->Value.getZExtValue() % 8 == 0) {
5656 Key = ShiftAmt->Value.getZExtValue() / 8;
5661 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5662 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5667AMDGPUInstructionSelector::selectSWMMACIndex16(
MachineOperand &Root)
const {
5674 std::optional<ValueAndVReg> ShiftAmt;
5676 MRI->getType(ShiftSrc).getSizeInBits() == 32 &&
5677 ShiftAmt->Value.getZExtValue() == 16) {
5683 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5684 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5689AMDGPUInstructionSelector::selectSWMMACIndex32(
MachineOperand &Root)
const {
5696 S32 = matchAnyExtendFromS32(Src);
5700 if (
Def->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) {
5705 Src =
Def->getOperand(2).getReg();
5712 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5713 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5718AMDGPUInstructionSelector::selectVOP3OpSelMods(
MachineOperand &Root)
const {
5721 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
5725 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5726 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5732AMDGPUInstructionSelector::selectVINTERPMods(
MachineOperand &Root)
const {
5735 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
5741 [=](MachineInstrBuilder &MIB) {
5743 copyToVGPRIfSrcFolded(Src, Mods, Root, MIB,
true));
5745 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
5750AMDGPUInstructionSelector::selectVINTERPModsHi(
MachineOperand &Root)
const {
5753 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
5759 [=](MachineInstrBuilder &MIB) {
5761 copyToVGPRIfSrcFolded(Src, Mods, Root, MIB,
true));
5763 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
5770bool AMDGPUInstructionSelector::selectScaleOffset(
MachineOperand &Root,
5772 bool IsSigned)
const {
5773 if (!Subtarget->hasScaleOffset())
5777 MachineMemOperand *MMO = *
MI.memoperands_begin();
5789 OffsetReg =
Def->Reg;
5804 m_BinOp(IsSigned ? AMDGPU::S_MUL_I64_I32_PSEUDO : AMDGPU::S_MUL_U64,
5808 (
Mul->getOpcode() == (IsSigned ? AMDGPU::G_AMDGPU_MAD_I64_I32
5809 : AMDGPU::G_AMDGPU_MAD_U64_U32) ||
5810 (IsSigned &&
Mul->getOpcode() == AMDGPU::G_AMDGPU_MAD_U64_U32 &&
5811 VT->signBitIsZero(
Mul->getOperand(2).getReg()))) &&
5824bool AMDGPUInstructionSelector::selectSmrdOffset(
MachineOperand &Root,
5828 bool *ScaleOffset)
const {
5835 getAddrModeInfo(*
MI, *MRI, AddrInfo);
5837 if (AddrInfo.
empty())
5840 const GEPInfo &GEPI = AddrInfo[0];
5841 std::optional<int64_t> EncodedImm;
5844 *ScaleOffset =
false;
5849 if (GEPI.SgprParts.size() == 1 && GEPI.Imm != 0 && EncodedImm &&
5850 AddrInfo.
size() > 1) {
5851 const GEPInfo &GEPI2 = AddrInfo[1];
5852 if (GEPI2.SgprParts.size() == 2 && GEPI2.Imm == 0) {
5853 Register OffsetReg = GEPI2.SgprParts[1];
5856 selectScaleOffset(Root, OffsetReg,
false );
5857 OffsetReg = matchZeroExtendFromS32OrS32(OffsetReg);
5859 Base = GEPI2.SgprParts[0];
5860 *SOffset = OffsetReg;
5869 auto SKnown =
VT->getKnownBits(*SOffset);
5870 if (*
Offset + SKnown.getMinValue().getSExtValue() < 0)
5882 if (
Offset && GEPI.SgprParts.size() == 1 && EncodedImm) {
5883 Base = GEPI.SgprParts[0];
5889 if (SOffset && GEPI.SgprParts.size() == 1 &&
isUInt<32>(GEPI.Imm) &&
5895 Base = GEPI.SgprParts[0];
5896 *SOffset = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
5897 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), *SOffset)
5902 if (SOffset && GEPI.SgprParts.size() && GEPI.Imm == 0) {
5903 Register OffsetReg = GEPI.SgprParts[1];
5905 *ScaleOffset = selectScaleOffset(Root, OffsetReg,
false );
5906 OffsetReg = matchZeroExtendFromS32OrS32(OffsetReg);
5908 Base = GEPI.SgprParts[0];
5909 *SOffset = OffsetReg;
5918AMDGPUInstructionSelector::selectSmrdImm(
MachineOperand &Root)
const {
5921 if (!selectSmrdOffset(Root,
Base,
nullptr, &
Offset,
5923 return std::nullopt;
5925 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
5926 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Offset); }}};
5930AMDGPUInstructionSelector::selectSmrdImm32(
MachineOperand &Root)
const {
5932 getAddrModeInfo(*Root.
getParent(), *MRI, AddrInfo);
5934 if (AddrInfo.
empty() || AddrInfo[0].SgprParts.size() != 1)
5935 return std::nullopt;
5937 const GEPInfo &GEPInfo = AddrInfo[0];
5938 Register PtrReg = GEPInfo.SgprParts[0];
5939 std::optional<int64_t> EncodedImm =
5942 return std::nullopt;
5945 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrReg); },
5946 [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); }
5951AMDGPUInstructionSelector::selectSmrdSgpr(
MachineOperand &Root)
const {
5954 if (!selectSmrdOffset(Root,
Base, &SOffset,
nullptr,
5956 return std::nullopt;
5959 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
5960 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
5961 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }}};
5965AMDGPUInstructionSelector::selectSmrdSgprImm(
MachineOperand &Root)
const {
5969 if (!selectSmrdOffset(Root,
Base, &SOffset, &
Offset, &ScaleOffset))
5970 return std::nullopt;
5973 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
5974 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
5976 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }}};
5979std::pair<Register, int> AMDGPUInstructionSelector::selectFlatOffsetImpl(
5985 if (!STI.hasFlatInstOffsets())
5989 int64_t ConstOffset;
5991 std::tie(PtrBase, ConstOffset, IsInBounds) =
5992 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
5998 if (ConstOffset == 0 ||
6000 !isFlatScratchBaseLegal(Root.
getReg())) ||
6004 unsigned AddrSpace = (*
MI->memoperands_begin())->getAddrSpace();
6005 if (!TII.isLegalFLATOffset(ConstOffset, AddrSpace, FlatVariant))
6008 return std::pair(PtrBase, ConstOffset);
6012AMDGPUInstructionSelector::selectFlatOffset(
MachineOperand &Root)
const {
6016 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6017 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6022AMDGPUInstructionSelector::selectGlobalOffset(
MachineOperand &Root)
const {
6023 auto PtrWithOffset =
6027 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6028 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6033AMDGPUInstructionSelector::selectScratchOffset(
MachineOperand &Root)
const {
6034 auto PtrWithOffset =
6038 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6039 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6045AMDGPUInstructionSelector::selectGlobalSAddr(
MachineOperand &Root,
6047 bool NeedIOffset)
const {
6050 int64_t ConstOffset;
6051 int64_t ImmOffset = 0;
6055 std::tie(PtrBase, ConstOffset, std::ignore) =
6056 getPtrBaseWithConstantOffset(Addr, *MRI);
6058 if (ConstOffset != 0) {
6063 ImmOffset = ConstOffset;
6066 if (isSGPR(PtrBaseDef->Reg)) {
6067 if (ConstOffset > 0) {
6073 int64_t SplitImmOffset = 0, RemainderOffset = ConstOffset;
6075 std::tie(SplitImmOffset, RemainderOffset) =
6080 if (Subtarget->hasSignedGVSOffset() ?
isInt<32>(RemainderOffset)
6085 MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6087 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32),
6089 .
addImm(RemainderOffset);
6093 [=](MachineInstrBuilder &MIB) {
6096 [=](MachineInstrBuilder &MIB) {
6099 [=](MachineInstrBuilder &MIB) { MIB.
addImm(SplitImmOffset); },
6100 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); },
6103 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrBase); },
6104 [=](MachineInstrBuilder &MIB) {
6107 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); },
6117 unsigned NumLiterals =
6118 !TII.isInlineConstant(APInt(32,
Lo_32(ConstOffset))) +
6119 !TII.isInlineConstant(APInt(32,
Hi_32(ConstOffset)));
6120 if (STI.getConstantBusLimit(AMDGPU::V_ADD_U32_e64) > NumLiterals)
6121 return std::nullopt;
6128 if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
6133 if (isSGPR(SAddr)) {
6134 Register PtrBaseOffset = AddrDef->MI->getOperand(2).getReg();
6138 bool ScaleOffset = selectScaleOffset(Root, PtrBaseOffset,
6139 Subtarget->hasSignedGVSOffset());
6140 if (
Register VOffset = matchExtendFromS32OrS32(
6141 PtrBaseOffset, Subtarget->hasSignedGVSOffset())) {
6143 return {{[=](MachineInstrBuilder &MIB) {
6146 [=](MachineInstrBuilder &MIB) {
6149 [=](MachineInstrBuilder &MIB) {
6152 [=](MachineInstrBuilder &MIB) {
6156 return {{[=](MachineInstrBuilder &MIB) {
6159 [=](MachineInstrBuilder &MIB) {
6162 [=](MachineInstrBuilder &MIB) {
6172 if (AddrDef->MI->getOpcode() == AMDGPU::G_IMPLICIT_DEF ||
6173 AddrDef->MI->getOpcode() == AMDGPU::G_CONSTANT || !isSGPR(AddrDef->Reg))
6174 return std::nullopt;
6180 Register VOffset = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6182 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32), VOffset)
6187 [=](MachineInstrBuilder &MIB) { MIB.
addReg(AddrDef->Reg); },
6188 [=](MachineInstrBuilder &MIB) { MIB.
addReg(VOffset); },
6189 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6190 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); }
6193 [=](MachineInstrBuilder &MIB) { MIB.
addReg(AddrDef->Reg); },
6194 [=](MachineInstrBuilder &MIB) { MIB.
addReg(VOffset); },
6195 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); }
6200AMDGPUInstructionSelector::selectGlobalSAddr(
MachineOperand &Root)
const {
6201 return selectGlobalSAddr(Root, 0);
6205AMDGPUInstructionSelector::selectGlobalSAddrCPol(
MachineOperand &Root)
const {
6211 return selectGlobalSAddr(Root, PassedCPol);
6215AMDGPUInstructionSelector::selectGlobalSAddrCPolM0(
MachineOperand &Root)
const {
6221 return selectGlobalSAddr(Root, PassedCPol);
6225AMDGPUInstructionSelector::selectGlobalSAddrGLC(
MachineOperand &Root)
const {
6230AMDGPUInstructionSelector::selectGlobalSAddrNoIOffset(
6237 return selectGlobalSAddr(Root, PassedCPol,
false);
6241AMDGPUInstructionSelector::selectGlobalSAddrNoIOffsetM0(
6248 return selectGlobalSAddr(Root, PassedCPol,
false);
6252AMDGPUInstructionSelector::selectScratchSAddr(
MachineOperand &Root)
const {
6255 int64_t ConstOffset;
6256 int64_t ImmOffset = 0;
6260 std::tie(PtrBase, ConstOffset, std::ignore) =
6261 getPtrBaseWithConstantOffset(Addr, *MRI);
6263 if (ConstOffset != 0 && isFlatScratchBaseLegal(Addr) &&
6267 ImmOffset = ConstOffset;
6271 if (AddrDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX) {
6272 int FI = AddrDef->MI->getOperand(1).
getIndex();
6275 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); }
6281 if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
6282 Register LHS = AddrDef->MI->getOperand(1).getReg();
6283 Register RHS = AddrDef->MI->getOperand(2).getReg();
6287 if (LHSDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX &&
6288 isSGPR(RHSDef->Reg)) {
6289 int FI = LHSDef->MI->getOperand(1).getIndex();
6293 SAddr = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
6295 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_ADD_I32), SAddr)
6303 return std::nullopt;
6306 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SAddr); },
6307 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); }
6312bool AMDGPUInstructionSelector::checkFlatScratchSVSSwizzleBug(
6314 if (!Subtarget->hasFlatScratchSVSSwizzleBug())
6320 auto VKnown =
VT->getKnownBits(VAddr);
6323 uint64_t VMax = VKnown.getMaxValue().getZExtValue();
6325 return (VMax & 3) + (
SMax & 3) >= 4;
6329AMDGPUInstructionSelector::selectScratchSVAddr(
MachineOperand &Root)
const {
6332 int64_t ConstOffset;
6333 int64_t ImmOffset = 0;
6337 std::tie(PtrBase, ConstOffset, std::ignore) =
6338 getPtrBaseWithConstantOffset(Addr, *MRI);
6341 if (ConstOffset != 0 &&
6345 ImmOffset = ConstOffset;
6349 if (AddrDef->MI->getOpcode() != AMDGPU::G_PTR_ADD)
6350 return std::nullopt;
6352 Register RHS = AddrDef->MI->getOperand(2).getReg();
6353 if (RBI.getRegBank(
RHS, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID)
6354 return std::nullopt;
6356 Register LHS = AddrDef->MI->getOperand(1).getReg();
6359 if (OrigAddr != Addr) {
6360 if (!isFlatScratchBaseLegalSVImm(OrigAddr))
6361 return std::nullopt;
6363 if (!isFlatScratchBaseLegalSV(OrigAddr))
6364 return std::nullopt;
6367 if (checkFlatScratchSVSSwizzleBug(
RHS,
LHS, ImmOffset))
6368 return std::nullopt;
6370 unsigned CPol = selectScaleOffset(Root,
RHS,
true )
6374 if (LHSDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX) {
6375 int FI = LHSDef->MI->getOperand(1).getIndex();
6377 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
RHS); },
6379 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6380 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }
6389 return std::nullopt;
6392 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
RHS); },
6393 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
LHS); },
6394 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6395 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }
6400AMDGPUInstructionSelector::selectMUBUFScratchOffen(
MachineOperand &Root)
const {
6404 const SIMachineFunctionInfo *
Info =
MF->getInfo<SIMachineFunctionInfo>();
6409 Register HighBits = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6414 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32),
6418 return {{[=](MachineInstrBuilder &MIB) {
6421 [=](MachineInstrBuilder &MIB) {
6424 [=](MachineInstrBuilder &MIB) {
6429 [=](MachineInstrBuilder &MIB) {
6438 std::optional<int> FI;
6442 int64_t ConstOffset;
6443 std::tie(PtrBase, ConstOffset, std::ignore) =
6444 getPtrBaseWithConstantOffset(VAddr, *MRI);
6446 if (ConstOffset != 0) {
6447 if (TII.isLegalMUBUFImmOffset(ConstOffset) &&
6448 (!STI.privateMemoryResourceIsRangeChecked() ||
6449 VT->signBitIsZero(PtrBase))) {
6460 return {{[=](MachineInstrBuilder &MIB) {
6463 [=](MachineInstrBuilder &MIB) {
6469 [=](MachineInstrBuilder &MIB) {
6474 [=](MachineInstrBuilder &MIB) {
6479bool AMDGPUInstructionSelector::isDSOffsetLegal(
Register Base,
6484 if (STI.hasUsableDSOffset() || STI.unsafeDSOffsetFoldingEnabled())
6489 return VT->signBitIsZero(
Base);
6492bool AMDGPUInstructionSelector::isDSOffset2Legal(
Register Base, int64_t Offset0,
6494 unsigned Size)
const {
6495 if (Offset0 %
Size != 0 || Offset1 %
Size != 0)
6500 if (STI.hasUsableDSOffset() || STI.unsafeDSOffsetFoldingEnabled())
6505 return VT->signBitIsZero(
Base);
6510 return Addr->
getOpcode() == TargetOpcode::G_OR ||
6511 (Addr->
getOpcode() == TargetOpcode::G_PTR_ADD &&
6518bool AMDGPUInstructionSelector::isFlatScratchBaseLegal(
Register Addr)
const {
6526 if (STI.hasSignedScratchOffsets())
6532 if (AddrMI->
getOpcode() == TargetOpcode::G_PTR_ADD) {
6533 std::optional<ValueAndVReg> RhsValReg =
6539 if (RhsValReg && RhsValReg->Value.getSExtValue() < 0 &&
6540 RhsValReg->Value.getSExtValue() > -0x40000000)
6544 return VT->signBitIsZero(
LHS);
6549bool AMDGPUInstructionSelector::isFlatScratchBaseLegalSV(
Register Addr)
const {
6557 if (STI.hasSignedScratchOffsets())
6562 return VT->signBitIsZero(
RHS) &&
VT->signBitIsZero(
LHS);
6567bool AMDGPUInstructionSelector::isFlatScratchBaseLegalSVImm(
6571 if (STI.hasSignedScratchOffsets())
6576 std::optional<DefinitionAndSourceRegister> BaseDef =
6578 std::optional<ValueAndVReg> RHSOffset =
6588 (RHSOffset->Value.getSExtValue() < 0 &&
6589 RHSOffset->Value.getSExtValue() > -0x40000000)))
6592 Register LHS = BaseDef->MI->getOperand(1).getReg();
6593 Register RHS = BaseDef->MI->getOperand(2).getReg();
6594 return VT->signBitIsZero(
RHS) &&
VT->signBitIsZero(
LHS);
6597bool AMDGPUInstructionSelector::isUnneededShiftMask(
const MachineInstr &
MI,
6598 unsigned ShAmtBits)
const {
6599 assert(
MI.getOpcode() == TargetOpcode::G_AND);
6601 std::optional<APInt>
RHS =
6606 if (
RHS->countr_one() >= ShAmtBits)
6609 const APInt &LHSKnownZeros =
VT->getKnownZeroes(
MI.getOperand(1).getReg());
6610 return (LHSKnownZeros | *
RHS).countr_one() >= ShAmtBits;
6614AMDGPUInstructionSelector::selectMUBUFScratchOffset(
6617 const SIMachineFunctionInfo *
Info =
MF->getInfo<SIMachineFunctionInfo>();
6619 std::optional<DefinitionAndSourceRegister>
Def =
6621 assert(Def &&
"this shouldn't be an optional result");
6626 [=](MachineInstrBuilder &MIB) {
6629 [=](MachineInstrBuilder &MIB) {
6632 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
6643 if (!TII.isLegalMUBUFImmOffset(
Offset))
6651 [=](MachineInstrBuilder &MIB) {
6654 [=](MachineInstrBuilder &MIB) {
6662 !TII.isLegalMUBUFImmOffset(
Offset))
6666 [=](MachineInstrBuilder &MIB) {
6669 [=](MachineInstrBuilder &MIB) {
6676std::pair<Register, unsigned>
6677AMDGPUInstructionSelector::selectDS1Addr1OffsetImpl(
6679 int64_t ConstAddr = 0;
6683 std::tie(PtrBase,
Offset, std::ignore) =
6684 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
6687 if (isDSOffsetLegal(PtrBase,
Offset)) {
6689 return std::pair(PtrBase,
Offset);
6698 return std::pair(Root.
getReg(), 0);
6702AMDGPUInstructionSelector::selectDS1Addr1Offset(
MachineOperand &Root)
const {
6705 std::tie(
Reg,
Offset) = selectDS1Addr1OffsetImpl(Root);
6707 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
6713AMDGPUInstructionSelector::selectDS64Bit4ByteAligned(
MachineOperand &Root)
const {
6714 return selectDSReadWrite2(Root, 4);
6718AMDGPUInstructionSelector::selectDS128Bit8ByteAligned(
MachineOperand &Root)
const {
6719 return selectDSReadWrite2(Root, 8);
6723AMDGPUInstructionSelector::selectDSReadWrite2(
MachineOperand &Root,
6724 unsigned Size)
const {
6729 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
6731 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Offset+1); }
6735std::pair<Register, unsigned>
6736AMDGPUInstructionSelector::selectDSReadWrite2Impl(
MachineOperand &Root,
6737 unsigned Size)
const {
6738 int64_t ConstAddr = 0;
6742 std::tie(PtrBase,
Offset, std::ignore) =
6743 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
6746 int64_t OffsetValue0 =
Offset;
6748 if (isDSOffset2Legal(PtrBase, OffsetValue0, OffsetValue1,
Size)) {
6750 return std::pair(PtrBase, OffsetValue0 /
Size);
6759 return std::pair(Root.
getReg(), 0);
6767std::tuple<Register, int64_t, bool>
6768AMDGPUInstructionSelector::getPtrBaseWithConstantOffset(
6771 if (RootI->
getOpcode() != TargetOpcode::G_PTR_ADD)
6772 return {Root, 0,
false};
6775 std::optional<ValueAndVReg> MaybeOffset =
6778 return {Root, 0,
false};
6798 B.buildInstr(AMDGPU::S_MOV_B32)
6801 B.buildInstr(AMDGPU::S_MOV_B32)
6808 B.buildInstr(AMDGPU::REG_SEQUENCE)
6811 .addImm(AMDGPU::sub0)
6813 .addImm(AMDGPU::sub1);
6818 B.buildInstr(AMDGPU::S_MOV_B64)
6823 B.buildInstr(AMDGPU::REG_SEQUENCE)
6826 .addImm(AMDGPU::sub0_sub1)
6828 .addImm(AMDGPU::sub2_sub3);
6835 uint64_t DefaultFormat =
TII.getDefaultRsrcDataFormat();
6844 uint64_t DefaultFormat =
TII.getDefaultRsrcDataFormat();
6851AMDGPUInstructionSelector::MUBUFAddressData
6852AMDGPUInstructionSelector::parseMUBUFAddress(
Register Src)
const {
6853 MUBUFAddressData
Data;
6859 std::tie(PtrBase,
Offset, std::ignore) =
6860 getPtrBaseWithConstantOffset(Src, *MRI);
6866 if (MachineInstr *InputAdd
6868 Data.N2 = InputAdd->getOperand(1).getReg();
6869 Data.N3 = InputAdd->getOperand(2).getReg();
6884bool AMDGPUInstructionSelector::shouldUseAddr64(MUBUFAddressData Addr)
const {
6890 const RegisterBank *N0Bank = RBI.getRegBank(Addr.N0, *MRI, TRI);
6891 return N0Bank->
getID() == AMDGPU::VGPRRegBankID;
6897void AMDGPUInstructionSelector::splitIllegalMUBUFOffset(
6899 if (TII.isLegalMUBUFImmOffset(ImmOffset))
6903 SOffset = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
6904 B.buildInstr(AMDGPU::S_MOV_B32)
6910bool AMDGPUInstructionSelector::selectMUBUFAddr64Impl(
6915 if (!STI.hasAddr64() || STI.useFlatForGlobal())
6918 MUBUFAddressData AddrData = parseMUBUFAddress(Root.
getReg());
6919 if (!shouldUseAddr64(AddrData))
6925 Offset = AddrData.Offset;
6931 if (RBI.getRegBank(N2, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
6933 if (RBI.getRegBank(N3, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
6946 }
else if (RBI.getRegBank(N0, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
6957 splitIllegalMUBUFOffset(
B, SOffset,
Offset);
6961bool AMDGPUInstructionSelector::selectMUBUFOffsetImpl(
6966 if (STI.useFlatForGlobal())
6969 MUBUFAddressData AddrData = parseMUBUFAddress(Root.
getReg());
6970 if (shouldUseAddr64(AddrData))
6976 Offset = AddrData.Offset;
6982 splitIllegalMUBUFOffset(
B, SOffset,
Offset);
6987AMDGPUInstructionSelector::selectMUBUFAddr64(
MachineOperand &Root)
const {
6993 if (!selectMUBUFAddr64Impl(Root, VAddr, RSrcReg, SOffset,
Offset))
6999 [=](MachineInstrBuilder &MIB) {
7002 [=](MachineInstrBuilder &MIB) {
7005 [=](MachineInstrBuilder &MIB) {
7008 else if (STI.hasRestrictedSOffset())
7009 MIB.
addReg(AMDGPU::SGPR_NULL);
7013 [=](MachineInstrBuilder &MIB) {
7023AMDGPUInstructionSelector::selectMUBUFOffset(
MachineOperand &Root)
const {
7028 if (!selectMUBUFOffsetImpl(Root, RSrcReg, SOffset,
Offset))
7032 [=](MachineInstrBuilder &MIB) {
7035 [=](MachineInstrBuilder &MIB) {
7038 else if (STI.hasRestrictedSOffset())
7039 MIB.
addReg(AMDGPU::SGPR_NULL);
7051AMDGPUInstructionSelector::selectBUFSOffset(
MachineOperand &Root)
const {
7056 SOffset = AMDGPU::SGPR_NULL;
7058 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); }}};
7062static std::optional<uint64_t>
7066 if (!OffsetVal || !
isInt<32>(*OffsetVal))
7067 return std::nullopt;
7068 return Lo_32(*OffsetVal);
7072AMDGPUInstructionSelector::selectSMRDBufferImm(
MachineOperand &Root)
const {
7073 std::optional<uint64_t> OffsetVal =
7078 std::optional<int64_t> EncodedImm =
7083 return {{ [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); } }};
7087AMDGPUInstructionSelector::selectSMRDBufferImm32(
MachineOperand &Root)
const {
7094 std::optional<int64_t> EncodedImm =
7099 return {{ [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); } }};
7103AMDGPUInstructionSelector::selectSMRDBufferSgprImm(
MachineOperand &Root)
const {
7111 return std::nullopt;
7113 std::optional<int64_t> EncodedOffset =
7116 return std::nullopt;
7118 assert(MRI->getType(SOffset).getSizeInBits() == 32);
7119 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
7120 [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedOffset); }}};
7123std::pair<Register, unsigned>
7124AMDGPUInstructionSelector::selectVOP3PMadMixModsImpl(
MachineOperand &Root,
7125 bool &Matched)
const {
7130 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
7140 const auto CheckAbsNeg = [&]() {
7145 std::tie(Src, ModsTmp) = selectVOP3ModsImpl(Src);
7176AMDGPUInstructionSelector::selectVOP3PMadMixModsExt(
7181 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7186 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
7187 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
7192AMDGPUInstructionSelector::selectVOP3PMadMixMods(
MachineOperand &Root)
const {
7196 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7199 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
7200 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
7205AMDGPUInstructionSelector::selectVOP3PMadMixModsExtNeg(
7210 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7215 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
7216 [=](MachineInstrBuilder &MIB) {
7223AMDGPUInstructionSelector::selectVOP3PMadMixModsNeg(
7228 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7231 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
7232 [=](MachineInstrBuilder &MIB) {
7238bool AMDGPUInstructionSelector::selectSBarrierSignalIsfirst(
7242 Register CCReg =
I.getOperand(0).getReg();
7247 BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM))
7248 .
addImm(
I.getOperand(2).getImm());
7252 I.eraseFromParent();
7253 return RBI.constrainGenericRegister(CCReg, AMDGPU::SReg_32_XM0_XEXECRegClass,
7257bool AMDGPUInstructionSelector::selectSGetBarrierState(
7261 const MachineOperand &BarOp =
I.getOperand(2);
7262 std::optional<int64_t> BarValImm =
7266 auto CopyMIB =
BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
7270 MachineInstrBuilder MIB;
7271 unsigned Opc = BarValImm ? AMDGPU::S_GET_BARRIER_STATE_IMM
7272 : AMDGPU::S_GET_BARRIER_STATE_M0;
7275 auto DstReg =
I.getOperand(0).getReg();
7277 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
7278 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
7284 I.eraseFromParent();
7289 if (HasInlineConst) {
7293 case Intrinsic::amdgcn_s_barrier_join:
7294 return AMDGPU::S_BARRIER_JOIN_IMM;
7295 case Intrinsic::amdgcn_s_wakeup_barrier:
7296 return AMDGPU::S_WAKEUP_BARRIER_IMM;
7297 case Intrinsic::amdgcn_s_get_named_barrier_state:
7298 return AMDGPU::S_GET_BARRIER_STATE_IMM;
7304 case Intrinsic::amdgcn_s_barrier_join:
7305 return AMDGPU::S_BARRIER_JOIN_M0;
7306 case Intrinsic::amdgcn_s_wakeup_barrier:
7307 return AMDGPU::S_WAKEUP_BARRIER_M0;
7308 case Intrinsic::amdgcn_s_get_named_barrier_state:
7309 return AMDGPU::S_GET_BARRIER_STATE_M0;
7314bool AMDGPUInstructionSelector::selectNamedBarrierInit(
7318 const MachineOperand &BarOp =
I.getOperand(1);
7319 const MachineOperand &CntOp =
I.getOperand(2);
7323 if (IntrID == Intrinsic::amdgcn_s_barrier_signal_var) {
7324 std::optional<int64_t> CntImm =
7326 if (CntImm && *CntImm == 0) {
7327 std::optional<int64_t> BarValImm =
7330 auto BarID = ((*BarValImm) >> 4) & 0x3F;
7331 BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::S_BARRIER_SIGNAL_IMM))
7333 I.eraseFromParent();
7340 Register TmpReg0 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7346 Register TmpReg1 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7353 Register TmpReg2 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7359 Register TmpReg3 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7360 constexpr unsigned ShAmt = 16;
7366 Register TmpReg4 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7376 unsigned Opc = IntrID == Intrinsic::amdgcn_s_barrier_init
7377 ? AMDGPU::S_BARRIER_INIT_M0
7378 : AMDGPU::S_BARRIER_SIGNAL_M0;
7379 MachineInstrBuilder MIB;
7382 I.eraseFromParent();
7386bool AMDGPUInstructionSelector::selectNamedBarrierInst(
7390 MachineOperand BarOp = IntrID == Intrinsic::amdgcn_s_get_named_barrier_state
7393 std::optional<int64_t> BarValImm =
7398 Register TmpReg0 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7404 Register TmpReg1 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7410 auto CopyMIB =
BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
7415 MachineInstrBuilder MIB;
7419 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state) {
7420 auto DstReg =
I.getOperand(0).getReg();
7422 TRI.getConstrainedRegClassForReg(DstReg, *MRI);
7423 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
7429 auto BarId = ((*BarValImm) >> 4) & 0x3F;
7433 I.eraseFromParent();
7440 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
7441 "Expected G_CONSTANT");
7442 MIB.
addImm(
MI.getOperand(1).getCImm()->getSExtValue());
7448 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
7449 "Expected G_CONSTANT");
7450 MIB.
addImm(-
MI.getOperand(1).getCImm()->getSExtValue());
7456 const MachineOperand &
Op =
MI.getOperand(1);
7457 assert(
MI.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1);
7458 MIB.
addImm(
Op.getFPImm()->getValueAPF().bitcastToAPInt().getZExtValue());
7461void AMDGPUInstructionSelector::renderCountTrailingOnesImm(
7463 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
7464 "Expected G_CONSTANT");
7465 MIB.
addImm(
MI.getOperand(1).getCImm()->getValue().countTrailingOnes());
7473 const MachineOperand &
Op =
MI.getOperand(OpIdx);
7484 MIB.
addImm(
MI.getOperand(OpIdx).getImm() != 0);
7490 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7494void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_0_0(
7496 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7501void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_0_1(
7503 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7504 MIB.
addImm((
MI.getOperand(OpIdx).getImm() & 0x1)
7509void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_1_0(
7511 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7516void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_1_1(
7518 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7519 MIB.
addImm((
MI.getOperand(OpIdx).getImm() & 0x2)
7524void AMDGPUInstructionSelector::renderDstSelToOpSelXForm(
7526 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7531void AMDGPUInstructionSelector::renderSrcSelToOpSelXForm(
7533 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7538void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_2_0(
7540 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7545void AMDGPUInstructionSelector::renderDstSelToOpSel3XFormXForm(
7547 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7548 MIB.
addImm((
MI.getOperand(OpIdx).getImm() & 0x2)
7556 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7557 MIB.
addImm(
MI.getOperand(OpIdx).getImm() &
7565 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7566 const bool Swizzle =
MI.getOperand(OpIdx).getImm() &
7572void AMDGPUInstructionSelector::renderExtractCpolSetGLC(
7574 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7575 const uint32_t Cpol =
MI.getOperand(OpIdx).getImm() &
7584 const APFloat &APF =
MI.getOperand(1).getFPImm()->getValueAPF();
7586 assert(ExpVal != INT_MIN);
7597 MIB.
addImm((
MI.getOperand(OpIdx).getImm() + 3) % 4);
7604 if (
MI.getOperand(OpIdx).getImm())
7606 MIB.
addImm((int64_t)Mods);
7613 if (
MI.getOperand(OpIdx).getImm())
7615 MIB.
addImm((int64_t)Mods);
7621 unsigned Val =
MI.getOperand(OpIdx).getImm();
7629 MIB.
addImm((int64_t)Mods);
7635 uint32_t
V =
MI.getOperand(2).getImm();
7638 if (!Subtarget->hasSafeCUPrefetch())
7644void AMDGPUInstructionSelector::renderScaledMAIIntrinsicOperand(
7646 unsigned Val =
MI.getOperand(OpIdx).getImm();
7655bool AMDGPUInstructionSelector::isInlineImmediate(
const APInt &
Imm)
const {
7656 return TII.isInlineConstant(
Imm);
7659bool AMDGPUInstructionSelector::isInlineImmediate(
const APFloat &
Imm)
const {
7660 return TII.isInlineConstant(
Imm);
MachineInstrBuilder MachineInstrBuilder & DefMI
static unsigned getIntrinsicID(const SDNode *N)
#define GET_GLOBALISEL_PREDICATES_INIT
#define GET_GLOBALISEL_TEMPORARIES_INIT
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
static bool isShlHalf(const MachineInstr *MI, const MachineRegisterInfo &MRI)
Test if the MI is shift left with half bits, such as reg0:2n =G_SHL reg1:2n, CONST(n)
static bool isNoUnsignedWrap(MachineInstr *Addr)
static Register buildOffsetSrc(MachineIRBuilder &B, MachineRegisterInfo &MRI, const SIInstrInfo &TII, Register BasePtr)
unsigned getNamedBarrierOp(bool HasInlineConst, Intrinsic::ID IntrID)
static Register getLegalRegBank(Register NewReg, Register RootReg, MachineInstr &Use, const AMDGPURegisterBankInfo &RBI, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const SIInstrInfo &TII)
static bool checkRB(Register Reg, unsigned int RBNo, const AMDGPURegisterBankInfo &RBI, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI)
static unsigned updateMods(SrcStatus HiStat, SrcStatus LoStat, unsigned Mods)
static bool isTruncHalf(const MachineInstr *MI, const MachineRegisterInfo &MRI)
Test if the MI is truncating to half, such as reg0:n = G_TRUNC reg1:2n
static Register getWaveAddress(const MachineInstr *Def)
static bool isExtractHiElt(MachineRegisterInfo &MRI, Register In, Register &Out)
static bool shouldUseAndMask(unsigned Size, unsigned &Mask)
static std::pair< unsigned, uint8_t > BitOp3_Op(Register R, SmallVectorImpl< Register > &Src, const MachineRegisterInfo &MRI)
static TypeClass isVectorOfTwoOrScalar(Register Reg, const MachineRegisterInfo &MRI)
static bool isLaneMaskFromSameBlock(Register Reg, MachineRegisterInfo &MRI, MachineBasicBlock *MBB)
static bool parseTexFail(uint64_t TexFailCtrl, bool &TFE, bool &LWE, bool &IsTexFail)
static void addZeroImm(MachineInstrBuilder &MIB)
static unsigned gwsIntrinToOpcode(unsigned IntrID)
static bool isConstant(const MachineInstr &MI)
static bool isSameBitWidth(Register Reg1, Register Reg2, const MachineRegisterInfo &MRI)
static Register buildRegSequence(SmallVectorImpl< Register > &Elts, MachineInstr *InsertPt, MachineRegisterInfo &MRI)
static Register buildRSRC(MachineIRBuilder &B, MachineRegisterInfo &MRI, uint32_t FormatLo, uint32_t FormatHi, Register BasePtr)
Return a resource descriptor for use with an arbitrary 64-bit pointer.
static bool isAsyncLDSDMA(Intrinsic::ID Intr)
static std::pair< Register, unsigned > computeIndirectRegIndex(MachineRegisterInfo &MRI, const SIRegisterInfo &TRI, const TargetRegisterClass *SuperRC, Register IdxReg, unsigned EltSize, GISelValueTracking &ValueTracking)
Return the register to use for the index value, and the subregister to use for the indirectly accesse...
static unsigned getLogicalBitOpcode(unsigned Opc, bool Is64)
static std::pair< Register, SrcStatus > getLastSameOrNeg(Register Reg, const MachineRegisterInfo &MRI, SearchOptions SO, int MaxDepth=3)
static Register stripCopy(Register Reg, MachineRegisterInfo &MRI)
static std::optional< std::pair< Register, SrcStatus > > calcNextStatus(std::pair< Register, SrcStatus > Curr, const MachineRegisterInfo &MRI)
static Register stripBitCast(Register Reg, MachineRegisterInfo &MRI)
static std::optional< uint64_t > getConstantZext32Val(Register Reg, const MachineRegisterInfo &MRI)
Get an immediate that must be 32-bits, and treated as zero extended.
static bool isValidToPack(SrcStatus HiStat, SrcStatus LoStat, Register NewReg, Register RootReg, const SIInstrInfo &TII, const MachineRegisterInfo &MRI)
static int getV_CMPOpcode(CmpInst::Predicate P, unsigned Size, const GCNSubtarget &ST)
static SmallVector< std::pair< Register, SrcStatus > > getSrcStats(Register Reg, const MachineRegisterInfo &MRI, SearchOptions SO, int MaxDepth=3)
static bool isUnmergeHalf(const MachineInstr *MI, const MachineRegisterInfo &MRI)
Test function, if the MI is reg0:n, reg1:n = G_UNMERGE_VALUES reg2:2n
static SrcStatus getNegStatus(Register Reg, SrcStatus S, const MachineRegisterInfo &MRI)
static bool isVCmpResult(Register Reg, MachineRegisterInfo &MRI)
static Register buildAddr64RSrc(MachineIRBuilder &B, MachineRegisterInfo &MRI, const SIInstrInfo &TII, Register BasePtr)
static bool isLshrHalf(const MachineInstr *MI, const MachineRegisterInfo &MRI)
Test if the MI is logic shift right with half bits, such as reg0:2n =G_LSHR reg1:2n,...
static void selectWMMAModsNegAbs(unsigned ModOpcode, unsigned &Mods, SmallVectorImpl< Register > &Elts, Register &Src, MachineInstr *InsertPt, MachineRegisterInfo &MRI)
This file declares the targeting of the InstructionSelector class for AMDGPU.
AMDGPU Register Bank Select
This file declares the targeting of the RegisterBankInfo class for AMDGPU.
The AMDGPU TargetMachine interface definition for hw codegen targets.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool isAllZeros(StringRef Arr)
Return true if the array is empty or all zeros.
Provides analysis for querying information about KnownBits during GISel passes.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static std::vector< std::pair< int, unsigned > > Swizzle(std::vector< std::pair< int, unsigned > > Src, R600InstrInfo::BankSwizzle Swz)
This is used to control valid status that current MI supports.
bool checkOptions(SrcStatus Stat) const
SearchOptions(Register Reg, const MachineRegisterInfo &MRI)
AMDGPUInstructionSelector(const GCNSubtarget &STI, const AMDGPURegisterBankInfo &RBI)
static const char * getName()
bool select(MachineInstr &I) override
Select the (possibly generic) instruction I to only use target-specific opcodes.
void setupMF(MachineFunction &MF, GISelValueTracking *VT, CodeGenCoverage *CoverageInfo, ProfileSummaryInfo *PSI, BlockFrequencyInfo *BFI) override
Setup per-MF executor state.
uint32_t getLDSSize() const
LLVM_READONLY int getExactLog2Abs() const
Class for arbitrary precision integers.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
int64_t getSExtValue() const
Get sign extended value.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ FCMP_TRUE
1 1 1 1 Always true (always folded)
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ ICMP_ULT
unsigned less than
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ ICMP_ULE
unsigned less or equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ FCMP_FALSE
0 0 0 0 Always false (always folded)
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
DILocation * get() const
Get the underlying DILocation.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
void checkSubtargetFeatures(const Function &F) const
Diagnose inconsistent subtarget features before attempting to codegen function F.
std::optional< SmallVector< std::function< void(MachineInstrBuilder &)>, 4 > > ComplexRendererFns
virtual void setupMF(MachineFunction &mf, GISelValueTracking *vt, CodeGenCoverage *covinfo=nullptr, ProfileSummaryInfo *psi=nullptr, BlockFrequencyInfo *bfi=nullptr)
Setup per-MF executor state.
CodeGenCoverage * CoverageInfo
Register getSourceReg(unsigned I) const
Returns the I'th source register.
unsigned getNumSources() const
Returns the number of source registers.
Represents a G_UNMERGE_VALUES.
unsigned getNumDefs() const
Returns the number of def registers.
Register getSourceReg() const
Get the unmerge source register.
constexpr bool isScalar() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
constexpr bool isVector() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr unsigned getAddressSpace() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
TypeSize getValue() const
int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const
Returns the value of the specified operand constraint if it is present.
bool hasSuperClassEq(const MCRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
unsigned getID() const
getID() - Return the register class ID number.
bool hasSubClassEq(const MCRegisterClass *RC) const
Returns true if RC is a sub-class of or equal to this class.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void setReturnAddressIsTaken(bool s)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Helper class to build MachineInstr.
const MachineInstrBuilder & setMemRefs(ArrayRef< MachineMemOperand * > MMOs) const
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
bool getFlag(MIFlag Flag) const
Return whether an MI flag is set.
unsigned getNumOperands() const
Retuns the total number of operands.
LLVM_ABI void tieOperands(unsigned DefIdx, unsigned UseIdx)
Add a tie between the register operands at DefIdx and UseIdx.
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
LocationSize getSize() const
Return the size in bytes of the memory reference.
unsigned getAddrSpace() const
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
const MachinePointerInfo & getPointerInfo() const
Flags getFlags() const
Return the raw flags of the source value,.
const Value * getValue() const
Return the base address of the memory access.
Align getBaseAlign() const
Return the minimum known alignment in bytes of the base address, without the offset.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
const ConstantInt * getCImm() const
void setImm(int64_t immVal)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
static MachineOperand CreateImm(int64_t Val)
bool isEarlyClobber() const
Register getReg() const
getReg - Returns the register number.
bool isInternalRead() const
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
const RegisterBank * getRegBankOrNull(Register Reg) const
Return the register bank of Reg, or null if Reg has not been assigned a register bank or has been ass...
LLVM_ABI Register cloneVirtualRegister(Register VReg, StringRef Name="")
Create and return a new virtual register in the function with the same attributes as the given regist...
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Analysis providing profile information.
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
This class implements the register bank concept.
unsigned getID() const
Get the identifier of this register bank.
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
static unsigned getDSShaderTypeValue(const MachineFunction &MF)
static unsigned getSubRegFromChannel(unsigned Channel, unsigned NumRegs=1)
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static bool isGenericOpcode(unsigned Opc)
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
A Use represents the edge between a Value definition and its users.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CONSTANT_ADDRESS_32BIT
Address space for 32-bit constant memory.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ PRIVATE_ADDRESS
Address space for private memory.
@ BUFFER_RESOURCE
Address space for 128-bit buffer resources.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
LLVM_READONLY const MIMGG16MappingInfo * getMIMGG16MappingInfo(unsigned G)
int getMIMGOpcode(unsigned BaseOpcode, unsigned MIMGEncoding, unsigned VDataDwords, unsigned VAddrDwords)
std::optional< int64_t > getSMRDEncodedLiteralOffset32(const MCSubtargetInfo &ST, int64_t ByteOffset)
bool isGFX12Plus(const MCSubtargetInfo &STI)
constexpr int64_t getNullPointerValue(unsigned AS)
Get the null pointer value for the given address space.
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, OpName NamedIdx)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
bool hasSMRDSignedImmOffset(const MCSubtargetInfo &ST)
LLVM_READONLY int32_t getGlobalSaddrOp(uint32_t Opcode)
bool isGFX13Plus(const MCSubtargetInfo &STI)
bool isGFX11Plus(const MCSubtargetInfo &STI)
bool isGFX10Plus(const MCSubtargetInfo &STI)
std::optional< int64_t > getSMRDEncodedOffset(const MCSubtargetInfo &ST, int64_t ByteOffset, bool IsBuffer, bool HasSOffset)
LLVM_READONLY const MIMGDimInfo * getMIMGDimInfo(unsigned DimEnum)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
Intrinsic::ID getIntrinsicID(const MachineInstr &I)
Return the intrinsic ID for opcodes with the G_AMDGPU_INTRIN_ prefix.
std::pair< Register, unsigned > getBaseWithConstantOffset(MachineRegisterInfo &MRI, Register Reg, GISelValueTracking *ValueTracking=nullptr, bool CheckNUW=false)
Returns base register and constant offset.
const ImageDimIntrinsicInfo * getImageDimIntrinsicInfo(unsigned Intr)
IndexMode
ARM Index Modes.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
operand_type_match m_Reg()
SpecificConstantMatch m_SpecificICst(const APInt &RequestedValue)
Matches a constant equal to RequestedValue.
GInstrBind< GBuildVector > m_GBuildVector(GBuildVector *&Inst)
GCstAndRegMatch m_GCst(std::optional< ValueAndVReg > &ValReg)
UnaryOp_match< SrcTy, TargetOpcode::COPY > m_Copy(SrcTy &&Src)
UnaryOp_match< SrcTy, TargetOpcode::G_ZEXT > m_GZExt(const SrcTy &Src)
BinaryOp_match< LHS, RHS, TargetOpcode::G_XOR, true > m_GXor(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_SEXT > m_GSExt(const SrcTy &Src)
UnaryOp_match< SrcTy, TargetOpcode::G_FPEXT > m_GFPExt(const SrcTy &Src)
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
ConstantMatch< APInt > m_ICst(APInt &Cst)
SpecificConstantMatch m_AllOnesInt()
BinaryOp_match< LHS, RHS, TargetOpcode::G_OR, true > m_GOr(const LHS &L, const RHS &R)
ICstOrSplatMatch< APInt > m_ICstOrSplat(APInt &Cst)
ImplicitDefMatch m_GImplicitDef()
GInstrBind< GConcatVectors > m_GConcatVectors(GConcatVectors *&Inst)
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
GInstrBind< GUnmerge > m_GUnmerge(GUnmerge *&Inst)
Instruction binders for ops with no operand-form matcher (constant-immediate or variadic-source ops).
BinaryOp_match< LHS, RHS, TargetOpcode::G_SUB > m_GSub(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, TargetOpcode::G_ASHR, false > m_GAShr(const LHS &L, const RHS &R)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
BinaryOp_match< LHS, RHS, TargetOpcode::G_PTR_ADD, false > m_GPtrAdd(const LHS &L, const RHS &R)
SpecificRegisterMatch m_SpecificReg(Register RequestedReg)
Matches a register only if it is equal to RequestedReg.
BinaryOp_match< LHS, RHS, TargetOpcode::G_SHL, false > m_GShl(const LHS &L, const RHS &R)
GFrameIndexMatch m_GFrameIndex(int &FI)
Or< Preds... > m_any_of(Preds &&... preds)
BinaryOp_match< LHS, RHS, TargetOpcode::G_AND, true > m_GAnd(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_BITCAST > m_GBitcast(const SrcTy &Src)
bind_ty< MachineInstr * > m_MInstr(MachineInstr *&MI)
UnaryOp_match< SrcTy, TargetOpcode::G_FNEG > m_GFNeg(const SrcTy &Src)
GFCstOrSplatGFCstMatch m_GFCstOrSplat(std::optional< FPValueAndVReg > &FPValReg)
UnaryOp_match< SrcTy, TargetOpcode::G_FABS > m_GFabs(const SrcTy &Src)
BinaryOp_match< LHS, RHS, TargetOpcode::G_LSHR, false > m_GLShr(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_ANYEXT > m_GAnyExt(const SrcTy &Src)
ShuffleVectorMatch< Src1Ty, Src2Ty > m_GShuffleVector(const Src1Ty &Src1, const Src2Ty &Src2, ArrayRef< int > &Mask)
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
BinaryOp_match< LHS, RHS, TargetOpcode::G_MUL, true > m_GMul(const LHS &L, const RHS &R)
UnaryOp_match< SrcTy, TargetOpcode::G_TRUNC > m_GTrunc(const SrcTy &Src)
auto m_BinOp()
Match an arbitrary binary operation and ignore it.
NodeAddr< DefNode * > Def
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI Register getFunctionLiveInPhysReg(MachineFunction &MF, const TargetInstrInfo &TII, MCRegister PhysReg, const TargetRegisterClass &RC, const DebugLoc &DL, LLT RegTy=LLT())
Return a virtual register corresponding to the incoming argument register PhysReg.
LLVM_ABI bool isBuildVectorAllZeros(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndef=false)
Return true if the specified instruction is a G_BUILD_VECTOR or G_BUILD_VECTOR_TRUNC where all of the...
LLVM_ABI Register constrainOperandRegClass(const MachineFunction &MF, const TargetRegisterInfo &TRI, MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const RegisterBankInfo &RBI, MachineInstr &InsertPt, const TargetRegisterClass &RegClass, MachineOperand &RegMO)
Constrain the Register operand OpIdx, so that it is now constrained to the TargetRegisterClass passed...
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
PointerUnion< const TargetRegisterClass *, const RegisterBank * > RegClassOrRegBank
Convenient type to represent either a register class or a register bank.
LLVM_ABI const ConstantFP * getConstantFPVRegVal(Register VReg, const MachineRegisterInfo &MRI)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI std::optional< APInt > getIConstantVRegVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT, return the corresponding value.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI void constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
@ Load
The value being inserted comes from a load (InsertElement only).
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI MachineInstr * getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, folding away any trivial copies.
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI std::optional< int64_t > getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT fits in int64_t returns it.
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI std::optional< ValueAndVReg > getAnyConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true, bool LookThroughAnyExt=false)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT or G_FCONST...
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
@ Or
Bitwise or logical OR of integers.
@ Mul
Product of integers.
@ SMax
Signed integer max implemented in terms of select(cmp()).
@ And
Bitwise or logical AND of integers.
@ Sub
Subtraction of integers.
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
LLVM_ABI std::optional< DefinitionAndSourceRegister > getDefSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, and underlying value Register folding away any copies.
LLVM_ABI Register getSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the source register for Reg, folding away any trivial copies.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
constexpr RegState getUndefRegState(bool B)
@ Default
The result value is uniform if and only if all operands are uniform.
MCRegisterClass TargetRegisterClass
unsigned AtomicNoRetBaseOpcode
static KnownBits makeConstant(const APInt &C)
Create known bits from a known constant.
static KnownBits add(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false, bool SelfAdd=false)
Compute knownbits resulting from addition of LHS and RHS.
int64_t Offset
Offset - This is an offset from the base Value*.
PointerUnion< const Value *, const PseudoSourceValue * > V
This is the IR pointer value for the access, or it is null if unknown.