27#include "llvm/IR/IntrinsicsAMDGPU.h"
31#ifdef EXPENSIVE_CHECKS
36#define DEBUG_TYPE "amdgpu-isel"
51 In = stripBitcast(In);
57 Out = In.getOperand(0);
68 if (ShiftAmt->getZExtValue() == 16) {
88 if (
Lo->isDivergent()) {
90 SL,
Lo.getValueType()),
98 Src.getValueType(),
Ops),
116 SDValue Idx = In.getOperand(1);
118 return In.getOperand(0);
122 SDValue Src = In.getOperand(0);
123 if (Src.getValueType().getSizeInBits() == 32)
124 return stripBitcast(Src);
134 assert(Elts.
size() == SubRegClass.
size() &&
"array size mismatch");
135 unsigned NumElts = Elts.
size();
138 for (
unsigned i = 0; i < NumElts; ++i) {
139 Ops[2 * i + 1] = Elts[i];
149 "AMDGPU DAG->DAG Pattern Instruction Selection",
false,
153#ifdef EXPENSIVE_CHECKS
158 "AMDGPU DAG->DAG Pattern Instruction Selection",
false,
179bool AMDGPUDAGToDAGISel::fp16SrcZerosHighBits(
unsigned Opc)
const {
215 case AMDGPUISD::FRACT:
216 case AMDGPUISD::CLAMP:
217 case AMDGPUISD::COS_HW:
218 case AMDGPUISD::SIN_HW:
219 case AMDGPUISD::FMIN3:
220 case AMDGPUISD::FMAX3:
221 case AMDGPUISD::FMED3:
222 case AMDGPUISD::FMAD_FTZ:
225 case AMDGPUISD::RCP_IFLAG:
235 case AMDGPUISD::DIV_FIXUP:
245#ifdef EXPENSIVE_CHECKS
249 assert(L->isLCSSAForm(DT));
257#ifdef EXPENSIVE_CHECKS
265 assert(Subtarget->d16PreservesUnusedBits());
266 MVT VT =
N->getValueType(0).getSimpleVT();
267 if (VT != MVT::v2i16 && VT != MVT::v2f16)
289 unsigned LoadOp = AMDGPUISD::LOAD_D16_HI;
292 AMDGPUISD::LOAD_D16_HI_I8 : AMDGPUISD::LOAD_D16_HI_U8;
298 CurDAG->getMemIntrinsicNode(LoadOp,
SDLoc(LdHi), VTList,
311 if (LdLo &&
Lo.hasOneUse()) {
317 unsigned LoadOp = AMDGPUISD::LOAD_D16_LO;
320 AMDGPUISD::LOAD_D16_LO_I8 : AMDGPUISD::LOAD_D16_LO_U8;
332 CurDAG->getMemIntrinsicNode(LoadOp,
SDLoc(LdLo), VTList,
345 if (!Subtarget->d16PreservesUnusedBits())
350 bool MadeChange =
false;
351 while (Position !=
CurDAG->allnodes_begin()) {
356 switch (
N->getOpcode()) {
367 CurDAG->RemoveDeadNodes();
373bool AMDGPUDAGToDAGISel::isInlineImmediate(
const SDNode *
N)
const {
379 return TII->isInlineConstant(
C->getAPIntValue());
382 return TII->isInlineConstant(
C->getValueAPF());
392 unsigned OpNo)
const {
393 if (!
N->isMachineOpcode()) {
396 if (
Reg.isVirtual()) {
401 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
402 return TRI->getPhysRegBaseClass(
Reg);
408 switch (
N->getMachineOpcode()) {
410 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
411 const MCInstrDesc &
Desc =
TII->get(
N->getMachineOpcode());
412 unsigned OpIdx =
Desc.getNumDefs() + OpNo;
413 if (OpIdx >=
Desc.getNumOperands())
416 int16_t RegClass =
TII->getOpRegClassID(
Desc.operands()[OpIdx]);
420 return Subtarget->getRegisterInfo()->getRegClass(RegClass);
422 case AMDGPU::REG_SEQUENCE: {
423 unsigned RCID =
N->getConstantOperandVal(0);
425 Subtarget->getRegisterInfo()->getRegClass(RCID);
427 SDValue SubRegOp =
N->getOperand(OpNo + 1);
429 return Subtarget->getRegisterInfo()->getSubClassWithSubReg(SuperRC,
438 Ops.push_back(NewChain);
439 for (
unsigned i = 1, e =
N->getNumOperands(); i != e; ++i)
440 Ops.push_back(
N->getOperand(i));
443 return CurDAG->MorphNodeTo(
N,
N->getOpcode(),
N->getVTList(),
Ops);
450 assert(
N->getOperand(0).getValueType() == MVT::Other &&
"Expected chain");
453 return glueCopyToOp(
N,
M0,
M0.getValue(1));
456SDNode *AMDGPUDAGToDAGISel::glueCopyToM0LDSInit(
SDNode *
N)
const {
459 if (Subtarget->ldsRequiresM0Init())
461 N,
CurDAG->getSignedTargetConstant(-1, SDLoc(
N), MVT::i32));
464 unsigned Value =
MF.getInfo<SIMachineFunctionInfo>()->getGDSSize();
466 glueCopyToM0(
N,
CurDAG->getTargetConstant(
Value, SDLoc(
N), MVT::i32));
473 SDNode *
Lo =
CurDAG->getMachineNode(
474 AMDGPU::S_MOV_B32,
DL, MVT::i32,
476 SDNode *
Hi =
CurDAG->getMachineNode(
477 AMDGPU::S_MOV_B32,
DL, MVT::i32,
480 CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID,
DL, MVT::i32),
484 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL, VT,
Ops);
487SDNode *AMDGPUDAGToDAGISel::packConstantV2I16(
const SDNode *
N,
492 uint32_t LHSVal, RHSVal;
496 uint32_t
K = (LHSVal & 0xffff) | (RHSVal << 16);
498 isVGPRImm(
N) ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32, SL,
506 EVT VT =
N->getValueType(0);
510 SDValue RegClass =
CurDAG->getTargetConstant(RegClassID,
DL, MVT::i32);
512 if (NumVectorElts == 1) {
513 CurDAG->SelectNodeTo(
N, AMDGPU::COPY_TO_REGCLASS, EltVT,
N->getOperand(0),
518 bool IsGCN =
CurDAG->getSubtarget().getTargetTriple().isAMDGCN();
519 if (IsGCN && Subtarget->has64BitLiterals() && VT.
getSizeInBits() == 64 &&
522 bool AllConst =
true;
524 for (
unsigned I = 0;
I < NumVectorElts; ++
I) {
532 Val = CF->getValueAPF().bitcastToAPInt().getZExtValue();
535 C |= Val << (EltSize *
I);
540 CurDAG->getMachineNode(AMDGPU::S_MOV_B64_IMM_PSEUDO,
DL, VT, CV);
541 CurDAG->SelectNodeTo(
N, AMDGPU::COPY_TO_REGCLASS, VT,
SDValue(Copy, 0),
547 assert(NumVectorElts <= 32 &&
"Vectors with more than 32 elements not "
554 RegSeqArgs[0] =
CurDAG->getTargetConstant(RegClassID,
DL, MVT::i32);
555 bool IsRegSeq =
true;
556 unsigned NOps =
N->getNumOperands();
558 assert(IsGCN || EltSizeInRegs == 1);
559 for (
unsigned i = 0; i < NOps; i++) {
566 i * EltSizeInRegs, EltSizeInRegs)
568 RegSeqArgs[1 + (2 * i)] =
N->getOperand(i);
569 RegSeqArgs[1 + (2 * i) + 1] =
CurDAG->getTargetConstant(
Sub,
DL, MVT::i32);
571 if (NOps != NumVectorElts) {
576 for (
unsigned i = NOps; i < NumVectorElts; ++i) {
578 i * EltSizeInRegs, EltSizeInRegs)
580 RegSeqArgs[1 + (2 * i)] =
SDValue(ImpDef, 0);
581 RegSeqArgs[1 + (2 * i) + 1] =
588 CurDAG->SelectNodeTo(
N, AMDGPU::REG_SEQUENCE,
N->getVTList(), RegSeqArgs);
592 EVT VT =
N->getValueType(0);
596 if (!Subtarget->hasPkMovB32() || !EltVT.
bitsEq(MVT::i32) ||
610 Mask[0] < 4 && Mask[1] < 4);
612 SDValue VSrc0 = Mask[0] < 2 ? Src0 : Src1;
613 SDValue VSrc1 = Mask[1] < 2 ? Src0 : Src1;
614 unsigned Src0SubReg = Mask[0] & 1 ? AMDGPU::sub1 : AMDGPU::sub0;
615 unsigned Src1SubReg = Mask[1] & 1 ? AMDGPU::sub1 : AMDGPU::sub0;
618 Src0SubReg = Src1SubReg;
620 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, VT);
625 Src1SubReg = Src0SubReg;
627 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, VT);
637 if (
N->isDivergent() && Src0SubReg == AMDGPU::sub1 &&
638 Src1SubReg == AMDGPU::sub0) {
654 SDValue Src0OpSelVal =
CurDAG->getTargetConstant(Src0OpSel,
DL, MVT::i32);
655 SDValue Src1OpSelVal =
CurDAG->getTargetConstant(Src1OpSel,
DL, MVT::i32);
658 CurDAG->SelectNodeTo(
N, AMDGPU::V_PK_MOV_B32,
N->getVTList(),
659 {Src0OpSelVal, VSrc0, Src1OpSelVal, VSrc1,
669 CurDAG->getTargetExtractSubreg(Src0SubReg,
DL, EltVT, VSrc0);
671 CurDAG->getTargetExtractSubreg(Src1SubReg,
DL, EltVT, VSrc1);
674 CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID,
DL, MVT::i32),
675 ResultElt0,
CurDAG->getTargetConstant(AMDGPU::sub0,
DL, MVT::i32),
676 ResultElt1,
CurDAG->getTargetConstant(AMDGPU::sub1,
DL, MVT::i32)};
677 CurDAG->SelectNodeTo(
N, TargetOpcode::REG_SEQUENCE, VT,
Ops);
681 unsigned int Opc =
N->getOpcode();
682 if (
N->isMachineOpcode()) {
690 N = glueCopyToM0LDSInit(
N);
700 if (
N->getValueType(0) == MVT::i64) {
701 SelectAddcSubbI64(
N);
705 if (
N->getValueType(0) != MVT::i32)
712 if (
N->getValueType(0) == MVT::i64) {
713 SelectAddcSubbI64(
N);
717 SelectUADDO_USUBO(
N);
720 case AMDGPUISD::FMUL_W_CHAIN: {
721 SelectFMUL_W_CHAIN(
N);
724 case AMDGPUISD::FMA_W_CHAIN: {
725 SelectFMA_W_CHAIN(
N);
731 EVT VT =
N->getValueType(0);
749 N->isDivergent() ?
TRI->getDefaultVectorSuperClassForBitWidth(VecInBits)
761 if (
N->getValueType(0) == MVT::i128) {
762 RC =
CurDAG->getTargetConstant(AMDGPU::SGPR_128RegClassID,
DL, MVT::i32);
763 SubReg0 =
CurDAG->getTargetConstant(AMDGPU::sub0_sub1,
DL, MVT::i32);
764 SubReg1 =
CurDAG->getTargetConstant(AMDGPU::sub2_sub3,
DL, MVT::i32);
765 }
else if (
N->getValueType(0) == MVT::i64) {
766 RC =
CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID,
DL, MVT::i32);
767 SubReg0 =
CurDAG->getTargetConstant(AMDGPU::sub0,
DL, MVT::i32);
768 SubReg1 =
CurDAG->getTargetConstant(AMDGPU::sub1,
DL, MVT::i32);
772 const SDValue Ops[] = { RC,
N->getOperand(0), SubReg0,
773 N->getOperand(1), SubReg1 };
775 N->getValueType(0),
Ops));
781 if (
N->getValueType(0).getSizeInBits() != 64 || isInlineImmediate(
N) ||
782 Subtarget->has64BitLiterals())
787 Imm =
FP->getValueAPF().bitcastToAPInt().getZExtValue();
792 Imm =
C->getZExtValue();
801 case AMDGPUISD::BFE_I32:
802 case AMDGPUISD::BFE_U32: {
828 case AMDGPUISD::DIV_SCALE: {
839 return SelectMUL_LOHI(
N);
850 if (
N->getValueType(0) != MVT::i32)
861 case AMDGPUISD::CVT_PKRTZ_F16_F32:
862 case AMDGPUISD::CVT_PKNORM_I16_F32:
863 case AMDGPUISD::CVT_PKNORM_U16_F32:
864 case AMDGPUISD::CVT_PK_U16_U32:
865 case AMDGPUISD::CVT_PK_I16_I32: {
867 if (
N->getValueType(0) == MVT::i32) {
868 MVT NewVT =
Opc == AMDGPUISD::CVT_PKRTZ_F16_F32 ? MVT::v2f16 : MVT::v2i16;
870 { N->getOperand(0), N->getOperand(1) });
878 SelectINTRINSIC_W_CHAIN(
N);
882 SelectINTRINSIC_WO_CHAIN(
N);
886 SelectINTRINSIC_VOID(
N);
890 SelectWAVE_ADDRESS(
N);
894 SelectSTACKRESTORE(
N);
903 if (!Subtarget->hasSDWA())
913 return RHS->getZExtValue() == 0xFF || RHS->getZExtValue() == 0xFFFF;
917 return (RHS->getZExtValue() % 8) == 0;
922bool AMDGPUDAGToDAGISel::isUniformBr(
const SDNode *
N)
const {
925 return Term->getMetadata(
"amdgpu.uniform") ||
926 Term->getMetadata(
"structurizecfg.uniform");
929bool AMDGPUDAGToDAGISel::isUnneededShiftMask(
const SDNode *
N,
930 unsigned ShAmtBits)
const {
933 const APInt &
RHS =
N->getConstantOperandAPInt(1);
934 if (
RHS.countr_one() >= ShAmtBits)
964 N1 =
Lo.getOperand(1);
974 if (
CurDAG->isBaseWithConstantOffset(Addr)) {
989 return "AMDGPU DAG->DAG Pattern Instruction Selection";
1005#ifdef EXPENSIVE_CHECKS
1008 for (
auto &L : LI.getLoopsInPreorder())
1009 assert(L->isLCSSAForm(DT) &&
"Loop is not in LCSSA form!");
1031 }
else if ((Addr.
getOpcode() == AMDGPUISD::DWORDADDR) &&
1033 Base =
CurDAG->getRegister(R600::INDIRECT_BASE_ADDR, MVT::i32);
1047SDValue AMDGPUDAGToDAGISel::getMaterializedScalarImm32(int64_t Val,
1049 SDNode *Mov =
CurDAG->getMachineNode(
1050 AMDGPU::S_MOV_B32,
DL, MVT::i32,
1051 CurDAG->getTargetConstant(Val,
DL, MVT::i32));
1055void AMDGPUDAGToDAGISel::SelectAddcSubb(
SDNode *
N) {
1060 if (
N->isDivergent()) {
1062 : AMDGPU::V_SUBB_U32_e64;
1064 N,
Opc,
N->getVTList(),
1066 CurDAG->getTargetConstant(0, {}, MVT::i1) });
1069 : AMDGPU::S_SUB_CO_PSEUDO;
1070 CurDAG->SelectNodeTo(
N,
Opc,
N->getVTList(), {LHS, RHS, CI});
1074void AMDGPUDAGToDAGISel::SelectAddcSubbI64(
SDNode *
N) {
1079 unsigned Opcode =
N->getOpcode();
1086 SDNode *Lo0 =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
DL,
1087 MVT::i32,
LHS, Sub0);
1088 SDNode *Hi0 =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
DL,
1089 MVT::i32,
LHS, Sub1);
1091 SDNode *Lo1 =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
DL,
1092 MVT::i32,
RHS, Sub0);
1093 SDNode *Hi1 =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
DL,
1094 MVT::i32,
RHS, Sub1);
1096 SDVTList VTList =
CurDAG->getVTList(MVT::i32,
N->getValueType(1));
1098 static const unsigned NoCarryOpcMap[2][2] = {
1099 {AMDGPU::S_USUBO_PSEUDO, AMDGPU::S_UADDO_PSEUDO},
1100 {AMDGPU::V_SUB_CO_U32_e64, AMDGPU::V_ADD_CO_U32_e64}};
1101 static const unsigned CarryOpcMap[2][2] = {
1102 {AMDGPU::S_SUB_CO_PSEUDO, AMDGPU::S_ADD_CO_PSEUDO},
1103 {AMDGPU::V_SUBB_U32_e64, AMDGPU::V_ADDC_U32_e64}};
1105 bool IsVALU =
N->isDivergent();
1107 unsigned NoCarryOpc = NoCarryOpcMap[IsVALU][IsAdd];
1108 unsigned CarryOpc = CarryOpcMap[IsVALU][IsAdd];
1112 if (!ConsumeCarry) {
1115 AddLo =
CurDAG->getMachineNode(NoCarryOpc,
DL, VTList, Args);
1118 AddLo =
CurDAG->getMachineNode(NoCarryOpc,
DL, VTList, Args);
1124 AddLo =
CurDAG->getMachineNode(CarryOpc,
DL, VTList, Args);
1127 AddLo =
CurDAG->getMachineNode(CarryOpc,
DL, VTList, Args);
1135 AddHi =
CurDAG->getMachineNode(CarryOpc,
DL, VTList, Args);
1138 AddHi =
CurDAG->getMachineNode(CarryOpc,
DL, VTList, Args);
1141 unsigned RC = IsVALU ? AMDGPU::VReg_64RegClassID : AMDGPU::SReg_64RegClassID;
1142 SDValue RegSequenceArgs[] = {
CurDAG->getTargetConstant(RC,
DL, MVT::i32),
1146 MVT::i64, RegSequenceArgs);
1152void AMDGPUDAGToDAGISel::SelectUADDO_USUBO(
SDNode *
N) {
1157 bool IsVALU =
N->isDivergent();
1159 for (SDNode::user_iterator UI =
N->user_begin(),
E =
N->user_end(); UI !=
E;
1161 if (UI.getUse().getResNo() == 1) {
1162 if (UI->isMachineOpcode()) {
1163 if (UI->getMachineOpcode() !=
1164 (IsAdd ? AMDGPU::S_ADD_CO_PSEUDO : AMDGPU::S_SUB_CO_PSEUDO)) {
1177 unsigned Opc = IsAdd ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_SUB_CO_U32_e64;
1180 N,
Opc,
N->getVTList(),
1181 {N->getOperand(0), N->getOperand(1),
1182 CurDAG->getTargetConstant(0, {}, MVT::i1) });
1184 unsigned Opc = IsAdd ? AMDGPU::S_UADDO_PSEUDO : AMDGPU::S_USUBO_PSEUDO;
1186 CurDAG->SelectNodeTo(
N,
Opc,
N->getVTList(),
1187 {N->getOperand(0), N->getOperand(1)});
1191void AMDGPUDAGToDAGISel::SelectFMA_W_CHAIN(
SDNode *
N) {
1195 SelectVOP3Mods0(
N->getOperand(1),
Ops[1],
Ops[0],
Ops[6],
Ops[7]);
1196 SelectVOP3Mods(
N->getOperand(2),
Ops[3],
Ops[2]);
1197 SelectVOP3Mods(
N->getOperand(3),
Ops[5],
Ops[4]);
1198 Ops[8] =
N->getOperand(0);
1199 Ops[9] =
N->getOperand(4);
1203 bool UseFMAC = Subtarget->hasDLInsts() &&
1207 unsigned Opcode = UseFMAC ? AMDGPU::V_FMAC_F32_e64 : AMDGPU::V_FMA_F32_e64;
1208 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(),
Ops);
1211void AMDGPUDAGToDAGISel::SelectFMUL_W_CHAIN(
SDNode *
N) {
1215 SelectVOP3Mods0(
N->getOperand(1),
Ops[1],
Ops[0],
Ops[4],
Ops[5]);
1216 SelectVOP3Mods(
N->getOperand(2),
Ops[3],
Ops[2]);
1217 Ops[6] =
N->getOperand(0);
1218 Ops[7] =
N->getOperand(3);
1220 CurDAG->SelectNodeTo(
N, AMDGPU::V_MUL_F32_e64,
N->getVTList(),
Ops);
1225void AMDGPUDAGToDAGISel::SelectDIV_SCALE(
SDNode *
N) {
1226 EVT VT =
N->getValueType(0);
1228 assert(VT == MVT::f32 || VT == MVT::f64);
1231 = (VT == MVT::f64) ? AMDGPU::V_DIV_SCALE_F64_e64 : AMDGPU::V_DIV_SCALE_F32_e64;
1236 SelectVOP3BMods0(
N->getOperand(0),
Ops[1],
Ops[0],
Ops[6],
Ops[7]);
1237 SelectVOP3BMods(
N->getOperand(1),
Ops[3],
Ops[2]);
1238 SelectVOP3BMods(
N->getOperand(2),
Ops[5],
Ops[4]);
1244void AMDGPUDAGToDAGISel::SelectMAD_64_32(
SDNode *
N) {
1248 bool UseNoCarry = Subtarget->hasMadNC64_32Insts() && !
N->hasAnyUseOfValue(1);
1249 if (Subtarget->hasMADIntraFwdBug())
1250 Opc =
Signed ? AMDGPU::V_MAD_I64_I32_gfx11_e64
1251 : AMDGPU::V_MAD_U64_U32_gfx11_e64;
1252 else if (UseNoCarry)
1253 Opc =
Signed ? AMDGPU::V_MAD_NC_I64_I32_e64 : AMDGPU::V_MAD_NC_U64_U32_e64;
1255 Opc =
Signed ? AMDGPU::V_MAD_I64_I32_e64 : AMDGPU::V_MAD_U64_U32_e64;
1258 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1),
N->getOperand(2),
1262 MachineSDNode *Mad =
CurDAG->getMachineNode(
Opc, SL, MVT::i64,
Ops);
1273void AMDGPUDAGToDAGISel::SelectMUL_LOHI(
SDNode *
N) {
1278 if (Subtarget->hasMadNC64_32Insts()) {
1279 VTList =
CurDAG->getVTList(MVT::i64);
1280 Opc =
Signed ? AMDGPU::V_MAD_NC_I64_I32_e64 : AMDGPU::V_MAD_NC_U64_U32_e64;
1282 VTList =
CurDAG->getVTList(MVT::i64, MVT::i1);
1283 if (Subtarget->hasMADIntraFwdBug()) {
1284 Opc =
Signed ? AMDGPU::V_MAD_I64_I32_gfx11_e64
1285 : AMDGPU::V_MAD_U64_U32_gfx11_e64;
1287 Opc =
Signed ? AMDGPU::V_MAD_I64_I32_e64 : AMDGPU::V_MAD_U64_U32_e64;
1294 SDNode *Mad =
CurDAG->getMachineNode(
Opc, SL, VTList,
Ops);
1296 SDValue Sub0 =
CurDAG->getTargetConstant(AMDGPU::sub0, SL, MVT::i32);
1297 SDNode *
Lo =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, SL,
1298 MVT::i32,
SDValue(Mad, 0), Sub0);
1302 SDValue Sub1 =
CurDAG->getTargetConstant(AMDGPU::sub1, SL, MVT::i32);
1303 SDNode *
Hi =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, SL,
1304 MVT::i32,
SDValue(Mad, 0), Sub1);
1314 if (!
Base || Subtarget->hasUsableDSOffset() ||
1315 Subtarget->unsafeDSOffsetFoldingEnabled())
1326 if (
CurDAG->isBaseWithConstantOffset(Addr)) {
1339 int64_t ByteOffset =
C->getSExtValue();
1340 if (isDSOffsetLegal(
SDValue(), ByteOffset)) {
1349 if (isDSOffsetLegal(
Sub, ByteOffset)) {
1355 unsigned SubOp = AMDGPU::V_SUB_CO_U32_e32;
1356 if (Subtarget->hasAddNoCarryInsts()) {
1357 SubOp = AMDGPU::V_SUB_U32_e64;
1359 CurDAG->getTargetConstant(0, {}, MVT::i1));
1362 MachineSDNode *MachineSub =
1363 CurDAG->getMachineNode(SubOp,
DL, MVT::i32, Opnds);
1379 if (isDSOffsetLegal(
SDValue(), CAddr->getZExtValue())) {
1381 MachineSDNode *MovZero =
CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32,
1382 DL, MVT::i32, Zero);
1384 Offset =
CurDAG->getTargetConstant(CAddr->getZExtValue(),
DL, MVT::i16);
1391 Offset =
CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i16);
1395bool AMDGPUDAGToDAGISel::isDSOffset2Legal(
SDValue Base,
unsigned Offset0,
1397 unsigned Size)
const {
1398 if (Offset0 %
Size != 0 || Offset1 %
Size != 0)
1403 if (!
Base || Subtarget->hasUsableDSOffset() ||
1404 Subtarget->unsafeDSOffsetFoldingEnabled())
1422bool AMDGPUDAGToDAGISel::isFlatScratchBaseLegal(
SDValue Addr)
const {
1428 if (Subtarget->hasSignedScratchOffsets())
1438 ConstantSDNode *ImmOp =
nullptr;
1449bool AMDGPUDAGToDAGISel::isFlatScratchBaseLegalSV(
SDValue Addr)
const {
1455 if (Subtarget->hasSignedScratchOffsets())
1465bool AMDGPUDAGToDAGISel::isFlatScratchBaseLegalSVImm(
SDValue Addr)
const {
1479 (RHSImm->getSExtValue() < 0 && RHSImm->getSExtValue() > -0x40000000)))
1482 auto LHS =
Base.getOperand(0);
1483 auto RHS =
Base.getOperand(1);
1491 return SelectDSReadWrite2(Addr,
Base, Offset0, Offset1, 4);
1497 return SelectDSReadWrite2(Addr,
Base, Offset0, Offset1, 8);
1502 unsigned Size)
const {
1505 if (
CurDAG->isBaseWithConstantOffset(Addr)) {
1510 unsigned OffsetValue1 = OffsetValue0 +
Size;
1513 if (isDSOffset2Legal(N0, OffsetValue0, OffsetValue1,
Size)) {
1515 Offset0 =
CurDAG->getTargetConstant(OffsetValue0 /
Size,
DL, MVT::i32);
1516 Offset1 =
CurDAG->getTargetConstant(OffsetValue1 /
Size,
DL, MVT::i32);
1521 if (
const ConstantSDNode *
C =
1523 unsigned OffsetValue0 =
C->getZExtValue();
1524 unsigned OffsetValue1 = OffsetValue0 +
Size;
1526 if (isDSOffset2Legal(
SDValue(), OffsetValue0, OffsetValue1,
Size)) {
1536 if (isDSOffset2Legal(
Sub, OffsetValue0, OffsetValue1,
Size)) {
1540 unsigned SubOp = AMDGPU::V_SUB_CO_U32_e32;
1541 if (Subtarget->hasAddNoCarryInsts()) {
1542 SubOp = AMDGPU::V_SUB_U32_e64;
1544 CurDAG->getTargetConstant(0, {}, MVT::i1));
1547 MachineSDNode *MachineSub =
CurDAG->getMachineNode(
1552 CurDAG->getTargetConstant(OffsetValue0 /
Size,
DL, MVT::i32);
1554 CurDAG->getTargetConstant(OffsetValue1 /
Size,
DL, MVT::i32);
1560 unsigned OffsetValue0 = CAddr->getZExtValue();
1561 unsigned OffsetValue1 = OffsetValue0 +
Size;
1563 if (isDSOffset2Legal(
SDValue(), OffsetValue0, OffsetValue1,
Size)) {
1565 MachineSDNode *MovZero =
1566 CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32,
DL, MVT::i32, Zero);
1568 Offset0 =
CurDAG->getTargetConstant(OffsetValue0 /
Size,
DL, MVT::i32);
1569 Offset1 =
CurDAG->getTargetConstant(OffsetValue1 /
Size,
DL, MVT::i32);
1577 Offset0 =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1578 Offset1 =
CurDAG->getTargetConstant(1,
DL, MVT::i32);
1588 if (Subtarget->useFlatForGlobal())
1593 Idxen =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
1594 Offen =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
1595 Addr64 =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
1596 SOffset = Subtarget->hasRestrictedSOffset()
1597 ?
CurDAG->getRegister(AMDGPU::SGPR_NULL, MVT::i32)
1598 :
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1600 ConstantSDNode *C1 =
nullptr;
1602 if (
CurDAG->isBaseWithConstantOffset(Addr)) {
1615 Addr64 =
CurDAG->getTargetConstant(1,
DL, MVT::i1);
1621 Ptr =
SDValue(buildSMovImm64(
DL, 0, MVT::v2i32), 0);
1637 Ptr =
SDValue(buildSMovImm64(
DL, 0, MVT::v2i32), 0);
1639 Addr64 =
CurDAG->getTargetConstant(1,
DL, MVT::i1);
1643 VAddr =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1653 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
1664 AMDGPU::S_MOV_B32,
DL, MVT::i32,
1670bool AMDGPUDAGToDAGISel::SelectMUBUFAddr64(
SDValue Addr,
SDValue &SRsrc,
1673 SDValue Ptr, Offen, Idxen, Addr64;
1677 if (!Subtarget->hasAddr64())
1680 if (!SelectMUBUF(Addr, Ptr, VAddr, SOffset,
Offset, Offen, Idxen, Addr64))
1684 if (
C->getSExtValue()) {
1697std::pair<SDValue, SDValue> AMDGPUDAGToDAGISel::foldFrameIndex(
SDValue N)
const {
1702 FI ?
CurDAG->getTargetFrameIndex(FI->getIndex(), FI->getValueType(0)) :
N;
1708 return std::pair(TFI,
CurDAG->getTargetConstant(0,
DL, MVT::i32));
1711bool AMDGPUDAGToDAGISel::SelectMUBUFScratchOffen(
SDNode *Parent,
1718 const SIMachineFunctionInfo *
Info =
MF.getInfo<SIMachineFunctionInfo>();
1720 Rsrc =
CurDAG->getRegister(
Info->getScratchRSrcReg(), MVT::v4i32);
1723 int64_t
Imm = CAddr->getSExtValue();
1724 const int64_t NullPtr =
1727 if (
Imm != NullPtr) {
1730 CurDAG->getTargetConstant(
Imm & ~MaxOffset,
DL, MVT::i32);
1731 MachineSDNode *MovHighBits =
CurDAG->getMachineNode(
1732 AMDGPU::V_MOV_B32_e32,
DL, MVT::i32, HighBits);
1733 VAddr =
SDValue(MovHighBits, 0);
1735 SOffset =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1736 ImmOffset =
CurDAG->getTargetConstant(
Imm & MaxOffset,
DL, MVT::i32);
1741 if (
CurDAG->isBaseWithConstantOffset(Addr)) {
1762 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
1763 if (
TII->isLegalMUBUFImmOffset(C1) &&
1764 (!Subtarget->privateMemoryResourceIsRangeChecked() ||
1765 CurDAG->SignBitIsZero(N0))) {
1766 std::tie(VAddr, SOffset) = foldFrameIndex(N0);
1767 ImmOffset =
CurDAG->getTargetConstant(C1,
DL, MVT::i32);
1773 std::tie(VAddr, SOffset) = foldFrameIndex(Addr);
1774 ImmOffset =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1782 if (!
Reg.isPhysical())
1784 const auto *RC =
TRI.getPhysRegBaseClass(
Reg);
1785 return RC &&
TRI.isSGPRClass(RC);
1788bool AMDGPUDAGToDAGISel::SelectMUBUFScratchOffset(
SDNode *Parent,
1793 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
1794 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
1796 const SIMachineFunctionInfo *
Info =
MF.getInfo<SIMachineFunctionInfo>();
1801 SRsrc =
CurDAG->getRegister(
Info->getScratchRSrcReg(), MVT::v4i32);
1807 ConstantSDNode *CAddr;
1820 SOffset =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1825 SRsrc =
CurDAG->getRegister(
Info->getScratchRSrcReg(), MVT::v4i32);
1831bool AMDGPUDAGToDAGISel::SelectMUBUFOffset(
SDValue Addr,
SDValue &SRsrc,
1834 SDValue Ptr, VAddr, Offen, Idxen, Addr64;
1835 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
1837 if (!SelectMUBUF(Addr, Ptr, VAddr, SOffset,
Offset, Offen, Idxen, Addr64))
1856bool AMDGPUDAGToDAGISel::SelectBUFSOffset(
SDValue ByteOffsetNode,
1858 if (Subtarget->hasRestrictedSOffset() &&
isNullConstant(ByteOffsetNode)) {
1859 SOffset =
CurDAG->getRegister(AMDGPU::SGPR_NULL, MVT::i32);
1863 SOffset = ByteOffsetNode;
1881bool AMDGPUDAGToDAGISel::SelectFlatOffsetImpl(
1885 int64_t OffsetVal = 0;
1889 bool CanHaveFlatSegmentOffsetBug =
1890 Subtarget->hasFlatSegmentOffsetBug() &&
1891 FlatVariant == FlatAddrSpace::FLAT &&
1894 if (Subtarget->hasFlatInstOffsets() && !CanHaveFlatSegmentOffsetBug) {
1896 if (isBaseWithConstantOffset64(Addr, N0, N1) &&
1897 (FlatVariant != FlatAddrSpace::FlatScratch ||
1898 isFlatScratchBaseLegal(Addr))) {
1906 if (COffsetVal == 0 || FlatVariant != FlatAddrSpace::FLAT || IsInBounds) {
1907 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
1908 if (
TII->isLegalFLATOffset(COffsetVal, AS, FlatVariant)) {
1910 OffsetVal = COffsetVal;
1925 std::tie(OffsetVal, RemainderOffset) =
1926 TII->splitFlatOffset(COffsetVal, AS, FlatVariant);
1929 getMaterializedScalarImm32(
Lo_32(RemainderOffset),
DL);
1936 unsigned AddOp = AMDGPU::V_ADD_CO_U32_e32;
1937 if (Subtarget->hasAddNoCarryInsts()) {
1938 AddOp = AMDGPU::V_ADD_U32_e64;
1947 CurDAG->getTargetConstant(AMDGPU::sub0,
DL, MVT::i32);
1949 CurDAG->getTargetConstant(AMDGPU::sub1,
DL, MVT::i32);
1951 SDNode *N0Lo =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
1952 DL, MVT::i32, N0, Sub0);
1953 SDNode *N0Hi =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
1954 DL, MVT::i32, N0, Sub1);
1957 getMaterializedScalarImm32(
Hi_32(RemainderOffset),
DL);
1959 SDVTList VTs =
CurDAG->getVTList(MVT::i32, MVT::i1);
1962 CurDAG->getMachineNode(AMDGPU::V_ADD_CO_U32_e64,
DL, VTs,
1963 {AddOffsetLo,
SDValue(N0Lo, 0), Clamp});
1965 SDNode *Addc =
CurDAG->getMachineNode(
1966 AMDGPU::V_ADDC_U32_e64,
DL, VTs,
1970 CurDAG->getTargetConstant(AMDGPU::VReg_64RegClassID,
DL,
1975 MVT::i64, RegSequenceArgs),
1984 Offset =
CurDAG->getSignedTargetConstant(OffsetVal, SDLoc(), MVT::i32);
1988bool AMDGPUDAGToDAGISel::SelectFlatOffset(
SDNode *
N,
SDValue Addr,
1991 return SelectFlatOffsetImpl(
N, Addr, VAddr,
Offset,
1995bool AMDGPUDAGToDAGISel::SelectGlobalOffset(
SDNode *
N,
SDValue Addr,
1998 return SelectFlatOffsetImpl(
N, Addr, VAddr,
Offset,
2002bool AMDGPUDAGToDAGISel::SelectScratchOffset(
SDNode *
N,
SDValue Addr,
2005 return SelectFlatOffsetImpl(
N, Addr, VAddr,
Offset,
2013 if (
Op.getValueType() == MVT::i32)
2028bool AMDGPUDAGToDAGISel::SelectGlobalSAddr(
SDNode *
N,
SDValue Addr,
2031 bool NeedIOffset)
const {
2033 int64_t ImmOffset = 0;
2034 ScaleOffset =
false;
2040 if (isBaseWithConstantOffset64(Addr,
LHS,
RHS)) {
2042 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
2046 FlatAddrSpace::FlatGlobal)) {
2048 ImmOffset = COffsetVal;
2049 }
else if (!
LHS->isDivergent()) {
2050 if (COffsetVal > 0) {
2055 int64_t SplitImmOffset = 0, RemainderOffset = COffsetVal;
2057 std::tie(SplitImmOffset, RemainderOffset) =
TII->splitFlatOffset(
2061 if (Subtarget->hasSignedGVSOffset() ?
isInt<32>(RemainderOffset)
2063 SDNode *VMov =
CurDAG->getMachineNode(
2064 AMDGPU::V_MOV_B32_e32, SL, MVT::i32,
2065 CurDAG->getTargetConstant(RemainderOffset, SDLoc(), MVT::i32));
2068 Offset =
CurDAG->getTargetConstant(SplitImmOffset, SDLoc(), MVT::i32);
2078 unsigned NumLiterals =
2079 !
TII->isInlineConstant(APInt(32,
Lo_32(COffsetVal))) +
2080 !
TII->isInlineConstant(APInt(32,
Hi_32(COffsetVal)));
2081 if (Subtarget->getConstantBusLimit(AMDGPU::V_ADD_U32_e64) > NumLiterals)
2090 if (!
LHS->isDivergent()) {
2093 ScaleOffset = SelectScaleOffset(
N,
RHS, Subtarget->hasSignedGVSOffset());
2095 RHS, Subtarget->hasSignedGVSOffset(),
CurDAG)) {
2102 if (!SAddr && !
RHS->isDivergent()) {
2104 ScaleOffset = SelectScaleOffset(
N,
LHS, Subtarget->hasSignedGVSOffset());
2106 LHS, Subtarget->hasSignedGVSOffset(),
CurDAG)) {
2113 Offset =
CurDAG->getSignedTargetConstant(ImmOffset, SDLoc(), MVT::i32);
2118 if (Subtarget->hasScaleOffset() &&
2119 (Addr.
getOpcode() == (Subtarget->hasSignedGVSOffset()
2134 Offset =
CurDAG->getTargetConstant(ImmOffset, SDLoc(), MVT::i32);
2146 CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32, SDLoc(Addr), MVT::i32,
2147 CurDAG->getTargetConstant(0, SDLoc(), MVT::i32));
2149 Offset =
CurDAG->getSignedTargetConstant(ImmOffset, SDLoc(), MVT::i32);
2153bool AMDGPUDAGToDAGISel::SelectGlobalSAddr(
SDNode *
N,
SDValue Addr,
2158 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset,
Offset, ScaleOffset))
2166bool AMDGPUDAGToDAGISel::SelectGlobalSAddrCPol(
SDNode *
N,
SDValue Addr,
2171 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset,
Offset, ScaleOffset))
2176 N->getConstantOperandVal(
N->getNumOperands() - 1) & ~AMDGPU::CPol::SCAL;
2182bool AMDGPUDAGToDAGISel::SelectGlobalSAddrCPolM0(
SDNode *
N,
SDValue Addr,
2188 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset,
Offset, ScaleOffset))
2193 N->getConstantOperandVal(
N->getNumOperands() - 2) & ~AMDGPU::CPol::SCAL;
2199bool AMDGPUDAGToDAGISel::SelectGlobalSAddrGLC(
SDNode *
N,
SDValue Addr,
2204 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset,
Offset, ScaleOffset))
2208 CPol =
CurDAG->getTargetConstant(CPolVal, SDLoc(), MVT::i32);
2212bool AMDGPUDAGToDAGISel::SelectGlobalSAddrNoIOffset(
SDNode *
N,
SDValue Addr,
2218 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset, DummyOffset, ScaleOffset,
2224 N->getConstantOperandVal(
N->getNumOperands() - 1) & ~AMDGPU::CPol::SCAL;
2230bool AMDGPUDAGToDAGISel::SelectGlobalSAddrNoIOffsetM0(
SDNode *
N,
SDValue Addr,
2236 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset, DummyOffset, ScaleOffset,
2257 FI->getValueType(0));
2267bool AMDGPUDAGToDAGISel::SelectScratchSAddr(
SDNode *Parent,
SDValue Addr,
2276 int64_t COffsetVal = 0;
2278 if (
CurDAG->isBaseWithConstantOffset(Addr) && isFlatScratchBaseLegal(Addr)) {
2287 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
2290 FlatAddrSpace::FlatScratch)) {
2291 int64_t SplitImmOffset, RemainderOffset;
2292 std::tie(SplitImmOffset, RemainderOffset) =
TII->splitFlatOffset(
2295 COffsetVal = SplitImmOffset;
2299 ? getMaterializedScalarImm32(
Lo_32(RemainderOffset),
DL)
2300 :
CurDAG->getSignedTargetConstant(RemainderOffset,
DL, MVT::i32);
2301 SAddr =
SDValue(
CurDAG->getMachineNode(AMDGPU::S_ADD_I32,
DL, MVT::i32,
2306 Offset =
CurDAG->getSignedTargetConstant(COffsetVal,
DL, MVT::i32);
2312bool AMDGPUDAGToDAGISel::checkFlatScratchSVSSwizzleBug(
2314 if (!Subtarget->hasFlatScratchSVSSwizzleBug())
2320 KnownBits VKnown =
CurDAG->computeKnownBits(VAddr);
2327 return (VMax & 3) + (
SMax & 3) >= 4;
2330bool AMDGPUDAGToDAGISel::SelectScratchSVAddr(
SDNode *
N,
SDValue Addr,
2334 int64_t ImmOffset = 0;
2338 if (isBaseWithConstantOffset64(Addr,
LHS,
RHS)) {
2340 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
2345 ImmOffset = COffsetVal;
2346 }
else if (!
LHS->isDivergent() && COffsetVal > 0) {
2350 int64_t SplitImmOffset, RemainderOffset;
2351 std::tie(SplitImmOffset, RemainderOffset) =
2356 SDNode *VMov =
CurDAG->getMachineNode(
2357 AMDGPU::V_MOV_B32_e32, SL, MVT::i32,
2358 CurDAG->getTargetConstant(RemainderOffset, SDLoc(), MVT::i32));
2361 if (!isFlatScratchBaseLegal(Addr))
2363 if (checkFlatScratchSVSSwizzleBug(VAddr, SAddr, SplitImmOffset))
2365 Offset =
CurDAG->getTargetConstant(SplitImmOffset, SDLoc(), MVT::i32);
2366 CPol =
CurDAG->getTargetConstant(0, SDLoc(), MVT::i32);
2378 if (!
LHS->isDivergent() &&
RHS->isDivergent()) {
2381 }
else if (!
RHS->isDivergent() &&
LHS->isDivergent()) {
2388 if (OrigAddr != Addr) {
2389 if (!isFlatScratchBaseLegalSVImm(OrigAddr))
2392 if (!isFlatScratchBaseLegalSV(OrigAddr))
2396 if (checkFlatScratchSVSSwizzleBug(VAddr, SAddr, ImmOffset))
2399 Offset =
CurDAG->getSignedTargetConstant(ImmOffset, SDLoc(), MVT::i32);
2401 bool ScaleOffset = SelectScaleOffset(
N, VAddr,
true );
2410bool AMDGPUDAGToDAGISel::isSOffsetLegalWithImmOffset(
SDValue *SOffset,
2413 int64_t ImmOffset)
const {
2414 if (!IsBuffer && !Imm32Only && ImmOffset < 0 &&
2416 KnownBits SKnown =
CurDAG->computeKnownBits(*SOffset);
2428 bool IsSigned)
const {
2429 bool ScaleOffset =
false;
2430 if (!Subtarget->hasScaleOffset() || !
Offset)
2444 (IsSigned &&
Offset.getOpcode() == AMDGPUISD::MUL_I24) ||
2445 Offset.getOpcode() == AMDGPUISD::MUL_U24 ||
2446 (
Offset.isMachineOpcode() &&
2447 Offset.getMachineOpcode() ==
2448 (IsSigned ? AMDGPU::S_MUL_I64_I32_PSEUDO
2449 : AMDGPU::S_MUL_U64_U32_PSEUDO))) {
2451 ScaleOffset =
C->getZExtValue() ==
Size;
2463bool AMDGPUDAGToDAGISel::SelectSMRDOffset(
SDNode *
N,
SDValue ByteOffsetNode,
2465 bool Imm32Only,
bool IsBuffer,
2466 bool HasSOffset, int64_t ImmOffset,
2467 bool *ScaleOffset)
const {
2469 "Cannot match both soffset and offset at the same time!");
2474 *ScaleOffset = SelectScaleOffset(
N, ByteOffsetNode,
false );
2484 *SOffset = ByteOffsetNode;
2485 return isSOffsetLegalWithImmOffset(SOffset, Imm32Only, IsBuffer,
2491 return isSOffsetLegalWithImmOffset(SOffset, Imm32Only, IsBuffer,
2498 SDLoc SL(ByteOffsetNode);
2502 int64_t ByteOffset = IsBuffer ?
C->getZExtValue() :
C->getSExtValue();
2504 *Subtarget, ByteOffset, IsBuffer, HasSOffset);
2505 if (EncodedOffset &&
Offset && !Imm32Only) {
2506 *
Offset =
CurDAG->getSignedTargetConstant(*EncodedOffset, SL, MVT::i32);
2515 if (EncodedOffset &&
Offset && Imm32Only) {
2516 *
Offset =
CurDAG->getTargetConstant(*EncodedOffset, SL, MVT::i32);
2524 SDValue C32Bit =
CurDAG->getTargetConstant(ByteOffset, SL, MVT::i32);
2526 CurDAG->getMachineNode(AMDGPU::S_MOV_B32, SL, MVT::i32, C32Bit), 0);
2533SDValue AMDGPUDAGToDAGISel::Expand32BitAddress(
SDValue Addr)
const {
2541 const SIMachineFunctionInfo *
Info =
MF.getInfo<SIMachineFunctionInfo>();
2542 unsigned AddrHiVal =
Info->get32BitAddressHighBits();
2543 SDValue AddrHi =
CurDAG->getTargetConstant(AddrHiVal, SL, MVT::i32);
2546 CurDAG->getTargetConstant(AMDGPU::SReg_64_XEXECRegClassID, SL, MVT::i32),
2548 CurDAG->getTargetConstant(AMDGPU::sub0, SL, MVT::i32),
2549 SDValue(
CurDAG->getMachineNode(AMDGPU::S_MOV_B32, SL, MVT::i32, AddrHi),
2551 CurDAG->getTargetConstant(AMDGPU::sub1, SL, MVT::i32),
2554 return SDValue(
CurDAG->getMachineNode(AMDGPU::REG_SEQUENCE, SL, MVT::i64,
2561bool AMDGPUDAGToDAGISel::SelectSMRDBaseOffset(
SDNode *
N,
SDValue Addr,
2564 bool IsBuffer,
bool HasSOffset,
2566 bool *ScaleOffset)
const {
2568 assert(!Imm32Only && !IsBuffer);
2571 if (!SelectSMRDBaseOffset(
N, Addr,
B,
nullptr,
Offset,
false,
false,
true))
2576 ImmOff =
C->getSExtValue();
2578 return SelectSMRDBaseOffset(
N,
B, SBase, SOffset,
nullptr,
false,
false,
2579 true, ImmOff, ScaleOffset);
2599 if (SelectSMRDOffset(
N, N1, SOffset,
Offset, Imm32Only, IsBuffer, HasSOffset,
2600 ImmOffset, ScaleOffset)) {
2604 if (SelectSMRDOffset(
N, N0, SOffset,
Offset, Imm32Only, IsBuffer, HasSOffset,
2605 ImmOffset, ScaleOffset)) {
2614 bool Imm32Only,
bool *ScaleOffset)
const {
2615 if (SelectSMRDBaseOffset(
N, Addr, SBase, SOffset,
Offset, Imm32Only,
2618 SBase = Expand32BitAddress(SBase);
2623 SBase = Expand32BitAddress(Addr);
2624 *
Offset =
CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
2631bool AMDGPUDAGToDAGISel::SelectSMRDImm(
SDValue Addr,
SDValue &SBase,
2633 return SelectSMRD(
nullptr, Addr, SBase,
nullptr,
2637bool AMDGPUDAGToDAGISel::SelectSMRDImm32(
SDValue Addr,
SDValue &SBase,
2640 return SelectSMRD(
nullptr, Addr, SBase,
nullptr,
2647 if (!SelectSMRD(
N, Addr, SBase, &SOffset,
nullptr,
2648 false, &ScaleOffset))
2652 SDLoc(
N), MVT::i32);
2656bool AMDGPUDAGToDAGISel::SelectSMRDSgprImm(
SDNode *
N,
SDValue Addr,
2661 if (!SelectSMRD(
N, Addr, SBase, &SOffset, &
Offset,
false, &ScaleOffset))
2665 SDLoc(
N), MVT::i32);
2670 return SelectSMRDOffset(
nullptr,
N,
nullptr, &
Offset,
2674bool AMDGPUDAGToDAGISel::SelectSMRDBufferImm32(
SDValue N,
2677 return SelectSMRDOffset(
nullptr,
N,
nullptr, &
Offset,
2681bool AMDGPUDAGToDAGISel::SelectSMRDBufferSgprImm(
SDValue N,
SDValue &SOffset,
2685 return N.getValueType() == MVT::i32 &&
2686 SelectSMRDBaseOffset(
nullptr,
N, SOffset,
2691bool AMDGPUDAGToDAGISel::SelectMOVRELOffset(
SDValue Index,
2696 if (
CurDAG->isBaseWithConstantOffset(Index)) {
2721SDNode *AMDGPUDAGToDAGISel::getBFE32(
bool IsSigned,
const SDLoc &
DL,
2725 unsigned Opcode = IsSigned ? AMDGPU::V_BFE_I32_e64 : AMDGPU::V_BFE_U32_e64;
2729 return CurDAG->getMachineNode(Opcode,
DL, MVT::i32, Val, Off, W);
2731 unsigned Opcode = IsSigned ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32;
2735 uint32_t PackedVal =
Offset | (Width << 16);
2736 SDValue PackedConst =
CurDAG->getTargetConstant(PackedVal,
DL, MVT::i32);
2738 return CurDAG->getMachineNode(Opcode,
DL, MVT::i32, Val, PackedConst);
2741void AMDGPUDAGToDAGISel::SelectS_BFEFromShifts(
SDNode *
N) {
2746 const SDValue &Shl =
N->getOperand(0);
2751 uint32_t BVal =
B->getZExtValue();
2752 uint32_t CVal =
C->getZExtValue();
2754 if (0 < BVal && BVal <= CVal && CVal < 32) {
2764void AMDGPUDAGToDAGISel::SelectS_BFE(
SDNode *
N) {
2765 switch (
N->getOpcode()) {
2767 if (
N->getOperand(0).getOpcode() ==
ISD::SRL) {
2770 const SDValue &Srl =
N->getOperand(0);
2774 if (Shift && Mask) {
2776 uint32_t MaskVal =
Mask->getZExtValue();
2788 if (
N->getOperand(0).getOpcode() ==
ISD::AND) {
2795 if (Shift && Mask) {
2797 uint32_t MaskVal =
Mask->getZExtValue() >> ShiftVal;
2806 }
else if (
N->getOperand(0).getOpcode() ==
ISD::SHL) {
2807 SelectS_BFEFromShifts(
N);
2812 if (
N->getOperand(0).getOpcode() ==
ISD::SHL) {
2813 SelectS_BFEFromShifts(
N);
2828 unsigned Width =
cast<VTSDNode>(
N->getOperand(1))->getVT().getSizeInBits();
2838bool AMDGPUDAGToDAGISel::isCBranchSCC(
const SDNode *
N)
const {
2840 if (!
N->hasOneUse())
2850 MVT VT =
Cond.getOperand(0).getSimpleValueType();
2854 if (VT == MVT::i64) {
2857 Subtarget->hasScalarCompareEq64();
2860 if ((VT == MVT::f16 || VT == MVT::f32) && Subtarget->hasSALUFloatInsts())
2893void AMDGPUDAGToDAGISel::SelectBRCOND(
SDNode *
N) {
2896 if (
Cond.isUndef()) {
2897 CurDAG->SelectNodeTo(
N, AMDGPU::SI_BR_UNDEF, MVT::Other,
2898 N->getOperand(2),
N->getOperand(0));
2902 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
2904 bool UseSCCBr = isCBranchSCC(
N) && isUniformBr(
N);
2905 bool AndExec = !UseSCCBr;
2906 bool Negate =
false;
2909 Cond->getOperand(0)->getOpcode() == AMDGPUISD::SETCC) {
2924 bool NegatedBallot =
false;
2927 UseSCCBr = !BallotCond->isDivergent();
2928 Negate = Negate ^ NegatedBallot;
2943 UseSCCBr ? (Negate ? AMDGPU::S_CBRANCH_SCC0 : AMDGPU::S_CBRANCH_SCC1)
2944 : (Negate ? AMDGPU::S_CBRANCH_VCCZ : AMDGPU::S_CBRANCH_VCCNZ);
2945 Register CondReg = UseSCCBr ? AMDGPU::SCC :
TRI->getVCC();
2964 Subtarget->isWave32() ? AMDGPU::S_AND_B32 : AMDGPU::S_AND_B64, SL,
2966 CurDAG->getRegister(Subtarget->isWave32() ? AMDGPU::EXEC_LO
2974 CurDAG->SelectNodeTo(
N, BrOp, MVT::Other,
2979void AMDGPUDAGToDAGISel::SelectFP_EXTEND(
SDNode *
N) {
2980 if (Subtarget->hasSALUFloatInsts() &&
N->getValueType(0) == MVT::f32 &&
2981 !
N->isDivergent()) {
2983 if (Src.getValueType() == MVT::f16) {
2985 CurDAG->SelectNodeTo(
N, AMDGPU::S_CVT_HI_F32_F16,
N->getVTList(),
2995void AMDGPUDAGToDAGISel::SelectDSAppendConsume(
SDNode *
N,
unsigned IntrID) {
2998 unsigned Opc = IntrID == Intrinsic::amdgcn_ds_append ?
2999 AMDGPU::DS_APPEND : AMDGPU::DS_CONSUME;
3004 MachineMemOperand *MMO =
M->getMemOperand();
3008 if (
CurDAG->isBaseWithConstantOffset(Ptr)) {
3013 if (isDSOffsetLegal(PtrBase, OffsetVal.
getZExtValue())) {
3014 N = glueCopyToM0(
N, PtrBase);
3015 Offset =
CurDAG->getTargetConstant(OffsetVal, SDLoc(), MVT::i32);
3020 N = glueCopyToM0(
N, Ptr);
3021 Offset =
CurDAG->getTargetConstant(0, SDLoc(), MVT::i32);
3026 CurDAG->getTargetConstant(IsGDS, SDLoc(), MVT::i32),
3031 SDNode *Selected =
CurDAG->SelectNodeTo(
N,
Opc,
N->getVTList(),
Ops);
3037void AMDGPUDAGToDAGISel::SelectDSBvhStackIntrinsic(
SDNode *
N,
unsigned IntrID) {
3040 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
3041 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
3042 Opc = AMDGPU::DS_BVH_STACK_RTN_B32;
3044 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
3045 Opc = AMDGPU::DS_BVH_STACK_PUSH8_POP1_RTN_B32;
3047 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn:
3048 Opc = AMDGPU::DS_BVH_STACK_PUSH8_POP2_RTN_B64;
3051 SDValue Ops[] = {
N->getOperand(2),
N->getOperand(3),
N->getOperand(4),
3052 N->getOperand(5),
N->getOperand(0)};
3055 MachineMemOperand *MMO =
M->getMemOperand();
3056 SDNode *Selected =
CurDAG->SelectNodeTo(
N,
Opc,
N->getVTList(),
Ops);
3060void AMDGPUDAGToDAGISel::SelectTensorLoadStore(
SDNode *
N,
unsigned IntrID) {
3061 bool IsLoad = IntrID == Intrinsic::amdgcn_tensor_load_to_lds;
3063 IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d4 : AMDGPU::TENSOR_STORE_FROM_LDS_d4;
3075 Opc = IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d2
3076 : AMDGPU::TENSOR_STORE_FROM_LDS_d2;
3088 (void)
CurDAG->SelectNodeTo(
N,
Opc, MVT::Other, TensorOps);
3093 case Intrinsic::amdgcn_ds_gws_init:
3094 return AMDGPU::DS_GWS_INIT;
3095 case Intrinsic::amdgcn_ds_gws_barrier:
3096 return AMDGPU::DS_GWS_BARRIER;
3097 case Intrinsic::amdgcn_ds_gws_sema_v:
3098 return AMDGPU::DS_GWS_SEMA_V;
3099 case Intrinsic::amdgcn_ds_gws_sema_br:
3100 return AMDGPU::DS_GWS_SEMA_BR;
3101 case Intrinsic::amdgcn_ds_gws_sema_p:
3102 return AMDGPU::DS_GWS_SEMA_P;
3103 case Intrinsic::amdgcn_ds_gws_sema_release_all:
3104 return AMDGPU::DS_GWS_SEMA_RELEASE_ALL;
3110void AMDGPUDAGToDAGISel::SelectDS_GWS(
SDNode *
N,
unsigned IntrID) {
3111 if (!Subtarget->hasGWS() ||
3112 (IntrID == Intrinsic::amdgcn_ds_gws_sema_release_all &&
3113 !Subtarget->hasGWSSemaReleaseAll())) {
3120 const bool HasVSrc =
N->getNumOperands() == 4;
3121 assert(HasVSrc ||
N->getNumOperands() == 3);
3124 SDValue BaseOffset =
N->getOperand(HasVSrc ? 3 : 2);
3127 MachineMemOperand *MMO =
M->getMemOperand();
3140 glueCopyToM0(
N,
CurDAG->getTargetConstant(0, SL, MVT::i32));
3141 ImmOffset = ConstOffset->getZExtValue();
3143 if (
CurDAG->isBaseWithConstantOffset(BaseOffset)) {
3152 =
CurDAG->getMachineNode(AMDGPU::V_READFIRSTLANE_B32, SL, MVT::i32,
3156 =
CurDAG->getMachineNode(AMDGPU::S_LSHL_B32, SL, MVT::i32,
3158 CurDAG->getTargetConstant(16, SL, MVT::i32));
3159 glueCopyToM0(
N,
SDValue(M0Base, 0));
3163 SDValue OffsetField =
CurDAG->getTargetConstant(ImmOffset, SL, MVT::i32);
3167 const MCInstrDesc &InstrDesc =
TII->get(
Opc);
3168 int Data0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
3174 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3177 MVT DataVT =
Data.getValueType().getSimpleVT();
3178 if (
TRI->isTypeLegalForClass(*DataRC, DataVT)) {
3180 Ops.push_back(
N->getOperand(2));
3186 CurDAG->getTargetConstant(AMDGPU::sub0, SL, MVT::i32),
3188 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, SL, MVT::i32),
3190 CurDAG->getTargetConstant(AMDGPU::sub1, SL, MVT::i32)};
3193 SL, MVT::v2i32, RegSeqOps),
3198 Ops.push_back(OffsetField);
3199 Ops.push_back(Chain);
3201 SDNode *Selected =
CurDAG->SelectNodeTo(
N,
Opc,
N->getVTList(),
Ops);
3205void AMDGPUDAGToDAGISel::SelectInterpP1F16(
SDNode *
N) {
3206 if (Subtarget->getLDSBankCount() != 16) {
3236 SDVTList VTs =
CurDAG->getVTList(MVT::f32, MVT::Other);
3239 CurDAG->getMachineNode(AMDGPU::V_INTERP_MOV_F32,
DL, VTs, {
3240 CurDAG->getTargetConstant(2,
DL, MVT::i32),
3246 SDNode *InterpP1LV =
3247 CurDAG->getMachineNode(AMDGPU::V_INTERP_P1LV_F16,
DL, MVT::f32, {
3248 CurDAG->getTargetConstant(0,
DL, MVT::i32),
3252 CurDAG->getTargetConstant(0,
DL, MVT::i32),
3255 CurDAG->getTargetConstant(0,
DL, MVT::i1),
3256 CurDAG->getTargetConstant(0,
DL, MVT::i32),
3263void AMDGPUDAGToDAGISel::SelectINTRINSIC_W_CHAIN(
SDNode *
N) {
3264 unsigned IntrID =
N->getConstantOperandVal(1);
3266 case Intrinsic::amdgcn_ds_append:
3267 case Intrinsic::amdgcn_ds_consume: {
3268 if (
N->getValueType(0) != MVT::i32)
3270 SelectDSAppendConsume(
N, IntrID);
3273 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
3274 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
3275 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
3276 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn:
3277 SelectDSBvhStackIntrinsic(
N, IntrID);
3279 case Intrinsic::amdgcn_init_whole_wave:
3280 CurDAG->getMachineFunction()
3281 .getInfo<SIMachineFunctionInfo>()
3282 ->setInitWholeWave();
3289void AMDGPUDAGToDAGISel::SelectINTRINSIC_WO_CHAIN(
SDNode *
N) {
3290 unsigned IntrID =
N->getConstantOperandVal(0);
3291 unsigned Opcode = AMDGPU::INSTRUCTION_LIST_END;
3292 SDNode *ConvGlueNode =
N->getGluedNode();
3298 CurDAG->getMachineNode(TargetOpcode::CONVERGENCECTRL_GLUE, {},
3299 MVT::Glue,
SDValue(ConvGlueNode, 0));
3301 ConvGlueNode =
nullptr;
3304 case Intrinsic::amdgcn_wqm:
3305 Opcode = AMDGPU::WQM;
3307 case Intrinsic::amdgcn_softwqm:
3308 Opcode = AMDGPU::SOFT_WQM;
3310 case Intrinsic::amdgcn_wwm:
3311 case Intrinsic::amdgcn_strict_wwm:
3312 Opcode = AMDGPU::STRICT_WWM;
3314 case Intrinsic::amdgcn_strict_wqm:
3315 Opcode = AMDGPU::STRICT_WQM;
3317 case Intrinsic::amdgcn_interp_p1_f16:
3318 SelectInterpP1F16(
N);
3320 case Intrinsic::amdgcn_permlane16_swap:
3321 case Intrinsic::amdgcn_permlane32_swap: {
3322 if ((IntrID == Intrinsic::amdgcn_permlane16_swap &&
3323 !Subtarget->hasPermlane16Swap()) ||
3324 (IntrID == Intrinsic::amdgcn_permlane32_swap &&
3325 !Subtarget->hasPermlane32Swap())) {
3330 Opcode = IntrID == Intrinsic::amdgcn_permlane16_swap
3331 ? AMDGPU::V_PERMLANE16_SWAP_B32_e64
3332 : AMDGPU::V_PERMLANE32_SWAP_B32_e64;
3336 NewOps.push_back(
SDValue(ConvGlueNode, 0));
3338 bool FI =
N->getConstantOperandVal(3);
3339 NewOps[2] =
CurDAG->getTargetConstant(
3342 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(), NewOps);
3350 if (Opcode != AMDGPU::INSTRUCTION_LIST_END) {
3352 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(), {Src});
3357 NewOps.push_back(
SDValue(ConvGlueNode, 0));
3358 CurDAG->MorphNodeTo(
N,
N->getOpcode(),
N->getVTList(), NewOps);
3362void AMDGPUDAGToDAGISel::SelectINTRINSIC_VOID(
SDNode *
N) {
3363 unsigned IntrID =
N->getConstantOperandVal(1);
3365 case Intrinsic::amdgcn_ds_gws_init:
3366 case Intrinsic::amdgcn_ds_gws_barrier:
3367 case Intrinsic::amdgcn_ds_gws_sema_v:
3368 case Intrinsic::amdgcn_ds_gws_sema_br:
3369 case Intrinsic::amdgcn_ds_gws_sema_p:
3370 case Intrinsic::amdgcn_ds_gws_sema_release_all:
3371 SelectDS_GWS(
N, IntrID);
3373 case Intrinsic::amdgcn_tensor_load_to_lds:
3374 case Intrinsic::amdgcn_tensor_store_from_lds:
3375 SelectTensorLoadStore(
N, IntrID);
3384void AMDGPUDAGToDAGISel::SelectWAVE_ADDRESS(
SDNode *
N) {
3386 CurDAG->getTargetConstant(Subtarget->getWavefrontSizeLog2(), SDLoc(
N), MVT::i32);
3387 CurDAG->SelectNodeTo(
N, AMDGPU::S_LSHR_B32,
N->getVTList(),
3388 {N->getOperand(0), Log2WaveSize});
3391void AMDGPUDAGToDAGISel::SelectSTACKRESTORE(
SDNode *
N) {
3406 Subtarget->getWavefrontSizeLog2(), SL, MVT::i32);
3408 if (
N->isDivergent()) {
3409 SrcVal =
SDValue(
CurDAG->getMachineNode(AMDGPU::V_READFIRSTLANE_B32, SL,
3414 CopyVal =
SDValue(
CurDAG->getMachineNode(AMDGPU::S_LSHL_B32, SL, MVT::i32,
3415 {SrcVal, Log2WaveSize}),
3419 SDValue CopyToSP =
CurDAG->getCopyToReg(
N->getOperand(0), SL,
SP, CopyVal);
3423bool AMDGPUDAGToDAGISel::SelectVOP3ModsImpl(
SDValue In,
SDValue &Src,
3425 bool IsCanonicalizing,
3426 bool AllowAbs)
const {
3432 Src = Src.getOperand(0);
3433 }
else if (Src.getOpcode() ==
ISD::FSUB && IsCanonicalizing) {
3437 if (
LHS &&
LHS->isZero()) {
3439 Src = Src.getOperand(1);
3443 if (AllowAbs && Src.getOpcode() ==
ISD::FABS) {
3445 Src = Src.getOperand(0);
3458 if (IsCanonicalizing)
3473 EVT VT = Src.getValueType();
3475 (VT != MVT::i32 && VT != MVT::v2i32 && VT != MVT::i64))
3482 auto ReplaceSrc = [&]() ->
SDValue {
3484 return Src.getOperand(0);
3489 Src.getValueType(),
LHS, Index);
3515 if (SelectVOP3ModsImpl(In, Src, Mods,
true,
3517 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3524bool AMDGPUDAGToDAGISel::SelectVOP3ModsNonCanonicalizing(
3527 if (SelectVOP3ModsImpl(In, Src, Mods,
false,
3529 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3536bool AMDGPUDAGToDAGISel::SelectVOP3BMods(
SDValue In,
SDValue &Src,
3539 if (SelectVOP3ModsImpl(In, Src, Mods,
3542 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3549bool AMDGPUDAGToDAGISel::SelectVOP3NoMods(
SDValue In,
SDValue &Src)
const {
3557bool AMDGPUDAGToDAGISel::SelectVINTERPModsImpl(
SDValue In,
SDValue &Src,
3561 if (SelectVOP3ModsImpl(In, Src, Mods,
3566 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3573bool AMDGPUDAGToDAGISel::SelectVINTERPMods(
SDValue In,
SDValue &Src,
3575 return SelectVINTERPModsImpl(In, Src, SrcMods,
false);
3578bool AMDGPUDAGToDAGISel::SelectVINTERPModsHi(
SDValue In,
SDValue &Src,
3580 return SelectVINTERPModsImpl(In, Src, SrcMods,
true);
3583bool AMDGPUDAGToDAGISel::SelectVOP3Mods0(
SDValue In,
SDValue &Src,
3587 Clamp =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3588 Omod =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3590 return SelectVOP3Mods(In, Src, SrcMods);
3593bool AMDGPUDAGToDAGISel::SelectVOP3BMods0(
SDValue In,
SDValue &Src,
3597 Clamp =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3598 Omod =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3600 return SelectVOP3BMods(In, Src, SrcMods);
3603bool AMDGPUDAGToDAGISel::SelectVOP3OMods(
SDValue In,
SDValue &Src,
3608 Clamp =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3609 Omod =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3614bool AMDGPUDAGToDAGISel::SelectVOP3PMods(
SDValue In,
SDValue &Src,
3615 SDValue &SrcMods,
bool IsDOT)
const {
3622 Src = Src.getOperand(0);
3626 bool HasOpSel = Src.getValueSizeInBits() != 128;
3629 (!IsDOT || !Subtarget->hasDOTOpSelHazard())) {
3630 unsigned VecMods = Mods;
3632 SDValue Lo = stripBitcast(Src.getOperand(0));
3633 SDValue Hi = stripBitcast(Src.getOperand(1));
3636 Lo = stripBitcast(
Lo.getOperand(0));
3641 Hi = stripBitcast(
Hi.getOperand(0));
3653 unsigned VecSize = Src.getValueSizeInBits();
3654 Lo = stripExtractLoElt(
Lo);
3655 Hi = stripExtractLoElt(
Hi);
3657 if (
Lo.getValueSizeInBits() > VecSize) {
3658 Lo =
CurDAG->getTargetExtractSubreg(
3659 (VecSize > 32) ? AMDGPU::sub0_sub1 : AMDGPU::sub0, SDLoc(In),
3663 if (
Hi.getValueSizeInBits() > VecSize) {
3664 Hi =
CurDAG->getTargetExtractSubreg(
3665 (VecSize > 32) ? AMDGPU::sub0_sub1 : AMDGPU::sub0, SDLoc(In),
3669 assert(
Lo.getValueSizeInBits() <= VecSize &&
3670 Hi.getValueSizeInBits() <= VecSize);
3672 if (
Lo ==
Hi && !isInlineImmediate(
Lo.getNode())) {
3676 if (VecSize ==
Lo.getValueSizeInBits()) {
3678 }
else if (VecSize == 32) {
3679 Src = createVOP3PSrc32FromLo16(
Lo, Src,
CurDAG, Subtarget);
3681 assert((
Lo.getValueSizeInBits() == 32 && VecSize == 64) ||
3682 (
Lo.getValueSizeInBits() == 64 && VecSize == 128));
3686 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, SL,
3687 Lo.getValueType()), 0);
3688 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3693 auto RC =
Lo->isDivergent() ?
TRI->getVGPRClassForBitWidth(VecSize)
3694 :
TRI->getSGPRClassForBitWidth(VecSize);
3695 unsigned NumRegs =
Lo.getValueSizeInBits() == 32 ? 1 : 2;
3697 CurDAG->getTargetConstant(RC->getID(), SL, MVT::i32),
Lo,
3698 CurDAG->getTargetConstant(
TRI->getSubRegFromChannel(0, NumRegs), SL,
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);
3711 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3717 .bitcastToAPInt().getZExtValue();
3719 Src =
CurDAG->getTargetConstant(
Lit, SDLoc(In), MVT::i64);
3720 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3727 Src.getNumOperands() == 2) {
3732 assert(Src.getValueSizeInBits() != 128 &&
3733 "<2 x 64> VECTOR_SHUFFLE should not be legal.");
3736 ArrayRef<int>
Mask = SVN->getMask();
3738 if (Mask[0] < 2 && Mask[1] < 2) {
3740 SDValue ShuffleSrc = SVN->getOperand(0);
3753 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3761 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3765bool AMDGPUDAGToDAGISel::SelectVOP3PModsDOT(
SDValue In,
SDValue &Src,
3767 return SelectVOP3PMods(In, Src, SrcMods,
true);
3770bool AMDGPUDAGToDAGISel::SelectVOP3PNoModsDOT(
SDValue In,
SDValue &Src)
const {
3772 SelectVOP3PMods(In, SrcTmp, SrcModsTmp,
true);
3781bool AMDGPUDAGToDAGISel::SelectVOP3PModsF32(
SDValue In,
SDValue &Src,
3783 SelectVOP3Mods(In, Src, SrcMods);
3786 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3790bool AMDGPUDAGToDAGISel::SelectVOP3PNoModsF32(
SDValue In,
SDValue &Src)
const {
3792 SelectVOP3PModsF32(In, SrcTmp, SrcModsTmp);
3801bool AMDGPUDAGToDAGISel::SelectWMMAOpSelVOP3PMods(
SDValue In,
3804 assert(
C->getAPIntValue().getBitWidth() == 1 &&
"expected i1 value");
3807 unsigned SrcVal =
C->getZExtValue();
3811 Src =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3818 unsigned DstRegClass;
3820 switch (Elts.
size()) {
3822 DstRegClass = AMDGPU::VReg_256RegClassID;
3826 DstRegClass = AMDGPU::VReg_128RegClassID;
3830 DstRegClass = AMDGPU::VReg_64RegClassID;
3838 Ops.push_back(
CurDAG->getTargetConstant(DstRegClass,
DL, MVT::i32));
3839 for (
unsigned i = 0; i < Elts.
size(); ++i) {
3840 Ops.push_back(Elts[i]);
3841 Ops.push_back(
CurDAG->getTargetConstant(
3844 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL, DstTy,
Ops);
3851 assert(
"unhandled Reg sequence size" &&
3852 (Elts.
size() == 8 || Elts.
size() == 16));
3856 for (
unsigned i = 0; i < Elts.
size(); i += 2) {
3857 SDValue LoSrc = stripExtractLoElt(stripBitcast(Elts[i]));
3862 if (Subtarget->useRealTrue16Insts()) {
3867 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, MVT::i16),
3870 emitRegSequence(*
CurDAG, AMDGPU::VGPR_32RegClassID, MVT::i32,
3871 {Elts[i],
Undef}, {AMDGPU::lo16, AMDGPU::hi16},
DL);
3872 Elts[i + 1] = emitRegSequence(*
CurDAG, AMDGPU::VGPR_32RegClassID,
3873 MVT::i32, {Elts[i + 1],
Undef},
3874 {AMDGPU::lo16, AMDGPU::hi16},
DL);
3876 SDValue PackLoLo =
CurDAG->getTargetConstant(0x05040100,
DL, MVT::i32);
3878 CurDAG->getMachineNode(AMDGPU::V_PERM_B32_e64,
DL, MVT::i32,
3879 {Elts[i + 1], Elts[i], PackLoLo});
3883 return buildRegSequence32(PackedElts,
DL);
3889 unsigned ElementSize)
const {
3890 if (ElementSize == 16)
3891 return buildRegSequence16(Elts,
DL);
3892 if (ElementSize == 32)
3893 return buildRegSequence32(Elts,
DL);
3897void AMDGPUDAGToDAGISel::selectWMMAModsNegAbs(
unsigned ModOpcode,
3901 unsigned ElementSize)
const {
3906 for (
auto El : Elts) {
3909 NegAbsElts.
push_back(El->getOperand(0));
3911 if (Elts.size() != NegAbsElts.
size()) {
3913 Src =
SDValue(buildRegSequence(Elts,
DL, ElementSize), 0);
3917 Src =
SDValue(buildRegSequence(NegAbsElts,
DL, ElementSize), 0);
3923 Src =
SDValue(buildRegSequence(Elts,
DL, ElementSize), 0);
3931 std::function<
bool(
SDValue)> ModifierCheck) {
3935 for (
unsigned i = 0; i < F16Pair->getNumOperands(); ++i) {
3936 SDValue ElF16 = stripBitcast(F16Pair->getOperand(i));
3937 if (!ModifierCheck(ElF16))
3944bool AMDGPUDAGToDAGISel::SelectWMMAModsF16Neg(
SDValue In,
SDValue &Src,
3962 Src =
SDValue(buildRegSequence16(EltsF16, SDLoc(In)), 0);
3981 Src =
SDValue(buildRegSequence32(EltsV2F16, SDLoc(In)), 0);
3987 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3991bool AMDGPUDAGToDAGISel::SelectWMMAModsF16NegAbs(
SDValue In,
SDValue &Src,
4002 if (EltsF16.
empty())
4012 selectWMMAModsNegAbs(ModOpcode, Mods, EltsF16, Src, SDLoc(In), 16);
4022 if (EltsV2F16.
empty())
4031 selectWMMAModsNegAbs(ModOpcode, Mods, EltsV2F16, Src, SDLoc(In), 32);
4034 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4038bool AMDGPUDAGToDAGISel::SelectWMMAModsF32NegAbs(
SDValue In,
SDValue &Src,
4048 unsigned ModOpcode =
4059 selectWMMAModsNegAbs(ModOpcode, Mods, EltsF32, Src, SDLoc(In), 32);
4062 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4066bool AMDGPUDAGToDAGISel::SelectWMMAVISrc(
SDValue In,
SDValue &Src)
const {
4068 BitVector UndefElements;
4070 if (isInlineImmediate(
Splat.getNode())) {
4072 unsigned Imm =
C->getAPIntValue().getSExtValue();
4073 Src =
CurDAG->getTargetConstant(
Imm, SDLoc(In), MVT::i32);
4077 unsigned Imm =
C->getValueAPF().bitcastToAPInt().getSExtValue();
4078 Src =
CurDAG->getTargetConstant(
Imm, SDLoc(In), MVT::i32);
4086 SDValue SplatSrc32 = stripBitcast(In);
4088 if (
SDValue Splat32 = SplatSrc32BV->getSplatValue()) {
4089 SDValue SplatSrc16 = stripBitcast(Splat32);
4092 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
4093 std::optional<APInt> RawValue;
4095 RawValue =
C->getValueAPF().bitcastToAPInt();
4097 RawValue =
C->getAPIntValue();
4099 if (RawValue.has_value()) {
4100 EVT VT =
In.getValueType().getScalarType();
4106 if (
TII->isInlineConstant(FloatVal)) {
4107 Src =
CurDAG->getTargetConstant(RawValue.value(), SDLoc(In),
4112 if (
TII->isInlineConstant(RawValue.value())) {
4113 Src =
CurDAG->getTargetConstant(RawValue.value(), SDLoc(In),
4126 if (
CurDAG->isConstantIntBuildVectorOrConstantInt(SplatSrc32)) {
4131 int64_t LoImm = Lo32->getAPIntValue().getSExtValue();
4132 int64_t HiImm = Hi32->getAPIntValue().getSExtValue();
4133 int64_t Imm64I = (HiImm << 32) + LoImm;
4135 if (!isInlineImmediate(APInt(64, Imm64I)))
4138 }
else if (Imm64I != Imm64)
4142 Src =
CurDAG->getTargetConstant(Imm64, SDLoc(In), MVT::i64);
4149bool AMDGPUDAGToDAGISel::SelectSWMMACIndex8(
SDValue In,
SDValue &Src,
4155 const llvm::SDValue &ShiftSrc =
In.getOperand(0);
4164 IndexKey =
CurDAG->getTargetConstant(
Key, SDLoc(In), MVT::i32);
4168bool AMDGPUDAGToDAGISel::SelectSWMMACIndex16(
SDValue In,
SDValue &Src,
4174 const llvm::SDValue &ShiftSrc =
In.getOperand(0);
4183 IndexKey =
CurDAG->getTargetConstant(
Key, SDLoc(In), MVT::i32);
4187bool AMDGPUDAGToDAGISel::SelectSWMMACIndex32(
SDValue In,
SDValue &Src,
4195 const SDValue &ExtendSrc =
In.getOperand(0);
4199 const SDValue &CastSrc =
In.getOperand(0);
4203 if (Zero &&
Zero->getZExtValue() == 0)
4214 Src = ExtractVecEltSrc;
4218 IndexKey =
CurDAG->getTargetConstant(
Key, SDLoc(In), MVT::i32);
4222bool AMDGPUDAGToDAGISel::SelectVOP3OpSel(
SDValue In,
SDValue &Src,
4226 SrcMods =
CurDAG->getTargetConstant(0, SDLoc(In), MVT::i32);
4230bool AMDGPUDAGToDAGISel::SelectVOP3OpSelMods(
SDValue In,
SDValue &Src,
4233 return SelectVOP3Mods(In, Src, SrcMods);
4245 Op =
Op.getOperand(0);
4247 IsExtractHigh =
false;
4250 if (!Low16 || !Low16->isZero())
4252 Op = stripBitcast(
Op.getOperand(1));
4253 if (
Op.getValueType() != MVT::bf16)
4258 if (
Op.getValueType() != MVT::i32)
4263 if (Mask->getZExtValue() == 0xffff0000) {
4264 IsExtractHigh =
true;
4265 return Op.getOperand(0);
4274 return Op.getOperand(0);
4283bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixModsImpl(
SDValue In,
SDValue &Src,
4287 SelectVOP3ModsImpl(In, Src, Mods);
4289 bool IsExtractHigh =
false;
4291 Src = Src.getOperand(0);
4292 }
else if (VT == MVT::bf16) {
4300 if (Src.getValueType() != VT &&
4301 (VT != MVT::bf16 || Src.getValueType() != MVT::i32))
4304 Src = stripBitcast(Src);
4310 SelectVOP3ModsImpl(Src, Src, ModsTmp);
4325 if (Src.getValueSizeInBits() == 16) {
4334 Src.getOperand(0).getValueType() == MVT::i32) {
4335 Src = Src.getOperand(0);
4339 if (Subtarget->useRealTrue16Insts())
4341 Src = createVOP3PSrc32FromLo16(Src, In,
CurDAG, Subtarget);
4342 }
else if (IsExtractHigh)
4348bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixModsExt(
SDValue In,
SDValue &Src,
4351 if (!SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::f16))
4353 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4357bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixMods(
SDValue In,
SDValue &Src,
4360 SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::f16);
4361 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4365bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixModsExtNeg(
SDValue In,
SDValue &Src,
4368 if (!SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::f16))
4375bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixModsNeg(
SDValue In,
SDValue &Src,
4378 SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::f16);
4384bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixBF16ModsExt(
SDValue In,
SDValue &Src,
4387 if (!SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::bf16))
4389 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4393bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixBF16Mods(
SDValue In,
SDValue &Src,
4396 SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::bf16);
4397 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4401bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixBF16ModsExtNeg(
4404 if (!SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::bf16))
4411bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixBF16ModsNeg(
SDValue In,
SDValue &Src,
4414 SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::bf16);
4424 unsigned NumOpcodes = 0;
4437 const uint8_t SrcBits[3] = { 0xf0, 0xcc, 0xaa };
4440 if (
C->isAllOnes()) {
4450 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4464 if (Src.size() == 3) {
4470 if (
C->isAllOnes()) {
4472 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4473 if (Src[
I] ==
LHS) {
4485 Bits = SrcBits[Src.size()];
4490 switch (In.getOpcode()) {
4498 if (!getOperandBits(
LHS, LHSBits) ||
4499 !getOperandBits(
RHS, RHSBits)) {
4500 Src = std::move(Backup);
4501 return std::make_pair(0, 0);
4522 uint8_t LHSBitsOrig = LHSBits;
4523 uint8_t RHSBitsOrig = RHSBits;
4527 NumOpcodes += LHSOp.first;
4528 LHSBits = LHSOp.second;
4535 NumOpcodes += RHSOp.first;
4536 RHSBits = RHSOp.second;
4540 auto dependsOnSlot = [](
uint8_t TT,
int Slot) ->
bool {
4541 if (Slot < 0 || Slot > 2)
4543 const uint8_t Masks[3] = {0x0f, 0x33, 0x55};
4544 const int Shifts[3] = {4, 2, 1};
4545 return ((TT ^ (TT >> Shifts[Slot])) & Masks[Slot]) != 0;
4551 const uint8_t SrcBitsConst[3] = {0xf0, 0xcc, 0xaa};
4558 NegatedInner =
Op.getOperand(0);
4559 for (
int I = 0;
I < (int)S.size();
I++) {
4560 if (Bits == SrcBitsConst[
I] && S[
I] ==
Op)
4562 if (IsNegationOp && Bits == (
uint8_t)~SrcBitsConst[
I] &&
4563 S[
I] == NegatedInner)
4574 for (
int I = 0;
I < (int)SrcAfterLHS.
size() &&
I < 3;
I++) {
4575 if (
I < (
int)Src.size() && Src[
I] != SrcAfterLHS[
I] &&
4576 dependsOnSlot(LHSBits,
I)) {
4585 if (!Stale && !RHSOp.first) {
4586 int Slot = findSlot(RHSBitsOrig,
RHS, SrcBeforeRecurse);
4588 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4594 if (!Stale && !LHSOp.first) {
4595 int Slot = findSlot(LHSBitsOrig,
LHS, SrcBeforeRecurse);
4597 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4602 Src = std::move(SrcBeforeRecurse);
4603 LHSBits = LHSBitsOrig;
4604 RHSBits = RHSBitsOrig;
4610 return std::make_pair(0, 0);
4614 switch (In.getOpcode()) {
4616 TTbl = LHSBits & RHSBits;
4619 TTbl = LHSBits | RHSBits;
4622 TTbl = LHSBits ^ RHSBits;
4628 return std::make_pair(NumOpcodes + 1, TTbl);
4635 unsigned NumOpcodes;
4637 std::tie(NumOpcodes, TTbl) =
BitOp3_Op(In, Src);
4641 if (NumOpcodes < 2 || Src.empty())
4647 if (NumOpcodes < 4 && !In->isDivergent())
4650 if (NumOpcodes == 2 &&
In.getValueType() == MVT::i32) {
4655 (
In.getOperand(0).getOpcode() ==
In.getOpcode() ||
4656 In.getOperand(1).getOpcode() ==
In.getOpcode()))
4670 while (Src.size() < 3)
4671 Src.push_back(Src[0]);
4677 Tbl =
CurDAG->getTargetConstant(TTbl, SDLoc(In), MVT::i32);
4683 return CurDAG->getPOISON(MVT::i32);
4686 return CurDAG->getUNDEF(MVT::i32);
4690 return CurDAG->getConstant(
C->getZExtValue() << 16, SL, MVT::i32);
4695 return CurDAG->getConstant(
4696 C->getValueAPF().bitcastToAPInt().getZExtValue() << 16, SL, MVT::i32);
4706bool AMDGPUDAGToDAGISel::isVGPRImm(
const SDNode *
N)
const {
4707 assert(
CurDAG->getTarget().getTargetTriple().isAMDGCN());
4709 const SIRegisterInfo *SIRI = Subtarget->getRegisterInfo();
4710 const SIInstrInfo *SII = Subtarget->getInstrInfo();
4713 bool AllUsesAcceptSReg =
true;
4715 Limit < 10 && U !=
E; ++U, ++Limit) {
4717 getOperandRegClass(
U->getUser(),
U->getOperandNo());
4725 if (RC != &AMDGPU::VS_32RegClass && RC != &AMDGPU::VS_64RegClass &&
4726 RC != &AMDGPU::VS_64_Align2RegClass) {
4727 AllUsesAcceptSReg =
false;
4728 SDNode *
User =
U->getUser();
4729 if (
User->isMachineOpcode()) {
4730 unsigned Opc =
User->getMachineOpcode();
4731 const MCInstrDesc &
Desc = SII->get(
Opc);
4732 if (
Desc.isCommutable()) {
4733 unsigned OpIdx =
Desc.getNumDefs() +
U->getOperandNo();
4736 unsigned CommutedOpNo = CommuteIdx1 -
Desc.getNumDefs();
4738 getOperandRegClass(
U->getUser(), CommutedOpNo);
4739 if (CommutedRC == &AMDGPU::VS_32RegClass ||
4740 CommutedRC == &AMDGPU::VS_64RegClass ||
4741 CommutedRC == &AMDGPU::VS_64_Align2RegClass)
4742 AllUsesAcceptSReg =
true;
4750 if (!AllUsesAcceptSReg)
4754 return !AllUsesAcceptSReg && (Limit < 10);
4757bool AMDGPUDAGToDAGISel::isUniformLoad(
const SDNode *
N)
const {
4759 const MachineMemOperand *MMO = Ld->getMemOperand();
4777 (Subtarget->getScalarizeGlobalBehavior() &&
4781 ->isMemOpHasNoClobberedMemOperand(
N)));
4787 bool IsModified =
false;
4793 while (Position !=
CurDAG->allnodes_end()) {
4800 if (ResNode !=
Node) {
4806 CurDAG->RemoveDeadNodes();
4807 }
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)
Base class for AMDGPU specific classes of TargetSubtarget.
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.