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));
103 MachineOperand &Dst =
MI.getOperand(0);
104 MachineOperand &Src =
MI.getOperand(1);
111 = TRI.getConstrainedRegClassForOperand(Dst, *MRI);
113 = TRI.getConstrainedRegClassForOperand(Src, *MRI);
114 if (!DstRC || DstRC != SrcRC)
117 if (!RBI.constrainGenericRegister(Dst.getReg(), *DstRC, *MRI) ||
118 !RBI.constrainGenericRegister(Src.getReg(), *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 const MachineOperand &Src =
I.getOperand(1);
133 MachineOperand &Dst =
I.getOperand(0);
137 if (isVCC(DstReg, *MRI)) {
138 if (SrcReg == AMDGPU::SCC) {
140 = TRI.getConstrainedRegClassForOperand(Dst, *MRI);
143 return RBI.constrainGenericRegister(DstReg, *RC, *MRI);
146 if (!isVCC(SrcReg, *MRI)) {
148 if (!RBI.constrainGenericRegister(DstReg, *TRI.getBoolRC(), *MRI))
152 = TRI.getConstrainedRegClassForOperand(Src, *MRI);
154 std::optional<ValueAndVReg> ConstVal =
158 STI.isWave64() ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
160 .
addImm(ConstVal->Value.getBoolValue() ? -1 : 0);
162 Register MaskedReg = MRI->createVirtualRegister(SrcRC);
169 assert(Subtarget->useRealTrue16Insts());
170 const int64_t NoMods = 0;
171 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::V_AND_B16_t16_e64), MaskedReg)
177 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::V_CMP_NE_U16_t16_e64), DstReg)
184 bool IsSGPR = TRI.isSGPRClass(SrcRC);
185 unsigned AndOpc = IsSGPR ? AMDGPU::S_AND_B32 : AMDGPU::V_AND_B32_e32;
192 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::V_CMP_NE_U32_e64), DstReg)
198 if (!MRI->getRegClassOrNull(SrcReg))
199 MRI->setRegClass(SrcReg, SrcRC);
205 TRI.getConstrainedRegClassForOperand(Dst, *MRI);
206 if (RC && !RBI.constrainGenericRegister(DstReg, *RC, *MRI))
212 for (
const MachineOperand &MO :
I.operands()) {
213 if (MO.getReg().isPhysical())
217 TRI.getConstrainedRegClassForOperand(MO, *MRI);
220 RBI.constrainGenericRegister(MO.getReg(), *RC, *MRI);
225bool AMDGPUInstructionSelector::selectCOPY_SCC_VCC(
MachineInstr &
I)
const {
228 Register VCCReg =
I.getOperand(1).getReg();
232 if (STI.hasScalarCompareEq64()) {
234 STI.isWave64() ? AMDGPU::S_CMP_LG_U64 : AMDGPU::S_CMP_LG_U32;
237 Register DeadDst = MRI->createVirtualRegister(&AMDGPU::SReg_64RegClass);
238 Cmp =
BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_OR_B64), DeadDst)
245 Register DstReg =
I.getOperand(0).getReg();
249 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_32RegClass, *MRI);
252bool AMDGPUInstructionSelector::selectCOPY_VCC_SCC(
MachineInstr &
I)
const {
256 Register DstReg =
I.getOperand(0).getReg();
257 Register SrcReg =
I.getOperand(1).getReg();
258 std::optional<ValueAndVReg> Arg =
262 const int64_t
Value = Arg->Value.getZExtValue();
264 unsigned Opcode = STI.isWave64() ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
271 return RBI.constrainGenericRegister(DstReg, *TRI.getBoolRC(), *MRI);
277 unsigned SelectOpcode =
278 STI.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
288bool AMDGPUInstructionSelector::selectReadAnyLane(
MachineInstr &
I)
const {
289 Register DstReg =
I.getOperand(0).getReg();
290 Register SrcReg =
I.getOperand(1).getReg();
295 auto RFL =
BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
303bool AMDGPUInstructionSelector::selectPHI(
MachineInstr &
I)
const {
304 const Register DefReg =
I.getOperand(0).getReg();
305 const LLT DefTy = MRI->getType(DefReg);
317 MRI->getRegClassOrRegBank(DefReg);
328 DefRC = TRI.getRegClassForTypeOnBank(DefTy, RB);
337 for (
unsigned i = 1; i !=
I.getNumOperands(); i += 2) {
338 const Register SrcReg =
I.getOperand(i).getReg();
340 const RegisterBank *RB = MRI->getRegBankOrNull(SrcReg);
342 const LLT SrcTy = MRI->getType(SrcReg);
344 TRI.getRegClassForTypeOnBank(SrcTy, *RB);
345 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI))
350 I.setDesc(TII.get(TargetOpcode::PHI));
351 return RBI.constrainGenericRegister(DefReg, *DefRC, *MRI);
357 unsigned SubIdx)
const {
361 Register DstReg = MRI->createVirtualRegister(&SubRC);
364 unsigned ComposedSubIdx = TRI.composeSubRegIndices(MO.
getSubReg(), SubIdx);
366 BuildMI(*BB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::COPY), DstReg)
392 return Is64 ? AMDGPU::S_AND_B64 : AMDGPU::S_AND_B32;
394 return Is64 ? AMDGPU::S_OR_B64 : AMDGPU::S_OR_B32;
396 return Is64 ? AMDGPU::S_XOR_B64 : AMDGPU::S_XOR_B32;
402bool AMDGPUInstructionSelector::selectG_AND_OR_XOR(
MachineInstr &
I)
const {
403 Register DstReg =
I.getOperand(0).getReg();
404 unsigned Size = RBI.getSizeInBits(DstReg, *MRI, TRI);
406 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
407 if (DstRB->
getID() != AMDGPU::SGPRRegBankID &&
408 DstRB->
getID() != AMDGPU::VCCRegBankID)
411 bool Is64 =
Size > 32 || (DstRB->
getID() == AMDGPU::VCCRegBankID &&
424bool AMDGPUInstructionSelector::selectG_ADD_SUB(
MachineInstr &
I)
const {
427 Register DstReg =
I.getOperand(0).getReg();
429 LLT Ty = MRI->getType(DstReg);
434 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
435 const bool IsSALU = DstRB->
getID() == AMDGPU::SGPRRegBankID;
436 const bool Sub =
I.getOpcode() == TargetOpcode::G_SUB;
440 const unsigned Opc =
Sub ? AMDGPU::S_SUB_U32 : AMDGPU::S_ADD_U32;
443 .
add(
I.getOperand(1))
444 .
add(
I.getOperand(2))
451 if (STI.hasAddNoCarryInsts()) {
452 const unsigned Opc =
Sub ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_ADD_U32_e64;
453 I.setDesc(TII.get(
Opc));
460 const unsigned Opc =
Sub ? AMDGPU::V_SUB_CO_U32_e64 : AMDGPU::V_ADD_CO_U32_e64;
462 Register UnusedCarry = MRI->createVirtualRegister(TRI.getWaveMaskRegClass());
466 .
add(
I.getOperand(1))
467 .
add(
I.getOperand(2))
474 assert(!
Sub &&
"illegal sub should not reach here");
477 = IsSALU ? AMDGPU::SReg_64_XEXECRegClass : AMDGPU::VReg_64RegClass;
479 = IsSALU ? AMDGPU::SReg_32RegClass : AMDGPU::VGPR_32RegClass;
481 MachineOperand Lo1(getSubOperand64(
I.getOperand(1), HalfRC, AMDGPU::sub0));
482 MachineOperand Lo2(getSubOperand64(
I.getOperand(2), HalfRC, AMDGPU::sub0));
483 MachineOperand Hi1(getSubOperand64(
I.getOperand(1), HalfRC, AMDGPU::sub1));
484 MachineOperand Hi2(getSubOperand64(
I.getOperand(2), HalfRC, AMDGPU::sub1));
486 Register DstLo = MRI->createVirtualRegister(&HalfRC);
487 Register DstHi = MRI->createVirtualRegister(&HalfRC);
490 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_ADD_U32), DstLo)
493 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_ADDC_U32), DstHi)
499 Register CarryReg = MRI->createVirtualRegister(CarryRC);
500 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::V_ADD_CO_U32_e64), DstLo)
505 MachineInstr *Addc =
BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::V_ADDC_U32_e64), DstHi)
515 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
522 if (!RBI.constrainGenericRegister(DstReg, RC, *MRI))
529bool AMDGPUInstructionSelector::selectG_UADDO_USUBO_UADDE_USUBE(
534 Register Dst0Reg =
I.getOperand(0).getReg();
535 Register Dst1Reg =
I.getOperand(1).getReg();
536 const bool IsAdd =
I.getOpcode() == AMDGPU::G_UADDO ||
537 I.getOpcode() == AMDGPU::G_UADDE;
538 const bool HasCarryIn =
I.getOpcode() == AMDGPU::G_UADDE ||
539 I.getOpcode() == AMDGPU::G_USUBE;
541 if (isVCC(Dst1Reg, *MRI)) {
542 unsigned NoCarryOpc =
543 IsAdd ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_SUB_CO_U32_e64;
544 unsigned CarryOpc = IsAdd ? AMDGPU::V_ADDC_U32_e64 : AMDGPU::V_SUBB_U32_e64;
545 I.setDesc(TII.get(HasCarryIn ? CarryOpc : NoCarryOpc));
552 Register Src0Reg =
I.getOperand(2).getReg();
553 Register Src1Reg =
I.getOperand(3).getReg();
556 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::SCC)
557 .
addReg(
I.getOperand(4).getReg());
560 unsigned NoCarryOpc = IsAdd ? AMDGPU::S_ADD_U32 : AMDGPU::S_SUB_U32;
561 unsigned CarryOpc = IsAdd ? AMDGPU::S_ADDC_U32 : AMDGPU::S_SUBB_U32;
563 auto CarryInst =
BuildMI(*BB, &
I,
DL, TII.get(HasCarryIn ? CarryOpc : NoCarryOpc), Dst0Reg)
564 .
add(
I.getOperand(2))
565 .
add(
I.getOperand(3));
567 if (MRI->use_nodbg_empty(Dst1Reg)) {
568 CarryInst.setOperandDead(3);
570 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), Dst1Reg)
572 if (!MRI->getRegClassOrNull(Dst1Reg))
573 MRI->setRegClass(Dst1Reg, &AMDGPU::SReg_32RegClass);
576 if (!RBI.constrainGenericRegister(Dst0Reg, AMDGPU::SReg_32RegClass, *MRI) ||
577 !RBI.constrainGenericRegister(Src0Reg, AMDGPU::SReg_32RegClass, *MRI) ||
578 !RBI.constrainGenericRegister(Src1Reg, AMDGPU::SReg_32RegClass, *MRI))
582 !RBI.constrainGenericRegister(
I.getOperand(4).getReg(),
583 AMDGPU::SReg_32RegClass, *MRI))
590bool AMDGPUInstructionSelector::selectG_AMDGPU_MAD_64_32(
594 const bool IsUnsigned =
I.getOpcode() == AMDGPU::G_AMDGPU_MAD_U64_U32;
595 bool UseNoCarry = Subtarget->hasMadNC64_32Insts() &&
596 MRI->use_nodbg_empty(
I.getOperand(1).getReg());
599 if (Subtarget->hasMADIntraFwdBug())
600 Opc = IsUnsigned ? AMDGPU::V_MAD_U64_U32_gfx11_e64
601 : AMDGPU::V_MAD_I64_I32_gfx11_e64;
603 Opc = IsUnsigned ? AMDGPU::V_MAD_NC_U64_U32_e64
604 : AMDGPU::V_MAD_NC_I64_I32_e64;
606 Opc = IsUnsigned ? AMDGPU::V_MAD_U64_U32_e64 : AMDGPU::V_MAD_I64_I32_e64;
611 I.setDesc(TII.get(
Opc));
613 I.addImplicitDefUseOperands(*
MF);
614 I.getOperand(0).setIsEarlyClobber(
true);
620bool AMDGPUInstructionSelector::selectG_EXTRACT(
MachineInstr &
I)
const {
622 Register DstReg =
I.getOperand(0).getReg();
623 Register SrcReg =
I.getOperand(1).getReg();
624 LLT DstTy = MRI->getType(DstReg);
625 LLT SrcTy = MRI->getType(SrcReg);
630 unsigned Offset =
I.getOperand(2).getImm();
631 if (
Offset % 32 != 0 || DstSize > 128)
640 TRI.getConstrainedRegClassForOperand(
I.getOperand(0), *MRI);
641 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
644 const RegisterBank *SrcBank = RBI.getRegBank(SrcReg, *MRI, TRI);
646 TRI.getRegClassForSizeOnBank(SrcSize, *SrcBank);
651 SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubReg);
656 *SrcRC,
I.getOperand(1));
658 BuildMI(*BB, &
I,
DL, TII.get(TargetOpcode::COPY), DstReg)
659 .
addReg(SrcReg, {}, SubReg);
665bool AMDGPUInstructionSelector::selectS16MergeToS32(
MachineInstr &
MI)
const {
670 LLT Src0Ty = MRI->getType(Src0);
671 LLT Src1Ty = MRI->getType(Src1);
673 const RegisterBank *DstBank = RBI.getRegBank(Dst, *MRI, TRI);
674 const RegisterBank *Src0Bank = RBI.getRegBank(Src0, *MRI, TRI);
675 const RegisterBank *Src1Bank = RBI.getRegBank(Src1, *MRI, TRI);
676 const bool IsVector = DstBank->
getID() == AMDGPU::VGPRRegBankID;
687 if (Src0Bank->
getID() == AMDGPU::VGPRRegBankID &&
688 Src1Bank->
getID() == AMDGPU::VGPRRegBankID &&
690 BuildMI(*BB,
MI,
DL, TII.get(TargetOpcode::REG_SEQUENCE), Dst)
696 if (!RBI.constrainGenericRegister(Dst, AMDGPU::VGPR_32RegClass, *MRI))
699 MI.eraseFromParent();
704 Register TmpReg = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
705 auto MIB =
BuildMI(*BB,
MI,
DL, TII.get(AMDGPU::V_AND_B32_e32), TmpReg)
710 MIB =
BuildMI(*BB,
MI,
DL, TII.get(AMDGPU::V_LSHL_OR_B32_e64), Dst)
716 MI.eraseFromParent();
739 unsigned Opc = AMDGPU::S_PACK_LL_B32_B16;
740 if (Shift0 && Shift1) {
741 Opc = AMDGPU::S_PACK_HH_B32_B16;
742 MI.getOperand(1).setReg(ShiftSrc0);
743 MI.getOperand(2).setReg(ShiftSrc1);
745 Opc = AMDGPU::S_PACK_LH_B32_B16;
746 MI.getOperand(2).setReg(ShiftSrc1);
750 if (ConstSrc1 && ConstSrc1->Value == 0) {
752 auto MIB =
BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_LSHR_B32), Dst)
757 MI.eraseFromParent();
761 if (STI.hasSPackHL()) {
762 Opc = AMDGPU::S_PACK_HL_B32_B16;
763 MI.getOperand(1).setReg(ShiftSrc0);
767 MI.setDesc(TII.get(
Opc));
774bool AMDGPUInstructionSelector::selectS16MergeToWide(
MachineInstr &
MI)
const {
778 const unsigned DstSize = MRI->getType(DstReg).getSizeInBits();
779 const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
780 const unsigned NumSrc =
MI.getNumOperands() - 1;
784 for (
unsigned I = 0;
I != NumSrc;
I += 2) {
785 Register S32 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
795 TRI.getRegClassForSizeOnBank(DstSize, *DstBank);
796 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
798 ArrayRef<int16_t> SubRegs = TRI.getRegSplitParts(DstRC, 4);
799 auto MIB =
BuildMI(*BB,
MI,
DL, TII.get(TargetOpcode::REG_SEQUENCE), DstReg);
800 for (
unsigned I = 0,
E = S32Regs.
size();
I !=
E; ++
I)
801 MIB.addReg(S32Regs[
I]).addImm(SubRegs[
I]);
803 MI.eraseFromParent();
807bool AMDGPUInstructionSelector::selectG_MERGE_VALUES(
MachineInstr &
MI)
const {
810 LLT DstTy = MRI->getType(DstReg);
811 LLT SrcTy = MRI->getType(
MI.getOperand(1).getReg());
817 MI.getNumOperands() == 3) {
818 return selectS16MergeToS32(
MI);
822 bool IsWideS16Merge = SrcSize == 16 && DstTy.
getSizeInBits() > 32 &&
826 if (IsWideS16Merge &&
827 RBI.getRegBank(DstReg, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID)
828 return selectS16MergeToWide(
MI);
836 const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
839 TRI.getRegClassForSizeOnBank(DstSize, *DstBank);
843 ArrayRef<int16_t> SubRegs = TRI.getRegSplitParts(DstRC, SrcSize / 8);
844 MachineInstrBuilder MIB =
845 BuildMI(*BB, &
MI,
DL, TII.get(TargetOpcode::REG_SEQUENCE), DstReg);
846 for (
int I = 0,
E =
MI.getNumOperands() - 1;
I !=
E; ++
I) {
847 MachineOperand &Src =
MI.getOperand(
I + 1);
852 = TRI.getConstrainedRegClassForOperand(Src, *MRI);
853 if (SrcRC && !RBI.constrainGenericRegister(Src.getReg(), *SrcRC, *MRI))
857 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
860 MI.eraseFromParent();
864bool AMDGPUInstructionSelector::selectG_UNMERGE_VALUES(
MachineInstr &
MI)
const {
866 const int NumDst =
MI.getNumOperands() - 1;
868 MachineOperand &Src =
MI.getOperand(NumDst);
872 LLT DstTy = MRI->getType(DstReg0);
873 LLT SrcTy = MRI->getType(SrcReg);
878 const RegisterBank *SrcBank = RBI.getRegBank(SrcReg, *MRI, TRI);
881 TRI.getRegClassForSizeOnBank(SrcSize, *SrcBank);
882 if (!SrcRC || !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI))
888 ArrayRef<int16_t> SubRegs = TRI.getRegSplitParts(SrcRC, DstSize / 8);
889 for (
int I = 0,
E = NumDst;
I !=
E; ++
I) {
890 MachineOperand &Dst =
MI.getOperand(
I);
892 if (SrcBank->
getID() == AMDGPU::SGPRRegBankID &&
893 SubRegs[
I] == AMDGPU::hi16) {
894 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_LSHR_B32), Dst.getReg())
898 BuildMI(*BB, &
MI,
DL, TII.get(TargetOpcode::COPY), Dst.getReg())
899 .
addReg(SrcReg, {}, SubRegs[
I]);
903 SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubRegs[
I]);
904 if (!SrcRC || !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI))
908 TRI.getConstrainedRegClassForOperand(Dst, *MRI);
909 if (DstRC && !RBI.constrainGenericRegister(Dst.getReg(), *DstRC, *MRI))
913 MI.eraseFromParent();
917bool AMDGPUInstructionSelector::selectG_BUILD_VECTOR(
MachineInstr &
MI)
const {
918 assert(
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC ||
919 MI.getOpcode() == AMDGPU::G_BUILD_VECTOR);
923 LLT SrcTy = MRI->getType(Src0);
927 if (
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR && SrcSize >= 32) {
928 return selectG_MERGE_VALUES(
MI);
935 (
MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC &&
939 const RegisterBank *DstBank = RBI.getRegBank(Dst, *MRI, TRI);
940 if (DstBank->
getID() == AMDGPU::AGPRRegBankID)
943 assert(DstBank->
getID() == AMDGPU::SGPRRegBankID ||
944 DstBank->
getID() == AMDGPU::VGPRRegBankID);
945 const bool IsVector = DstBank->
getID() == AMDGPU::VGPRRegBankID;
958 const int64_t K0 = ConstSrc0->Value.getSExtValue();
959 const int64_t K1 = ConstSrc1->Value.getSExtValue();
960 uint32_t Lo16 =
static_cast<uint32_t
>(K0) & 0xffff;
961 uint32_t Hi16 =
static_cast<uint32_t
>(K1) & 0xffff;
962 uint32_t
Imm = Lo16 | (Hi16 << 16);
967 MI.eraseFromParent();
968 return RBI.constrainGenericRegister(Dst, AMDGPU::VGPR_32RegClass, *MRI);
973 MI.eraseFromParent();
974 return RBI.constrainGenericRegister(Dst, AMDGPU::SReg_32RegClass, *MRI);
985 if (Src1Def->
getOpcode() == AMDGPU::G_IMPLICIT_DEF) {
986 MI.setDesc(TII.get(AMDGPU::COPY));
989 IsVector ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
990 return RBI.constrainGenericRegister(Dst, RC, *MRI) &&
991 RBI.constrainGenericRegister(Src0, RC, *MRI);
994 return selectS16MergeToS32(
MI);
997bool AMDGPUInstructionSelector::selectG_IMPLICIT_DEF(
MachineInstr &
I)
const {
998 const MachineOperand &MO =
I.getOperand(0);
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_icmp:
1281 case Intrinsic::amdgcn_fcmp:
1284 return selectIntrinsicCmp(
I);
1285 case Intrinsic::amdgcn_ballot:
1286 return selectBallot(
I);
1287 case Intrinsic::amdgcn_reloc_constant:
1288 return selectRelocConstant(
I);
1289 case Intrinsic::amdgcn_groupstaticsize:
1290 return selectGroupStaticSize(
I);
1291 case Intrinsic::returnaddress:
1292 return selectReturnAddress(
I);
1293 case Intrinsic::amdgcn_smfmac_f32_16x16x32_f16:
1294 case Intrinsic::amdgcn_smfmac_f32_32x32x16_f16:
1295 case Intrinsic::amdgcn_smfmac_f32_16x16x32_bf16:
1296 case Intrinsic::amdgcn_smfmac_f32_32x32x16_bf16:
1297 case Intrinsic::amdgcn_smfmac_i32_16x16x64_i8:
1298 case Intrinsic::amdgcn_smfmac_i32_32x32x32_i8:
1299 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_bf8:
1300 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_fp8:
1301 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_bf8:
1302 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_fp8:
1303 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_bf8:
1304 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_fp8:
1305 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_bf8:
1306 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_fp8:
1307 case Intrinsic::amdgcn_smfmac_f32_16x16x64_f16:
1308 case Intrinsic::amdgcn_smfmac_f32_32x32x32_f16:
1309 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf16:
1310 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf16:
1311 case Intrinsic::amdgcn_smfmac_i32_16x16x128_i8:
1312 case Intrinsic::amdgcn_smfmac_i32_32x32x64_i8:
1313 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_bf8:
1314 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_fp8:
1315 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_bf8:
1316 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_fp8:
1317 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_bf8:
1318 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_fp8:
1319 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_bf8:
1320 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_fp8:
1321 return selectSMFMACIntrin(
I);
1322 case Intrinsic::amdgcn_permlane16_swap:
1323 case Intrinsic::amdgcn_permlane32_swap:
1324 return selectPermlaneSwapIntrin(
I, IntrinsicID);
1325 case Intrinsic::amdgcn_wave_shuffle:
1326 return selectWaveShuffleIntrin(
I);
1337 if (
Size == 16 && !ST.has16BitInsts())
1340 const auto Select = [&](
unsigned S16Opc,
unsigned TrueS16Opc,
1341 unsigned FakeS16Opc,
unsigned S32Opc,
1344 return ST.hasTrue16BitInsts()
1345 ? ST.useRealTrue16Insts() ? TrueS16Opc : FakeS16Opc
1356 return Select(AMDGPU::V_CMP_NE_U16_e64, AMDGPU::V_CMP_NE_U16_t16_e64,
1357 AMDGPU::V_CMP_NE_U16_fake16_e64, AMDGPU::V_CMP_NE_U32_e64,
1358 AMDGPU::V_CMP_NE_U64_e64);
1360 return Select(AMDGPU::V_CMP_EQ_U16_e64, AMDGPU::V_CMP_EQ_U16_t16_e64,
1361 AMDGPU::V_CMP_EQ_U16_fake16_e64, AMDGPU::V_CMP_EQ_U32_e64,
1362 AMDGPU::V_CMP_EQ_U64_e64);
1364 return Select(AMDGPU::V_CMP_GT_I16_e64, AMDGPU::V_CMP_GT_I16_t16_e64,
1365 AMDGPU::V_CMP_GT_I16_fake16_e64, AMDGPU::V_CMP_GT_I32_e64,
1366 AMDGPU::V_CMP_GT_I64_e64);
1368 return Select(AMDGPU::V_CMP_GE_I16_e64, AMDGPU::V_CMP_GE_I16_t16_e64,
1369 AMDGPU::V_CMP_GE_I16_fake16_e64, AMDGPU::V_CMP_GE_I32_e64,
1370 AMDGPU::V_CMP_GE_I64_e64);
1372 return Select(AMDGPU::V_CMP_LT_I16_e64, AMDGPU::V_CMP_LT_I16_t16_e64,
1373 AMDGPU::V_CMP_LT_I16_fake16_e64, AMDGPU::V_CMP_LT_I32_e64,
1374 AMDGPU::V_CMP_LT_I64_e64);
1376 return Select(AMDGPU::V_CMP_LE_I16_e64, AMDGPU::V_CMP_LE_I16_t16_e64,
1377 AMDGPU::V_CMP_LE_I16_fake16_e64, AMDGPU::V_CMP_LE_I32_e64,
1378 AMDGPU::V_CMP_LE_I64_e64);
1380 return Select(AMDGPU::V_CMP_GT_U16_e64, AMDGPU::V_CMP_GT_U16_t16_e64,
1381 AMDGPU::V_CMP_GT_U16_fake16_e64, AMDGPU::V_CMP_GT_U32_e64,
1382 AMDGPU::V_CMP_GT_U64_e64);
1384 return Select(AMDGPU::V_CMP_GE_U16_e64, AMDGPU::V_CMP_GE_U16_t16_e64,
1385 AMDGPU::V_CMP_GE_U16_fake16_e64, AMDGPU::V_CMP_GE_U32_e64,
1386 AMDGPU::V_CMP_GE_U64_e64);
1388 return Select(AMDGPU::V_CMP_LT_U16_e64, AMDGPU::V_CMP_LT_U16_t16_e64,
1389 AMDGPU::V_CMP_LT_U16_fake16_e64, AMDGPU::V_CMP_LT_U32_e64,
1390 AMDGPU::V_CMP_LT_U64_e64);
1392 return Select(AMDGPU::V_CMP_LE_U16_e64, AMDGPU::V_CMP_LE_U16_t16_e64,
1393 AMDGPU::V_CMP_LE_U16_fake16_e64, AMDGPU::V_CMP_LE_U32_e64,
1394 AMDGPU::V_CMP_LE_U64_e64);
1397 return Select(AMDGPU::V_CMP_EQ_F16_e64, AMDGPU::V_CMP_EQ_F16_t16_e64,
1398 AMDGPU::V_CMP_EQ_F16_fake16_e64, AMDGPU::V_CMP_EQ_F32_e64,
1399 AMDGPU::V_CMP_EQ_F64_e64);
1401 return Select(AMDGPU::V_CMP_GT_F16_e64, AMDGPU::V_CMP_GT_F16_t16_e64,
1402 AMDGPU::V_CMP_GT_F16_fake16_e64, AMDGPU::V_CMP_GT_F32_e64,
1403 AMDGPU::V_CMP_GT_F64_e64);
1405 return Select(AMDGPU::V_CMP_GE_F16_e64, AMDGPU::V_CMP_GE_F16_t16_e64,
1406 AMDGPU::V_CMP_GE_F16_fake16_e64, AMDGPU::V_CMP_GE_F32_e64,
1407 AMDGPU::V_CMP_GE_F64_e64);
1409 return Select(AMDGPU::V_CMP_LT_F16_e64, AMDGPU::V_CMP_LT_F16_t16_e64,
1410 AMDGPU::V_CMP_LT_F16_fake16_e64, AMDGPU::V_CMP_LT_F32_e64,
1411 AMDGPU::V_CMP_LT_F64_e64);
1413 return Select(AMDGPU::V_CMP_LE_F16_e64, AMDGPU::V_CMP_LE_F16_t16_e64,
1414 AMDGPU::V_CMP_LE_F16_fake16_e64, AMDGPU::V_CMP_LE_F32_e64,
1415 AMDGPU::V_CMP_LE_F64_e64);
1417 return Select(AMDGPU::V_CMP_NEQ_F16_e64, AMDGPU::V_CMP_NEQ_F16_t16_e64,
1418 AMDGPU::V_CMP_NEQ_F16_fake16_e64, AMDGPU::V_CMP_NEQ_F32_e64,
1419 AMDGPU::V_CMP_NEQ_F64_e64);
1421 return Select(AMDGPU::V_CMP_O_F16_e64, AMDGPU::V_CMP_O_F16_t16_e64,
1422 AMDGPU::V_CMP_O_F16_fake16_e64, AMDGPU::V_CMP_O_F32_e64,
1423 AMDGPU::V_CMP_O_F64_e64);
1425 return Select(AMDGPU::V_CMP_U_F16_e64, AMDGPU::V_CMP_U_F16_t16_e64,
1426 AMDGPU::V_CMP_U_F16_fake16_e64, AMDGPU::V_CMP_U_F32_e64,
1427 AMDGPU::V_CMP_U_F64_e64);
1429 return Select(AMDGPU::V_CMP_NLG_F16_e64, AMDGPU::V_CMP_NLG_F16_t16_e64,
1430 AMDGPU::V_CMP_NLG_F16_fake16_e64, AMDGPU::V_CMP_NLG_F32_e64,
1431 AMDGPU::V_CMP_NLG_F64_e64);
1433 return Select(AMDGPU::V_CMP_NLE_F16_e64, AMDGPU::V_CMP_NLE_F16_t16_e64,
1434 AMDGPU::V_CMP_NLE_F16_fake16_e64, AMDGPU::V_CMP_NLE_F32_e64,
1435 AMDGPU::V_CMP_NLE_F64_e64);
1437 return Select(AMDGPU::V_CMP_NLT_F16_e64, AMDGPU::V_CMP_NLT_F16_t16_e64,
1438 AMDGPU::V_CMP_NLT_F16_fake16_e64, AMDGPU::V_CMP_NLT_F32_e64,
1439 AMDGPU::V_CMP_NLT_F64_e64);
1441 return Select(AMDGPU::V_CMP_NGE_F16_e64, AMDGPU::V_CMP_NGE_F16_t16_e64,
1442 AMDGPU::V_CMP_NGE_F16_fake16_e64, AMDGPU::V_CMP_NGE_F32_e64,
1443 AMDGPU::V_CMP_NGE_F64_e64);
1445 return Select(AMDGPU::V_CMP_NGT_F16_e64, AMDGPU::V_CMP_NGT_F16_t16_e64,
1446 AMDGPU::V_CMP_NGT_F16_fake16_e64, AMDGPU::V_CMP_NGT_F32_e64,
1447 AMDGPU::V_CMP_NGT_F64_e64);
1449 return Select(AMDGPU::V_CMP_NEQ_F16_e64, AMDGPU::V_CMP_NEQ_F16_t16_e64,
1450 AMDGPU::V_CMP_NEQ_F16_fake16_e64, AMDGPU::V_CMP_NEQ_F32_e64,
1451 AMDGPU::V_CMP_NEQ_F64_e64);
1453 return Select(AMDGPU::V_CMP_TRU_F16_e64, AMDGPU::V_CMP_TRU_F16_t16_e64,
1454 AMDGPU::V_CMP_TRU_F16_fake16_e64, AMDGPU::V_CMP_TRU_F32_e64,
1455 AMDGPU::V_CMP_TRU_F64_e64);
1457 return Select(AMDGPU::V_CMP_F_F16_e64, AMDGPU::V_CMP_F_F16_t16_e64,
1458 AMDGPU::V_CMP_F_F16_fake16_e64, AMDGPU::V_CMP_F_F32_e64,
1459 AMDGPU::V_CMP_F_F64_e64);
1464 unsigned Size)
const {
1466 if (!STI.hasScalarCompareEq64())
1471 return AMDGPU::S_CMP_LG_U64;
1473 return AMDGPU::S_CMP_EQ_U64;
1482 return AMDGPU::S_CMP_LG_U32;
1484 return AMDGPU::S_CMP_EQ_U32;
1486 return AMDGPU::S_CMP_GT_I32;
1488 return AMDGPU::S_CMP_GE_I32;
1490 return AMDGPU::S_CMP_LT_I32;
1492 return AMDGPU::S_CMP_LE_I32;
1494 return AMDGPU::S_CMP_GT_U32;
1496 return AMDGPU::S_CMP_GE_U32;
1498 return AMDGPU::S_CMP_LT_U32;
1500 return AMDGPU::S_CMP_LE_U32;
1502 return AMDGPU::S_CMP_EQ_F32;
1504 return AMDGPU::S_CMP_GT_F32;
1506 return AMDGPU::S_CMP_GE_F32;
1508 return AMDGPU::S_CMP_LT_F32;
1510 return AMDGPU::S_CMP_LE_F32;
1512 return AMDGPU::S_CMP_LG_F32;
1514 return AMDGPU::S_CMP_O_F32;
1516 return AMDGPU::S_CMP_U_F32;
1518 return AMDGPU::S_CMP_NLG_F32;
1520 return AMDGPU::S_CMP_NLE_F32;
1522 return AMDGPU::S_CMP_NLT_F32;
1524 return AMDGPU::S_CMP_NGE_F32;
1526 return AMDGPU::S_CMP_NGT_F32;
1528 return AMDGPU::S_CMP_NEQ_F32;
1535 if (!STI.hasSALUFloatInsts())
1540 return AMDGPU::S_CMP_EQ_F16;
1542 return AMDGPU::S_CMP_GT_F16;
1544 return AMDGPU::S_CMP_GE_F16;
1546 return AMDGPU::S_CMP_LT_F16;
1548 return AMDGPU::S_CMP_LE_F16;
1550 return AMDGPU::S_CMP_LG_F16;
1552 return AMDGPU::S_CMP_O_F16;
1554 return AMDGPU::S_CMP_U_F16;
1556 return AMDGPU::S_CMP_NLG_F16;
1558 return AMDGPU::S_CMP_NLE_F16;
1560 return AMDGPU::S_CMP_NLT_F16;
1562 return AMDGPU::S_CMP_NGE_F16;
1564 return AMDGPU::S_CMP_NGT_F16;
1566 return AMDGPU::S_CMP_NEQ_F16;
1575bool AMDGPUInstructionSelector::selectG_ICMP_or_FCMP(
MachineInstr &
I)
const {
1580 Register SrcReg =
I.getOperand(2).getReg();
1581 unsigned Size = RBI.getSizeInBits(SrcReg, *MRI, TRI);
1585 Register CCReg =
I.getOperand(0).getReg();
1586 if (!isVCC(CCReg, *MRI)) {
1587 int Opcode = getS_CMPOpcode(Pred,
Size);
1590 MachineInstr *ICmp =
BuildMI(*BB, &
I,
DL, TII.get(Opcode))
1591 .
add(
I.getOperand(2))
1592 .
add(
I.getOperand(3));
1593 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), CCReg)
1597 RBI.constrainGenericRegister(CCReg, AMDGPU::SReg_32RegClass, *MRI);
1598 I.eraseFromParent();
1602 if (
I.getOpcode() == AMDGPU::G_FCMP)
1609 MachineInstrBuilder ICmp;
1612 ICmp =
BuildMI(*BB, &
I,
DL, TII.get(Opcode),
I.getOperand(0).getReg())
1614 .
add(
I.getOperand(2))
1616 .
add(
I.getOperand(3))
1619 ICmp =
BuildMI(*BB, &
I,
DL, TII.get(Opcode),
I.getOperand(0).getReg())
1620 .
add(
I.getOperand(2))
1621 .
add(
I.getOperand(3));
1625 *TRI.getBoolRC(), *MRI);
1627 I.eraseFromParent();
1631bool AMDGPUInstructionSelector::selectIntrinsicCmp(
MachineInstr &
I)
const {
1632 Register Dst =
I.getOperand(0).getReg();
1633 if (isVCC(Dst, *MRI))
1636 LLT DstTy = MRI->getType(Dst);
1642 Register SrcReg =
I.getOperand(2).getReg();
1643 unsigned Size = RBI.getSizeInBits(SrcReg, *MRI, TRI);
1651 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::IMPLICIT_DEF), Dst);
1652 I.eraseFromParent();
1653 return RBI.constrainGenericRegister(Dst, *TRI.getBoolRC(), *MRI);
1660 MachineInstrBuilder SelectedMI;
1661 MachineOperand &
LHS =
I.getOperand(2);
1662 MachineOperand &
RHS =
I.getOperand(3);
1663 auto [Src0, Src0Mods] = selectVOP3ModsImpl(
LHS.getReg());
1664 auto [Src1, Src1Mods] = selectVOP3ModsImpl(
RHS.getReg());
1666 copyToVGPRIfSrcFolded(Src0, Src0Mods,
LHS, &
I,
true);
1668 copyToVGPRIfSrcFolded(Src1, Src1Mods,
RHS, &
I,
true);
1669 SelectedMI =
BuildMI(*BB, &
I,
DL, TII.get(Opcode), Dst);
1671 SelectedMI.
addImm(Src0Mods);
1672 SelectedMI.
addReg(Src0Reg);
1674 SelectedMI.
addImm(Src1Mods);
1675 SelectedMI.
addReg(Src1Reg);
1681 RBI.constrainGenericRegister(Dst, *TRI.getBoolRC(), *MRI);
1684 I.eraseFromParent();
1695 if (
MI->getParent() !=
MBB)
1699 if (
MI->getOpcode() == AMDGPU::COPY) {
1702 if (DstRB && SrcRB && DstRB->
getID() == AMDGPU::VCCRegBankID &&
1703 SrcRB->getID() == AMDGPU::SGPRRegBankID)
1708 if (
MI->getOpcode() == AMDGPU::G_AMDGPU_COPY_VCC_SCC)
1724bool AMDGPUInstructionSelector::selectBallot(
MachineInstr &
I)
const {
1727 Register DstReg =
I.getOperand(0).getReg();
1728 Register SrcReg =
I.getOperand(2).getReg();
1729 const unsigned BallotSize = MRI->getType(DstReg).getSizeInBits();
1730 const unsigned WaveSize = STI.getWavefrontSize();
1734 if (BallotSize != WaveSize && (BallotSize != 64 || WaveSize != 32))
1737 std::optional<ValueAndVReg> Arg =
1742 if (BallotSize != WaveSize) {
1743 Dst = MRI->createVirtualRegister(TRI.getBoolRC());
1747 const int64_t
Value = Arg->Value.getZExtValue();
1750 unsigned Opcode = WaveSize == 64 ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
1757 if (!RBI.constrainGenericRegister(Dst, *TRI.getBoolRC(), *MRI))
1763 if (!RBI.constrainGenericRegister(Dst, *TRI.getBoolRC(), *MRI))
1767 unsigned AndOpc = WaveSize == 64 ? AMDGPU::S_AND_B64 : AMDGPU::S_AND_B32;
1777 if (BallotSize != WaveSize) {
1778 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
1780 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
1787 I.eraseFromParent();
1791bool AMDGPUInstructionSelector::selectRelocConstant(
MachineInstr &
I)
const {
1792 Register DstReg =
I.getOperand(0).getReg();
1793 const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
1795 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
1798 const bool IsVALU = DstBank->
getID() == AMDGPU::VGPRRegBankID;
1800 Module *
M =
MF->getFunction().getParent();
1801 const MDNode *
Metadata =
I.getOperand(2).getMetadata();
1808 TII.get(IsVALU ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32), DstReg)
1811 I.eraseFromParent();
1815bool AMDGPUInstructionSelector::selectGroupStaticSize(
MachineInstr &
I)
const {
1818 Register DstReg =
I.getOperand(0).getReg();
1819 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
1820 unsigned Mov = DstRB->
getID() == AMDGPU::SGPRRegBankID ?
1821 AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
1829 const SIMachineFunctionInfo *MFI =
MF->getInfo<SIMachineFunctionInfo>();
1832 Module *
M =
MF->getFunction().getParent();
1833 const GlobalValue *GV =
1838 I.eraseFromParent();
1843bool AMDGPUInstructionSelector::selectReturnAddress(
MachineInstr &
I)
const {
1848 MachineOperand &Dst =
I.getOperand(0);
1850 unsigned Depth =
I.getOperand(2).getImm();
1853 = TRI.getConstrainedRegClassForOperand(Dst, *MRI);
1855 !RBI.constrainGenericRegister(DstReg, *RC, *MRI))
1860 MF.getInfo<SIMachineFunctionInfo>()->isEntryFunction()) {
1863 I.eraseFromParent();
1867 MachineFrameInfo &MFI =
MF.getFrameInfo();
1872 Register ReturnAddrReg = TRI.getReturnAddressReg(
MF);
1874 AMDGPU::SReg_64RegClass,
DL);
1877 I.eraseFromParent();
1881bool AMDGPUInstructionSelector::selectEndCfIntrinsic(
MachineInstr &
MI)
const {
1885 BuildMI(*BB, &
MI,
MI.getDebugLoc(), TII.get(AMDGPU::SI_END_CF))
1886 .
add(
MI.getOperand(1));
1889 MI.eraseFromParent();
1891 if (!MRI->getRegClassOrNull(
Reg))
1892 MRI->setRegClass(
Reg, TRI.getWaveMaskRegClass());
1896bool AMDGPUInstructionSelector::selectDSOrderedIntrinsic(
1902 unsigned IndexOperand =
MI.getOperand(7).getImm();
1903 bool WaveRelease =
MI.getOperand(8).getImm() != 0;
1904 bool WaveDone =
MI.getOperand(9).getImm() != 0;
1906 if (WaveDone && !WaveRelease) {
1910 Fn,
"ds_ordered_count: wave_done requires wave_release",
DL));
1913 unsigned OrderedCountIndex = IndexOperand & 0x3f;
1914 IndexOperand &= ~0x3f;
1915 unsigned CountDw = 0;
1918 CountDw = (IndexOperand >> 24) & 0xf;
1919 IndexOperand &= ~(0xf << 24);
1921 if (CountDw < 1 || CountDw > 4) {
1924 Fn,
"ds_ordered_count: dword count must be between 1 and 4",
DL));
1932 Fn,
"ds_ordered_count: bad index operand",
DL));
1935 unsigned Instruction = IntrID == Intrinsic::amdgcn_ds_ordered_add ? 0 : 1;
1938 unsigned Offset0 = OrderedCountIndex << 2;
1939 unsigned Offset1 = WaveRelease | (WaveDone << 1) | (Instruction << 4);
1942 Offset1 |= (CountDw - 1) << 6;
1945 Offset1 |= ShaderType << 2;
1947 unsigned Offset = Offset0 | (Offset1 << 8);
1955 MachineInstrBuilder
DS =
1956 BuildMI(*
MBB, &
MI,
DL, TII.get(AMDGPU::DS_ORDERED_COUNT), DstReg)
1961 if (!RBI.constrainGenericRegister(M0Val, AMDGPU::SReg_32RegClass, *MRI))
1965 MI.eraseFromParent();
1971 case Intrinsic::amdgcn_ds_gws_init:
1972 return AMDGPU::DS_GWS_INIT;
1973 case Intrinsic::amdgcn_ds_gws_barrier:
1974 return AMDGPU::DS_GWS_BARRIER;
1975 case Intrinsic::amdgcn_ds_gws_sema_v:
1976 return AMDGPU::DS_GWS_SEMA_V;
1977 case Intrinsic::amdgcn_ds_gws_sema_br:
1978 return AMDGPU::DS_GWS_SEMA_BR;
1979 case Intrinsic::amdgcn_ds_gws_sema_p:
1980 return AMDGPU::DS_GWS_SEMA_P;
1981 case Intrinsic::amdgcn_ds_gws_sema_release_all:
1982 return AMDGPU::DS_GWS_SEMA_RELEASE_ALL;
1988bool AMDGPUInstructionSelector::selectDSGWSIntrinsic(
MachineInstr &
MI,
1990 if (!STI.hasGWS() || (IID == Intrinsic::amdgcn_ds_gws_sema_release_all &&
1991 !STI.hasGWSSemaReleaseAll()))
1995 const bool HasVSrc =
MI.getNumOperands() == 3;
1996 assert(HasVSrc ||
MI.getNumOperands() == 2);
1998 Register BaseOffset =
MI.getOperand(HasVSrc ? 2 : 1).getReg();
1999 const RegisterBank *OffsetRB = RBI.getRegBank(BaseOffset, *MRI, TRI);
2000 if (OffsetRB->
getID() != AMDGPU::SGPRRegBankID)
2009 MachineInstr *Readfirstlane =
nullptr;
2014 if (OffsetDef->
getOpcode() == AMDGPU::V_READFIRSTLANE_B32) {
2015 Readfirstlane = OffsetDef;
2020 if (OffsetDef->
getOpcode() == AMDGPU::G_CONSTANT) {
2030 std::tie(BaseOffset, ImmOffset) =
2033 if (Readfirstlane) {
2036 if (!RBI.constrainGenericRegister(BaseOffset, AMDGPU::VGPR_32RegClass, *MRI))
2042 if (!RBI.constrainGenericRegister(BaseOffset,
2043 AMDGPU::SReg_32RegClass, *MRI))
2047 Register M0Base = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2062 const MCInstrDesc &InstrDesc = TII.get(
Opc);
2067 int Data0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
2070 TRI.getSubRegisterClass(DataRC, AMDGPU::sub0);
2074 if (!RBI.constrainGenericRegister(VSrc, *DataRC, *MRI))
2084 Register DataReg = MRI->createVirtualRegister(DataRC);
2085 if (!RBI.constrainGenericRegister(VSrc, *SubRC, *MRI))
2088 Register UndefReg = MRI->createVirtualRegister(SubRC);
2107 MI.eraseFromParent();
2111bool AMDGPUInstructionSelector::selectDSAppendConsume(
MachineInstr &
MI,
2112 bool IsAppend)
const {
2113 Register PtrBase =
MI.getOperand(2).getReg();
2114 LLT PtrTy = MRI->getType(PtrBase);
2118 std::tie(PtrBase,
Offset) = selectDS1Addr1OffsetImpl(
MI.getOperand(2));
2121 if (!isDSOffsetLegal(PtrBase,
Offset)) {
2122 PtrBase =
MI.getOperand(2).getReg();
2128 const unsigned Opc = IsAppend ? AMDGPU::DS_APPEND : AMDGPU::DS_CONSUME;
2132 if (!RBI.constrainGenericRegister(PtrBase, AMDGPU::SReg_32RegClass, *MRI))
2139 MI.eraseFromParent();
2144bool AMDGPUInstructionSelector::selectInitWholeWave(
MachineInstr &
MI)
const {
2146 SIMachineFunctionInfo *MFInfo =
MF->getInfo<SIMachineFunctionInfo>();
2157 TFE = TexFailCtrl & 0x1;
2159 LWE = TexFailCtrl & 0x2;
2162 return TexFailCtrl == 0;
2165bool AMDGPUInstructionSelector::selectImageIntrinsic(
2173 Register ResultDef =
MI.getOperand(0).getReg();
2174 if (MRI->use_nodbg_empty(ResultDef))
2178 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
2187 const unsigned ArgOffset =
MI.getNumExplicitDefs() + 1;
2189 Register VDataIn = AMDGPU::NoRegister;
2190 Register VDataOut = AMDGPU::NoRegister;
2192 int NumVDataDwords = -1;
2193 bool IsD16 =
MI.getOpcode() == AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16 ||
2194 MI.getOpcode() == AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16;
2200 Unorm =
MI.getOperand(ArgOffset + Intr->
UnormIndex).getImm() != 0;
2204 bool IsTexFail =
false;
2206 TFE, LWE, IsTexFail))
2209 const int Flags =
MI.getOperand(ArgOffset + Intr->
NumArgs).getImm();
2210 const bool IsA16 = (
Flags & 1) != 0;
2211 const bool IsG16 = (
Flags & 2) != 0;
2214 if (IsA16 && !STI.hasG16() && !IsG16)
2218 unsigned DMaskLanes = 0;
2220 if (BaseOpcode->
Atomic) {
2222 VDataOut =
MI.getOperand(0).getReg();
2223 VDataIn =
MI.getOperand(2).getReg();
2224 LLT Ty = MRI->getType(VDataIn);
2227 const bool Is64Bit = BaseOpcode->
AtomicX2 ?
2232 assert(
MI.getOperand(3).getReg() == AMDGPU::NoRegister);
2234 DMask = Is64Bit ? 0xf : 0x3;
2235 NumVDataDwords = Is64Bit ? 4 : 2;
2237 DMask = Is64Bit ? 0x3 : 0x1;
2238 NumVDataDwords = Is64Bit ? 2 : 1;
2241 DMask =
MI.getOperand(ArgOffset + Intr->
DMaskIndex).getImm();
2244 if (BaseOpcode->
Store) {
2245 VDataIn =
MI.getOperand(1).getReg();
2246 VDataTy = MRI->getType(VDataIn);
2251 VDataOut =
MI.getOperand(0).getReg();
2252 VDataTy = MRI->getType(VDataOut);
2253 NumVDataDwords = DMaskLanes;
2255 if (IsD16 && !STI.hasUnpackedD16VMem())
2256 NumVDataDwords = (DMaskLanes + 1) / 2;
2261 if (Subtarget->hasG16() && IsG16) {
2262 const AMDGPU::MIMGG16MappingInfo *G16MappingInfo =
2265 IntrOpcode = G16MappingInfo->
G16;
2269 assert((!IsTexFail || DMaskLanes >= 1) &&
"should have legalized this");
2279 int NumVAddrRegs = 0;
2280 int NumVAddrDwords = 0;
2283 MachineOperand &AddrOp =
MI.getOperand(ArgOffset +
I);
2284 if (!AddrOp.
isReg())
2292 NumVAddrDwords += (MRI->getType(Addr).getSizeInBits() + 31) / 32;
2299 NumVAddrRegs != 1 &&
2300 (STI.hasPartialNSAEncoding() ? NumVAddrDwords >= NumVAddrRegs
2301 : NumVAddrDwords == NumVAddrRegs);
2302 if (UseNSA && !STI.hasFeature(AMDGPU::FeatureNSAEncoding)) {
2313 NumVDataDwords, NumVAddrDwords);
2314 }
else if (IsGFX12Plus) {
2316 NumVDataDwords, NumVAddrDwords);
2317 }
else if (IsGFX11Plus) {
2319 UseNSA ? AMDGPU::MIMGEncGfx11NSA
2320 : AMDGPU::MIMGEncGfx11Default,
2321 NumVDataDwords, NumVAddrDwords);
2322 }
else if (IsGFX10Plus) {
2324 UseNSA ? AMDGPU::MIMGEncGfx10NSA
2325 : AMDGPU::MIMGEncGfx10Default,
2326 NumVDataDwords, NumVAddrDwords);
2328 if (Subtarget->hasGFX90AInsts()) {
2330 NumVDataDwords, NumVAddrDwords);
2334 <<
"requested image instruction is not supported on this GPU\n");
2341 NumVDataDwords, NumVAddrDwords);
2344 NumVDataDwords, NumVAddrDwords);
2354 const bool Is64 = MRI->getType(VDataOut).getSizeInBits() == 64;
2356 Register TmpReg = MRI->createVirtualRegister(
2357 Is64 ? &AMDGPU::VReg_128RegClass : &AMDGPU::VReg_64RegClass);
2358 unsigned SubReg = Is64 ? AMDGPU::sub0_sub1 : AMDGPU::sub0;
2361 if (!MRI->use_empty(VDataOut)) {
2374 for (
int I = 0;
I != NumVAddrRegs; ++
I) {
2375 MachineOperand &SrcOp =
MI.getOperand(ArgOffset + Intr->
VAddrStart +
I);
2376 if (SrcOp.
isReg()) {
2395 STI.hasFeature(AMDGPU::FeatureR128A16) ? -1 : 0);
2397 MIB.
addImm(IsA16 ? -1 : 0);
2399 if (!Subtarget->hasGFX90AInsts()) {
2411 MIB.
addImm(IsD16 ? -1 : 0);
2413 MI.eraseFromParent();
2415 TII.enforceOperandRCAlignment(*MIB, AMDGPU::OpName::vaddr);
2421bool AMDGPUInstructionSelector::selectDSBvhStackIntrinsic(
2432 unsigned Offset =
MI.getOperand(6).getImm();
2436 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
2437 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
2438 Opc = AMDGPU::DS_BVH_STACK_RTN_B32;
2440 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
2441 Opc = AMDGPU::DS_BVH_STACK_PUSH8_POP1_RTN_B32;
2443 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn:
2444 Opc = AMDGPU::DS_BVH_STACK_PUSH8_POP2_RTN_B64;
2456 MI.eraseFromParent();
2461bool AMDGPUInstructionSelector::selectG_INTRINSIC_W_SIDE_EFFECTS(
2464 switch (IntrinsicID) {
2465 case Intrinsic::amdgcn_end_cf:
2466 return selectEndCfIntrinsic(
I);
2467 case Intrinsic::amdgcn_ds_ordered_add:
2468 case Intrinsic::amdgcn_ds_ordered_swap:
2469 return selectDSOrderedIntrinsic(
I, IntrinsicID);
2470 case Intrinsic::amdgcn_ds_gws_init:
2471 case Intrinsic::amdgcn_ds_gws_barrier:
2472 case Intrinsic::amdgcn_ds_gws_sema_v:
2473 case Intrinsic::amdgcn_ds_gws_sema_br:
2474 case Intrinsic::amdgcn_ds_gws_sema_p:
2475 case Intrinsic::amdgcn_ds_gws_sema_release_all:
2476 return selectDSGWSIntrinsic(
I, IntrinsicID);
2477 case Intrinsic::amdgcn_ds_append:
2478 return selectDSAppendConsume(
I,
true);
2479 case Intrinsic::amdgcn_ds_consume:
2480 return selectDSAppendConsume(
I,
false);
2481 case Intrinsic::amdgcn_init_whole_wave:
2482 return selectInitWholeWave(
I);
2483 case Intrinsic::amdgcn_raw_buffer_load_lds:
2484 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
2485 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
2486 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
2487 case Intrinsic::amdgcn_struct_buffer_load_lds:
2488 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
2489 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
2490 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
2491 return selectBufferLoadLds(
I);
2496 case Intrinsic::amdgcn_load_to_lds:
2497 case Intrinsic::amdgcn_load_async_to_lds:
2498 case Intrinsic::amdgcn_global_load_lds:
2499 case Intrinsic::amdgcn_global_load_async_lds:
2500 return selectGlobalLoadLds(
I);
2501 case Intrinsic::amdgcn_tensor_load_to_lds:
2502 case Intrinsic::amdgcn_tensor_store_from_lds:
2503 return selectTensorLoadStore(
I, IntrinsicID);
2504 case Intrinsic::amdgcn_asyncmark:
2505 case Intrinsic::amdgcn_wait_asyncmark:
2506 if (!Subtarget->hasAsyncMark())
2509 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
2510 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
2511 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
2512 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn:
2513 return selectDSBvhStackIntrinsic(
I);
2514 case Intrinsic::amdgcn_s_alloc_vgpr: {
2520 Register ResReg =
I.getOperand(0).getReg();
2522 MachineInstr *AllocMI =
BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::S_ALLOC_VGPR))
2523 .
add(
I.getOperand(2));
2526 I.eraseFromParent();
2528 return RBI.constrainGenericRegister(ResReg, AMDGPU::SReg_32RegClass, *MRI);
2530 case Intrinsic::amdgcn_s_barrier_init:
2531 case Intrinsic::amdgcn_s_barrier_signal_var:
2532 return selectNamedBarrierInit(
I, IntrinsicID);
2533 case Intrinsic::amdgcn_s_wakeup_barrier:
2534 case Intrinsic::amdgcn_s_barrier_join:
2535 case Intrinsic::amdgcn_s_get_named_barrier_state:
2536 return selectNamedBarrierInst(
I, IntrinsicID);
2537 case Intrinsic::amdgcn_s_get_barrier_state:
2538 return selectSGetBarrierState(
I, IntrinsicID);
2539 case Intrinsic::amdgcn_s_barrier_signal_isfirst:
2540 return selectSBarrierSignalIsfirst(
I, IntrinsicID);
2545bool AMDGPUInstructionSelector::selectG_SELECT(
MachineInstr &
I)
const {
2552 Register DstReg =
I.getOperand(0).getReg();
2553 unsigned Size = RBI.getSizeInBits(DstReg, *MRI, TRI);
2555 const MachineOperand &CCOp =
I.getOperand(1);
2557 if (!isVCC(CCReg, *MRI)) {
2558 unsigned SelectOpcode =
Size == 64 ? AMDGPU::S_CSELECT_B64 :
2559 AMDGPU::S_CSELECT_B32;
2560 MachineInstr *CopySCC =
BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::SCC)
2566 if (!MRI->getRegClassOrNull(CCReg))
2567 MRI->setRegClass(CCReg, TRI.getConstrainedRegClassForOperand(CCOp, *MRI));
2569 .
add(
I.getOperand(2))
2570 .
add(
I.getOperand(3));
2574 I.eraseFromParent();
2583 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
2585 .
add(
I.getOperand(3))
2587 .
add(
I.getOperand(2))
2588 .
add(
I.getOperand(1));
2591 I.eraseFromParent();
2595bool AMDGPUInstructionSelector::selectG_TRUNC(
MachineInstr &
I)
const {
2596 Register DstReg =
I.getOperand(0).getReg();
2597 Register SrcReg =
I.getOperand(1).getReg();
2598 const LLT DstTy = MRI->getType(DstReg);
2599 const LLT SrcTy = MRI->getType(SrcReg);
2602 const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
2603 const RegisterBank *DstRB;
2609 DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
2614 const bool IsVALU = DstRB->
getID() == AMDGPU::VGPRRegBankID;
2620 TRI.getRegClassForSizeOnBank(SrcSize, *SrcRB);
2622 TRI.getRegClassForSizeOnBank(DstSize, *DstRB);
2623 if (!SrcRC || !DstRC)
2626 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
2627 !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI)) {
2632 if (DstRC == &AMDGPU::VGPR_16RegClass && SrcSize == 32) {
2633 assert(STI.useRealTrue16Insts());
2637 .
addReg(SrcReg, {}, AMDGPU::lo16);
2638 I.eraseFromParent();
2646 Register LoReg = MRI->createVirtualRegister(DstRC);
2647 Register HiReg = MRI->createVirtualRegister(DstRC);
2649 .
addReg(SrcReg, {}, AMDGPU::sub0);
2651 .
addReg(SrcReg, {}, AMDGPU::sub1);
2653 if (IsVALU && STI.hasSDWA()) {
2656 MachineInstr *MovSDWA =
2657 BuildMI(*
MBB,
I,
DL, TII.get(AMDGPU::V_MOV_B32_sdwa), DstReg)
2667 Register TmpReg0 = MRI->createVirtualRegister(DstRC);
2668 Register TmpReg1 = MRI->createVirtualRegister(DstRC);
2669 Register ImmReg = MRI->createVirtualRegister(DstRC);
2671 BuildMI(*
MBB,
I,
DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), TmpReg0)
2681 unsigned MovOpc = IsVALU ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32;
2682 unsigned AndOpc = IsVALU ? AMDGPU::V_AND_B32_e64 : AMDGPU::S_AND_B32;
2683 unsigned OrOpc = IsVALU ? AMDGPU::V_OR_B32_e64 : AMDGPU::S_OR_B32;
2695 And.setOperandDead(3);
2696 Or.setOperandDead(3);
2700 I.eraseFromParent();
2708 unsigned SubRegIdx = DstSize < 32
2709 ?
static_cast<unsigned>(AMDGPU::sub0)
2710 : TRI.getSubRegFromChannel(0, DstSize / 32);
2711 if (SubRegIdx == AMDGPU::NoSubRegister)
2717 = TRI.getSubClassWithSubReg(SrcRC, SubRegIdx);
2721 if (SrcWithSubRC != SrcRC) {
2722 if (!RBI.constrainGenericRegister(SrcReg, *SrcWithSubRC, *MRI))
2726 I.getOperand(1).setSubReg(SubRegIdx);
2729 I.setDesc(TII.get(TargetOpcode::COPY));
2736 int SignedMask =
static_cast<int>(Mask);
2737 return SignedMask >= -16 && SignedMask <= 64;
2741const RegisterBank *AMDGPUInstructionSelector::getArtifactRegBank(
2750 return &RBI.getRegBankFromRegClass(*RC, LLT());
2754bool AMDGPUInstructionSelector::selectG_SZA_EXT(
MachineInstr &
I)
const {
2755 bool InReg =
I.getOpcode() == AMDGPU::G_SEXT_INREG;
2756 bool Signed =
I.getOpcode() == AMDGPU::G_SEXT || InReg;
2759 const Register DstReg =
I.getOperand(0).getReg();
2760 const Register SrcReg =
I.getOperand(1).getReg();
2762 const LLT DstTy = MRI->getType(DstReg);
2763 const LLT SrcTy = MRI->getType(SrcReg);
2764 const unsigned SrcSize =
I.getOpcode() == AMDGPU::G_SEXT_INREG ?
2771 const RegisterBank *SrcBank = getArtifactRegBank(SrcReg, *MRI, TRI);
2774 if (
I.getOpcode() == AMDGPU::G_ANYEXT) {
2776 return selectCOPY(
I);
2779 TRI.getRegClassForTypeOnBank(SrcTy, *SrcBank);
2780 const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
2782 TRI.getRegClassForSizeOnBank(DstSize, *DstBank);
2784 Register UndefReg = MRI->createVirtualRegister(SrcRC);
2785 BuildMI(
MBB,
I,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefReg);
2791 I.eraseFromParent();
2793 return RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) &&
2794 RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI);
2797 if (SrcBank->
getID() == AMDGPU::VGPRRegBankID && DstSize <= 32) {
2803 MachineInstr *ExtI =
2807 I.eraseFromParent();
2812 const unsigned BFE =
Signed ? AMDGPU::V_BFE_I32_e64 : AMDGPU::V_BFE_U32_e64;
2813 MachineInstr *ExtI =
2818 I.eraseFromParent();
2823 if (SrcBank->
getID() == AMDGPU::SGPRRegBankID && DstSize <= 64) {
2825 AMDGPU::SReg_64RegClass : AMDGPU::SReg_32RegClass;
2826 if (!RBI.constrainGenericRegister(SrcReg, SrcRC, *MRI))
2829 if (
Signed && DstSize == 32 && (SrcSize == 8 || SrcSize == 16)) {
2830 const unsigned SextOpc = SrcSize == 8 ?
2831 AMDGPU::S_SEXT_I32_I8 : AMDGPU::S_SEXT_I32_I16;
2834 I.eraseFromParent();
2835 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_32RegClass, *MRI);
2840 if (DstSize > 32 && SrcSize == 32) {
2841 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2842 unsigned SubReg = InReg ? AMDGPU::sub0 : AMDGPU::NoSubRegister;
2845 .
addReg(SrcReg, {}, SubReg)
2853 .
addReg(SrcReg, {}, SubReg)
2854 .addImm(AMDGPU::sub0)
2857 I.eraseFromParent();
2858 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_64RegClass,
2862 const unsigned BFE64 =
Signed ? AMDGPU::S_BFE_I64 : AMDGPU::S_BFE_U64;
2863 const unsigned BFE32 =
Signed ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32;
2866 if (DstSize > 32 && (SrcSize <= 32 || InReg)) {
2868 Register ExtReg = MRI->createVirtualRegister(&AMDGPU::SReg_64RegClass);
2869 Register UndefReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
2870 unsigned SubReg = InReg ? AMDGPU::sub0 : AMDGPU::NoSubRegister;
2872 BuildMI(
MBB,
I,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefReg);
2874 .
addReg(SrcReg, {}, SubReg)
2875 .addImm(AMDGPU::sub0)
2883 I.eraseFromParent();
2884 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_64RegClass, *MRI);
2899 I.eraseFromParent();
2900 return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_32RegClass, *MRI);
2952 assert(Mask.size() == 2);
2954 if (Mask[0] == 1 && Mask[1] <= 1) {
2962bool AMDGPUInstructionSelector::selectG_FPEXT(
MachineInstr &
I)
const {
2963 if (!Subtarget->hasSALUFloatInsts())
2966 Register Dst =
I.getOperand(0).getReg();
2967 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
2968 if (DstRB->
getID() != AMDGPU::SGPRRegBankID)
2971 Register Src =
I.getOperand(1).getReg();
2977 BuildMI(*BB, &
I,
I.getDebugLoc(), TII.get(AMDGPU::S_CVT_HI_F32_F16), Dst)
2979 I.eraseFromParent();
2980 return RBI.constrainGenericRegister(Dst, AMDGPU::SReg_32RegClass, *MRI);
2987bool AMDGPUInstructionSelector::selectG_FNEG(
MachineInstr &
MI)
const {
3000 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
3001 if (DstRB->
getID() != AMDGPU::SGPRRegBankID ||
3006 MachineInstr *Fabs =
getOpcodeDef(TargetOpcode::G_FABS, Src, *MRI);
3010 if (!RBI.constrainGenericRegister(Src, AMDGPU::SReg_64RegClass, *MRI) ||
3011 !RBI.constrainGenericRegister(Dst, AMDGPU::SReg_64RegClass, *MRI))
3016 Register LoReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3017 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3018 Register ConstReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3019 Register OpReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3021 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), LoReg)
3022 .
addReg(Src, {}, AMDGPU::sub0);
3023 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), HiReg)
3024 .
addReg(Src, {}, AMDGPU::sub1);
3025 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_MOV_B32), ConstReg)
3029 unsigned Opc = Fabs ? AMDGPU::S_OR_B32 : AMDGPU::S_XOR_B32;
3034 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::REG_SEQUENCE), Dst)
3039 MI.eraseFromParent();
3044bool AMDGPUInstructionSelector::selectG_FABS(
MachineInstr &
MI)
const {
3046 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
3047 if (DstRB->
getID() != AMDGPU::SGPRRegBankID ||
3054 Register LoReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3055 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3056 Register ConstReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3057 Register OpReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3059 if (!RBI.constrainGenericRegister(Src, AMDGPU::SReg_64RegClass, *MRI) ||
3060 !RBI.constrainGenericRegister(Dst, AMDGPU::SReg_64RegClass, *MRI))
3063 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), LoReg)
3064 .
addReg(Src, {}, AMDGPU::sub0);
3065 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), HiReg)
3066 .
addReg(Src, {}, AMDGPU::sub1);
3067 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_MOV_B32), ConstReg)
3072 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_AND_B32), OpReg)
3076 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::REG_SEQUENCE), Dst)
3082 MI.eraseFromParent();
3087 return MI.getOpcode() == TargetOpcode::G_CONSTANT;
3093 unsigned OpNo =
Load.getOpcode() == AMDGPU::G_PREFETCH ? 0 : 1;
3094 const MachineInstr *PtrMI =
3095 MRI.getUniqueVRegDef(
Load.getOperand(OpNo).getReg());
3099 if (PtrMI->
getOpcode() != TargetOpcode::G_PTR_ADD)
3104 for (
unsigned i = 1; i != 3; ++i) {
3105 const MachineOperand &GEPOp = PtrMI->
getOperand(i);
3106 const MachineInstr *OpDef = MRI.getUniqueVRegDef(GEPOp.
getReg());
3111 assert(GEPInfo.Imm == 0);
3115 const RegisterBank *OpBank = RBI.getRegBank(GEPOp.
getReg(), MRI, TRI);
3116 if (OpBank->
getID() == AMDGPU::SGPRRegBankID)
3117 GEPInfo.SgprParts.push_back(GEPOp.
getReg());
3119 GEPInfo.VgprParts.push_back(GEPOp.
getReg());
3123 getAddrModeInfo(*PtrMI, MRI, AddrInfo);
3126bool AMDGPUInstructionSelector::isSGPR(
Register Reg)
const {
3127 return RBI.getRegBank(
Reg, *MRI, TRI)->getID() == AMDGPU::SGPRRegBankID;
3130bool AMDGPUInstructionSelector::isInstrUniform(
const MachineInstr &
MI)
const {
3131 if (!
MI.hasOneMemOperand())
3134 const MachineMemOperand *MMO = *
MI.memoperands_begin();
3147 if (
MI.getOpcode() == AMDGPU::G_PREFETCH)
3148 return RBI.getRegBank(
MI.getOperand(0).getReg(), *MRI, TRI)->getID() ==
3149 AMDGPU::SGPRRegBankID;
3152 return I &&
I->getMetadata(
"amdgpu.uniform");
3156 for (
const GEPInfo &GEPInfo : AddrInfo) {
3157 if (!GEPInfo.VgprParts.empty())
3163void AMDGPUInstructionSelector::initM0(
MachineInstr &
I)
const {
3164 const LLT PtrTy = MRI->getType(
I.getOperand(1).getReg());
3167 STI.ldsRequiresM0Init()) {
3171 BuildMI(*BB, &
I,
I.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), AMDGPU::M0)
3176bool AMDGPUInstructionSelector::selectG_LOAD_STORE_ATOMICRMW(
3183 if (
Reg.isPhysical())
3187 const unsigned Opcode =
MI.getOpcode();
3189 if (Opcode == AMDGPU::COPY)
3192 if (Opcode == AMDGPU::G_AND || Opcode == AMDGPU::G_OR ||
3193 Opcode == AMDGPU::G_XOR)
3198 return GI->is(Intrinsic::amdgcn_class);
3200 return Opcode == AMDGPU::G_ICMP || Opcode == AMDGPU::G_FCMP;
3203bool AMDGPUInstructionSelector::selectG_BRCOND(
MachineInstr &
I)
const {
3205 MachineOperand &CondOp =
I.getOperand(0);
3218 if (!isVCC(CondReg, *MRI)) {
3222 CondPhysReg = AMDGPU::SCC;
3223 BrOpcode = AMDGPU::S_CBRANCH_SCC1;
3224 ConstrainRC = &AMDGPU::SReg_32RegClass;
3231 const bool Is64 = STI.isWave64();
3232 const unsigned Opcode = Is64 ? AMDGPU::S_AND_B64 : AMDGPU::S_AND_B32;
3233 const Register Exec = Is64 ? AMDGPU::EXEC : AMDGPU::EXEC_LO;
3235 Register TmpReg = MRI->createVirtualRegister(TRI.getBoolRC());
3236 BuildMI(*BB, &
I,
DL, TII.get(Opcode), TmpReg)
3243 CondPhysReg = TRI.getVCC();
3244 BrOpcode = AMDGPU::S_CBRANCH_VCCNZ;
3245 ConstrainRC = TRI.getBoolRC();
3248 if (!MRI->getRegClassOrNull(CondReg))
3249 MRI->setRegClass(CondReg, ConstrainRC);
3251 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), CondPhysReg)
3254 .
addMBB(
I.getOperand(1).getMBB());
3256 I.eraseFromParent();
3260bool AMDGPUInstructionSelector::selectG_GLOBAL_VALUE(
3262 Register DstReg =
I.getOperand(0).getReg();
3263 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3264 const bool IsVGPR = DstRB->
getID() == AMDGPU::VGPRRegBankID;
3265 I.setDesc(TII.get(IsVGPR ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32));
3269 return RBI.constrainGenericRegister(
3270 DstReg, IsVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass, *MRI);
3273bool AMDGPUInstructionSelector::selectG_PTRMASK(
MachineInstr &
I)
const {
3274 Register DstReg =
I.getOperand(0).getReg();
3275 Register SrcReg =
I.getOperand(1).getReg();
3276 Register MaskReg =
I.getOperand(2).getReg();
3277 LLT Ty = MRI->getType(DstReg);
3278 LLT MaskTy = MRI->getType(MaskReg);
3282 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3283 const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
3284 const RegisterBank *MaskRB = RBI.getRegBank(MaskReg, *MRI, TRI);
3285 const bool IsVGPR = DstRB->
getID() == AMDGPU::VGPRRegBankID;
3291 APInt MaskOnes =
VT->getKnownOnes(MaskReg).zext(64);
3295 const bool CanCopyLow32 = (MaskOnes & MaskLo32) == MaskLo32;
3296 const bool CanCopyHi32 = (MaskOnes & MaskHi32) == MaskHi32;
3299 !CanCopyLow32 && !CanCopyHi32) {
3300 auto MIB =
BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_AND_B64), DstReg)
3304 I.eraseFromParent();
3309 unsigned NewOpc = IsVGPR ? AMDGPU::V_AND_B32_e64 : AMDGPU::S_AND_B32;
3311 = IsVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
3316 TRI.getRegClassForTypeOnBank(MaskTy, *MaskRB);
3318 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
3319 !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
3320 !RBI.constrainGenericRegister(MaskReg, *MaskRC, *MRI))
3325 "ptrmask should have been narrowed during legalize");
3327 auto NewOp =
BuildMI(*BB, &
I,
DL, TII.get(NewOpc), DstReg)
3333 I.eraseFromParent();
3337 Register HiReg = MRI->createVirtualRegister(&RegRC);
3338 Register LoReg = MRI->createVirtualRegister(&RegRC);
3341 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), LoReg)
3342 .
addReg(SrcReg, {}, AMDGPU::sub0);
3343 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), HiReg)
3344 .
addReg(SrcReg, {}, AMDGPU::sub1);
3353 Register MaskLo = MRI->createVirtualRegister(&RegRC);
3354 MaskedLo = MRI->createVirtualRegister(&RegRC);
3356 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), MaskLo)
3357 .
addReg(MaskReg, {}, AMDGPU::sub0);
3358 BuildMI(*BB, &
I,
DL, TII.get(NewOpc), MaskedLo)
3367 Register MaskHi = MRI->createVirtualRegister(&RegRC);
3368 MaskedHi = MRI->createVirtualRegister(&RegRC);
3370 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), MaskHi)
3371 .
addReg(MaskReg, {}, AMDGPU::sub1);
3372 BuildMI(*BB, &
I,
DL, TII.get(NewOpc), MaskedHi)
3377 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
3382 I.eraseFromParent();
3388static std::pair<Register, unsigned>
3395 std::tie(IdxBaseReg,
Offset) =
3397 if (IdxBaseReg == AMDGPU::NoRegister) {
3401 IdxBaseReg = IdxReg;
3408 if (
static_cast<unsigned>(
Offset) >= SubRegs.
size())
3409 return std::pair(IdxReg, SubRegs[0]);
3410 return std::pair(IdxBaseReg, SubRegs[
Offset]);
3413bool AMDGPUInstructionSelector::selectG_EXTRACT_VECTOR_ELT(
3419 LLT DstTy = MRI->getType(DstReg);
3420 LLT SrcTy = MRI->getType(SrcReg);
3422 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3423 const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
3424 const RegisterBank *IdxRB = RBI.getRegBank(IdxReg, *MRI, TRI);
3428 if (IdxRB->
getID() != AMDGPU::SGPRRegBankID)
3432 TRI.getRegClassForTypeOnBank(SrcTy, *SrcRB);
3434 TRI.getRegClassForTypeOnBank(DstTy, *DstRB);
3435 if (!SrcRC || !DstRC)
3437 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
3438 !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
3439 !RBI.constrainGenericRegister(IdxReg, AMDGPU::SReg_32RegClass, *MRI))
3450 if (SrcRB->
getID() == AMDGPU::SGPRRegBankID) {
3454 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3457 unsigned Opc = Is64 ? AMDGPU::S_MOVRELS_B64 : AMDGPU::S_MOVRELS_B32;
3459 .
addReg(SrcReg, {}, SubReg)
3461 MI.eraseFromParent();
3468 if (!STI.useVGPRIndexMode()) {
3469 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3471 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::V_MOVRELS_B32_e32), DstReg)
3472 .
addReg(SrcReg, {}, SubReg)
3474 MI.eraseFromParent();
3478 const MCInstrDesc &GPRIDXDesc =
3479 TII.getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*SrcRC),
true);
3485 MI.eraseFromParent();
3490bool AMDGPUInstructionSelector::selectG_INSERT_VECTOR_ELT(
3497 LLT VecTy = MRI->getType(DstReg);
3498 LLT ValTy = MRI->getType(ValReg);
3502 const RegisterBank *VecRB = RBI.getRegBank(VecReg, *MRI, TRI);
3503 const RegisterBank *ValRB = RBI.getRegBank(ValReg, *MRI, TRI);
3504 const RegisterBank *IdxRB = RBI.getRegBank(IdxReg, *MRI, TRI);
3510 if (IdxRB->
getID() != AMDGPU::SGPRRegBankID)
3514 TRI.getRegClassForTypeOnBank(VecTy, *VecRB);
3516 TRI.getRegClassForTypeOnBank(ValTy, *ValRB);
3518 if (!RBI.constrainGenericRegister(VecReg, *VecRC, *MRI) ||
3519 !RBI.constrainGenericRegister(DstReg, *VecRC, *MRI) ||
3520 !RBI.constrainGenericRegister(ValReg, *ValRC, *MRI) ||
3521 !RBI.constrainGenericRegister(IdxReg, AMDGPU::SReg_32RegClass, *MRI))
3524 if (VecRB->
getID() == AMDGPU::VGPRRegBankID && ValSize != 32)
3528 std::tie(IdxReg, SubReg) =
3531 const bool IndexMode = VecRB->
getID() == AMDGPU::VGPRRegBankID &&
3532 STI.useVGPRIndexMode();
3538 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3541 const MCInstrDesc &RegWriteOp = TII.getIndirectRegWriteMovRelPseudo(
3542 VecSize, ValSize, VecRB->
getID() == AMDGPU::SGPRRegBankID);
3547 MI.eraseFromParent();
3551 const MCInstrDesc &GPRIDXDesc =
3552 TII.getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC),
false);
3559 MI.eraseFromParent();
3565 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
3566 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
3567 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
3568 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
3569 case Intrinsic::amdgcn_load_async_to_lds:
3570 case Intrinsic::amdgcn_global_load_async_lds:
3576bool AMDGPUInstructionSelector::selectBufferLoadLds(
MachineInstr &
MI)
const {
3577 if (!Subtarget->hasVMemToLDSLoad())
3580 unsigned Size =
MI.getOperand(3).getImm();
3584 const bool HasVIndex =
MI.getNumOperands() == 9;
3588 VIndex =
MI.getOperand(4).getReg();
3592 Register VOffset =
MI.getOperand(4 + OpOffset).getReg();
3593 std::optional<ValueAndVReg> MaybeVOffset =
3595 const bool HasVOffset = !MaybeVOffset || MaybeVOffset->Value.getZExtValue();
3601 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_BOTHEN
3602 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_IDXEN
3603 : HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFEN
3604 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFSET;
3607 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_BOTHEN
3608 : AMDGPU::BUFFER_LOAD_USHORT_LDS_IDXEN
3609 : HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFEN
3610 : AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFSET;
3613 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_BOTHEN
3614 : AMDGPU::BUFFER_LOAD_DWORD_LDS_IDXEN
3615 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFEN
3616 : AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFSET;
3619 if (!Subtarget->hasLDSLoadB96_B128())
3622 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_BOTHEN
3623 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_IDXEN
3624 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFEN
3625 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFSET;
3628 if (!Subtarget->hasLDSLoadB96_B128())
3631 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_BOTHEN
3632 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_IDXEN
3633 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFEN
3634 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFSET;
3641 .
add(
MI.getOperand(2));
3645 if (HasVIndex && HasVOffset) {
3646 Register IdxReg = MRI->createVirtualRegister(TRI.getVGPR64Class());
3647 BuildMI(*
MBB, &*MIB,
DL, TII.get(AMDGPU::REG_SEQUENCE), IdxReg)
3654 }
else if (HasVIndex) {
3656 }
else if (HasVOffset) {
3660 MIB.
add(
MI.getOperand(1));
3661 MIB.
add(
MI.getOperand(5 + OpOffset));
3662 MIB.
add(
MI.getOperand(6 + OpOffset));
3664 unsigned Aux =
MI.getOperand(7 + OpOffset).getImm();
3673 MachineMemOperand *LoadMMO = *
MI.memoperands_begin();
3678 MachinePointerInfo StorePtrI = LoadPtrI;
3689 MachineMemOperand *StoreMMO =
3695 MI.eraseFromParent();
3708 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3714 return Def->getOperand(1).getReg();
3728 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3736 return Def->getOperand(1).getReg();
3738 if (
VT->signBitIsZero(
Reg))
3739 return matchZeroExtendFromS32(
Reg);
3747AMDGPUInstructionSelector::matchZeroExtendFromS32OrS32(
Register Reg)
const {
3749 : matchZeroExtendFromS32(
Reg);
3755AMDGPUInstructionSelector::matchSignExtendFromS32OrS32(
Register Reg)
const {
3757 : matchSignExtendFromS32(
Reg);
3761AMDGPUInstructionSelector::matchExtendFromS32OrS32(
Register Reg,
3762 bool IsSigned)
const {
3764 return matchSignExtendFromS32OrS32(
Reg);
3766 return matchZeroExtendFromS32OrS32(
Reg);
3776 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3783 return Def->getOperand(1).getReg();
3788bool AMDGPUInstructionSelector::selectGlobalLoadLds(
MachineInstr &
MI)
const{
3789 if (!Subtarget->hasVMemToLDSLoad())
3793 unsigned Size =
MI.getOperand(3).getImm();
3800 Opc = AMDGPU::GLOBAL_LOAD_LDS_UBYTE;
3803 Opc = AMDGPU::GLOBAL_LOAD_LDS_USHORT;
3806 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORD;
3809 if (!Subtarget->hasLDSLoadB96_B128())
3811 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX3;
3814 if (!Subtarget->hasLDSLoadB96_B128())
3816 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX4;
3823 .
add(
MI.getOperand(2));
3829 if (!isSGPR(Addr)) {
3831 if (isSGPR(AddrDef->Reg)) {
3832 Addr = AddrDef->Reg;
3833 }
else if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
3836 if (isSGPR(SAddr)) {
3837 Register PtrBaseOffset = AddrDef->MI->getOperand(2).getReg();
3838 if (
Register Off = matchZeroExtendFromS32(PtrBaseOffset)) {
3849 VOffset = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
3861 MIB.
add(
MI.getOperand(4));
3863 unsigned Aux =
MI.getOperand(5).getImm();
3867 MachineMemOperand *LoadMMO = *
MI.memoperands_begin();
3869 LoadPtrI.
Offset =
MI.getOperand(4).getImm();
3870 MachinePointerInfo StorePtrI = LoadPtrI;
3879 MachineMemOperand *StoreMMO =
3881 sizeof(int32_t),
Align(4));
3885 MI.eraseFromParent();
3890bool AMDGPUInstructionSelector::selectTensorLoadStore(
MachineInstr &
MI,
3892 bool IsLoad = IID == Intrinsic::amdgcn_tensor_load_to_lds;
3894 IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d4 : AMDGPU::TENSOR_STORE_FROM_LDS_d4;
3898 const auto isAllZeros = [&](MachineOperand &Opnd) {
3899 const MachineInstr *
DefMI = MRI->getVRegDef(Opnd.getReg());
3908 Opc = IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d2
3909 : AMDGPU::TENSOR_STORE_FROM_LDS_d2;
3916 .
add(
MI.getOperand(1))
3917 .
add(
MI.getOperand(2));
3919 if (NumGroups >= 4) {
3920 MIB.
add(
MI.getOperand(3))
3921 .
add(
MI.getOperand(4));
3925 .
add(
MI.getOperand(6));
3927 MI.eraseFromParent();
3931bool AMDGPUInstructionSelector::selectBVHIntersectRayIntrinsic(
3933 unsigned OpcodeOpIdx =
3934 MI.getOpcode() == AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY ? 1 : 3;
3935 MI.setDesc(TII.get(
MI.getOperand(OpcodeOpIdx).getImm()));
3936 MI.removeOperand(OpcodeOpIdx);
3937 MI.addImplicitDefUseOperands(*
MI.getMF());
3944bool AMDGPUInstructionSelector::selectSMFMACIntrin(
MachineInstr &
MI)
const {
3947 case Intrinsic::amdgcn_smfmac_f32_16x16x32_f16:
3948 Opc = AMDGPU::V_SMFMAC_F32_16X16X32_F16_e64;
3950 case Intrinsic::amdgcn_smfmac_f32_32x32x16_f16:
3951 Opc = AMDGPU::V_SMFMAC_F32_32X32X16_F16_e64;
3953 case Intrinsic::amdgcn_smfmac_f32_16x16x32_bf16:
3954 Opc = AMDGPU::V_SMFMAC_F32_16X16X32_BF16_e64;
3956 case Intrinsic::amdgcn_smfmac_f32_32x32x16_bf16:
3957 Opc = AMDGPU::V_SMFMAC_F32_32X32X16_BF16_e64;
3959 case Intrinsic::amdgcn_smfmac_i32_16x16x64_i8:
3960 Opc = AMDGPU::V_SMFMAC_I32_16X16X64_I8_e64;
3962 case Intrinsic::amdgcn_smfmac_i32_32x32x32_i8:
3963 Opc = AMDGPU::V_SMFMAC_I32_32X32X32_I8_e64;
3965 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_bf8:
3966 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF8_BF8_e64;
3968 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_fp8:
3969 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF8_FP8_e64;
3971 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_bf8:
3972 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_FP8_BF8_e64;
3974 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_fp8:
3975 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_FP8_FP8_e64;
3977 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_bf8:
3978 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF8_BF8_e64;
3980 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_fp8:
3981 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF8_FP8_e64;
3983 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_bf8:
3984 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_FP8_BF8_e64;
3986 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_fp8:
3987 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_FP8_FP8_e64;
3989 case Intrinsic::amdgcn_smfmac_f32_16x16x64_f16:
3990 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_F16_e64;
3992 case Intrinsic::amdgcn_smfmac_f32_32x32x32_f16:
3993 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_F16_e64;
3995 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf16:
3996 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF16_e64;
3998 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf16:
3999 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF16_e64;
4001 case Intrinsic::amdgcn_smfmac_i32_16x16x128_i8:
4002 Opc = AMDGPU::V_SMFMAC_I32_16X16X128_I8_e64;
4004 case Intrinsic::amdgcn_smfmac_i32_32x32x64_i8:
4005 Opc = AMDGPU::V_SMFMAC_I32_32X32X64_I8_e64;
4007 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_bf8:
4008 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_BF8_BF8_e64;
4010 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_fp8:
4011 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_BF8_FP8_e64;
4013 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_bf8:
4014 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_FP8_BF8_e64;
4016 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_fp8:
4017 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_FP8_FP8_e64;
4019 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_bf8:
4020 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_BF8_BF8_e64;
4022 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_fp8:
4023 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_BF8_FP8_e64;
4025 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_bf8:
4026 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_FP8_BF8_e64;
4028 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_fp8:
4029 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_FP8_FP8_e64;
4035 auto VDst_In =
MI.getOperand(4);
4037 MI.setDesc(TII.get(
Opc));
4038 MI.removeOperand(4);
4039 MI.removeOperand(1);
4040 MI.addOperand(VDst_In);
4041 MI.addImplicitDefUseOperands(*
MI.getMF());
4042 const MCInstrDesc &MCID =
MI.getDesc();
4044 MI.getOperand(0).setIsEarlyClobber(
true);
4049bool AMDGPUInstructionSelector::selectPermlaneSwapIntrin(
4051 if (IntrID == Intrinsic::amdgcn_permlane16_swap &&
4052 !Subtarget->hasPermlane16Swap())
4054 if (IntrID == Intrinsic::amdgcn_permlane32_swap &&
4055 !Subtarget->hasPermlane32Swap())
4058 unsigned Opcode = IntrID == Intrinsic::amdgcn_permlane16_swap
4059 ? AMDGPU::V_PERMLANE16_SWAP_B32_e64
4060 : AMDGPU::V_PERMLANE32_SWAP_B32_e64;
4062 MI.removeOperand(2);
4063 MI.setDesc(TII.get(Opcode));
4066 MachineOperand &FI =
MI.getOperand(4);
4073bool AMDGPUInstructionSelector::selectWaveAddress(
MachineInstr &
MI)
const {
4076 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4077 const bool IsVALU = DstRB->
getID() == AMDGPU::VGPRRegBankID;
4082 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHRREV_B32_e64), DstReg)
4083 .
addImm(Subtarget->getWavefrontSizeLog2())
4088 .
addImm(Subtarget->getWavefrontSizeLog2())
4093 IsVALU ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
4094 if (!RBI.constrainGenericRegister(DstReg, RC, *MRI))
4097 MI.eraseFromParent();
4101bool AMDGPUInstructionSelector::selectWaveShuffleIntrin(
4111 const LLT DstTy = MRI->getType(DstReg);
4113 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4115 TRI.getRegClassForSizeOnBank(DstSize, *DstRB);
4120 if (!Subtarget->supportsBPermute())
4124 if (Subtarget->supportsWaveWideBPermute()) {
4125 Register ShiftIdxReg = MRI->createVirtualRegister(DstRC);
4126 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), ShiftIdxReg)
4136 assert(Subtarget->isWave64());
4140 MRI->createVirtualRegister(TRI.getRegClass(AMDGPU::SReg_32RegClassID));
4141 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefValReg);
4143 Register UndefExecReg = MRI->createVirtualRegister(
4144 TRI.getRegClass(AMDGPU::SReg_64_XEXECRegClassID));
4145 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefExecReg);
4147 Register PoisonValReg = MRI->createVirtualRegister(DstRC);
4148 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_SET_INACTIVE_B32), PoisonValReg)
4156 Register ShiftIdxReg = MRI->createVirtualRegister(DstRC);
4157 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), ShiftIdxReg)
4161 Register PoisonIdxReg = MRI->createVirtualRegister(DstRC);
4162 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_SET_INACTIVE_B32), PoisonIdxReg)
4169 Register PoisonUnshiftedIdxReg = MRI->createVirtualRegister(DstRC);
4171 PoisonUnshiftedIdxReg)
4179 Register SameSidePermReg = MRI->createVirtualRegister(DstRC);
4180 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::DS_BPERMUTE_B32), SameSidePermReg)
4185 Register SwappedValReg = MRI->createVirtualRegister(DstRC);
4186 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_PERMLANE64_B32), SwappedValReg)
4189 Register OppSidePermReg = MRI->createVirtualRegister(DstRC);
4190 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::DS_BPERMUTE_B32), OppSidePermReg)
4195 Register WWMSwapPermReg = MRI->createVirtualRegister(DstRC);
4196 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::STRICT_WWM), WWMSwapPermReg)
4203 Register ThreadIDReg = MRI->createVirtualRegister(DstRC);
4204 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_MBCNT_LO_U32_B32_e64), ThreadIDReg)
4208 Register XORReg = MRI->createVirtualRegister(DstRC);
4211 .
addReg(PoisonUnshiftedIdxReg);
4213 Register ANDReg = MRI->createVirtualRegister(DstRC);
4218 Register CompareReg = MRI->createVirtualRegister(
4219 TRI.getRegClass(AMDGPU::SReg_64_XEXECRegClassID));
4220 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_CMP_EQ_U32_e64), CompareReg)
4225 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
4233 MI.eraseFromParent();
4242 unsigned NumOpcodes = 0;
4255 const uint8_t SrcBits[3] = { 0xf0, 0xcc, 0xaa };
4266 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4280 if (Src.size() == 3) {
4287 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4288 if (Src[
I] ==
LHS) {
4298 Bits = SrcBits[Src.size()];
4304 switch (
MI->getOpcode()) {
4305 case TargetOpcode::G_AND:
4306 case TargetOpcode::G_OR:
4307 case TargetOpcode::G_XOR: {
4312 if (!getOperandBits(
LHS, LHSBits) ||
4313 !getOperandBits(
RHS, RHSBits)) {
4314 Src = std::move(Backup);
4315 return std::make_pair(0, 0);
4336 uint8_t LHSBitsOrig = LHSBits;
4337 uint8_t RHSBitsOrig = RHSBits;
4341 NumOpcodes += LHSOp.first;
4342 LHSBits = LHSOp.second;
4349 NumOpcodes += RHSOp.first;
4350 RHSBits = RHSOp.second;
4354 auto dependsOnSlot = [](
uint8_t TT,
int Slot) ->
bool {
4355 if (Slot < 0 || Slot > 2)
4357 const uint8_t Masks[3] = {0x0f, 0x33, 0x55};
4358 const int Shifts[3] = {4, 2, 1};
4359 return ((TT ^ (TT >> Shifts[Slot])) & Masks[Slot]) != 0;
4365 const uint8_t SrcBitsConst[3] = {0xf0, 0xcc, 0xaa};
4372 for (
int I = 0;
I < (int)S.size();
I++) {
4373 if (Bits == SrcBitsConst[
I] && S[
I] ==
Op)
4375 if (IsNegationOp && Bits == (
uint8_t)~SrcBitsConst[
I] &&
4376 S[
I] == NegatedInner)
4387 for (
int I = 0;
I < (int)SrcAfterLHS.
size() &&
I < 3;
I++) {
4388 if (
I < (
int)Src.size() && Src[
I] != SrcAfterLHS[
I] &&
4389 dependsOnSlot(LHSBits,
I)) {
4398 if (!Stale && !RHSOp.first) {
4399 int Slot = findSlot(RHSBitsOrig,
RHS, SrcBeforeRecurse);
4401 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4407 if (!Stale && !LHSOp.first) {
4408 int Slot = findSlot(LHSBitsOrig,
LHS, SrcBeforeRecurse);
4410 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4415 Src = std::move(SrcBeforeRecurse);
4416 LHSBits = LHSBitsOrig;
4417 RHSBits = RHSBitsOrig;
4423 return std::make_pair(0, 0);
4427 switch (
MI->getOpcode()) {
4428 case TargetOpcode::G_AND:
4429 TTbl = LHSBits & RHSBits;
4431 case TargetOpcode::G_OR:
4432 TTbl = LHSBits | RHSBits;
4434 case TargetOpcode::G_XOR:
4435 TTbl = LHSBits ^ RHSBits;
4441 return std::make_pair(NumOpcodes + 1, TTbl);
4444bool AMDGPUInstructionSelector::selectBITOP3(
MachineInstr &
MI)
const {
4445 if (!Subtarget->hasBitOp3Insts())
4449 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4450 const bool IsVALU = DstRB->
getID() == AMDGPU::VGPRRegBankID;
4456 unsigned NumOpcodes;
4458 std::tie(NumOpcodes, TTbl) =
BitOp3_Op(DstReg, Src, *MRI);
4462 if (NumOpcodes < 2 || Src.empty())
4467 unsigned Size = MRI->getType(DstReg).getSizeInBits();
4468 assert((
Size == 16 ||
Size == 32) &&
"unexpected VALU logic op size");
4469 const bool IsB32 =
Size == 32;
4470 if (NumOpcodes == 2 && IsB32) {
4478 }
else if (NumOpcodes < 4) {
4485 unsigned Opc = IsB32 ? AMDGPU::V_BITOP3_B32_e64 : AMDGPU::V_BITOP3_B16_e64;
4486 if (!IsB32 && STI.hasTrue16BitInsts())
4487 Opc = STI.useRealTrue16Insts() ? AMDGPU::V_BITOP3_B16_gfx1250_t16_e64
4488 : AMDGPU::V_BITOP3_B16_gfx1250_fake16_e64;
4489 unsigned CBL = STI.getConstantBusLimit(
Opc);
4493 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4494 const RegisterBank *RB = RBI.getRegBank(Src[
I], *MRI, TRI);
4495 if (RB->
getID() != AMDGPU::SGPRRegBankID)
4501 Register NewReg = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
4512 while (Src.size() < 3)
4513 Src.push_back(Src[0]);
4530 MI.eraseFromParent();
4535bool AMDGPUInstructionSelector::selectStackRestore(
MachineInstr &
MI)
const {
4537 if (!RBI.constrainGenericRegister(SrcReg, AMDGPU::SReg_32RegClass, *MRI))
4540 MachineInstr *
DefMI = MRI->getVRegDef(SrcReg);
4542 Subtarget->getTargetLowering()->getStackPointerRegisterToSaveRestore();
4548 WaveAddr = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
4551 .
addImm(Subtarget->getWavefrontSizeLog2())
4558 MI.eraseFromParent();
4564 if (!
I.isPreISelOpcode()) {
4566 return selectCOPY(
I);
4570 switch (
I.getOpcode()) {
4571 case TargetOpcode::G_AND:
4572 case TargetOpcode::G_OR:
4573 case TargetOpcode::G_XOR:
4574 if (selectBITOP3(
I))
4578 return selectG_AND_OR_XOR(
I);
4579 case TargetOpcode::G_ADD:
4580 case TargetOpcode::G_SUB:
4581 case TargetOpcode::G_PTR_ADD:
4584 return selectG_ADD_SUB(
I);
4585 case TargetOpcode::G_UADDO:
4586 case TargetOpcode::G_USUBO:
4587 case TargetOpcode::G_UADDE:
4588 case TargetOpcode::G_USUBE:
4589 return selectG_UADDO_USUBO_UADDE_USUBE(
I);
4590 case AMDGPU::G_AMDGPU_MAD_U64_U32:
4591 case AMDGPU::G_AMDGPU_MAD_I64_I32:
4592 return selectG_AMDGPU_MAD_64_32(
I);
4593 case TargetOpcode::G_INTTOPTR:
4594 case TargetOpcode::G_BITCAST:
4595 case TargetOpcode::G_PTRTOINT:
4596 case TargetOpcode::G_FREEZE:
4597 return selectCOPY(
I);
4598 case TargetOpcode::G_FNEG:
4601 return selectG_FNEG(
I);
4602 case TargetOpcode::G_FABS:
4605 return selectG_FABS(
I);
4606 case TargetOpcode::G_EXTRACT:
4607 return selectG_EXTRACT(
I);
4608 case TargetOpcode::G_MERGE_VALUES:
4609 case TargetOpcode::G_CONCAT_VECTORS:
4610 return selectG_MERGE_VALUES(
I);
4611 case TargetOpcode::G_UNMERGE_VALUES:
4612 return selectG_UNMERGE_VALUES(
I);
4613 case TargetOpcode::G_BUILD_VECTOR:
4614 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
4615 return selectG_BUILD_VECTOR(
I);
4616 case TargetOpcode::G_IMPLICIT_DEF:
4617 return selectG_IMPLICIT_DEF(
I);
4618 case TargetOpcode::G_INSERT:
4619 return selectG_INSERT(
I);
4620 case TargetOpcode::G_INTRINSIC:
4621 case TargetOpcode::G_INTRINSIC_CONVERGENT:
4622 return selectG_INTRINSIC(
I);
4623 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
4624 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
4625 return selectG_INTRINSIC_W_SIDE_EFFECTS(
I);
4626 case TargetOpcode::G_ICMP:
4627 case TargetOpcode::G_FCMP:
4628 if (selectG_ICMP_or_FCMP(
I))
4631 case TargetOpcode::G_LOAD:
4632 case TargetOpcode::G_ZEXTLOAD:
4633 case TargetOpcode::G_SEXTLOAD:
4634 case TargetOpcode::G_STORE:
4635 case TargetOpcode::G_ATOMIC_CMPXCHG:
4636 case TargetOpcode::G_ATOMICRMW_XCHG:
4637 case TargetOpcode::G_ATOMICRMW_ADD:
4638 case TargetOpcode::G_ATOMICRMW_SUB:
4639 case TargetOpcode::G_ATOMICRMW_AND:
4640 case TargetOpcode::G_ATOMICRMW_OR:
4641 case TargetOpcode::G_ATOMICRMW_XOR:
4642 case TargetOpcode::G_ATOMICRMW_MIN:
4643 case TargetOpcode::G_ATOMICRMW_MAX:
4644 case TargetOpcode::G_ATOMICRMW_UMIN:
4645 case TargetOpcode::G_ATOMICRMW_UMAX:
4646 case TargetOpcode::G_ATOMICRMW_UINC_WRAP:
4647 case TargetOpcode::G_ATOMICRMW_UDEC_WRAP:
4648 case TargetOpcode::G_ATOMICRMW_USUB_COND:
4649 case TargetOpcode::G_ATOMICRMW_USUB_SAT:
4650 case TargetOpcode::G_ATOMICRMW_FADD:
4651 case TargetOpcode::G_ATOMICRMW_FMIN:
4652 case TargetOpcode::G_ATOMICRMW_FMAX:
4653 return selectG_LOAD_STORE_ATOMICRMW(
I);
4654 case TargetOpcode::G_SELECT:
4655 return selectG_SELECT(
I);
4656 case TargetOpcode::G_TRUNC:
4657 return selectG_TRUNC(
I);
4658 case TargetOpcode::G_SEXT:
4659 case TargetOpcode::G_ZEXT:
4660 case TargetOpcode::G_ANYEXT:
4661 case TargetOpcode::G_SEXT_INREG:
4665 if (MRI->getType(
I.getOperand(1).getReg()) !=
LLT::scalar(1) &&
4668 return selectG_SZA_EXT(
I);
4669 case TargetOpcode::G_FPEXT:
4670 if (selectG_FPEXT(
I))
4673 case TargetOpcode::G_BRCOND:
4674 return selectG_BRCOND(
I);
4675 case TargetOpcode::G_GLOBAL_VALUE:
4676 return selectG_GLOBAL_VALUE(
I);
4677 case TargetOpcode::G_PTRMASK:
4678 return selectG_PTRMASK(
I);
4679 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4680 return selectG_EXTRACT_VECTOR_ELT(
I);
4681 case TargetOpcode::G_INSERT_VECTOR_ELT:
4682 return selectG_INSERT_VECTOR_ELT(
I);
4683 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD:
4684 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16:
4685 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET:
4686 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE:
4687 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16: {
4690 assert(Intr &&
"not an image intrinsic with image pseudo");
4691 return selectImageIntrinsic(
I, Intr);
4693 case AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY:
4694 case AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY:
4695 case AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY:
4696 return selectBVHIntersectRayIntrinsic(
I);
4697 case AMDGPU::G_SBFX:
4698 case AMDGPU::G_UBFX:
4699 return selectG_SBFX_UBFX(
I);
4700 case AMDGPU::G_SI_CALL:
4701 I.setDesc(TII.get(AMDGPU::SI_CALL));
4703 case AMDGPU::G_AMDGPU_WAVE_ADDRESS:
4704 return selectWaveAddress(
I);
4705 case AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_RETURN: {
4706 I.setDesc(TII.get(AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN));
4709 case AMDGPU::G_STACKRESTORE:
4710 return selectStackRestore(
I);
4712 return selectPHI(
I);
4713 case AMDGPU::G_AMDGPU_COPY_SCC_VCC:
4714 return selectCOPY_SCC_VCC(
I);
4715 case AMDGPU::G_AMDGPU_COPY_VCC_SCC:
4716 return selectCOPY_VCC_SCC(
I);
4717 case AMDGPU::G_AMDGPU_READANYLANE:
4718 return selectReadAnyLane(
I);
4719 case TargetOpcode::G_CONSTANT:
4720 case TargetOpcode::G_FCONSTANT:
4728AMDGPUInstructionSelector::selectVCSRC(
MachineOperand &Root)
const {
4735std::pair<Register, unsigned> AMDGPUInstructionSelector::selectVOP3ModsImpl(
4736 Register Src,
bool IsCanonicalizing,
bool AllowAbs,
bool OpSel)
const {
4740 if (
MI->getOpcode() == AMDGPU::G_FNEG) {
4741 Src =
MI->getOperand(1).getReg();
4744 }
else if (
MI->getOpcode() == AMDGPU::G_FSUB && IsCanonicalizing) {
4749 if (
LHS &&
LHS->isZero()) {
4751 Src =
MI->getOperand(2).getReg();
4755 if (AllowAbs &&
MI->getOpcode() == AMDGPU::G_FABS) {
4756 Src =
MI->getOperand(1).getReg();
4763 return std::pair(Src, Mods);
4766std::pair<Register, unsigned>
4767AMDGPUInstructionSelector::selectVOP3PModsF32Impl(
Register Src)
const {
4769 std::tie(Src, Mods) = selectVOP3ModsImpl(Src);
4771 return std::pair(Src, Mods);
4774Register AMDGPUInstructionSelector::copyToVGPRIfSrcFolded(
4776 bool ForceVGPR)
const {
4777 if ((Mods != 0 || ForceVGPR) &&
4778 RBI.getRegBank(Src, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID) {
4785 TII.
get(AMDGPU::COPY), VGPRSrc)
4797AMDGPUInstructionSelector::selectVSRC0(
MachineOperand &Root)
const {
4799 [=](MachineInstrBuilder &MIB) { MIB.
add(Root); }
4804AMDGPUInstructionSelector::selectVOP3Mods0(
MachineOperand &Root)
const {
4807 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
4810 [=](MachineInstrBuilder &MIB) {
4811 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4813 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
4814 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4815 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4820AMDGPUInstructionSelector::selectVOP3BMods0(
MachineOperand &Root)
const {
4823 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
4828 [=](MachineInstrBuilder &MIB) {
4829 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4831 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
4832 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4833 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4838AMDGPUInstructionSelector::selectVOP3OMods(
MachineOperand &Root)
const {
4840 [=](MachineInstrBuilder &MIB) { MIB.
add(Root); },
4841 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4842 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4847AMDGPUInstructionSelector::selectVOP3Mods(
MachineOperand &Root)
const {
4850 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
4853 [=](MachineInstrBuilder &MIB) {
4854 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4856 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4861AMDGPUInstructionSelector::selectVOP3ModsNonCanonicalizing(
4865 std::tie(Src, Mods) =
4866 selectVOP3ModsImpl(Root.
getReg(),
false);
4869 [=](MachineInstrBuilder &MIB) {
4870 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4872 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4877AMDGPUInstructionSelector::selectVOP3BMods(
MachineOperand &Root)
const {
4880 std::tie(Src, Mods) =
4881 selectVOP3ModsImpl(Root.
getReg(),
true,
4885 [=](MachineInstrBuilder &MIB) {
4886 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4888 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4893AMDGPUInstructionSelector::selectVOP3NoMods(
MachineOperand &Root)
const {
4896 if (
Def->getOpcode() == AMDGPU::G_FNEG ||
Def->getOpcode() == AMDGPU::G_FABS)
4899 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
4924 if (
MI->getOpcode() != AMDGPU::G_TRUNC)
4929 return DstSize * 2 == SrcSize;
4935 if (
MI->getOpcode() != AMDGPU::G_LSHR)
4939 std::optional<ValueAndVReg> ShiftAmt;
4940 if (
mi_match(
MI->getOperand(0).getReg(), MRI,
4943 unsigned Shift = ShiftAmt->Value.getZExtValue();
4944 return Shift * 2 == SrcSize;
4952 if (
MI->getOpcode() != AMDGPU::G_SHL)
4956 std::optional<ValueAndVReg> ShiftAmt;
4957 if (
mi_match(
MI->getOperand(0).getReg(), MRI,
4960 unsigned Shift = ShiftAmt->Value.getZExtValue();
4961 return Shift * 2 == SrcSize;
4969 if (
MI->getOpcode() != AMDGPU::G_UNMERGE_VALUES)
4971 return MI->getNumOperands() == 3 &&
MI->getOperand(0).isDef() &&
4972 MI->getOperand(1).isDef() && !
MI->getOperand(2).isDef();
4980 if (
OpTy.isScalar())
4982 if (
OpTy.isVector() &&
OpTy.getNumElements() == 2)
5142static std::optional<std::pair<Register, SrcStatus>>
5147 unsigned Opc =
MI->getOpcode();
5151 case AMDGPU::G_BITCAST:
5152 return std::optional<std::pair<Register, SrcStatus>>(
5153 {
MI->getOperand(1).getReg(), Curr.second});
5155 if (
MI->getOperand(1).getReg().isPhysical())
5156 return std::nullopt;
5157 return std::optional<std::pair<Register, SrcStatus>>(
5158 {
MI->getOperand(1).getReg(), Curr.second});
5159 case AMDGPU::G_FNEG: {
5162 return std::nullopt;
5163 return std::optional<std::pair<Register, SrcStatus>>(
5164 {
MI->getOperand(1).getReg(), Stat});
5171 switch (Curr.second) {
5174 return std::optional<std::pair<Register, SrcStatus>>(
5177 if (Curr.first ==
MI->getOperand(0).getReg())
5178 return std::optional<std::pair<Register, SrcStatus>>(
5180 return std::optional<std::pair<Register, SrcStatus>>(
5192 return std::optional<std::pair<Register, SrcStatus>>(
5196 if (Curr.first ==
MI->getOperand(0).getReg())
5197 return std::optional<std::pair<Register, SrcStatus>>(
5199 return std::optional<std::pair<Register, SrcStatus>>(
5205 return std::optional<std::pair<Register, SrcStatus>>(
5210 return std::optional<std::pair<Register, SrcStatus>>(
5215 return std::optional<std::pair<Register, SrcStatus>>(
5220 return std::optional<std::pair<Register, SrcStatus>>(
5226 return std::nullopt;
5236 bool HasNeg =
false;
5238 bool HasOpsel =
true;
5243 unsigned Opc =
MI->getOpcode();
5245 if (
Opc == TargetOpcode::G_INTRINSIC) {
5248 if (IntrinsicID == Intrinsic::amdgcn_fdot2)
5275 while (
Depth <= MaxDepth && Curr.has_value()) {
5278 Statlist.push_back(Curr.value());
5285static std::pair<Register, SrcStatus>
5292 while (
Depth <= MaxDepth && Curr.has_value()) {
5298 LastSameOrNeg = Curr.value();
5303 return LastSameOrNeg;
5310 return Width1 == Width2;
5345 return isSameBitWidth(NewReg, RootReg, MRI) && IsHalfState(LoStat) &&
5346 IsHalfState(HiStat);
5349std::pair<Register, unsigned> AMDGPUInstructionSelector::selectVOP3PModsImpl(
5355 return {RootReg, Mods};
5358 SearchOptions SO(RootReg, MRI);
5371 if (MRI.getType(RootReg).getSizeInBits() == 128) {
5373 return {Stat.first, Mods};
5378 MI->getNumOperands() != 3 || (IsDOT && Subtarget->hasDOTOpSelHazard())) {
5380 return {Stat.first, Mods};
5386 if (StatlistHi.
empty()) {
5388 return {Stat.first, Mods};
5394 if (StatlistLo.
empty()) {
5396 return {Stat.first, Mods};
5399 for (
int I = StatlistHi.
size() - 1;
I >= 0;
I--) {
5400 for (
int J = StatlistLo.
size() - 1; J >= 0; J--) {
5401 if (StatlistHi[
I].first == StatlistLo[J].first &&
5403 StatlistHi[
I].first, RootReg, TII, MRI))
5404 return {StatlistHi[
I].first,
5405 updateMods(StatlistHi[
I].second, StatlistLo[J].second, Mods)};
5411 return {Stat.first, Mods};
5421 return RB->
getID() == RBNo;
5437 if (
checkRB(RootReg, AMDGPU::SGPRRegBankID, RBI, MRI,
TRI) ||
5438 checkRB(NewReg, AMDGPU::VGPRRegBankID, RBI, MRI,
TRI))
5448 TII.get(AMDGPU::COPY), DstReg)
5456AMDGPUInstructionSelector::selectVOP3PRetHelper(
MachineOperand &Root,
5461 std::tie(
Reg, Mods) = selectVOP3PModsImpl(Root.
getReg(), MRI, IsDOT);
5466 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
5467 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5472AMDGPUInstructionSelector::selectVOP3PMods(
MachineOperand &Root)
const {
5474 return selectVOP3PRetHelper(Root);
5478AMDGPUInstructionSelector::selectVOP3PModsDOT(
MachineOperand &Root)
const {
5480 return selectVOP3PRetHelper(Root,
true);
5484AMDGPUInstructionSelector::selectVOP3PNoModsDOT(
MachineOperand &Root)
const {
5488 std::tie(Src, Mods) = selectVOP3PModsImpl(Root.
getReg(), MRI,
true );
5492 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); }}};
5496AMDGPUInstructionSelector::selectVOP3PModsF32(
MachineOperand &Root)
const {
5499 std::tie(Src, Mods) = selectVOP3PModsF32Impl(Root.
getReg());
5502 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5503 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5508AMDGPUInstructionSelector::selectVOP3PNoModsF32(
MachineOperand &Root)
const {
5511 std::tie(Src, Mods) = selectVOP3PModsF32Impl(Root.
getReg());
5515 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); }}};
5519AMDGPUInstructionSelector::selectWMMAOpSelVOP3PMods(
5522 "expected i1 value");
5528 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5536 switch (Elts.
size()) {
5538 DstRegClass = &AMDGPU::VReg_256RegClass;
5541 DstRegClass = &AMDGPU::VReg_128RegClass;
5544 DstRegClass = &AMDGPU::VReg_64RegClass;
5551 auto MIB =
B.buildInstr(AMDGPU::REG_SEQUENCE)
5553 for (
unsigned i = 0; i < Elts.
size(); ++i) {
5564 if (ModOpcode == TargetOpcode::G_FNEG) {
5568 for (
auto El : Elts) {
5574 if (Elts.size() != NegAbsElts.
size()) {
5583 assert(ModOpcode == TargetOpcode::G_FABS);
5591AMDGPUInstructionSelector::selectWMMAModsF32NegAbs(
MachineOperand &Root)
const {
5600 MachineInstr *ElF32 = MRI->getVRegDef(BV->
getSourceReg(0));
5601 unsigned ModOpcode = (ElF32->
getOpcode() == AMDGPU::G_FNEG)
5618 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5619 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5623AMDGPUInstructionSelector::selectWMMAModsF16Neg(
MachineOperand &Root)
const {
5645 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5646 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5650AMDGPUInstructionSelector::selectWMMAModsF16NegAbs(
MachineOperand &Root)
const {
5658 MachineInstr *ElV2F16 = MRI->getVRegDef(CV->
getSourceReg(0));
5660 unsigned ModOpcode = (ElV2F16->
getOpcode() == AMDGPU::G_FNEG)
5679 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5680 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5684AMDGPUInstructionSelector::selectWMMAVISrc(
MachineOperand &Root)
const {
5685 std::optional<FPValueAndVReg> FPValReg;
5687 if (TII.isInlineConstant(FPValReg->Value)) {
5688 return {{[=](MachineInstrBuilder &MIB) {
5689 MIB.
addImm(FPValReg->Value.bitcastToAPInt().getSExtValue());
5699 if (TII.isInlineConstant(ICst)) {
5709AMDGPUInstructionSelector::selectSWMMACIndex8(
MachineOperand &Root)
const {
5715 std::optional<ValueAndVReg> ShiftAmt;
5717 MRI->getType(ShiftSrc).getSizeInBits() == 32 &&
5718 ShiftAmt->Value.getZExtValue() % 8 == 0) {
5719 Key = ShiftAmt->Value.getZExtValue() / 8;
5724 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5725 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5730AMDGPUInstructionSelector::selectSWMMACIndex16(
MachineOperand &Root)
const {
5737 std::optional<ValueAndVReg> ShiftAmt;
5739 MRI->getType(ShiftSrc).getSizeInBits() == 32 &&
5740 ShiftAmt->Value.getZExtValue() == 16) {
5746 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5747 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5752AMDGPUInstructionSelector::selectSWMMACIndex32(
MachineOperand &Root)
const {
5759 S32 = matchAnyExtendFromS32(Src);
5763 if (
Def->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) {
5768 Src =
Def->getOperand(2).getReg();
5775 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5776 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5781AMDGPUInstructionSelector::selectVOP3OpSelMods(
MachineOperand &Root)
const {
5784 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
5788 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5789 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5795AMDGPUInstructionSelector::selectVINTERPMods(
MachineOperand &Root)
const {
5798 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
5804 [=](MachineInstrBuilder &MIB) {
5806 copyToVGPRIfSrcFolded(Src, Mods, Root, MIB,
true));
5808 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
5813AMDGPUInstructionSelector::selectVINTERPModsHi(
MachineOperand &Root)
const {
5816 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
5822 [=](MachineInstrBuilder &MIB) {
5824 copyToVGPRIfSrcFolded(Src, Mods, Root, MIB,
true));
5826 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
5833bool AMDGPUInstructionSelector::selectScaleOffset(
MachineOperand &Root,
5835 bool IsSigned)
const {
5836 if (!Subtarget->hasScaleOffset())
5840 MachineMemOperand *MMO = *
MI.memoperands_begin();
5852 OffsetReg =
Def->Reg;
5867 m_BinOp(IsSigned ? AMDGPU::S_MUL_I64_I32_PSEUDO : AMDGPU::S_MUL_U64,
5871 (
Mul->getOpcode() == (IsSigned ? AMDGPU::G_AMDGPU_MAD_I64_I32
5872 : AMDGPU::G_AMDGPU_MAD_U64_U32) ||
5873 (IsSigned &&
Mul->getOpcode() == AMDGPU::G_AMDGPU_MAD_U64_U32 &&
5874 VT->signBitIsZero(
Mul->getOperand(2).getReg()))) &&
5887bool AMDGPUInstructionSelector::selectSmrdOffset(
MachineOperand &Root,
5891 bool *ScaleOffset)
const {
5898 getAddrModeInfo(*
MI, *MRI, AddrInfo);
5900 if (AddrInfo.
empty())
5903 const GEPInfo &GEPI = AddrInfo[0];
5904 std::optional<int64_t> EncodedImm;
5907 *ScaleOffset =
false;
5912 if (GEPI.SgprParts.size() == 1 && GEPI.Imm != 0 && EncodedImm &&
5913 AddrInfo.
size() > 1) {
5914 const GEPInfo &GEPI2 = AddrInfo[1];
5915 if (GEPI2.SgprParts.size() == 2 && GEPI2.Imm == 0) {
5916 Register OffsetReg = GEPI2.SgprParts[1];
5919 selectScaleOffset(Root, OffsetReg,
false );
5920 OffsetReg = matchZeroExtendFromS32OrS32(OffsetReg);
5922 Base = GEPI2.SgprParts[0];
5923 *SOffset = OffsetReg;
5932 auto SKnown =
VT->getKnownBits(*SOffset);
5933 if (*
Offset + SKnown.getMinValue().getSExtValue() < 0)
5945 if (
Offset && GEPI.SgprParts.size() == 1 && EncodedImm) {
5946 Base = GEPI.SgprParts[0];
5952 if (SOffset && GEPI.SgprParts.size() == 1 &&
isUInt<32>(GEPI.Imm) &&
5958 Base = GEPI.SgprParts[0];
5959 *SOffset = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
5960 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), *SOffset)
5965 if (SOffset && GEPI.SgprParts.size() && GEPI.Imm == 0) {
5966 Register OffsetReg = GEPI.SgprParts[1];
5968 *ScaleOffset = selectScaleOffset(Root, OffsetReg,
false );
5969 OffsetReg = matchZeroExtendFromS32OrS32(OffsetReg);
5971 Base = GEPI.SgprParts[0];
5972 *SOffset = OffsetReg;
5981AMDGPUInstructionSelector::selectSmrdImm(
MachineOperand &Root)
const {
5984 if (!selectSmrdOffset(Root,
Base,
nullptr, &
Offset,
5986 return std::nullopt;
5988 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
5989 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Offset); }}};
5993AMDGPUInstructionSelector::selectSmrdImm32(
MachineOperand &Root)
const {
5995 getAddrModeInfo(*Root.
getParent(), *MRI, AddrInfo);
5997 if (AddrInfo.
empty() || AddrInfo[0].SgprParts.size() != 1)
5998 return std::nullopt;
6000 const GEPInfo &GEPInfo = AddrInfo[0];
6001 Register PtrReg = GEPInfo.SgprParts[0];
6002 std::optional<int64_t> EncodedImm =
6005 return std::nullopt;
6008 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrReg); },
6009 [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); }
6014AMDGPUInstructionSelector::selectSmrdSgpr(
MachineOperand &Root)
const {
6017 if (!selectSmrdOffset(Root,
Base, &SOffset,
nullptr,
6019 return std::nullopt;
6022 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
6023 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
6024 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }}};
6028AMDGPUInstructionSelector::selectSmrdSgprImm(
MachineOperand &Root)
const {
6032 if (!selectSmrdOffset(Root,
Base, &SOffset, &
Offset, &ScaleOffset))
6033 return std::nullopt;
6036 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
6037 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
6039 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }}};
6042std::pair<Register, int> AMDGPUInstructionSelector::selectFlatOffsetImpl(
6048 if (!STI.hasFlatInstOffsets())
6052 int64_t ConstOffset;
6054 std::tie(PtrBase, ConstOffset, IsInBounds) =
6055 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
6061 if (ConstOffset == 0 ||
6063 !isFlatScratchBaseLegal(Root.
getReg())) ||
6067 unsigned AddrSpace = (*
MI->memoperands_begin())->getAddrSpace();
6068 if (!TII.isLegalFLATOffset(ConstOffset, AddrSpace, FlatVariant))
6071 return std::pair(PtrBase, ConstOffset);
6075AMDGPUInstructionSelector::selectFlatOffset(
MachineOperand &Root)
const {
6079 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6080 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6085AMDGPUInstructionSelector::selectGlobalOffset(
MachineOperand &Root)
const {
6086 auto PtrWithOffset =
6090 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6091 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6096AMDGPUInstructionSelector::selectScratchOffset(
MachineOperand &Root)
const {
6097 auto PtrWithOffset =
6101 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6102 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6108AMDGPUInstructionSelector::selectGlobalSAddr(
MachineOperand &Root,
6110 bool NeedIOffset)
const {
6113 int64_t ConstOffset;
6114 int64_t ImmOffset = 0;
6118 std::tie(PtrBase, ConstOffset, std::ignore) =
6119 getPtrBaseWithConstantOffset(Addr, *MRI);
6121 if (ConstOffset != 0) {
6126 ImmOffset = ConstOffset;
6129 if (isSGPR(PtrBaseDef->Reg)) {
6130 if (ConstOffset > 0) {
6136 int64_t SplitImmOffset = 0, RemainderOffset = ConstOffset;
6138 std::tie(SplitImmOffset, RemainderOffset) =
6143 if (Subtarget->hasSignedGVSOffset() ?
isInt<32>(RemainderOffset)
6148 MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6150 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32),
6152 .
addImm(RemainderOffset);
6156 [=](MachineInstrBuilder &MIB) {
6159 [=](MachineInstrBuilder &MIB) {
6162 [=](MachineInstrBuilder &MIB) { MIB.
addImm(SplitImmOffset); },
6163 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); },
6166 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrBase); },
6167 [=](MachineInstrBuilder &MIB) {
6170 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); },
6180 unsigned NumLiterals =
6181 !TII.isInlineConstant(APInt(32,
Lo_32(ConstOffset))) +
6182 !TII.isInlineConstant(APInt(32,
Hi_32(ConstOffset)));
6183 if (STI.getConstantBusLimit(AMDGPU::V_ADD_U32_e64) > NumLiterals)
6184 return std::nullopt;
6191 if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
6196 if (isSGPR(SAddr)) {
6197 Register PtrBaseOffset = AddrDef->MI->getOperand(2).getReg();
6201 bool ScaleOffset = selectScaleOffset(Root, PtrBaseOffset,
6202 Subtarget->hasSignedGVSOffset());
6203 if (
Register VOffset = matchExtendFromS32OrS32(
6204 PtrBaseOffset, Subtarget->hasSignedGVSOffset())) {
6206 return {{[=](MachineInstrBuilder &MIB) {
6209 [=](MachineInstrBuilder &MIB) {
6212 [=](MachineInstrBuilder &MIB) {
6215 [=](MachineInstrBuilder &MIB) {
6219 return {{[=](MachineInstrBuilder &MIB) {
6222 [=](MachineInstrBuilder &MIB) {
6225 [=](MachineInstrBuilder &MIB) {
6235 if (AddrDef->MI->getOpcode() == AMDGPU::G_IMPLICIT_DEF ||
6236 AddrDef->MI->getOpcode() == AMDGPU::G_CONSTANT || !isSGPR(AddrDef->Reg))
6237 return std::nullopt;
6243 Register VOffset = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6245 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32), VOffset)
6250 [=](MachineInstrBuilder &MIB) { MIB.
addReg(AddrDef->Reg); },
6251 [=](MachineInstrBuilder &MIB) { MIB.
addReg(VOffset); },
6252 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6253 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); }
6256 [=](MachineInstrBuilder &MIB) { MIB.
addReg(AddrDef->Reg); },
6257 [=](MachineInstrBuilder &MIB) { MIB.
addReg(VOffset); },
6258 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); }
6263AMDGPUInstructionSelector::selectGlobalSAddr(
MachineOperand &Root)
const {
6264 return selectGlobalSAddr(Root, 0);
6268AMDGPUInstructionSelector::selectGlobalSAddrCPol(
MachineOperand &Root)
const {
6274 return selectGlobalSAddr(Root, PassedCPol);
6278AMDGPUInstructionSelector::selectGlobalSAddrCPolM0(
MachineOperand &Root)
const {
6284 return selectGlobalSAddr(Root, PassedCPol);
6288AMDGPUInstructionSelector::selectGlobalSAddrGLC(
MachineOperand &Root)
const {
6293AMDGPUInstructionSelector::selectGlobalSAddrNoIOffset(
6300 return selectGlobalSAddr(Root, PassedCPol,
false);
6304AMDGPUInstructionSelector::selectGlobalSAddrNoIOffsetM0(
6311 return selectGlobalSAddr(Root, PassedCPol,
false);
6315AMDGPUInstructionSelector::selectScratchSAddr(
MachineOperand &Root)
const {
6318 int64_t ConstOffset;
6319 int64_t ImmOffset = 0;
6323 std::tie(PtrBase, ConstOffset, std::ignore) =
6324 getPtrBaseWithConstantOffset(Addr, *MRI);
6326 if (ConstOffset != 0 && isFlatScratchBaseLegal(Addr) &&
6330 ImmOffset = ConstOffset;
6334 if (AddrDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX) {
6335 int FI = AddrDef->MI->getOperand(1).
getIndex();
6338 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); }
6344 if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
6345 Register LHS = AddrDef->MI->getOperand(1).getReg();
6346 Register RHS = AddrDef->MI->getOperand(2).getReg();
6350 if (LHSDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX &&
6351 isSGPR(RHSDef->Reg)) {
6352 int FI = LHSDef->MI->getOperand(1).getIndex();
6356 SAddr = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
6358 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_ADD_I32), SAddr)
6366 return std::nullopt;
6369 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SAddr); },
6370 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); }
6375bool AMDGPUInstructionSelector::checkFlatScratchSVSSwizzleBug(
6377 if (!Subtarget->hasFlatScratchSVSSwizzleBug())
6383 auto VKnown =
VT->getKnownBits(VAddr);
6386 uint64_t VMax = VKnown.getMaxValue().getZExtValue();
6388 return (VMax & 3) + (
SMax & 3) >= 4;
6392AMDGPUInstructionSelector::selectScratchSVAddr(
MachineOperand &Root)
const {
6395 int64_t ConstOffset;
6396 int64_t ImmOffset = 0;
6400 std::tie(PtrBase, ConstOffset, std::ignore) =
6401 getPtrBaseWithConstantOffset(Addr, *MRI);
6404 if (ConstOffset != 0 &&
6408 ImmOffset = ConstOffset;
6412 if (AddrDef->MI->getOpcode() != AMDGPU::G_PTR_ADD)
6413 return std::nullopt;
6415 Register RHS = AddrDef->MI->getOperand(2).getReg();
6416 if (RBI.getRegBank(
RHS, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID)
6417 return std::nullopt;
6419 Register LHS = AddrDef->MI->getOperand(1).getReg();
6422 if (OrigAddr != Addr) {
6423 if (!isFlatScratchBaseLegalSVImm(OrigAddr))
6424 return std::nullopt;
6426 if (!isFlatScratchBaseLegalSV(OrigAddr))
6427 return std::nullopt;
6430 if (checkFlatScratchSVSSwizzleBug(
RHS,
LHS, ImmOffset))
6431 return std::nullopt;
6433 unsigned CPol = selectScaleOffset(Root,
RHS,
true )
6437 if (LHSDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX) {
6438 int FI = LHSDef->MI->getOperand(1).getIndex();
6440 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
RHS); },
6442 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6443 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }
6452 return std::nullopt;
6455 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
RHS); },
6456 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
LHS); },
6457 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6458 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }
6463AMDGPUInstructionSelector::selectMUBUFScratchOffen(
MachineOperand &Root)
const {
6467 const SIMachineFunctionInfo *
Info =
MF->getInfo<SIMachineFunctionInfo>();
6472 Register HighBits = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6477 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32),
6481 return {{[=](MachineInstrBuilder &MIB) {
6484 [=](MachineInstrBuilder &MIB) {
6487 [=](MachineInstrBuilder &MIB) {
6492 [=](MachineInstrBuilder &MIB) {
6501 std::optional<int> FI;
6505 int64_t ConstOffset;
6506 std::tie(PtrBase, ConstOffset, std::ignore) =
6507 getPtrBaseWithConstantOffset(VAddr, *MRI);
6509 if (ConstOffset != 0) {
6510 if (TII.isLegalMUBUFImmOffset(ConstOffset) &&
6511 (!STI.privateMemoryResourceIsRangeChecked() ||
6512 VT->signBitIsZero(PtrBase))) {
6523 return {{[=](MachineInstrBuilder &MIB) {
6526 [=](MachineInstrBuilder &MIB) {
6532 [=](MachineInstrBuilder &MIB) {
6537 [=](MachineInstrBuilder &MIB) {
6542bool AMDGPUInstructionSelector::isDSOffsetLegal(
Register Base,
6547 if (STI.hasUsableDSOffset() || STI.unsafeDSOffsetFoldingEnabled())
6552 return VT->signBitIsZero(
Base);
6555bool AMDGPUInstructionSelector::isDSOffset2Legal(
Register Base, int64_t Offset0,
6557 unsigned Size)
const {
6558 if (Offset0 %
Size != 0 || Offset1 %
Size != 0)
6563 if (STI.hasUsableDSOffset() || STI.unsafeDSOffsetFoldingEnabled())
6568 return VT->signBitIsZero(
Base);
6573 return Addr->
getOpcode() == TargetOpcode::G_OR ||
6574 (Addr->
getOpcode() == TargetOpcode::G_PTR_ADD &&
6581bool AMDGPUInstructionSelector::isFlatScratchBaseLegal(
Register Addr)
const {
6589 if (STI.hasSignedScratchOffsets())
6595 if (AddrMI->
getOpcode() == TargetOpcode::G_PTR_ADD) {
6596 std::optional<ValueAndVReg> RhsValReg =
6602 if (RhsValReg && RhsValReg->Value.getSExtValue() < 0 &&
6603 RhsValReg->Value.getSExtValue() > -0x40000000)
6607 return VT->signBitIsZero(
LHS);
6612bool AMDGPUInstructionSelector::isFlatScratchBaseLegalSV(
Register Addr)
const {
6620 if (STI.hasSignedScratchOffsets())
6625 return VT->signBitIsZero(
RHS) &&
VT->signBitIsZero(
LHS);
6630bool AMDGPUInstructionSelector::isFlatScratchBaseLegalSVImm(
6634 if (STI.hasSignedScratchOffsets())
6639 std::optional<DefinitionAndSourceRegister> BaseDef =
6641 std::optional<ValueAndVReg> RHSOffset =
6651 (RHSOffset->Value.getSExtValue() < 0 &&
6652 RHSOffset->Value.getSExtValue() > -0x40000000)))
6655 Register LHS = BaseDef->MI->getOperand(1).getReg();
6656 Register RHS = BaseDef->MI->getOperand(2).getReg();
6657 return VT->signBitIsZero(
RHS) &&
VT->signBitIsZero(
LHS);
6660bool AMDGPUInstructionSelector::isUnneededShiftMask(
const MachineInstr &
MI,
6661 unsigned ShAmtBits)
const {
6662 assert(
MI.getOpcode() == TargetOpcode::G_AND);
6664 std::optional<APInt>
RHS =
6669 if (
RHS->countr_one() >= ShAmtBits)
6672 const APInt &LHSKnownZeros =
VT->getKnownZeroes(
MI.getOperand(1).getReg());
6673 return (LHSKnownZeros | *
RHS).countr_one() >= ShAmtBits;
6677AMDGPUInstructionSelector::selectMUBUFScratchOffset(
6680 const SIMachineFunctionInfo *
Info =
MF->getInfo<SIMachineFunctionInfo>();
6682 std::optional<DefinitionAndSourceRegister>
Def =
6684 assert(Def &&
"this shouldn't be an optional result");
6689 [=](MachineInstrBuilder &MIB) {
6692 [=](MachineInstrBuilder &MIB) {
6695 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
6706 if (!TII.isLegalMUBUFImmOffset(
Offset))
6714 [=](MachineInstrBuilder &MIB) {
6717 [=](MachineInstrBuilder &MIB) {
6725 !TII.isLegalMUBUFImmOffset(
Offset))
6729 [=](MachineInstrBuilder &MIB) {
6732 [=](MachineInstrBuilder &MIB) {
6739std::pair<Register, unsigned>
6740AMDGPUInstructionSelector::selectDS1Addr1OffsetImpl(
6742 int64_t ConstAddr = 0;
6746 std::tie(PtrBase,
Offset, std::ignore) =
6747 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
6750 if (isDSOffsetLegal(PtrBase,
Offset)) {
6752 return std::pair(PtrBase,
Offset);
6761 return std::pair(Root.
getReg(), 0);
6765AMDGPUInstructionSelector::selectDS1Addr1Offset(
MachineOperand &Root)
const {
6768 std::tie(
Reg,
Offset) = selectDS1Addr1OffsetImpl(Root);
6770 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
6776AMDGPUInstructionSelector::selectDS64Bit4ByteAligned(
MachineOperand &Root)
const {
6777 return selectDSReadWrite2(Root, 4);
6781AMDGPUInstructionSelector::selectDS128Bit8ByteAligned(
MachineOperand &Root)
const {
6782 return selectDSReadWrite2(Root, 8);
6786AMDGPUInstructionSelector::selectDSReadWrite2(
MachineOperand &Root,
6787 unsigned Size)
const {
6792 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
6794 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Offset+1); }
6798std::pair<Register, unsigned>
6799AMDGPUInstructionSelector::selectDSReadWrite2Impl(
MachineOperand &Root,
6800 unsigned Size)
const {
6801 int64_t ConstAddr = 0;
6805 std::tie(PtrBase,
Offset, std::ignore) =
6806 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
6809 int64_t OffsetValue0 =
Offset;
6811 if (isDSOffset2Legal(PtrBase, OffsetValue0, OffsetValue1,
Size)) {
6813 return std::pair(PtrBase, OffsetValue0 /
Size);
6822 return std::pair(Root.
getReg(), 0);
6830std::tuple<Register, int64_t, bool>
6831AMDGPUInstructionSelector::getPtrBaseWithConstantOffset(
6834 if (RootI->
getOpcode() != TargetOpcode::G_PTR_ADD)
6835 return {Root, 0,
false};
6838 std::optional<ValueAndVReg> MaybeOffset =
6841 return {Root, 0,
false};
6861 B.buildInstr(AMDGPU::S_MOV_B32)
6864 B.buildInstr(AMDGPU::S_MOV_B32)
6871 B.buildInstr(AMDGPU::REG_SEQUENCE)
6874 .addImm(AMDGPU::sub0)
6876 .addImm(AMDGPU::sub1);
6881 B.buildInstr(AMDGPU::S_MOV_B64)
6886 B.buildInstr(AMDGPU::REG_SEQUENCE)
6889 .addImm(AMDGPU::sub0_sub1)
6891 .addImm(AMDGPU::sub2_sub3);
6898 uint64_t DefaultFormat =
TII.getDefaultRsrcDataFormat();
6907 uint64_t DefaultFormat =
TII.getDefaultRsrcDataFormat();
6914AMDGPUInstructionSelector::MUBUFAddressData
6915AMDGPUInstructionSelector::parseMUBUFAddress(
Register Src)
const {
6916 MUBUFAddressData
Data;
6922 std::tie(PtrBase,
Offset, std::ignore) =
6923 getPtrBaseWithConstantOffset(Src, *MRI);
6929 if (MachineInstr *InputAdd
6931 Data.N2 = InputAdd->getOperand(1).getReg();
6932 Data.N3 = InputAdd->getOperand(2).getReg();
6947bool AMDGPUInstructionSelector::shouldUseAddr64(MUBUFAddressData Addr)
const {
6953 const RegisterBank *N0Bank = RBI.getRegBank(Addr.N0, *MRI, TRI);
6954 return N0Bank->
getID() == AMDGPU::VGPRRegBankID;
6960void AMDGPUInstructionSelector::splitIllegalMUBUFOffset(
6962 if (TII.isLegalMUBUFImmOffset(ImmOffset))
6966 SOffset = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
6967 B.buildInstr(AMDGPU::S_MOV_B32)
6973bool AMDGPUInstructionSelector::selectMUBUFAddr64Impl(
6978 if (!STI.hasAddr64() || STI.useFlatForGlobal())
6981 MUBUFAddressData AddrData = parseMUBUFAddress(Root.
getReg());
6982 if (!shouldUseAddr64(AddrData))
6988 Offset = AddrData.Offset;
6994 if (RBI.getRegBank(N2, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
6996 if (RBI.getRegBank(N3, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
7009 }
else if (RBI.getRegBank(N0, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
7020 splitIllegalMUBUFOffset(
B, SOffset,
Offset);
7024bool AMDGPUInstructionSelector::selectMUBUFOffsetImpl(
7029 if (STI.useFlatForGlobal())
7032 MUBUFAddressData AddrData = parseMUBUFAddress(Root.
getReg());
7033 if (shouldUseAddr64(AddrData))
7039 Offset = AddrData.Offset;
7045 splitIllegalMUBUFOffset(
B, SOffset,
Offset);
7050AMDGPUInstructionSelector::selectMUBUFAddr64(
MachineOperand &Root)
const {
7056 if (!selectMUBUFAddr64Impl(Root, VAddr, RSrcReg, SOffset,
Offset))
7062 [=](MachineInstrBuilder &MIB) {
7065 [=](MachineInstrBuilder &MIB) {
7068 [=](MachineInstrBuilder &MIB) {
7071 else if (STI.hasRestrictedSOffset())
7072 MIB.
addReg(AMDGPU::SGPR_NULL);
7076 [=](MachineInstrBuilder &MIB) {
7086AMDGPUInstructionSelector::selectMUBUFOffset(
MachineOperand &Root)
const {
7091 if (!selectMUBUFOffsetImpl(Root, RSrcReg, SOffset,
Offset))
7095 [=](MachineInstrBuilder &MIB) {
7098 [=](MachineInstrBuilder &MIB) {
7101 else if (STI.hasRestrictedSOffset())
7102 MIB.
addReg(AMDGPU::SGPR_NULL);
7114AMDGPUInstructionSelector::selectBUFSOffset(
MachineOperand &Root)
const {
7119 SOffset = AMDGPU::SGPR_NULL;
7121 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); }}};
7125static std::optional<uint64_t>
7129 if (!OffsetVal || !
isInt<32>(*OffsetVal))
7130 return std::nullopt;
7131 return Lo_32(*OffsetVal);
7135AMDGPUInstructionSelector::selectSMRDBufferImm(
MachineOperand &Root)
const {
7136 std::optional<uint64_t> OffsetVal =
7141 std::optional<int64_t> EncodedImm =
7146 return {{ [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); } }};
7150AMDGPUInstructionSelector::selectSMRDBufferImm32(
MachineOperand &Root)
const {
7157 std::optional<int64_t> EncodedImm =
7162 return {{ [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); } }};
7166AMDGPUInstructionSelector::selectSMRDBufferSgprImm(
MachineOperand &Root)
const {
7174 return std::nullopt;
7176 std::optional<int64_t> EncodedOffset =
7179 return std::nullopt;
7181 assert(MRI->getType(SOffset).getSizeInBits() == 32);
7182 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
7183 [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedOffset); }}};
7186std::pair<Register, unsigned>
7187AMDGPUInstructionSelector::selectVOP3PMadMixModsImpl(
MachineOperand &Root,
7188 bool &Matched)
const {
7193 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
7203 const auto CheckAbsNeg = [&]() {
7208 std::tie(Src, ModsTmp) = selectVOP3ModsImpl(Src);
7239AMDGPUInstructionSelector::selectVOP3PMadMixModsExt(
7244 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7249 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
7250 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
7255AMDGPUInstructionSelector::selectVOP3PMadMixMods(
MachineOperand &Root)
const {
7259 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7262 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
7263 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
7268AMDGPUInstructionSelector::selectVOP3PMadMixModsExtNeg(
7273 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7278 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
7279 [=](MachineInstrBuilder &MIB) {
7286AMDGPUInstructionSelector::selectVOP3PMadMixModsNeg(
7291 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7294 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
7295 [=](MachineInstrBuilder &MIB) {
7301bool AMDGPUInstructionSelector::selectSBarrierSignalIsfirst(
7305 Register CCReg =
I.getOperand(0).getReg();
7310 BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM))
7311 .
addImm(
I.getOperand(2).getImm());
7315 I.eraseFromParent();
7316 return RBI.constrainGenericRegister(CCReg, AMDGPU::SReg_32_XM0_XEXECRegClass,
7320bool AMDGPUInstructionSelector::selectSGetBarrierState(
7324 const MachineOperand &BarOp =
I.getOperand(2);
7325 std::optional<int64_t> BarValImm =
7329 auto CopyMIB =
BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
7333 MachineInstrBuilder MIB;
7334 unsigned Opc = BarValImm ? AMDGPU::S_GET_BARRIER_STATE_IMM
7335 : AMDGPU::S_GET_BARRIER_STATE_M0;
7338 auto DstReg =
I.getOperand(0).getReg();
7340 TRI.getConstrainedRegClassForOperand(
I.getOperand(0), *MRI);
7341 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
7347 I.eraseFromParent();
7352 if (HasInlineConst) {
7356 case Intrinsic::amdgcn_s_barrier_join:
7357 return AMDGPU::S_BARRIER_JOIN_IMM;
7358 case Intrinsic::amdgcn_s_wakeup_barrier:
7359 return AMDGPU::S_WAKEUP_BARRIER_IMM;
7360 case Intrinsic::amdgcn_s_get_named_barrier_state:
7361 return AMDGPU::S_GET_BARRIER_STATE_IMM;
7367 case Intrinsic::amdgcn_s_barrier_join:
7368 return AMDGPU::S_BARRIER_JOIN_M0;
7369 case Intrinsic::amdgcn_s_wakeup_barrier:
7370 return AMDGPU::S_WAKEUP_BARRIER_M0;
7371 case Intrinsic::amdgcn_s_get_named_barrier_state:
7372 return AMDGPU::S_GET_BARRIER_STATE_M0;
7377bool AMDGPUInstructionSelector::selectNamedBarrierInit(
7381 const MachineOperand &BarOp =
I.getOperand(1);
7382 const MachineOperand &CntOp =
I.getOperand(2);
7386 if (IntrID == Intrinsic::amdgcn_s_barrier_signal_var) {
7387 std::optional<int64_t> CntImm =
7389 if (CntImm && *CntImm == 0) {
7390 std::optional<int64_t> BarValImm =
7393 auto BarID = ((*BarValImm) >> 4) & 0x3F;
7394 BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::S_BARRIER_SIGNAL_IMM))
7396 I.eraseFromParent();
7403 Register TmpReg0 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7409 Register TmpReg1 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7416 Register TmpReg2 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7422 Register TmpReg3 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7423 constexpr unsigned ShAmt = 16;
7429 Register TmpReg4 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7439 unsigned Opc = IntrID == Intrinsic::amdgcn_s_barrier_init
7440 ? AMDGPU::S_BARRIER_INIT_M0
7441 : AMDGPU::S_BARRIER_SIGNAL_M0;
7442 MachineInstrBuilder MIB;
7445 I.eraseFromParent();
7449bool AMDGPUInstructionSelector::selectNamedBarrierInst(
7453 MachineOperand BarOp = IntrID == Intrinsic::amdgcn_s_get_named_barrier_state
7456 std::optional<int64_t> BarValImm =
7461 Register TmpReg0 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7467 Register TmpReg1 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7473 auto CopyMIB =
BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
7478 MachineInstrBuilder MIB;
7482 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state) {
7483 auto DstReg =
I.getOperand(0).getReg();
7485 TRI.getConstrainedRegClassForOperand(
I.getOperand(0), *MRI);
7486 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
7492 auto BarId = ((*BarValImm) >> 4) & 0x3F;
7496 I.eraseFromParent();
7503 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
7504 "Expected G_CONSTANT");
7505 MIB.
addImm(
MI.getOperand(1).getCImm()->getSExtValue());
7511 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
7512 "Expected G_CONSTANT");
7513 MIB.
addImm(-
MI.getOperand(1).getCImm()->getSExtValue());
7519 const MachineOperand &
Op =
MI.getOperand(1);
7520 assert(
MI.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1);
7521 MIB.
addImm(
Op.getFPImm()->getValueAPF().bitcastToAPInt().getZExtValue());
7524void AMDGPUInstructionSelector::renderCountTrailingOnesImm(
7526 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
7527 "Expected G_CONSTANT");
7528 MIB.
addImm(
MI.getOperand(1).getCImm()->getValue().countTrailingOnes());
7536 const MachineOperand &
Op =
MI.getOperand(OpIdx);
7547 MIB.
addImm(
MI.getOperand(OpIdx).getImm() != 0);
7553 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7557void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_0_0(
7559 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7564void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_0_1(
7566 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7567 MIB.
addImm((
MI.getOperand(OpIdx).getImm() & 0x1)
7572void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_1_0(
7574 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7579void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_1_1(
7581 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7582 MIB.
addImm((
MI.getOperand(OpIdx).getImm() & 0x2)
7587void AMDGPUInstructionSelector::renderDstSelToOpSelXForm(
7589 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7594void AMDGPUInstructionSelector::renderSrcSelToOpSelXForm(
7596 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7601void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_2_0(
7603 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7608void AMDGPUInstructionSelector::renderDstSelToOpSel3XFormXForm(
7610 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7611 MIB.
addImm((
MI.getOperand(OpIdx).getImm() & 0x2)
7619 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7620 MIB.
addImm(
MI.getOperand(OpIdx).getImm() &
7628 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7629 const bool Swizzle =
MI.getOperand(OpIdx).getImm() &
7635void AMDGPUInstructionSelector::renderExtractCpolSetGLC(
7637 assert(OpIdx >= 0 &&
"expected to match an immediate operand");
7638 const uint32_t Cpol =
MI.getOperand(OpIdx).getImm() &
7647 const APFloat &APF =
MI.getOperand(1).getFPImm()->getValueAPF();
7649 assert(ExpVal != INT_MIN);
7660 MIB.
addImm((
MI.getOperand(OpIdx).getImm() + 3) % 4);
7667 if (
MI.getOperand(OpIdx).getImm())
7669 MIB.
addImm((int64_t)Mods);
7676 if (
MI.getOperand(OpIdx).getImm())
7678 MIB.
addImm((int64_t)Mods);
7684 unsigned Val =
MI.getOperand(OpIdx).getImm();
7692 MIB.
addImm((int64_t)Mods);
7698 uint32_t
V =
MI.getOperand(2).getImm();
7701 if (!Subtarget->hasSafeCUPrefetch())
7707void AMDGPUInstructionSelector::renderScaledMAIIntrinsicOperand(
7709 unsigned Val =
MI.getOperand(OpIdx).getImm();
7718bool AMDGPUInstructionSelector::isInlineImmediate(
const APInt &
Imm)
const {
7719 return TII.isInlineConstant(
Imm);
7722bool AMDGPUInstructionSelector::isInlineImmediate(
const APFloat &
Imm)
const {
7723 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)
bool isFPPredicate() const
bool isIntPredicate() const
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.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
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.