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,
346 EVT VT =
N->getValueType(0);
360 Ld ?
CurDAG->getExtLoad(ExtType, SL, MVT::i32, Mem->getChain(),
361 Mem->getBasePtr(), MemVT, Mem->getMemOperand())
362 :
CurDAG->getAtomicLoad(ExtType, SL, MemVT, MVT::i32, Mem->getChain(),
363 Mem->getBasePtr(), Mem->getMemOperand());
374 bool MadeChange =
false;
375 while (Position !=
CurDAG->allnodes_begin()) {
380 switch (
N->getOpcode()) {
383 if (Subtarget->d16PreservesUnusedBits())
388 if (Subtarget->useRealTrue16Insts())
397 CurDAG->RemoveDeadNodes();
403bool AMDGPUDAGToDAGISel::isInlineImmediate(
const SDNode *
N)
const {
409 return TII->isInlineConstant(
C->getAPIntValue());
412 return TII->isInlineConstant(
C->getValueAPF());
422 unsigned OpNo)
const {
423 if (!
N->isMachineOpcode()) {
426 if (
Reg.isVirtual()) {
431 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
432 return TRI->getPhysRegBaseClass(
Reg);
438 switch (
N->getMachineOpcode()) {
440 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
441 const MCInstrDesc &
Desc =
TII->get(
N->getMachineOpcode());
442 unsigned OpIdx =
Desc.getNumDefs() + OpNo;
443 if (OpIdx >=
Desc.getNumOperands())
446 int16_t RegClass =
TII->getOpRegClassID(
Desc.operands()[OpIdx]);
450 return Subtarget->getRegisterInfo()->getRegClass(RegClass);
452 case AMDGPU::REG_SEQUENCE: {
453 unsigned RCID =
N->getConstantOperandVal(0);
455 Subtarget->getRegisterInfo()->getRegClass(RCID);
457 SDValue SubRegOp =
N->getOperand(OpNo + 1);
459 return Subtarget->getRegisterInfo()->getSubClassWithSubReg(SuperRC,
468 Ops.push_back(NewChain);
469 for (
unsigned i = 1, e =
N->getNumOperands(); i != e; ++i)
470 Ops.push_back(
N->getOperand(i));
473 return CurDAG->MorphNodeTo(
N,
N->getOpcode(),
N->getVTList(),
Ops);
480 assert(
N->getOperand(0).getValueType() == MVT::Other &&
"Expected chain");
483 return glueCopyToOp(
N,
M0,
M0.getValue(1));
486SDNode *AMDGPUDAGToDAGISel::glueCopyToM0LDSInit(
SDNode *
N)
const {
489 if (Subtarget->ldsRequiresM0Init())
491 N,
CurDAG->getSignedTargetConstant(-1, SDLoc(
N), MVT::i32));
494 unsigned Value =
MF.getInfo<SIMachineFunctionInfo>()->getGDSSize();
496 glueCopyToM0(
N,
CurDAG->getTargetConstant(
Value, SDLoc(
N), MVT::i32));
503 SDNode *
Lo =
CurDAG->getMachineNode(
504 AMDGPU::S_MOV_B32,
DL, MVT::i32,
506 SDNode *
Hi =
CurDAG->getMachineNode(
507 AMDGPU::S_MOV_B32,
DL, MVT::i32,
509 const SDValue
Ops[] = {
510 CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID,
DL, MVT::i32),
511 SDValue(
Lo, 0),
CurDAG->getTargetConstant(AMDGPU::sub0,
DL, MVT::i32),
512 SDValue(
Hi, 0),
CurDAG->getTargetConstant(AMDGPU::sub1,
DL, MVT::i32)};
514 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL, VT,
Ops);
517SDNode *AMDGPUDAGToDAGISel::packConstantV2I16(
const SDNode *
N,
522 uint32_t LHSVal, RHSVal;
526 uint32_t
K = (LHSVal & 0xffff) | (RHSVal << 16);
528 isVGPRImm(
N) ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32, SL,
536 EVT VT =
N->getValueType(0);
540 SDValue RegClass =
CurDAG->getTargetConstant(RegClassID,
DL, MVT::i32);
542 if (NumVectorElts == 1) {
543 CurDAG->SelectNodeTo(
N, AMDGPU::COPY_TO_REGCLASS, EltVT,
N->getOperand(0),
548 bool IsGCN =
CurDAG->getSubtarget().getTargetTriple().isAMDGCN();
549 if (IsGCN && Subtarget->has64BitLiterals() && VT.
getSizeInBits() == 64 &&
552 bool AllConst =
true;
554 for (
unsigned I = 0;
I < NumVectorElts; ++
I) {
562 Val = CF->getValueAPF().bitcastToAPInt().getZExtValue();
565 C |= Val << (EltSize *
I);
570 CurDAG->getMachineNode(AMDGPU::S_MOV_B64_IMM_PSEUDO,
DL, VT, CV);
571 CurDAG->SelectNodeTo(
N, AMDGPU::COPY_TO_REGCLASS, VT,
SDValue(Copy, 0),
577 assert(NumVectorElts <= 32 &&
"Vectors with more than 32 elements not "
584 RegSeqArgs[0] =
CurDAG->getTargetConstant(RegClassID,
DL, MVT::i32);
585 bool IsRegSeq =
true;
586 unsigned NOps =
N->getNumOperands();
588 assert(IsGCN || EltSizeInRegs == 1);
589 for (
unsigned i = 0; i < NOps; i++) {
596 i * EltSizeInRegs, EltSizeInRegs)
598 RegSeqArgs[1 + (2 * i)] =
N->getOperand(i);
599 RegSeqArgs[1 + (2 * i) + 1] =
CurDAG->getTargetConstant(
Sub,
DL, MVT::i32);
601 if (NOps != NumVectorElts) {
606 for (
unsigned i = NOps; i < NumVectorElts; ++i) {
608 i * EltSizeInRegs, EltSizeInRegs)
610 RegSeqArgs[1 + (2 * i)] =
SDValue(ImpDef, 0);
611 RegSeqArgs[1 + (2 * i) + 1] =
618 CurDAG->SelectNodeTo(
N, AMDGPU::REG_SEQUENCE,
N->getVTList(), RegSeqArgs);
622 EVT VT =
N->getValueType(0);
626 if (!Subtarget->hasPkMovB32() || !EltVT.
bitsEq(MVT::i32) ||
634 SDValue Src0 = SVN->getOperand(0);
635 SDValue Src1 = SVN->getOperand(1);
639 assert(Src0.getValueType().getVectorNumElements() == 2 && Mask.size() == 2 &&
640 Mask[0] < 4 && Mask[1] < 4);
642 SDValue VSrc0 = Mask[0] < 2 ? Src0 : Src1;
643 SDValue VSrc1 = Mask[1] < 2 ? Src0 : Src1;
644 unsigned Src0SubReg = Mask[0] & 1 ? AMDGPU::sub1 : AMDGPU::sub0;
645 unsigned Src1SubReg = Mask[1] & 1 ? AMDGPU::sub1 : AMDGPU::sub0;
648 Src0SubReg = Src1SubReg;
650 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, VT);
655 Src1SubReg = Src0SubReg;
657 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, VT);
667 if (
N->isDivergent() && Src0SubReg == AMDGPU::sub1 &&
668 Src1SubReg == AMDGPU::sub0) {
684 SDValue Src0OpSelVal =
CurDAG->getTargetConstant(Src0OpSel,
DL, MVT::i32);
685 SDValue Src1OpSelVal =
CurDAG->getTargetConstant(Src1OpSel,
DL, MVT::i32);
688 CurDAG->SelectNodeTo(
N, AMDGPU::V_PK_MOV_B32,
N->getVTList(),
689 {Src0OpSelVal, VSrc0, Src1OpSelVal, VSrc1,
699 CurDAG->getTargetExtractSubreg(Src0SubReg,
DL, EltVT, VSrc0);
701 CurDAG->getTargetExtractSubreg(Src1SubReg,
DL, EltVT, VSrc1);
704 CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID,
DL, MVT::i32),
705 ResultElt0,
CurDAG->getTargetConstant(AMDGPU::sub0,
DL, MVT::i32),
706 ResultElt1,
CurDAG->getTargetConstant(AMDGPU::sub1,
DL, MVT::i32)};
707 CurDAG->SelectNodeTo(
N, TargetOpcode::REG_SEQUENCE, VT,
Ops);
711 unsigned int Opc =
N->getOpcode();
712 if (
N->isMachineOpcode()) {
720 N = glueCopyToM0LDSInit(
N);
730 if (
N->getValueType(0) == MVT::i64) {
731 SelectAddcSubbI64(
N);
735 if (
N->getValueType(0) != MVT::i32)
742 if (
N->getValueType(0) == MVT::i64) {
743 SelectAddcSubbI64(
N);
747 SelectUADDO_USUBO(
N);
750 case AMDGPUISD::FMUL_W_CHAIN: {
751 SelectFMUL_W_CHAIN(
N);
754 case AMDGPUISD::FMA_W_CHAIN: {
755 SelectFMA_W_CHAIN(
N);
761 EVT VT =
N->getValueType(0);
779 N->isDivergent() ?
TRI->getDefaultVectorSuperClassForBitWidth(VecInBits)
791 if (
N->getValueType(0) == MVT::i128) {
792 RC =
CurDAG->getTargetConstant(AMDGPU::SGPR_128RegClassID,
DL, MVT::i32);
793 SubReg0 =
CurDAG->getTargetConstant(AMDGPU::sub0_sub1,
DL, MVT::i32);
794 SubReg1 =
CurDAG->getTargetConstant(AMDGPU::sub2_sub3,
DL, MVT::i32);
795 }
else if (
N->getValueType(0) == MVT::i64) {
796 RC =
CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID,
DL, MVT::i32);
797 SubReg0 =
CurDAG->getTargetConstant(AMDGPU::sub0,
DL, MVT::i32);
798 SubReg1 =
CurDAG->getTargetConstant(AMDGPU::sub1,
DL, MVT::i32);
802 const SDValue Ops[] = { RC,
N->getOperand(0), SubReg0,
803 N->getOperand(1), SubReg1 };
805 N->getValueType(0),
Ops));
811 if (
N->getValueType(0).getSizeInBits() != 64 || isInlineImmediate(
N) ||
812 Subtarget->has64BitLiterals())
817 Imm =
FP->getValueAPF().bitcastToAPInt().getZExtValue();
822 Imm =
C->getZExtValue();
831 case AMDGPUISD::BFE_I32:
832 case AMDGPUISD::BFE_U32: {
858 case AMDGPUISD::DIV_SCALE: {
869 return SelectMUL_LOHI(
N);
880 if (
N->getValueType(0) != MVT::i32)
891 case AMDGPUISD::CVT_PKRTZ_F16_F32:
892 case AMDGPUISD::CVT_PKNORM_I16_F32:
893 case AMDGPUISD::CVT_PKNORM_U16_F32:
894 case AMDGPUISD::CVT_PK_U16_U32:
895 case AMDGPUISD::CVT_PK_I16_I32: {
897 if (
N->getValueType(0) == MVT::i32) {
898 MVT NewVT =
Opc == AMDGPUISD::CVT_PKRTZ_F16_F32 ? MVT::v2f16 : MVT::v2i16;
900 { N->getOperand(0), N->getOperand(1) });
908 SelectINTRINSIC_W_CHAIN(
N);
912 SelectINTRINSIC_WO_CHAIN(
N);
916 SelectINTRINSIC_VOID(
N);
920 SelectWAVE_ADDRESS(
N);
924 SelectSTACKRESTORE(
N);
928 SelectWRITE_REGISTER(
N);
937 if (!Subtarget->hasSDWA())
947 return RHS->getZExtValue() == 0xFF || RHS->getZExtValue() == 0xFFFF;
951 return (RHS->getZExtValue() % 8) == 0;
956bool AMDGPUDAGToDAGISel::isUniformBr(
const SDNode *
N)
const {
959 return Term->getMetadata(
"amdgpu.uniform") ||
960 Term->getMetadata(
"structurizecfg.uniform");
963bool AMDGPUDAGToDAGISel::isUnneededShiftMask(
const SDNode *
N,
964 unsigned ShAmtBits)
const {
967 const APInt &
RHS =
N->getConstantOperandAPInt(1);
968 if (
RHS.countr_one() >= ShAmtBits)
998 N1 =
Lo.getOperand(1);
1008 if (
CurDAG->isBaseWithConstantOffset(Addr)) {
1023 return "AMDGPU DAG->DAG Pattern Instruction Selection";
1039#ifdef EXPENSIVE_CHECKS
1042 for (
auto &L : LI.getLoopsInPreorder())
1043 assert(L->isLCSSAForm(DT) &&
"Loop is not in LCSSA form!");
1065 }
else if ((Addr.
getOpcode() == AMDGPUISD::DWORDADDR) &&
1067 Base =
CurDAG->getRegister(R600::INDIRECT_BASE_ADDR, MVT::i32);
1081SDValue AMDGPUDAGToDAGISel::getMaterializedScalarImm32(int64_t Val,
1083 SDNode *Mov =
CurDAG->getMachineNode(
1084 AMDGPU::S_MOV_B32,
DL, MVT::i32,
1085 CurDAG->getTargetConstant(Val,
DL, MVT::i32));
1086 return SDValue(Mov, 0);
1089void AMDGPUDAGToDAGISel::SelectAddcSubb(
SDNode *
N) {
1090 SDValue
LHS =
N->getOperand(0);
1091 SDValue
RHS =
N->getOperand(1);
1092 SDValue CI =
N->getOperand(2);
1094 if (
N->isDivergent()) {
1096 : AMDGPU::V_SUBB_U32_e64;
1098 N,
Opc,
N->getVTList(),
1100 CurDAG->getTargetConstant(0, {}, MVT::i1) });
1103 : AMDGPU::S_SUB_CO_PSEUDO;
1104 CurDAG->SelectNodeTo(
N,
Opc,
N->getVTList(), {LHS, RHS, CI});
1108void AMDGPUDAGToDAGISel::SelectAddcSubbI64(
SDNode *
N) {
1110 SDValue
LHS =
N->getOperand(0);
1111 SDValue
RHS =
N->getOperand(1);
1113 unsigned Opcode =
N->getOpcode();
1117 SDValue Sub0 =
CurDAG->getTargetConstant(AMDGPU::sub0,
DL, MVT::i32);
1118 SDValue Sub1 =
CurDAG->getTargetConstant(AMDGPU::sub1,
DL, MVT::i32);
1120 SDNode *Lo0 =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
DL,
1121 MVT::i32,
LHS, Sub0);
1122 SDNode *Hi0 =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
DL,
1123 MVT::i32,
LHS, Sub1);
1125 SDNode *Lo1 =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
DL,
1126 MVT::i32,
RHS, Sub0);
1127 SDNode *Hi1 =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
DL,
1128 MVT::i32,
RHS, Sub1);
1130 SDVTList VTList =
CurDAG->getVTList(MVT::i32,
N->getValueType(1));
1132 static const unsigned NoCarryOpcMap[2][2] = {
1133 {AMDGPU::S_USUBO_PSEUDO, AMDGPU::S_UADDO_PSEUDO},
1134 {AMDGPU::V_SUB_CO_U32_e64, AMDGPU::V_ADD_CO_U32_e64}};
1135 static const unsigned CarryOpcMap[2][2] = {
1136 {AMDGPU::S_SUB_CO_PSEUDO, AMDGPU::S_ADD_CO_PSEUDO},
1137 {AMDGPU::V_SUBB_U32_e64, AMDGPU::V_ADDC_U32_e64}};
1139 bool IsVALU =
N->isDivergent();
1141 unsigned NoCarryOpc = NoCarryOpcMap[IsVALU][IsAdd];
1142 unsigned CarryOpc = CarryOpcMap[IsVALU][IsAdd];
1143 SDValue Clamp =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
1146 if (!ConsumeCarry) {
1148 SDValue
Args[] = {SDValue(Lo0, 0), SDValue(Lo1, 0), Clamp};
1149 AddLo =
CurDAG->getMachineNode(NoCarryOpc,
DL, VTList, Args);
1151 SDValue
Args[] = {SDValue(Lo0, 0), SDValue(Lo1, 0)};
1152 AddLo =
CurDAG->getMachineNode(NoCarryOpc,
DL, VTList, Args);
1156 SDValue
Args[] = {SDValue(Lo0, 0), SDValue(Lo1, 0),
N->getOperand(2),
1158 AddLo =
CurDAG->getMachineNode(CarryOpc,
DL, VTList, Args);
1160 SDValue
Args[] = {SDValue(Lo0, 0), SDValue(Lo1, 0),
N->getOperand(2)};
1161 AddLo =
CurDAG->getMachineNode(CarryOpc,
DL, VTList, Args);
1167 SDValue
Args[] = {SDValue(Hi0, 0), SDValue(Hi1, 0), SDValue(AddLo, 1),
1169 AddHi =
CurDAG->getMachineNode(CarryOpc,
DL, VTList, Args);
1171 SDValue
Args[] = {SDValue(Hi0, 0), SDValue(Hi1, 0), SDValue(AddLo, 1)};
1172 AddHi =
CurDAG->getMachineNode(CarryOpc,
DL, VTList, Args);
1175 unsigned RC = IsVALU ? AMDGPU::VReg_64RegClassID : AMDGPU::SReg_64RegClassID;
1176 SDValue RegSequenceArgs[] = {
CurDAG->getTargetConstant(RC,
DL, MVT::i32),
1177 SDValue(AddLo, 0), Sub0, SDValue(AddHi, 0),
1180 MVT::i64, RegSequenceArgs);
1186void AMDGPUDAGToDAGISel::SelectUADDO_USUBO(
SDNode *
N) {
1191 bool IsVALU =
N->isDivergent();
1193 for (SDNode::user_iterator UI =
N->user_begin(),
E =
N->user_end(); UI !=
E;
1195 if (UI.getUse().getResNo() == 1) {
1196 if (UI->isMachineOpcode()) {
1197 if (UI->getMachineOpcode() !=
1198 (IsAdd ? AMDGPU::S_ADD_CO_PSEUDO : AMDGPU::S_SUB_CO_PSEUDO)) {
1211 unsigned Opc = IsAdd ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_SUB_CO_U32_e64;
1214 N,
Opc,
N->getVTList(),
1215 {N->getOperand(0), N->getOperand(1),
1216 CurDAG->getTargetConstant(0, {}, MVT::i1) });
1218 unsigned Opc = IsAdd ? AMDGPU::S_UADDO_PSEUDO : AMDGPU::S_USUBO_PSEUDO;
1220 CurDAG->SelectNodeTo(
N,
Opc,
N->getVTList(),
1221 {N->getOperand(0), N->getOperand(1)});
1225void AMDGPUDAGToDAGISel::SelectFMA_W_CHAIN(
SDNode *
N) {
1229 SelectVOP3Mods0(
N->getOperand(1),
Ops[1],
Ops[0],
Ops[6],
Ops[7]);
1230 SelectVOP3Mods(
N->getOperand(2),
Ops[3],
Ops[2]);
1231 SelectVOP3Mods(
N->getOperand(3),
Ops[5],
Ops[4]);
1232 Ops[8] =
N->getOperand(0);
1233 Ops[9] =
N->getOperand(4);
1237 bool UseFMAC = Subtarget->hasDLInsts() &&
1241 unsigned Opcode = UseFMAC ? AMDGPU::V_FMAC_F32_e64 : AMDGPU::V_FMA_F32_e64;
1242 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(),
Ops);
1245void AMDGPUDAGToDAGISel::SelectFMUL_W_CHAIN(
SDNode *
N) {
1249 SelectVOP3Mods0(
N->getOperand(1),
Ops[1],
Ops[0],
Ops[4],
Ops[5]);
1250 SelectVOP3Mods(
N->getOperand(2),
Ops[3],
Ops[2]);
1251 Ops[6] =
N->getOperand(0);
1252 Ops[7] =
N->getOperand(3);
1254 CurDAG->SelectNodeTo(
N, AMDGPU::V_MUL_F32_e64,
N->getVTList(),
Ops);
1259void AMDGPUDAGToDAGISel::SelectDIV_SCALE(
SDNode *
N) {
1260 EVT VT =
N->getValueType(0);
1262 assert(VT == MVT::f32 || VT == MVT::f64);
1265 = (VT == MVT::f64) ? AMDGPU::V_DIV_SCALE_F64_e64 : AMDGPU::V_DIV_SCALE_F32_e64;
1270 SelectVOP3BMods0(
N->getOperand(0),
Ops[1],
Ops[0],
Ops[6],
Ops[7]);
1271 SelectVOP3BMods(
N->getOperand(1),
Ops[3],
Ops[2]);
1272 SelectVOP3BMods(
N->getOperand(2),
Ops[5],
Ops[4]);
1278void AMDGPUDAGToDAGISel::SelectMAD_64_32(
SDNode *
N) {
1282 bool UseNoCarry = Subtarget->hasMadNC64_32Insts() && !
N->hasAnyUseOfValue(1);
1283 if (Subtarget->hasMADIntraFwdBug())
1284 Opc =
Signed ? AMDGPU::V_MAD_I64_I32_gfx11_e64
1285 : AMDGPU::V_MAD_U64_U32_gfx11_e64;
1286 else if (UseNoCarry)
1287 Opc =
Signed ? AMDGPU::V_MAD_NC_I64_I32_e64 : AMDGPU::V_MAD_NC_U64_U32_e64;
1289 Opc =
Signed ? AMDGPU::V_MAD_I64_I32_e64 : AMDGPU::V_MAD_U64_U32_e64;
1291 SDValue Clamp =
CurDAG->getTargetConstant(0, SL, MVT::i1);
1292 SDValue
Ops[] = {
N->getOperand(0),
N->getOperand(1),
N->getOperand(2),
1296 MachineSDNode *Mad =
CurDAG->getMachineNode(
Opc, SL, MVT::i64,
Ops);
1307void AMDGPUDAGToDAGISel::SelectMUL_LOHI(
SDNode *
N) {
1312 if (Subtarget->hasMadNC64_32Insts()) {
1313 VTList =
CurDAG->getVTList(MVT::i64);
1314 Opc =
Signed ? AMDGPU::V_MAD_NC_I64_I32_e64 : AMDGPU::V_MAD_NC_U64_U32_e64;
1316 VTList =
CurDAG->getVTList(MVT::i64, MVT::i1);
1317 if (Subtarget->hasMADIntraFwdBug()) {
1318 Opc =
Signed ? AMDGPU::V_MAD_I64_I32_gfx11_e64
1319 : AMDGPU::V_MAD_U64_U32_gfx11_e64;
1321 Opc =
Signed ? AMDGPU::V_MAD_I64_I32_e64 : AMDGPU::V_MAD_U64_U32_e64;
1325 SDValue
Zero =
CurDAG->getTargetConstant(0, SL, MVT::i64);
1326 SDValue Clamp =
CurDAG->getTargetConstant(0, SL, MVT::i1);
1327 SDValue
Ops[] = {
N->getOperand(0),
N->getOperand(1),
Zero, Clamp};
1328 SDNode *Mad =
CurDAG->getMachineNode(
Opc, SL, VTList,
Ops);
1329 if (!SDValue(
N, 0).use_empty()) {
1330 SDValue Sub0 =
CurDAG->getTargetConstant(AMDGPU::sub0, SL, MVT::i32);
1331 SDNode *
Lo =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, SL,
1332 MVT::i32, SDValue(Mad, 0), Sub0);
1335 if (!SDValue(
N, 1).use_empty()) {
1336 SDValue Sub1 =
CurDAG->getTargetConstant(AMDGPU::sub1, SL, MVT::i32);
1337 SDNode *
Hi =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, SL,
1338 MVT::i32, SDValue(Mad, 0), Sub1);
1348 if (!
Base || Subtarget->hasUsableDSOffset() ||
1349 Subtarget->unsafeDSOffsetFoldingEnabled())
1360 if (
CurDAG->isBaseWithConstantOffset(Addr)) {
1373 int64_t ByteOffset =
C->getSExtValue();
1374 if (isDSOffsetLegal(SDValue(), ByteOffset)) {
1375 SDValue
Zero =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1383 if (isDSOffsetLegal(
Sub, ByteOffset)) {
1389 unsigned SubOp = AMDGPU::V_SUB_CO_U32_e32;
1390 if (Subtarget->hasAddNoCarryInsts()) {
1391 SubOp = AMDGPU::V_SUB_U32_e64;
1393 CurDAG->getTargetConstant(0, {}, MVT::i1));
1396 MachineSDNode *MachineSub =
1397 CurDAG->getMachineNode(SubOp,
DL, MVT::i32, Opnds);
1399 Base = SDValue(MachineSub, 0);
1413 if (isDSOffsetLegal(SDValue(), CAddr->getZExtValue())) {
1414 SDValue
Zero =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1415 MachineSDNode *MovZero =
CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32,
1416 DL, MVT::i32, Zero);
1417 Base = SDValue(MovZero, 0);
1418 Offset =
CurDAG->getTargetConstant(CAddr->getZExtValue(),
DL, MVT::i16);
1425 Offset =
CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i16);
1429bool AMDGPUDAGToDAGISel::isDSOffset2Legal(
SDValue Base,
unsigned Offset0,
1431 unsigned Size)
const {
1432 if (Offset0 %
Size != 0 || Offset1 %
Size != 0)
1437 if (!
Base || Subtarget->hasUsableDSOffset() ||
1438 Subtarget->unsafeDSOffsetFoldingEnabled())
1456bool AMDGPUDAGToDAGISel::isFlatScratchBaseLegal(
SDValue Addr)
const {
1462 if (Subtarget->hasSignedScratchOffsets())
1472 ConstantSDNode *ImmOp =
nullptr;
1483bool AMDGPUDAGToDAGISel::isFlatScratchBaseLegalSV(
SDValue Addr)
const {
1489 if (Subtarget->hasSignedScratchOffsets())
1499bool AMDGPUDAGToDAGISel::isFlatScratchBaseLegalSVImm(
SDValue Addr)
const {
1513 (RHSImm->getSExtValue() < 0 && RHSImm->getSExtValue() > -0x40000000)))
1516 auto LHS =
Base.getOperand(0);
1517 auto RHS =
Base.getOperand(1);
1525 return SelectDSReadWrite2(Addr,
Base, Offset0, Offset1, 4);
1531 return SelectDSReadWrite2(Addr,
Base, Offset0, Offset1, 8);
1536 unsigned Size)
const {
1539 if (
CurDAG->isBaseWithConstantOffset(Addr)) {
1544 unsigned OffsetValue1 = OffsetValue0 +
Size;
1547 if (isDSOffset2Legal(N0, OffsetValue0, OffsetValue1,
Size)) {
1549 Offset0 =
CurDAG->getTargetConstant(OffsetValue0 /
Size,
DL, MVT::i32);
1550 Offset1 =
CurDAG->getTargetConstant(OffsetValue1 /
Size,
DL, MVT::i32);
1555 if (
const ConstantSDNode *
C =
1557 unsigned OffsetValue0 =
C->getZExtValue();
1558 unsigned OffsetValue1 = OffsetValue0 +
Size;
1560 if (isDSOffset2Legal(SDValue(), OffsetValue0, OffsetValue1,
Size)) {
1562 SDValue
Zero =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1570 if (isDSOffset2Legal(
Sub, OffsetValue0, OffsetValue1,
Size)) {
1574 unsigned SubOp = AMDGPU::V_SUB_CO_U32_e32;
1575 if (Subtarget->hasAddNoCarryInsts()) {
1576 SubOp = AMDGPU::V_SUB_U32_e64;
1578 CurDAG->getTargetConstant(0, {}, MVT::i1));
1581 MachineSDNode *MachineSub =
CurDAG->getMachineNode(
1584 Base = SDValue(MachineSub, 0);
1586 CurDAG->getTargetConstant(OffsetValue0 /
Size,
DL, MVT::i32);
1588 CurDAG->getTargetConstant(OffsetValue1 /
Size,
DL, MVT::i32);
1594 unsigned OffsetValue0 = CAddr->getZExtValue();
1595 unsigned OffsetValue1 = OffsetValue0 +
Size;
1597 if (isDSOffset2Legal(SDValue(), OffsetValue0, OffsetValue1,
Size)) {
1598 SDValue
Zero =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1599 MachineSDNode *MovZero =
1600 CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32,
DL, MVT::i32, Zero);
1601 Base = SDValue(MovZero, 0);
1602 Offset0 =
CurDAG->getTargetConstant(OffsetValue0 /
Size,
DL, MVT::i32);
1603 Offset1 =
CurDAG->getTargetConstant(OffsetValue1 /
Size,
DL, MVT::i32);
1611 Offset0 =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1612 Offset1 =
CurDAG->getTargetConstant(1,
DL, MVT::i32);
1622 if (Subtarget->useFlatForGlobal())
1627 Idxen =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
1628 Offen =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
1629 Addr64 =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
1630 SOffset = Subtarget->hasRestrictedSOffset()
1631 ?
CurDAG->getRegister(AMDGPU::SGPR_NULL, MVT::i32)
1632 :
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1634 ConstantSDNode *C1 =
nullptr;
1636 if (
CurDAG->isBaseWithConstantOffset(Addr)) {
1649 Addr64 =
CurDAG->getTargetConstant(1,
DL, MVT::i1);
1655 Ptr = SDValue(buildSMovImm64(
DL, 0, MVT::v2i32), 0);
1671 Ptr = SDValue(buildSMovImm64(
DL, 0, MVT::v2i32), 0);
1673 Addr64 =
CurDAG->getTargetConstant(1,
DL, MVT::i1);
1677 VAddr =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1687 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
1697 SDValue(
CurDAG->getMachineNode(
1698 AMDGPU::S_MOV_B32,
DL, MVT::i32,
1704bool AMDGPUDAGToDAGISel::SelectMUBUFAddr64(
SDValue Addr,
SDValue &SRsrc,
1707 SDValue Ptr, Offen, Idxen, Addr64;
1711 if (!Subtarget->hasAddr64())
1714 if (!SelectMUBUF(Addr, Ptr, VAddr, SOffset,
Offset, Offen, Idxen, Addr64))
1718 if (
C->getSExtValue()) {
1731std::pair<SDValue, SDValue> AMDGPUDAGToDAGISel::foldFrameIndex(
SDValue N)
const {
1736 FI ?
CurDAG->getTargetFrameIndex(FI->getIndex(), FI->getValueType(0)) :
N;
1742 return std::pair(TFI,
CurDAG->getTargetConstant(0,
DL, MVT::i32));
1745bool AMDGPUDAGToDAGISel::SelectMUBUFScratchOffen(
SDNode *Parent,
1752 const SIMachineFunctionInfo *
Info =
MF.getInfo<SIMachineFunctionInfo>();
1754 Rsrc =
CurDAG->getRegister(
Info->getScratchRSrcReg(), MVT::v4i32);
1757 int64_t
Imm = CAddr->getSExtValue();
1758 const int64_t NullPtr =
1761 if (
Imm != NullPtr) {
1764 CurDAG->getTargetConstant(
Imm & ~MaxOffset,
DL, MVT::i32);
1765 MachineSDNode *MovHighBits =
CurDAG->getMachineNode(
1766 AMDGPU::V_MOV_B32_e32,
DL, MVT::i32, HighBits);
1767 VAddr = SDValue(MovHighBits, 0);
1769 SOffset =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1770 ImmOffset =
CurDAG->getTargetConstant(
Imm & MaxOffset,
DL, MVT::i32);
1775 if (
CurDAG->isBaseWithConstantOffset(Addr)) {
1796 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
1797 if (
TII->isLegalMUBUFImmOffset(C1) &&
1798 (!Subtarget->privateMemoryResourceIsRangeChecked() ||
1799 CurDAG->SignBitIsZero(N0))) {
1800 std::tie(VAddr, SOffset) = foldFrameIndex(N0);
1801 ImmOffset =
CurDAG->getTargetConstant(C1,
DL, MVT::i32);
1807 std::tie(VAddr, SOffset) = foldFrameIndex(Addr);
1808 ImmOffset =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1816 if (!
Reg.isPhysical())
1818 const auto *RC =
TRI.getPhysRegBaseClass(
Reg);
1819 return RC &&
TRI.isSGPRClass(RC);
1822bool AMDGPUDAGToDAGISel::SelectMUBUFScratchOffset(
SDNode *Parent,
1827 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
1828 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
1830 const SIMachineFunctionInfo *
Info =
MF.getInfo<SIMachineFunctionInfo>();
1835 SRsrc =
CurDAG->getRegister(
Info->getScratchRSrcReg(), MVT::v4i32);
1841 ConstantSDNode *CAddr;
1854 SOffset =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1859 SRsrc =
CurDAG->getRegister(
Info->getScratchRSrcReg(), MVT::v4i32);
1865bool AMDGPUDAGToDAGISel::SelectMUBUFOffset(
SDValue Addr,
SDValue &SRsrc,
1868 SDValue Ptr, VAddr, Offen, Idxen, Addr64;
1869 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
1871 if (!SelectMUBUF(Addr, Ptr, VAddr, SOffset,
Offset, Offen, Idxen, Addr64))
1890bool AMDGPUDAGToDAGISel::SelectBUFSOffset(
SDValue ByteOffsetNode,
1892 if (Subtarget->hasRestrictedSOffset() &&
isNullConstant(ByteOffsetNode)) {
1893 SOffset =
CurDAG->getRegister(AMDGPU::SGPR_NULL, MVT::i32);
1897 SOffset = ByteOffsetNode;
1915bool AMDGPUDAGToDAGISel::SelectFlatOffsetImpl(
1919 int64_t OffsetVal = 0;
1923 bool CanHaveFlatSegmentOffsetBug =
1924 Subtarget->hasFlatSegmentOffsetBug() &&
1925 FlatVariant == FlatAddrSpace::FLAT &&
1928 if (Subtarget->hasFlatInstOffsets() && !CanHaveFlatSegmentOffsetBug) {
1930 if (isBaseWithConstantOffset64(Addr, N0, N1) &&
1931 (FlatVariant != FlatAddrSpace::FlatScratch ||
1932 isFlatScratchBaseLegal(Addr))) {
1940 if (COffsetVal == 0 || FlatVariant != FlatAddrSpace::FLAT || IsInBounds) {
1941 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
1942 if (
TII->isLegalFLATOffset(COffsetVal, AS, FlatVariant)) {
1944 OffsetVal = COffsetVal;
1959 std::tie(OffsetVal, RemainderOffset) =
1960 TII->splitFlatOffset(COffsetVal, AS, FlatVariant);
1962 SDValue AddOffsetLo =
1963 getMaterializedScalarImm32(
Lo_32(RemainderOffset),
DL);
1964 SDValue Clamp =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
1970 unsigned AddOp = AMDGPU::V_ADD_CO_U32_e32;
1971 if (Subtarget->hasAddNoCarryInsts()) {
1972 AddOp = AMDGPU::V_ADD_U32_e64;
1976 SDValue(
CurDAG->getMachineNode(AddOp,
DL, MVT::i32, Opnds), 0);
1981 CurDAG->getTargetConstant(AMDGPU::sub0,
DL, MVT::i32);
1983 CurDAG->getTargetConstant(AMDGPU::sub1,
DL, MVT::i32);
1985 SDNode *N0Lo =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
1986 DL, MVT::i32, N0, Sub0);
1987 SDNode *N0Hi =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
1988 DL, MVT::i32, N0, Sub1);
1990 SDValue AddOffsetHi =
1991 getMaterializedScalarImm32(
Hi_32(RemainderOffset),
DL);
1993 SDVTList VTs =
CurDAG->getVTList(MVT::i32, MVT::i1);
1996 CurDAG->getMachineNode(AMDGPU::V_ADD_CO_U32_e64,
DL, VTs,
1997 {AddOffsetLo, SDValue(N0Lo, 0), Clamp});
1999 SDNode *Addc =
CurDAG->getMachineNode(
2000 AMDGPU::V_ADDC_U32_e64,
DL, VTs,
2001 {AddOffsetHi, SDValue(N0Hi, 0), SDValue(
Add, 1), Clamp});
2003 SDValue RegSequenceArgs[] = {
2004 CurDAG->getTargetConstant(AMDGPU::VReg_64RegClassID,
DL,
2006 SDValue(
Add, 0), Sub0, SDValue(Addc, 0), Sub1};
2008 Addr = SDValue(
CurDAG->getMachineNode(AMDGPU::REG_SEQUENCE,
DL,
2009 MVT::i64, RegSequenceArgs),
2018 Offset =
CurDAG->getSignedTargetConstant(OffsetVal, SDLoc(), MVT::i32);
2022bool AMDGPUDAGToDAGISel::SelectFlatOffset(
SDNode *
N,
SDValue Addr,
2025 return SelectFlatOffsetImpl(
N, Addr, VAddr,
Offset,
2029bool AMDGPUDAGToDAGISel::SelectGlobalOffset(
SDNode *
N,
SDValue Addr,
2032 return SelectFlatOffsetImpl(
N, Addr, VAddr,
Offset,
2036bool AMDGPUDAGToDAGISel::SelectScratchOffset(
SDNode *
N,
SDValue Addr,
2039 return SelectFlatOffsetImpl(
N, Addr, VAddr,
Offset,
2047 if (
Op.getValueType() == MVT::i32)
2062bool AMDGPUDAGToDAGISel::SelectGlobalSAddr(
SDNode *
N,
SDValue Addr,
2065 bool NeedIOffset)
const {
2067 int64_t ImmOffset = 0;
2068 ScaleOffset =
false;
2074 if (isBaseWithConstantOffset64(Addr,
LHS,
RHS)) {
2076 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
2080 FlatAddrSpace::FlatGlobal)) {
2082 ImmOffset = COffsetVal;
2083 }
else if (!
LHS->isDivergent()) {
2084 if (COffsetVal != 0) {
2089 int64_t SplitImmOffset = 0, RemainderOffset = COffsetVal;
2091 std::tie(SplitImmOffset, RemainderOffset) =
TII->splitFlatOffset(
2095 if (Subtarget->hasSignedGVSOffset() ?
isInt<32>(RemainderOffset)
2097 SDNode *VMov =
CurDAG->getMachineNode(
2098 AMDGPU::V_MOV_B32_e32, SL, MVT::i32,
2099 CurDAG->getTargetConstant(
Lo_32(RemainderOffset), SDLoc(),
2101 VOffset = SDValue(VMov, 0);
2103 Offset =
CurDAG->getSignedTargetConstant(SplitImmOffset, SDLoc(),
2114 unsigned NumLiterals =
2115 !
TII->isInlineConstant(APInt(32,
Lo_32(COffsetVal))) +
2116 !
TII->isInlineConstant(APInt(32,
Hi_32(COffsetVal)));
2117 if (Subtarget->getConstantBusLimit(AMDGPU::V_ADD_U32_e64) > NumLiterals)
2126 if (!
LHS->isDivergent()) {
2129 ScaleOffset = SelectScaleOffset(
N,
RHS, Subtarget->hasSignedGVSOffset());
2131 RHS, Subtarget->hasSignedGVSOffset(),
CurDAG)) {
2138 if (!SAddr && !
RHS->isDivergent()) {
2140 ScaleOffset = SelectScaleOffset(
N,
LHS, Subtarget->hasSignedGVSOffset());
2142 LHS, Subtarget->hasSignedGVSOffset(),
CurDAG)) {
2149 Offset =
CurDAG->getSignedTargetConstant(ImmOffset, SDLoc(), MVT::i32);
2154 if (Subtarget->hasScaleOffset() &&
2155 (Addr.
getOpcode() == (Subtarget->hasSignedGVSOffset()
2170 Offset =
CurDAG->getTargetConstant(ImmOffset, SDLoc(), MVT::i32);
2182 CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32, SDLoc(Addr), MVT::i32,
2183 CurDAG->getTargetConstant(0, SDLoc(), MVT::i32));
2184 VOffset = SDValue(VMov, 0);
2185 Offset =
CurDAG->getSignedTargetConstant(ImmOffset, SDLoc(), MVT::i32);
2189bool AMDGPUDAGToDAGISel::SelectGlobalSAddr(
SDNode *
N,
SDValue Addr,
2194 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset,
Offset, ScaleOffset))
2202bool AMDGPUDAGToDAGISel::SelectGlobalSAddrCPol(
SDNode *
N,
SDValue Addr,
2207 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset,
Offset, ScaleOffset))
2212 N->getConstantOperandVal(
N->getNumOperands() - 1) & ~AMDGPU::CPol::SCAL;
2218bool AMDGPUDAGToDAGISel::SelectGlobalSAddrCPolM0(
SDNode *
N,
SDValue Addr,
2224 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset,
Offset, ScaleOffset))
2229 N->getConstantOperandVal(
N->getNumOperands() - 2) & ~AMDGPU::CPol::SCAL;
2235bool AMDGPUDAGToDAGISel::SelectGlobalSAddrGLC(
SDNode *
N,
SDValue Addr,
2240 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset,
Offset, ScaleOffset))
2244 CPol =
CurDAG->getTargetConstant(CPolVal, SDLoc(), MVT::i32);
2248bool AMDGPUDAGToDAGISel::SelectGlobalSAddrNoIOffset(
SDNode *
N,
SDValue Addr,
2253 SDValue DummyOffset;
2254 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset, DummyOffset, ScaleOffset,
2260 N->getConstantOperandVal(
N->getNumOperands() - 1) & ~AMDGPU::CPol::SCAL;
2266bool AMDGPUDAGToDAGISel::SelectGlobalSAddrNoIOffsetM0(
SDNode *
N,
SDValue Addr,
2271 SDValue DummyOffset;
2272 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset, DummyOffset, ScaleOffset,
2293 FI->getValueType(0));
2303bool AMDGPUDAGToDAGISel::SelectScratchSAddr(
SDNode *Parent,
SDValue Addr,
2312 int64_t COffsetVal = 0;
2314 if (
CurDAG->isBaseWithConstantOffset(Addr) && isFlatScratchBaseLegal(Addr)) {
2323 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
2326 FlatAddrSpace::FlatScratch)) {
2327 int64_t SplitImmOffset, RemainderOffset;
2328 std::tie(SplitImmOffset, RemainderOffset) =
TII->splitFlatOffset(
2331 COffsetVal = SplitImmOffset;
2335 ? getMaterializedScalarImm32(
Lo_32(RemainderOffset),
DL)
2336 :
CurDAG->getSignedTargetConstant(RemainderOffset,
DL, MVT::i32);
2337 SAddr = SDValue(
CurDAG->getMachineNode(AMDGPU::S_ADD_I32,
DL, MVT::i32,
2342 Offset =
CurDAG->getSignedTargetConstant(COffsetVal,
DL, MVT::i32);
2348bool AMDGPUDAGToDAGISel::checkFlatScratchSVSSwizzleBug(
2350 if (!Subtarget->hasFlatScratchSVSSwizzleBug())
2356 KnownBits VKnown =
CurDAG->computeKnownBits(VAddr);
2363 return (VMax & 3) + (
SMax & 3) >= 4;
2366bool AMDGPUDAGToDAGISel::SelectScratchSVAddr(
SDNode *
N,
SDValue Addr,
2370 int64_t ImmOffset = 0;
2373 SDValue OrigAddr = Addr;
2374 if (isBaseWithConstantOffset64(Addr,
LHS,
RHS)) {
2376 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
2381 ImmOffset = COffsetVal;
2382 }
else if (!
LHS->isDivergent() && COffsetVal > 0) {
2386 int64_t SplitImmOffset, RemainderOffset;
2387 std::tie(SplitImmOffset, RemainderOffset) =
2392 SDNode *VMov =
CurDAG->getMachineNode(
2393 AMDGPU::V_MOV_B32_e32, SL, MVT::i32,
2394 CurDAG->getTargetConstant(RemainderOffset, SDLoc(), MVT::i32));
2395 VAddr = SDValue(VMov, 0);
2397 if (!isFlatScratchBaseLegal(Addr))
2399 if (checkFlatScratchSVSSwizzleBug(VAddr, SAddr, SplitImmOffset))
2401 Offset =
CurDAG->getTargetConstant(SplitImmOffset, SDLoc(), MVT::i32);
2402 CPol =
CurDAG->getTargetConstant(0, SDLoc(), MVT::i32);
2414 if (!
LHS->isDivergent() &&
RHS->isDivergent()) {
2417 }
else if (!
RHS->isDivergent() &&
LHS->isDivergent()) {
2424 if (OrigAddr != Addr) {
2425 if (!isFlatScratchBaseLegalSVImm(OrigAddr))
2428 if (!isFlatScratchBaseLegalSV(OrigAddr))
2432 if (checkFlatScratchSVSSwizzleBug(VAddr, SAddr, ImmOffset))
2435 Offset =
CurDAG->getSignedTargetConstant(ImmOffset, SDLoc(), MVT::i32);
2437 bool ScaleOffset = SelectScaleOffset(
N, VAddr,
true );
2446bool AMDGPUDAGToDAGISel::isSOffsetLegalWithImmOffset(
SDValue *SOffset,
2449 int64_t ImmOffset)
const {
2450 if (!IsBuffer && !Imm32Only && ImmOffset < 0 &&
2452 KnownBits SKnown =
CurDAG->computeKnownBits(*SOffset);
2464 bool IsSigned)
const {
2465 bool ScaleOffset =
false;
2466 if (!Subtarget->hasScaleOffset() || !
Offset)
2480 (IsSigned &&
Offset.getOpcode() == AMDGPUISD::MUL_I24) ||
2481 Offset.getOpcode() == AMDGPUISD::MUL_U24 ||
2482 (
Offset.isMachineOpcode() &&
2483 Offset.getMachineOpcode() ==
2484 (IsSigned ? AMDGPU::S_MUL_I64_I32_PSEUDO
2485 : AMDGPU::S_MUL_U64_U32_PSEUDO))) {
2487 ScaleOffset =
C->getZExtValue() ==
Size;
2499bool AMDGPUDAGToDAGISel::SelectSMRDOffset(
SDNode *
N,
SDValue ByteOffsetNode,
2501 bool Imm32Only,
bool IsBuffer,
2502 bool HasSOffset, int64_t ImmOffset,
2503 bool *ScaleOffset)
const {
2505 "Cannot match both soffset and offset at the same time!");
2510 *ScaleOffset = SelectScaleOffset(
N, ByteOffsetNode,
false );
2520 *SOffset = ByteOffsetNode;
2521 return isSOffsetLegalWithImmOffset(SOffset, Imm32Only, IsBuffer,
2527 return isSOffsetLegalWithImmOffset(SOffset, Imm32Only, IsBuffer,
2534 SDLoc SL(ByteOffsetNode);
2538 int64_t ByteOffset = IsBuffer ?
C->getZExtValue() :
C->getSExtValue();
2540 *Subtarget, ByteOffset, IsBuffer, HasSOffset);
2541 if (EncodedOffset &&
Offset && !Imm32Only) {
2542 *
Offset =
CurDAG->getSignedTargetConstant(*EncodedOffset, SL, MVT::i32);
2551 if (EncodedOffset &&
Offset && Imm32Only) {
2552 *
Offset =
CurDAG->getTargetConstant(*EncodedOffset, SL, MVT::i32);
2560 SDValue C32Bit =
CurDAG->getTargetConstant(ByteOffset, SL, MVT::i32);
2562 CurDAG->getMachineNode(AMDGPU::S_MOV_B32, SL, MVT::i32, C32Bit), 0);
2569SDValue AMDGPUDAGToDAGISel::Expand32BitAddress(
SDValue Addr)
const {
2577 const SIMachineFunctionInfo *
Info =
MF.getInfo<SIMachineFunctionInfo>();
2578 unsigned AddrHiVal =
Info->get32BitAddressHighBits();
2579 SDValue AddrHi =
CurDAG->getTargetConstant(AddrHiVal, SL, MVT::i32);
2581 const SDValue
Ops[] = {
2582 CurDAG->getTargetConstant(AMDGPU::SReg_64_XEXECRegClassID, SL, MVT::i32),
2584 CurDAG->getTargetConstant(AMDGPU::sub0, SL, MVT::i32),
2585 SDValue(
CurDAG->getMachineNode(AMDGPU::S_MOV_B32, SL, MVT::i32, AddrHi),
2587 CurDAG->getTargetConstant(AMDGPU::sub1, SL, MVT::i32),
2590 return SDValue(
CurDAG->getMachineNode(AMDGPU::REG_SEQUENCE, SL, MVT::i64,
2597bool AMDGPUDAGToDAGISel::SelectSMRDBaseOffset(
SDNode *
N,
SDValue Addr,
2600 bool IsBuffer,
bool HasSOffset,
2602 bool *ScaleOffset)
const {
2604 assert(!Imm32Only && !IsBuffer);
2607 if (!SelectSMRDBaseOffset(
N, Addr,
B,
nullptr,
Offset,
false,
false,
true))
2612 ImmOff =
C->getSExtValue();
2614 return SelectSMRDBaseOffset(
N,
B, SBase, SOffset,
nullptr,
false,
false,
2615 true, ImmOff, ScaleOffset);
2635 if (SelectSMRDOffset(
N, N1, SOffset,
Offset, Imm32Only, IsBuffer, HasSOffset,
2636 ImmOffset, ScaleOffset)) {
2640 if (SelectSMRDOffset(
N, N0, SOffset,
Offset, Imm32Only, IsBuffer, HasSOffset,
2641 ImmOffset, ScaleOffset)) {
2650 bool Imm32Only,
bool *ScaleOffset)
const {
2651 if (SelectSMRDBaseOffset(
N, Addr, SBase, SOffset,
Offset, Imm32Only,
2654 SBase = Expand32BitAddress(SBase);
2659 SBase = Expand32BitAddress(Addr);
2660 *
Offset =
CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
2667bool AMDGPUDAGToDAGISel::SelectSMRDImm(
SDValue Addr,
SDValue &SBase,
2669 return SelectSMRD(
nullptr, Addr, SBase,
nullptr,
2673bool AMDGPUDAGToDAGISel::SelectSMRDImm32(
SDValue Addr,
SDValue &SBase,
2676 return SelectSMRD(
nullptr, Addr, SBase,
nullptr,
2683 if (!SelectSMRD(
N, Addr, SBase, &SOffset,
nullptr,
2684 false, &ScaleOffset))
2688 SDLoc(
N), MVT::i32);
2692bool AMDGPUDAGToDAGISel::SelectSMRDSgprImm(
SDNode *
N,
SDValue Addr,
2697 if (!SelectSMRD(
N, Addr, SBase, &SOffset, &
Offset,
false, &ScaleOffset))
2701 SDLoc(
N), MVT::i32);
2706 return SelectSMRDOffset(
nullptr,
N,
nullptr, &
Offset,
2710bool AMDGPUDAGToDAGISel::SelectSMRDBufferImm32(
SDValue N,
2713 return SelectSMRDOffset(
nullptr,
N,
nullptr, &
Offset,
2717bool AMDGPUDAGToDAGISel::SelectSMRDBufferSgprImm(
SDValue N,
SDValue &SOffset,
2721 return N.getValueType() == MVT::i32 &&
2722 SelectSMRDBaseOffset(
nullptr,
N, SOffset,
2727bool AMDGPUDAGToDAGISel::SelectMOVRELOffset(
SDValue Index,
2732 if (
CurDAG->isBaseWithConstantOffset(Index)) {
2733 SDValue N0 =
Index.getOperand(0);
2734 SDValue N1 =
Index.getOperand(1);
2757SDNode *AMDGPUDAGToDAGISel::getBFE32(
bool IsSigned,
const SDLoc &
DL,
2761 unsigned Opcode = IsSigned ? AMDGPU::V_BFE_I32_e64 : AMDGPU::V_BFE_U32_e64;
2763 SDValue
W =
CurDAG->getTargetConstant(Width,
DL, MVT::i32);
2765 return CurDAG->getMachineNode(Opcode,
DL, MVT::i32, Val,
Off, W);
2767 unsigned Opcode = IsSigned ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32;
2771 uint32_t PackedVal =
Offset | (Width << 16);
2772 SDValue PackedConst =
CurDAG->getTargetConstant(PackedVal,
DL, MVT::i32);
2774 return CurDAG->getMachineNode(Opcode,
DL, MVT::i32, Val, PackedConst);
2777void AMDGPUDAGToDAGISel::SelectS_BFEFromShifts(
SDNode *
N) {
2782 const SDValue &Shl =
N->getOperand(0);
2787 uint32_t BVal =
B->getZExtValue();
2788 uint32_t CVal =
C->getZExtValue();
2790 if (0 < BVal && BVal <= CVal && CVal < 32) {
2800void AMDGPUDAGToDAGISel::SelectS_BFE(
SDNode *
N) {
2801 switch (
N->getOpcode()) {
2803 if (
N->getOperand(0).getOpcode() ==
ISD::SRL) {
2806 const SDValue &Srl =
N->getOperand(0);
2810 if (Shift && Mask) {
2812 uint32_t MaskVal =
Mask->getZExtValue();
2824 if (
N->getOperand(0).getOpcode() ==
ISD::AND) {
2827 const SDValue &
And =
N->getOperand(0);
2831 if (Shift && Mask) {
2833 uint32_t MaskVal =
Mask->getZExtValue() >> ShiftVal;
2842 }
else if (
N->getOperand(0).getOpcode() ==
ISD::SHL) {
2843 SelectS_BFEFromShifts(
N);
2848 if (
N->getOperand(0).getOpcode() ==
ISD::SHL) {
2849 SelectS_BFEFromShifts(
N);
2856 SDValue Src =
N->getOperand(0);
2864 unsigned Width =
cast<VTSDNode>(
N->getOperand(1))->getVT().getSizeInBits();
2874bool AMDGPUDAGToDAGISel::isCBranchSCC(
const SDNode *
N)
const {
2876 if (!
N->hasOneUse())
2879 SDValue
Cond =
N->getOperand(1);
2886 MVT VT =
Cond.getOperand(0).getSimpleValueType();
2890 if (VT == MVT::i64) {
2893 Subtarget->hasScalarCompareEq64();
2896 if ((VT == MVT::f16 || VT == MVT::f32) && Subtarget->hasSALUFloatInsts())
2929void AMDGPUDAGToDAGISel::SelectBRCOND(
SDNode *
N) {
2930 SDValue
Cond =
N->getOperand(1);
2932 if (
Cond.isUndef()) {
2933 CurDAG->SelectNodeTo(
N, AMDGPU::SI_BR_UNDEF, MVT::Other,
2934 N->getOperand(2),
N->getOperand(0));
2938 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
2940 bool UseSCCBr = isCBranchSCC(
N) && isUniformBr(
N);
2941 bool AndExec = !UseSCCBr;
2942 bool Negate =
false;
2945 Cond->getOperand(0)->getOpcode() == AMDGPUISD::SETCC) {
2946 SDValue VCMP =
Cond->getOperand(0);
2960 bool NegatedBallot =
false;
2963 UseSCCBr = !BallotCond->isDivergent();
2964 Negate = Negate ^ NegatedBallot;
2979 UseSCCBr ? (Negate ? AMDGPU::S_CBRANCH_SCC0 : AMDGPU::S_CBRANCH_SCC1)
2980 : (Negate ? AMDGPU::S_CBRANCH_VCCZ : AMDGPU::S_CBRANCH_VCCNZ);
2981 Register CondReg = UseSCCBr ? AMDGPU::SCC :
TRI->getVCC();
3000 Subtarget->isWave32() ? AMDGPU::S_AND_B32 : AMDGPU::S_AND_B64, SL,
3002 CurDAG->getRegister(Subtarget->isWave32() ? AMDGPU::EXEC_LO
3009 SDValue VCC =
CurDAG->getCopyToReg(
N->getOperand(0), SL, CondReg,
Cond);
3010 CurDAG->SelectNodeTo(
N, BrOp, MVT::Other,
3015void AMDGPUDAGToDAGISel::SelectFP_EXTEND(
SDNode *
N) {
3016 if (Subtarget->hasSALUFloatInsts() &&
N->getValueType(0) == MVT::f32 &&
3017 !
N->isDivergent()) {
3018 SDValue Src =
N->getOperand(0);
3019 if (Src.getValueType() == MVT::f16) {
3021 CurDAG->SelectNodeTo(
N, AMDGPU::S_CVT_HI_F32_F16,
N->getVTList(),
3031void AMDGPUDAGToDAGISel::SelectDSAppendConsume(
SDNode *
N,
unsigned IntrID) {
3034 unsigned Opc = IntrID == Intrinsic::amdgcn_ds_append ?
3035 AMDGPU::DS_APPEND : AMDGPU::DS_CONSUME;
3037 SDValue Chain =
N->getOperand(0);
3040 MachineMemOperand *MMO =
M->getMemOperand();
3044 if (
CurDAG->isBaseWithConstantOffset(Ptr)) {
3049 if (isDSOffsetLegal(PtrBase, OffsetVal.
getZExtValue())) {
3050 N = glueCopyToM0(
N, PtrBase);
3051 Offset =
CurDAG->getTargetConstant(OffsetVal, SDLoc(), MVT::i32);
3056 N = glueCopyToM0(
N, Ptr);
3057 Offset =
CurDAG->getTargetConstant(0, SDLoc(), MVT::i32);
3062 CurDAG->getTargetConstant(IsGDS, SDLoc(), MVT::i32),
3067 SDNode *Selected =
CurDAG->SelectNodeTo(
N,
Opc,
N->getVTList(),
Ops);
3073void AMDGPUDAGToDAGISel::SelectDSBvhStackIntrinsic(
SDNode *
N,
unsigned IntrID) {
3076 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
3077 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
3078 Opc = AMDGPU::DS_BVH_STACK_RTN_B32;
3080 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
3081 Opc = AMDGPU::DS_BVH_STACK_PUSH8_POP1_RTN_B32;
3083 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn:
3084 Opc = AMDGPU::DS_BVH_STACK_PUSH8_POP2_RTN_B64;
3087 SDValue
Ops[] = {
N->getOperand(2),
N->getOperand(3),
N->getOperand(4),
3088 N->getOperand(5),
N->getOperand(0)};
3091 MachineMemOperand *MMO =
M->getMemOperand();
3092 SDNode *Selected =
CurDAG->SelectNodeTo(
N,
Opc,
N->getVTList(),
Ops);
3096void AMDGPUDAGToDAGISel::SelectTensorLoadStore(
SDNode *
N,
unsigned IntrID) {
3097 bool IsLoad = IntrID == Intrinsic::amdgcn_tensor_load_to_lds;
3099 IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d4 : AMDGPU::TENSOR_STORE_FROM_LDS_d4;
3107 SDValue Group2 =
N->getOperand(4);
3108 SDValue Group3 =
N->getOperand(5);
3111 Opc = IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d2
3112 : AMDGPU::TENSOR_STORE_FROM_LDS_d2;
3124 (void)
CurDAG->SelectNodeTo(
N,
Opc, MVT::Other, TensorOps);
3129 case Intrinsic::amdgcn_ds_gws_init:
3130 return AMDGPU::DS_GWS_INIT;
3131 case Intrinsic::amdgcn_ds_gws_barrier:
3132 return AMDGPU::DS_GWS_BARRIER;
3133 case Intrinsic::amdgcn_ds_gws_sema_v:
3134 return AMDGPU::DS_GWS_SEMA_V;
3135 case Intrinsic::amdgcn_ds_gws_sema_br:
3136 return AMDGPU::DS_GWS_SEMA_BR;
3137 case Intrinsic::amdgcn_ds_gws_sema_p:
3138 return AMDGPU::DS_GWS_SEMA_P;
3139 case Intrinsic::amdgcn_ds_gws_sema_release_all:
3140 return AMDGPU::DS_GWS_SEMA_RELEASE_ALL;
3146void AMDGPUDAGToDAGISel::SelectDS_GWS(
SDNode *
N,
unsigned IntrID) {
3147 if (!Subtarget->hasGWS() ||
3148 (IntrID == Intrinsic::amdgcn_ds_gws_sema_release_all &&
3149 !Subtarget->hasGWSSemaReleaseAll())) {
3156 const bool HasVSrc =
N->getNumOperands() == 4;
3157 assert(HasVSrc ||
N->getNumOperands() == 3);
3160 SDValue BaseOffset =
N->getOperand(HasVSrc ? 3 : 2);
3163 MachineMemOperand *MMO =
M->getMemOperand();
3176 glueCopyToM0(
N,
CurDAG->getTargetConstant(0, SL, MVT::i32));
3177 ImmOffset = ConstOffset->getZExtValue();
3179 if (
CurDAG->isBaseWithConstantOffset(BaseOffset)) {
3188 =
CurDAG->getMachineNode(AMDGPU::V_READFIRSTLANE_B32, SL, MVT::i32,
3192 =
CurDAG->getMachineNode(AMDGPU::S_LSHL_B32, SL, MVT::i32,
3193 SDValue(SGPROffset, 0),
3194 CurDAG->getTargetConstant(16, SL, MVT::i32));
3195 glueCopyToM0(
N, SDValue(M0Base, 0));
3199 SDValue OffsetField =
CurDAG->getTargetConstant(ImmOffset, SL, MVT::i32);
3203 const MCInstrDesc &InstrDesc =
TII->get(
Opc);
3204 int Data0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
3210 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3212 SDValue
Data =
N->getOperand(2);
3213 MVT DataVT =
Data.getValueType().getSimpleVT();
3214 if (
TRI->isTypeLegalForClass(*DataRC, DataVT)) {
3216 Ops.push_back(
N->getOperand(2));
3220 const SDValue RegSeqOps[] = {
3222 CurDAG->getTargetConstant(AMDGPU::sub0, SL, MVT::i32),
3224 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, SL, MVT::i32),
3226 CurDAG->getTargetConstant(AMDGPU::sub1, SL, MVT::i32)};
3228 Ops.push_back(SDValue(
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
3229 SL, MVT::v2i32, RegSeqOps),
3234 Ops.push_back(OffsetField);
3235 Ops.push_back(Chain);
3237 SDNode *Selected =
CurDAG->SelectNodeTo(
N,
Opc,
N->getVTList(),
Ops);
3241void AMDGPUDAGToDAGISel::SelectInterpP1F16(
SDNode *
N) {
3242 if (Subtarget->getLDSBankCount() != 16) {
3269 SDValue ToM0 =
CurDAG->getCopyToReg(
CurDAG->getEntryNode(),
DL, AMDGPU::M0,
3270 N->getOperand(5), SDValue());
3272 SDVTList VTs =
CurDAG->getVTList(MVT::f32, MVT::Other);
3275 CurDAG->getMachineNode(AMDGPU::V_INTERP_MOV_F32,
DL, VTs, {
3276 CurDAG->getTargetConstant(2,
DL, MVT::i32),
3282 SDNode *InterpP1LV =
3283 CurDAG->getMachineNode(AMDGPU::V_INTERP_P1LV_F16,
DL, MVT::f32, {
3284 CurDAG->getTargetConstant(0,
DL, MVT::i32),
3288 CurDAG->getTargetConstant(0,
DL, MVT::i32),
3289 SDValue(InterpMov, 0),
3291 CurDAG->getTargetConstant(0,
DL, MVT::i1),
3292 CurDAG->getTargetConstant(0,
DL, MVT::i32),
3293 SDValue(InterpMov, 1)
3296 CurDAG->ReplaceAllUsesOfValueWith(SDValue(
N, 0), SDValue(InterpP1LV, 0));
3299void AMDGPUDAGToDAGISel::SelectINTRINSIC_W_CHAIN(
SDNode *
N) {
3300 unsigned IntrID =
N->getConstantOperandVal(1);
3302 case Intrinsic::amdgcn_ds_append:
3303 case Intrinsic::amdgcn_ds_consume: {
3304 if (
N->getValueType(0) != MVT::i32)
3306 SelectDSAppendConsume(
N, IntrID);
3309 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
3310 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
3311 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
3312 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn:
3313 SelectDSBvhStackIntrinsic(
N, IntrID);
3315 case Intrinsic::amdgcn_init_whole_wave:
3316 CurDAG->getMachineFunction()
3317 .getInfo<SIMachineFunctionInfo>()
3318 ->setInitWholeWave();
3325void AMDGPUDAGToDAGISel::SelectINTRINSIC_WO_CHAIN(
SDNode *
N) {
3326 unsigned IntrID =
N->getConstantOperandVal(0);
3327 unsigned Opcode = AMDGPU::INSTRUCTION_LIST_END;
3328 SDNode *ConvGlueNode =
N->getGluedNode();
3334 CurDAG->getMachineNode(TargetOpcode::CONVERGENCECTRL_GLUE, {},
3335 MVT::Glue, SDValue(ConvGlueNode, 0));
3337 ConvGlueNode =
nullptr;
3340 case Intrinsic::amdgcn_wqm:
3341 Opcode = AMDGPU::WQM;
3343 case Intrinsic::amdgcn_softwqm:
3344 Opcode = AMDGPU::SOFT_WQM;
3346 case Intrinsic::amdgcn_wwm:
3347 case Intrinsic::amdgcn_strict_wwm:
3348 Opcode = AMDGPU::STRICT_WWM;
3350 case Intrinsic::amdgcn_strict_wqm:
3351 Opcode = AMDGPU::STRICT_WQM;
3353 case Intrinsic::amdgcn_interp_p1_f16:
3354 SelectInterpP1F16(
N);
3356 case Intrinsic::amdgcn_permlane16_swap:
3357 case Intrinsic::amdgcn_permlane32_swap: {
3358 if ((IntrID == Intrinsic::amdgcn_permlane16_swap &&
3359 !Subtarget->hasPermlane16Swap()) ||
3360 (IntrID == Intrinsic::amdgcn_permlane32_swap &&
3361 !Subtarget->hasPermlane32Swap())) {
3366 Opcode = IntrID == Intrinsic::amdgcn_permlane16_swap
3367 ? AMDGPU::V_PERMLANE16_SWAP_B32_e64
3368 : AMDGPU::V_PERMLANE32_SWAP_B32_e64;
3372 NewOps.push_back(SDValue(ConvGlueNode, 0));
3374 bool FI =
N->getConstantOperandVal(3);
3375 NewOps[2] =
CurDAG->getTargetConstant(
3378 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(), NewOps);
3386 if (Opcode != AMDGPU::INSTRUCTION_LIST_END) {
3387 SDValue Src =
N->getOperand(1);
3388 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(), {Src});
3393 NewOps.push_back(SDValue(ConvGlueNode, 0));
3394 CurDAG->MorphNodeTo(
N,
N->getOpcode(),
N->getVTList(), NewOps);
3398void AMDGPUDAGToDAGISel::SelectINTRINSIC_VOID(
SDNode *
N) {
3399 unsigned IntrID =
N->getConstantOperandVal(1);
3401 case Intrinsic::amdgcn_ds_gws_init:
3402 case Intrinsic::amdgcn_ds_gws_barrier:
3403 case Intrinsic::amdgcn_ds_gws_sema_v:
3404 case Intrinsic::amdgcn_ds_gws_sema_br:
3405 case Intrinsic::amdgcn_ds_gws_sema_p:
3406 case Intrinsic::amdgcn_ds_gws_sema_release_all:
3407 SelectDS_GWS(
N, IntrID);
3409 case Intrinsic::amdgcn_tensor_load_to_lds:
3410 case Intrinsic::amdgcn_tensor_store_from_lds:
3411 SelectTensorLoadStore(
N, IntrID);
3420void AMDGPUDAGToDAGISel::SelectWAVE_ADDRESS(
SDNode *
N) {
3421 SDValue Log2WaveSize =
3422 CurDAG->getTargetConstant(Subtarget->getWavefrontSizeLog2(), SDLoc(
N), MVT::i32);
3423 CurDAG->SelectNodeTo(
N, AMDGPU::S_LSHR_B32,
N->getVTList(),
3424 {N->getOperand(0), Log2WaveSize});
3427void AMDGPUDAGToDAGISel::SelectSTACKRESTORE(
SDNode *
N) {
3428 SDValue SrcVal =
N->getOperand(1);
3441 SDValue Log2WaveSize =
CurDAG->getTargetConstant(
3442 Subtarget->getWavefrontSizeLog2(), SL, MVT::i32);
3444 if (
N->isDivergent()) {
3445 SrcVal = SDValue(
CurDAG->getMachineNode(AMDGPU::V_READFIRSTLANE_B32, SL,
3450 CopyVal = SDValue(
CurDAG->getMachineNode(AMDGPU::S_LSHL_B32, SL, MVT::i32,
3451 {SrcVal, Log2WaveSize}),
3455 SDValue CopyToSP =
CurDAG->getCopyToReg(
N->getOperand(0), SL,
SP, CopyVal);
3456 CurDAG->ReplaceAllUsesOfValueWith(SDValue(
N, 0), CopyToSP);
3459void AMDGPUDAGToDAGISel::SelectWRITE_REGISTER(
SDNode *
N) {
3466 CurDAG->getMachineFunction());
3470 "invalid register \"" + Twine(RegStr->
getString()) +
3471 "\" for llvm.write_register",
3472 Fn,
N->getDebugLoc()));
3484 }
else if (VT == MVT::i32) {
3485 CopyVal = SDValue(
CurDAG->getMachineNode(AMDGPU::V_READFIRSTLANE_B32, SL,
3491 CurDAG->getTargetExtractSubreg(AMDGPU::sub0, SL, MVT::i32, SrcVal);
3493 CurDAG->getTargetExtractSubreg(AMDGPU::sub1, SL, MVT::i32, SrcVal);
3495 CurDAG->getMachineNode(AMDGPU::V_READFIRSTLANE_B32, SL, MVT::i32,
Lo),
3498 CurDAG->getMachineNode(AMDGPU::V_READFIRSTLANE_B32, SL, MVT::i32,
Hi),
3500 CopyVal = emitRegSequence(*
CurDAG, AMDGPU::SReg_64RegClassID, VT, {
Lo,
Hi},
3501 {AMDGPU::sub0, AMDGPU::sub1}, SL);
3505 CurDAG->ReplaceAllUsesOfValueWith(SDValue(
N, 0), CopyToReg);
3508bool AMDGPUDAGToDAGISel::SelectVOP3ModsImpl(
SDValue In,
SDValue &Src,
3510 bool IsCanonicalizing,
3511 bool AllowAbs)
const {
3517 Src = Src.getOperand(0);
3518 }
else if (Src.getOpcode() ==
ISD::FSUB && IsCanonicalizing) {
3522 if (
LHS &&
LHS->isZero()) {
3524 Src = Src.getOperand(1);
3528 if (AllowAbs && Src.getOpcode() ==
ISD::FABS) {
3530 Src = Src.getOperand(0);
3543 if (IsCanonicalizing)
3558 EVT VT = Src.getValueType();
3560 (VT != MVT::i32 && VT != MVT::v2i32 && VT != MVT::i64))
3567 auto ReplaceSrc = [&]() -> SDValue {
3569 return Src.getOperand(0);
3572 SDValue
Index = Src->getOperand(1);
3574 Src.getValueType(),
LHS, Index);
3600 if (SelectVOP3ModsImpl(In, Src, Mods,
true,
3602 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3609bool AMDGPUDAGToDAGISel::SelectVOP3ModsNonCanonicalizing(
3612 if (SelectVOP3ModsImpl(In, Src, Mods,
false,
3614 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3621bool AMDGPUDAGToDAGISel::SelectVOP3BMods(
SDValue In,
SDValue &Src,
3624 if (SelectVOP3ModsImpl(In, Src, Mods,
3627 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3634bool AMDGPUDAGToDAGISel::SelectVOP3NoMods(
SDValue In,
SDValue &Src)
const {
3642bool AMDGPUDAGToDAGISel::SelectVINTERPModsImpl(
SDValue In,
SDValue &Src,
3646 if (SelectVOP3ModsImpl(In, Src, Mods,
3651 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3658bool AMDGPUDAGToDAGISel::SelectVINTERPMods(
SDValue In,
SDValue &Src,
3660 return SelectVINTERPModsImpl(In, Src, SrcMods,
false);
3663bool AMDGPUDAGToDAGISel::SelectVINTERPModsHi(
SDValue In,
SDValue &Src,
3665 return SelectVINTERPModsImpl(In, Src, SrcMods,
true);
3668bool AMDGPUDAGToDAGISel::SelectVOP3Mods0(
SDValue In,
SDValue &Src,
3672 Clamp =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3673 Omod =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3675 return SelectVOP3Mods(In, Src, SrcMods);
3678bool AMDGPUDAGToDAGISel::SelectVOP3BMods0(
SDValue In,
SDValue &Src,
3682 Clamp =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3683 Omod =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3685 return SelectVOP3BMods(In, Src, SrcMods);
3688bool AMDGPUDAGToDAGISel::SelectVOP3OMods(
SDValue In,
SDValue &Src,
3693 Clamp =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3694 Omod =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3699bool AMDGPUDAGToDAGISel::SelectVOP3PMods(
SDValue In,
SDValue &Src,
3700 SDValue &SrcMods,
bool IsDOT)
const {
3707 Src = Src.getOperand(0);
3711 bool HasOpSel = Src.getValueSizeInBits() != 128;
3714 (!IsDOT || !Subtarget->hasDOTOpSelHazard())) {
3715 unsigned VecMods = Mods;
3717 SDValue
Lo = stripBitcast(Src.getOperand(0));
3718 SDValue
Hi = stripBitcast(Src.getOperand(1));
3721 Lo = stripBitcast(
Lo.getOperand(0));
3726 Hi = stripBitcast(
Hi.getOperand(0));
3738 unsigned VecSize = Src.getValueSizeInBits();
3739 Lo = stripExtractLoElt(
Lo);
3740 Hi = stripExtractLoElt(
Hi);
3742 if (
Lo.getValueSizeInBits() > VecSize) {
3743 Lo =
CurDAG->getTargetExtractSubreg(
3744 (VecSize > 32) ? AMDGPU::sub0_sub1 : AMDGPU::sub0, SDLoc(In),
3748 if (
Hi.getValueSizeInBits() > VecSize) {
3749 Hi =
CurDAG->getTargetExtractSubreg(
3750 (VecSize > 32) ? AMDGPU::sub0_sub1 : AMDGPU::sub0, SDLoc(In),
3754 assert(
Lo.getValueSizeInBits() <= VecSize &&
3755 Hi.getValueSizeInBits() <= VecSize);
3757 if (
Lo ==
Hi && !isInlineImmediate(
Lo.getNode())) {
3761 if (VecSize ==
Lo.getValueSizeInBits()) {
3763 }
else if (VecSize == 32) {
3764 Src = createVOP3PSrc32FromLo16(
Lo, Src,
CurDAG, Subtarget);
3766 assert((
Lo.getValueSizeInBits() == 32 && VecSize == 64) ||
3767 (
Lo.getValueSizeInBits() == 64 && VecSize == 128));
3770 SDValue
Undef = SDValue(
3771 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, SL,
3772 Lo.getValueType()), 0);
3773 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3778 auto RC =
Lo->isDivergent() ?
TRI->getVGPRClassForBitWidth(VecSize)
3779 :
TRI->getSGPRClassForBitWidth(VecSize);
3780 unsigned NumRegs =
Lo.getValueSizeInBits() == 32 ? 1 : 2;
3781 const SDValue
Ops[] = {
3782 CurDAG->getTargetConstant(RC->getID(), SL, MVT::i32),
Lo,
3783 CurDAG->getTargetConstant(
TRI->getSubRegFromChannel(0, NumRegs), SL,
3788 CurDAG->getTargetConstant(
3789 TRI->getSubRegFromChannel(NumRegs, NumRegs), SL, MVT::i32)};
3791 Src = SDValue(
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, SL,
3792 Src.getValueType(),
Ops), 0);
3796 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3802 .bitcastToAPInt().getZExtValue();
3804 Src =
CurDAG->getTargetConstant(
Lit, SDLoc(In), MVT::i64);
3805 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3812 Src.getNumOperands() == 2) {
3817 assert(Src.getValueSizeInBits() != 128 &&
3818 "<2 x 64> VECTOR_SHUFFLE should not be legal.");
3821 ArrayRef<int>
Mask = SVN->getMask();
3823 if (Mask[0] < 2 && Mask[1] < 2) {
3825 SDValue ShuffleSrc = SVN->getOperand(0);
3838 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3846 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3850bool AMDGPUDAGToDAGISel::SelectVOP3PModsDOT(
SDValue In,
SDValue &Src,
3852 return SelectVOP3PMods(In, Src, SrcMods,
true);
3855bool AMDGPUDAGToDAGISel::SelectVOP3PNoModsDOT(
SDValue In,
SDValue &Src)
const {
3856 SDValue SrcTmp, SrcModsTmp;
3857 SelectVOP3PMods(In, SrcTmp, SrcModsTmp,
true);
3866bool AMDGPUDAGToDAGISel::SelectVOP3PModsF32(
SDValue In,
SDValue &Src,
3868 SelectVOP3Mods(In, Src, SrcMods);
3871 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3875bool AMDGPUDAGToDAGISel::SelectVOP3PNoModsF32(
SDValue In,
SDValue &Src)
const {
3876 SDValue SrcTmp, SrcModsTmp;
3877 SelectVOP3PModsF32(In, SrcTmp, SrcModsTmp);
3886bool AMDGPUDAGToDAGISel::SelectWMMAOpSelVOP3PMods(
SDValue In,
3889 assert(
C->getAPIntValue().getBitWidth() == 1 &&
"expected i1 value");
3892 unsigned SrcVal =
C->getZExtValue();
3896 Src =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3903 unsigned DstRegClass;
3905 switch (Elts.
size()) {
3907 DstRegClass = AMDGPU::VReg_256RegClassID;
3911 DstRegClass = AMDGPU::VReg_128RegClassID;
3915 DstRegClass = AMDGPU::VReg_64RegClassID;
3923 Ops.push_back(
CurDAG->getTargetConstant(DstRegClass,
DL, MVT::i32));
3924 for (
unsigned i = 0; i < Elts.
size(); ++i) {
3925 Ops.push_back(Elts[i]);
3926 Ops.push_back(
CurDAG->getTargetConstant(
3929 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL, DstTy,
Ops);
3936 assert(
"unhandled Reg sequence size" &&
3937 (Elts.
size() == 8 || Elts.
size() == 16));
3941 for (
unsigned i = 0; i < Elts.
size(); i += 2) {
3942 SDValue LoSrc = stripExtractLoElt(stripBitcast(Elts[i]));
3947 if (Subtarget->useRealTrue16Insts()) {
3951 SDValue
Undef = SDValue(
3952 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, MVT::i16),
3955 emitRegSequence(*
CurDAG, AMDGPU::VGPR_32RegClassID, MVT::i32,
3956 {Elts[i],
Undef}, {AMDGPU::lo16, AMDGPU::hi16},
DL);
3957 Elts[i + 1] = emitRegSequence(*
CurDAG, AMDGPU::VGPR_32RegClassID,
3958 MVT::i32, {Elts[i + 1],
Undef},
3959 {AMDGPU::lo16, AMDGPU::hi16},
DL);
3961 SDValue PackLoLo =
CurDAG->getTargetConstant(0x05040100,
DL, MVT::i32);
3963 CurDAG->getMachineNode(AMDGPU::V_PERM_B32_e64,
DL, MVT::i32,
3964 {Elts[i + 1], Elts[i], PackLoLo});
3965 PackedElts.
push_back(SDValue(Packed, 0));
3968 return buildRegSequence32(PackedElts,
DL);
3974 unsigned ElementSize)
const {
3975 if (ElementSize == 16)
3976 return buildRegSequence16(Elts,
DL);
3977 if (ElementSize == 32)
3978 return buildRegSequence32(Elts,
DL);
3982void AMDGPUDAGToDAGISel::selectWMMAModsNegAbs(
unsigned ModOpcode,
3986 unsigned ElementSize)
const {
3991 for (
auto El : Elts) {
3994 NegAbsElts.
push_back(El->getOperand(0));
3996 if (Elts.size() != NegAbsElts.
size()) {
3998 Src = SDValue(buildRegSequence(Elts,
DL, ElementSize), 0);
4002 Src = SDValue(buildRegSequence(NegAbsElts,
DL, ElementSize), 0);
4008 Src = SDValue(buildRegSequence(Elts,
DL, ElementSize), 0);
4016 std::function<
bool(
SDValue)> ModifierCheck) {
4020 for (
unsigned i = 0; i < F16Pair->getNumOperands(); ++i) {
4021 SDValue ElF16 = stripBitcast(F16Pair->getOperand(i));
4022 if (!ModifierCheck(ElF16))
4029bool AMDGPUDAGToDAGISel::SelectWMMAModsF16Neg(
SDValue In,
SDValue &Src,
4047 Src = SDValue(buildRegSequence16(EltsF16, SDLoc(In)), 0);
4057 SDValue ElV2f16 = stripBitcast(BV->
getOperand(i));
4066 Src = SDValue(buildRegSequence32(EltsV2F16, SDLoc(In)), 0);
4072 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4076bool AMDGPUDAGToDAGISel::SelectWMMAModsF16NegAbs(
SDValue In,
SDValue &Src,
4087 if (EltsF16.
empty())
4097 selectWMMAModsNegAbs(ModOpcode, Mods, EltsF16, Src, SDLoc(In), 16);
4105 SDValue ElV2f16 = stripBitcast(BV->
getOperand(i));
4107 if (EltsV2F16.
empty())
4116 selectWMMAModsNegAbs(ModOpcode, Mods, EltsV2F16, Src, SDLoc(In), 32);
4119 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4123bool AMDGPUDAGToDAGISel::SelectWMMAModsF32NegAbs(
SDValue In,
SDValue &Src,
4132 SDValue ElF32 = stripBitcast(BV->
getOperand(0));
4133 unsigned ModOpcode =
4136 SDValue ElF32 = stripBitcast(BV->
getOperand(i));
4144 selectWMMAModsNegAbs(ModOpcode, Mods, EltsF32, Src, SDLoc(In), 32);
4147 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4151bool AMDGPUDAGToDAGISel::SelectWMMAVISrc(
SDValue In,
SDValue &Src)
const {
4153 BitVector UndefElements;
4155 if (isInlineImmediate(
Splat.getNode())) {
4157 unsigned Imm =
C->getAPIntValue().getSExtValue();
4158 Src =
CurDAG->getTargetConstant(
Imm, SDLoc(In), MVT::i32);
4162 unsigned Imm =
C->getValueAPF().bitcastToAPInt().getSExtValue();
4163 Src =
CurDAG->getTargetConstant(
Imm, SDLoc(In), MVT::i32);
4171 SDValue SplatSrc32 = stripBitcast(In);
4173 if (SDValue Splat32 = SplatSrc32BV->getSplatValue()) {
4174 SDValue SplatSrc16 = stripBitcast(Splat32);
4176 if (SDValue
Splat = SplatSrc16BV->getSplatValue()) {
4177 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
4178 std::optional<APInt> RawValue;
4180 RawValue =
C->getValueAPF().bitcastToAPInt();
4182 RawValue =
C->getAPIntValue();
4184 if (RawValue.has_value()) {
4185 EVT VT =
In.getValueType().getScalarType();
4191 if (
TII->isInlineConstant(FloatVal)) {
4192 Src =
CurDAG->getTargetConstant(RawValue.value(), SDLoc(In),
4197 if (
TII->isInlineConstant(RawValue.value())) {
4198 Src =
CurDAG->getTargetConstant(RawValue.value(), SDLoc(In),
4211 if (
CurDAG->isConstantIntBuildVectorOrConstantInt(SplatSrc32)) {
4216 int64_t LoImm = Lo32->getAPIntValue().getSExtValue();
4217 int64_t HiImm = Hi32->getAPIntValue().getSExtValue();
4218 int64_t Imm64I = (HiImm << 32) + LoImm;
4220 if (!isInlineImmediate(APInt(64, Imm64I)))
4223 }
else if (Imm64I != Imm64)
4227 Src =
CurDAG->getTargetConstant(Imm64, SDLoc(In), MVT::i64);
4234bool AMDGPUDAGToDAGISel::SelectSWMMACIndex8(
SDValue In,
SDValue &Src,
4240 const llvm::SDValue &ShiftSrc =
In.getOperand(0);
4249 IndexKey =
CurDAG->getTargetConstant(
Key, SDLoc(In), MVT::i32);
4253bool AMDGPUDAGToDAGISel::SelectSWMMACIndex16(
SDValue In,
SDValue &Src,
4259 const llvm::SDValue &ShiftSrc =
In.getOperand(0);
4268 IndexKey =
CurDAG->getTargetConstant(
Key, SDLoc(In), MVT::i32);
4272bool AMDGPUDAGToDAGISel::SelectSWMMACIndex32(
SDValue In,
SDValue &Src,
4280 const SDValue &ExtendSrc =
In.getOperand(0);
4284 const SDValue &CastSrc =
In.getOperand(0);
4288 if (Zero &&
Zero->getZExtValue() == 0)
4294 const SDValue &ExtractVecEltSrc = InI32.
getOperand(0);
4299 Src = ExtractVecEltSrc;
4303 IndexKey =
CurDAG->getTargetConstant(
Key, SDLoc(In), MVT::i32);
4307bool AMDGPUDAGToDAGISel::SelectVOP3OpSel(
SDValue In,
SDValue &Src,
4311 if (!Subtarget->useRealTrue16Insts() &&
In.getValueSizeInBits() == 16 &&
4314 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4318bool AMDGPUDAGToDAGISel::SelectVOP3OpSelMods(
SDValue In,
SDValue &Src,
4321 if (!SelectVOP3ModsImpl(In, Src, Mods,
true,
4325 if (!Subtarget->useRealTrue16Insts() &&
In.getValueSizeInBits() == 16 &&
4329 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4342 Op =
Op.getOperand(0);
4344 IsExtractHigh =
false;
4347 if (!Low16 || !Low16->isZero())
4349 Op = stripBitcast(
Op.getOperand(1));
4350 if (
Op.getValueType() != MVT::bf16)
4355 if (
Op.getValueType() != MVT::i32)
4360 if (Mask->getZExtValue() == 0xffff0000) {
4361 IsExtractHigh =
true;
4362 return Op.getOperand(0);
4371 return Op.getOperand(0);
4380bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixModsImpl(
SDValue In,
SDValue &Src,
4384 SelectVOP3ModsImpl(In, Src, Mods);
4386 bool IsExtractHigh =
false;
4388 Src.getOperand(0).getValueType() == VT) {
4389 Src = Src.getOperand(0);
4390 }
else if (VT == MVT::bf16) {
4398 if (Src.getValueType() != VT &&
4399 (VT != MVT::bf16 || Src.getValueType() != MVT::i32))
4402 Src = stripBitcast(Src);
4408 SelectVOP3ModsImpl(Src, Src, ModsTmp);
4423 if (Src.getValueSizeInBits() == 16) {
4432 Src.getOperand(0).getValueType() == MVT::i32) {
4433 Src = Src.getOperand(0);
4437 if (Subtarget->useRealTrue16Insts())
4439 Src = createVOP3PSrc32FromLo16(Src, In,
CurDAG, Subtarget);
4440 }
else if (IsExtractHigh)
4446bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixModsExt(
SDValue In,
SDValue &Src,
4449 if (!SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::f16))
4451 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4455bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixMods(
SDValue In,
SDValue &Src,
4458 SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::f16);
4459 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4463bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixModsExtNeg(
SDValue In,
SDValue &Src,
4466 if (!SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::f16))
4473bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixModsNeg(
SDValue In,
SDValue &Src,
4476 SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::f16);
4482bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixBF16ModsExt(
SDValue In,
SDValue &Src,
4485 if (!SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::bf16))
4487 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4491bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixBF16Mods(
SDValue In,
SDValue &Src,
4494 SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::bf16);
4495 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4499bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixBF16ModsExtNeg(
4502 if (!SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::bf16))
4509bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixBF16ModsNeg(
SDValue In,
SDValue &Src,
4512 SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::bf16);
4522 unsigned NumOpcodes = 0;
4535 const uint8_t SrcBits[3] = { 0xf0, 0xcc, 0xaa };
4538 if (
C->isAllOnes()) {
4548 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4562 if (Src.size() == 3) {
4568 if (
C->isAllOnes()) {
4570 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4571 if (Src[
I] ==
LHS) {
4583 Bits = SrcBits[Src.size()];
4588 switch (In.getOpcode()) {
4596 if (!getOperandBits(
LHS, LHSBits) ||
4597 !getOperandBits(
RHS, RHSBits)) {
4598 Src = std::move(Backup);
4599 return std::make_pair(0, 0);
4620 uint8_t LHSBitsOrig = LHSBits;
4621 uint8_t RHSBitsOrig = RHSBits;
4625 NumOpcodes += LHSOp.first;
4626 LHSBits = LHSOp.second;
4633 NumOpcodes += RHSOp.first;
4634 RHSBits = RHSOp.second;
4638 auto dependsOnSlot = [](
uint8_t TT,
int Slot) ->
bool {
4639 if (Slot < 0 || Slot > 2)
4641 const uint8_t Masks[3] = {0x0f, 0x33, 0x55};
4642 const int Shifts[3] = {4, 2, 1};
4643 return ((TT ^ (TT >> Shifts[Slot])) & Masks[Slot]) != 0;
4649 const uint8_t SrcBitsConst[3] = {0xf0, 0xcc, 0xaa};
4656 NegatedInner =
Op.getOperand(0);
4657 for (
int I = 0;
I < (int)S.size();
I++) {
4658 if (Bits == SrcBitsConst[
I] && S[
I] ==
Op)
4660 if (IsNegationOp && Bits == (
uint8_t)~SrcBitsConst[
I] &&
4661 S[
I] == NegatedInner)
4672 for (
int I = 0;
I < (int)SrcAfterLHS.
size() &&
I < 3;
I++) {
4673 if (
I < (
int)Src.size() && Src[
I] != SrcAfterLHS[
I] &&
4674 dependsOnSlot(LHSBits,
I)) {
4683 if (!Stale && !RHSOp.first) {
4684 int Slot = findSlot(RHSBitsOrig,
RHS, SrcBeforeRecurse);
4686 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4692 if (!Stale && !LHSOp.first) {
4693 int Slot = findSlot(LHSBitsOrig,
LHS, SrcBeforeRecurse);
4695 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4700 Src = std::move(SrcBeforeRecurse);
4701 LHSBits = LHSBitsOrig;
4702 RHSBits = RHSBitsOrig;
4708 return std::make_pair(0, 0);
4712 switch (In.getOpcode()) {
4714 TTbl = LHSBits & RHSBits;
4717 TTbl = LHSBits | RHSBits;
4720 TTbl = LHSBits ^ RHSBits;
4726 return std::make_pair(NumOpcodes + 1, TTbl);
4733 unsigned NumOpcodes;
4735 std::tie(NumOpcodes, TTbl) =
BitOp3_Op(In, Src);
4739 if (NumOpcodes < 2 || Src.empty())
4745 if (NumOpcodes < 4 && !In->isDivergent())
4748 if (NumOpcodes == 2 &&
In.getValueType() == MVT::i32) {
4753 (
In.getOperand(0).getOpcode() ==
In.getOpcode() ||
4754 In.getOperand(1).getOpcode() ==
In.getOpcode()))
4768 while (Src.size() < 3)
4769 Src.push_back(Src[0]);
4775 Tbl =
CurDAG->getTargetConstant(TTbl, SDLoc(In), MVT::i32);
4781 return CurDAG->getPOISON(MVT::i32);
4784 return CurDAG->getUNDEF(MVT::i32);
4788 return CurDAG->getConstant(
C->getZExtValue() << 16, SL, MVT::i32);
4793 return CurDAG->getConstant(
4794 C->getValueAPF().bitcastToAPInt().getZExtValue() << 16, SL, MVT::i32);
4804bool AMDGPUDAGToDAGISel::isVGPRImm(
const SDNode *
N)
const {
4805 assert(
CurDAG->getTarget().getTargetTriple().isAMDGCN());
4807 const SIRegisterInfo *SIRI = Subtarget->getRegisterInfo();
4808 const SIInstrInfo *SII = Subtarget->getInstrInfo();
4811 bool AllUsesAcceptSReg =
true;
4813 Limit < 10 && U !=
E; ++U, ++Limit) {
4815 getOperandRegClass(
U->getUser(),
U->getOperandNo());
4823 if (RC != &AMDGPU::VS_32RegClass && RC != &AMDGPU::VS_64RegClass &&
4824 RC != &AMDGPU::VS_64_Align2RegClass) {
4825 AllUsesAcceptSReg =
false;
4826 SDNode *
User =
U->getUser();
4827 if (
User->isMachineOpcode()) {
4828 unsigned Opc =
User->getMachineOpcode();
4829 const MCInstrDesc &
Desc = SII->get(
Opc);
4830 if (
Desc.isCommutable()) {
4831 unsigned OpIdx =
Desc.getNumDefs() +
U->getOperandNo();
4834 unsigned CommutedOpNo = CommuteIdx1 -
Desc.getNumDefs();
4836 getOperandRegClass(
U->getUser(), CommutedOpNo);
4837 if (CommutedRC == &AMDGPU::VS_32RegClass ||
4838 CommutedRC == &AMDGPU::VS_64RegClass ||
4839 CommutedRC == &AMDGPU::VS_64_Align2RegClass)
4840 AllUsesAcceptSReg =
true;
4848 if (!AllUsesAcceptSReg)
4852 return !AllUsesAcceptSReg && (Limit < 10);
4858 bool IsModified =
false;
4864 while (Position !=
CurDAG->allnodes_end()) {
4871 if (ResNode !=
Node) {
4877 CurDAG->RemoveDeadNodes();
4878 }
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 widenRegionLoad16(SDNode *N) const
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.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
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.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
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.
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.
LLVM_ABI StringRef getString() const
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.
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.
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
static const unsigned CommuteAnyOperandIndex
Primary interface to the complete machine description for the target machine.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ 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 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)
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.
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ 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,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
@ 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...
LLVM_ABI LLT getLLTForMVT(MVT Ty)
Get a rough equivalent of an LLT for a given MVT.
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.
EVT changeTypeToInteger() const
Return the type converted to an equivalently sized integer or vector with integer element type.
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 isVector() const
Return true if this is a vector value type.
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.