29#include "llvm/IR/IntrinsicsAMDGPU.h"
33#ifdef EXPENSIVE_CHECKS
38#define DEBUG_TYPE "amdgpu-isel"
53 In = stripBitcast(In);
59 Out = In.getOperand(0);
70 if (ShiftAmt->getZExtValue() == 16) {
90 if (
Lo->isDivergent()) {
92 SL,
Lo.getValueType()),
100 Src.getValueType(),
Ops),
118 SDValue Idx = In.getOperand(1);
120 return In.getOperand(0);
124 SDValue Src = In.getOperand(0);
125 if (Src.getValueType().getSizeInBits() == 32)
126 return stripBitcast(Src);
136 assert(Elts.
size() == SubRegClass.
size() &&
"array size mismatch");
137 unsigned NumElts = Elts.
size();
140 for (
unsigned i = 0; i < NumElts; ++i) {
141 Ops[2 * i + 1] = Elts[i];
151 "AMDGPU DAG->DAG Pattern Instruction Selection",
false,
155#ifdef EXPENSIVE_CHECKS
160 "AMDGPU DAG->DAG Pattern Instruction Selection",
false,
181bool AMDGPUDAGToDAGISel::fp16SrcZerosHighBits(
unsigned Opc)
const {
217 case AMDGPUISD::FRACT:
218 case AMDGPUISD::CLAMP:
219 case AMDGPUISD::COS_HW:
220 case AMDGPUISD::SIN_HW:
221 case AMDGPUISD::FMIN3:
222 case AMDGPUISD::FMAX3:
223 case AMDGPUISD::FMED3:
224 case AMDGPUISD::FMAD_FTZ:
227 case AMDGPUISD::RCP_IFLAG:
237 case AMDGPUISD::DIV_FIXUP:
247#ifdef EXPENSIVE_CHECKS
251 assert(L->isLCSSAForm(DT));
259#ifdef EXPENSIVE_CHECKS
267 assert(Subtarget->d16PreservesUnusedBits());
268 MVT VT =
N->getValueType(0).getSimpleVT();
269 if (VT != MVT::v2i16 && VT != MVT::v2f16)
291 unsigned LoadOp = AMDGPUISD::LOAD_D16_HI;
294 AMDGPUISD::LOAD_D16_HI_I8 : AMDGPUISD::LOAD_D16_HI_U8;
300 CurDAG->getMemIntrinsicNode(LoadOp,
SDLoc(LdHi), VTList,
313 if (LdLo &&
Lo.hasOneUse()) {
319 unsigned LoadOp = AMDGPUISD::LOAD_D16_LO;
322 AMDGPUISD::LOAD_D16_LO_I8 : AMDGPUISD::LOAD_D16_LO_U8;
334 CurDAG->getMemIntrinsicNode(LoadOp,
SDLoc(LdLo), VTList,
347 if (!Subtarget->d16PreservesUnusedBits())
352 bool MadeChange =
false;
353 while (Position !=
CurDAG->allnodes_begin()) {
358 switch (
N->getOpcode()) {
369 CurDAG->RemoveDeadNodes();
375bool AMDGPUDAGToDAGISel::isInlineImmediate(
const SDNode *
N)
const {
381 return TII->isInlineConstant(
C->getAPIntValue());
384 return TII->isInlineConstant(
C->getValueAPF());
394 unsigned OpNo)
const {
395 if (!
N->isMachineOpcode()) {
398 if (
Reg.isVirtual()) {
403 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
404 return TRI->getPhysRegBaseClass(
Reg);
410 switch (
N->getMachineOpcode()) {
412 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
413 const MCInstrDesc &
Desc =
TII->get(
N->getMachineOpcode());
414 unsigned OpIdx =
Desc.getNumDefs() + OpNo;
418 int16_t RegClass =
TII->getOpRegClassID(
Desc.operands()[
OpIdx]);
422 return Subtarget->getRegisterInfo()->getRegClass(RegClass);
424 case AMDGPU::REG_SEQUENCE: {
425 unsigned RCID =
N->getConstantOperandVal(0);
427 Subtarget->getRegisterInfo()->getRegClass(RCID);
429 SDValue SubRegOp =
N->getOperand(OpNo + 1);
431 return Subtarget->getRegisterInfo()->getSubClassWithSubReg(SuperRC,
440 Ops.push_back(NewChain);
441 for (
unsigned i = 1, e =
N->getNumOperands(); i != e; ++i)
442 Ops.push_back(
N->getOperand(i));
445 return CurDAG->MorphNodeTo(
N,
N->getOpcode(),
N->getVTList(),
Ops);
452 assert(
N->getOperand(0).getValueType() == MVT::Other &&
"Expected chain");
455 return glueCopyToOp(
N,
M0,
M0.getValue(1));
458SDNode *AMDGPUDAGToDAGISel::glueCopyToM0LDSInit(
SDNode *
N)
const {
461 if (Subtarget->ldsRequiresM0Init())
463 N,
CurDAG->getSignedTargetConstant(-1, SDLoc(
N), MVT::i32));
465 MachineFunction &
MF =
CurDAG->getMachineFunction();
466 unsigned Value =
MF.getInfo<SIMachineFunctionInfo>()->getGDSSize();
468 glueCopyToM0(
N,
CurDAG->getTargetConstant(
Value, SDLoc(
N), MVT::i32));
475 SDNode *
Lo =
CurDAG->getMachineNode(
476 AMDGPU::S_MOV_B32,
DL, MVT::i32,
478 SDNode *
Hi =
CurDAG->getMachineNode(
479 AMDGPU::S_MOV_B32,
DL, MVT::i32,
482 CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID,
DL, MVT::i32),
486 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL, VT,
Ops);
489SDNode *AMDGPUDAGToDAGISel::packConstantV2I16(
const SDNode *
N,
494 uint32_t LHSVal, RHSVal;
498 uint32_t
K = (LHSVal & 0xffff) | (RHSVal << 16);
500 isVGPRImm(
N) ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32, SL,
508 EVT VT =
N->getValueType(0);
512 SDValue RegClass =
CurDAG->getTargetConstant(RegClassID,
DL, MVT::i32);
514 if (NumVectorElts == 1) {
515 CurDAG->SelectNodeTo(
N, AMDGPU::COPY_TO_REGCLASS, EltVT,
N->getOperand(0),
520 bool IsGCN =
CurDAG->getSubtarget().getTargetTriple().isAMDGCN();
521 if (IsGCN && Subtarget->has64BitLiterals() && VT.
getSizeInBits() == 64 &&
524 bool AllConst =
true;
526 for (
unsigned I = 0;
I < NumVectorElts; ++
I) {
534 Val = CF->getValueAPF().bitcastToAPInt().getZExtValue();
537 C |= Val << (EltSize *
I);
542 CurDAG->getMachineNode(AMDGPU::S_MOV_B64_IMM_PSEUDO,
DL, VT, CV);
543 CurDAG->SelectNodeTo(
N, AMDGPU::COPY_TO_REGCLASS, VT,
SDValue(Copy, 0),
549 assert(NumVectorElts <= 32 &&
"Vectors with more than 32 elements not "
556 RegSeqArgs[0] =
CurDAG->getTargetConstant(RegClassID,
DL, MVT::i32);
557 bool IsRegSeq =
true;
558 unsigned NOps =
N->getNumOperands();
560 assert(IsGCN || EltSizeInRegs == 1);
561 for (
unsigned i = 0; i < NOps; i++) {
568 i * EltSizeInRegs, EltSizeInRegs)
570 RegSeqArgs[1 + (2 * i)] =
N->getOperand(i);
571 RegSeqArgs[1 + (2 * i) + 1] =
CurDAG->getTargetConstant(
Sub,
DL, MVT::i32);
573 if (NOps != NumVectorElts) {
578 for (
unsigned i = NOps; i < NumVectorElts; ++i) {
580 i * EltSizeInRegs, EltSizeInRegs)
582 RegSeqArgs[1 + (2 * i)] =
SDValue(ImpDef, 0);
583 RegSeqArgs[1 + (2 * i) + 1] =
590 CurDAG->SelectNodeTo(
N, AMDGPU::REG_SEQUENCE,
N->getVTList(), RegSeqArgs);
594 EVT VT =
N->getValueType(0);
598 if (!Subtarget->hasPkMovB32() || !EltVT.
bitsEq(MVT::i32) ||
612 Mask[0] < 4 && Mask[1] < 4);
614 SDValue VSrc0 = Mask[0] < 2 ? Src0 : Src1;
615 SDValue VSrc1 = Mask[1] < 2 ? Src0 : Src1;
616 unsigned Src0SubReg = Mask[0] & 1 ? AMDGPU::sub1 : AMDGPU::sub0;
617 unsigned Src1SubReg = Mask[1] & 1 ? AMDGPU::sub1 : AMDGPU::sub0;
620 Src0SubReg = Src1SubReg;
622 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, VT);
627 Src1SubReg = Src0SubReg;
629 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, VT);
639 if (
N->isDivergent() && Src0SubReg == AMDGPU::sub1 &&
640 Src1SubReg == AMDGPU::sub0) {
656 SDValue Src0OpSelVal =
CurDAG->getTargetConstant(Src0OpSel,
DL, MVT::i32);
657 SDValue Src1OpSelVal =
CurDAG->getTargetConstant(Src1OpSel,
DL, MVT::i32);
660 CurDAG->SelectNodeTo(
N, AMDGPU::V_PK_MOV_B32,
N->getVTList(),
661 {Src0OpSelVal, VSrc0, Src1OpSelVal, VSrc1,
671 CurDAG->getTargetExtractSubreg(Src0SubReg,
DL, EltVT, VSrc0);
673 CurDAG->getTargetExtractSubreg(Src1SubReg,
DL, EltVT, VSrc1);
676 CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID,
DL, MVT::i32),
677 ResultElt0,
CurDAG->getTargetConstant(AMDGPU::sub0,
DL, MVT::i32),
678 ResultElt1,
CurDAG->getTargetConstant(AMDGPU::sub1,
DL, MVT::i32)};
679 CurDAG->SelectNodeTo(
N, TargetOpcode::REG_SEQUENCE, VT,
Ops);
683 unsigned int Opc =
N->getOpcode();
684 if (
N->isMachineOpcode()) {
692 N = glueCopyToM0LDSInit(
N);
702 if (
N->getValueType(0) == MVT::i64) {
703 SelectAddcSubbI64(
N);
707 if (
N->getValueType(0) != MVT::i32)
714 if (
N->getValueType(0) == MVT::i64) {
715 SelectAddcSubbI64(
N);
719 SelectUADDO_USUBO(
N);
722 case AMDGPUISD::FMUL_W_CHAIN: {
723 SelectFMUL_W_CHAIN(
N);
726 case AMDGPUISD::FMA_W_CHAIN: {
727 SelectFMA_W_CHAIN(
N);
733 EVT VT =
N->getValueType(0);
751 N->isDivergent() ?
TRI->getDefaultVectorSuperClassForBitWidth(VecInBits)
763 if (
N->getValueType(0) == MVT::i128) {
764 RC =
CurDAG->getTargetConstant(AMDGPU::SGPR_128RegClassID,
DL, MVT::i32);
765 SubReg0 =
CurDAG->getTargetConstant(AMDGPU::sub0_sub1,
DL, MVT::i32);
766 SubReg1 =
CurDAG->getTargetConstant(AMDGPU::sub2_sub3,
DL, MVT::i32);
767 }
else if (
N->getValueType(0) == MVT::i64) {
768 RC =
CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID,
DL, MVT::i32);
769 SubReg0 =
CurDAG->getTargetConstant(AMDGPU::sub0,
DL, MVT::i32);
770 SubReg1 =
CurDAG->getTargetConstant(AMDGPU::sub1,
DL, MVT::i32);
774 const SDValue Ops[] = { RC,
N->getOperand(0), SubReg0,
775 N->getOperand(1), SubReg1 };
777 N->getValueType(0),
Ops));
783 if (
N->getValueType(0).getSizeInBits() != 64 || isInlineImmediate(
N) ||
784 Subtarget->has64BitLiterals())
789 Imm =
FP->getValueAPF().bitcastToAPInt().getZExtValue();
794 Imm =
C->getZExtValue();
803 case AMDGPUISD::BFE_I32:
804 case AMDGPUISD::BFE_U32: {
830 case AMDGPUISD::DIV_SCALE: {
841 return SelectMUL_LOHI(
N);
852 if (
N->getValueType(0) != MVT::i32)
863 case AMDGPUISD::CVT_PKRTZ_F16_F32:
864 case AMDGPUISD::CVT_PKNORM_I16_F32:
865 case AMDGPUISD::CVT_PKNORM_U16_F32:
866 case AMDGPUISD::CVT_PK_U16_U32:
867 case AMDGPUISD::CVT_PK_I16_I32: {
869 if (
N->getValueType(0) == MVT::i32) {
870 MVT NewVT =
Opc == AMDGPUISD::CVT_PKRTZ_F16_F32 ? MVT::v2f16 : MVT::v2i16;
872 { N->getOperand(0), N->getOperand(1) });
880 SelectINTRINSIC_W_CHAIN(
N);
884 SelectINTRINSIC_WO_CHAIN(
N);
888 SelectINTRINSIC_VOID(
N);
892 SelectWAVE_ADDRESS(
N);
896 SelectSTACKRESTORE(
N);
905 if (!Subtarget->hasSDWA())
915 return RHS->getZExtValue() == 0xFF || RHS->getZExtValue() == 0xFFFF;
919 return (RHS->getZExtValue() % 8) == 0;
924bool AMDGPUDAGToDAGISel::isUniformBr(
const SDNode *
N)
const {
927 return Term->getMetadata(
"amdgpu.uniform") ||
928 Term->getMetadata(
"structurizecfg.uniform");
931bool AMDGPUDAGToDAGISel::isUnneededShiftMask(
const SDNode *
N,
932 unsigned ShAmtBits)
const {
935 const APInt &
RHS =
N->getConstantOperandAPInt(1);
936 if (
RHS.countr_one() >= ShAmtBits)
966 N1 =
Lo.getOperand(1);
976 if (
CurDAG->isBaseWithConstantOffset(Addr)) {
991 return "AMDGPU DAG->DAG Pattern Instruction Selection";
1007#ifdef EXPENSIVE_CHECKS
1010 for (
auto &L : LI.getLoopsInPreorder())
1011 assert(L->isLCSSAForm(DT) &&
"Loop is not in LCSSA form!");
1033 }
else if ((Addr.
getOpcode() == AMDGPUISD::DWORDADDR) &&
1035 Base =
CurDAG->getRegister(R600::INDIRECT_BASE_ADDR, MVT::i32);
1049SDValue AMDGPUDAGToDAGISel::getMaterializedScalarImm32(int64_t Val,
1051 SDNode *Mov =
CurDAG->getMachineNode(
1052 AMDGPU::S_MOV_B32,
DL, MVT::i32,
1053 CurDAG->getTargetConstant(Val,
DL, MVT::i32));
1057void AMDGPUDAGToDAGISel::SelectAddcSubb(
SDNode *
N) {
1062 if (
N->isDivergent()) {
1064 : AMDGPU::V_SUBB_U32_e64;
1066 N,
Opc,
N->getVTList(),
1068 CurDAG->getTargetConstant(0, {}, MVT::i1) });
1071 : AMDGPU::S_SUB_CO_PSEUDO;
1072 CurDAG->SelectNodeTo(
N,
Opc,
N->getVTList(), {LHS, RHS, CI});
1076void AMDGPUDAGToDAGISel::SelectAddcSubbI64(
SDNode *
N) {
1081 unsigned Opcode =
N->getOpcode();
1088 SDNode *Lo0 =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
DL,
1089 MVT::i32,
LHS, Sub0);
1090 SDNode *Hi0 =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
DL,
1091 MVT::i32,
LHS, Sub1);
1093 SDNode *Lo1 =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
DL,
1094 MVT::i32,
RHS, Sub0);
1095 SDNode *Hi1 =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
DL,
1096 MVT::i32,
RHS, Sub1);
1098 SDVTList VTList =
CurDAG->getVTList(MVT::i32,
N->getValueType(1));
1100 static const unsigned NoCarryOpcMap[2][2] = {
1101 {AMDGPU::S_USUBO_PSEUDO, AMDGPU::S_UADDO_PSEUDO},
1102 {AMDGPU::V_SUB_CO_U32_e64, AMDGPU::V_ADD_CO_U32_e64}};
1103 static const unsigned CarryOpcMap[2][2] = {
1104 {AMDGPU::S_SUB_CO_PSEUDO, AMDGPU::S_ADD_CO_PSEUDO},
1105 {AMDGPU::V_SUBB_U32_e64, AMDGPU::V_ADDC_U32_e64}};
1107 bool IsVALU =
N->isDivergent();
1109 unsigned NoCarryOpc = NoCarryOpcMap[IsVALU][IsAdd];
1110 unsigned CarryOpc = CarryOpcMap[IsVALU][IsAdd];
1114 if (!ConsumeCarry) {
1117 AddLo =
CurDAG->getMachineNode(NoCarryOpc,
DL, VTList, Args);
1120 AddLo =
CurDAG->getMachineNode(NoCarryOpc,
DL, VTList, Args);
1126 AddLo =
CurDAG->getMachineNode(CarryOpc,
DL, VTList, Args);
1129 AddLo =
CurDAG->getMachineNode(CarryOpc,
DL, VTList, Args);
1137 AddHi =
CurDAG->getMachineNode(CarryOpc,
DL, VTList, Args);
1140 AddHi =
CurDAG->getMachineNode(CarryOpc,
DL, VTList, Args);
1143 unsigned RC = IsVALU ? AMDGPU::VReg_64RegClassID : AMDGPU::SReg_64RegClassID;
1144 SDValue RegSequenceArgs[] = {
CurDAG->getTargetConstant(RC,
DL, MVT::i32),
1148 MVT::i64, RegSequenceArgs);
1154void AMDGPUDAGToDAGISel::SelectUADDO_USUBO(
SDNode *
N) {
1159 bool IsVALU =
N->isDivergent();
1161 for (SDNode::user_iterator UI =
N->user_begin(),
E =
N->user_end(); UI !=
E;
1163 if (UI.getUse().getResNo() == 1) {
1164 if (UI->isMachineOpcode()) {
1165 if (UI->getMachineOpcode() !=
1166 (IsAdd ? AMDGPU::S_ADD_CO_PSEUDO : AMDGPU::S_SUB_CO_PSEUDO)) {
1179 unsigned Opc = IsAdd ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_SUB_CO_U32_e64;
1182 N,
Opc,
N->getVTList(),
1183 {N->getOperand(0), N->getOperand(1),
1184 CurDAG->getTargetConstant(0, {}, MVT::i1) });
1186 unsigned Opc = IsAdd ? AMDGPU::S_UADDO_PSEUDO : AMDGPU::S_USUBO_PSEUDO;
1188 CurDAG->SelectNodeTo(
N,
Opc,
N->getVTList(),
1189 {N->getOperand(0), N->getOperand(1)});
1193void AMDGPUDAGToDAGISel::SelectFMA_W_CHAIN(
SDNode *
N) {
1197 SelectVOP3Mods0(
N->getOperand(1),
Ops[1],
Ops[0],
Ops[6],
Ops[7]);
1198 SelectVOP3Mods(
N->getOperand(2),
Ops[3],
Ops[2]);
1199 SelectVOP3Mods(
N->getOperand(3),
Ops[5],
Ops[4]);
1200 Ops[8] =
N->getOperand(0);
1201 Ops[9] =
N->getOperand(4);
1205 bool UseFMAC = Subtarget->hasDLInsts() &&
1209 unsigned Opcode = UseFMAC ? AMDGPU::V_FMAC_F32_e64 : AMDGPU::V_FMA_F32_e64;
1210 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(),
Ops);
1213void AMDGPUDAGToDAGISel::SelectFMUL_W_CHAIN(
SDNode *
N) {
1217 SelectVOP3Mods0(
N->getOperand(1),
Ops[1],
Ops[0],
Ops[4],
Ops[5]);
1218 SelectVOP3Mods(
N->getOperand(2),
Ops[3],
Ops[2]);
1219 Ops[6] =
N->getOperand(0);
1220 Ops[7] =
N->getOperand(3);
1222 CurDAG->SelectNodeTo(
N, AMDGPU::V_MUL_F32_e64,
N->getVTList(),
Ops);
1227void AMDGPUDAGToDAGISel::SelectDIV_SCALE(
SDNode *
N) {
1228 EVT VT =
N->getValueType(0);
1230 assert(VT == MVT::f32 || VT == MVT::f64);
1233 = (VT == MVT::f64) ? AMDGPU::V_DIV_SCALE_F64_e64 : AMDGPU::V_DIV_SCALE_F32_e64;
1238 SelectVOP3BMods0(
N->getOperand(0),
Ops[1],
Ops[0],
Ops[6],
Ops[7]);
1239 SelectVOP3BMods(
N->getOperand(1),
Ops[3],
Ops[2]);
1240 SelectVOP3BMods(
N->getOperand(2),
Ops[5],
Ops[4]);
1246void AMDGPUDAGToDAGISel::SelectMAD_64_32(
SDNode *
N) {
1250 bool UseNoCarry = Subtarget->hasMadNC64_32Insts() && !
N->hasAnyUseOfValue(1);
1251 if (Subtarget->hasMADIntraFwdBug())
1252 Opc =
Signed ? AMDGPU::V_MAD_I64_I32_gfx11_e64
1253 : AMDGPU::V_MAD_U64_U32_gfx11_e64;
1254 else if (UseNoCarry)
1255 Opc =
Signed ? AMDGPU::V_MAD_NC_I64_I32_e64 : AMDGPU::V_MAD_NC_U64_U32_e64;
1257 Opc =
Signed ? AMDGPU::V_MAD_I64_I32_e64 : AMDGPU::V_MAD_U64_U32_e64;
1260 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1),
N->getOperand(2),
1264 MachineSDNode *Mad =
CurDAG->getMachineNode(
Opc, SL, MVT::i64,
Ops);
1275void AMDGPUDAGToDAGISel::SelectMUL_LOHI(
SDNode *
N) {
1280 if (Subtarget->hasMadNC64_32Insts()) {
1281 VTList =
CurDAG->getVTList(MVT::i64);
1282 Opc =
Signed ? AMDGPU::V_MAD_NC_I64_I32_e64 : AMDGPU::V_MAD_NC_U64_U32_e64;
1284 VTList =
CurDAG->getVTList(MVT::i64, MVT::i1);
1285 if (Subtarget->hasMADIntraFwdBug()) {
1286 Opc =
Signed ? AMDGPU::V_MAD_I64_I32_gfx11_e64
1287 : AMDGPU::V_MAD_U64_U32_gfx11_e64;
1289 Opc =
Signed ? AMDGPU::V_MAD_I64_I32_e64 : AMDGPU::V_MAD_U64_U32_e64;
1296 SDNode *Mad =
CurDAG->getMachineNode(
Opc, SL, VTList,
Ops);
1298 SDValue Sub0 =
CurDAG->getTargetConstant(AMDGPU::sub0, SL, MVT::i32);
1299 SDNode *
Lo =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, SL,
1300 MVT::i32,
SDValue(Mad, 0), Sub0);
1304 SDValue Sub1 =
CurDAG->getTargetConstant(AMDGPU::sub1, SL, MVT::i32);
1305 SDNode *
Hi =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, SL,
1306 MVT::i32,
SDValue(Mad, 0), Sub1);
1316 if (!
Base || Subtarget->hasUsableDSOffset() ||
1317 Subtarget->unsafeDSOffsetFoldingEnabled())
1328 if (
CurDAG->isBaseWithConstantOffset(Addr)) {
1341 int64_t ByteOffset =
C->getSExtValue();
1342 if (isDSOffsetLegal(
SDValue(), ByteOffset)) {
1351 if (isDSOffsetLegal(
Sub, ByteOffset)) {
1357 unsigned SubOp = AMDGPU::V_SUB_CO_U32_e32;
1358 if (Subtarget->hasAddNoCarryInsts()) {
1359 SubOp = AMDGPU::V_SUB_U32_e64;
1361 CurDAG->getTargetConstant(0, {}, MVT::i1));
1364 MachineSDNode *MachineSub =
1365 CurDAG->getMachineNode(SubOp,
DL, MVT::i32, Opnds);
1381 if (isDSOffsetLegal(
SDValue(), CAddr->getZExtValue())) {
1383 MachineSDNode *MovZero =
CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32,
1384 DL, MVT::i32, Zero);
1386 Offset =
CurDAG->getTargetConstant(CAddr->getZExtValue(),
DL, MVT::i16);
1393 Offset =
CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i16);
1397bool AMDGPUDAGToDAGISel::isDSOffset2Legal(
SDValue Base,
unsigned Offset0,
1399 unsigned Size)
const {
1400 if (Offset0 %
Size != 0 || Offset1 %
Size != 0)
1405 if (!
Base || Subtarget->hasUsableDSOffset() ||
1406 Subtarget->unsafeDSOffsetFoldingEnabled())
1424bool AMDGPUDAGToDAGISel::isFlatScratchBaseLegal(
SDValue Addr)
const {
1430 if (Subtarget->hasSignedScratchOffsets())
1440 ConstantSDNode *ImmOp =
nullptr;
1451bool AMDGPUDAGToDAGISel::isFlatScratchBaseLegalSV(
SDValue Addr)
const {
1457 if (Subtarget->hasSignedScratchOffsets())
1467bool AMDGPUDAGToDAGISel::isFlatScratchBaseLegalSVImm(
SDValue Addr)
const {
1481 (RHSImm->getSExtValue() < 0 && RHSImm->getSExtValue() > -0x40000000)))
1484 auto LHS =
Base.getOperand(0);
1485 auto RHS =
Base.getOperand(1);
1493 return SelectDSReadWrite2(Addr,
Base, Offset0, Offset1, 4);
1499 return SelectDSReadWrite2(Addr,
Base, Offset0, Offset1, 8);
1504 unsigned Size)
const {
1507 if (
CurDAG->isBaseWithConstantOffset(Addr)) {
1512 unsigned OffsetValue1 = OffsetValue0 +
Size;
1515 if (isDSOffset2Legal(N0, OffsetValue0, OffsetValue1,
Size)) {
1517 Offset0 =
CurDAG->getTargetConstant(OffsetValue0 /
Size,
DL, MVT::i32);
1518 Offset1 =
CurDAG->getTargetConstant(OffsetValue1 /
Size,
DL, MVT::i32);
1523 if (
const ConstantSDNode *
C =
1525 unsigned OffsetValue0 =
C->getZExtValue();
1526 unsigned OffsetValue1 = OffsetValue0 +
Size;
1528 if (isDSOffset2Legal(
SDValue(), OffsetValue0, OffsetValue1,
Size)) {
1538 if (isDSOffset2Legal(
Sub, OffsetValue0, OffsetValue1,
Size)) {
1542 unsigned SubOp = AMDGPU::V_SUB_CO_U32_e32;
1543 if (Subtarget->hasAddNoCarryInsts()) {
1544 SubOp = AMDGPU::V_SUB_U32_e64;
1546 CurDAG->getTargetConstant(0, {}, MVT::i1));
1549 MachineSDNode *MachineSub =
CurDAG->getMachineNode(
1554 CurDAG->getTargetConstant(OffsetValue0 /
Size,
DL, MVT::i32);
1556 CurDAG->getTargetConstant(OffsetValue1 /
Size,
DL, MVT::i32);
1562 unsigned OffsetValue0 = CAddr->getZExtValue();
1563 unsigned OffsetValue1 = OffsetValue0 +
Size;
1565 if (isDSOffset2Legal(
SDValue(), OffsetValue0, OffsetValue1,
Size)) {
1567 MachineSDNode *MovZero =
1568 CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32,
DL, MVT::i32, Zero);
1570 Offset0 =
CurDAG->getTargetConstant(OffsetValue0 /
Size,
DL, MVT::i32);
1571 Offset1 =
CurDAG->getTargetConstant(OffsetValue1 /
Size,
DL, MVT::i32);
1579 Offset0 =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1580 Offset1 =
CurDAG->getTargetConstant(1,
DL, MVT::i32);
1590 if (Subtarget->useFlatForGlobal())
1595 Idxen =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
1596 Offen =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
1597 Addr64 =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
1598 SOffset = Subtarget->hasRestrictedSOffset()
1599 ?
CurDAG->getRegister(AMDGPU::SGPR_NULL, MVT::i32)
1600 :
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1602 ConstantSDNode *C1 =
nullptr;
1604 if (
CurDAG->isBaseWithConstantOffset(Addr)) {
1617 Addr64 =
CurDAG->getTargetConstant(1,
DL, MVT::i1);
1623 Ptr =
SDValue(buildSMovImm64(
DL, 0, MVT::v2i32), 0);
1639 Ptr =
SDValue(buildSMovImm64(
DL, 0, MVT::v2i32), 0);
1641 Addr64 =
CurDAG->getTargetConstant(1,
DL, MVT::i1);
1645 VAddr =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1655 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
1666 AMDGPU::S_MOV_B32,
DL, MVT::i32,
1672bool AMDGPUDAGToDAGISel::SelectMUBUFAddr64(
SDValue Addr,
SDValue &SRsrc,
1675 SDValue Ptr, Offen, Idxen, Addr64;
1679 if (!Subtarget->hasAddr64())
1682 if (!SelectMUBUF(Addr, Ptr, VAddr, SOffset,
Offset, Offen, Idxen, Addr64))
1686 if (
C->getSExtValue()) {
1699std::pair<SDValue, SDValue> AMDGPUDAGToDAGISel::foldFrameIndex(
SDValue N)
const {
1704 FI ?
CurDAG->getTargetFrameIndex(FI->getIndex(), FI->getValueType(0)) :
N;
1710 return std::pair(TFI,
CurDAG->getTargetConstant(0,
DL, MVT::i32));
1713bool AMDGPUDAGToDAGISel::SelectMUBUFScratchOffen(
SDNode *Parent,
1719 MachineFunction &
MF =
CurDAG->getMachineFunction();
1720 const SIMachineFunctionInfo *
Info =
MF.getInfo<SIMachineFunctionInfo>();
1722 Rsrc =
CurDAG->getRegister(
Info->getScratchRSrcReg(), MVT::v4i32);
1725 int64_t
Imm = CAddr->getSExtValue();
1726 const int64_t NullPtr =
1729 if (Imm != NullPtr) {
1732 CurDAG->getTargetConstant(Imm & ~MaxOffset,
DL, MVT::i32);
1733 MachineSDNode *MovHighBits =
CurDAG->getMachineNode(
1734 AMDGPU::V_MOV_B32_e32,
DL, MVT::i32, HighBits);
1735 VAddr =
SDValue(MovHighBits, 0);
1737 SOffset =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1738 ImmOffset =
CurDAG->getTargetConstant(Imm & MaxOffset,
DL, MVT::i32);
1743 if (
CurDAG->isBaseWithConstantOffset(Addr)) {
1764 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
1765 if (
TII->isLegalMUBUFImmOffset(C1) &&
1766 (!Subtarget->privateMemoryResourceIsRangeChecked() ||
1767 CurDAG->SignBitIsZero(N0))) {
1768 std::tie(VAddr, SOffset) = foldFrameIndex(N0);
1769 ImmOffset =
CurDAG->getTargetConstant(C1,
DL, MVT::i32);
1775 std::tie(VAddr, SOffset) = foldFrameIndex(Addr);
1776 ImmOffset =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1784 if (!
Reg.isPhysical())
1786 const auto *RC =
TRI.getPhysRegBaseClass(
Reg);
1787 return RC &&
TRI.isSGPRClass(RC);
1790bool AMDGPUDAGToDAGISel::SelectMUBUFScratchOffset(
SDNode *Parent,
1795 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
1796 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
1797 MachineFunction &
MF =
CurDAG->getMachineFunction();
1798 const SIMachineFunctionInfo *
Info =
MF.getInfo<SIMachineFunctionInfo>();
1803 SRsrc =
CurDAG->getRegister(
Info->getScratchRSrcReg(), MVT::v4i32);
1809 ConstantSDNode *CAddr;
1822 SOffset =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1827 SRsrc =
CurDAG->getRegister(
Info->getScratchRSrcReg(), MVT::v4i32);
1833bool AMDGPUDAGToDAGISel::SelectMUBUFOffset(
SDValue Addr,
SDValue &SRsrc,
1836 SDValue Ptr, VAddr, Offen, Idxen, Addr64;
1837 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
1839 if (!SelectMUBUF(Addr, Ptr, VAddr, SOffset,
Offset, Offen, Idxen, Addr64))
1845 uint64_t Rsrc =
TII->getDefaultRsrcDataFormat() |
1858bool AMDGPUDAGToDAGISel::SelectBUFSOffset(
SDValue ByteOffsetNode,
1860 if (Subtarget->hasRestrictedSOffset() &&
isNullConstant(ByteOffsetNode)) {
1861 SOffset =
CurDAG->getRegister(AMDGPU::SGPR_NULL, MVT::i32);
1865 SOffset = ByteOffsetNode;
1883bool AMDGPUDAGToDAGISel::SelectFlatOffsetImpl(
1887 int64_t OffsetVal = 0;
1891 bool CanHaveFlatSegmentOffsetBug =
1892 Subtarget->hasFlatSegmentOffsetBug() &&
1893 FlatVariant == FlatAddrSpace::FLAT &&
1896 if (Subtarget->hasFlatInstOffsets() && !CanHaveFlatSegmentOffsetBug) {
1898 if (isBaseWithConstantOffset64(Addr, N0, N1) &&
1899 (FlatVariant != FlatAddrSpace::FlatScratch ||
1900 isFlatScratchBaseLegal(Addr))) {
1908 if (COffsetVal == 0 || FlatVariant != FlatAddrSpace::FLAT || IsInBounds) {
1909 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
1910 if (
TII->isLegalFLATOffset(COffsetVal, AS, FlatVariant)) {
1912 OffsetVal = COffsetVal;
1925 uint64_t RemainderOffset;
1927 std::tie(OffsetVal, RemainderOffset) =
1928 TII->splitFlatOffset(COffsetVal, AS, FlatVariant);
1931 getMaterializedScalarImm32(
Lo_32(RemainderOffset),
DL);
1938 unsigned AddOp = AMDGPU::V_ADD_CO_U32_e32;
1939 if (Subtarget->hasAddNoCarryInsts()) {
1940 AddOp = AMDGPU::V_ADD_U32_e64;
1949 CurDAG->getTargetConstant(AMDGPU::sub0,
DL, MVT::i32);
1951 CurDAG->getTargetConstant(AMDGPU::sub1,
DL, MVT::i32);
1953 SDNode *N0Lo =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
1954 DL, MVT::i32, N0, Sub0);
1955 SDNode *N0Hi =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
1956 DL, MVT::i32, N0, Sub1);
1959 getMaterializedScalarImm32(
Hi_32(RemainderOffset),
DL);
1961 SDVTList VTs =
CurDAG->getVTList(MVT::i32, MVT::i1);
1964 CurDAG->getMachineNode(AMDGPU::V_ADD_CO_U32_e64,
DL, VTs,
1965 {AddOffsetLo,
SDValue(N0Lo, 0), Clamp});
1967 SDNode *Addc =
CurDAG->getMachineNode(
1968 AMDGPU::V_ADDC_U32_e64,
DL, VTs,
1972 CurDAG->getTargetConstant(AMDGPU::VReg_64RegClassID,
DL,
1977 MVT::i64, RegSequenceArgs),
1986 Offset =
CurDAG->getSignedTargetConstant(OffsetVal, SDLoc(), MVT::i32);
1990bool AMDGPUDAGToDAGISel::SelectFlatOffset(
SDNode *
N,
SDValue Addr,
1993 return SelectFlatOffsetImpl(
N, Addr, VAddr,
Offset,
1997bool AMDGPUDAGToDAGISel::SelectGlobalOffset(
SDNode *
N,
SDValue Addr,
2000 return SelectFlatOffsetImpl(
N, Addr, VAddr,
Offset,
2004bool AMDGPUDAGToDAGISel::SelectScratchOffset(
SDNode *
N,
SDValue Addr,
2007 return SelectFlatOffsetImpl(
N, Addr, VAddr,
Offset,
2015 if (
Op.getValueType() == MVT::i32)
2030bool AMDGPUDAGToDAGISel::SelectGlobalSAddr(
SDNode *
N,
SDValue Addr,
2033 bool NeedIOffset)
const {
2035 int64_t ImmOffset = 0;
2036 ScaleOffset =
false;
2042 if (isBaseWithConstantOffset64(Addr,
LHS,
RHS)) {
2044 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
2048 FlatAddrSpace::FlatGlobal)) {
2050 ImmOffset = COffsetVal;
2051 }
else if (!
LHS->isDivergent()) {
2052 if (COffsetVal > 0) {
2057 int64_t SplitImmOffset = 0, RemainderOffset = COffsetVal;
2059 std::tie(SplitImmOffset, RemainderOffset) =
TII->splitFlatOffset(
2063 if (Subtarget->hasSignedGVSOffset() ?
isInt<32>(RemainderOffset)
2065 SDNode *VMov =
CurDAG->getMachineNode(
2066 AMDGPU::V_MOV_B32_e32, SL, MVT::i32,
2067 CurDAG->getTargetConstant(RemainderOffset, SDLoc(), MVT::i32));
2070 Offset =
CurDAG->getTargetConstant(SplitImmOffset, SDLoc(), MVT::i32);
2080 unsigned NumLiterals =
2081 !
TII->isInlineConstant(APInt(32,
Lo_32(COffsetVal))) +
2082 !
TII->isInlineConstant(APInt(32,
Hi_32(COffsetVal)));
2083 if (Subtarget->getConstantBusLimit(AMDGPU::V_ADD_U32_e64) > NumLiterals)
2092 if (!
LHS->isDivergent()) {
2095 ScaleOffset = SelectScaleOffset(
N,
RHS, Subtarget->hasSignedGVSOffset());
2097 RHS, Subtarget->hasSignedGVSOffset(),
CurDAG)) {
2104 if (!SAddr && !
RHS->isDivergent()) {
2106 ScaleOffset = SelectScaleOffset(
N,
LHS, Subtarget->hasSignedGVSOffset());
2108 LHS, Subtarget->hasSignedGVSOffset(),
CurDAG)) {
2115 Offset =
CurDAG->getSignedTargetConstant(ImmOffset, SDLoc(), MVT::i32);
2120 if (Subtarget->hasScaleOffset() &&
2121 (Addr.
getOpcode() == (Subtarget->hasSignedGVSOffset()
2136 Offset =
CurDAG->getTargetConstant(ImmOffset, SDLoc(), MVT::i32);
2148 CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32, SDLoc(Addr), MVT::i32,
2149 CurDAG->getTargetConstant(0, SDLoc(), MVT::i32));
2151 Offset =
CurDAG->getSignedTargetConstant(ImmOffset, SDLoc(), MVT::i32);
2155bool AMDGPUDAGToDAGISel::SelectGlobalSAddr(
SDNode *
N,
SDValue Addr,
2160 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset,
Offset, ScaleOffset))
2168bool AMDGPUDAGToDAGISel::SelectGlobalSAddrCPol(
SDNode *
N,
SDValue Addr,
2173 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset,
Offset, ScaleOffset))
2178 N->getConstantOperandVal(
N->getNumOperands() - 1) & ~AMDGPU::CPol::SCAL;
2184bool AMDGPUDAGToDAGISel::SelectGlobalSAddrCPolM0(
SDNode *
N,
SDValue Addr,
2190 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset,
Offset, ScaleOffset))
2195 N->getConstantOperandVal(
N->getNumOperands() - 2) & ~AMDGPU::CPol::SCAL;
2201bool AMDGPUDAGToDAGISel::SelectGlobalSAddrGLC(
SDNode *
N,
SDValue Addr,
2206 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset,
Offset, ScaleOffset))
2210 CPol =
CurDAG->getTargetConstant(CPolVal, SDLoc(), MVT::i32);
2214bool AMDGPUDAGToDAGISel::SelectGlobalSAddrNoIOffset(
SDNode *
N,
SDValue Addr,
2220 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset, DummyOffset, ScaleOffset,
2226 N->getConstantOperandVal(
N->getNumOperands() - 1) & ~AMDGPU::CPol::SCAL;
2232bool AMDGPUDAGToDAGISel::SelectGlobalSAddrNoIOffsetM0(
SDNode *
N,
SDValue Addr,
2238 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset, DummyOffset, ScaleOffset,
2259 FI->getValueType(0));
2269bool AMDGPUDAGToDAGISel::SelectScratchSAddr(
SDNode *Parent,
SDValue Addr,
2278 int64_t COffsetVal = 0;
2280 if (
CurDAG->isBaseWithConstantOffset(Addr) && isFlatScratchBaseLegal(Addr)) {
2289 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
2292 FlatAddrSpace::FlatScratch)) {
2293 int64_t SplitImmOffset, RemainderOffset;
2294 std::tie(SplitImmOffset, RemainderOffset) =
TII->splitFlatOffset(
2297 COffsetVal = SplitImmOffset;
2301 ? getMaterializedScalarImm32(
Lo_32(RemainderOffset),
DL)
2302 :
CurDAG->getSignedTargetConstant(RemainderOffset,
DL, MVT::i32);
2303 SAddr =
SDValue(
CurDAG->getMachineNode(AMDGPU::S_ADD_I32,
DL, MVT::i32,
2308 Offset =
CurDAG->getSignedTargetConstant(COffsetVal,
DL, MVT::i32);
2314bool AMDGPUDAGToDAGISel::checkFlatScratchSVSSwizzleBug(
2316 if (!Subtarget->hasFlatScratchSVSSwizzleBug())
2322 KnownBits VKnown =
CurDAG->computeKnownBits(VAddr);
2329 return (VMax & 3) + (
SMax & 3) >= 4;
2332bool AMDGPUDAGToDAGISel::SelectScratchSVAddr(
SDNode *
N,
SDValue Addr,
2336 int64_t ImmOffset = 0;
2340 if (isBaseWithConstantOffset64(Addr,
LHS,
RHS)) {
2342 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
2347 ImmOffset = COffsetVal;
2348 }
else if (!
LHS->isDivergent() && COffsetVal > 0) {
2352 int64_t SplitImmOffset, RemainderOffset;
2353 std::tie(SplitImmOffset, RemainderOffset) =
2358 SDNode *VMov =
CurDAG->getMachineNode(
2359 AMDGPU::V_MOV_B32_e32, SL, MVT::i32,
2360 CurDAG->getTargetConstant(RemainderOffset, SDLoc(), MVT::i32));
2363 if (!isFlatScratchBaseLegal(Addr))
2365 if (checkFlatScratchSVSSwizzleBug(VAddr, SAddr, SplitImmOffset))
2367 Offset =
CurDAG->getTargetConstant(SplitImmOffset, SDLoc(), MVT::i32);
2368 CPol =
CurDAG->getTargetConstant(0, SDLoc(), MVT::i32);
2380 if (!
LHS->isDivergent() &&
RHS->isDivergent()) {
2383 }
else if (!
RHS->isDivergent() &&
LHS->isDivergent()) {
2390 if (OrigAddr != Addr) {
2391 if (!isFlatScratchBaseLegalSVImm(OrigAddr))
2394 if (!isFlatScratchBaseLegalSV(OrigAddr))
2398 if (checkFlatScratchSVSSwizzleBug(VAddr, SAddr, ImmOffset))
2401 Offset =
CurDAG->getSignedTargetConstant(ImmOffset, SDLoc(), MVT::i32);
2403 bool ScaleOffset = SelectScaleOffset(
N, VAddr,
true );
2412bool AMDGPUDAGToDAGISel::isSOffsetLegalWithImmOffset(
SDValue *SOffset,
2415 int64_t ImmOffset)
const {
2416 if (!IsBuffer && !Imm32Only && ImmOffset < 0 &&
2418 KnownBits SKnown =
CurDAG->computeKnownBits(*SOffset);
2430 bool IsSigned)
const {
2431 bool ScaleOffset =
false;
2432 if (!Subtarget->hasScaleOffset() || !
Offset)
2446 (IsSigned &&
Offset.getOpcode() == AMDGPUISD::MUL_I24) ||
2447 Offset.getOpcode() == AMDGPUISD::MUL_U24 ||
2448 (
Offset.isMachineOpcode() &&
2449 Offset.getMachineOpcode() ==
2450 (IsSigned ? AMDGPU::S_MUL_I64_I32_PSEUDO
2451 : AMDGPU::S_MUL_U64_U32_PSEUDO))) {
2453 ScaleOffset =
C->getZExtValue() ==
Size;
2465bool AMDGPUDAGToDAGISel::SelectSMRDOffset(
SDNode *
N,
SDValue ByteOffsetNode,
2467 bool Imm32Only,
bool IsBuffer,
2468 bool HasSOffset, int64_t ImmOffset,
2469 bool *ScaleOffset)
const {
2471 "Cannot match both soffset and offset at the same time!");
2476 *ScaleOffset = SelectScaleOffset(
N, ByteOffsetNode,
false );
2486 *SOffset = ByteOffsetNode;
2487 return isSOffsetLegalWithImmOffset(SOffset, Imm32Only, IsBuffer,
2493 return isSOffsetLegalWithImmOffset(SOffset, Imm32Only, IsBuffer,
2500 SDLoc SL(ByteOffsetNode);
2504 int64_t ByteOffset = IsBuffer ?
C->getZExtValue() :
C->getSExtValue();
2506 *Subtarget, ByteOffset, IsBuffer, HasSOffset);
2507 if (EncodedOffset &&
Offset && !Imm32Only) {
2508 *
Offset =
CurDAG->getSignedTargetConstant(*EncodedOffset, SL, MVT::i32);
2517 if (EncodedOffset &&
Offset && Imm32Only) {
2518 *
Offset =
CurDAG->getTargetConstant(*EncodedOffset, SL, MVT::i32);
2526 SDValue C32Bit =
CurDAG->getTargetConstant(ByteOffset, SL, MVT::i32);
2528 CurDAG->getMachineNode(AMDGPU::S_MOV_B32, SL, MVT::i32, C32Bit), 0);
2535SDValue AMDGPUDAGToDAGISel::Expand32BitAddress(
SDValue Addr)
const {
2542 const MachineFunction &
MF =
CurDAG->getMachineFunction();
2543 const SIMachineFunctionInfo *
Info =
MF.getInfo<SIMachineFunctionInfo>();
2544 unsigned AddrHiVal =
Info->get32BitAddressHighBits();
2545 SDValue AddrHi =
CurDAG->getTargetConstant(AddrHiVal, SL, MVT::i32);
2548 CurDAG->getTargetConstant(AMDGPU::SReg_64_XEXECRegClassID, SL, MVT::i32),
2550 CurDAG->getTargetConstant(AMDGPU::sub0, SL, MVT::i32),
2551 SDValue(
CurDAG->getMachineNode(AMDGPU::S_MOV_B32, SL, MVT::i32, AddrHi),
2553 CurDAG->getTargetConstant(AMDGPU::sub1, SL, MVT::i32),
2556 return SDValue(
CurDAG->getMachineNode(AMDGPU::REG_SEQUENCE, SL, MVT::i64,
2563bool AMDGPUDAGToDAGISel::SelectSMRDBaseOffset(
SDNode *
N,
SDValue Addr,
2566 bool IsBuffer,
bool HasSOffset,
2568 bool *ScaleOffset)
const {
2570 assert(!Imm32Only && !IsBuffer);
2573 if (!SelectSMRDBaseOffset(
N, Addr,
B,
nullptr,
Offset,
false,
false,
true))
2578 ImmOff =
C->getSExtValue();
2580 return SelectSMRDBaseOffset(
N,
B, SBase, SOffset,
nullptr,
false,
false,
2581 true, ImmOff, ScaleOffset);
2601 if (SelectSMRDOffset(
N, N1, SOffset,
Offset, Imm32Only, IsBuffer, HasSOffset,
2602 ImmOffset, ScaleOffset)) {
2606 if (SelectSMRDOffset(
N, N0, SOffset,
Offset, Imm32Only, IsBuffer, HasSOffset,
2607 ImmOffset, ScaleOffset)) {
2616 bool Imm32Only,
bool *ScaleOffset)
const {
2617 if (SelectSMRDBaseOffset(
N, Addr, SBase, SOffset,
Offset, Imm32Only,
2620 SBase = Expand32BitAddress(SBase);
2625 SBase = Expand32BitAddress(Addr);
2626 *
Offset =
CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
2633bool AMDGPUDAGToDAGISel::SelectSMRDImm(
SDValue Addr,
SDValue &SBase,
2635 return SelectSMRD(
nullptr, Addr, SBase,
nullptr,
2639bool AMDGPUDAGToDAGISel::SelectSMRDImm32(
SDValue Addr,
SDValue &SBase,
2642 return SelectSMRD(
nullptr, Addr, SBase,
nullptr,
2649 if (!SelectSMRD(
N, Addr, SBase, &SOffset,
nullptr,
2650 false, &ScaleOffset))
2654 SDLoc(
N), MVT::i32);
2658bool AMDGPUDAGToDAGISel::SelectSMRDSgprImm(
SDNode *
N,
SDValue Addr,
2663 if (!SelectSMRD(
N, Addr, SBase, &SOffset, &
Offset,
false, &ScaleOffset))
2667 SDLoc(
N), MVT::i32);
2672 return SelectSMRDOffset(
nullptr,
N,
nullptr, &
Offset,
2676bool AMDGPUDAGToDAGISel::SelectSMRDBufferImm32(
SDValue N,
2679 return SelectSMRDOffset(
nullptr,
N,
nullptr, &
Offset,
2683bool AMDGPUDAGToDAGISel::SelectSMRDBufferSgprImm(
SDValue N,
SDValue &SOffset,
2687 return N.getValueType() == MVT::i32 &&
2688 SelectSMRDBaseOffset(
nullptr,
N, SOffset,
2693bool AMDGPUDAGToDAGISel::SelectMOVRELOffset(
SDValue Index,
2698 if (
CurDAG->isBaseWithConstantOffset(Index)) {
2723SDNode *AMDGPUDAGToDAGISel::getBFE32(
bool IsSigned,
const SDLoc &
DL,
2727 unsigned Opcode = IsSigned ? AMDGPU::V_BFE_I32_e64 : AMDGPU::V_BFE_U32_e64;
2731 return CurDAG->getMachineNode(Opcode,
DL, MVT::i32, Val, Off, W);
2733 unsigned Opcode = IsSigned ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32;
2737 uint32_t PackedVal =
Offset | (Width << 16);
2738 SDValue PackedConst =
CurDAG->getTargetConstant(PackedVal,
DL, MVT::i32);
2740 return CurDAG->getMachineNode(Opcode,
DL, MVT::i32, Val, PackedConst);
2743void AMDGPUDAGToDAGISel::SelectS_BFEFromShifts(
SDNode *
N) {
2748 const SDValue &Shl =
N->getOperand(0);
2753 uint32_t BVal =
B->getZExtValue();
2754 uint32_t CVal =
C->getZExtValue();
2756 if (0 < BVal && BVal <= CVal && CVal < 32) {
2766void AMDGPUDAGToDAGISel::SelectS_BFE(
SDNode *
N) {
2767 switch (
N->getOpcode()) {
2769 if (
N->getOperand(0).getOpcode() ==
ISD::SRL) {
2772 const SDValue &Srl =
N->getOperand(0);
2776 if (Shift && Mask) {
2778 uint32_t MaskVal =
Mask->getZExtValue();
2790 if (
N->getOperand(0).getOpcode() ==
ISD::AND) {
2797 if (Shift && Mask) {
2799 uint32_t MaskVal =
Mask->getZExtValue() >> ShiftVal;
2808 }
else if (
N->getOperand(0).getOpcode() ==
ISD::SHL) {
2809 SelectS_BFEFromShifts(
N);
2814 if (
N->getOperand(0).getOpcode() ==
ISD::SHL) {
2815 SelectS_BFEFromShifts(
N);
2830 unsigned Width =
cast<VTSDNode>(
N->getOperand(1))->getVT().getSizeInBits();
2840bool AMDGPUDAGToDAGISel::isCBranchSCC(
const SDNode *
N)
const {
2842 if (!
N->hasOneUse())
2852 MVT VT =
Cond.getOperand(0).getSimpleValueType();
2856 if (VT == MVT::i64) {
2859 Subtarget->hasScalarCompareEq64();
2862 if ((VT == MVT::f16 || VT == MVT::f32) && Subtarget->hasSALUFloatInsts())
2895void AMDGPUDAGToDAGISel::SelectBRCOND(
SDNode *
N) {
2898 if (
Cond.isUndef()) {
2899 CurDAG->SelectNodeTo(
N, AMDGPU::SI_BR_UNDEF, MVT::Other,
2900 N->getOperand(2),
N->getOperand(0));
2904 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
2906 bool UseSCCBr = isCBranchSCC(
N) && isUniformBr(
N);
2907 bool AndExec = !UseSCCBr;
2908 bool Negate =
false;
2911 Cond->getOperand(0)->getOpcode() == AMDGPUISD::SETCC) {
2926 bool NegatedBallot =
false;
2929 UseSCCBr = !BallotCond->isDivergent();
2930 Negate = Negate ^ NegatedBallot;
2945 UseSCCBr ? (Negate ? AMDGPU::S_CBRANCH_SCC0 : AMDGPU::S_CBRANCH_SCC1)
2946 : (Negate ? AMDGPU::S_CBRANCH_VCCZ : AMDGPU::S_CBRANCH_VCCNZ);
2947 Register CondReg = UseSCCBr ? AMDGPU::SCC :
TRI->getVCC();
2966 Subtarget->isWave32() ? AMDGPU::S_AND_B32 : AMDGPU::S_AND_B64, SL,
2968 CurDAG->getRegister(Subtarget->isWave32() ? AMDGPU::EXEC_LO
2976 CurDAG->SelectNodeTo(
N, BrOp, MVT::Other,
2981void AMDGPUDAGToDAGISel::SelectFP_EXTEND(
SDNode *
N) {
2982 if (Subtarget->hasSALUFloatInsts() &&
N->getValueType(0) == MVT::f32 &&
2983 !
N->isDivergent()) {
2985 if (Src.getValueType() == MVT::f16) {
2987 CurDAG->SelectNodeTo(
N, AMDGPU::S_CVT_HI_F32_F16,
N->getVTList(),
2997void AMDGPUDAGToDAGISel::SelectDSAppendConsume(
SDNode *
N,
unsigned IntrID) {
3000 unsigned Opc = IntrID == Intrinsic::amdgcn_ds_append ?
3001 AMDGPU::DS_APPEND : AMDGPU::DS_CONSUME;
3006 MachineMemOperand *MMO =
M->getMemOperand();
3010 if (
CurDAG->isBaseWithConstantOffset(Ptr)) {
3015 if (isDSOffsetLegal(PtrBase, OffsetVal.
getZExtValue())) {
3016 N = glueCopyToM0(
N, PtrBase);
3017 Offset =
CurDAG->getTargetConstant(OffsetVal, SDLoc(), MVT::i32);
3022 N = glueCopyToM0(
N, Ptr);
3023 Offset =
CurDAG->getTargetConstant(0, SDLoc(), MVT::i32);
3028 CurDAG->getTargetConstant(IsGDS, SDLoc(), MVT::i32),
3033 SDNode *Selected =
CurDAG->SelectNodeTo(
N,
Opc,
N->getVTList(),
Ops);
3039void AMDGPUDAGToDAGISel::SelectDSBvhStackIntrinsic(
SDNode *
N,
unsigned IntrID) {
3042 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
3043 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
3044 Opc = AMDGPU::DS_BVH_STACK_RTN_B32;
3046 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
3047 Opc = AMDGPU::DS_BVH_STACK_PUSH8_POP1_RTN_B32;
3049 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn:
3050 Opc = AMDGPU::DS_BVH_STACK_PUSH8_POP2_RTN_B64;
3053 SDValue Ops[] = {
N->getOperand(2),
N->getOperand(3),
N->getOperand(4),
3054 N->getOperand(5),
N->getOperand(0)};
3057 MachineMemOperand *MMO =
M->getMemOperand();
3058 SDNode *Selected =
CurDAG->SelectNodeTo(
N,
Opc,
N->getVTList(),
Ops);
3062void AMDGPUDAGToDAGISel::SelectTensorLoadStore(
SDNode *
N,
unsigned IntrID) {
3063 bool IsLoad = IntrID == Intrinsic::amdgcn_tensor_load_to_lds;
3065 IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d4 : AMDGPU::TENSOR_STORE_FROM_LDS_d4;
3077 Opc = IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d2
3078 : AMDGPU::TENSOR_STORE_FROM_LDS_d2;
3090 (void)
CurDAG->SelectNodeTo(
N,
Opc, MVT::Other, TensorOps);
3095 case Intrinsic::amdgcn_ds_gws_init:
3096 return AMDGPU::DS_GWS_INIT;
3097 case Intrinsic::amdgcn_ds_gws_barrier:
3098 return AMDGPU::DS_GWS_BARRIER;
3099 case Intrinsic::amdgcn_ds_gws_sema_v:
3100 return AMDGPU::DS_GWS_SEMA_V;
3101 case Intrinsic::amdgcn_ds_gws_sema_br:
3102 return AMDGPU::DS_GWS_SEMA_BR;
3103 case Intrinsic::amdgcn_ds_gws_sema_p:
3104 return AMDGPU::DS_GWS_SEMA_P;
3105 case Intrinsic::amdgcn_ds_gws_sema_release_all:
3106 return AMDGPU::DS_GWS_SEMA_RELEASE_ALL;
3112void AMDGPUDAGToDAGISel::SelectDS_GWS(
SDNode *
N,
unsigned IntrID) {
3113 if (!Subtarget->hasGWS() ||
3114 (IntrID == Intrinsic::amdgcn_ds_gws_sema_release_all &&
3115 !Subtarget->hasGWSSemaReleaseAll())) {
3122 const bool HasVSrc =
N->getNumOperands() == 4;
3123 assert(HasVSrc ||
N->getNumOperands() == 3);
3126 SDValue BaseOffset =
N->getOperand(HasVSrc ? 3 : 2);
3129 MachineMemOperand *MMO =
M->getMemOperand();
3142 glueCopyToM0(
N,
CurDAG->getTargetConstant(0, SL, MVT::i32));
3143 ImmOffset = ConstOffset->getZExtValue();
3145 if (
CurDAG->isBaseWithConstantOffset(BaseOffset)) {
3154 =
CurDAG->getMachineNode(AMDGPU::V_READFIRSTLANE_B32, SL, MVT::i32,
3158 =
CurDAG->getMachineNode(AMDGPU::S_LSHL_B32, SL, MVT::i32,
3160 CurDAG->getTargetConstant(16, SL, MVT::i32));
3161 glueCopyToM0(
N,
SDValue(M0Base, 0));
3165 SDValue OffsetField =
CurDAG->getTargetConstant(ImmOffset, SL, MVT::i32);
3169 const MCInstrDesc &InstrDesc =
TII->get(
Opc);
3170 int Data0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
3176 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3179 MVT DataVT =
Data.getValueType().getSimpleVT();
3180 if (
TRI->isTypeLegalForClass(*DataRC, DataVT)) {
3182 Ops.push_back(
N->getOperand(2));
3188 CurDAG->getTargetConstant(AMDGPU::sub0, SL, MVT::i32),
3190 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, SL, MVT::i32),
3192 CurDAG->getTargetConstant(AMDGPU::sub1, SL, MVT::i32)};
3195 SL, MVT::v2i32, RegSeqOps),
3200 Ops.push_back(OffsetField);
3201 Ops.push_back(Chain);
3203 SDNode *Selected =
CurDAG->SelectNodeTo(
N,
Opc,
N->getVTList(),
Ops);
3207void AMDGPUDAGToDAGISel::SelectInterpP1F16(
SDNode *
N) {
3208 if (Subtarget->getLDSBankCount() != 16) {
3238 SDVTList VTs =
CurDAG->getVTList(MVT::f32, MVT::Other);
3241 CurDAG->getMachineNode(AMDGPU::V_INTERP_MOV_F32,
DL, VTs, {
3242 CurDAG->getTargetConstant(2,
DL, MVT::i32),
3248 SDNode *InterpP1LV =
3249 CurDAG->getMachineNode(AMDGPU::V_INTERP_P1LV_F16,
DL, MVT::f32, {
3250 CurDAG->getTargetConstant(0,
DL, MVT::i32),
3254 CurDAG->getTargetConstant(0,
DL, MVT::i32),
3257 CurDAG->getTargetConstant(0,
DL, MVT::i1),
3258 CurDAG->getTargetConstant(0,
DL, MVT::i32),
3265void AMDGPUDAGToDAGISel::SelectINTRINSIC_W_CHAIN(
SDNode *
N) {
3266 unsigned IntrID =
N->getConstantOperandVal(1);
3268 case Intrinsic::amdgcn_ds_append:
3269 case Intrinsic::amdgcn_ds_consume: {
3270 if (
N->getValueType(0) != MVT::i32)
3272 SelectDSAppendConsume(
N, IntrID);
3275 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
3276 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
3277 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
3278 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn:
3279 SelectDSBvhStackIntrinsic(
N, IntrID);
3281 case Intrinsic::amdgcn_init_whole_wave:
3282 CurDAG->getMachineFunction()
3283 .getInfo<SIMachineFunctionInfo>()
3284 ->setInitWholeWave();
3291void AMDGPUDAGToDAGISel::SelectINTRINSIC_WO_CHAIN(
SDNode *
N) {
3292 unsigned IntrID =
N->getConstantOperandVal(0);
3293 unsigned Opcode = AMDGPU::INSTRUCTION_LIST_END;
3294 SDNode *ConvGlueNode =
N->getGluedNode();
3300 CurDAG->getMachineNode(TargetOpcode::CONVERGENCECTRL_GLUE, {},
3301 MVT::Glue,
SDValue(ConvGlueNode, 0));
3303 ConvGlueNode =
nullptr;
3306 case Intrinsic::amdgcn_wqm:
3307 Opcode = AMDGPU::WQM;
3309 case Intrinsic::amdgcn_softwqm:
3310 Opcode = AMDGPU::SOFT_WQM;
3312 case Intrinsic::amdgcn_wwm:
3313 case Intrinsic::amdgcn_strict_wwm:
3314 Opcode = AMDGPU::STRICT_WWM;
3316 case Intrinsic::amdgcn_strict_wqm:
3317 Opcode = AMDGPU::STRICT_WQM;
3319 case Intrinsic::amdgcn_interp_p1_f16:
3320 SelectInterpP1F16(
N);
3322 case Intrinsic::amdgcn_permlane16_swap:
3323 case Intrinsic::amdgcn_permlane32_swap: {
3324 if ((IntrID == Intrinsic::amdgcn_permlane16_swap &&
3325 !Subtarget->hasPermlane16Swap()) ||
3326 (IntrID == Intrinsic::amdgcn_permlane32_swap &&
3327 !Subtarget->hasPermlane32Swap())) {
3332 Opcode = IntrID == Intrinsic::amdgcn_permlane16_swap
3333 ? AMDGPU::V_PERMLANE16_SWAP_B32_e64
3334 : AMDGPU::V_PERMLANE32_SWAP_B32_e64;
3338 NewOps.push_back(
SDValue(ConvGlueNode, 0));
3340 bool FI =
N->getConstantOperandVal(3);
3341 NewOps[2] =
CurDAG->getTargetConstant(
3344 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(), NewOps);
3352 if (Opcode != AMDGPU::INSTRUCTION_LIST_END) {
3354 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(), {Src});
3359 NewOps.push_back(
SDValue(ConvGlueNode, 0));
3360 CurDAG->MorphNodeTo(
N,
N->getOpcode(),
N->getVTList(), NewOps);
3364void AMDGPUDAGToDAGISel::SelectINTRINSIC_VOID(
SDNode *
N) {
3365 unsigned IntrID =
N->getConstantOperandVal(1);
3367 case Intrinsic::amdgcn_ds_gws_init:
3368 case Intrinsic::amdgcn_ds_gws_barrier:
3369 case Intrinsic::amdgcn_ds_gws_sema_v:
3370 case Intrinsic::amdgcn_ds_gws_sema_br:
3371 case Intrinsic::amdgcn_ds_gws_sema_p:
3372 case Intrinsic::amdgcn_ds_gws_sema_release_all:
3373 SelectDS_GWS(
N, IntrID);
3375 case Intrinsic::amdgcn_tensor_load_to_lds:
3376 case Intrinsic::amdgcn_tensor_store_from_lds:
3377 SelectTensorLoadStore(
N, IntrID);
3386void AMDGPUDAGToDAGISel::SelectWAVE_ADDRESS(
SDNode *
N) {
3388 CurDAG->getTargetConstant(Subtarget->getWavefrontSizeLog2(), SDLoc(
N), MVT::i32);
3389 CurDAG->SelectNodeTo(
N, AMDGPU::S_LSHR_B32,
N->getVTList(),
3390 {N->getOperand(0), Log2WaveSize});
3393void AMDGPUDAGToDAGISel::SelectSTACKRESTORE(
SDNode *
N) {
3408 Subtarget->getWavefrontSizeLog2(), SL, MVT::i32);
3410 if (
N->isDivergent()) {
3411 SrcVal =
SDValue(
CurDAG->getMachineNode(AMDGPU::V_READFIRSTLANE_B32, SL,
3416 CopyVal =
SDValue(
CurDAG->getMachineNode(AMDGPU::S_LSHL_B32, SL, MVT::i32,
3417 {SrcVal, Log2WaveSize}),
3421 SDValue CopyToSP =
CurDAG->getCopyToReg(
N->getOperand(0), SL,
SP, CopyVal);
3425bool AMDGPUDAGToDAGISel::SelectVOP3ModsImpl(
SDValue In,
SDValue &Src,
3427 bool IsCanonicalizing,
3428 bool AllowAbs)
const {
3434 Src = Src.getOperand(0);
3435 }
else if (Src.getOpcode() ==
ISD::FSUB && IsCanonicalizing) {
3439 if (
LHS &&
LHS->isZero()) {
3441 Src = Src.getOperand(1);
3445 if (AllowAbs && Src.getOpcode() ==
ISD::FABS) {
3447 Src = Src.getOperand(0);
3460 if (IsCanonicalizing)
3475 EVT VT = Src.getValueType();
3477 (VT != MVT::i32 && VT != MVT::v2i32 && VT != MVT::i64))
3484 auto ReplaceSrc = [&]() ->
SDValue {
3486 return Src.getOperand(0);
3491 Src.getValueType(),
LHS, Index);
3517 if (SelectVOP3ModsImpl(In, Src, Mods,
true,
3519 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3526bool AMDGPUDAGToDAGISel::SelectVOP3ModsNonCanonicalizing(
3529 if (SelectVOP3ModsImpl(In, Src, Mods,
false,
3531 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3538bool AMDGPUDAGToDAGISel::SelectVOP3BMods(
SDValue In,
SDValue &Src,
3541 if (SelectVOP3ModsImpl(In, Src, Mods,
3544 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3551bool AMDGPUDAGToDAGISel::SelectVOP3NoMods(
SDValue In,
SDValue &Src)
const {
3559bool AMDGPUDAGToDAGISel::SelectVINTERPModsImpl(
SDValue In,
SDValue &Src,
3563 if (SelectVOP3ModsImpl(In, Src, Mods,
3568 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3575bool AMDGPUDAGToDAGISel::SelectVINTERPMods(
SDValue In,
SDValue &Src,
3577 return SelectVINTERPModsImpl(In, Src, SrcMods,
false);
3580bool AMDGPUDAGToDAGISel::SelectVINTERPModsHi(
SDValue In,
SDValue &Src,
3582 return SelectVINTERPModsImpl(In, Src, SrcMods,
true);
3585bool AMDGPUDAGToDAGISel::SelectVOP3Mods0(
SDValue In,
SDValue &Src,
3589 Clamp =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3590 Omod =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3592 return SelectVOP3Mods(In, Src, SrcMods);
3595bool AMDGPUDAGToDAGISel::SelectVOP3BMods0(
SDValue In,
SDValue &Src,
3599 Clamp =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3600 Omod =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3602 return SelectVOP3BMods(In, Src, SrcMods);
3605bool AMDGPUDAGToDAGISel::SelectVOP3OMods(
SDValue In,
SDValue &Src,
3610 Clamp =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3611 Omod =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3616bool AMDGPUDAGToDAGISel::SelectVOP3PMods(
SDValue In,
SDValue &Src,
3617 SDValue &SrcMods,
bool IsDOT)
const {
3624 Src = Src.getOperand(0);
3628 bool HasOpSel = Src.getValueSizeInBits() != 128;
3631 (!IsDOT || !Subtarget->hasDOTOpSelHazard())) {
3632 unsigned VecMods = Mods;
3634 SDValue Lo = stripBitcast(Src.getOperand(0));
3635 SDValue Hi = stripBitcast(Src.getOperand(1));
3638 Lo = stripBitcast(
Lo.getOperand(0));
3643 Hi = stripBitcast(
Hi.getOperand(0));
3655 unsigned VecSize = Src.getValueSizeInBits();
3656 Lo = stripExtractLoElt(
Lo);
3657 Hi = stripExtractLoElt(
Hi);
3659 if (
Lo.getValueSizeInBits() > VecSize) {
3660 Lo =
CurDAG->getTargetExtractSubreg(
3661 (VecSize > 32) ? AMDGPU::sub0_sub1 : AMDGPU::sub0, SDLoc(In),
3665 if (
Hi.getValueSizeInBits() > VecSize) {
3666 Hi =
CurDAG->getTargetExtractSubreg(
3667 (VecSize > 32) ? AMDGPU::sub0_sub1 : AMDGPU::sub0, SDLoc(In),
3671 assert(
Lo.getValueSizeInBits() <= VecSize &&
3672 Hi.getValueSizeInBits() <= VecSize);
3674 if (
Lo ==
Hi && !isInlineImmediate(
Lo.getNode())) {
3678 if (VecSize ==
Lo.getValueSizeInBits()) {
3680 }
else if (VecSize == 32) {
3681 Src = createVOP3PSrc32FromLo16(
Lo, Src,
CurDAG, Subtarget);
3683 assert((
Lo.getValueSizeInBits() == 32 && VecSize == 64) ||
3684 (
Lo.getValueSizeInBits() == 64 && VecSize == 128));
3688 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, SL,
3689 Lo.getValueType()), 0);
3690 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3695 auto RC =
Lo->isDivergent() ?
TRI->getVGPRClassForBitWidth(VecSize)
3696 :
TRI->getSGPRClassForBitWidth(VecSize);
3697 unsigned NumRegs =
Lo.getValueSizeInBits() == 32 ? 1 : 2;
3699 CurDAG->getTargetConstant(RC->getID(), SL, MVT::i32),
Lo,
3700 CurDAG->getTargetConstant(
TRI->getSubRegFromChannel(0, NumRegs), SL,
3702 (!HasOpSel &&
Lo->isDivergent()) ?
Lo :
Undef,
3703 CurDAG->getTargetConstant(
3704 TRI->getSubRegFromChannel(NumRegs, NumRegs), SL, MVT::i32)};
3706 Src =
SDValue(
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, SL,
3707 Src.getValueType(),
Ops), 0);
3709 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3715 .bitcastToAPInt().getZExtValue();
3717 Src =
CurDAG->getTargetConstant(
Lit, SDLoc(In), MVT::i64);
3718 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3725 Src.getNumOperands() == 2) {
3730 assert(Src.getValueSizeInBits() != 128 &&
3731 "<2 x 64> VECTOR_SHUFFLE should not be legal.");
3734 ArrayRef<int>
Mask = SVN->getMask();
3736 if (Mask[0] < 2 && Mask[1] < 2) {
3738 SDValue ShuffleSrc = SVN->getOperand(0);
3751 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3759 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3763bool AMDGPUDAGToDAGISel::SelectVOP3PModsDOT(
SDValue In,
SDValue &Src,
3765 return SelectVOP3PMods(In, Src, SrcMods,
true);
3768bool AMDGPUDAGToDAGISel::SelectVOP3PNoModsDOT(
SDValue In,
SDValue &Src)
const {
3770 SelectVOP3PMods(In, SrcTmp, SrcModsTmp,
true);
3779bool AMDGPUDAGToDAGISel::SelectVOP3PModsF32(
SDValue In,
SDValue &Src,
3781 SelectVOP3Mods(In, Src, SrcMods);
3784 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3788bool AMDGPUDAGToDAGISel::SelectVOP3PNoModsF32(
SDValue In,
SDValue &Src)
const {
3790 SelectVOP3PModsF32(In, SrcTmp, SrcModsTmp);
3799bool AMDGPUDAGToDAGISel::SelectWMMAOpSelVOP3PMods(
SDValue In,
3802 assert(
C->getAPIntValue().getBitWidth() == 1 &&
"expected i1 value");
3805 unsigned SrcVal =
C->getZExtValue();
3809 Src =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3816 unsigned DstRegClass;
3818 switch (Elts.
size()) {
3820 DstRegClass = AMDGPU::VReg_256RegClassID;
3824 DstRegClass = AMDGPU::VReg_128RegClassID;
3828 DstRegClass = AMDGPU::VReg_64RegClassID;
3836 Ops.push_back(
CurDAG->getTargetConstant(DstRegClass,
DL, MVT::i32));
3837 for (
unsigned i = 0; i < Elts.
size(); ++i) {
3838 Ops.push_back(Elts[i]);
3839 Ops.push_back(
CurDAG->getTargetConstant(
3842 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL, DstTy,
Ops);
3849 assert(
"unhandled Reg sequence size" &&
3850 (Elts.
size() == 8 || Elts.
size() == 16));
3854 for (
unsigned i = 0; i < Elts.
size(); i += 2) {
3855 SDValue LoSrc = stripExtractLoElt(stripBitcast(Elts[i]));
3860 if (Subtarget->useRealTrue16Insts()) {
3865 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, MVT::i16),
3868 emitRegSequence(*
CurDAG, AMDGPU::VGPR_32RegClassID, MVT::i32,
3869 {Elts[i],
Undef}, {AMDGPU::lo16, AMDGPU::hi16},
DL);
3870 Elts[i + 1] = emitRegSequence(*
CurDAG, AMDGPU::VGPR_32RegClassID,
3871 MVT::i32, {Elts[i + 1],
Undef},
3872 {AMDGPU::lo16, AMDGPU::hi16},
DL);
3874 SDValue PackLoLo =
CurDAG->getTargetConstant(0x05040100,
DL, MVT::i32);
3876 CurDAG->getMachineNode(AMDGPU::V_PERM_B32_e64,
DL, MVT::i32,
3877 {Elts[i + 1], Elts[i], PackLoLo});
3881 return buildRegSequence32(PackedElts,
DL);
3887 unsigned ElementSize)
const {
3888 if (ElementSize == 16)
3889 return buildRegSequence16(Elts,
DL);
3890 if (ElementSize == 32)
3891 return buildRegSequence32(Elts,
DL);
3895void AMDGPUDAGToDAGISel::selectWMMAModsNegAbs(
unsigned ModOpcode,
3899 unsigned ElementSize)
const {
3904 for (
auto El : Elts) {
3907 NegAbsElts.
push_back(El->getOperand(0));
3909 if (Elts.size() != NegAbsElts.
size()) {
3911 Src =
SDValue(buildRegSequence(Elts,
DL, ElementSize), 0);
3915 Src =
SDValue(buildRegSequence(NegAbsElts,
DL, ElementSize), 0);
3921 Src =
SDValue(buildRegSequence(Elts,
DL, ElementSize), 0);
3929 std::function<
bool(
SDValue)> ModifierCheck) {
3933 for (
unsigned i = 0; i < F16Pair->getNumOperands(); ++i) {
3934 SDValue ElF16 = stripBitcast(F16Pair->getOperand(i));
3935 if (!ModifierCheck(ElF16))
3942bool AMDGPUDAGToDAGISel::SelectWMMAModsF16Neg(
SDValue In,
SDValue &Src,
3960 Src =
SDValue(buildRegSequence16(EltsF16, SDLoc(In)), 0);
3979 Src =
SDValue(buildRegSequence32(EltsV2F16, SDLoc(In)), 0);
3985 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3989bool AMDGPUDAGToDAGISel::SelectWMMAModsF16NegAbs(
SDValue In,
SDValue &Src,
4000 if (EltsF16.
empty())
4010 selectWMMAModsNegAbs(ModOpcode, Mods, EltsF16, Src, SDLoc(In), 16);
4020 if (EltsV2F16.
empty())
4029 selectWMMAModsNegAbs(ModOpcode, Mods, EltsV2F16, Src, SDLoc(In), 32);
4032 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4036bool AMDGPUDAGToDAGISel::SelectWMMAModsF32NegAbs(
SDValue In,
SDValue &Src,
4046 unsigned ModOpcode =
4057 selectWMMAModsNegAbs(ModOpcode, Mods, EltsF32, Src, SDLoc(In), 32);
4060 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4064bool AMDGPUDAGToDAGISel::SelectWMMAVISrc(
SDValue In,
SDValue &Src)
const {
4066 BitVector UndefElements;
4068 if (isInlineImmediate(
Splat.getNode())) {
4070 unsigned Imm =
C->getAPIntValue().getSExtValue();
4071 Src =
CurDAG->getTargetConstant(Imm, SDLoc(In), MVT::i32);
4075 unsigned Imm =
C->getValueAPF().bitcastToAPInt().getSExtValue();
4076 Src =
CurDAG->getTargetConstant(Imm, SDLoc(In), MVT::i32);
4084 SDValue SplatSrc32 = stripBitcast(In);
4086 if (
SDValue Splat32 = SplatSrc32BV->getSplatValue()) {
4087 SDValue SplatSrc16 = stripBitcast(Splat32);
4090 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
4091 std::optional<APInt> RawValue;
4093 RawValue =
C->getValueAPF().bitcastToAPInt();
4095 RawValue =
C->getAPIntValue();
4097 if (RawValue.has_value()) {
4098 EVT VT =
In.getValueType().getScalarType();
4104 if (
TII->isInlineConstant(FloatVal)) {
4105 Src =
CurDAG->getTargetConstant(RawValue.value(), SDLoc(In),
4110 if (
TII->isInlineConstant(RawValue.value())) {
4111 Src =
CurDAG->getTargetConstant(RawValue.value(), SDLoc(In),
4124 if (
CurDAG->isConstantIntBuildVectorOrConstantInt(SplatSrc32)) {
4129 int64_t LoImm = Lo32->getAPIntValue().getSExtValue();
4130 int64_t HiImm = Hi32->getAPIntValue().getSExtValue();
4131 int64_t Imm64I = (HiImm << 32) + LoImm;
4133 if (!isInlineImmediate(APInt(64, Imm64I)))
4136 }
else if (Imm64I != Imm64)
4140 Src =
CurDAG->getTargetConstant(Imm64, SDLoc(In), MVT::i64);
4147bool AMDGPUDAGToDAGISel::SelectSWMMACIndex8(
SDValue In,
SDValue &Src,
4153 const llvm::SDValue &ShiftSrc =
In.getOperand(0);
4162 IndexKey =
CurDAG->getTargetConstant(
Key, SDLoc(In), MVT::i32);
4166bool AMDGPUDAGToDAGISel::SelectSWMMACIndex16(
SDValue In,
SDValue &Src,
4172 const llvm::SDValue &ShiftSrc =
In.getOperand(0);
4181 IndexKey =
CurDAG->getTargetConstant(
Key, SDLoc(In), MVT::i32);
4185bool AMDGPUDAGToDAGISel::SelectSWMMACIndex32(
SDValue In,
SDValue &Src,
4193 const SDValue &ExtendSrc =
In.getOperand(0);
4197 const SDValue &CastSrc =
In.getOperand(0);
4201 if (Zero &&
Zero->getZExtValue() == 0)
4212 Src = ExtractVecEltSrc;
4216 IndexKey =
CurDAG->getTargetConstant(
Key, SDLoc(In), MVT::i32);
4220bool AMDGPUDAGToDAGISel::SelectVOP3OpSel(
SDValue In,
SDValue &Src,
4224 SrcMods =
CurDAG->getTargetConstant(0, SDLoc(In), MVT::i32);
4228bool AMDGPUDAGToDAGISel::SelectVOP3OpSelMods(
SDValue In,
SDValue &Src,
4231 return SelectVOP3Mods(In, Src, SrcMods);
4243 Op =
Op.getOperand(0);
4245 IsExtractHigh =
false;
4248 if (!Low16 || !Low16->isZero())
4250 Op = stripBitcast(
Op.getOperand(1));
4251 if (
Op.getValueType() != MVT::bf16)
4256 if (
Op.getValueType() != MVT::i32)
4261 if (Mask->getZExtValue() == 0xffff0000) {
4262 IsExtractHigh =
true;
4263 return Op.getOperand(0);
4272 return Op.getOperand(0);
4281bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixModsImpl(
SDValue In,
SDValue &Src,
4285 SelectVOP3ModsImpl(In, Src, Mods);
4287 bool IsExtractHigh =
false;
4289 Src = Src.getOperand(0);
4290 }
else if (VT == MVT::bf16) {
4298 if (Src.getValueType() != VT &&
4299 (VT != MVT::bf16 || Src.getValueType() != MVT::i32))
4302 Src = stripBitcast(Src);
4308 SelectVOP3ModsImpl(Src, Src, ModsTmp);
4323 if (Src.getValueSizeInBits() == 16) {
4332 Src.getOperand(0).getValueType() == MVT::i32) {
4333 Src = Src.getOperand(0);
4337 if (Subtarget->useRealTrue16Insts())
4339 Src = createVOP3PSrc32FromLo16(Src, In,
CurDAG, Subtarget);
4340 }
else if (IsExtractHigh)
4346bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixModsExt(
SDValue In,
SDValue &Src,
4349 if (!SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::f16))
4351 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4355bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixMods(
SDValue In,
SDValue &Src,
4358 SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::f16);
4359 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4363bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixBF16ModsExt(
SDValue In,
SDValue &Src,
4366 if (!SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::bf16))
4368 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4372bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixBF16Mods(
SDValue In,
SDValue &Src,
4375 SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::bf16);
4376 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4384 unsigned NumOpcodes = 0;
4397 const uint8_t SrcBits[3] = { 0xf0, 0xcc, 0xaa };
4400 if (
C->isAllOnes()) {
4410 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4424 if (Src.size() == 3) {
4430 if (
C->isAllOnes()) {
4432 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4433 if (Src[
I] ==
LHS) {
4445 Bits = SrcBits[Src.size()];
4450 switch (In.getOpcode()) {
4458 if (!getOperandBits(
LHS, LHSBits) ||
4459 !getOperandBits(
RHS, RHSBits)) {
4460 Src = std::move(Backup);
4461 return std::make_pair(0, 0);
4482 uint8_t LHSBitsOrig = LHSBits;
4483 uint8_t RHSBitsOrig = RHSBits;
4487 NumOpcodes += LHSOp.first;
4488 LHSBits = LHSOp.second;
4495 NumOpcodes += RHSOp.first;
4496 RHSBits = RHSOp.second;
4500 auto dependsOnSlot = [](
uint8_t TT,
int Slot) ->
bool {
4501 if (Slot < 0 || Slot > 2)
4503 const uint8_t Masks[3] = {0x0f, 0x33, 0x55};
4504 const int Shifts[3] = {4, 2, 1};
4505 return ((TT ^ (TT >> Shifts[Slot])) & Masks[Slot]) != 0;
4511 const uint8_t SrcBitsConst[3] = {0xf0, 0xcc, 0xaa};
4518 NegatedInner =
Op.getOperand(0);
4519 for (
int I = 0;
I < (int)S.size();
I++) {
4520 if (Bits == SrcBitsConst[
I] && S[
I] ==
Op)
4522 if (IsNegationOp && Bits == (
uint8_t)~SrcBitsConst[
I] &&
4523 S[
I] == NegatedInner)
4534 for (
int I = 0;
I < (int)SrcAfterLHS.
size() &&
I < 3;
I++) {
4535 if (
I < (
int)Src.size() && Src[
I] != SrcAfterLHS[
I] &&
4536 dependsOnSlot(LHSBits,
I)) {
4545 if (!Stale && !RHSOp.first) {
4546 int Slot = findSlot(RHSBitsOrig,
RHS, SrcBeforeRecurse);
4548 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4554 if (!Stale && !LHSOp.first) {
4555 int Slot = findSlot(LHSBitsOrig,
LHS, SrcBeforeRecurse);
4557 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4562 Src = std::move(SrcBeforeRecurse);
4563 LHSBits = LHSBitsOrig;
4564 RHSBits = RHSBitsOrig;
4570 return std::make_pair(0, 0);
4574 switch (In.getOpcode()) {
4576 TTbl = LHSBits & RHSBits;
4579 TTbl = LHSBits | RHSBits;
4582 TTbl = LHSBits ^ RHSBits;
4588 return std::make_pair(NumOpcodes + 1, TTbl);
4595 unsigned NumOpcodes;
4597 std::tie(NumOpcodes, TTbl) =
BitOp3_Op(In, Src);
4601 if (NumOpcodes < 2 || Src.empty())
4607 if (NumOpcodes < 4 && !In->isDivergent())
4610 if (NumOpcodes == 2 &&
In.getValueType() == MVT::i32) {
4615 (
In.getOperand(0).getOpcode() ==
In.getOpcode() ||
4616 In.getOperand(1).getOpcode() ==
In.getOpcode()))
4630 while (Src.size() < 3)
4631 Src.push_back(Src[0]);
4637 Tbl =
CurDAG->getTargetConstant(TTbl, SDLoc(In), MVT::i32);
4643 return CurDAG->getPOISON(MVT::i32);
4646 return CurDAG->getUNDEF(MVT::i32);
4650 return CurDAG->getConstant(
C->getZExtValue() << 16, SL, MVT::i32);
4655 return CurDAG->getConstant(
4656 C->getValueAPF().bitcastToAPInt().getZExtValue() << 16, SL, MVT::i32);
4666bool AMDGPUDAGToDAGISel::isVGPRImm(
const SDNode *
N)
const {
4667 assert(
CurDAG->getTarget().getTargetTriple().isAMDGCN());
4669 const SIRegisterInfo *SIRI = Subtarget->getRegisterInfo();
4670 const SIInstrInfo *SII = Subtarget->getInstrInfo();
4673 bool AllUsesAcceptSReg =
true;
4675 Limit < 10 && U !=
E; ++U, ++Limit) {
4677 getOperandRegClass(
U->getUser(),
U->getOperandNo());
4685 if (RC != &AMDGPU::VS_32RegClass && RC != &AMDGPU::VS_64RegClass &&
4686 RC != &AMDGPU::VS_64_Align2RegClass) {
4687 AllUsesAcceptSReg =
false;
4688 SDNode *
User =
U->getUser();
4689 if (
User->isMachineOpcode()) {
4690 unsigned Opc =
User->getMachineOpcode();
4691 const MCInstrDesc &
Desc = SII->get(
Opc);
4692 if (
Desc.isCommutable()) {
4693 unsigned OpIdx =
Desc.getNumDefs() +
U->getOperandNo();
4696 unsigned CommutedOpNo = CommuteIdx1 -
Desc.getNumDefs();
4698 getOperandRegClass(
U->getUser(), CommutedOpNo);
4699 if (CommutedRC == &AMDGPU::VS_32RegClass ||
4700 CommutedRC == &AMDGPU::VS_64RegClass ||
4701 CommutedRC == &AMDGPU::VS_64_Align2RegClass)
4702 AllUsesAcceptSReg =
true;
4710 if (!AllUsesAcceptSReg)
4714 return !AllUsesAcceptSReg && (Limit < 10);
4717bool AMDGPUDAGToDAGISel::isUniformLoad(
const SDNode *
N)
const {
4719 const MachineMemOperand *MMO = Ld->getMemOperand();
4737 (Subtarget->getScalarizeGlobalBehavior() &&
4741 ->isMemOpHasNoClobberedMemOperand(
N)));
4747 bool IsModified =
false;
4753 while (Position !=
CurDAG->allnodes_end()) {
4760 if (ResNode !=
Node) {
4766 CurDAG->RemoveDeadNodes();
4767 }
while (IsModified);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool getBaseWithOffsetUsingSplitOR(SelectionDAG &DAG, SDValue Addr, SDValue &N0, SDValue &N1)
static SDValue SelectSAddrFI(SelectionDAG *CurDAG, SDValue SAddr)
static SDValue matchExtFromI32orI32(SDValue Op, bool IsSigned, const SelectionDAG *DAG)
static MemSDNode * findMemSDNode(SDNode *N)
static bool IsCopyFromSGPR(const SIRegisterInfo &TRI, SDValue Val)
static SDValue combineBallotPattern(SDValue VCMP, bool &Negate)
static SDValue matchBF16FPExtendLike(SDValue Op, bool &IsExtractHigh)
static void checkWMMAElementsModifiersF16(BuildVectorSDNode *BV, std::function< bool(SDValue)> ModifierCheck)
Defines an instruction selector for the AMDGPU target.
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
static bool isNoUnsignedWrap(MachineInstr *Addr)
static bool isExtractHiElt(MachineRegisterInfo &MRI, Register In, Register &Out)
static std::pair< unsigned, uint8_t > BitOp3_Op(Register R, SmallVectorImpl< Register > &Src, const MachineRegisterInfo &MRI)
static unsigned gwsIntrinToOpcode(unsigned IntrID)
Provides AMDGPU specific target descriptions.
Base class for AMDGPU specific classes of TargetSubtarget.
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")
const HexagonInstrInfo * TII
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Register const TargetRegisterInfo * TRI
Promote Memory to Register
MachineInstr unsigned OpIdx
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Provides R600 specific target descriptions.
Interface definition for R600RegisterInfo.
const SmallVectorImpl< MachineOperand > & Cond
SI DAG Lowering interface definition.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
AMDGPUDAGToDAGISelLegacy(TargetMachine &TM, CodeGenOptLevel OptLevel)
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
StringRef getPassName() const override
getPassName - Return a nice clean name for a pass.
AMDGPU specific code to select AMDGPU machine instructions for SelectionDAG operations.
bool isSDWAOperand(const SDNode *N) const
void SelectBuildVector(SDNode *N, unsigned RegClassID)
void Select(SDNode *N) override
Main hook for targets to transform nodes into machine nodes.
bool runOnMachineFunction(MachineFunction &MF) override
void SelectVectorShuffle(SDNode *N)
void PreprocessISelDAG() override
PreprocessISelDAG - This hook allows targets to hack on the graph before instruction selection starts...
AMDGPUDAGToDAGISel()=delete
void PostprocessISelDAG() override
PostprocessISelDAG() - This hook allows the target to hack on the graph right after selection.
bool matchLoadD16FromBuildVector(SDNode *N) const
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
AMDGPUISelDAGToDAGPass(TargetMachine &TM)
static SDValue stripBitcast(SDValue Val)
static const fltSemantics & BFloat()
static const fltSemantics & IEEEhalf()
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
bool isSignMask() const
Check if the APInt's value is returned by getSignMask.
bool isMaxSignedValue() const
Determine if this is the largest signed value.
int64_t getSExtValue() const
Get sign extended value.
unsigned countr_one() const
Count the number of trailing one bits.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
LLVM Basic Block Representation.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
A "pseudo-class" with methods for operating on BUILD_VECTORs.
LLVM_ABI SDValue getSplatValue(const APInt &DemandedElts, BitVector *UndefElements=nullptr) const
Returns the demanded splatted value or a null value if this is not a splat.
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
int64_t getSExtValue() const
Analysis pass which computes a DominatorTree.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
FunctionPass class - This class is used to implement most global optimizations.
const SIInstrInfo * getInstrInfo() const override
bool useRealTrue16Insts() const
Return true if real (non-fake) variants of True16 instructions using 16-bit registers should be code-...
Generation getGeneration() const
void checkSubtargetFeatures(const Function &F) const
Diagnose inconsistent subtarget features before attempting to codegen function F.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
ISD::LoadExtType getExtensionType() const
Return whether this is a plain node, or one of the varieties of value-extending loads.
TypeSize getValue() const
Analysis pass that exposes the LoopInfo for a function.
SmallVector< LoopT *, 4 > getLoopsInPreorder() const
Return all of the loops in the function in preorder across the loop nests, with siblings in forward p...
The legacy pass manager's analysis pass to compute loop information.
unsigned getID() const
getID() - Return the register class ID number.
static MVT getIntegerVT(unsigned BitWidth)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
LocationSize getSize() const
Return the size in bytes of the memory reference.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
An SDNode that represents everything that will be needed to construct a MachineInstr.
This is an abstract virtual class for memory operations.
unsigned getAddressSpace() const
Return the address space for the associated pointer.
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
A set of analyses that are preserved following a run of a transformation pass.
Wrapper class representing virtual and physical registers.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
const APInt & getAsAPIntVal() const
Helper method returns the APInt value of a ConstantSDNode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
SDNodeFlags getFlags() const
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
bool isPredecessorOf(const SDNode *N) const
Return true if this node is a predecessor of N.
bool isAnyAdd() const
Returns true if the node type is ADD or PTRADD.
static use_iterator use_end()
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
uint64_t getConstantOperandVal(unsigned i) const
unsigned getOpcode() const
static unsigned getMaxMUBUFImmOffset(const GCNSubtarget &ST)
bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx0, unsigned &SrcOpIdx1) const override
static unsigned getSubRegFromChannel(unsigned Channel, unsigned NumRegs=1)
static LLVM_READONLY const TargetRegisterClass * getSGPRClassForBitWidth(unsigned BitWidth)
static bool isSGPRClass(const TargetRegisterClass *RC)
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
SelectionDAGISelLegacy(char &ID, std::unique_ptr< SelectionDAGISel > S)
SelectionDAGISelPass(std::unique_ptr< SelectionDAGISel > Selector)
LLVM_ABI PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
std::unique_ptr< FunctionLoweringInfo > FuncInfo
const TargetLowering * TLI
const TargetInstrInfo * TII
void ReplaceUses(SDValue F, SDValue T)
ReplaceUses - replace all uses of the old node F with the use of the new node T.
void ReplaceNode(SDNode *F, SDNode *T)
Replace all uses of F with T, then remove F from the DAG.
SelectionDAGISel(TargetMachine &tm, CodeGenOptLevel OL=CodeGenOptLevel::Default)
virtual bool runOnMachineFunction(MachineFunction &mf)
const TargetLowering * getTargetLowering() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
SDValue getTargetFrameIndex(int FI, EVT VT)
LLVM_ABI bool SignBitIsZero(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI bool isBaseWithConstantOffset(SDValue Op) const
Return true if the specified operand is an ISD::ADD with a ConstantSDNode on the right-hand side,...
MachineFunction & getMachineFunction() const
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
ilist< SDNode >::iterator allnodes_iterator
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.
Represent a constant reference to a string, i.e.
static const unsigned CommuteAnyOperandIndex
Primary interface to the complete machine description for the target machine.
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
#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.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ PRIVATE_ADDRESS
Address space for private memory.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
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.
bool isValid32BitLiteral(uint64_t Val, bool IsFP64)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
bool hasSMRDSignedImmOffset(const MCSubtargetInfo &ST)
std::optional< int64_t > getSMRDEncodedOffset(const MCSubtargetInfo &ST, int64_t ByteOffset, bool IsBuffer, bool HasSOffset)
bool isUniformMMO(const MachineMemOperand *MMO)
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.
@ C
The default llvm calling convention, compatible with C.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ STACKRESTORE
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain.
@ PTRADD
PTRADD represents pointer arithmetic semantics, for targets that opt in using shouldPreservePtrArith(...
@ POISON
POISON - A poison node.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ FMAD
FMAD - Perform a * b + c, while getting the same result as the separately rounded operations.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ FADD
Simple binary floating point operators.
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ CONVERGENCECTRL_GLUE
This does not correspond to any convergence control intrinsic.
@ SIGN_EXTEND
Conversion operators.
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
@ UNDEF
UNDEF - An undefined node.
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ BRCOND
BRCOND - Conditional branch.
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
bool isExtOpcode(unsigned Opcode)
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
@ User
could "use" a pointer
This is an optimization pass for GlobalISel generic memory operations.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
@ Undef
Value of the register doesn't matter.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
constexpr bool isMask_32(uint32_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
bool isBoolSGPR(SDValue V)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
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.
static bool getConstantValue(SDValue N, uint32_t &Out)
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
CodeGenOptLevel
Code generation optimization level.
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
FunctionPass * createAMDGPUISelDag(TargetMachine &TM, CodeGenOptLevel OptLevel)
This pass converts a legalized DAG into a AMDGPU-specific.
@ SMax
Signed integer max implemented in terms of select(cmp()).
@ And
Bitwise or logical AND of integers.
@ Sub
Subtraction of integers.
DWARFExpression::Operation Op
unsigned M0(unsigned Val)
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
MCRegisterClass TargetRegisterClass
Implement std::hash so that hash_code can be used in STL containers.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
uint64_t getScalarSizeInBits() const
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool bitsEq(EVT VT) const
Return true if this has the same number of bits as VT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
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.
APInt getMaxValue() const
Return the maximal unsigned value possible given these KnownBits.
APInt getMinValue() const
Return the minimal unsigned value possible given these KnownBits.
static unsigned getSubRegFromChannel(unsigned Channel)
bool hasNoUnsignedWrap() const
This represents a list of ValueType's that has been intern'd by a SelectionDAG.