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);
89 return MRI.getVRegDef(
Reg)->getOpcode() != AMDGPU::G_TRUNC &&
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;
682 MachineBasicBlock *BB =
MI.getParent();
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 {
775 MachineBasicBlock *BB =
MI.getParent();
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 {
808 MachineBasicBlock *BB =
MI.getParent();
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 {
865 MachineBasicBlock *BB =
MI.getParent();
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;
948 MachineBasicBlock *BB =
MI.getParent();
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");
1083 MachineBasicBlock *
MBB =
MI.getParent();
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);
1117 MachineBasicBlock *
MBB =
MI.getParent();
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)
1151 MachineBasicBlock *
MBB =
MI.getParent();
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;
1217 MachineBasicBlock *
MBB =
MI.getParent();
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 {
1884 MachineBasicBlock *BB =
MI.getParent();
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(
1898 MachineBasicBlock *
MBB =
MI.getParent();
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)
2006 MachineBasicBlock *
MBB =
MI.getParent();
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();
2126 MachineBasicBlock *
MBB =
MI.getParent();
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 {
2145 MachineFunction *
MF =
MI.getMF();
2146 SIMachineFunctionInfo *MFInfo =
MF->getInfo<SIMachineFunctionInfo>();
2157 TFE = TexFailCtrl & 0x1;
2159 LWE = TexFailCtrl & 0x2;
2162 return TexFailCtrl == 0;
2165bool AMDGPUInstructionSelector::selectImageIntrinsic(
2167 MachineBasicBlock *
MBB =
MI.getParent();
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(
2427 MachineBasicBlock *
MBB =
MI.getParent();
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);
2924 if (Unmerge->getNumDefs() == 2 && Unmerge->getOperand(1).getReg() == In &&
2926 Out = Unmerge->getSourceReg();
2946 if (Shuffle->
getOpcode() != AMDGPU::G_SHUFFLE_VECTOR)
2953 assert(Mask.size() == 2);
2955 if (Mask[0] == 1 && Mask[1] <= 1) {
2963bool AMDGPUInstructionSelector::selectG_FPEXT(
MachineInstr &
I)
const {
2964 if (!Subtarget->hasSALUFloatInsts())
2967 Register Dst =
I.getOperand(0).getReg();
2968 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
2969 if (DstRB->
getID() != AMDGPU::SGPRRegBankID)
2972 Register Src =
I.getOperand(1).getReg();
2978 BuildMI(*BB, &
I,
I.getDebugLoc(), TII.get(AMDGPU::S_CVT_HI_F32_F16), Dst)
2980 I.eraseFromParent();
2981 return RBI.constrainGenericRegister(Dst, AMDGPU::SReg_32RegClass, *MRI);
2988bool AMDGPUInstructionSelector::selectG_FNEG(
MachineInstr &
MI)
const {
3001 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
3002 if (DstRB->
getID() != AMDGPU::SGPRRegBankID ||
3007 MachineInstr *Fabs =
getOpcodeDef(TargetOpcode::G_FABS, Src, *MRI);
3011 if (!RBI.constrainGenericRegister(Src, AMDGPU::SReg_64RegClass, *MRI) ||
3012 !RBI.constrainGenericRegister(Dst, AMDGPU::SReg_64RegClass, *MRI))
3015 MachineBasicBlock *BB =
MI.getParent();
3017 Register LoReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3018 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3019 Register ConstReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3020 Register OpReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3022 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), LoReg)
3023 .
addReg(Src, {}, AMDGPU::sub0);
3024 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), HiReg)
3025 .
addReg(Src, {}, AMDGPU::sub1);
3026 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_MOV_B32), ConstReg)
3030 unsigned Opc = Fabs ? AMDGPU::S_OR_B32 : AMDGPU::S_XOR_B32;
3035 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::REG_SEQUENCE), Dst)
3040 MI.eraseFromParent();
3045bool AMDGPUInstructionSelector::selectG_FABS(
MachineInstr &
MI)
const {
3047 const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
3048 if (DstRB->
getID() != AMDGPU::SGPRRegBankID ||
3053 MachineBasicBlock *BB =
MI.getParent();
3055 Register LoReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3056 Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3057 Register ConstReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3058 Register OpReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
3060 if (!RBI.constrainGenericRegister(Src, AMDGPU::SReg_64RegClass, *MRI) ||
3061 !RBI.constrainGenericRegister(Dst, AMDGPU::SReg_64RegClass, *MRI))
3064 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), LoReg)
3065 .
addReg(Src, {}, AMDGPU::sub0);
3066 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), HiReg)
3067 .
addReg(Src, {}, AMDGPU::sub1);
3068 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_MOV_B32), ConstReg)
3073 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::S_AND_B32), OpReg)
3077 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::REG_SEQUENCE), Dst)
3083 MI.eraseFromParent();
3088 return MI.getOpcode() == TargetOpcode::G_CONSTANT;
3094 unsigned OpNo =
Load.getOpcode() == AMDGPU::G_PREFETCH ? 0 : 1;
3095 const MachineInstr *PtrMI =
3096 MRI.getUniqueVRegDef(
Load.getOperand(OpNo).getReg());
3100 if (PtrMI->
getOpcode() != TargetOpcode::G_PTR_ADD)
3105 for (
unsigned i = 1; i != 3; ++i) {
3106 const MachineOperand &GEPOp = PtrMI->
getOperand(i);
3107 const MachineInstr *OpDef = MRI.getUniqueVRegDef(GEPOp.
getReg());
3112 assert(GEPInfo.Imm == 0);
3116 const RegisterBank *OpBank = RBI.getRegBank(GEPOp.
getReg(), MRI, TRI);
3117 if (OpBank->
getID() == AMDGPU::SGPRRegBankID)
3118 GEPInfo.SgprParts.push_back(GEPOp.
getReg());
3120 GEPInfo.VgprParts.push_back(GEPOp.
getReg());
3124 getAddrModeInfo(*PtrMI, MRI, AddrInfo);
3127bool AMDGPUInstructionSelector::isSGPR(
Register Reg)
const {
3128 return RBI.getRegBank(
Reg, *MRI, TRI)->getID() == AMDGPU::SGPRRegBankID;
3131bool AMDGPUInstructionSelector::isInstrUniform(
const MachineInstr &
MI)
const {
3132 if (!
MI.hasOneMemOperand())
3135 const MachineMemOperand *MMO = *
MI.memoperands_begin();
3148 if (
MI.getOpcode() == AMDGPU::G_PREFETCH)
3149 return RBI.getRegBank(
MI.getOperand(0).getReg(), *MRI, TRI)->getID() ==
3150 AMDGPU::SGPRRegBankID;
3153 return I &&
I->getMetadata(
"amdgpu.uniform");
3157 for (
const GEPInfo &GEPInfo : AddrInfo) {
3158 if (!GEPInfo.VgprParts.empty())
3164void AMDGPUInstructionSelector::initM0(
MachineInstr &
I)
const {
3165 const LLT PtrTy = MRI->getType(
I.getOperand(1).getReg());
3168 STI.ldsRequiresM0Init()) {
3172 BuildMI(*BB, &
I,
I.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), AMDGPU::M0)
3177bool AMDGPUInstructionSelector::selectG_LOAD_STORE_ATOMICRMW(
3184 if (
Reg.isPhysical())
3188 const unsigned Opcode =
MI.getOpcode();
3190 if (Opcode == AMDGPU::COPY)
3193 if (Opcode == AMDGPU::G_AND || Opcode == AMDGPU::G_OR ||
3194 Opcode == AMDGPU::G_XOR)
3199 return GI->is(Intrinsic::amdgcn_class);
3201 return Opcode == AMDGPU::G_ICMP || Opcode == AMDGPU::G_FCMP;
3204bool AMDGPUInstructionSelector::selectG_BRCOND(
MachineInstr &
I)
const {
3206 MachineOperand &CondOp =
I.getOperand(0);
3219 if (!isVCC(CondReg, *MRI)) {
3223 CondPhysReg = AMDGPU::SCC;
3224 BrOpcode = AMDGPU::S_CBRANCH_SCC1;
3225 ConstrainRC = &AMDGPU::SReg_32RegClass;
3232 const bool Is64 = STI.isWave64();
3233 const unsigned Opcode = Is64 ? AMDGPU::S_AND_B64 : AMDGPU::S_AND_B32;
3234 const Register Exec = Is64 ? AMDGPU::EXEC : AMDGPU::EXEC_LO;
3236 Register TmpReg = MRI->createVirtualRegister(TRI.getBoolRC());
3237 BuildMI(*BB, &
I,
DL, TII.get(Opcode), TmpReg)
3244 CondPhysReg = TRI.getVCC();
3245 BrOpcode = AMDGPU::S_CBRANCH_VCCNZ;
3246 ConstrainRC = TRI.getBoolRC();
3249 if (!MRI->getRegClassOrNull(CondReg))
3250 MRI->setRegClass(CondReg, ConstrainRC);
3252 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), CondPhysReg)
3255 .
addMBB(
I.getOperand(1).getMBB());
3257 I.eraseFromParent();
3261bool AMDGPUInstructionSelector::selectG_GLOBAL_VALUE(
3263 Register DstReg =
I.getOperand(0).getReg();
3264 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3265 const bool IsVGPR = DstRB->
getID() == AMDGPU::VGPRRegBankID;
3266 I.setDesc(TII.get(IsVGPR ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32));
3270 return RBI.constrainGenericRegister(
3271 DstReg, IsVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass, *MRI);
3274bool AMDGPUInstructionSelector::selectG_PTRMASK(
MachineInstr &
I)
const {
3275 Register DstReg =
I.getOperand(0).getReg();
3276 Register SrcReg =
I.getOperand(1).getReg();
3277 Register MaskReg =
I.getOperand(2).getReg();
3278 LLT Ty = MRI->getType(DstReg);
3279 LLT MaskTy = MRI->getType(MaskReg);
3283 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3284 const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
3285 const RegisterBank *MaskRB = RBI.getRegBank(MaskReg, *MRI, TRI);
3286 const bool IsVGPR = DstRB->
getID() == AMDGPU::VGPRRegBankID;
3292 APInt MaskOnes =
VT->getKnownOnes(MaskReg).zext(64);
3296 const bool CanCopyLow32 = (MaskOnes & MaskLo32) == MaskLo32;
3297 const bool CanCopyHi32 = (MaskOnes & MaskHi32) == MaskHi32;
3300 !CanCopyLow32 && !CanCopyHi32) {
3301 auto MIB =
BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_AND_B64), DstReg)
3305 I.eraseFromParent();
3310 unsigned NewOpc = IsVGPR ? AMDGPU::V_AND_B32_e64 : AMDGPU::S_AND_B32;
3312 = IsVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
3317 TRI.getRegClassForTypeOnBank(MaskTy, *MaskRB);
3319 if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
3320 !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
3321 !RBI.constrainGenericRegister(MaskReg, *MaskRC, *MRI))
3326 "ptrmask should have been narrowed during legalize");
3328 auto NewOp =
BuildMI(*BB, &
I,
DL, TII.get(NewOpc), DstReg)
3334 I.eraseFromParent();
3338 Register HiReg = MRI->createVirtualRegister(&RegRC);
3339 Register LoReg = MRI->createVirtualRegister(&RegRC);
3342 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), LoReg)
3343 .
addReg(SrcReg, {}, AMDGPU::sub0);
3344 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), HiReg)
3345 .
addReg(SrcReg, {}, AMDGPU::sub1);
3354 Register MaskLo = MRI->createVirtualRegister(&RegRC);
3355 MaskedLo = MRI->createVirtualRegister(&RegRC);
3357 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), MaskLo)
3358 .
addReg(MaskReg, {}, AMDGPU::sub0);
3359 BuildMI(*BB, &
I,
DL, TII.get(NewOpc), MaskedLo)
3368 Register MaskHi = MRI->createVirtualRegister(&RegRC);
3369 MaskedHi = MRI->createVirtualRegister(&RegRC);
3371 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::COPY), MaskHi)
3372 .
addReg(MaskReg, {}, AMDGPU::sub1);
3373 BuildMI(*BB, &
I,
DL, TII.get(NewOpc), MaskedHi)
3378 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
3383 I.eraseFromParent();
3389static std::pair<Register, unsigned>
3396 std::tie(IdxBaseReg,
Offset) =
3398 if (IdxBaseReg == AMDGPU::NoRegister) {
3402 IdxBaseReg = IdxReg;
3409 if (
static_cast<unsigned>(
Offset) >= SubRegs.
size())
3410 return std::pair(IdxReg, SubRegs[0]);
3411 return std::pair(IdxBaseReg, SubRegs[
Offset]);
3414bool AMDGPUInstructionSelector::selectG_EXTRACT_VECTOR_ELT(
3420 LLT DstTy = MRI->getType(DstReg);
3421 LLT SrcTy = MRI->getType(SrcReg);
3423 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
3424 const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
3425 const RegisterBank *IdxRB = RBI.getRegBank(IdxReg, *MRI, TRI);
3429 if (IdxRB->
getID() != AMDGPU::SGPRRegBankID)
3433 TRI.getRegClassForTypeOnBank(SrcTy, *SrcRB);
3435 TRI.getRegClassForTypeOnBank(DstTy, *DstRB);
3436 if (!SrcRC || !DstRC)
3438 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
3439 !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
3440 !RBI.constrainGenericRegister(IdxReg, AMDGPU::SReg_32RegClass, *MRI))
3443 MachineBasicBlock *BB =
MI.getParent();
3451 if (SrcRB->
getID() == AMDGPU::SGPRRegBankID) {
3455 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3458 unsigned Opc = Is64 ? AMDGPU::S_MOVRELS_B64 : AMDGPU::S_MOVRELS_B32;
3460 .
addReg(SrcReg, {}, SubReg)
3462 MI.eraseFromParent();
3469 if (!STI.useVGPRIndexMode()) {
3470 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3472 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::V_MOVRELS_B32_e32), DstReg)
3473 .
addReg(SrcReg, {}, SubReg)
3475 MI.eraseFromParent();
3479 const MCInstrDesc &GPRIDXDesc =
3480 TII.getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*SrcRC),
true);
3486 MI.eraseFromParent();
3491bool AMDGPUInstructionSelector::selectG_INSERT_VECTOR_ELT(
3498 LLT VecTy = MRI->getType(DstReg);
3499 LLT ValTy = MRI->getType(ValReg);
3503 const RegisterBank *VecRB = RBI.getRegBank(VecReg, *MRI, TRI);
3504 const RegisterBank *ValRB = RBI.getRegBank(ValReg, *MRI, TRI);
3505 const RegisterBank *IdxRB = RBI.getRegBank(IdxReg, *MRI, TRI);
3511 if (IdxRB->
getID() != AMDGPU::SGPRRegBankID)
3515 TRI.getRegClassForTypeOnBank(VecTy, *VecRB);
3517 TRI.getRegClassForTypeOnBank(ValTy, *ValRB);
3519 if (!RBI.constrainGenericRegister(VecReg, *VecRC, *MRI) ||
3520 !RBI.constrainGenericRegister(DstReg, *VecRC, *MRI) ||
3521 !RBI.constrainGenericRegister(ValReg, *ValRC, *MRI) ||
3522 !RBI.constrainGenericRegister(IdxReg, AMDGPU::SReg_32RegClass, *MRI))
3525 if (VecRB->
getID() == AMDGPU::VGPRRegBankID && ValSize != 32)
3529 std::tie(IdxReg, SubReg) =
3532 const bool IndexMode = VecRB->
getID() == AMDGPU::VGPRRegBankID &&
3533 STI.useVGPRIndexMode();
3535 MachineBasicBlock *BB =
MI.getParent();
3539 BuildMI(*BB, &
MI,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
3542 const MCInstrDesc &RegWriteOp = TII.getIndirectRegWriteMovRelPseudo(
3543 VecSize, ValSize, VecRB->
getID() == AMDGPU::SGPRRegBankID);
3548 MI.eraseFromParent();
3552 const MCInstrDesc &GPRIDXDesc =
3553 TII.getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC),
false);
3560 MI.eraseFromParent();
3566 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
3567 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
3568 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
3569 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
3570 case Intrinsic::amdgcn_load_async_to_lds:
3571 case Intrinsic::amdgcn_global_load_async_lds:
3577bool AMDGPUInstructionSelector::selectBufferLoadLds(
MachineInstr &
MI)
const {
3578 if (!Subtarget->hasVMemToLDSLoad())
3581 unsigned Size =
MI.getOperand(3).getImm();
3585 const bool HasVIndex =
MI.getNumOperands() == 9;
3589 VIndex =
MI.getOperand(4).getReg();
3593 Register VOffset =
MI.getOperand(4 + OpOffset).getReg();
3594 std::optional<ValueAndVReg> MaybeVOffset =
3596 const bool HasVOffset = !MaybeVOffset || MaybeVOffset->Value.getZExtValue();
3602 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_BOTHEN
3603 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_IDXEN
3604 : HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFEN
3605 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFSET;
3608 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_BOTHEN
3609 : AMDGPU::BUFFER_LOAD_USHORT_LDS_IDXEN
3610 : HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFEN
3611 : AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFSET;
3614 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_BOTHEN
3615 : AMDGPU::BUFFER_LOAD_DWORD_LDS_IDXEN
3616 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFEN
3617 : AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFSET;
3620 if (!Subtarget->hasLDSLoadB96_B128())
3623 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_BOTHEN
3624 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_IDXEN
3625 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFEN
3626 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFSET;
3629 if (!Subtarget->hasLDSLoadB96_B128())
3632 Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_BOTHEN
3633 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_IDXEN
3634 : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFEN
3635 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFSET;
3639 MachineBasicBlock *
MBB =
MI.getParent();
3642 .
add(
MI.getOperand(2));
3646 if (HasVIndex && HasVOffset) {
3647 Register IdxReg = MRI->createVirtualRegister(TRI.getVGPR64Class());
3648 BuildMI(*
MBB, &*MIB,
DL, TII.get(AMDGPU::REG_SEQUENCE), IdxReg)
3655 }
else if (HasVIndex) {
3657 }
else if (HasVOffset) {
3661 MIB.
add(
MI.getOperand(1));
3662 MIB.
add(
MI.getOperand(5 + OpOffset));
3663 MIB.
add(
MI.getOperand(6 + OpOffset));
3665 unsigned Aux =
MI.getOperand(7 + OpOffset).getImm();
3674 MachineMemOperand *LoadMMO = *
MI.memoperands_begin();
3679 MachinePointerInfo StorePtrI = LoadPtrI;
3690 MachineMemOperand *StoreMMO =
3696 MI.eraseFromParent();
3709 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3715 return Def->getOperand(1).getReg();
3729 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3737 return Def->getOperand(1).getReg();
3739 if (
VT->signBitIsZero(
Reg))
3740 return matchZeroExtendFromS32(
Reg);
3748AMDGPUInstructionSelector::matchZeroExtendFromS32OrS32(
Register Reg)
const {
3750 : matchZeroExtendFromS32(
Reg);
3756AMDGPUInstructionSelector::matchSignExtendFromS32OrS32(
Register Reg)
const {
3758 : matchSignExtendFromS32(
Reg);
3762AMDGPUInstructionSelector::matchExtendFromS32OrS32(
Register Reg,
3763 bool IsSigned)
const {
3765 return matchSignExtendFromS32OrS32(
Reg);
3767 return matchZeroExtendFromS32OrS32(
Reg);
3777 if (
Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
3784 return Def->getOperand(1).getReg();
3789bool AMDGPUInstructionSelector::selectGlobalLoadLds(
MachineInstr &
MI)
const{
3790 if (!Subtarget->hasVMemToLDSLoad())
3794 unsigned Size =
MI.getOperand(3).getImm();
3801 Opc = AMDGPU::GLOBAL_LOAD_LDS_UBYTE;
3804 Opc = AMDGPU::GLOBAL_LOAD_LDS_USHORT;
3807 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORD;
3810 if (!Subtarget->hasLDSLoadB96_B128())
3812 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX3;
3815 if (!Subtarget->hasLDSLoadB96_B128())
3817 Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX4;
3821 MachineBasicBlock *
MBB =
MI.getParent();
3824 .
add(
MI.getOperand(2));
3830 if (!isSGPR(Addr)) {
3832 if (isSGPR(AddrDef->Reg)) {
3833 Addr = AddrDef->Reg;
3834 }
else if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
3837 if (isSGPR(SAddr)) {
3838 Register PtrBaseOffset = AddrDef->MI->getOperand(2).getReg();
3839 if (
Register Off = matchZeroExtendFromS32(PtrBaseOffset)) {
3850 VOffset = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
3862 MIB.
add(
MI.getOperand(4));
3864 unsigned Aux =
MI.getOperand(5).getImm();
3868 MachineMemOperand *LoadMMO = *
MI.memoperands_begin();
3870 LoadPtrI.
Offset =
MI.getOperand(4).getImm();
3871 MachinePointerInfo StorePtrI = LoadPtrI;
3880 MachineMemOperand *StoreMMO =
3882 sizeof(int32_t),
Align(4));
3886 MI.eraseFromParent();
3891bool AMDGPUInstructionSelector::selectTensorLoadStore(
MachineInstr &
MI,
3893 bool IsLoad = IID == Intrinsic::amdgcn_tensor_load_to_lds;
3895 IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d4 : AMDGPU::TENSOR_STORE_FROM_LDS_d4;
3899 const auto isAllZeros = [&](MachineOperand &Opnd) {
3900 const MachineInstr *
DefMI = MRI->getVRegDef(Opnd.getReg());
3909 Opc = IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d2
3910 : AMDGPU::TENSOR_STORE_FROM_LDS_d2;
3915 MachineBasicBlock *
MBB =
MI.getParent();
3917 .
add(
MI.getOperand(1))
3918 .
add(
MI.getOperand(2));
3920 if (NumGroups >= 4) {
3921 MIB.
add(
MI.getOperand(3))
3922 .
add(
MI.getOperand(4));
3926 .
add(
MI.getOperand(6));
3928 MI.eraseFromParent();
3932bool AMDGPUInstructionSelector::selectBVHIntersectRayIntrinsic(
3934 unsigned OpcodeOpIdx =
3935 MI.getOpcode() == AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY ? 1 : 3;
3936 MI.setDesc(TII.get(
MI.getOperand(OpcodeOpIdx).getImm()));
3937 MI.removeOperand(OpcodeOpIdx);
3938 MI.addImplicitDefUseOperands(*
MI.getMF());
3945bool AMDGPUInstructionSelector::selectSMFMACIntrin(
MachineInstr &
MI)
const {
3948 case Intrinsic::amdgcn_smfmac_f32_16x16x32_f16:
3949 Opc = AMDGPU::V_SMFMAC_F32_16X16X32_F16_e64;
3951 case Intrinsic::amdgcn_smfmac_f32_32x32x16_f16:
3952 Opc = AMDGPU::V_SMFMAC_F32_32X32X16_F16_e64;
3954 case Intrinsic::amdgcn_smfmac_f32_16x16x32_bf16:
3955 Opc = AMDGPU::V_SMFMAC_F32_16X16X32_BF16_e64;
3957 case Intrinsic::amdgcn_smfmac_f32_32x32x16_bf16:
3958 Opc = AMDGPU::V_SMFMAC_F32_32X32X16_BF16_e64;
3960 case Intrinsic::amdgcn_smfmac_i32_16x16x64_i8:
3961 Opc = AMDGPU::V_SMFMAC_I32_16X16X64_I8_e64;
3963 case Intrinsic::amdgcn_smfmac_i32_32x32x32_i8:
3964 Opc = AMDGPU::V_SMFMAC_I32_32X32X32_I8_e64;
3966 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_bf8:
3967 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF8_BF8_e64;
3969 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_fp8:
3970 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF8_FP8_e64;
3972 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_bf8:
3973 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_FP8_BF8_e64;
3975 case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_fp8:
3976 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_FP8_FP8_e64;
3978 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_bf8:
3979 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF8_BF8_e64;
3981 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_fp8:
3982 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF8_FP8_e64;
3984 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_bf8:
3985 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_FP8_BF8_e64;
3987 case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_fp8:
3988 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_FP8_FP8_e64;
3990 case Intrinsic::amdgcn_smfmac_f32_16x16x64_f16:
3991 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_F16_e64;
3993 case Intrinsic::amdgcn_smfmac_f32_32x32x32_f16:
3994 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_F16_e64;
3996 case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf16:
3997 Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF16_e64;
3999 case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf16:
4000 Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF16_e64;
4002 case Intrinsic::amdgcn_smfmac_i32_16x16x128_i8:
4003 Opc = AMDGPU::V_SMFMAC_I32_16X16X128_I8_e64;
4005 case Intrinsic::amdgcn_smfmac_i32_32x32x64_i8:
4006 Opc = AMDGPU::V_SMFMAC_I32_32X32X64_I8_e64;
4008 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_bf8:
4009 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_BF8_BF8_e64;
4011 case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_fp8:
4012 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_BF8_FP8_e64;
4014 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_bf8:
4015 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_FP8_BF8_e64;
4017 case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_fp8:
4018 Opc = AMDGPU::V_SMFMAC_F32_16X16X128_FP8_FP8_e64;
4020 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_bf8:
4021 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_BF8_BF8_e64;
4023 case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_fp8:
4024 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_BF8_FP8_e64;
4026 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_bf8:
4027 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_FP8_BF8_e64;
4029 case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_fp8:
4030 Opc = AMDGPU::V_SMFMAC_F32_32X32X64_FP8_FP8_e64;
4036 auto VDst_In =
MI.getOperand(4);
4038 MI.setDesc(TII.get(
Opc));
4039 MI.removeOperand(4);
4040 MI.removeOperand(1);
4041 MI.addOperand(VDst_In);
4042 MI.addImplicitDefUseOperands(*
MI.getMF());
4043 const MCInstrDesc &MCID =
MI.getDesc();
4045 MI.getOperand(0).setIsEarlyClobber(
true);
4050bool AMDGPUInstructionSelector::selectPermlaneSwapIntrin(
4052 if (IntrID == Intrinsic::amdgcn_permlane16_swap &&
4053 !Subtarget->hasPermlane16Swap())
4055 if (IntrID == Intrinsic::amdgcn_permlane32_swap &&
4056 !Subtarget->hasPermlane32Swap())
4059 unsigned Opcode = IntrID == Intrinsic::amdgcn_permlane16_swap
4060 ? AMDGPU::V_PERMLANE16_SWAP_B32_e64
4061 : AMDGPU::V_PERMLANE32_SWAP_B32_e64;
4063 MI.removeOperand(2);
4064 MI.setDesc(TII.get(Opcode));
4067 MachineOperand &FI =
MI.getOperand(4);
4074bool AMDGPUInstructionSelector::selectWaveAddress(
MachineInstr &
MI)
const {
4077 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4078 const bool IsVALU = DstRB->
getID() == AMDGPU::VGPRRegBankID;
4079 MachineBasicBlock *
MBB =
MI.getParent();
4083 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHRREV_B32_e64), DstReg)
4084 .
addImm(Subtarget->getWavefrontSizeLog2())
4089 .
addImm(Subtarget->getWavefrontSizeLog2())
4094 IsVALU ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
4095 if (!RBI.constrainGenericRegister(DstReg, RC, *MRI))
4098 MI.eraseFromParent();
4102bool AMDGPUInstructionSelector::selectWaveShuffleIntrin(
4105 MachineBasicBlock *
MBB =
MI.getParent();
4112 const LLT DstTy = MRI->getType(DstReg);
4114 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4116 TRI.getRegClassForSizeOnBank(DstSize, *DstRB);
4121 if (!Subtarget->supportsBPermute())
4125 if (Subtarget->supportsWaveWideBPermute()) {
4126 Register ShiftIdxReg = MRI->createVirtualRegister(DstRC);
4127 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), ShiftIdxReg)
4137 assert(Subtarget->isWave64());
4141 MRI->createVirtualRegister(TRI.getRegClass(AMDGPU::SReg_32RegClassID));
4142 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefValReg);
4144 Register UndefExecReg = MRI->createVirtualRegister(
4145 TRI.getRegClass(AMDGPU::SReg_64_XEXECRegClassID));
4146 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefExecReg);
4148 Register PoisonValReg = MRI->createVirtualRegister(DstRC);
4149 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_SET_INACTIVE_B32), PoisonValReg)
4157 Register ShiftIdxReg = MRI->createVirtualRegister(DstRC);
4158 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), ShiftIdxReg)
4162 Register PoisonIdxReg = MRI->createVirtualRegister(DstRC);
4163 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_SET_INACTIVE_B32), PoisonIdxReg)
4170 Register PoisonUnshiftedIdxReg = MRI->createVirtualRegister(DstRC);
4172 PoisonUnshiftedIdxReg)
4180 Register SameSidePermReg = MRI->createVirtualRegister(DstRC);
4181 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::DS_BPERMUTE_B32), SameSidePermReg)
4186 Register SwappedValReg = MRI->createVirtualRegister(DstRC);
4187 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_PERMLANE64_B32), SwappedValReg)
4190 Register OppSidePermReg = MRI->createVirtualRegister(DstRC);
4191 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::DS_BPERMUTE_B32), OppSidePermReg)
4196 Register WWMSwapPermReg = MRI->createVirtualRegister(DstRC);
4197 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::STRICT_WWM), WWMSwapPermReg)
4204 Register ThreadIDReg = MRI->createVirtualRegister(DstRC);
4205 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_MBCNT_LO_U32_B32_e64), ThreadIDReg)
4209 Register XORReg = MRI->createVirtualRegister(DstRC);
4212 .
addReg(PoisonUnshiftedIdxReg);
4214 Register ANDReg = MRI->createVirtualRegister(DstRC);
4219 Register CompareReg = MRI->createVirtualRegister(
4220 TRI.getRegClass(AMDGPU::SReg_64_XEXECRegClassID));
4221 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_CMP_EQ_U32_e64), CompareReg)
4226 BuildMI(*
MBB,
MI,
DL, TII.get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
4234 MI.eraseFromParent();
4243 unsigned NumOpcodes = 0;
4256 const uint8_t SrcBits[3] = { 0xf0, 0xcc, 0xaa };
4267 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4281 if (Src.size() == 3) {
4288 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4289 if (Src[
I] ==
LHS) {
4299 Bits = SrcBits[Src.size()];
4305 switch (
MI->getOpcode()) {
4306 case TargetOpcode::G_AND:
4307 case TargetOpcode::G_OR:
4308 case TargetOpcode::G_XOR: {
4313 if (!getOperandBits(
LHS, LHSBits) ||
4314 !getOperandBits(
RHS, RHSBits)) {
4315 Src = std::move(Backup);
4316 return std::make_pair(0, 0);
4337 uint8_t LHSBitsOrig = LHSBits;
4338 uint8_t RHSBitsOrig = RHSBits;
4342 NumOpcodes += LHSOp.first;
4343 LHSBits = LHSOp.second;
4350 NumOpcodes += RHSOp.first;
4351 RHSBits = RHSOp.second;
4355 auto dependsOnSlot = [](
uint8_t TT,
int Slot) ->
bool {
4356 if (Slot < 0 || Slot > 2)
4358 const uint8_t Masks[3] = {0x0f, 0x33, 0x55};
4359 const int Shifts[3] = {4, 2, 1};
4360 return ((TT ^ (TT >> Shifts[Slot])) & Masks[Slot]) != 0;
4366 const uint8_t SrcBitsConst[3] = {0xf0, 0xcc, 0xaa};
4373 for (
int I = 0;
I < (int)S.size();
I++) {
4374 if (Bits == SrcBitsConst[
I] && S[
I] ==
Op)
4376 if (IsNegationOp && Bits == (
uint8_t)~SrcBitsConst[
I] &&
4377 S[
I] == NegatedInner)
4388 for (
int I = 0;
I < (int)SrcAfterLHS.
size() &&
I < 3;
I++) {
4389 if (
I < (
int)Src.size() && Src[
I] != SrcAfterLHS[
I] &&
4390 dependsOnSlot(LHSBits,
I)) {
4399 if (!Stale && !RHSOp.first) {
4400 int Slot = findSlot(RHSBitsOrig,
RHS, SrcBeforeRecurse);
4402 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4408 if (!Stale && !LHSOp.first) {
4409 int Slot = findSlot(LHSBitsOrig,
LHS, SrcBeforeRecurse);
4411 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4416 Src = std::move(SrcBeforeRecurse);
4417 LHSBits = LHSBitsOrig;
4418 RHSBits = RHSBitsOrig;
4424 return std::make_pair(0, 0);
4428 switch (
MI->getOpcode()) {
4429 case TargetOpcode::G_AND:
4430 TTbl = LHSBits & RHSBits;
4432 case TargetOpcode::G_OR:
4433 TTbl = LHSBits | RHSBits;
4435 case TargetOpcode::G_XOR:
4436 TTbl = LHSBits ^ RHSBits;
4442 return std::make_pair(NumOpcodes + 1, TTbl);
4445bool AMDGPUInstructionSelector::selectBITOP3(
MachineInstr &
MI)
const {
4446 if (!Subtarget->hasBitOp3Insts())
4450 const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
4451 const bool IsVALU = DstRB->
getID() == AMDGPU::VGPRRegBankID;
4457 unsigned NumOpcodes;
4459 std::tie(NumOpcodes, TTbl) =
BitOp3_Op(DstReg, Src, *MRI);
4463 if (NumOpcodes < 2 || Src.empty())
4466 const bool IsB32 = MRI->getType(DstReg) ==
LLT::scalar(32);
4467 if (NumOpcodes == 2 && IsB32) {
4475 }
else if (NumOpcodes < 4) {
4482 unsigned Opc = IsB32 ? AMDGPU::V_BITOP3_B32_e64 : AMDGPU::V_BITOP3_B16_e64;
4483 if (!IsB32 && STI.hasTrue16BitInsts())
4484 Opc = STI.useRealTrue16Insts() ? AMDGPU::V_BITOP3_B16_gfx1250_t16_e64
4485 : AMDGPU::V_BITOP3_B16_gfx1250_fake16_e64;
4486 unsigned CBL = STI.getConstantBusLimit(
Opc);
4487 MachineBasicBlock *
MBB =
MI.getParent();
4490 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4491 const RegisterBank *RB = RBI.getRegBank(Src[
I], *MRI, TRI);
4492 if (RB->
getID() != AMDGPU::SGPRRegBankID)
4498 Register NewReg = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
4509 while (Src.size() < 3)
4510 Src.push_back(Src[0]);
4527 MI.eraseFromParent();
4532bool AMDGPUInstructionSelector::selectStackRestore(
MachineInstr &
MI)
const {
4534 if (!RBI.constrainGenericRegister(SrcReg, AMDGPU::SReg_32RegClass, *MRI))
4537 MachineInstr *
DefMI = MRI->getVRegDef(SrcReg);
4539 Subtarget->getTargetLowering()->getStackPointerRegisterToSaveRestore();
4541 MachineBasicBlock *
MBB =
MI.getParent();
4545 WaveAddr = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
4548 .
addImm(Subtarget->getWavefrontSizeLog2())
4555 MI.eraseFromParent();
4561 if (!
I.isPreISelOpcode()) {
4563 return selectCOPY(
I);
4567 switch (
I.getOpcode()) {
4568 case TargetOpcode::G_AND:
4569 case TargetOpcode::G_OR:
4570 case TargetOpcode::G_XOR:
4571 if (selectBITOP3(
I))
4575 return selectG_AND_OR_XOR(
I);
4576 case TargetOpcode::G_ADD:
4577 case TargetOpcode::G_SUB:
4578 case TargetOpcode::G_PTR_ADD:
4581 return selectG_ADD_SUB(
I);
4582 case TargetOpcode::G_UADDO:
4583 case TargetOpcode::G_USUBO:
4584 case TargetOpcode::G_UADDE:
4585 case TargetOpcode::G_USUBE:
4586 return selectG_UADDO_USUBO_UADDE_USUBE(
I);
4587 case AMDGPU::G_AMDGPU_MAD_U64_U32:
4588 case AMDGPU::G_AMDGPU_MAD_I64_I32:
4589 return selectG_AMDGPU_MAD_64_32(
I);
4590 case TargetOpcode::G_INTTOPTR:
4591 case TargetOpcode::G_BITCAST:
4592 case TargetOpcode::G_PTRTOINT:
4593 case TargetOpcode::G_FREEZE:
4594 return selectCOPY(
I);
4595 case TargetOpcode::G_FNEG:
4598 return selectG_FNEG(
I);
4599 case TargetOpcode::G_FABS:
4602 return selectG_FABS(
I);
4603 case TargetOpcode::G_EXTRACT:
4604 return selectG_EXTRACT(
I);
4605 case TargetOpcode::G_MERGE_VALUES:
4606 case TargetOpcode::G_CONCAT_VECTORS:
4607 return selectG_MERGE_VALUES(
I);
4608 case TargetOpcode::G_UNMERGE_VALUES:
4609 return selectG_UNMERGE_VALUES(
I);
4610 case TargetOpcode::G_BUILD_VECTOR:
4611 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
4612 return selectG_BUILD_VECTOR(
I);
4613 case TargetOpcode::G_IMPLICIT_DEF:
4614 return selectG_IMPLICIT_DEF(
I);
4615 case TargetOpcode::G_INSERT:
4616 return selectG_INSERT(
I);
4617 case TargetOpcode::G_INTRINSIC:
4618 case TargetOpcode::G_INTRINSIC_CONVERGENT:
4619 return selectG_INTRINSIC(
I);
4620 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
4621 case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
4622 return selectG_INTRINSIC_W_SIDE_EFFECTS(
I);
4623 case TargetOpcode::G_ICMP:
4624 case TargetOpcode::G_FCMP:
4625 if (selectG_ICMP_or_FCMP(
I))
4628 case TargetOpcode::G_LOAD:
4629 case TargetOpcode::G_ZEXTLOAD:
4630 case TargetOpcode::G_SEXTLOAD:
4631 case TargetOpcode::G_STORE:
4632 case TargetOpcode::G_ATOMIC_CMPXCHG:
4633 case TargetOpcode::G_ATOMICRMW_XCHG:
4634 case TargetOpcode::G_ATOMICRMW_ADD:
4635 case TargetOpcode::G_ATOMICRMW_SUB:
4636 case TargetOpcode::G_ATOMICRMW_AND:
4637 case TargetOpcode::G_ATOMICRMW_OR:
4638 case TargetOpcode::G_ATOMICRMW_XOR:
4639 case TargetOpcode::G_ATOMICRMW_MIN:
4640 case TargetOpcode::G_ATOMICRMW_MAX:
4641 case TargetOpcode::G_ATOMICRMW_UMIN:
4642 case TargetOpcode::G_ATOMICRMW_UMAX:
4643 case TargetOpcode::G_ATOMICRMW_UINC_WRAP:
4644 case TargetOpcode::G_ATOMICRMW_UDEC_WRAP:
4645 case TargetOpcode::G_ATOMICRMW_USUB_COND:
4646 case TargetOpcode::G_ATOMICRMW_USUB_SAT:
4647 case TargetOpcode::G_ATOMICRMW_FADD:
4648 case TargetOpcode::G_ATOMICRMW_FMIN:
4649 case TargetOpcode::G_ATOMICRMW_FMAX:
4650 return selectG_LOAD_STORE_ATOMICRMW(
I);
4651 case TargetOpcode::G_SELECT:
4652 return selectG_SELECT(
I);
4653 case TargetOpcode::G_TRUNC:
4654 return selectG_TRUNC(
I);
4655 case TargetOpcode::G_SEXT:
4656 case TargetOpcode::G_ZEXT:
4657 case TargetOpcode::G_ANYEXT:
4658 case TargetOpcode::G_SEXT_INREG:
4662 if (MRI->getType(
I.getOperand(1).getReg()) !=
LLT::scalar(1) &&
4665 return selectG_SZA_EXT(
I);
4666 case TargetOpcode::G_FPEXT:
4667 if (selectG_FPEXT(
I))
4670 case TargetOpcode::G_BRCOND:
4671 return selectG_BRCOND(
I);
4672 case TargetOpcode::G_GLOBAL_VALUE:
4673 return selectG_GLOBAL_VALUE(
I);
4674 case TargetOpcode::G_PTRMASK:
4675 return selectG_PTRMASK(
I);
4676 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4677 return selectG_EXTRACT_VECTOR_ELT(
I);
4678 case TargetOpcode::G_INSERT_VECTOR_ELT:
4679 return selectG_INSERT_VECTOR_ELT(
I);
4680 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD:
4681 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16:
4682 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET:
4683 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE:
4684 case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16: {
4687 assert(Intr &&
"not an image intrinsic with image pseudo");
4688 return selectImageIntrinsic(
I, Intr);
4690 case AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY:
4691 case AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY:
4692 case AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY:
4693 return selectBVHIntersectRayIntrinsic(
I);
4694 case AMDGPU::G_SBFX:
4695 case AMDGPU::G_UBFX:
4696 return selectG_SBFX_UBFX(
I);
4697 case AMDGPU::G_SI_CALL:
4698 I.setDesc(TII.get(AMDGPU::SI_CALL));
4700 case AMDGPU::G_AMDGPU_WAVE_ADDRESS:
4701 return selectWaveAddress(
I);
4702 case AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_RETURN: {
4703 I.setDesc(TII.get(AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN));
4706 case AMDGPU::G_STACKRESTORE:
4707 return selectStackRestore(
I);
4709 return selectPHI(
I);
4710 case AMDGPU::G_AMDGPU_COPY_SCC_VCC:
4711 return selectCOPY_SCC_VCC(
I);
4712 case AMDGPU::G_AMDGPU_COPY_VCC_SCC:
4713 return selectCOPY_VCC_SCC(
I);
4714 case AMDGPU::G_AMDGPU_READANYLANE:
4715 return selectReadAnyLane(
I);
4716 case TargetOpcode::G_CONSTANT:
4717 case TargetOpcode::G_FCONSTANT:
4725AMDGPUInstructionSelector::selectVCSRC(
MachineOperand &Root)
const {
4732std::pair<Register, unsigned> AMDGPUInstructionSelector::selectVOP3ModsImpl(
4733 Register Src,
bool IsCanonicalizing,
bool AllowAbs,
bool OpSel)
const {
4737 if (
MI->getOpcode() == AMDGPU::G_FNEG) {
4738 Src =
MI->getOperand(1).getReg();
4741 }
else if (
MI->getOpcode() == AMDGPU::G_FSUB && IsCanonicalizing) {
4746 if (
LHS &&
LHS->isZero()) {
4748 Src =
MI->getOperand(2).getReg();
4752 if (AllowAbs &&
MI->getOpcode() == AMDGPU::G_FABS) {
4753 Src =
MI->getOperand(1).getReg();
4760 return std::pair(Src, Mods);
4763std::pair<Register, unsigned>
4764AMDGPUInstructionSelector::selectVOP3PModsF32Impl(
Register Src)
const {
4766 std::tie(Src, Mods) = selectVOP3ModsImpl(Src);
4768 return std::pair(Src, Mods);
4771Register AMDGPUInstructionSelector::copyToVGPRIfSrcFolded(
4773 bool ForceVGPR)
const {
4774 if ((Mods != 0 || ForceVGPR) &&
4775 RBI.getRegBank(Src, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID) {
4782 TII.
get(AMDGPU::COPY), VGPRSrc)
4794AMDGPUInstructionSelector::selectVSRC0(
MachineOperand &Root)
const {
4796 [=](MachineInstrBuilder &MIB) { MIB.
add(Root); }
4801AMDGPUInstructionSelector::selectVOP3Mods0(
MachineOperand &Root)
const {
4804 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
4807 [=](MachineInstrBuilder &MIB) {
4808 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4810 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
4811 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4812 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4817AMDGPUInstructionSelector::selectVOP3BMods0(
MachineOperand &Root)
const {
4820 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
4825 [=](MachineInstrBuilder &MIB) {
4826 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4828 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
4829 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4830 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4835AMDGPUInstructionSelector::selectVOP3OMods(
MachineOperand &Root)
const {
4837 [=](MachineInstrBuilder &MIB) { MIB.
add(Root); },
4838 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); },
4839 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
4844AMDGPUInstructionSelector::selectVOP3Mods(
MachineOperand &Root)
const {
4847 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
4850 [=](MachineInstrBuilder &MIB) {
4851 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4853 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4858AMDGPUInstructionSelector::selectVOP3ModsNonCanonicalizing(
4862 std::tie(Src, Mods) =
4863 selectVOP3ModsImpl(Root.
getReg(),
false);
4866 [=](MachineInstrBuilder &MIB) {
4867 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4869 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4874AMDGPUInstructionSelector::selectVOP3BMods(
MachineOperand &Root)
const {
4877 std::tie(Src, Mods) =
4878 selectVOP3ModsImpl(Root.
getReg(),
true,
4882 [=](MachineInstrBuilder &MIB) {
4883 MIB.
addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
4885 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
4890AMDGPUInstructionSelector::selectVOP3NoMods(
MachineOperand &Root)
const {
4893 if (
Def->getOpcode() == AMDGPU::G_FNEG ||
Def->getOpcode() == AMDGPU::G_FABS)
4896 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
4921 if (
MI->getOpcode() != AMDGPU::G_TRUNC)
4926 return DstSize * 2 == SrcSize;
4932 if (
MI->getOpcode() != AMDGPU::G_LSHR)
4936 std::optional<ValueAndVReg> ShiftAmt;
4937 if (
mi_match(
MI->getOperand(0).getReg(), MRI,
4940 unsigned Shift = ShiftAmt->Value.getZExtValue();
4941 return Shift * 2 == SrcSize;
4949 if (
MI->getOpcode() != AMDGPU::G_SHL)
4953 std::optional<ValueAndVReg> ShiftAmt;
4954 if (
mi_match(
MI->getOperand(0).getReg(), MRI,
4957 unsigned Shift = ShiftAmt->Value.getZExtValue();
4958 return Shift * 2 == SrcSize;
4966 if (
MI->getOpcode() != AMDGPU::G_UNMERGE_VALUES)
4968 return MI->getNumOperands() == 3 &&
MI->getOperand(0).isDef() &&
4969 MI->getOperand(1).isDef() && !
MI->getOperand(2).isDef();
4977 if (
OpTy.isScalar())
4979 if (
OpTy.isVector() &&
OpTy.getNumElements() == 2)
5139static std::optional<std::pair<Register, SrcStatus>>
5144 unsigned Opc =
MI->getOpcode();
5148 case AMDGPU::G_BITCAST:
5149 return std::optional<std::pair<Register, SrcStatus>>(
5150 {
MI->getOperand(1).getReg(), Curr.second});
5152 if (
MI->getOperand(1).getReg().isPhysical())
5153 return std::nullopt;
5154 return std::optional<std::pair<Register, SrcStatus>>(
5155 {
MI->getOperand(1).getReg(), Curr.second});
5156 case AMDGPU::G_FNEG: {
5159 return std::nullopt;
5160 return std::optional<std::pair<Register, SrcStatus>>(
5161 {
MI->getOperand(1).getReg(), Stat});
5168 switch (Curr.second) {
5171 return std::optional<std::pair<Register, SrcStatus>>(
5174 if (Curr.first ==
MI->getOperand(0).getReg())
5175 return std::optional<std::pair<Register, SrcStatus>>(
5177 return std::optional<std::pair<Register, SrcStatus>>(
5189 return std::optional<std::pair<Register, SrcStatus>>(
5193 if (Curr.first ==
MI->getOperand(0).getReg())
5194 return std::optional<std::pair<Register, SrcStatus>>(
5196 return std::optional<std::pair<Register, SrcStatus>>(
5202 return std::optional<std::pair<Register, SrcStatus>>(
5207 return std::optional<std::pair<Register, SrcStatus>>(
5212 return std::optional<std::pair<Register, SrcStatus>>(
5217 return std::optional<std::pair<Register, SrcStatus>>(
5223 return std::nullopt;
5233 bool HasNeg =
false;
5235 bool HasOpsel =
true;
5240 unsigned Opc =
MI->getOpcode();
5242 if (
Opc == TargetOpcode::G_INTRINSIC) {
5245 if (IntrinsicID == Intrinsic::amdgcn_fdot2)
5272 while (
Depth <= MaxDepth && Curr.has_value()) {
5275 Statlist.push_back(Curr.value());
5282static std::pair<Register, SrcStatus>
5289 while (
Depth <= MaxDepth && Curr.has_value()) {
5295 LastSameOrNeg = Curr.value();
5300 return LastSameOrNeg;
5307 return Width1 == Width2;
5342 return isSameBitWidth(NewReg, RootReg, MRI) && IsHalfState(LoStat) &&
5343 IsHalfState(HiStat);
5346std::pair<Register, unsigned> AMDGPUInstructionSelector::selectVOP3PModsImpl(
5352 return {RootReg, Mods};
5355 SearchOptions SO(RootReg, MRI);
5368 if (MRI.getType(RootReg).getSizeInBits() == 128) {
5370 return {Stat.first, Mods};
5373 MachineInstr *
MI = MRI.getVRegDef(Stat.first);
5375 if (
MI->getOpcode() != AMDGPU::G_BUILD_VECTOR ||
MI->getNumOperands() != 3 ||
5376 (IsDOT && Subtarget->hasDOTOpSelHazard())) {
5378 return {Stat.first, Mods};
5384 if (StatlistHi.
empty()) {
5386 return {Stat.first, Mods};
5392 if (StatlistLo.
empty()) {
5394 return {Stat.first, Mods};
5397 for (
int I = StatlistHi.
size() - 1;
I >= 0;
I--) {
5398 for (
int J = StatlistLo.
size() - 1; J >= 0; J--) {
5399 if (StatlistHi[
I].first == StatlistLo[J].first &&
5401 StatlistHi[
I].first, RootReg, TII, MRI))
5402 return {StatlistHi[
I].first,
5403 updateMods(StatlistHi[
I].second, StatlistLo[J].second, Mods)};
5409 return {Stat.first, Mods};
5419 return RB->
getID() == RBNo;
5436 if (
checkRB(RootReg, AMDGPU::SGPRRegBankID, RBI, MRI,
TRI) ||
5437 checkRB(NewReg, AMDGPU::VGPRRegBankID, RBI, MRI,
TRI))
5441 if (
MI->getOpcode() == AMDGPU::COPY && NewReg ==
MI->getOperand(1).getReg()) {
5450 BuildMI(*BB,
MI,
MI->getDebugLoc(),
TII.get(AMDGPU::COPY), DstReg)
5458AMDGPUInstructionSelector::selectVOP3PRetHelper(
MachineOperand &Root,
5463 std::tie(
Reg, Mods) = selectVOP3PModsImpl(Root.
getReg(), MRI, IsDOT);
5467 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
5468 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5473AMDGPUInstructionSelector::selectVOP3PMods(
MachineOperand &Root)
const {
5475 return selectVOP3PRetHelper(Root);
5479AMDGPUInstructionSelector::selectVOP3PModsDOT(
MachineOperand &Root)
const {
5481 return selectVOP3PRetHelper(Root,
true);
5485AMDGPUInstructionSelector::selectVOP3PNoModsDOT(
MachineOperand &Root)
const {
5489 std::tie(Src, Mods) = selectVOP3PModsImpl(Root.
getReg(), MRI,
true );
5493 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); }}};
5497AMDGPUInstructionSelector::selectVOP3PModsF32(
MachineOperand &Root)
const {
5500 std::tie(Src, Mods) = selectVOP3PModsF32Impl(Root.
getReg());
5503 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5504 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5509AMDGPUInstructionSelector::selectVOP3PNoModsF32(
MachineOperand &Root)
const {
5512 std::tie(Src, Mods) = selectVOP3PModsF32Impl(Root.
getReg());
5516 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); }}};
5520AMDGPUInstructionSelector::selectWMMAOpSelVOP3PMods(
5523 "expected i1 value");
5529 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5537 switch (Elts.
size()) {
5539 DstRegClass = &AMDGPU::VReg_256RegClass;
5542 DstRegClass = &AMDGPU::VReg_128RegClass;
5545 DstRegClass = &AMDGPU::VReg_64RegClass;
5552 auto MIB =
B.buildInstr(AMDGPU::REG_SEQUENCE)
5554 for (
unsigned i = 0; i < Elts.
size(); ++i) {
5565 if (ModOpcode == TargetOpcode::G_FNEG) {
5569 for (
auto El : Elts) {
5575 if (Elts.size() != NegAbsElts.
size()) {
5584 assert(ModOpcode == TargetOpcode::G_FABS);
5592AMDGPUInstructionSelector::selectWMMAModsF32NegAbs(
MachineOperand &Root)
const {
5598 assert(BV->getNumSources() > 0);
5600 MachineInstr *ElF32 = MRI->getVRegDef(BV->getSourceReg(0));
5601 unsigned ModOpcode = (ElF32->
getOpcode() == AMDGPU::G_FNEG)
5604 for (
unsigned i = 0; i < BV->getNumSources(); ++i) {
5605 ElF32 = MRI->getVRegDef(BV->getSourceReg(i));
5612 if (BV->getNumSources() == EltsF32.
size()) {
5618 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5619 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5623AMDGPUInstructionSelector::selectWMMAModsF16Neg(
MachineOperand &Root)
const {
5629 for (
unsigned i = 0; i < CV->getNumSources(); ++i) {
5637 if (CV->getNumSources() == EltsV2F16.
size()) {
5644 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5645 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5649AMDGPUInstructionSelector::selectWMMAModsF16NegAbs(
MachineOperand &Root)
const {
5655 assert(CV->getNumSources() > 0);
5656 MachineInstr *ElV2F16 = MRI->getVRegDef(CV->getSourceReg(0));
5658 unsigned ModOpcode = (ElV2F16->
getOpcode() == AMDGPU::G_FNEG)
5662 for (
unsigned i = 0; i < CV->getNumSources(); ++i) {
5663 ElV2F16 = MRI->getVRegDef(CV->getSourceReg(i));
5670 if (CV->getNumSources() == EltsV2F16.
size()) {
5677 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5678 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }}};
5682AMDGPUInstructionSelector::selectWMMAVISrc(
MachineOperand &Root)
const {
5683 std::optional<FPValueAndVReg> FPValReg;
5685 if (TII.isInlineConstant(FPValReg->Value)) {
5686 return {{[=](MachineInstrBuilder &MIB) {
5687 MIB.
addImm(FPValReg->Value.bitcastToAPInt().getSExtValue());
5697 if (TII.isInlineConstant(ICst)) {
5707AMDGPUInstructionSelector::selectSWMMACIndex8(
MachineOperand &Root)
const {
5713 std::optional<ValueAndVReg> ShiftAmt;
5715 MRI->getType(ShiftSrc).getSizeInBits() == 32 &&
5716 ShiftAmt->Value.getZExtValue() % 8 == 0) {
5717 Key = ShiftAmt->Value.getZExtValue() / 8;
5722 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5723 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5728AMDGPUInstructionSelector::selectSWMMACIndex16(
MachineOperand &Root)
const {
5735 std::optional<ValueAndVReg> ShiftAmt;
5737 MRI->getType(ShiftSrc).getSizeInBits() == 32 &&
5738 ShiftAmt->Value.getZExtValue() == 16) {
5744 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5745 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5750AMDGPUInstructionSelector::selectSWMMACIndex32(
MachineOperand &Root)
const {
5757 S32 = matchAnyExtendFromS32(Src);
5761 if (
Def->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) {
5766 Src =
Def->getOperand(2).getReg();
5773 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5774 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Key); }
5779AMDGPUInstructionSelector::selectVOP3OpSelMods(
MachineOperand &Root)
const {
5782 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
5786 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
5787 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
5793AMDGPUInstructionSelector::selectVINTERPMods(
MachineOperand &Root)
const {
5796 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
5802 [=](MachineInstrBuilder &MIB) {
5804 copyToVGPRIfSrcFolded(Src, Mods, Root, MIB,
true));
5806 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
5811AMDGPUInstructionSelector::selectVINTERPModsHi(
MachineOperand &Root)
const {
5814 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg(),
5820 [=](MachineInstrBuilder &MIB) {
5822 copyToVGPRIfSrcFolded(Src, Mods, Root, MIB,
true));
5824 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); },
5831bool AMDGPUInstructionSelector::selectScaleOffset(
MachineOperand &Root,
5833 bool IsSigned)
const {
5834 if (!Subtarget->hasScaleOffset())
5838 MachineMemOperand *MMO = *
MI.memoperands_begin();
5850 OffsetReg =
Def->Reg;
5865 m_BinOp(IsSigned ? AMDGPU::S_MUL_I64_I32_PSEUDO : AMDGPU::S_MUL_U64,
5869 (
Mul->getOpcode() == (IsSigned ? AMDGPU::G_AMDGPU_MAD_I64_I32
5870 : AMDGPU::G_AMDGPU_MAD_U64_U32) ||
5871 (IsSigned &&
Mul->getOpcode() == AMDGPU::G_AMDGPU_MAD_U64_U32 &&
5872 VT->signBitIsZero(
Mul->getOperand(2).getReg()))) &&
5885bool AMDGPUInstructionSelector::selectSmrdOffset(
MachineOperand &Root,
5889 bool *ScaleOffset)
const {
5891 MachineBasicBlock *
MBB =
MI->getParent();
5896 getAddrModeInfo(*
MI, *MRI, AddrInfo);
5898 if (AddrInfo.
empty())
5901 const GEPInfo &GEPI = AddrInfo[0];
5902 std::optional<int64_t> EncodedImm;
5905 *ScaleOffset =
false;
5910 if (GEPI.SgprParts.size() == 1 && GEPI.Imm != 0 && EncodedImm &&
5911 AddrInfo.
size() > 1) {
5912 const GEPInfo &GEPI2 = AddrInfo[1];
5913 if (GEPI2.SgprParts.size() == 2 && GEPI2.Imm == 0) {
5914 Register OffsetReg = GEPI2.SgprParts[1];
5917 selectScaleOffset(Root, OffsetReg,
false );
5918 OffsetReg = matchZeroExtendFromS32OrS32(OffsetReg);
5920 Base = GEPI2.SgprParts[0];
5921 *SOffset = OffsetReg;
5930 auto SKnown =
VT->getKnownBits(*SOffset);
5931 if (*
Offset + SKnown.getMinValue().getSExtValue() < 0)
5943 if (
Offset && GEPI.SgprParts.size() == 1 && EncodedImm) {
5944 Base = GEPI.SgprParts[0];
5950 if (SOffset && GEPI.SgprParts.size() == 1 &&
isUInt<32>(GEPI.Imm) &&
5956 Base = GEPI.SgprParts[0];
5957 *SOffset = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
5958 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), *SOffset)
5963 if (SOffset && GEPI.SgprParts.size() && GEPI.Imm == 0) {
5964 Register OffsetReg = GEPI.SgprParts[1];
5966 *ScaleOffset = selectScaleOffset(Root, OffsetReg,
false );
5967 OffsetReg = matchZeroExtendFromS32OrS32(OffsetReg);
5969 Base = GEPI.SgprParts[0];
5970 *SOffset = OffsetReg;
5979AMDGPUInstructionSelector::selectSmrdImm(
MachineOperand &Root)
const {
5982 if (!selectSmrdOffset(Root,
Base,
nullptr, &
Offset,
5984 return std::nullopt;
5986 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
5987 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Offset); }}};
5991AMDGPUInstructionSelector::selectSmrdImm32(
MachineOperand &Root)
const {
5993 getAddrModeInfo(*Root.
getParent(), *MRI, AddrInfo);
5995 if (AddrInfo.
empty() || AddrInfo[0].SgprParts.size() != 1)
5996 return std::nullopt;
5998 const GEPInfo &GEPInfo = AddrInfo[0];
5999 Register PtrReg = GEPInfo.SgprParts[0];
6000 std::optional<int64_t> EncodedImm =
6003 return std::nullopt;
6006 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrReg); },
6007 [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); }
6012AMDGPUInstructionSelector::selectSmrdSgpr(
MachineOperand &Root)
const {
6015 if (!selectSmrdOffset(Root,
Base, &SOffset,
nullptr,
6017 return std::nullopt;
6020 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
6021 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
6022 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }}};
6026AMDGPUInstructionSelector::selectSmrdSgprImm(
MachineOperand &Root)
const {
6030 if (!selectSmrdOffset(Root,
Base, &SOffset, &
Offset, &ScaleOffset))
6031 return std::nullopt;
6034 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(
Base); },
6035 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
6037 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }}};
6040std::pair<Register, int> AMDGPUInstructionSelector::selectFlatOffsetImpl(
6046 if (!STI.hasFlatInstOffsets())
6050 int64_t ConstOffset;
6052 std::tie(PtrBase, ConstOffset, IsInBounds) =
6053 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
6059 if (ConstOffset == 0 ||
6061 !isFlatScratchBaseLegal(Root.
getReg())) ||
6065 unsigned AddrSpace = (*
MI->memoperands_begin())->getAddrSpace();
6066 if (!TII.isLegalFLATOffset(ConstOffset, AddrSpace, FlatVariant))
6069 return std::pair(PtrBase, ConstOffset);
6073AMDGPUInstructionSelector::selectFlatOffset(
MachineOperand &Root)
const {
6077 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6078 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6083AMDGPUInstructionSelector::selectGlobalOffset(
MachineOperand &Root)
const {
6084 auto PtrWithOffset =
6088 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6089 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6094AMDGPUInstructionSelector::selectScratchOffset(
MachineOperand &Root)
const {
6095 auto PtrWithOffset =
6099 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrWithOffset.first); },
6100 [=](MachineInstrBuilder &MIB) { MIB.
addImm(PtrWithOffset.second); },
6106AMDGPUInstructionSelector::selectGlobalSAddr(
MachineOperand &Root,
6108 bool NeedIOffset)
const {
6111 int64_t ConstOffset;
6112 int64_t ImmOffset = 0;
6116 std::tie(PtrBase, ConstOffset, std::ignore) =
6117 getPtrBaseWithConstantOffset(Addr, *MRI);
6119 if (ConstOffset != 0) {
6124 ImmOffset = ConstOffset;
6127 if (isSGPR(PtrBaseDef->Reg)) {
6128 if (ConstOffset > 0) {
6134 int64_t SplitImmOffset = 0, RemainderOffset = ConstOffset;
6136 std::tie(SplitImmOffset, RemainderOffset) =
6141 if (Subtarget->hasSignedGVSOffset() ?
isInt<32>(RemainderOffset)
6144 MachineBasicBlock *
MBB =
MI->getParent();
6146 MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6148 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32),
6150 .
addImm(RemainderOffset);
6154 [=](MachineInstrBuilder &MIB) {
6157 [=](MachineInstrBuilder &MIB) {
6160 [=](MachineInstrBuilder &MIB) { MIB.
addImm(SplitImmOffset); },
6161 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); },
6164 [=](MachineInstrBuilder &MIB) { MIB.
addReg(PtrBase); },
6165 [=](MachineInstrBuilder &MIB) {
6168 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); },
6178 unsigned NumLiterals =
6179 !TII.isInlineConstant(APInt(32,
Lo_32(ConstOffset))) +
6180 !TII.isInlineConstant(APInt(32,
Hi_32(ConstOffset)));
6181 if (STI.getConstantBusLimit(AMDGPU::V_ADD_U32_e64) > NumLiterals)
6182 return std::nullopt;
6189 if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
6194 if (isSGPR(SAddr)) {
6195 Register PtrBaseOffset = AddrDef->MI->getOperand(2).getReg();
6199 bool ScaleOffset = selectScaleOffset(Root, PtrBaseOffset,
6200 Subtarget->hasSignedGVSOffset());
6201 if (
Register VOffset = matchExtendFromS32OrS32(
6202 PtrBaseOffset, Subtarget->hasSignedGVSOffset())) {
6204 return {{[=](MachineInstrBuilder &MIB) {
6207 [=](MachineInstrBuilder &MIB) {
6210 [=](MachineInstrBuilder &MIB) {
6213 [=](MachineInstrBuilder &MIB) {
6217 return {{[=](MachineInstrBuilder &MIB) {
6220 [=](MachineInstrBuilder &MIB) {
6223 [=](MachineInstrBuilder &MIB) {
6233 if (AddrDef->MI->getOpcode() == AMDGPU::G_IMPLICIT_DEF ||
6234 AddrDef->MI->getOpcode() == AMDGPU::G_CONSTANT || !isSGPR(AddrDef->Reg))
6235 return std::nullopt;
6240 MachineBasicBlock *
MBB =
MI->getParent();
6241 Register VOffset = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6243 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32), VOffset)
6248 [=](MachineInstrBuilder &MIB) { MIB.
addReg(AddrDef->Reg); },
6249 [=](MachineInstrBuilder &MIB) { MIB.
addReg(VOffset); },
6250 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6251 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); }
6254 [=](MachineInstrBuilder &MIB) { MIB.
addReg(AddrDef->Reg); },
6255 [=](MachineInstrBuilder &MIB) { MIB.
addReg(VOffset); },
6256 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPolBits); }
6261AMDGPUInstructionSelector::selectGlobalSAddr(
MachineOperand &Root)
const {
6262 return selectGlobalSAddr(Root, 0);
6266AMDGPUInstructionSelector::selectGlobalSAddrCPol(
MachineOperand &Root)
const {
6272 return selectGlobalSAddr(Root, PassedCPol);
6276AMDGPUInstructionSelector::selectGlobalSAddrCPolM0(
MachineOperand &Root)
const {
6282 return selectGlobalSAddr(Root, PassedCPol);
6286AMDGPUInstructionSelector::selectGlobalSAddrGLC(
MachineOperand &Root)
const {
6291AMDGPUInstructionSelector::selectGlobalSAddrNoIOffset(
6298 return selectGlobalSAddr(Root, PassedCPol,
false);
6302AMDGPUInstructionSelector::selectGlobalSAddrNoIOffsetM0(
6309 return selectGlobalSAddr(Root, PassedCPol,
false);
6313AMDGPUInstructionSelector::selectScratchSAddr(
MachineOperand &Root)
const {
6316 int64_t ConstOffset;
6317 int64_t ImmOffset = 0;
6321 std::tie(PtrBase, ConstOffset, std::ignore) =
6322 getPtrBaseWithConstantOffset(Addr, *MRI);
6324 if (ConstOffset != 0 && isFlatScratchBaseLegal(Addr) &&
6328 ImmOffset = ConstOffset;
6332 if (AddrDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX) {
6333 int FI = AddrDef->MI->getOperand(1).
getIndex();
6336 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); }
6342 if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
6343 Register LHS = AddrDef->MI->getOperand(1).getReg();
6344 Register RHS = AddrDef->MI->getOperand(2).getReg();
6348 if (LHSDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX &&
6349 isSGPR(RHSDef->Reg)) {
6350 int FI = LHSDef->MI->getOperand(1).getIndex();
6354 SAddr = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
6356 BuildMI(*BB, &
I,
DL, TII.get(AMDGPU::S_ADD_I32), SAddr)
6364 return std::nullopt;
6367 [=](MachineInstrBuilder &MIB) { MIB.
addReg(SAddr); },
6368 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); }
6373bool AMDGPUInstructionSelector::checkFlatScratchSVSSwizzleBug(
6375 if (!Subtarget->hasFlatScratchSVSSwizzleBug())
6381 auto VKnown =
VT->getKnownBits(VAddr);
6384 uint64_t VMax = VKnown.getMaxValue().getZExtValue();
6385 uint64_t
SMax = SKnown.getMaxValue().getZExtValue();
6386 return (VMax & 3) + (
SMax & 3) >= 4;
6390AMDGPUInstructionSelector::selectScratchSVAddr(
MachineOperand &Root)
const {
6393 int64_t ConstOffset;
6394 int64_t ImmOffset = 0;
6398 std::tie(PtrBase, ConstOffset, std::ignore) =
6399 getPtrBaseWithConstantOffset(Addr, *MRI);
6402 if (ConstOffset != 0 &&
6406 ImmOffset = ConstOffset;
6410 if (AddrDef->MI->getOpcode() != AMDGPU::G_PTR_ADD)
6411 return std::nullopt;
6413 Register RHS = AddrDef->MI->getOperand(2).getReg();
6414 if (RBI.getRegBank(
RHS, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID)
6415 return std::nullopt;
6417 Register LHS = AddrDef->MI->getOperand(1).getReg();
6420 if (OrigAddr != Addr) {
6421 if (!isFlatScratchBaseLegalSVImm(OrigAddr))
6422 return std::nullopt;
6424 if (!isFlatScratchBaseLegalSV(OrigAddr))
6425 return std::nullopt;
6428 if (checkFlatScratchSVSSwizzleBug(
RHS,
LHS, ImmOffset))
6429 return std::nullopt;
6431 unsigned CPol = selectScaleOffset(Root,
RHS,
true )
6435 if (LHSDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX) {
6436 int FI = LHSDef->MI->getOperand(1).getIndex();
6438 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
RHS); },
6440 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6441 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }
6450 return std::nullopt;
6453 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
RHS); },
6454 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
LHS); },
6455 [=](MachineInstrBuilder &MIB) { MIB.
addImm(ImmOffset); },
6456 [=](MachineInstrBuilder &MIB) { MIB.
addImm(CPol); }
6461AMDGPUInstructionSelector::selectMUBUFScratchOffen(
MachineOperand &Root)
const {
6463 MachineBasicBlock *
MBB =
MI->getParent();
6465 const SIMachineFunctionInfo *
Info =
MF->getInfo<SIMachineFunctionInfo>();
6470 Register HighBits = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
6475 BuildMI(*
MBB,
MI,
MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32),
6479 return {{[=](MachineInstrBuilder &MIB) {
6482 [=](MachineInstrBuilder &MIB) {
6485 [=](MachineInstrBuilder &MIB) {
6490 [=](MachineInstrBuilder &MIB) {
6499 std::optional<int> FI;
6502 const MachineInstr *RootDef = MRI->getVRegDef(Root.
getReg());
6504 int64_t ConstOffset;
6505 std::tie(PtrBase, ConstOffset, std::ignore) =
6506 getPtrBaseWithConstantOffset(VAddr, *MRI);
6507 if (ConstOffset != 0) {
6508 if (TII.isLegalMUBUFImmOffset(ConstOffset) &&
6509 (!STI.privateMemoryResourceIsRangeChecked() ||
6510 VT->signBitIsZero(PtrBase))) {
6511 const MachineInstr *PtrBaseDef = MRI->getVRegDef(PtrBase);
6512 if (PtrBaseDef->
getOpcode() == AMDGPU::G_FRAME_INDEX)
6518 }
else if (RootDef->
getOpcode() == AMDGPU::G_FRAME_INDEX) {
6522 return {{[=](MachineInstrBuilder &MIB) {
6525 [=](MachineInstrBuilder &MIB) {
6531 [=](MachineInstrBuilder &MIB) {
6536 [=](MachineInstrBuilder &MIB) {
6541bool AMDGPUInstructionSelector::isDSOffsetLegal(
Register Base,
6546 if (STI.hasUsableDSOffset() || STI.unsafeDSOffsetFoldingEnabled())
6551 return VT->signBitIsZero(
Base);
6554bool AMDGPUInstructionSelector::isDSOffset2Legal(
Register Base, int64_t Offset0,
6556 unsigned Size)
const {
6557 if (Offset0 %
Size != 0 || Offset1 %
Size != 0)
6562 if (STI.hasUsableDSOffset() || STI.unsafeDSOffsetFoldingEnabled())
6567 return VT->signBitIsZero(
Base);
6572 return Addr->
getOpcode() == TargetOpcode::G_OR ||
6573 (Addr->
getOpcode() == TargetOpcode::G_PTR_ADD &&
6580bool AMDGPUInstructionSelector::isFlatScratchBaseLegal(
Register Addr)
const {
6588 if (STI.hasSignedScratchOffsets())
6594 if (AddrMI->
getOpcode() == TargetOpcode::G_PTR_ADD) {
6595 std::optional<ValueAndVReg> RhsValReg =
6601 if (RhsValReg && RhsValReg->Value.getSExtValue() < 0 &&
6602 RhsValReg->Value.getSExtValue() > -0x40000000)
6606 return VT->signBitIsZero(
LHS);
6611bool AMDGPUInstructionSelector::isFlatScratchBaseLegalSV(
Register Addr)
const {
6619 if (STI.hasSignedScratchOffsets())
6624 return VT->signBitIsZero(
RHS) &&
VT->signBitIsZero(
LHS);
6629bool AMDGPUInstructionSelector::isFlatScratchBaseLegalSVImm(
6633 if (STI.hasSignedScratchOffsets())
6638 std::optional<DefinitionAndSourceRegister> BaseDef =
6640 std::optional<ValueAndVReg> RHSOffset =
6650 (RHSOffset->Value.getSExtValue() < 0 &&
6651 RHSOffset->Value.getSExtValue() > -0x40000000)))
6654 Register LHS = BaseDef->MI->getOperand(1).getReg();
6655 Register RHS = BaseDef->MI->getOperand(2).getReg();
6656 return VT->signBitIsZero(
RHS) &&
VT->signBitIsZero(
LHS);
6659bool AMDGPUInstructionSelector::isUnneededShiftMask(
const MachineInstr &
MI,
6660 unsigned ShAmtBits)
const {
6661 assert(
MI.getOpcode() == TargetOpcode::G_AND);
6663 std::optional<APInt>
RHS =
6668 if (
RHS->countr_one() >= ShAmtBits)
6671 const APInt &LHSKnownZeros =
VT->getKnownZeroes(
MI.getOperand(1).getReg());
6672 return (LHSKnownZeros | *
RHS).countr_one() >= ShAmtBits;
6676AMDGPUInstructionSelector::selectMUBUFScratchOffset(
6679 const SIMachineFunctionInfo *
Info =
MF->getInfo<SIMachineFunctionInfo>();
6681 std::optional<DefinitionAndSourceRegister>
Def =
6683 assert(Def &&
"this shouldn't be an optional result");
6688 [=](MachineInstrBuilder &MIB) {
6691 [=](MachineInstrBuilder &MIB) {
6694 [=](MachineInstrBuilder &MIB) { MIB.
addImm(0); }
6705 if (!TII.isLegalMUBUFImmOffset(
Offset))
6713 [=](MachineInstrBuilder &MIB) {
6716 [=](MachineInstrBuilder &MIB) {
6724 !TII.isLegalMUBUFImmOffset(
Offset))
6728 [=](MachineInstrBuilder &MIB) {
6731 [=](MachineInstrBuilder &MIB) {
6738std::pair<Register, unsigned>
6739AMDGPUInstructionSelector::selectDS1Addr1OffsetImpl(
MachineOperand &Root)
const {
6740 const MachineInstr *RootDef = MRI->getVRegDef(Root.
getReg());
6741 int64_t ConstAddr = 0;
6745 std::tie(PtrBase,
Offset, std::ignore) =
6746 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
6749 if (isDSOffsetLegal(PtrBase,
Offset)) {
6751 return std::pair(PtrBase,
Offset);
6753 }
else if (RootDef->
getOpcode() == AMDGPU::G_SUB) {
6762 return std::pair(Root.
getReg(), 0);
6766AMDGPUInstructionSelector::selectDS1Addr1Offset(
MachineOperand &Root)
const {
6769 std::tie(
Reg,
Offset) = selectDS1Addr1OffsetImpl(Root);
6771 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
6777AMDGPUInstructionSelector::selectDS64Bit4ByteAligned(
MachineOperand &Root)
const {
6778 return selectDSReadWrite2(Root, 4);
6782AMDGPUInstructionSelector::selectDS128Bit8ByteAligned(
MachineOperand &Root)
const {
6783 return selectDSReadWrite2(Root, 8);
6787AMDGPUInstructionSelector::selectDSReadWrite2(
MachineOperand &Root,
6788 unsigned Size)
const {
6793 [=](MachineInstrBuilder &MIB) { MIB.
addReg(
Reg); },
6795 [=](MachineInstrBuilder &MIB) { MIB.
addImm(
Offset+1); }
6799std::pair<Register, unsigned>
6800AMDGPUInstructionSelector::selectDSReadWrite2Impl(
MachineOperand &Root,
6801 unsigned Size)
const {
6802 const MachineInstr *RootDef = MRI->getVRegDef(Root.
getReg());
6803 int64_t ConstAddr = 0;
6807 std::tie(PtrBase,
Offset, std::ignore) =
6808 getPtrBaseWithConstantOffset(Root.
getReg(), *MRI);
6811 int64_t OffsetValue0 =
Offset;
6813 if (isDSOffset2Legal(PtrBase, OffsetValue0, OffsetValue1,
Size)) {
6815 return std::pair(PtrBase, OffsetValue0 /
Size);
6817 }
else if (RootDef->
getOpcode() == AMDGPU::G_SUB) {
6825 return std::pair(Root.
getReg(), 0);
6833std::tuple<Register, int64_t, bool>
6834AMDGPUInstructionSelector::getPtrBaseWithConstantOffset(
6837 if (RootI->
getOpcode() != TargetOpcode::G_PTR_ADD)
6838 return {Root, 0,
false};
6841 std::optional<ValueAndVReg> MaybeOffset =
6844 return {Root, 0,
false};
6864 B.buildInstr(AMDGPU::S_MOV_B32)
6867 B.buildInstr(AMDGPU::S_MOV_B32)
6874 B.buildInstr(AMDGPU::REG_SEQUENCE)
6877 .addImm(AMDGPU::sub0)
6879 .addImm(AMDGPU::sub1);
6884 B.buildInstr(AMDGPU::S_MOV_B64)
6889 B.buildInstr(AMDGPU::REG_SEQUENCE)
6892 .addImm(AMDGPU::sub0_sub1)
6894 .addImm(AMDGPU::sub2_sub3);
6901 uint64_t DefaultFormat =
TII.getDefaultRsrcDataFormat();
6910 uint64_t DefaultFormat =
TII.getDefaultRsrcDataFormat();
6917AMDGPUInstructionSelector::MUBUFAddressData
6918AMDGPUInstructionSelector::parseMUBUFAddress(
Register Src)
const {
6919 MUBUFAddressData
Data;
6925 std::tie(PtrBase,
Offset, std::ignore) =
6926 getPtrBaseWithConstantOffset(Src, *MRI);
6932 if (MachineInstr *InputAdd
6934 Data.N2 = InputAdd->getOperand(1).getReg();
6935 Data.N3 = InputAdd->getOperand(2).getReg();
6950bool AMDGPUInstructionSelector::shouldUseAddr64(MUBUFAddressData Addr)
const {
6956 const RegisterBank *N0Bank = RBI.getRegBank(Addr.N0, *MRI, TRI);
6957 return N0Bank->
getID() == AMDGPU::VGPRRegBankID;
6963void AMDGPUInstructionSelector::splitIllegalMUBUFOffset(
6965 if (TII.isLegalMUBUFImmOffset(ImmOffset))
6969 SOffset = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
6970 B.buildInstr(AMDGPU::S_MOV_B32)
6976bool AMDGPUInstructionSelector::selectMUBUFAddr64Impl(
6981 if (!STI.hasAddr64() || STI.useFlatForGlobal())
6984 MUBUFAddressData AddrData = parseMUBUFAddress(Root.
getReg());
6985 if (!shouldUseAddr64(AddrData))
6991 Offset = AddrData.Offset;
6997 if (RBI.getRegBank(N2, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
6999 if (RBI.getRegBank(N3, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
7012 }
else if (RBI.getRegBank(N0, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
7023 splitIllegalMUBUFOffset(
B, SOffset,
Offset);
7027bool AMDGPUInstructionSelector::selectMUBUFOffsetImpl(
7032 if (STI.useFlatForGlobal())
7035 MUBUFAddressData AddrData = parseMUBUFAddress(Root.
getReg());
7036 if (shouldUseAddr64(AddrData))
7042 Offset = AddrData.Offset;
7048 splitIllegalMUBUFOffset(
B, SOffset,
Offset);
7053AMDGPUInstructionSelector::selectMUBUFAddr64(
MachineOperand &Root)
const {
7059 if (!selectMUBUFAddr64Impl(Root, VAddr, RSrcReg, SOffset,
Offset))
7065 [=](MachineInstrBuilder &MIB) {
7068 [=](MachineInstrBuilder &MIB) {
7071 [=](MachineInstrBuilder &MIB) {
7074 else if (STI.hasRestrictedSOffset())
7075 MIB.
addReg(AMDGPU::SGPR_NULL);
7079 [=](MachineInstrBuilder &MIB) {
7089AMDGPUInstructionSelector::selectMUBUFOffset(
MachineOperand &Root)
const {
7094 if (!selectMUBUFOffsetImpl(Root, RSrcReg, SOffset,
Offset))
7098 [=](MachineInstrBuilder &MIB) {
7101 [=](MachineInstrBuilder &MIB) {
7104 else if (STI.hasRestrictedSOffset())
7105 MIB.
addReg(AMDGPU::SGPR_NULL);
7117AMDGPUInstructionSelector::selectBUFSOffset(
MachineOperand &Root)
const {
7122 SOffset = AMDGPU::SGPR_NULL;
7124 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); }}};
7128static std::optional<uint64_t>
7132 if (!OffsetVal || !
isInt<32>(*OffsetVal))
7133 return std::nullopt;
7134 return Lo_32(*OffsetVal);
7138AMDGPUInstructionSelector::selectSMRDBufferImm(
MachineOperand &Root)
const {
7139 std::optional<uint64_t> OffsetVal =
7144 std::optional<int64_t> EncodedImm =
7149 return {{ [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); } }};
7153AMDGPUInstructionSelector::selectSMRDBufferImm32(
MachineOperand &Root)
const {
7160 std::optional<int64_t> EncodedImm =
7165 return {{ [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedImm); } }};
7169AMDGPUInstructionSelector::selectSMRDBufferSgprImm(
MachineOperand &Root)
const {
7177 return std::nullopt;
7179 std::optional<int64_t> EncodedOffset =
7182 return std::nullopt;
7185 return {{[=](MachineInstrBuilder &MIB) { MIB.
addReg(SOffset); },
7186 [=](MachineInstrBuilder &MIB) { MIB.
addImm(*EncodedOffset); }}};
7189std::pair<Register, unsigned>
7190AMDGPUInstructionSelector::selectVOP3PMadMixModsImpl(
MachineOperand &Root,
7191 bool &Matched)
const {
7196 std::tie(Src, Mods) = selectVOP3ModsImpl(Root.
getReg());
7206 const auto CheckAbsNeg = [&]() {
7211 std::tie(Src, ModsTmp) = selectVOP3ModsImpl(Src);
7242AMDGPUInstructionSelector::selectVOP3PMadMixModsExt(
7247 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7252 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
7253 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
7258AMDGPUInstructionSelector::selectVOP3PMadMixMods(
MachineOperand &Root)
const {
7262 std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
7265 [=](MachineInstrBuilder &MIB) { MIB.
addReg(Src); },
7266 [=](MachineInstrBuilder &MIB) { MIB.
addImm(Mods); }
7270bool AMDGPUInstructionSelector::selectSBarrierSignalIsfirst(
7274 Register CCReg =
I.getOperand(0).getReg();
7279 BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM))
7280 .
addImm(
I.getOperand(2).getImm());
7284 I.eraseFromParent();
7285 return RBI.constrainGenericRegister(CCReg, AMDGPU::SReg_32_XM0_XEXECRegClass,
7289bool AMDGPUInstructionSelector::selectSGetBarrierState(
7293 const MachineOperand &BarOp =
I.getOperand(2);
7294 std::optional<int64_t> BarValImm =
7298 auto CopyMIB =
BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
7302 MachineInstrBuilder MIB;
7303 unsigned Opc = BarValImm ? AMDGPU::S_GET_BARRIER_STATE_IMM
7304 : AMDGPU::S_GET_BARRIER_STATE_M0;
7307 auto DstReg =
I.getOperand(0).getReg();
7309 TRI.getConstrainedRegClassForOperand(
I.getOperand(0), *MRI);
7310 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
7316 I.eraseFromParent();
7321 if (HasInlineConst) {
7325 case Intrinsic::amdgcn_s_barrier_join:
7326 return AMDGPU::S_BARRIER_JOIN_IMM;
7327 case Intrinsic::amdgcn_s_wakeup_barrier:
7328 return AMDGPU::S_WAKEUP_BARRIER_IMM;
7329 case Intrinsic::amdgcn_s_get_named_barrier_state:
7330 return AMDGPU::S_GET_BARRIER_STATE_IMM;
7336 case Intrinsic::amdgcn_s_barrier_join:
7337 return AMDGPU::S_BARRIER_JOIN_M0;
7338 case Intrinsic::amdgcn_s_wakeup_barrier:
7339 return AMDGPU::S_WAKEUP_BARRIER_M0;
7340 case Intrinsic::amdgcn_s_get_named_barrier_state:
7341 return AMDGPU::S_GET_BARRIER_STATE_M0;
7346bool AMDGPUInstructionSelector::selectNamedBarrierInit(
7350 const MachineOperand &BarOp =
I.getOperand(1);
7351 const MachineOperand &CntOp =
I.getOperand(2);
7355 if (IntrID == Intrinsic::amdgcn_s_barrier_signal_var) {
7356 std::optional<int64_t> CntImm =
7358 if (CntImm && *CntImm == 0) {
7359 std::optional<int64_t> BarValImm =
7362 auto BarID = ((*BarValImm) >> 4) & 0x3F;
7363 BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::S_BARRIER_SIGNAL_IMM))
7365 I.eraseFromParent();
7372 Register TmpReg0 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7378 Register TmpReg1 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7385 Register TmpReg2 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7391 Register TmpReg3 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7392 constexpr unsigned ShAmt = 16;
7398 Register TmpReg4 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7408 unsigned Opc = IntrID == Intrinsic::amdgcn_s_barrier_init
7409 ? AMDGPU::S_BARRIER_INIT_M0
7410 : AMDGPU::S_BARRIER_SIGNAL_M0;
7411 MachineInstrBuilder MIB;
7414 I.eraseFromParent();
7418bool AMDGPUInstructionSelector::selectNamedBarrierInst(
7422 MachineOperand BarOp = IntrID == Intrinsic::amdgcn_s_get_named_barrier_state
7425 std::optional<int64_t> BarValImm =
7430 Register TmpReg0 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7436 Register TmpReg1 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
7442 auto CopyMIB =
BuildMI(*
MBB, &
I,
DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
7447 MachineInstrBuilder MIB;
7451 if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state) {
7452 auto DstReg =
I.getOperand(0).getReg();
7454 TRI.getConstrainedRegClassForOperand(
I.getOperand(0), *MRI);
7455 if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
7461 auto BarId = ((*BarValImm) >> 4) & 0x3F;
7465 I.eraseFromParent();
7472 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT &&
OpIdx == -1 &&
7473 "Expected G_CONSTANT");
7474 MIB.
addImm(
MI.getOperand(1).getCImm()->getSExtValue());
7480 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT &&
OpIdx == -1 &&
7481 "Expected G_CONSTANT");
7482 MIB.
addImm(-
MI.getOperand(1).getCImm()->getSExtValue());
7488 const MachineOperand &
Op =
MI.getOperand(1);
7489 assert(
MI.getOpcode() == TargetOpcode::G_FCONSTANT &&
OpIdx == -1);
7490 MIB.
addImm(
Op.getFPImm()->getValueAPF().bitcastToAPInt().getZExtValue());
7493void AMDGPUInstructionSelector::renderCountTrailingOnesImm(
7495 assert(
MI.getOpcode() == TargetOpcode::G_CONSTANT &&
OpIdx == -1 &&
7496 "Expected G_CONSTANT");
7497 MIB.
addImm(
MI.getOperand(1).getCImm()->getValue().countTrailingOnes());
7505 const MachineOperand &
Op =
MI.getOperand(
OpIdx);
7522 assert(
OpIdx >= 0 &&
"expected to match an immediate operand");
7526void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_0_0(
7528 assert(
OpIdx >= 0 &&
"expected to match an immediate operand");
7533void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_0_1(
7535 assert(
OpIdx >= 0 &&
"expected to match an immediate operand");
7541void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_1_0(
7543 assert(
OpIdx >= 0 &&
"expected to match an immediate operand");
7548void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_1_1(
7550 assert(
OpIdx >= 0 &&
"expected to match an immediate operand");
7556void AMDGPUInstructionSelector::renderDstSelToOpSelXForm(
7558 assert(
OpIdx >= 0 &&
"expected to match an immediate operand");
7563void AMDGPUInstructionSelector::renderSrcSelToOpSelXForm(
7565 assert(
OpIdx >= 0 &&
"expected to match an immediate operand");
7570void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_2_0(
7572 assert(
OpIdx >= 0 &&
"expected to match an immediate operand");
7577void AMDGPUInstructionSelector::renderDstSelToOpSel3XFormXForm(
7579 assert(
OpIdx >= 0 &&
"expected to match an immediate operand");
7588 assert(
OpIdx >= 0 &&
"expected to match an immediate operand");
7597 assert(
OpIdx >= 0 &&
"expected to match an immediate operand");
7604void AMDGPUInstructionSelector::renderExtractCpolSetGLC(
7606 assert(
OpIdx >= 0 &&
"expected to match an immediate operand");
7607 const uint32_t Cpol =
MI.getOperand(
OpIdx).getImm() &
7616 const APFloat &APF =
MI.getOperand(1).getFPImm()->getValueAPF();
7618 assert(ExpVal != INT_MIN);
7636 if (
MI.getOperand(
OpIdx).getImm())
7638 MIB.
addImm((int64_t)Mods);
7645 if (
MI.getOperand(
OpIdx).getImm())
7647 MIB.
addImm((int64_t)Mods);
7653 unsigned Val =
MI.getOperand(
OpIdx).getImm();
7661 MIB.
addImm((int64_t)Mods);
7667 uint32_t
V =
MI.getOperand(2).getImm();
7670 if (!Subtarget->hasSafeCUPrefetch())
7676void AMDGPUInstructionSelector::renderScaledMAIIntrinsicOperand(
7678 unsigned Val =
MI.getOperand(
OpIdx).getImm();
7687bool AMDGPUInstructionSelector::isInlineImmediate(
const APInt &Imm)
const {
7688 return TII.isInlineConstant(Imm);
7691bool AMDGPUInstructionSelector::isInlineImmediate(
const APFloat &Imm)
const {
7692 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 Register getLegalRegBank(Register NewReg, Register RootReg, const AMDGPURegisterBankInfo &RBI, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const SIInstrInfo &TII)
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 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.
Machine Check Debug Module
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
MachineInstr unsigned OpIdx
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
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.
ArrayRef< int > getShuffleMask() const
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 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 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)
#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.
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()
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
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)
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)
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.