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) {
74 if (Result.getValueSizeInBits() != 32)
95 if (
Lo->isDivergent()) {
97 SL,
Lo.getValueType()),
105 Src.getValueType(),
Ops),
123 SDValue Idx = In.getOperand(1);
125 return In.getOperand(0);
129 SDValue Src = In.getOperand(0);
130 if (Src.getValueType().getSizeInBits() == 32)
131 return stripBitcast(Src);
141 assert(Elts.
size() == SubRegClass.
size() &&
"array size mismatch");
142 unsigned NumElts = Elts.
size();
145 for (
unsigned i = 0; i < NumElts; ++i) {
146 Ops[2 * i + 1] = Elts[i];
156 "AMDGPU DAG->DAG Pattern Instruction Selection",
false,
160#ifdef EXPENSIVE_CHECKS
165 "AMDGPU DAG->DAG Pattern Instruction Selection",
false,
186bool AMDGPUDAGToDAGISel::fp16SrcZerosHighBits(
unsigned Opc)
const {
222 case AMDGPUISD::FRACT:
223 case AMDGPUISD::CLAMP:
224 case AMDGPUISD::COS_HW:
225 case AMDGPUISD::SIN_HW:
226 case AMDGPUISD::FMIN3:
227 case AMDGPUISD::FMAX3:
228 case AMDGPUISD::FMED3:
229 case AMDGPUISD::FMAD_FTZ:
232 case AMDGPUISD::RCP_IFLAG:
242 case AMDGPUISD::DIV_FIXUP:
252#ifdef EXPENSIVE_CHECKS
256 assert(L->isLCSSAForm(DT));
264#ifdef EXPENSIVE_CHECKS
272 assert(Subtarget->d16PreservesUnusedBits());
273 MVT VT =
N->getValueType(0).getSimpleVT();
274 if (VT != MVT::v2i16 && VT != MVT::v2f16)
296 unsigned LoadOp = AMDGPUISD::LOAD_D16_HI;
299 AMDGPUISD::LOAD_D16_HI_I8 : AMDGPUISD::LOAD_D16_HI_U8;
305 CurDAG->getMemIntrinsicNode(LoadOp,
SDLoc(LdHi), VTList,
318 if (LdLo &&
Lo.hasOneUse()) {
324 unsigned LoadOp = AMDGPUISD::LOAD_D16_LO;
327 AMDGPUISD::LOAD_D16_LO_I8 : AMDGPUISD::LOAD_D16_LO_U8;
339 CurDAG->getMemIntrinsicNode(LoadOp,
SDLoc(LdLo), VTList,
353 EVT VT =
N->getValueType(0);
367 Ld ?
CurDAG->getExtLoad(ExtType, SL, MVT::i32, Mem->getChain(),
368 Mem->getBasePtr(), MemVT, Mem->getMemOperand())
369 :
CurDAG->getAtomicLoad(ExtType, SL, MemVT, MVT::i32, Mem->getChain(),
370 Mem->getBasePtr(), Mem->getMemOperand());
381 bool MadeChange =
false;
382 while (Position !=
CurDAG->allnodes_begin()) {
387 switch (
N->getOpcode()) {
390 if (Subtarget->d16PreservesUnusedBits())
395 if (Subtarget->useRealTrue16Insts())
404 CurDAG->RemoveDeadNodes();
410bool AMDGPUDAGToDAGISel::isInlineImmediate(
const SDNode *
N)
const {
416 return TII->isInlineConstant(
C->getAPIntValue());
419 return TII->isInlineConstant(
C->getValueAPF());
429 unsigned OpNo)
const {
430 if (!
N->isMachineOpcode()) {
433 if (
Reg.isVirtual()) {
438 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
439 return TRI->getPhysRegBaseClass(
Reg);
445 switch (
N->getMachineOpcode()) {
447 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
448 const MCInstrDesc &
Desc =
TII->get(
N->getMachineOpcode());
449 unsigned OpIdx =
Desc.getNumDefs() + OpNo;
450 if (OpIdx >=
Desc.getNumOperands())
453 int16_t RegClass =
TII->getOpRegClassID(
Desc.operands()[OpIdx]);
457 return Subtarget->getRegisterInfo()->getRegClass(RegClass);
459 case AMDGPU::REG_SEQUENCE: {
460 unsigned RCID =
N->getConstantOperandVal(0);
462 Subtarget->getRegisterInfo()->getRegClass(RCID);
464 SDValue SubRegOp =
N->getOperand(OpNo + 1);
466 return Subtarget->getRegisterInfo()->getSubClassWithSubReg(SuperRC,
475 Ops.push_back(NewChain);
476 for (
unsigned i = 1, e =
N->getNumOperands(); i != e; ++i)
477 Ops.push_back(
N->getOperand(i));
480 return CurDAG->MorphNodeTo(
N,
N->getOpcode(),
N->getVTList(),
Ops);
487 assert(
N->getOperand(0).getValueType() == MVT::Other &&
"Expected chain");
490 return glueCopyToOp(
N,
M0,
M0.getValue(1));
493SDNode *AMDGPUDAGToDAGISel::glueCopyToM0LDSInit(
SDNode *
N)
const {
496 if (Subtarget->ldsRequiresM0Init())
498 N,
CurDAG->getSignedTargetConstant(-1, SDLoc(
N), MVT::i32));
501 unsigned Value =
MF.getInfo<SIMachineFunctionInfo>()->getGDSSize();
503 glueCopyToM0(
N,
CurDAG->getTargetConstant(
Value, SDLoc(
N), MVT::i32));
510 SDNode *
Lo =
CurDAG->getMachineNode(
511 AMDGPU::S_MOV_B32,
DL, MVT::i32,
513 SDNode *
Hi =
CurDAG->getMachineNode(
514 AMDGPU::S_MOV_B32,
DL, MVT::i32,
516 const SDValue
Ops[] = {
517 CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID,
DL, MVT::i32),
518 SDValue(
Lo, 0),
CurDAG->getTargetConstant(AMDGPU::sub0,
DL, MVT::i32),
519 SDValue(
Hi, 0),
CurDAG->getTargetConstant(AMDGPU::sub1,
DL, MVT::i32)};
521 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL, VT,
Ops);
524SDNode *AMDGPUDAGToDAGISel::packConstantV2I16(
const SDNode *
N,
529 uint32_t LHSVal, RHSVal;
533 uint32_t
K = (LHSVal & 0xffff) | (RHSVal << 16);
535 isVGPRImm(
N) ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32, SL,
543 EVT VT =
N->getValueType(0);
547 SDValue RegClass =
CurDAG->getTargetConstant(RegClassID,
DL, MVT::i32);
549 if (NumVectorElts == 1) {
550 CurDAG->SelectNodeTo(
N, AMDGPU::COPY_TO_REGCLASS, EltVT,
N->getOperand(0),
555 bool IsGCN =
CurDAG->getSubtarget().getTargetTriple().isAMDGCN();
556 if (IsGCN && Subtarget->has64BitLiterals() && VT.
getSizeInBits() == 64 &&
559 bool AllConst =
true;
561 for (
unsigned I = 0;
I < NumVectorElts; ++
I) {
569 Val = CF->getValueAPF().bitcastToAPInt().getZExtValue();
572 C |= Val << (EltSize *
I);
577 CurDAG->getMachineNode(AMDGPU::S_MOV_B64_IMM_PSEUDO,
DL, VT, CV);
578 CurDAG->SelectNodeTo(
N, AMDGPU::COPY_TO_REGCLASS, VT,
SDValue(Copy, 0),
584 assert(NumVectorElts <= 32 &&
"Vectors with more than 32 elements not "
591 RegSeqArgs[0] =
CurDAG->getTargetConstant(RegClassID,
DL, MVT::i32);
592 bool IsRegSeq =
true;
593 unsigned NOps =
N->getNumOperands();
595 assert(IsGCN || EltSizeInRegs == 1);
596 for (
unsigned i = 0; i < NOps; i++) {
603 i * EltSizeInRegs, EltSizeInRegs)
605 RegSeqArgs[1 + (2 * i)] =
N->getOperand(i);
606 RegSeqArgs[1 + (2 * i) + 1] =
CurDAG->getTargetConstant(
Sub,
DL, MVT::i32);
608 if (NOps != NumVectorElts) {
613 for (
unsigned i = NOps; i < NumVectorElts; ++i) {
615 i * EltSizeInRegs, EltSizeInRegs)
617 RegSeqArgs[1 + (2 * i)] =
SDValue(ImpDef, 0);
618 RegSeqArgs[1 + (2 * i) + 1] =
625 CurDAG->SelectNodeTo(
N, AMDGPU::REG_SEQUENCE,
N->getVTList(), RegSeqArgs);
629 EVT VT =
N->getValueType(0);
633 if (!Subtarget->hasPkMovB32() || !EltVT.
bitsEq(MVT::i32) ||
641 SDValue Src0 = SVN->getOperand(0);
642 SDValue Src1 = SVN->getOperand(1);
646 assert(Src0.getValueType().getVectorNumElements() == 2 && Mask.size() == 2 &&
647 Mask[0] < 4 && Mask[1] < 4);
649 SDValue VSrc0 = Mask[0] < 2 ? Src0 : Src1;
650 SDValue VSrc1 = Mask[1] < 2 ? Src0 : Src1;
651 unsigned Src0SubReg = Mask[0] & 1 ? AMDGPU::sub1 : AMDGPU::sub0;
652 unsigned Src1SubReg = Mask[1] & 1 ? AMDGPU::sub1 : AMDGPU::sub0;
655 Src0SubReg = Src1SubReg;
657 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, VT);
662 Src1SubReg = Src0SubReg;
664 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, VT);
674 if (
N->isDivergent() && Src0SubReg == AMDGPU::sub1 &&
675 Src1SubReg == AMDGPU::sub0) {
691 SDValue Src0OpSelVal =
CurDAG->getTargetConstant(Src0OpSel,
DL, MVT::i32);
692 SDValue Src1OpSelVal =
CurDAG->getTargetConstant(Src1OpSel,
DL, MVT::i32);
695 CurDAG->SelectNodeTo(
N, AMDGPU::V_PK_MOV_B32,
N->getVTList(),
696 {Src0OpSelVal, VSrc0, Src1OpSelVal, VSrc1,
706 CurDAG->getTargetExtractSubreg(Src0SubReg,
DL, EltVT, VSrc0);
708 CurDAG->getTargetExtractSubreg(Src1SubReg,
DL, EltVT, VSrc1);
711 CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID,
DL, MVT::i32),
712 ResultElt0,
CurDAG->getTargetConstant(AMDGPU::sub0,
DL, MVT::i32),
713 ResultElt1,
CurDAG->getTargetConstant(AMDGPU::sub1,
DL, MVT::i32)};
714 CurDAG->SelectNodeTo(
N, TargetOpcode::REG_SEQUENCE, VT,
Ops);
718 unsigned int Opc =
N->getOpcode();
719 if (
N->isMachineOpcode()) {
727 N = glueCopyToM0LDSInit(
N);
737 if (
N->getValueType(0) == MVT::i64) {
738 SelectAddcSubbI64(
N);
742 if (
N->getValueType(0) != MVT::i32)
749 if (
N->getValueType(0) == MVT::i64) {
750 SelectAddcSubbI64(
N);
754 SelectUADDO_USUBO(
N);
757 case AMDGPUISD::FMUL_W_CHAIN: {
758 SelectFMUL_W_CHAIN(
N);
761 case AMDGPUISD::FMA_W_CHAIN: {
762 SelectFMA_W_CHAIN(
N);
768 EVT VT =
N->getValueType(0);
786 N->isDivergent() ?
TRI->getDefaultVectorSuperClassForBitWidth(VecInBits)
798 if (
N->getValueType(0) == MVT::i128) {
799 RC =
CurDAG->getTargetConstant(AMDGPU::SGPR_128RegClassID,
DL, MVT::i32);
800 SubReg0 =
CurDAG->getTargetConstant(AMDGPU::sub0_sub1,
DL, MVT::i32);
801 SubReg1 =
CurDAG->getTargetConstant(AMDGPU::sub2_sub3,
DL, MVT::i32);
802 }
else if (
N->getValueType(0) == MVT::i64) {
803 RC =
CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID,
DL, MVT::i32);
804 SubReg0 =
CurDAG->getTargetConstant(AMDGPU::sub0,
DL, MVT::i32);
805 SubReg1 =
CurDAG->getTargetConstant(AMDGPU::sub1,
DL, MVT::i32);
809 const SDValue Ops[] = { RC,
N->getOperand(0), SubReg0,
810 N->getOperand(1), SubReg1 };
812 N->getValueType(0),
Ops));
818 if (
N->getValueType(0).getSizeInBits() != 64 || isInlineImmediate(
N) ||
819 Subtarget->has64BitLiterals())
824 Imm =
FP->getValueAPF().bitcastToAPInt().getZExtValue();
829 Imm =
C->getZExtValue();
838 case AMDGPUISD::BFE_I32:
839 case AMDGPUISD::BFE_U32: {
865 case AMDGPUISD::DIV_SCALE: {
876 return SelectMUL_LOHI(
N);
887 if (
N->getValueType(0) != MVT::i32)
898 case AMDGPUISD::CVT_PKRTZ_F16_F32:
899 case AMDGPUISD::CVT_PKNORM_I16_F32:
900 case AMDGPUISD::CVT_PKNORM_U16_F32:
901 case AMDGPUISD::CVT_PK_U16_U32:
902 case AMDGPUISD::CVT_PK_I16_I32: {
904 if (
N->getValueType(0) == MVT::i32) {
905 MVT NewVT =
Opc == AMDGPUISD::CVT_PKRTZ_F16_F32 ? MVT::v2f16 : MVT::v2i16;
907 { N->getOperand(0), N->getOperand(1) });
915 SelectINTRINSIC_W_CHAIN(
N);
919 SelectINTRINSIC_WO_CHAIN(
N);
923 SelectINTRINSIC_VOID(
N);
927 SelectWAVE_ADDRESS(
N);
931 SelectSTACKRESTORE(
N);
935 SelectWRITE_REGISTER(
N);
944 if (!Subtarget->hasSDWA())
954 return RHS->getZExtValue() == 0xFF || RHS->getZExtValue() == 0xFFFF;
958 return (RHS->getZExtValue() % 8) == 0;
963bool AMDGPUDAGToDAGISel::isUniformBr(
const SDNode *
N)
const {
966 return Term->getMetadata(
"amdgpu.uniform") ||
967 Term->getMetadata(
"structurizecfg.uniform");
970bool AMDGPUDAGToDAGISel::isUnneededShiftMask(
const SDNode *
N,
971 unsigned ShAmtBits)
const {
974 const APInt &
RHS =
N->getConstantOperandAPInt(1);
975 if (
RHS.countr_one() >= ShAmtBits)
1005 N1 =
Lo.getOperand(1);
1015 if (
CurDAG->isBaseWithConstantOffset(Addr)) {
1030 return "AMDGPU DAG->DAG Pattern Instruction Selection";
1046#ifdef EXPENSIVE_CHECKS
1049 for (
auto &L : LI.getLoopsInPreorder())
1050 assert(L->isLCSSAForm(DT) &&
"Loop is not in LCSSA form!");
1072 }
else if ((Addr.
getOpcode() == AMDGPUISD::DWORDADDR) &&
1074 Base =
CurDAG->getRegister(R600::INDIRECT_BASE_ADDR, MVT::i32);
1088SDValue AMDGPUDAGToDAGISel::getMaterializedScalarImm32(int64_t Val,
1090 SDNode *Mov =
CurDAG->getMachineNode(
1091 AMDGPU::S_MOV_B32,
DL, MVT::i32,
1092 CurDAG->getTargetConstant(Val,
DL, MVT::i32));
1093 return SDValue(Mov, 0);
1096void AMDGPUDAGToDAGISel::SelectAddcSubb(
SDNode *
N) {
1097 SDValue
LHS =
N->getOperand(0);
1098 SDValue
RHS =
N->getOperand(1);
1099 SDValue CI =
N->getOperand(2);
1101 if (
N->isDivergent()) {
1103 : AMDGPU::V_SUBB_U32_e64;
1105 N,
Opc,
N->getVTList(),
1107 CurDAG->getTargetConstant(0, {}, MVT::i1) });
1110 : AMDGPU::S_SUB_CO_PSEUDO;
1111 CurDAG->SelectNodeTo(
N,
Opc,
N->getVTList(), {LHS, RHS, CI});
1115void AMDGPUDAGToDAGISel::SelectAddcSubbI64(
SDNode *
N) {
1117 SDValue
LHS =
N->getOperand(0);
1118 SDValue
RHS =
N->getOperand(1);
1120 unsigned Opcode =
N->getOpcode();
1124 SDValue Sub0 =
CurDAG->getTargetConstant(AMDGPU::sub0,
DL, MVT::i32);
1125 SDValue Sub1 =
CurDAG->getTargetConstant(AMDGPU::sub1,
DL, MVT::i32);
1127 SDNode *Lo0 =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
DL,
1128 MVT::i32,
LHS, Sub0);
1129 SDNode *Hi0 =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
DL,
1130 MVT::i32,
LHS, Sub1);
1132 SDNode *Lo1 =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
DL,
1133 MVT::i32,
RHS, Sub0);
1134 SDNode *Hi1 =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
DL,
1135 MVT::i32,
RHS, Sub1);
1137 SDVTList VTList =
CurDAG->getVTList(MVT::i32,
N->getValueType(1));
1139 static const unsigned NoCarryOpcMap[2][2] = {
1140 {AMDGPU::S_USUBO_PSEUDO, AMDGPU::S_UADDO_PSEUDO},
1141 {AMDGPU::V_SUB_CO_U32_e64, AMDGPU::V_ADD_CO_U32_e64}};
1142 static const unsigned CarryOpcMap[2][2] = {
1143 {AMDGPU::S_SUB_CO_PSEUDO, AMDGPU::S_ADD_CO_PSEUDO},
1144 {AMDGPU::V_SUBB_U32_e64, AMDGPU::V_ADDC_U32_e64}};
1146 bool IsVALU =
N->isDivergent();
1148 unsigned NoCarryOpc = NoCarryOpcMap[IsVALU][IsAdd];
1149 unsigned CarryOpc = CarryOpcMap[IsVALU][IsAdd];
1150 SDValue Clamp =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
1153 if (!ConsumeCarry) {
1155 SDValue
Args[] = {SDValue(Lo0, 0), SDValue(Lo1, 0), Clamp};
1156 AddLo =
CurDAG->getMachineNode(NoCarryOpc,
DL, VTList, Args);
1158 SDValue
Args[] = {SDValue(Lo0, 0), SDValue(Lo1, 0)};
1159 AddLo =
CurDAG->getMachineNode(NoCarryOpc,
DL, VTList, Args);
1163 SDValue
Args[] = {SDValue(Lo0, 0), SDValue(Lo1, 0),
N->getOperand(2),
1165 AddLo =
CurDAG->getMachineNode(CarryOpc,
DL, VTList, Args);
1167 SDValue
Args[] = {SDValue(Lo0, 0), SDValue(Lo1, 0),
N->getOperand(2)};
1168 AddLo =
CurDAG->getMachineNode(CarryOpc,
DL, VTList, Args);
1174 SDValue
Args[] = {SDValue(Hi0, 0), SDValue(Hi1, 0), SDValue(AddLo, 1),
1176 AddHi =
CurDAG->getMachineNode(CarryOpc,
DL, VTList, Args);
1178 SDValue
Args[] = {SDValue(Hi0, 0), SDValue(Hi1, 0), SDValue(AddLo, 1)};
1179 AddHi =
CurDAG->getMachineNode(CarryOpc,
DL, VTList, Args);
1182 unsigned RC = IsVALU ? AMDGPU::VReg_64RegClassID : AMDGPU::SReg_64RegClassID;
1183 SDValue RegSequenceArgs[] = {
CurDAG->getTargetConstant(RC,
DL, MVT::i32),
1184 SDValue(AddLo, 0), Sub0, SDValue(AddHi, 0),
1187 MVT::i64, RegSequenceArgs);
1193void AMDGPUDAGToDAGISel::SelectUADDO_USUBO(
SDNode *
N) {
1198 bool IsVALU =
N->isDivergent();
1200 for (SDNode::user_iterator UI =
N->user_begin(),
E =
N->user_end(); UI !=
E;
1202 if (UI.getUse().getResNo() == 1) {
1203 if (UI->isMachineOpcode()) {
1204 if (UI->getMachineOpcode() !=
1205 (IsAdd ? AMDGPU::S_ADD_CO_PSEUDO : AMDGPU::S_SUB_CO_PSEUDO)) {
1218 unsigned Opc = IsAdd ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_SUB_CO_U32_e64;
1221 N,
Opc,
N->getVTList(),
1222 {N->getOperand(0), N->getOperand(1),
1223 CurDAG->getTargetConstant(0, {}, MVT::i1) });
1225 unsigned Opc = IsAdd ? AMDGPU::S_UADDO_PSEUDO : AMDGPU::S_USUBO_PSEUDO;
1227 CurDAG->SelectNodeTo(
N,
Opc,
N->getVTList(),
1228 {N->getOperand(0), N->getOperand(1)});
1232void AMDGPUDAGToDAGISel::SelectFMA_W_CHAIN(
SDNode *
N) {
1236 SelectVOP3Mods0(
N->getOperand(1),
Ops[1],
Ops[0],
Ops[6],
Ops[7]);
1237 SelectVOP3Mods(
N->getOperand(2),
Ops[3],
Ops[2]);
1238 SelectVOP3Mods(
N->getOperand(3),
Ops[5],
Ops[4]);
1239 Ops[8] =
N->getOperand(0);
1240 Ops[9] =
N->getOperand(4);
1244 bool UseFMAC = Subtarget->hasDLInsts() &&
1248 unsigned Opcode = UseFMAC ? AMDGPU::V_FMAC_F32_e64 : AMDGPU::V_FMA_F32_e64;
1249 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(),
Ops);
1252void AMDGPUDAGToDAGISel::SelectFMUL_W_CHAIN(
SDNode *
N) {
1256 SelectVOP3Mods0(
N->getOperand(1),
Ops[1],
Ops[0],
Ops[4],
Ops[5]);
1257 SelectVOP3Mods(
N->getOperand(2),
Ops[3],
Ops[2]);
1258 Ops[6] =
N->getOperand(0);
1259 Ops[7] =
N->getOperand(3);
1261 CurDAG->SelectNodeTo(
N, AMDGPU::V_MUL_F32_e64,
N->getVTList(),
Ops);
1266void AMDGPUDAGToDAGISel::SelectDIV_SCALE(
SDNode *
N) {
1267 EVT VT =
N->getValueType(0);
1269 assert(VT == MVT::f32 || VT == MVT::f64);
1272 = (VT == MVT::f64) ? AMDGPU::V_DIV_SCALE_F64_e64 : AMDGPU::V_DIV_SCALE_F32_e64;
1277 SelectVOP3BMods0(
N->getOperand(0),
Ops[1],
Ops[0],
Ops[6],
Ops[7]);
1278 SelectVOP3BMods(
N->getOperand(1),
Ops[3],
Ops[2]);
1279 SelectVOP3BMods(
N->getOperand(2),
Ops[5],
Ops[4]);
1285void AMDGPUDAGToDAGISel::SelectMAD_64_32(
SDNode *
N) {
1289 bool UseNoCarry = Subtarget->hasMadNC64_32Insts() && !
N->hasAnyUseOfValue(1);
1290 if (Subtarget->hasMADIntraFwdBug())
1291 Opc =
Signed ? AMDGPU::V_MAD_I64_I32_gfx11_e64
1292 : AMDGPU::V_MAD_U64_U32_gfx11_e64;
1293 else if (UseNoCarry)
1294 Opc =
Signed ? AMDGPU::V_MAD_NC_I64_I32_e64 : AMDGPU::V_MAD_NC_U64_U32_e64;
1296 Opc =
Signed ? AMDGPU::V_MAD_I64_I32_e64 : AMDGPU::V_MAD_U64_U32_e64;
1298 SDValue Clamp =
CurDAG->getTargetConstant(0, SL, MVT::i1);
1299 SDValue
Ops[] = {
N->getOperand(0),
N->getOperand(1),
N->getOperand(2),
1303 MachineSDNode *Mad =
CurDAG->getMachineNode(
Opc, SL, MVT::i64,
Ops);
1314void AMDGPUDAGToDAGISel::SelectMUL_LOHI(
SDNode *
N) {
1319 if (Subtarget->hasMadNC64_32Insts()) {
1320 VTList =
CurDAG->getVTList(MVT::i64);
1321 Opc =
Signed ? AMDGPU::V_MAD_NC_I64_I32_e64 : AMDGPU::V_MAD_NC_U64_U32_e64;
1323 VTList =
CurDAG->getVTList(MVT::i64, MVT::i1);
1324 if (Subtarget->hasMADIntraFwdBug()) {
1325 Opc =
Signed ? AMDGPU::V_MAD_I64_I32_gfx11_e64
1326 : AMDGPU::V_MAD_U64_U32_gfx11_e64;
1328 Opc =
Signed ? AMDGPU::V_MAD_I64_I32_e64 : AMDGPU::V_MAD_U64_U32_e64;
1332 SDValue
Zero =
CurDAG->getTargetConstant(0, SL, MVT::i64);
1333 SDValue Clamp =
CurDAG->getTargetConstant(0, SL, MVT::i1);
1334 SDValue
Ops[] = {
N->getOperand(0),
N->getOperand(1),
Zero, Clamp};
1335 SDNode *Mad =
CurDAG->getMachineNode(
Opc, SL, VTList,
Ops);
1336 if (!SDValue(
N, 0).use_empty()) {
1337 SDValue Sub0 =
CurDAG->getTargetConstant(AMDGPU::sub0, SL, MVT::i32);
1338 SDNode *
Lo =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, SL,
1339 MVT::i32, SDValue(Mad, 0), Sub0);
1342 if (!SDValue(
N, 1).use_empty()) {
1343 SDValue Sub1 =
CurDAG->getTargetConstant(AMDGPU::sub1, SL, MVT::i32);
1344 SDNode *
Hi =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, SL,
1345 MVT::i32, SDValue(Mad, 0), Sub1);
1355 if (!
Base || Subtarget->hasUsableDSOffset() ||
1356 Subtarget->unsafeDSOffsetFoldingEnabled())
1367 if (
CurDAG->isBaseWithConstantOffset(Addr)) {
1380 int64_t ByteOffset =
C->getSExtValue();
1381 if (isDSOffsetLegal(SDValue(), ByteOffset)) {
1382 SDValue
Zero =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1390 if (isDSOffsetLegal(
Sub, ByteOffset)) {
1396 unsigned SubOp = AMDGPU::V_SUB_CO_U32_e32;
1397 if (Subtarget->hasAddNoCarryInsts()) {
1398 SubOp = AMDGPU::V_SUB_U32_e64;
1400 CurDAG->getTargetConstant(0, {}, MVT::i1));
1403 MachineSDNode *MachineSub =
1404 CurDAG->getMachineNode(SubOp,
DL, MVT::i32, Opnds);
1406 Base = SDValue(MachineSub, 0);
1420 if (isDSOffsetLegal(SDValue(), CAddr->getZExtValue())) {
1421 SDValue
Zero =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1422 MachineSDNode *MovZero =
CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32,
1423 DL, MVT::i32, Zero);
1424 Base = SDValue(MovZero, 0);
1425 Offset =
CurDAG->getTargetConstant(CAddr->getZExtValue(),
DL, MVT::i16);
1432 Offset =
CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i16);
1436bool AMDGPUDAGToDAGISel::isDSOffset2Legal(
SDValue Base,
unsigned Offset0,
1438 unsigned Size)
const {
1439 if (Offset0 %
Size != 0 || Offset1 %
Size != 0)
1444 if (!
Base || Subtarget->hasUsableDSOffset() ||
1445 Subtarget->unsafeDSOffsetFoldingEnabled())
1463bool AMDGPUDAGToDAGISel::isFlatScratchBaseLegal(
SDValue Addr)
const {
1469 if (Subtarget->hasSignedScratchOffsets())
1479 ConstantSDNode *ImmOp =
nullptr;
1490bool AMDGPUDAGToDAGISel::isFlatScratchBaseLegalSV(
SDValue Addr)
const {
1496 if (Subtarget->hasSignedScratchOffsets())
1506bool AMDGPUDAGToDAGISel::isFlatScratchBaseLegalSVImm(
SDValue Addr)
const {
1520 (RHSImm->getSExtValue() < 0 && RHSImm->getSExtValue() > -0x40000000)))
1523 auto LHS =
Base.getOperand(0);
1524 auto RHS =
Base.getOperand(1);
1532 return SelectDSReadWrite2(Addr,
Base, Offset0, Offset1, 4);
1538 return SelectDSReadWrite2(Addr,
Base, Offset0, Offset1, 8);
1543 unsigned Size)
const {
1546 if (
CurDAG->isBaseWithConstantOffset(Addr)) {
1551 unsigned OffsetValue1 = OffsetValue0 +
Size;
1554 if (isDSOffset2Legal(N0, OffsetValue0, OffsetValue1,
Size)) {
1556 Offset0 =
CurDAG->getTargetConstant(OffsetValue0 /
Size,
DL, MVT::i32);
1557 Offset1 =
CurDAG->getTargetConstant(OffsetValue1 /
Size,
DL, MVT::i32);
1562 if (
const ConstantSDNode *
C =
1564 unsigned OffsetValue0 =
C->getZExtValue();
1565 unsigned OffsetValue1 = OffsetValue0 +
Size;
1567 if (isDSOffset2Legal(SDValue(), OffsetValue0, OffsetValue1,
Size)) {
1569 SDValue
Zero =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1577 if (isDSOffset2Legal(
Sub, OffsetValue0, OffsetValue1,
Size)) {
1581 unsigned SubOp = AMDGPU::V_SUB_CO_U32_e32;
1582 if (Subtarget->hasAddNoCarryInsts()) {
1583 SubOp = AMDGPU::V_SUB_U32_e64;
1585 CurDAG->getTargetConstant(0, {}, MVT::i1));
1588 MachineSDNode *MachineSub =
CurDAG->getMachineNode(
1591 Base = SDValue(MachineSub, 0);
1593 CurDAG->getTargetConstant(OffsetValue0 /
Size,
DL, MVT::i32);
1595 CurDAG->getTargetConstant(OffsetValue1 /
Size,
DL, MVT::i32);
1601 unsigned OffsetValue0 = CAddr->getZExtValue();
1602 unsigned OffsetValue1 = OffsetValue0 +
Size;
1604 if (isDSOffset2Legal(SDValue(), OffsetValue0, OffsetValue1,
Size)) {
1605 SDValue
Zero =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1606 MachineSDNode *MovZero =
1607 CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32,
DL, MVT::i32, Zero);
1608 Base = SDValue(MovZero, 0);
1609 Offset0 =
CurDAG->getTargetConstant(OffsetValue0 /
Size,
DL, MVT::i32);
1610 Offset1 =
CurDAG->getTargetConstant(OffsetValue1 /
Size,
DL, MVT::i32);
1618 Offset0 =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1619 Offset1 =
CurDAG->getTargetConstant(1,
DL, MVT::i32);
1629 if (Subtarget->useFlatForGlobal())
1634 Idxen =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
1635 Offen =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
1636 Addr64 =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
1637 SOffset = Subtarget->hasRestrictedSOffset()
1638 ?
CurDAG->getRegister(AMDGPU::SGPR_NULL, MVT::i32)
1639 :
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1641 ConstantSDNode *C1 =
nullptr;
1643 if (
CurDAG->isBaseWithConstantOffset(Addr)) {
1656 Addr64 =
CurDAG->getTargetConstant(1,
DL, MVT::i1);
1662 Ptr = SDValue(buildSMovImm64(
DL, 0, MVT::v2i32), 0);
1678 Ptr = SDValue(buildSMovImm64(
DL, 0, MVT::v2i32), 0);
1680 Addr64 =
CurDAG->getTargetConstant(1,
DL, MVT::i1);
1684 VAddr =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1694 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
1704 SDValue(
CurDAG->getMachineNode(
1705 AMDGPU::S_MOV_B32,
DL, MVT::i32,
1711bool AMDGPUDAGToDAGISel::SelectMUBUFAddr64(
SDValue Addr,
SDValue &SRsrc,
1714 SDValue Ptr, Offen, Idxen, Addr64;
1718 if (!Subtarget->hasAddr64())
1721 if (!SelectMUBUF(Addr, Ptr, VAddr, SOffset,
Offset, Offen, Idxen, Addr64))
1725 if (
C->getSExtValue()) {
1738std::pair<SDValue, SDValue> AMDGPUDAGToDAGISel::foldFrameIndex(
SDValue N)
const {
1743 FI ?
CurDAG->getTargetFrameIndex(FI->getIndex(), FI->getValueType(0)) :
N;
1749 return std::pair(TFI,
CurDAG->getTargetConstant(0,
DL, MVT::i32));
1752bool AMDGPUDAGToDAGISel::SelectMUBUFScratchOffen(
SDNode *Parent,
1759 const SIMachineFunctionInfo *
Info =
MF.getInfo<SIMachineFunctionInfo>();
1761 Rsrc =
CurDAG->getRegister(
Info->getScratchRSrcReg(), MVT::v4i32);
1764 int64_t
Imm = CAddr->getSExtValue();
1765 const int64_t NullPtr =
1768 if (
Imm != NullPtr) {
1771 CurDAG->getTargetConstant(
Imm & ~MaxOffset,
DL, MVT::i32);
1772 MachineSDNode *MovHighBits =
CurDAG->getMachineNode(
1773 AMDGPU::V_MOV_B32_e32,
DL, MVT::i32, HighBits);
1774 VAddr = SDValue(MovHighBits, 0);
1776 SOffset =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1777 ImmOffset =
CurDAG->getTargetConstant(
Imm & MaxOffset,
DL, MVT::i32);
1782 if (
CurDAG->isBaseWithConstantOffset(Addr)) {
1803 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
1804 if (
TII->isLegalMUBUFImmOffset(C1) &&
1805 (!Subtarget->privateMemoryResourceIsRangeChecked() ||
1806 CurDAG->SignBitIsZero(N0))) {
1807 std::tie(VAddr, SOffset) = foldFrameIndex(N0);
1808 ImmOffset =
CurDAG->getTargetConstant(C1,
DL, MVT::i32);
1814 std::tie(VAddr, SOffset) = foldFrameIndex(Addr);
1815 ImmOffset =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1823 if (!
Reg.isPhysical())
1825 const auto *RC =
TRI.getPhysRegBaseClass(
Reg);
1826 return RC &&
TRI.isSGPRClass(RC);
1829bool AMDGPUDAGToDAGISel::SelectMUBUFScratchOffset(
SDNode *Parent,
1834 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
1835 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
1837 const SIMachineFunctionInfo *
Info =
MF.getInfo<SIMachineFunctionInfo>();
1842 SRsrc =
CurDAG->getRegister(
Info->getScratchRSrcReg(), MVT::v4i32);
1848 ConstantSDNode *CAddr;
1861 SOffset =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1866 SRsrc =
CurDAG->getRegister(
Info->getScratchRSrcReg(), MVT::v4i32);
1872bool AMDGPUDAGToDAGISel::SelectMUBUFOffset(
SDValue Addr,
SDValue &SRsrc,
1875 SDValue Ptr, VAddr, Offen, Idxen, Addr64;
1876 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
1878 if (!SelectMUBUF(Addr, Ptr, VAddr, SOffset,
Offset, Offen, Idxen, Addr64))
1897bool AMDGPUDAGToDAGISel::SelectBUFSOffset(
SDValue ByteOffsetNode,
1899 if (Subtarget->hasRestrictedSOffset() &&
isNullConstant(ByteOffsetNode)) {
1900 SOffset =
CurDAG->getRegister(AMDGPU::SGPR_NULL, MVT::i32);
1904 SOffset = ByteOffsetNode;
1922bool AMDGPUDAGToDAGISel::SelectFlatOffsetImpl(
1926 int64_t OffsetVal = 0;
1930 bool CanHaveFlatSegmentOffsetBug =
1931 Subtarget->hasFlatSegmentOffsetBug() &&
1932 FlatVariant == FlatAddrSpace::FLAT &&
1935 if (Subtarget->hasFlatInstOffsets() && !CanHaveFlatSegmentOffsetBug) {
1937 if (isBaseWithConstantOffset64(Addr, N0, N1) &&
1938 (FlatVariant != FlatAddrSpace::FlatScratch ||
1939 isFlatScratchBaseLegal(Addr))) {
1947 if (COffsetVal == 0 || FlatVariant != FlatAddrSpace::FLAT || IsInBounds) {
1948 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
1949 if (
TII->isLegalFLATOffset(COffsetVal, AS, FlatVariant)) {
1951 OffsetVal = COffsetVal;
1966 std::tie(OffsetVal, RemainderOffset) =
1967 TII->splitFlatOffset(COffsetVal, AS, FlatVariant);
1969 SDValue AddOffsetLo =
1970 getMaterializedScalarImm32(
Lo_32(RemainderOffset),
DL);
1971 SDValue Clamp =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
1977 unsigned AddOp = AMDGPU::V_ADD_CO_U32_e32;
1978 if (Subtarget->hasAddNoCarryInsts()) {
1979 AddOp = AMDGPU::V_ADD_U32_e64;
1983 SDValue(
CurDAG->getMachineNode(AddOp,
DL, MVT::i32, Opnds), 0);
1988 CurDAG->getTargetConstant(AMDGPU::sub0,
DL, MVT::i32);
1990 CurDAG->getTargetConstant(AMDGPU::sub1,
DL, MVT::i32);
1992 SDNode *N0Lo =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
1993 DL, MVT::i32, N0, Sub0);
1994 SDNode *N0Hi =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
1995 DL, MVT::i32, N0, Sub1);
1997 SDValue AddOffsetHi =
1998 getMaterializedScalarImm32(
Hi_32(RemainderOffset),
DL);
2000 SDVTList VTs =
CurDAG->getVTList(MVT::i32, MVT::i1);
2003 CurDAG->getMachineNode(AMDGPU::V_ADD_CO_U32_e64,
DL, VTs,
2004 {AddOffsetLo, SDValue(N0Lo, 0), Clamp});
2006 SDNode *Addc =
CurDAG->getMachineNode(
2007 AMDGPU::V_ADDC_U32_e64,
DL, VTs,
2008 {AddOffsetHi, SDValue(N0Hi, 0), SDValue(
Add, 1), Clamp});
2010 SDValue RegSequenceArgs[] = {
2011 CurDAG->getTargetConstant(AMDGPU::VReg_64RegClassID,
DL,
2013 SDValue(
Add, 0), Sub0, SDValue(Addc, 0), Sub1};
2015 Addr = SDValue(
CurDAG->getMachineNode(AMDGPU::REG_SEQUENCE,
DL,
2016 MVT::i64, RegSequenceArgs),
2025 Offset =
CurDAG->getSignedTargetConstant(OffsetVal, SDLoc(), MVT::i32);
2029bool AMDGPUDAGToDAGISel::SelectFlatOffset(
SDNode *
N,
SDValue Addr,
2032 return SelectFlatOffsetImpl(
N, Addr, VAddr,
Offset,
2036bool AMDGPUDAGToDAGISel::SelectGlobalOffset(
SDNode *
N,
SDValue Addr,
2039 return SelectFlatOffsetImpl(
N, Addr, VAddr,
Offset,
2043bool AMDGPUDAGToDAGISel::SelectScratchOffset(
SDNode *
N,
SDValue Addr,
2046 return SelectFlatOffsetImpl(
N, Addr, VAddr,
Offset,
2054 if (
Op.getValueType() == MVT::i32)
2069bool AMDGPUDAGToDAGISel::SelectGlobalSAddr(
SDNode *
N,
SDValue Addr,
2072 bool NeedIOffset)
const {
2074 int64_t ImmOffset = 0;
2075 ScaleOffset =
false;
2081 if (isBaseWithConstantOffset64(Addr,
LHS,
RHS)) {
2083 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
2087 FlatAddrSpace::FlatGlobal)) {
2089 ImmOffset = COffsetVal;
2090 }
else if (!
LHS->isDivergent()) {
2091 if (COffsetVal != 0) {
2096 int64_t SplitImmOffset = 0, RemainderOffset = COffsetVal;
2098 std::tie(SplitImmOffset, RemainderOffset) =
TII->splitFlatOffset(
2102 if (Subtarget->hasSignedGVSOffset() ?
isInt<32>(RemainderOffset)
2104 SDNode *VMov =
CurDAG->getMachineNode(
2105 AMDGPU::V_MOV_B32_e32, SL, MVT::i32,
2106 CurDAG->getTargetConstant(
Lo_32(RemainderOffset), SDLoc(),
2108 VOffset = SDValue(VMov, 0);
2110 Offset =
CurDAG->getSignedTargetConstant(SplitImmOffset, SDLoc(),
2121 unsigned NumLiterals =
2122 !
TII->isInlineConstant(APInt(32,
Lo_32(COffsetVal))) +
2123 !
TII->isInlineConstant(APInt(32,
Hi_32(COffsetVal)));
2124 if (Subtarget->getConstantBusLimit(AMDGPU::V_ADD_U32_e64) > NumLiterals)
2133 if (!
LHS->isDivergent()) {
2136 ScaleOffset = SelectScaleOffset(
N,
RHS, Subtarget->hasSignedGVSOffset());
2138 RHS, Subtarget->hasSignedGVSOffset(),
CurDAG)) {
2145 if (!SAddr && !
RHS->isDivergent()) {
2147 ScaleOffset = SelectScaleOffset(
N,
LHS, Subtarget->hasSignedGVSOffset());
2149 LHS, Subtarget->hasSignedGVSOffset(),
CurDAG)) {
2156 Offset =
CurDAG->getSignedTargetConstant(ImmOffset, SDLoc(), MVT::i32);
2161 if (Subtarget->hasScaleOffset() &&
2162 (Addr.
getOpcode() == (Subtarget->hasSignedGVSOffset()
2177 Offset =
CurDAG->getTargetConstant(ImmOffset, SDLoc(), MVT::i32);
2189 CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32, SDLoc(Addr), MVT::i32,
2190 CurDAG->getTargetConstant(0, SDLoc(), MVT::i32));
2191 VOffset = SDValue(VMov, 0);
2192 Offset =
CurDAG->getSignedTargetConstant(ImmOffset, SDLoc(), MVT::i32);
2196bool AMDGPUDAGToDAGISel::SelectGlobalSAddr(
SDNode *
N,
SDValue Addr,
2201 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset,
Offset, ScaleOffset))
2209bool AMDGPUDAGToDAGISel::SelectGlobalSAddrCPol(
SDNode *
N,
SDValue Addr,
2214 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset,
Offset, ScaleOffset))
2219 N->getConstantOperandVal(
N->getNumOperands() - 1) & ~AMDGPU::CPol::SCAL;
2225bool AMDGPUDAGToDAGISel::SelectGlobalSAddrCPolM0(
SDNode *
N,
SDValue Addr,
2231 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset,
Offset, ScaleOffset))
2236 N->getConstantOperandVal(
N->getNumOperands() - 2) & ~AMDGPU::CPol::SCAL;
2242bool AMDGPUDAGToDAGISel::SelectGlobalSAddrGLC(
SDNode *
N,
SDValue Addr,
2247 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset,
Offset, ScaleOffset))
2251 CPol =
CurDAG->getTargetConstant(CPolVal, SDLoc(), MVT::i32);
2255bool AMDGPUDAGToDAGISel::SelectGlobalSAddrNoIOffset(
SDNode *
N,
SDValue Addr,
2260 SDValue DummyOffset;
2261 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset, DummyOffset, ScaleOffset,
2267 N->getConstantOperandVal(
N->getNumOperands() - 1) & ~AMDGPU::CPol::SCAL;
2273bool AMDGPUDAGToDAGISel::SelectGlobalSAddrNoIOffsetM0(
SDNode *
N,
SDValue Addr,
2278 SDValue DummyOffset;
2279 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset, DummyOffset, ScaleOffset,
2300 FI->getValueType(0));
2310bool AMDGPUDAGToDAGISel::SelectScratchSAddr(
SDNode *Parent,
SDValue Addr,
2319 int64_t COffsetVal = 0;
2321 if (
CurDAG->isBaseWithConstantOffset(Addr) && isFlatScratchBaseLegal(Addr)) {
2330 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
2333 FlatAddrSpace::FlatScratch)) {
2334 int64_t SplitImmOffset, RemainderOffset;
2335 std::tie(SplitImmOffset, RemainderOffset) =
TII->splitFlatOffset(
2338 COffsetVal = SplitImmOffset;
2342 ? getMaterializedScalarImm32(
Lo_32(RemainderOffset),
DL)
2343 :
CurDAG->getSignedTargetConstant(RemainderOffset,
DL, MVT::i32);
2344 SAddr = SDValue(
CurDAG->getMachineNode(AMDGPU::S_ADD_I32,
DL, MVT::i32,
2349 Offset =
CurDAG->getSignedTargetConstant(COffsetVal,
DL, MVT::i32);
2355bool AMDGPUDAGToDAGISel::checkFlatScratchSVSSwizzleBug(
2357 if (!Subtarget->hasFlatScratchSVSSwizzleBug())
2363 KnownBits VKnown =
CurDAG->computeKnownBits(VAddr);
2370 return (VMax & 3) + (
SMax & 3) >= 4;
2373bool AMDGPUDAGToDAGISel::SelectScratchSVAddr(
SDNode *
N,
SDValue Addr,
2377 int64_t ImmOffset = 0;
2380 SDValue OrigAddr = Addr;
2381 if (isBaseWithConstantOffset64(Addr,
LHS,
RHS)) {
2383 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
2388 ImmOffset = COffsetVal;
2389 }
else if (!
LHS->isDivergent() && COffsetVal > 0) {
2393 int64_t SplitImmOffset, RemainderOffset;
2394 std::tie(SplitImmOffset, RemainderOffset) =
2399 SDNode *VMov =
CurDAG->getMachineNode(
2400 AMDGPU::V_MOV_B32_e32, SL, MVT::i32,
2401 CurDAG->getTargetConstant(RemainderOffset, SDLoc(), MVT::i32));
2402 VAddr = SDValue(VMov, 0);
2404 if (!isFlatScratchBaseLegal(Addr))
2406 if (checkFlatScratchSVSSwizzleBug(VAddr, SAddr, SplitImmOffset))
2408 Offset =
CurDAG->getTargetConstant(SplitImmOffset, SDLoc(), MVT::i32);
2409 CPol =
CurDAG->getTargetConstant(0, SDLoc(), MVT::i32);
2421 if (!
LHS->isDivergent() &&
RHS->isDivergent()) {
2424 }
else if (!
RHS->isDivergent() &&
LHS->isDivergent()) {
2431 if (OrigAddr != Addr) {
2432 if (!isFlatScratchBaseLegalSVImm(OrigAddr))
2435 if (!isFlatScratchBaseLegalSV(OrigAddr))
2439 if (checkFlatScratchSVSSwizzleBug(VAddr, SAddr, ImmOffset))
2442 Offset =
CurDAG->getSignedTargetConstant(ImmOffset, SDLoc(), MVT::i32);
2444 bool ScaleOffset = SelectScaleOffset(
N, VAddr,
true );
2453bool AMDGPUDAGToDAGISel::isSOffsetLegalWithImmOffset(
SDValue *SOffset,
2456 int64_t ImmOffset)
const {
2457 if (!IsBuffer && !Imm32Only && ImmOffset < 0 &&
2459 KnownBits SKnown =
CurDAG->computeKnownBits(*SOffset);
2471 bool IsSigned)
const {
2472 bool ScaleOffset =
false;
2473 if (!Subtarget->hasScaleOffset() || !
Offset)
2487 (IsSigned &&
Offset.getOpcode() == AMDGPUISD::MUL_I24) ||
2488 Offset.getOpcode() == AMDGPUISD::MUL_U24 ||
2489 (
Offset.isMachineOpcode() &&
2490 Offset.getMachineOpcode() ==
2491 (IsSigned ? AMDGPU::S_MUL_I64_I32_PSEUDO
2492 : AMDGPU::S_MUL_U64_U32_PSEUDO))) {
2494 ScaleOffset =
C->getZExtValue() ==
Size;
2506bool AMDGPUDAGToDAGISel::SelectSMRDOffset(
SDNode *
N,
SDValue ByteOffsetNode,
2508 bool Imm32Only,
bool IsBuffer,
2509 bool HasSOffset, int64_t ImmOffset,
2510 bool *ScaleOffset)
const {
2512 "Cannot match both soffset and offset at the same time!");
2517 *ScaleOffset = SelectScaleOffset(
N, ByteOffsetNode,
false );
2527 *SOffset = ByteOffsetNode;
2528 return isSOffsetLegalWithImmOffset(SOffset, Imm32Only, IsBuffer,
2534 return isSOffsetLegalWithImmOffset(SOffset, Imm32Only, IsBuffer,
2541 SDLoc SL(ByteOffsetNode);
2545 int64_t ByteOffset = IsBuffer ?
C->getZExtValue() :
C->getSExtValue();
2547 *Subtarget, ByteOffset, IsBuffer, HasSOffset);
2548 if (EncodedOffset &&
Offset && !Imm32Only) {
2549 *
Offset =
CurDAG->getSignedTargetConstant(*EncodedOffset, SL, MVT::i32);
2558 if (EncodedOffset &&
Offset && Imm32Only) {
2559 *
Offset =
CurDAG->getTargetConstant(*EncodedOffset, SL, MVT::i32);
2567 SDValue C32Bit =
CurDAG->getTargetConstant(ByteOffset, SL, MVT::i32);
2569 CurDAG->getMachineNode(AMDGPU::S_MOV_B32, SL, MVT::i32, C32Bit), 0);
2576SDValue AMDGPUDAGToDAGISel::Expand32BitAddress(
SDValue Addr)
const {
2584 const SIMachineFunctionInfo *
Info =
MF.getInfo<SIMachineFunctionInfo>();
2585 unsigned AddrHiVal =
Info->get32BitAddressHighBits();
2586 SDValue AddrHi =
CurDAG->getTargetConstant(AddrHiVal, SL, MVT::i32);
2588 const SDValue
Ops[] = {
2589 CurDAG->getTargetConstant(AMDGPU::SReg_64_XEXECRegClassID, SL, MVT::i32),
2591 CurDAG->getTargetConstant(AMDGPU::sub0, SL, MVT::i32),
2592 SDValue(
CurDAG->getMachineNode(AMDGPU::S_MOV_B32, SL, MVT::i32, AddrHi),
2594 CurDAG->getTargetConstant(AMDGPU::sub1, SL, MVT::i32),
2597 return SDValue(
CurDAG->getMachineNode(AMDGPU::REG_SEQUENCE, SL, MVT::i64,
2604bool AMDGPUDAGToDAGISel::SelectSMRDBaseOffset(
SDNode *
N,
SDValue Addr,
2607 bool IsBuffer,
bool HasSOffset,
2609 bool *ScaleOffset)
const {
2611 assert(!Imm32Only && !IsBuffer);
2614 if (!SelectSMRDBaseOffset(
N, Addr,
B,
nullptr,
Offset,
false,
false,
true))
2619 ImmOff =
C->getSExtValue();
2621 return SelectSMRDBaseOffset(
N,
B, SBase, SOffset,
nullptr,
false,
false,
2622 true, ImmOff, ScaleOffset);
2642 if (SelectSMRDOffset(
N, N1, SOffset,
Offset, Imm32Only, IsBuffer, HasSOffset,
2643 ImmOffset, ScaleOffset)) {
2647 if (SelectSMRDOffset(
N, N0, SOffset,
Offset, Imm32Only, IsBuffer, HasSOffset,
2648 ImmOffset, ScaleOffset)) {
2657 bool Imm32Only,
bool *ScaleOffset)
const {
2658 if (SelectSMRDBaseOffset(
N, Addr, SBase, SOffset,
Offset, Imm32Only,
2661 SBase = Expand32BitAddress(SBase);
2666 SBase = Expand32BitAddress(Addr);
2667 *
Offset =
CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
2674bool AMDGPUDAGToDAGISel::SelectSMRDImm(
SDValue Addr,
SDValue &SBase,
2676 return SelectSMRD(
nullptr, Addr, SBase,
nullptr,
2680bool AMDGPUDAGToDAGISel::SelectSMRDImm32(
SDValue Addr,
SDValue &SBase,
2683 return SelectSMRD(
nullptr, Addr, SBase,
nullptr,
2690 if (!SelectSMRD(
N, Addr, SBase, &SOffset,
nullptr,
2691 false, &ScaleOffset))
2695 SDLoc(
N), MVT::i32);
2699bool AMDGPUDAGToDAGISel::SelectSMRDSgprImm(
SDNode *
N,
SDValue Addr,
2704 if (!SelectSMRD(
N, Addr, SBase, &SOffset, &
Offset,
false, &ScaleOffset))
2708 SDLoc(
N), MVT::i32);
2713 return SelectSMRDOffset(
nullptr,
N,
nullptr, &
Offset,
2717bool AMDGPUDAGToDAGISel::SelectSMRDBufferImm32(
SDValue N,
2720 return SelectSMRDOffset(
nullptr,
N,
nullptr, &
Offset,
2724bool AMDGPUDAGToDAGISel::SelectSMRDBufferSgprImm(
SDValue N,
SDValue &SOffset,
2728 return N.getValueType() == MVT::i32 &&
2729 SelectSMRDBaseOffset(
nullptr,
N, SOffset,
2734bool AMDGPUDAGToDAGISel::SelectMOVRELOffset(
SDValue Index,
2739 if (
CurDAG->isBaseWithConstantOffset(Index)) {
2740 SDValue N0 =
Index.getOperand(0);
2741 SDValue N1 =
Index.getOperand(1);
2764SDNode *AMDGPUDAGToDAGISel::getBFE32(
bool IsSigned,
const SDLoc &
DL,
2768 unsigned Opcode = IsSigned ? AMDGPU::V_BFE_I32_e64 : AMDGPU::V_BFE_U32_e64;
2770 SDValue
W =
CurDAG->getTargetConstant(Width,
DL, MVT::i32);
2772 return CurDAG->getMachineNode(Opcode,
DL, MVT::i32, Val,
Off, W);
2774 unsigned Opcode = IsSigned ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32;
2778 uint32_t PackedVal =
Offset | (Width << 16);
2779 SDValue PackedConst =
CurDAG->getTargetConstant(PackedVal,
DL, MVT::i32);
2781 return CurDAG->getMachineNode(Opcode,
DL, MVT::i32, Val, PackedConst);
2784void AMDGPUDAGToDAGISel::SelectS_BFEFromShifts(
SDNode *
N) {
2789 const SDValue &Shl =
N->getOperand(0);
2794 uint32_t BVal =
B->getZExtValue();
2795 uint32_t CVal =
C->getZExtValue();
2797 if (0 < BVal && BVal <= CVal && CVal < 32) {
2807void AMDGPUDAGToDAGISel::SelectS_BFE(
SDNode *
N) {
2808 switch (
N->getOpcode()) {
2810 if (
N->getOperand(0).getOpcode() ==
ISD::SRL) {
2813 const SDValue &Srl =
N->getOperand(0);
2817 if (Shift && Mask) {
2819 uint32_t MaskVal =
Mask->getZExtValue();
2831 if (
N->getOperand(0).getOpcode() ==
ISD::AND) {
2834 const SDValue &
And =
N->getOperand(0);
2838 if (Shift && Mask) {
2840 uint32_t MaskVal =
Mask->getZExtValue() >> ShiftVal;
2849 }
else if (
N->getOperand(0).getOpcode() ==
ISD::SHL) {
2850 SelectS_BFEFromShifts(
N);
2855 if (
N->getOperand(0).getOpcode() ==
ISD::SHL) {
2856 SelectS_BFEFromShifts(
N);
2863 SDValue Src =
N->getOperand(0);
2871 unsigned Width =
cast<VTSDNode>(
N->getOperand(1))->getVT().getSizeInBits();
2881bool AMDGPUDAGToDAGISel::isCBranchSCC(
const SDNode *
N)
const {
2883 if (!
N->hasOneUse())
2886 SDValue
Cond =
N->getOperand(1);
2893 MVT VT =
Cond.getOperand(0).getSimpleValueType();
2897 if (VT == MVT::i64) {
2900 Subtarget->hasScalarCompareEq64();
2903 if ((VT == MVT::f16 || VT == MVT::f32) && Subtarget->hasSALUFloatInsts())
2936void AMDGPUDAGToDAGISel::SelectBRCOND(
SDNode *
N) {
2937 SDValue
Cond =
N->getOperand(1);
2939 if (
Cond.isUndef()) {
2940 CurDAG->SelectNodeTo(
N, AMDGPU::SI_BR_UNDEF, MVT::Other,
2941 N->getOperand(2),
N->getOperand(0));
2945 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
2947 bool UseSCCBr = isCBranchSCC(
N) && isUniformBr(
N);
2948 bool AndExec = !UseSCCBr;
2949 bool Negate =
false;
2952 Cond->getOperand(0)->getOpcode() == AMDGPUISD::SETCC) {
2953 SDValue VCMP =
Cond->getOperand(0);
2967 bool NegatedBallot =
false;
2970 UseSCCBr = !BallotCond->isDivergent();
2971 Negate = Negate ^ NegatedBallot;
2986 UseSCCBr ? (Negate ? AMDGPU::S_CBRANCH_SCC0 : AMDGPU::S_CBRANCH_SCC1)
2987 : (Negate ? AMDGPU::S_CBRANCH_VCCZ : AMDGPU::S_CBRANCH_VCCNZ);
2988 Register CondReg = UseSCCBr ? AMDGPU::SCC :
TRI->getVCC();
3007 Subtarget->isWave32() ? AMDGPU::S_AND_B32 : AMDGPU::S_AND_B64, SL,
3009 CurDAG->getRegister(Subtarget->isWave32() ? AMDGPU::EXEC_LO
3016 SDValue VCC =
CurDAG->getCopyToReg(
N->getOperand(0), SL, CondReg,
Cond);
3017 CurDAG->SelectNodeTo(
N, BrOp, MVT::Other,
3022void AMDGPUDAGToDAGISel::SelectFP_EXTEND(
SDNode *
N) {
3023 if (Subtarget->hasSALUFloatInsts() &&
N->getValueType(0) == MVT::f32 &&
3024 !
N->isDivergent()) {
3025 SDValue Src =
N->getOperand(0);
3026 if (Src.getValueType() == MVT::f16) {
3028 CurDAG->SelectNodeTo(
N, AMDGPU::S_CVT_HI_F32_F16,
N->getVTList(),
3038void AMDGPUDAGToDAGISel::SelectDSAppendConsume(
SDNode *
N,
unsigned IntrID) {
3041 unsigned Opc = IntrID == Intrinsic::amdgcn_ds_append ?
3042 AMDGPU::DS_APPEND : AMDGPU::DS_CONSUME;
3044 SDValue Chain =
N->getOperand(0);
3047 MachineMemOperand *MMO =
M->getMemOperand();
3051 if (
CurDAG->isBaseWithConstantOffset(Ptr)) {
3056 if (isDSOffsetLegal(PtrBase, OffsetVal.
getZExtValue())) {
3057 N = glueCopyToM0(
N, PtrBase);
3058 Offset =
CurDAG->getTargetConstant(OffsetVal, SDLoc(), MVT::i32);
3063 N = glueCopyToM0(
N, Ptr);
3064 Offset =
CurDAG->getTargetConstant(0, SDLoc(), MVT::i32);
3069 CurDAG->getTargetConstant(IsGDS, SDLoc(), MVT::i32),
3074 SDNode *Selected =
CurDAG->SelectNodeTo(
N,
Opc,
N->getVTList(),
Ops);
3080void AMDGPUDAGToDAGISel::SelectDSBvhStackIntrinsic(
SDNode *
N,
unsigned IntrID) {
3083 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
3084 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
3085 Opc = AMDGPU::DS_BVH_STACK_RTN_B32;
3087 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
3088 Opc = AMDGPU::DS_BVH_STACK_PUSH8_POP1_RTN_B32;
3090 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn:
3091 Opc = AMDGPU::DS_BVH_STACK_PUSH8_POP2_RTN_B64;
3094 SDValue
Ops[] = {
N->getOperand(2),
N->getOperand(3),
N->getOperand(4),
3095 N->getOperand(5),
N->getOperand(0)};
3098 MachineMemOperand *MMO =
M->getMemOperand();
3099 SDNode *Selected =
CurDAG->SelectNodeTo(
N,
Opc,
N->getVTList(),
Ops);
3103void AMDGPUDAGToDAGISel::SelectTensorLoadStore(
SDNode *
N,
unsigned IntrID) {
3104 bool IsLoad = IntrID == Intrinsic::amdgcn_tensor_load_to_lds;
3106 IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d4 : AMDGPU::TENSOR_STORE_FROM_LDS_d4;
3114 SDValue Group2 =
N->getOperand(4);
3115 SDValue Group3 =
N->getOperand(5);
3118 Opc = IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d2
3119 : AMDGPU::TENSOR_STORE_FROM_LDS_d2;
3131 (void)
CurDAG->SelectNodeTo(
N,
Opc, MVT::Other, TensorOps);
3136 case Intrinsic::amdgcn_ds_gws_init:
3137 return AMDGPU::DS_GWS_INIT;
3138 case Intrinsic::amdgcn_ds_gws_barrier:
3139 return AMDGPU::DS_GWS_BARRIER;
3140 case Intrinsic::amdgcn_ds_gws_sema_v:
3141 return AMDGPU::DS_GWS_SEMA_V;
3142 case Intrinsic::amdgcn_ds_gws_sema_br:
3143 return AMDGPU::DS_GWS_SEMA_BR;
3144 case Intrinsic::amdgcn_ds_gws_sema_p:
3145 return AMDGPU::DS_GWS_SEMA_P;
3146 case Intrinsic::amdgcn_ds_gws_sema_release_all:
3147 return AMDGPU::DS_GWS_SEMA_RELEASE_ALL;
3153void AMDGPUDAGToDAGISel::SelectDS_GWS(
SDNode *
N,
unsigned IntrID) {
3154 if (!Subtarget->hasGWS() ||
3155 (IntrID == Intrinsic::amdgcn_ds_gws_sema_release_all &&
3156 !Subtarget->hasGWSSemaReleaseAll())) {
3163 const bool HasVSrc =
N->getNumOperands() == 4;
3164 assert(HasVSrc ||
N->getNumOperands() == 3);
3167 SDValue BaseOffset =
N->getOperand(HasVSrc ? 3 : 2);
3170 MachineMemOperand *MMO =
M->getMemOperand();
3183 glueCopyToM0(
N,
CurDAG->getTargetConstant(0, SL, MVT::i32));
3184 ImmOffset = ConstOffset->getZExtValue();
3186 if (
CurDAG->isBaseWithConstantOffset(BaseOffset)) {
3195 =
CurDAG->getMachineNode(AMDGPU::V_READFIRSTLANE_B32, SL, MVT::i32,
3199 =
CurDAG->getMachineNode(AMDGPU::S_LSHL_B32, SL, MVT::i32,
3200 SDValue(SGPROffset, 0),
3201 CurDAG->getTargetConstant(16, SL, MVT::i32));
3202 glueCopyToM0(
N, SDValue(M0Base, 0));
3206 SDValue OffsetField =
CurDAG->getTargetConstant(ImmOffset, SL, MVT::i32);
3210 const MCInstrDesc &InstrDesc =
TII->get(
Opc);
3211 int Data0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
3217 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3219 SDValue
Data =
N->getOperand(2);
3220 MVT DataVT =
Data.getValueType().getSimpleVT();
3221 if (
TRI->isTypeLegalForClass(*DataRC, DataVT)) {
3223 Ops.push_back(
N->getOperand(2));
3227 const SDValue RegSeqOps[] = {
3229 CurDAG->getTargetConstant(AMDGPU::sub0, SL, MVT::i32),
3231 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, SL, MVT::i32),
3233 CurDAG->getTargetConstant(AMDGPU::sub1, SL, MVT::i32)};
3235 Ops.push_back(SDValue(
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
3236 SL, MVT::v2i32, RegSeqOps),
3241 Ops.push_back(OffsetField);
3242 Ops.push_back(Chain);
3244 SDNode *Selected =
CurDAG->SelectNodeTo(
N,
Opc,
N->getVTList(),
Ops);
3248void AMDGPUDAGToDAGISel::SelectInterpP1F16(
SDNode *
N) {
3249 if (Subtarget->getLDSBankCount() != 16) {
3276 SDValue ToM0 =
CurDAG->getCopyToReg(
CurDAG->getEntryNode(),
DL, AMDGPU::M0,
3277 N->getOperand(5), SDValue());
3279 SDVTList VTs =
CurDAG->getVTList(MVT::f32, MVT::Other);
3282 CurDAG->getMachineNode(AMDGPU::V_INTERP_MOV_F32,
DL, VTs, {
3283 CurDAG->getTargetConstant(2,
DL, MVT::i32),
3289 SDNode *InterpP1LV =
3290 CurDAG->getMachineNode(AMDGPU::V_INTERP_P1LV_F16,
DL, MVT::f32, {
3291 CurDAG->getTargetConstant(0,
DL, MVT::i32),
3295 CurDAG->getTargetConstant(0,
DL, MVT::i32),
3296 SDValue(InterpMov, 0),
3298 CurDAG->getTargetConstant(0,
DL, MVT::i1),
3299 CurDAG->getTargetConstant(0,
DL, MVT::i32),
3300 SDValue(InterpMov, 1)
3303 CurDAG->ReplaceAllUsesOfValueWith(SDValue(
N, 0), SDValue(InterpP1LV, 0));
3306void AMDGPUDAGToDAGISel::SelectINTRINSIC_W_CHAIN(
SDNode *
N) {
3307 unsigned IntrID =
N->getConstantOperandVal(1);
3309 case Intrinsic::amdgcn_ds_append:
3310 case Intrinsic::amdgcn_ds_consume: {
3311 if (
N->getValueType(0) != MVT::i32)
3313 SelectDSAppendConsume(
N, IntrID);
3316 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
3317 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
3318 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
3319 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn:
3320 SelectDSBvhStackIntrinsic(
N, IntrID);
3322 case Intrinsic::amdgcn_init_whole_wave:
3323 CurDAG->getMachineFunction()
3324 .getInfo<SIMachineFunctionInfo>()
3325 ->setInitWholeWave();
3332void AMDGPUDAGToDAGISel::SelectINTRINSIC_WO_CHAIN(
SDNode *
N) {
3333 unsigned IntrID =
N->getConstantOperandVal(0);
3334 unsigned Opcode = AMDGPU::INSTRUCTION_LIST_END;
3335 SDNode *ConvGlueNode =
N->getGluedNode();
3341 CurDAG->getMachineNode(TargetOpcode::CONVERGENCECTRL_GLUE, {},
3342 MVT::Glue, SDValue(ConvGlueNode, 0));
3344 ConvGlueNode =
nullptr;
3347 case Intrinsic::amdgcn_wqm:
3348 Opcode = AMDGPU::WQM;
3350 case Intrinsic::amdgcn_softwqm:
3351 Opcode = AMDGPU::SOFT_WQM;
3353 case Intrinsic::amdgcn_wwm:
3354 case Intrinsic::amdgcn_strict_wwm:
3355 Opcode = AMDGPU::STRICT_WWM;
3357 case Intrinsic::amdgcn_strict_wqm:
3358 Opcode = AMDGPU::STRICT_WQM;
3360 case Intrinsic::amdgcn_interp_p1_f16:
3361 SelectInterpP1F16(
N);
3363 case Intrinsic::amdgcn_permlane16_swap:
3364 case Intrinsic::amdgcn_permlane32_swap: {
3365 if ((IntrID == Intrinsic::amdgcn_permlane16_swap &&
3366 !Subtarget->hasPermlane16Swap()) ||
3367 (IntrID == Intrinsic::amdgcn_permlane32_swap &&
3368 !Subtarget->hasPermlane32Swap())) {
3373 Opcode = IntrID == Intrinsic::amdgcn_permlane16_swap
3374 ? AMDGPU::V_PERMLANE16_SWAP_B32_e64
3375 : AMDGPU::V_PERMLANE32_SWAP_B32_e64;
3379 NewOps.push_back(SDValue(ConvGlueNode, 0));
3381 bool FI =
N->getConstantOperandVal(3);
3382 NewOps[2] =
CurDAG->getTargetConstant(
3385 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(), NewOps);
3393 if (Opcode != AMDGPU::INSTRUCTION_LIST_END) {
3394 SDValue Src =
N->getOperand(1);
3395 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(), {Src});
3400 NewOps.push_back(SDValue(ConvGlueNode, 0));
3401 CurDAG->MorphNodeTo(
N,
N->getOpcode(),
N->getVTList(), NewOps);
3405void AMDGPUDAGToDAGISel::SelectINTRINSIC_VOID(
SDNode *
N) {
3406 unsigned IntrID =
N->getConstantOperandVal(1);
3408 case Intrinsic::amdgcn_ds_gws_init:
3409 case Intrinsic::amdgcn_ds_gws_barrier:
3410 case Intrinsic::amdgcn_ds_gws_sema_v:
3411 case Intrinsic::amdgcn_ds_gws_sema_br:
3412 case Intrinsic::amdgcn_ds_gws_sema_p:
3413 case Intrinsic::amdgcn_ds_gws_sema_release_all:
3414 SelectDS_GWS(
N, IntrID);
3416 case Intrinsic::amdgcn_tensor_load_to_lds:
3417 case Intrinsic::amdgcn_tensor_store_from_lds:
3418 SelectTensorLoadStore(
N, IntrID);
3427void AMDGPUDAGToDAGISel::SelectWAVE_ADDRESS(
SDNode *
N) {
3428 SDValue Log2WaveSize =
3429 CurDAG->getTargetConstant(Subtarget->getWavefrontSizeLog2(), SDLoc(
N), MVT::i32);
3430 CurDAG->SelectNodeTo(
N, AMDGPU::S_LSHR_B32,
N->getVTList(),
3431 {N->getOperand(0), Log2WaveSize});
3434void AMDGPUDAGToDAGISel::SelectSTACKRESTORE(
SDNode *
N) {
3435 SDValue SrcVal =
N->getOperand(1);
3448 SDValue Log2WaveSize =
CurDAG->getTargetConstant(
3449 Subtarget->getWavefrontSizeLog2(), SL, MVT::i32);
3451 if (
N->isDivergent()) {
3452 SrcVal = SDValue(
CurDAG->getMachineNode(AMDGPU::V_READFIRSTLANE_B32, SL,
3457 CopyVal = SDValue(
CurDAG->getMachineNode(AMDGPU::S_LSHL_B32, SL, MVT::i32,
3458 {SrcVal, Log2WaveSize}),
3462 SDValue CopyToSP =
CurDAG->getCopyToReg(
N->getOperand(0), SL,
SP, CopyVal);
3463 CurDAG->ReplaceAllUsesOfValueWith(SDValue(
N, 0), CopyToSP);
3466void AMDGPUDAGToDAGISel::SelectWRITE_REGISTER(
SDNode *
N) {
3473 CurDAG->getMachineFunction());
3477 "invalid register \"" + Twine(RegStr->
getString()) +
3478 "\" for llvm.write_register",
3479 Fn,
N->getDebugLoc()));
3491 }
else if (VT == MVT::i32) {
3492 CopyVal = SDValue(
CurDAG->getMachineNode(AMDGPU::V_READFIRSTLANE_B32, SL,
3498 CurDAG->getTargetExtractSubreg(AMDGPU::sub0, SL, MVT::i32, SrcVal);
3500 CurDAG->getTargetExtractSubreg(AMDGPU::sub1, SL, MVT::i32, SrcVal);
3502 CurDAG->getMachineNode(AMDGPU::V_READFIRSTLANE_B32, SL, MVT::i32,
Lo),
3505 CurDAG->getMachineNode(AMDGPU::V_READFIRSTLANE_B32, SL, MVT::i32,
Hi),
3507 CopyVal = emitRegSequence(*
CurDAG, AMDGPU::SReg_64RegClassID, VT, {
Lo,
Hi},
3508 {AMDGPU::sub0, AMDGPU::sub1}, SL);
3512 CurDAG->ReplaceAllUsesOfValueWith(SDValue(
N, 0), CopyToReg);
3515bool AMDGPUDAGToDAGISel::SelectVOP3ModsImpl(
SDValue In,
SDValue &Src,
3517 bool IsCanonicalizing,
3518 bool AllowAbs)
const {
3524 Src = Src.getOperand(0);
3525 }
else if (Src.getOpcode() ==
ISD::FSUB && IsCanonicalizing) {
3529 if (
LHS &&
LHS->isZero()) {
3531 Src = Src.getOperand(1);
3535 if (AllowAbs && Src.getOpcode() ==
ISD::FABS) {
3537 Src = Src.getOperand(0);
3550 if (IsCanonicalizing)
3565 EVT VT = Src.getValueType();
3567 (VT != MVT::i32 && VT != MVT::v2i32 && VT != MVT::i64))
3574 auto ReplaceSrc = [&]() -> SDValue {
3576 return Src.getOperand(0);
3579 SDValue
Index = Src->getOperand(1);
3581 Src.getValueType(),
LHS, Index);
3607 if (SelectVOP3ModsImpl(In, Src, Mods,
true,
3609 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3616bool AMDGPUDAGToDAGISel::SelectVOP3ModsNonCanonicalizing(
3619 if (SelectVOP3ModsImpl(In, Src, Mods,
false,
3621 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3628bool AMDGPUDAGToDAGISel::SelectVOP3BMods(
SDValue In,
SDValue &Src,
3631 if (SelectVOP3ModsImpl(In, Src, Mods,
3634 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3641bool AMDGPUDAGToDAGISel::SelectVOP3NoMods(
SDValue In,
SDValue &Src)
const {
3649bool AMDGPUDAGToDAGISel::SelectVINTERPModsImpl(
SDValue In,
SDValue &Src,
3653 if (SelectVOP3ModsImpl(In, Src, Mods,
3658 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3665bool AMDGPUDAGToDAGISel::SelectVINTERPMods(
SDValue In,
SDValue &Src,
3667 return SelectVINTERPModsImpl(In, Src, SrcMods,
false);
3670bool AMDGPUDAGToDAGISel::SelectVINTERPModsHi(
SDValue In,
SDValue &Src,
3672 return SelectVINTERPModsImpl(In, Src, SrcMods,
true);
3675bool AMDGPUDAGToDAGISel::SelectVOP3Mods0(
SDValue In,
SDValue &Src,
3679 Clamp =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3680 Omod =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3682 return SelectVOP3Mods(In, Src, SrcMods);
3685bool AMDGPUDAGToDAGISel::SelectVOP3BMods0(
SDValue In,
SDValue &Src,
3689 Clamp =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3690 Omod =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3692 return SelectVOP3BMods(In, Src, SrcMods);
3695bool AMDGPUDAGToDAGISel::SelectVOP3OMods(
SDValue In,
SDValue &Src,
3700 Clamp =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3701 Omod =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3706bool AMDGPUDAGToDAGISel::SelectVOP3PMods(
SDValue In,
SDValue &Src,
3707 SDValue &SrcMods,
bool IsDOT)
const {
3714 Src = Src.getOperand(0);
3718 bool HasOpSel = Src.getValueSizeInBits() != 128;
3721 (!IsDOT || !Subtarget->hasDOTOpSelHazard())) {
3722 unsigned VecMods = Mods;
3724 SDValue
Lo = stripBitcast(Src.getOperand(0));
3725 SDValue
Hi = stripBitcast(Src.getOperand(1));
3728 Lo = stripBitcast(
Lo.getOperand(0));
3733 Hi = stripBitcast(
Hi.getOperand(0));
3745 unsigned VecSize = Src.getValueSizeInBits();
3746 Lo = stripExtractLoElt(
Lo);
3747 Hi = stripExtractLoElt(
Hi);
3749 if (
Lo.getValueSizeInBits() > VecSize) {
3750 Lo =
CurDAG->getTargetExtractSubreg(
3751 (VecSize > 32) ? AMDGPU::sub0_sub1 : AMDGPU::sub0, SDLoc(In),
3755 if (
Hi.getValueSizeInBits() > VecSize) {
3756 Hi =
CurDAG->getTargetExtractSubreg(
3757 (VecSize > 32) ? AMDGPU::sub0_sub1 : AMDGPU::sub0, SDLoc(In),
3761 assert(
Lo.getValueSizeInBits() <= VecSize &&
3762 Hi.getValueSizeInBits() <= VecSize);
3764 if (
Lo ==
Hi && !isInlineImmediate(
Lo.getNode())) {
3768 if (VecSize ==
Lo.getValueSizeInBits()) {
3770 }
else if (VecSize == 32) {
3771 Src = createVOP3PSrc32FromLo16(
Lo, Src,
CurDAG, Subtarget);
3773 assert((
Lo.getValueSizeInBits() == 32 && VecSize == 64) ||
3774 (
Lo.getValueSizeInBits() == 64 && VecSize == 128));
3777 SDValue
Undef = SDValue(
3778 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, SL,
3779 Lo.getValueType()), 0);
3780 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3785 auto RC =
Lo->isDivergent() ?
TRI->getVGPRClassForBitWidth(VecSize)
3786 :
TRI->getSGPRClassForBitWidth(VecSize);
3787 unsigned NumRegs =
Lo.getValueSizeInBits() == 32 ? 1 : 2;
3788 const SDValue
Ops[] = {
3789 CurDAG->getTargetConstant(RC->getID(), SL, MVT::i32),
Lo,
3790 CurDAG->getTargetConstant(
TRI->getSubRegFromChannel(0, NumRegs), SL,
3795 CurDAG->getTargetConstant(
3796 TRI->getSubRegFromChannel(NumRegs, NumRegs), SL, MVT::i32)};
3798 Src = SDValue(
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, SL,
3799 Src.getValueType(),
Ops), 0);
3803 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3809 .bitcastToAPInt().getZExtValue();
3811 Src =
CurDAG->getTargetConstant(
Lit, SDLoc(In), MVT::i64);
3812 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3819 Src.getNumOperands() == 2) {
3824 assert(Src.getValueSizeInBits() != 128 &&
3825 "<2 x 64> VECTOR_SHUFFLE should not be legal.");
3828 ArrayRef<int>
Mask = SVN->getMask();
3830 if (Mask[0] < 2 && Mask[1] < 2) {
3832 SDValue ShuffleSrc = SVN->getOperand(0);
3845 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3853 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3857bool AMDGPUDAGToDAGISel::SelectVOP3PModsDOT(
SDValue In,
SDValue &Src,
3859 return SelectVOP3PMods(In, Src, SrcMods,
true);
3862bool AMDGPUDAGToDAGISel::SelectVOP3PNoModsDOT(
SDValue In,
SDValue &Src)
const {
3863 SDValue SrcTmp, SrcModsTmp;
3864 SelectVOP3PMods(In, SrcTmp, SrcModsTmp,
true);
3873bool AMDGPUDAGToDAGISel::SelectVOP3PModsF32(
SDValue In,
SDValue &Src,
3875 SelectVOP3Mods(In, Src, SrcMods);
3878 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3882bool AMDGPUDAGToDAGISel::SelectVOP3PNoModsF32(
SDValue In,
SDValue &Src)
const {
3883 SDValue SrcTmp, SrcModsTmp;
3884 SelectVOP3PModsF32(In, SrcTmp, SrcModsTmp);
3893bool AMDGPUDAGToDAGISel::SelectWMMAOpSelVOP3PMods(
SDValue In,
3896 assert(
C->getAPIntValue().getBitWidth() == 1 &&
"expected i1 value");
3899 unsigned SrcVal =
C->getZExtValue();
3903 Src =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3910 unsigned DstRegClass;
3912 switch (Elts.
size()) {
3914 DstRegClass = AMDGPU::VReg_256RegClassID;
3918 DstRegClass = AMDGPU::VReg_128RegClassID;
3922 DstRegClass = AMDGPU::VReg_64RegClassID;
3930 Ops.push_back(
CurDAG->getTargetConstant(DstRegClass,
DL, MVT::i32));
3931 for (
unsigned i = 0; i < Elts.
size(); ++i) {
3932 Ops.push_back(Elts[i]);
3933 Ops.push_back(
CurDAG->getTargetConstant(
3936 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL, DstTy,
Ops);
3943 assert(
"unhandled Reg sequence size" &&
3944 (Elts.
size() == 8 || Elts.
size() == 16));
3948 for (
unsigned i = 0; i < Elts.
size(); i += 2) {
3949 SDValue LoSrc = stripExtractLoElt(stripBitcast(Elts[i]));
3954 if (Subtarget->useRealTrue16Insts()) {
3958 SDValue
Undef = SDValue(
3959 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, MVT::i16),
3962 emitRegSequence(*
CurDAG, AMDGPU::VGPR_32RegClassID, MVT::i32,
3963 {Elts[i],
Undef}, {AMDGPU::lo16, AMDGPU::hi16},
DL);
3964 Elts[i + 1] = emitRegSequence(*
CurDAG, AMDGPU::VGPR_32RegClassID,
3965 MVT::i32, {Elts[i + 1],
Undef},
3966 {AMDGPU::lo16, AMDGPU::hi16},
DL);
3968 SDValue PackLoLo =
CurDAG->getTargetConstant(0x05040100,
DL, MVT::i32);
3970 CurDAG->getMachineNode(AMDGPU::V_PERM_B32_e64,
DL, MVT::i32,
3971 {Elts[i + 1], Elts[i], PackLoLo});
3972 PackedElts.
push_back(SDValue(Packed, 0));
3975 return buildRegSequence32(PackedElts,
DL);
3981 unsigned ElementSize)
const {
3982 if (ElementSize == 16)
3983 return buildRegSequence16(Elts,
DL);
3984 if (ElementSize == 32)
3985 return buildRegSequence32(Elts,
DL);
3989void AMDGPUDAGToDAGISel::selectWMMAModsNegAbs(
unsigned ModOpcode,
3993 unsigned ElementSize)
const {
3998 for (
auto El : Elts) {
4001 NegAbsElts.
push_back(El->getOperand(0));
4003 if (Elts.size() != NegAbsElts.
size()) {
4005 Src = SDValue(buildRegSequence(Elts,
DL, ElementSize), 0);
4009 Src = SDValue(buildRegSequence(NegAbsElts,
DL, ElementSize), 0);
4015 Src = SDValue(buildRegSequence(Elts,
DL, ElementSize), 0);
4023 std::function<
bool(
SDValue)> ModifierCheck) {
4027 for (
unsigned i = 0; i < F16Pair->getNumOperands(); ++i) {
4028 SDValue ElF16 = stripBitcast(F16Pair->getOperand(i));
4029 if (!ModifierCheck(ElF16))
4036bool AMDGPUDAGToDAGISel::SelectWMMAModsF16Neg(
SDValue In,
SDValue &Src,
4054 Src = SDValue(buildRegSequence16(EltsF16, SDLoc(In)), 0);
4064 SDValue ElV2f16 = stripBitcast(BV->
getOperand(i));
4073 Src = SDValue(buildRegSequence32(EltsV2F16, SDLoc(In)), 0);
4079 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4083bool AMDGPUDAGToDAGISel::SelectWMMAModsF16NegAbs(
SDValue In,
SDValue &Src,
4094 if (EltsF16.
empty())
4104 selectWMMAModsNegAbs(ModOpcode, Mods, EltsF16, Src, SDLoc(In), 16);
4112 SDValue ElV2f16 = stripBitcast(BV->
getOperand(i));
4114 if (EltsV2F16.
empty())
4123 selectWMMAModsNegAbs(ModOpcode, Mods, EltsV2F16, Src, SDLoc(In), 32);
4126 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4130bool AMDGPUDAGToDAGISel::SelectWMMAModsF32NegAbs(
SDValue In,
SDValue &Src,
4139 SDValue ElF32 = stripBitcast(BV->
getOperand(0));
4140 unsigned ModOpcode =
4143 SDValue ElF32 = stripBitcast(BV->
getOperand(i));
4151 selectWMMAModsNegAbs(ModOpcode, Mods, EltsF32, Src, SDLoc(In), 32);
4154 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4158bool AMDGPUDAGToDAGISel::SelectWMMAVISrc(
SDValue In,
SDValue &Src)
const {
4160 BitVector UndefElements;
4162 if (isInlineImmediate(
Splat.getNode())) {
4164 unsigned Imm =
C->getAPIntValue().getSExtValue();
4165 Src =
CurDAG->getTargetConstant(
Imm, SDLoc(In), MVT::i32);
4169 unsigned Imm =
C->getValueAPF().bitcastToAPInt().getSExtValue();
4170 Src =
CurDAG->getTargetConstant(
Imm, SDLoc(In), MVT::i32);
4178 SDValue SplatSrc32 = stripBitcast(In);
4180 if (SDValue Splat32 = SplatSrc32BV->getSplatValue()) {
4181 SDValue SplatSrc16 = stripBitcast(Splat32);
4183 if (SDValue
Splat = SplatSrc16BV->getSplatValue()) {
4184 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
4185 std::optional<APInt> RawValue;
4187 RawValue =
C->getValueAPF().bitcastToAPInt();
4189 RawValue =
C->getAPIntValue();
4191 if (RawValue.has_value()) {
4192 EVT VT =
In.getValueType().getScalarType();
4198 if (
TII->isInlineConstant(FloatVal)) {
4199 Src =
CurDAG->getTargetConstant(RawValue.value(), SDLoc(In),
4204 if (
TII->isInlineConstant(RawValue.value())) {
4205 Src =
CurDAG->getTargetConstant(RawValue.value(), SDLoc(In),
4218 if (
CurDAG->isConstantIntBuildVectorOrConstantInt(SplatSrc32)) {
4223 int64_t LoImm = Lo32->getAPIntValue().getSExtValue();
4224 int64_t HiImm = Hi32->getAPIntValue().getSExtValue();
4225 int64_t Imm64I = (HiImm << 32) + LoImm;
4227 if (!isInlineImmediate(APInt(64, Imm64I)))
4230 }
else if (Imm64I != Imm64)
4234 Src =
CurDAG->getTargetConstant(Imm64, SDLoc(In), MVT::i64);
4241bool AMDGPUDAGToDAGISel::SelectSWMMACIndex8(
SDValue In,
SDValue &Src,
4247 const llvm::SDValue &ShiftSrc =
In.getOperand(0);
4256 IndexKey =
CurDAG->getTargetConstant(
Key, SDLoc(In), MVT::i32);
4260bool AMDGPUDAGToDAGISel::SelectSWMMACIndex16(
SDValue In,
SDValue &Src,
4266 const llvm::SDValue &ShiftSrc =
In.getOperand(0);
4275 IndexKey =
CurDAG->getTargetConstant(
Key, SDLoc(In), MVT::i32);
4279bool AMDGPUDAGToDAGISel::SelectSWMMACIndex32(
SDValue In,
SDValue &Src,
4287 const SDValue &ExtendSrc =
In.getOperand(0);
4291 const SDValue &CastSrc =
In.getOperand(0);
4295 if (Zero &&
Zero->getZExtValue() == 0)
4301 const SDValue &ExtractVecEltSrc = InI32.
getOperand(0);
4306 Src = ExtractVecEltSrc;
4310 IndexKey =
CurDAG->getTargetConstant(
Key, SDLoc(In), MVT::i32);
4314bool AMDGPUDAGToDAGISel::SelectVOP3OpSel(
SDValue In,
SDValue &Src,
4318 if (!Subtarget->useRealTrue16Insts() &&
In.getValueSizeInBits() == 16 &&
4321 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4325bool AMDGPUDAGToDAGISel::SelectVOP3OpSelMods(
SDValue In,
SDValue &Src,
4328 if (!SelectVOP3ModsImpl(In, Src, Mods,
true,
4332 if (!Subtarget->useRealTrue16Insts() &&
In.getValueSizeInBits() == 16 &&
4336 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4349 Op =
Op.getOperand(0);
4351 IsExtractHigh =
false;
4354 if (!Low16 || !Low16->isZero())
4356 Op = stripBitcast(
Op.getOperand(1));
4357 if (
Op.getValueType() != MVT::bf16)
4362 if (
Op.getValueType() != MVT::i32)
4367 if (Mask->getZExtValue() == 0xffff0000) {
4368 IsExtractHigh =
true;
4369 return Op.getOperand(0);
4378 return Op.getOperand(0);
4387bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixModsImpl(
SDValue In,
SDValue &Src,
4391 SelectVOP3ModsImpl(In, Src, Mods);
4393 bool IsExtractHigh =
false;
4395 Src.getOperand(0).getValueType() == VT) {
4396 Src = Src.getOperand(0);
4397 }
else if (VT == MVT::bf16) {
4405 if (Src.getValueType() != VT &&
4406 (VT != MVT::bf16 || Src.getValueType() != MVT::i32))
4409 Src = stripBitcast(Src);
4415 SelectVOP3ModsImpl(Src, Src, ModsTmp);
4430 if (Src.getValueSizeInBits() == 16) {
4439 Src.getOperand(0).getValueType() == MVT::i32) {
4440 Src = Src.getOperand(0);
4444 if (Subtarget->useRealTrue16Insts())
4446 Src = createVOP3PSrc32FromLo16(Src, In,
CurDAG, Subtarget);
4447 }
else if (IsExtractHigh)
4453bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixModsExt(
SDValue In,
SDValue &Src,
4456 if (!SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::f16))
4458 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4462bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixMods(
SDValue In,
SDValue &Src,
4465 SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::f16);
4466 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4470bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixModsExtNeg(
SDValue In,
SDValue &Src,
4473 if (!SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::f16))
4480bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixModsNeg(
SDValue In,
SDValue &Src,
4483 SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::f16);
4489bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixBF16ModsExt(
SDValue In,
SDValue &Src,
4492 if (!SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::bf16))
4494 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4498bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixBF16Mods(
SDValue In,
SDValue &Src,
4501 SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::bf16);
4502 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4506bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixBF16ModsExtNeg(
4509 if (!SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::bf16))
4516bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixBF16ModsNeg(
SDValue In,
SDValue &Src,
4519 SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::bf16);
4529 unsigned NumOpcodes = 0;
4542 const uint8_t SrcBits[3] = { 0xf0, 0xcc, 0xaa };
4545 if (
C->isAllOnes()) {
4555 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4569 if (Src.size() == 3) {
4575 if (
C->isAllOnes()) {
4577 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4578 if (Src[
I] ==
LHS) {
4590 Bits = SrcBits[Src.size()];
4595 switch (In.getOpcode()) {
4603 if (!getOperandBits(
LHS, LHSBits) ||
4604 !getOperandBits(
RHS, RHSBits)) {
4605 Src = std::move(Backup);
4606 return std::make_pair(0, 0);
4627 uint8_t LHSBitsOrig = LHSBits;
4628 uint8_t RHSBitsOrig = RHSBits;
4632 NumOpcodes += LHSOp.first;
4633 LHSBits = LHSOp.second;
4640 NumOpcodes += RHSOp.first;
4641 RHSBits = RHSOp.second;
4645 auto dependsOnSlot = [](
uint8_t TT,
int Slot) ->
bool {
4646 if (Slot < 0 || Slot > 2)
4648 const uint8_t Masks[3] = {0x0f, 0x33, 0x55};
4649 const int Shifts[3] = {4, 2, 1};
4650 return ((TT ^ (TT >> Shifts[Slot])) & Masks[Slot]) != 0;
4656 const uint8_t SrcBitsConst[3] = {0xf0, 0xcc, 0xaa};
4663 NegatedInner =
Op.getOperand(0);
4664 for (
int I = 0;
I < (int)S.size();
I++) {
4665 if (Bits == SrcBitsConst[
I] && S[
I] ==
Op)
4667 if (IsNegationOp && Bits == (
uint8_t)~SrcBitsConst[
I] &&
4668 S[
I] == NegatedInner)
4679 for (
int I = 0;
I < (int)SrcAfterLHS.
size() &&
I < 3;
I++) {
4680 if (
I < (
int)Src.size() && Src[
I] != SrcAfterLHS[
I] &&
4681 dependsOnSlot(LHSBits,
I)) {
4690 if (!Stale && !RHSOp.first) {
4691 int Slot = findSlot(RHSBitsOrig,
RHS, SrcBeforeRecurse);
4693 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4699 if (!Stale && !LHSOp.first) {
4700 int Slot = findSlot(LHSBitsOrig,
LHS, SrcBeforeRecurse);
4702 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4707 Src = std::move(SrcBeforeRecurse);
4708 LHSBits = LHSBitsOrig;
4709 RHSBits = RHSBitsOrig;
4715 return std::make_pair(0, 0);
4719 switch (In.getOpcode()) {
4721 TTbl = LHSBits & RHSBits;
4724 TTbl = LHSBits | RHSBits;
4727 TTbl = LHSBits ^ RHSBits;
4733 return std::make_pair(NumOpcodes + 1, TTbl);
4740 unsigned NumOpcodes;
4742 std::tie(NumOpcodes, TTbl) =
BitOp3_Op(In, Src);
4746 if (NumOpcodes < 2 || Src.empty())
4752 if (NumOpcodes < 4 && !In->isDivergent())
4755 if (NumOpcodes == 2 &&
In.getValueType() == MVT::i32) {
4760 (
In.getOperand(0).getOpcode() ==
In.getOpcode() ||
4761 In.getOperand(1).getOpcode() ==
In.getOpcode()))
4775 while (Src.size() < 3)
4776 Src.push_back(Src[0]);
4782 Tbl =
CurDAG->getTargetConstant(TTbl, SDLoc(In), MVT::i32);
4788 return CurDAG->getPOISON(MVT::i32);
4791 return CurDAG->getUNDEF(MVT::i32);
4795 return CurDAG->getConstant(
C->getZExtValue() << 16, SL, MVT::i32);
4800 return CurDAG->getConstant(
4801 C->getValueAPF().bitcastToAPInt().getZExtValue() << 16, SL, MVT::i32);
4811bool AMDGPUDAGToDAGISel::isVGPRImm(
const SDNode *
N)
const {
4812 assert(
CurDAG->getTarget().getTargetTriple().isAMDGCN());
4814 const SIRegisterInfo *SIRI = Subtarget->getRegisterInfo();
4815 const SIInstrInfo *SII = Subtarget->getInstrInfo();
4818 bool AllUsesAcceptSReg =
true;
4820 Limit < 10 && U !=
E; ++U, ++Limit) {
4822 getOperandRegClass(
U->getUser(),
U->getOperandNo());
4830 if (RC != &AMDGPU::VS_32RegClass && RC != &AMDGPU::VS_64RegClass &&
4831 RC != &AMDGPU::VS_64_Align2RegClass) {
4832 AllUsesAcceptSReg =
false;
4833 SDNode *
User =
U->getUser();
4834 if (
User->isMachineOpcode()) {
4835 unsigned Opc =
User->getMachineOpcode();
4836 const MCInstrDesc &
Desc = SII->get(
Opc);
4837 if (
Desc.isCommutable()) {
4838 unsigned OpIdx =
Desc.getNumDefs() +
U->getOperandNo();
4841 unsigned CommutedOpNo = CommuteIdx1 -
Desc.getNumDefs();
4843 getOperandRegClass(
U->getUser(), CommutedOpNo);
4844 if (CommutedRC == &AMDGPU::VS_32RegClass ||
4845 CommutedRC == &AMDGPU::VS_64RegClass ||
4846 CommutedRC == &AMDGPU::VS_64_Align2RegClass)
4847 AllUsesAcceptSReg =
true;
4855 if (!AllUsesAcceptSReg)
4859 return !AllUsesAcceptSReg && (Limit < 10);
4865 bool IsModified =
false;
4871 while (Position !=
CurDAG->allnodes_end()) {
4878 if (ResNode !=
Node) {
4884 CurDAG->RemoveDeadNodes();
4885 }
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 - Same semantics as the llvm.minnum/maxnum intrinsics.
@ 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.