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;
415 if (OpIdx >=
Desc.getNumOperands())
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));
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,
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();
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))
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;
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 {
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,
3705 CurDAG->getTargetConstant(
3706 TRI->getSubRegFromChannel(NumRegs, NumRegs), SL, MVT::i32)};
3708 Src =
SDValue(
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, SL,
3709 Src.getValueType(),
Ops), 0);
3713 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3719 .bitcastToAPInt().getZExtValue();
3721 Src =
CurDAG->getTargetConstant(
Lit, SDLoc(In), MVT::i64);
3722 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3729 Src.getNumOperands() == 2) {
3734 assert(Src.getValueSizeInBits() != 128 &&
3735 "<2 x 64> VECTOR_SHUFFLE should not be legal.");
3738 ArrayRef<int>
Mask = SVN->getMask();
3740 if (Mask[0] < 2 && Mask[1] < 2) {
3742 SDValue ShuffleSrc = SVN->getOperand(0);
3755 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3763 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3767bool AMDGPUDAGToDAGISel::SelectVOP3PModsDOT(
SDValue In,
SDValue &Src,
3769 return SelectVOP3PMods(In, Src, SrcMods,
true);
3772bool AMDGPUDAGToDAGISel::SelectVOP3PNoModsDOT(
SDValue In,
SDValue &Src)
const {
3774 SelectVOP3PMods(In, SrcTmp, SrcModsTmp,
true);
3783bool AMDGPUDAGToDAGISel::SelectVOP3PModsF32(
SDValue In,
SDValue &Src,
3785 SelectVOP3Mods(In, Src, SrcMods);
3788 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3792bool AMDGPUDAGToDAGISel::SelectVOP3PNoModsF32(
SDValue In,
SDValue &Src)
const {
3794 SelectVOP3PModsF32(In, SrcTmp, SrcModsTmp);
3803bool AMDGPUDAGToDAGISel::SelectWMMAOpSelVOP3PMods(
SDValue In,
3806 assert(
C->getAPIntValue().getBitWidth() == 1 &&
"expected i1 value");
3809 unsigned SrcVal =
C->getZExtValue();
3813 Src =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3820 unsigned DstRegClass;
3822 switch (Elts.
size()) {
3824 DstRegClass = AMDGPU::VReg_256RegClassID;
3828 DstRegClass = AMDGPU::VReg_128RegClassID;
3832 DstRegClass = AMDGPU::VReg_64RegClassID;
3840 Ops.push_back(
CurDAG->getTargetConstant(DstRegClass,
DL, MVT::i32));
3841 for (
unsigned i = 0; i < Elts.
size(); ++i) {
3842 Ops.push_back(Elts[i]);
3843 Ops.push_back(
CurDAG->getTargetConstant(
3846 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL, DstTy,
Ops);
3853 assert(
"unhandled Reg sequence size" &&
3854 (Elts.
size() == 8 || Elts.
size() == 16));
3858 for (
unsigned i = 0; i < Elts.
size(); i += 2) {
3859 SDValue LoSrc = stripExtractLoElt(stripBitcast(Elts[i]));
3864 if (Subtarget->useRealTrue16Insts()) {
3869 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, MVT::i16),
3872 emitRegSequence(*
CurDAG, AMDGPU::VGPR_32RegClassID, MVT::i32,
3873 {Elts[i],
Undef}, {AMDGPU::lo16, AMDGPU::hi16},
DL);
3874 Elts[i + 1] = emitRegSequence(*
CurDAG, AMDGPU::VGPR_32RegClassID,
3875 MVT::i32, {Elts[i + 1],
Undef},
3876 {AMDGPU::lo16, AMDGPU::hi16},
DL);
3878 SDValue PackLoLo =
CurDAG->getTargetConstant(0x05040100,
DL, MVT::i32);
3880 CurDAG->getMachineNode(AMDGPU::V_PERM_B32_e64,
DL, MVT::i32,
3881 {Elts[i + 1], Elts[i], PackLoLo});
3885 return buildRegSequence32(PackedElts,
DL);
3891 unsigned ElementSize)
const {
3892 if (ElementSize == 16)
3893 return buildRegSequence16(Elts,
DL);
3894 if (ElementSize == 32)
3895 return buildRegSequence32(Elts,
DL);
3899void AMDGPUDAGToDAGISel::selectWMMAModsNegAbs(
unsigned ModOpcode,
3903 unsigned ElementSize)
const {
3908 for (
auto El : Elts) {
3911 NegAbsElts.
push_back(El->getOperand(0));
3913 if (Elts.size() != NegAbsElts.
size()) {
3915 Src =
SDValue(buildRegSequence(Elts,
DL, ElementSize), 0);
3919 Src =
SDValue(buildRegSequence(NegAbsElts,
DL, ElementSize), 0);
3925 Src =
SDValue(buildRegSequence(Elts,
DL, ElementSize), 0);
3933 std::function<
bool(
SDValue)> ModifierCheck) {
3937 for (
unsigned i = 0; i < F16Pair->getNumOperands(); ++i) {
3938 SDValue ElF16 = stripBitcast(F16Pair->getOperand(i));
3939 if (!ModifierCheck(ElF16))
3946bool AMDGPUDAGToDAGISel::SelectWMMAModsF16Neg(
SDValue In,
SDValue &Src,
3964 Src =
SDValue(buildRegSequence16(EltsF16, SDLoc(In)), 0);
3983 Src =
SDValue(buildRegSequence32(EltsV2F16, SDLoc(In)), 0);
3989 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3993bool AMDGPUDAGToDAGISel::SelectWMMAModsF16NegAbs(
SDValue In,
SDValue &Src,
4004 if (EltsF16.
empty())
4014 selectWMMAModsNegAbs(ModOpcode, Mods, EltsF16, Src, SDLoc(In), 16);
4024 if (EltsV2F16.
empty())
4033 selectWMMAModsNegAbs(ModOpcode, Mods, EltsV2F16, Src, SDLoc(In), 32);
4036 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4040bool AMDGPUDAGToDAGISel::SelectWMMAModsF32NegAbs(
SDValue In,
SDValue &Src,
4050 unsigned ModOpcode =
4061 selectWMMAModsNegAbs(ModOpcode, Mods, EltsF32, Src, SDLoc(In), 32);
4064 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4068bool AMDGPUDAGToDAGISel::SelectWMMAVISrc(
SDValue In,
SDValue &Src)
const {
4070 BitVector UndefElements;
4072 if (isInlineImmediate(
Splat.getNode())) {
4074 unsigned Imm =
C->getAPIntValue().getSExtValue();
4075 Src =
CurDAG->getTargetConstant(
Imm, SDLoc(In), MVT::i32);
4079 unsigned Imm =
C->getValueAPF().bitcastToAPInt().getSExtValue();
4080 Src =
CurDAG->getTargetConstant(
Imm, SDLoc(In), MVT::i32);
4088 SDValue SplatSrc32 = stripBitcast(In);
4090 if (
SDValue Splat32 = SplatSrc32BV->getSplatValue()) {
4091 SDValue SplatSrc16 = stripBitcast(Splat32);
4094 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
4095 std::optional<APInt> RawValue;
4097 RawValue =
C->getValueAPF().bitcastToAPInt();
4099 RawValue =
C->getAPIntValue();
4101 if (RawValue.has_value()) {
4102 EVT VT =
In.getValueType().getScalarType();
4108 if (
TII->isInlineConstant(FloatVal)) {
4109 Src =
CurDAG->getTargetConstant(RawValue.value(), SDLoc(In),
4114 if (
TII->isInlineConstant(RawValue.value())) {
4115 Src =
CurDAG->getTargetConstant(RawValue.value(), SDLoc(In),
4128 if (
CurDAG->isConstantIntBuildVectorOrConstantInt(SplatSrc32)) {
4133 int64_t LoImm = Lo32->getAPIntValue().getSExtValue();
4134 int64_t HiImm = Hi32->getAPIntValue().getSExtValue();
4135 int64_t Imm64I = (HiImm << 32) + LoImm;
4137 if (!isInlineImmediate(APInt(64, Imm64I)))
4140 }
else if (Imm64I != Imm64)
4144 Src =
CurDAG->getTargetConstant(Imm64, SDLoc(In), MVT::i64);
4151bool AMDGPUDAGToDAGISel::SelectSWMMACIndex8(
SDValue In,
SDValue &Src,
4157 const llvm::SDValue &ShiftSrc =
In.getOperand(0);
4166 IndexKey =
CurDAG->getTargetConstant(
Key, SDLoc(In), MVT::i32);
4170bool AMDGPUDAGToDAGISel::SelectSWMMACIndex16(
SDValue In,
SDValue &Src,
4176 const llvm::SDValue &ShiftSrc =
In.getOperand(0);
4185 IndexKey =
CurDAG->getTargetConstant(
Key, SDLoc(In), MVT::i32);
4189bool AMDGPUDAGToDAGISel::SelectSWMMACIndex32(
SDValue In,
SDValue &Src,
4197 const SDValue &ExtendSrc =
In.getOperand(0);
4201 const SDValue &CastSrc =
In.getOperand(0);
4205 if (Zero &&
Zero->getZExtValue() == 0)
4216 Src = ExtractVecEltSrc;
4220 IndexKey =
CurDAG->getTargetConstant(
Key, SDLoc(In), MVT::i32);
4224bool AMDGPUDAGToDAGISel::SelectVOP3OpSel(
SDValue In,
SDValue &Src,
4228 SrcMods =
CurDAG->getTargetConstant(0, SDLoc(In), MVT::i32);
4232bool AMDGPUDAGToDAGISel::SelectVOP3OpSelMods(
SDValue In,
SDValue &Src,
4235 return SelectVOP3Mods(In, Src, SrcMods);
4247 Op =
Op.getOperand(0);
4249 IsExtractHigh =
false;
4252 if (!Low16 || !Low16->isZero())
4254 Op = stripBitcast(
Op.getOperand(1));
4255 if (
Op.getValueType() != MVT::bf16)
4260 if (
Op.getValueType() != MVT::i32)
4265 if (Mask->getZExtValue() == 0xffff0000) {
4266 IsExtractHigh =
true;
4267 return Op.getOperand(0);
4276 return Op.getOperand(0);
4285bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixModsImpl(
SDValue In,
SDValue &Src,
4289 SelectVOP3ModsImpl(In, Src, Mods);
4291 bool IsExtractHigh =
false;
4293 Src = Src.getOperand(0);
4294 }
else if (VT == MVT::bf16) {
4302 if (Src.getValueType() != VT &&
4303 (VT != MVT::bf16 || Src.getValueType() != MVT::i32))
4306 Src = stripBitcast(Src);
4312 SelectVOP3ModsImpl(Src, Src, ModsTmp);
4327 if (Src.getValueSizeInBits() == 16) {
4336 Src.getOperand(0).getValueType() == MVT::i32) {
4337 Src = Src.getOperand(0);
4341 if (Subtarget->useRealTrue16Insts())
4343 Src = createVOP3PSrc32FromLo16(Src, In,
CurDAG, Subtarget);
4344 }
else if (IsExtractHigh)
4350bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixModsExt(
SDValue In,
SDValue &Src,
4353 if (!SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::f16))
4355 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4359bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixMods(
SDValue In,
SDValue &Src,
4362 SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::f16);
4363 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4367bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixModsExtNeg(
SDValue In,
SDValue &Src,
4370 if (!SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::f16))
4377bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixModsNeg(
SDValue In,
SDValue &Src,
4380 SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::f16);
4386bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixBF16ModsExt(
SDValue In,
SDValue &Src,
4389 if (!SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::bf16))
4391 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4395bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixBF16Mods(
SDValue In,
SDValue &Src,
4398 SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::bf16);
4399 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4403bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixBF16ModsExtNeg(
4406 if (!SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::bf16))
4413bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixBF16ModsNeg(
SDValue In,
SDValue &Src,
4416 SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::bf16);
4426 unsigned NumOpcodes = 0;
4439 const uint8_t SrcBits[3] = { 0xf0, 0xcc, 0xaa };
4442 if (
C->isAllOnes()) {
4452 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4466 if (Src.size() == 3) {
4472 if (
C->isAllOnes()) {
4474 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4475 if (Src[
I] ==
LHS) {
4487 Bits = SrcBits[Src.size()];
4492 switch (In.getOpcode()) {
4500 if (!getOperandBits(
LHS, LHSBits) ||
4501 !getOperandBits(
RHS, RHSBits)) {
4502 Src = std::move(Backup);
4503 return std::make_pair(0, 0);
4524 uint8_t LHSBitsOrig = LHSBits;
4525 uint8_t RHSBitsOrig = RHSBits;
4529 NumOpcodes += LHSOp.first;
4530 LHSBits = LHSOp.second;
4537 NumOpcodes += RHSOp.first;
4538 RHSBits = RHSOp.second;
4542 auto dependsOnSlot = [](
uint8_t TT,
int Slot) ->
bool {
4543 if (Slot < 0 || Slot > 2)
4545 const uint8_t Masks[3] = {0x0f, 0x33, 0x55};
4546 const int Shifts[3] = {4, 2, 1};
4547 return ((TT ^ (TT >> Shifts[Slot])) & Masks[Slot]) != 0;
4553 const uint8_t SrcBitsConst[3] = {0xf0, 0xcc, 0xaa};
4560 NegatedInner =
Op.getOperand(0);
4561 for (
int I = 0;
I < (int)S.size();
I++) {
4562 if (Bits == SrcBitsConst[
I] && S[
I] ==
Op)
4564 if (IsNegationOp && Bits == (
uint8_t)~SrcBitsConst[
I] &&
4565 S[
I] == NegatedInner)
4576 for (
int I = 0;
I < (int)SrcAfterLHS.
size() &&
I < 3;
I++) {
4577 if (
I < (
int)Src.size() && Src[
I] != SrcAfterLHS[
I] &&
4578 dependsOnSlot(LHSBits,
I)) {
4587 if (!Stale && !RHSOp.first) {
4588 int Slot = findSlot(RHSBitsOrig,
RHS, SrcBeforeRecurse);
4590 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4596 if (!Stale && !LHSOp.first) {
4597 int Slot = findSlot(LHSBitsOrig,
LHS, SrcBeforeRecurse);
4599 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4604 Src = std::move(SrcBeforeRecurse);
4605 LHSBits = LHSBitsOrig;
4606 RHSBits = RHSBitsOrig;
4612 return std::make_pair(0, 0);
4616 switch (In.getOpcode()) {
4618 TTbl = LHSBits & RHSBits;
4621 TTbl = LHSBits | RHSBits;
4624 TTbl = LHSBits ^ RHSBits;
4630 return std::make_pair(NumOpcodes + 1, TTbl);
4637 unsigned NumOpcodes;
4639 std::tie(NumOpcodes, TTbl) =
BitOp3_Op(In, Src);
4643 if (NumOpcodes < 2 || Src.empty())
4649 if (NumOpcodes < 4 && !In->isDivergent())
4652 if (NumOpcodes == 2 &&
In.getValueType() == MVT::i32) {
4657 (
In.getOperand(0).getOpcode() ==
In.getOpcode() ||
4658 In.getOperand(1).getOpcode() ==
In.getOpcode()))
4672 while (Src.size() < 3)
4673 Src.push_back(Src[0]);
4679 Tbl =
CurDAG->getTargetConstant(TTbl, SDLoc(In), MVT::i32);
4685 return CurDAG->getPOISON(MVT::i32);
4688 return CurDAG->getUNDEF(MVT::i32);
4692 return CurDAG->getConstant(
C->getZExtValue() << 16, SL, MVT::i32);
4697 return CurDAG->getConstant(
4698 C->getValueAPF().bitcastToAPInt().getZExtValue() << 16, SL, MVT::i32);
4708bool AMDGPUDAGToDAGISel::isVGPRImm(
const SDNode *
N)
const {
4709 assert(
CurDAG->getTarget().getTargetTriple().isAMDGCN());
4711 const SIRegisterInfo *SIRI = Subtarget->getRegisterInfo();
4712 const SIInstrInfo *SII = Subtarget->getInstrInfo();
4715 bool AllUsesAcceptSReg =
true;
4717 Limit < 10 && U !=
E; ++U, ++Limit) {
4719 getOperandRegClass(
U->getUser(),
U->getOperandNo());
4727 if (RC != &AMDGPU::VS_32RegClass && RC != &AMDGPU::VS_64RegClass &&
4728 RC != &AMDGPU::VS_64_Align2RegClass) {
4729 AllUsesAcceptSReg =
false;
4730 SDNode *
User =
U->getUser();
4731 if (
User->isMachineOpcode()) {
4732 unsigned Opc =
User->getMachineOpcode();
4733 const MCInstrDesc &
Desc = SII->get(
Opc);
4734 if (
Desc.isCommutable()) {
4735 unsigned OpIdx =
Desc.getNumDefs() +
U->getOperandNo();
4738 unsigned CommutedOpNo = CommuteIdx1 -
Desc.getNumDefs();
4740 getOperandRegClass(
U->getUser(), CommutedOpNo);
4741 if (CommutedRC == &AMDGPU::VS_32RegClass ||
4742 CommutedRC == &AMDGPU::VS_64RegClass ||
4743 CommutedRC == &AMDGPU::VS_64_Align2RegClass)
4744 AllUsesAcceptSReg =
true;
4752 if (!AllUsesAcceptSReg)
4756 return !AllUsesAcceptSReg && (Limit < 10);
4759bool AMDGPUDAGToDAGISel::isUniformLoad(
const SDNode *
N)
const {
4761 const MachineMemOperand *MMO = Ld->getMemOperand();
4779 (Subtarget->getScalarizeGlobalBehavior() &&
4783 ->isMemOpHasNoClobberedMemOperand(
N)));
4789 bool IsModified =
false;
4795 while (Position !=
CurDAG->allnodes_end()) {
4802 if (ResNode !=
Node) {
4808 CurDAG->RemoveDeadNodes();
4809 }
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< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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
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.
@ 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.