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)
85static bool isLoEltExtractHi(
SDValue BV) {
88 Lo = stripBitcast(
Lo.getOperand(0));
103 if (
Lo->isDivergent()) {
105 SL,
Lo.getValueType()),
113 Src.getValueType(),
Ops),
131 SDValue Idx = In.getOperand(1);
133 return In.getOperand(0);
137 SDValue Src = In.getOperand(0);
138 if (Src.getValueType().getSizeInBits() == 32)
139 return stripBitcast(Src);
149 assert(Elts.
size() == SubRegClass.
size() &&
"array size mismatch");
150 unsigned NumElts = Elts.
size();
153 for (
unsigned i = 0; i < NumElts; ++i) {
154 Ops[2 * i + 1] = Elts[i];
164 "AMDGPU DAG->DAG Pattern Instruction Selection",
false,
168#ifdef EXPENSIVE_CHECKS
173 "AMDGPU DAG->DAG Pattern Instruction Selection",
false,
194bool AMDGPUDAGToDAGISel::fp16SrcZerosHighBits(
unsigned Opc)
const {
230 case AMDGPUISD::FRACT:
231 case AMDGPUISD::CLAMP:
232 case AMDGPUISD::COS_HW:
233 case AMDGPUISD::SIN_HW:
234 case AMDGPUISD::FMIN3:
235 case AMDGPUISD::FMAX3:
236 case AMDGPUISD::FMED3:
237 case AMDGPUISD::FMAD_FTZ:
240 case AMDGPUISD::RCP_IFLAG:
250 case AMDGPUISD::DIV_FIXUP:
260#ifdef EXPENSIVE_CHECKS
264 assert(L->isLCSSAForm(DT));
272#ifdef EXPENSIVE_CHECKS
280 assert(Subtarget->d16PreservesUnusedBits());
281 MVT VT =
N->getValueType(0).getSimpleVT();
282 if (VT != MVT::v2i16 && VT != MVT::v2f16)
304 unsigned LoadOp = AMDGPUISD::LOAD_D16_HI;
307 AMDGPUISD::LOAD_D16_HI_I8 : AMDGPUISD::LOAD_D16_HI_U8;
313 CurDAG->getMemIntrinsicNode(LoadOp,
SDLoc(LdHi), VTList,
326 if (LdLo &&
Lo.hasOneUse()) {
332 unsigned LoadOp = AMDGPUISD::LOAD_D16_LO;
335 AMDGPUISD::LOAD_D16_LO_I8 : AMDGPUISD::LOAD_D16_LO_U8;
347 CurDAG->getMemIntrinsicNode(LoadOp,
SDLoc(LdLo), VTList,
361 EVT VT =
N->getValueType(0);
375 Ld ?
CurDAG->getExtLoad(ExtType, SL, MVT::i32, Mem->getChain(),
376 Mem->getBasePtr(), MemVT, Mem->getMemOperand())
377 :
CurDAG->getAtomicLoad(ExtType, SL, MemVT, MVT::i32, Mem->getChain(),
378 Mem->getBasePtr(), Mem->getMemOperand());
389 bool MadeChange =
false;
390 while (Position !=
CurDAG->allnodes_begin()) {
395 switch (
N->getOpcode()) {
398 if (Subtarget->d16PreservesUnusedBits())
403 if (Subtarget->useRealTrue16Insts())
412 CurDAG->RemoveDeadNodes();
418bool AMDGPUDAGToDAGISel::isInlineImmediate(
const SDNode *
N)
const {
424 return TII->isInlineConstant(
C->getAPIntValue());
427 return TII->isInlineConstant(
C->getValueAPF());
437 unsigned OpNo)
const {
438 if (!
N->isMachineOpcode()) {
441 if (
Reg.isVirtual()) {
443 return MRI.getRegClass(
Reg);
446 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
447 return TRI->getPhysRegBaseClass(
Reg);
453 switch (
N->getMachineOpcode()) {
455 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
456 const MCInstrDesc &
Desc =
TII->get(
N->getMachineOpcode());
457 unsigned OpIdx =
Desc.getNumDefs() + OpNo;
458 if (OpIdx >=
Desc.getNumOperands())
461 int16_t RegClass =
TII->getOpRegClassID(
Desc.operands()[OpIdx]);
465 return Subtarget->getRegisterInfo()->getRegClass(RegClass);
467 case AMDGPU::REG_SEQUENCE: {
468 unsigned RCID =
N->getConstantOperandVal(0);
470 Subtarget->getRegisterInfo()->getRegClass(RCID);
472 SDValue SubRegOp =
N->getOperand(OpNo + 1);
474 return Subtarget->getRegisterInfo()->getSubClassWithSubReg(SuperRC,
483 Ops.push_back(NewChain);
484 for (
unsigned i = 1, e =
N->getNumOperands(); i != e; ++i)
485 Ops.push_back(
N->getOperand(i));
488 return CurDAG->MorphNodeTo(
N,
N->getOpcode(),
N->getVTList(),
Ops);
495 assert(
N->getOperand(0).getValueType() == MVT::Other &&
"Expected chain");
498 return glueCopyToOp(
N,
M0,
M0.getValue(1));
501SDNode *AMDGPUDAGToDAGISel::glueCopyToM0LDSInit(
SDNode *
N)
const {
504 if (Subtarget->ldsRequiresM0Init())
506 N,
CurDAG->getSignedTargetConstant(-1, SDLoc(
N), MVT::i32));
509 unsigned Value =
MF.getInfo<SIMachineFunctionInfo>()->getGDSSize();
511 glueCopyToM0(
N,
CurDAG->getTargetConstant(
Value, SDLoc(
N), MVT::i32));
518 SDNode *
Lo =
CurDAG->getMachineNode(
519 AMDGPU::S_MOV_B32,
DL, MVT::i32,
521 SDNode *
Hi =
CurDAG->getMachineNode(
522 AMDGPU::S_MOV_B32,
DL, MVT::i32,
524 const SDValue
Ops[] = {
525 CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID,
DL, MVT::i32),
526 SDValue(
Lo, 0),
CurDAG->getTargetConstant(AMDGPU::sub0,
DL, MVT::i32),
527 SDValue(
Hi, 0),
CurDAG->getTargetConstant(AMDGPU::sub1,
DL, MVT::i32)};
529 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL, VT,
Ops);
532SDNode *AMDGPUDAGToDAGISel::packConstantV2I16(
const SDNode *
N,
537 uint32_t LHSVal, RHSVal;
541 uint32_t
K = (LHSVal & 0xffff) | (RHSVal << 16);
543 isVGPRImm(
N) ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32, SL,
551 EVT VT =
N->getValueType(0);
555 SDValue RegClass =
CurDAG->getTargetConstant(RegClassID,
DL, MVT::i32);
557 if (NumVectorElts == 1) {
558 CurDAG->SelectNodeTo(
N, AMDGPU::COPY_TO_REGCLASS, EltVT,
N->getOperand(0),
563 bool IsGCN =
CurDAG->getSubtarget().getTargetTriple().isAMDGCN();
564 if (IsGCN && Subtarget->has64BitLiterals() && VT.
getSizeInBits() == 64 &&
567 bool AllConst =
true;
569 for (
unsigned I = 0;
I < NumVectorElts; ++
I) {
577 Val = CF->getValueAPF().bitcastToAPInt().getZExtValue();
580 C |= Val << (EltSize *
I);
585 CurDAG->getMachineNode(AMDGPU::S_MOV_B64_IMM_PSEUDO,
DL, VT, CV);
586 CurDAG->SelectNodeTo(
N, AMDGPU::COPY_TO_REGCLASS, VT,
SDValue(Copy, 0),
592 assert(NumVectorElts <= 32 &&
"Vectors with more than 32 elements not "
599 RegSeqArgs[0] =
CurDAG->getTargetConstant(RegClassID,
DL, MVT::i32);
600 bool IsRegSeq =
true;
601 unsigned NOps =
N->getNumOperands();
603 assert(IsGCN || EltSizeInRegs == 1);
604 for (
unsigned i = 0; i < NOps; i++) {
611 i * EltSizeInRegs, EltSizeInRegs)
613 RegSeqArgs[1 + (2 * i)] =
N->getOperand(i);
614 RegSeqArgs[1 + (2 * i) + 1] =
CurDAG->getTargetConstant(
Sub,
DL, MVT::i32);
616 if (NOps != NumVectorElts) {
621 for (
unsigned i = NOps; i < NumVectorElts; ++i) {
623 i * EltSizeInRegs, EltSizeInRegs)
625 RegSeqArgs[1 + (2 * i)] =
SDValue(ImpDef, 0);
626 RegSeqArgs[1 + (2 * i) + 1] =
633 CurDAG->SelectNodeTo(
N, AMDGPU::REG_SEQUENCE,
N->getVTList(), RegSeqArgs);
637 EVT VT =
N->getValueType(0);
641 if (!Subtarget->hasPkMovB32() || !EltVT.
bitsEq(MVT::i32) ||
649 SDValue Src0 = SVN->getOperand(0);
650 SDValue Src1 = SVN->getOperand(1);
654 assert(Src0.getValueType().getVectorNumElements() == 2 && Mask.size() == 2 &&
655 Mask[0] < 4 && Mask[1] < 4);
657 SDValue VSrc0 = Mask[0] < 2 ? Src0 : Src1;
658 SDValue VSrc1 = Mask[1] < 2 ? Src0 : Src1;
659 unsigned Src0SubReg = Mask[0] & 1 ? AMDGPU::sub1 : AMDGPU::sub0;
660 unsigned Src1SubReg = Mask[1] & 1 ? AMDGPU::sub1 : AMDGPU::sub0;
663 Src0SubReg = Src1SubReg;
665 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, VT);
670 Src1SubReg = Src0SubReg;
672 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, VT);
682 if (
N->isDivergent() && Src0SubReg == AMDGPU::sub1 &&
683 Src1SubReg == AMDGPU::sub0) {
699 SDValue Src0OpSelVal =
CurDAG->getTargetConstant(Src0OpSel,
DL, MVT::i32);
700 SDValue Src1OpSelVal =
CurDAG->getTargetConstant(Src1OpSel,
DL, MVT::i32);
703 CurDAG->SelectNodeTo(
N, AMDGPU::V_PK_MOV_B32,
N->getVTList(),
704 {Src0OpSelVal, VSrc0, Src1OpSelVal, VSrc1,
714 CurDAG->getTargetExtractSubreg(Src0SubReg,
DL, EltVT, VSrc0);
716 CurDAG->getTargetExtractSubreg(Src1SubReg,
DL, EltVT, VSrc1);
719 CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID,
DL, MVT::i32),
720 ResultElt0,
CurDAG->getTargetConstant(AMDGPU::sub0,
DL, MVT::i32),
721 ResultElt1,
CurDAG->getTargetConstant(AMDGPU::sub1,
DL, MVT::i32)};
722 CurDAG->SelectNodeTo(
N, TargetOpcode::REG_SEQUENCE, VT,
Ops);
726 unsigned int Opc =
N->getOpcode();
727 if (
N->isMachineOpcode()) {
735 N = glueCopyToM0LDSInit(
N);
745 if (
N->getValueType(0) == MVT::i64) {
746 SelectAddcSubbI64(
N);
750 if (
N->getValueType(0) != MVT::i32)
757 if (
N->getValueType(0) == MVT::i64) {
758 SelectAddcSubbI64(
N);
762 SelectUADDO_USUBO(
N);
765 case AMDGPUISD::FMUL_W_CHAIN: {
766 SelectFMUL_W_CHAIN(
N);
769 case AMDGPUISD::FMA_W_CHAIN: {
770 SelectFMA_W_CHAIN(
N);
776 EVT VT =
N->getValueType(0);
794 N->isDivergent() ?
TRI->getDefaultVectorSuperClassForBitWidth(VecInBits)
806 if (
N->getValueType(0) == MVT::i128) {
807 RC =
CurDAG->getTargetConstant(AMDGPU::SGPR_128RegClassID,
DL, MVT::i32);
808 SubReg0 =
CurDAG->getTargetConstant(AMDGPU::sub0_sub1,
DL, MVT::i32);
809 SubReg1 =
CurDAG->getTargetConstant(AMDGPU::sub2_sub3,
DL, MVT::i32);
810 }
else if (
N->getValueType(0) == MVT::i64) {
811 RC =
CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID,
DL, MVT::i32);
812 SubReg0 =
CurDAG->getTargetConstant(AMDGPU::sub0,
DL, MVT::i32);
813 SubReg1 =
CurDAG->getTargetConstant(AMDGPU::sub1,
DL, MVT::i32);
817 const SDValue Ops[] = { RC,
N->getOperand(0), SubReg0,
818 N->getOperand(1), SubReg1 };
820 N->getValueType(0),
Ops));
826 if (
N->getValueType(0).getSizeInBits() != 64 || isInlineImmediate(
N) ||
827 Subtarget->has64BitLiterals())
832 Imm =
FP->getValueAPF().bitcastToAPInt().getZExtValue();
837 Imm =
C->getZExtValue();
846 case AMDGPUISD::BFE_I32:
847 case AMDGPUISD::BFE_U32: {
873 case AMDGPUISD::DIV_SCALE: {
884 return SelectMUL_LOHI(
N);
895 if (
N->getValueType(0) != MVT::i32)
906 case AMDGPUISD::CVT_PKRTZ_F16_F32:
907 case AMDGPUISD::CVT_PKNORM_I16_F32:
908 case AMDGPUISD::CVT_PKNORM_U16_F32:
909 case AMDGPUISD::CVT_PK_U16_U32:
910 case AMDGPUISD::CVT_PK_I16_I32: {
912 if (
N->getValueType(0) == MVT::i32) {
913 MVT NewVT =
Opc == AMDGPUISD::CVT_PKRTZ_F16_F32 ? MVT::v2f16 : MVT::v2i16;
915 { N->getOperand(0), N->getOperand(1) });
923 SelectINTRINSIC_W_CHAIN(
N);
927 SelectINTRINSIC_WO_CHAIN(
N);
931 SelectINTRINSIC_VOID(
N);
935 SelectWAVE_ADDRESS(
N);
939 SelectSTACKRESTORE(
N);
943 SelectWRITE_REGISTER(
N);
952 if (!Subtarget->hasSDWA())
962 return RHS->getZExtValue() == 0xFF || RHS->getZExtValue() == 0xFFFF;
966 return (RHS->getZExtValue() % 8) == 0;
971bool AMDGPUDAGToDAGISel::isUniformBr(
const SDNode *
N)
const {
974 return Term->getMetadata(
"amdgpu.uniform") ||
975 Term->getMetadata(
"structurizecfg.uniform");
978bool AMDGPUDAGToDAGISel::isUnneededShiftMask(
const SDNode *
N,
979 unsigned ShAmtBits)
const {
982 const APInt &
RHS =
N->getConstantOperandAPInt(1);
983 if (
RHS.countr_one() >= ShAmtBits)
1013 N1 =
Lo.getOperand(1);
1023 if (
CurDAG->isBaseWithConstantOffset(Addr)) {
1038 return "AMDGPU DAG->DAG Pattern Instruction Selection";
1054#ifdef EXPENSIVE_CHECKS
1057 for (
auto &L : LI.getLoopsInPreorder())
1058 assert(L->isLCSSAForm(DT) &&
"Loop is not in LCSSA form!");
1080 }
else if ((Addr.
getOpcode() == AMDGPUISD::DWORDADDR) &&
1082 Base =
CurDAG->getRegister(R600::INDIRECT_BASE_ADDR, MVT::i32);
1096SDValue AMDGPUDAGToDAGISel::getMaterializedScalarImm32(int64_t Val,
1098 SDNode *Mov =
CurDAG->getMachineNode(
1099 AMDGPU::S_MOV_B32,
DL, MVT::i32,
1100 CurDAG->getTargetConstant(Val,
DL, MVT::i32));
1101 return SDValue(Mov, 0);
1104void AMDGPUDAGToDAGISel::SelectAddcSubb(
SDNode *
N) {
1105 SDValue
LHS =
N->getOperand(0);
1106 SDValue
RHS =
N->getOperand(1);
1107 SDValue CI =
N->getOperand(2);
1109 if (
N->isDivergent()) {
1111 : AMDGPU::V_SUBB_U32_e64;
1113 N,
Opc,
N->getVTList(),
1115 CurDAG->getTargetConstant(0, {}, MVT::i1) });
1118 : AMDGPU::S_SUB_CO_PSEUDO;
1119 CurDAG->SelectNodeTo(
N,
Opc,
N->getVTList(), {LHS, RHS, CI});
1123void AMDGPUDAGToDAGISel::SelectAddcSubbI64(
SDNode *
N) {
1125 SDValue
LHS =
N->getOperand(0);
1126 SDValue
RHS =
N->getOperand(1);
1128 unsigned Opcode =
N->getOpcode();
1132 SDValue Sub0 =
CurDAG->getTargetConstant(AMDGPU::sub0,
DL, MVT::i32);
1133 SDValue Sub1 =
CurDAG->getTargetConstant(AMDGPU::sub1,
DL, MVT::i32);
1135 SDNode *Lo0 =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
DL,
1136 MVT::i32,
LHS, Sub0);
1137 SDNode *Hi0 =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
DL,
1138 MVT::i32,
LHS, Sub1);
1140 SDNode *Lo1 =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
DL,
1141 MVT::i32,
RHS, Sub0);
1142 SDNode *Hi1 =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
DL,
1143 MVT::i32,
RHS, Sub1);
1145 SDVTList VTList =
CurDAG->getVTList(MVT::i32,
N->getValueType(1));
1147 static const unsigned NoCarryOpcMap[2][2] = {
1148 {AMDGPU::S_USUBO_PSEUDO, AMDGPU::S_UADDO_PSEUDO},
1149 {AMDGPU::V_SUB_CO_U32_e64, AMDGPU::V_ADD_CO_U32_e64}};
1150 static const unsigned CarryOpcMap[2][2] = {
1151 {AMDGPU::S_SUB_CO_PSEUDO, AMDGPU::S_ADD_CO_PSEUDO},
1152 {AMDGPU::V_SUBB_U32_e64, AMDGPU::V_ADDC_U32_e64}};
1154 bool IsVALU =
N->isDivergent();
1156 unsigned NoCarryOpc = NoCarryOpcMap[IsVALU][IsAdd];
1157 unsigned CarryOpc = CarryOpcMap[IsVALU][IsAdd];
1158 SDValue Clamp =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
1161 if (!ConsumeCarry) {
1163 SDValue
Args[] = {SDValue(Lo0, 0), SDValue(Lo1, 0), Clamp};
1164 AddLo =
CurDAG->getMachineNode(NoCarryOpc,
DL, VTList, Args);
1166 SDValue
Args[] = {SDValue(Lo0, 0), SDValue(Lo1, 0)};
1167 AddLo =
CurDAG->getMachineNode(NoCarryOpc,
DL, VTList, Args);
1171 SDValue
Args[] = {SDValue(Lo0, 0), SDValue(Lo1, 0),
N->getOperand(2),
1173 AddLo =
CurDAG->getMachineNode(CarryOpc,
DL, VTList, Args);
1175 SDValue
Args[] = {SDValue(Lo0, 0), SDValue(Lo1, 0),
N->getOperand(2)};
1176 AddLo =
CurDAG->getMachineNode(CarryOpc,
DL, VTList, Args);
1182 SDValue
Args[] = {SDValue(Hi0, 0), SDValue(Hi1, 0), SDValue(AddLo, 1),
1184 AddHi =
CurDAG->getMachineNode(CarryOpc,
DL, VTList, Args);
1186 SDValue
Args[] = {SDValue(Hi0, 0), SDValue(Hi1, 0), SDValue(AddLo, 1)};
1187 AddHi =
CurDAG->getMachineNode(CarryOpc,
DL, VTList, Args);
1190 unsigned RC = IsVALU ? AMDGPU::VReg_64RegClassID : AMDGPU::SReg_64RegClassID;
1191 SDValue RegSequenceArgs[] = {
CurDAG->getTargetConstant(RC,
DL, MVT::i32),
1192 SDValue(AddLo, 0), Sub0, SDValue(AddHi, 0),
1195 MVT::i64, RegSequenceArgs);
1201void AMDGPUDAGToDAGISel::SelectUADDO_USUBO(
SDNode *
N) {
1206 bool IsVALU =
N->isDivergent();
1208 for (SDNode::user_iterator UI =
N->user_begin(),
E =
N->user_end(); UI !=
E;
1210 if (UI.getUse().getResNo() == 1) {
1211 if (UI->isMachineOpcode()) {
1212 if (UI->getMachineOpcode() !=
1213 (IsAdd ? AMDGPU::S_ADD_CO_PSEUDO : AMDGPU::S_SUB_CO_PSEUDO)) {
1226 unsigned Opc = IsAdd ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_SUB_CO_U32_e64;
1229 N,
Opc,
N->getVTList(),
1230 {N->getOperand(0), N->getOperand(1),
1231 CurDAG->getTargetConstant(0, {}, MVT::i1) });
1233 unsigned Opc = IsAdd ? AMDGPU::S_UADDO_PSEUDO : AMDGPU::S_USUBO_PSEUDO;
1235 CurDAG->SelectNodeTo(
N,
Opc,
N->getVTList(),
1236 {N->getOperand(0), N->getOperand(1)});
1240void AMDGPUDAGToDAGISel::SelectFMA_W_CHAIN(
SDNode *
N) {
1244 SelectVOP3Mods0(
N->getOperand(1),
Ops[1],
Ops[0],
Ops[6],
Ops[7]);
1245 SelectVOP3Mods(
N->getOperand(2),
Ops[3],
Ops[2]);
1246 SelectVOP3Mods(
N->getOperand(3),
Ops[5],
Ops[4]);
1247 Ops[8] =
N->getOperand(0);
1248 Ops[9] =
N->getOperand(4);
1252 bool UseFMAC = Subtarget->hasDLInsts() &&
1256 unsigned Opcode = UseFMAC ? AMDGPU::V_FMAC_F32_e64 : AMDGPU::V_FMA_F32_e64;
1257 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(),
Ops);
1260void AMDGPUDAGToDAGISel::SelectFMUL_W_CHAIN(
SDNode *
N) {
1264 SelectVOP3Mods0(
N->getOperand(1),
Ops[1],
Ops[0],
Ops[4],
Ops[5]);
1265 SelectVOP3Mods(
N->getOperand(2),
Ops[3],
Ops[2]);
1266 Ops[6] =
N->getOperand(0);
1267 Ops[7] =
N->getOperand(3);
1269 CurDAG->SelectNodeTo(
N, AMDGPU::V_MUL_F32_e64,
N->getVTList(),
Ops);
1274void AMDGPUDAGToDAGISel::SelectDIV_SCALE(
SDNode *
N) {
1275 EVT VT =
N->getValueType(0);
1277 assert(VT == MVT::f32 || VT == MVT::f64);
1280 = (VT == MVT::f64) ? AMDGPU::V_DIV_SCALE_F64_e64 : AMDGPU::V_DIV_SCALE_F32_e64;
1285 SelectVOP3BMods0(
N->getOperand(0),
Ops[1],
Ops[0],
Ops[6],
Ops[7]);
1286 SelectVOP3BMods(
N->getOperand(1),
Ops[3],
Ops[2]);
1287 SelectVOP3BMods(
N->getOperand(2),
Ops[5],
Ops[4]);
1293void AMDGPUDAGToDAGISel::SelectMAD_64_32(
SDNode *
N) {
1297 bool UseNoCarry = Subtarget->hasMadNC64_32Insts() && !
N->hasAnyUseOfValue(1);
1298 if (Subtarget->hasMADIntraFwdBug())
1299 Opc =
Signed ? AMDGPU::V_MAD_I64_I32_gfx11_e64
1300 : AMDGPU::V_MAD_U64_U32_gfx11_e64;
1301 else if (UseNoCarry)
1302 Opc =
Signed ? AMDGPU::V_MAD_NC_I64_I32_e64 : AMDGPU::V_MAD_NC_U64_U32_e64;
1304 Opc =
Signed ? AMDGPU::V_MAD_I64_I32_e64 : AMDGPU::V_MAD_U64_U32_e64;
1306 SDValue Clamp =
CurDAG->getTargetConstant(0, SL, MVT::i1);
1307 SDValue
Ops[] = {
N->getOperand(0),
N->getOperand(1),
N->getOperand(2),
1311 MachineSDNode *Mad =
CurDAG->getMachineNode(
Opc, SL, MVT::i64,
Ops);
1322void AMDGPUDAGToDAGISel::SelectMUL_LOHI(
SDNode *
N) {
1327 if (Subtarget->hasMadNC64_32Insts()) {
1328 VTList =
CurDAG->getVTList(MVT::i64);
1329 Opc =
Signed ? AMDGPU::V_MAD_NC_I64_I32_e64 : AMDGPU::V_MAD_NC_U64_U32_e64;
1331 VTList =
CurDAG->getVTList(MVT::i64, MVT::i1);
1332 if (Subtarget->hasMADIntraFwdBug()) {
1333 Opc =
Signed ? AMDGPU::V_MAD_I64_I32_gfx11_e64
1334 : AMDGPU::V_MAD_U64_U32_gfx11_e64;
1336 Opc =
Signed ? AMDGPU::V_MAD_I64_I32_e64 : AMDGPU::V_MAD_U64_U32_e64;
1340 SDValue
Zero =
CurDAG->getTargetConstant(0, SL, MVT::i64);
1341 SDValue Clamp =
CurDAG->getTargetConstant(0, SL, MVT::i1);
1342 SDValue
Ops[] = {
N->getOperand(0),
N->getOperand(1),
Zero, Clamp};
1343 SDNode *Mad =
CurDAG->getMachineNode(
Opc, SL, VTList,
Ops);
1344 if (!SDValue(
N, 0).use_empty()) {
1345 SDValue Sub0 =
CurDAG->getTargetConstant(AMDGPU::sub0, SL, MVT::i32);
1346 SDNode *
Lo =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, SL,
1347 MVT::i32, SDValue(Mad, 0), Sub0);
1350 if (!SDValue(
N, 1).use_empty()) {
1351 SDValue Sub1 =
CurDAG->getTargetConstant(AMDGPU::sub1, SL, MVT::i32);
1352 SDNode *
Hi =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, SL,
1353 MVT::i32, SDValue(Mad, 0), Sub1);
1363 if (!
Base || Subtarget->hasUsableDSOffset() ||
1364 Subtarget->unsafeDSOffsetFoldingEnabled())
1375 if (
CurDAG->isBaseWithConstantOffset(Addr)) {
1379 if (isDSOffsetLegal(N0,
C1->getSExtValue())) {
1388 int64_t ByteOffset =
C->getSExtValue();
1389 if (isDSOffsetLegal(SDValue(), ByteOffset)) {
1390 SDValue
Zero =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1398 if (isDSOffsetLegal(
Sub, ByteOffset)) {
1404 unsigned SubOp = AMDGPU::V_SUB_CO_U32_e32;
1405 if (Subtarget->hasAddNoCarryInsts()) {
1406 SubOp = AMDGPU::V_SUB_U32_e64;
1408 CurDAG->getTargetConstant(0, {}, MVT::i1));
1411 MachineSDNode *MachineSub =
1412 CurDAG->getMachineNode(SubOp,
DL, MVT::i32, Opnds);
1414 Base = SDValue(MachineSub, 0);
1428 if (isDSOffsetLegal(SDValue(), CAddr->getZExtValue())) {
1429 SDValue
Zero =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1430 MachineSDNode *MovZero =
CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32,
1431 DL, MVT::i32, Zero);
1432 Base = SDValue(MovZero, 0);
1433 Offset =
CurDAG->getTargetConstant(CAddr->getZExtValue(),
DL, MVT::i16);
1440 Offset =
CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i16);
1444bool AMDGPUDAGToDAGISel::isDSOffset2Legal(
SDValue Base,
unsigned Offset0,
1446 unsigned Size)
const {
1447 if (Offset0 %
Size != 0 || Offset1 %
Size != 0)
1452 if (!
Base || Subtarget->hasUsableDSOffset() ||
1453 Subtarget->unsafeDSOffsetFoldingEnabled())
1471bool AMDGPUDAGToDAGISel::isFlatScratchBaseLegal(
SDValue Addr)
const {
1477 if (Subtarget->hasSignedScratchOffsets())
1487 ConstantSDNode *ImmOp =
nullptr;
1498bool AMDGPUDAGToDAGISel::isFlatScratchBaseLegalSV(
SDValue Addr)
const {
1504 if (Subtarget->hasSignedScratchOffsets())
1514bool AMDGPUDAGToDAGISel::isFlatScratchBaseLegalSVImm(
SDValue Addr)
const {
1528 (RHSImm->getSExtValue() < 0 && RHSImm->getSExtValue() > -0x40000000)))
1531 auto LHS =
Base.getOperand(0);
1532 auto RHS =
Base.getOperand(1);
1540 return SelectDSReadWrite2(Addr,
Base, Offset0, Offset1, 4);
1546 return SelectDSReadWrite2(Addr,
Base, Offset0, Offset1, 8);
1551 unsigned Size)
const {
1554 if (
CurDAG->isBaseWithConstantOffset(Addr)) {
1558 unsigned OffsetValue0 =
C1->getZExtValue();
1559 unsigned OffsetValue1 = OffsetValue0 +
Size;
1562 if (isDSOffset2Legal(N0, OffsetValue0, OffsetValue1,
Size)) {
1564 Offset0 =
CurDAG->getTargetConstant(OffsetValue0 /
Size,
DL, MVT::i32);
1565 Offset1 =
CurDAG->getTargetConstant(OffsetValue1 /
Size,
DL, MVT::i32);
1570 if (
const ConstantSDNode *
C =
1572 unsigned OffsetValue0 =
C->getZExtValue();
1573 unsigned OffsetValue1 = OffsetValue0 +
Size;
1575 if (isDSOffset2Legal(SDValue(), OffsetValue0, OffsetValue1,
Size)) {
1577 SDValue
Zero =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1585 if (isDSOffset2Legal(
Sub, OffsetValue0, OffsetValue1,
Size)) {
1589 unsigned SubOp = AMDGPU::V_SUB_CO_U32_e32;
1590 if (Subtarget->hasAddNoCarryInsts()) {
1591 SubOp = AMDGPU::V_SUB_U32_e64;
1593 CurDAG->getTargetConstant(0, {}, MVT::i1));
1596 MachineSDNode *MachineSub =
CurDAG->getMachineNode(
1599 Base = SDValue(MachineSub, 0);
1601 CurDAG->getTargetConstant(OffsetValue0 /
Size,
DL, MVT::i32);
1603 CurDAG->getTargetConstant(OffsetValue1 /
Size,
DL, MVT::i32);
1609 unsigned OffsetValue0 = CAddr->getZExtValue();
1610 unsigned OffsetValue1 = OffsetValue0 +
Size;
1612 if (isDSOffset2Legal(SDValue(), OffsetValue0, OffsetValue1,
Size)) {
1613 SDValue
Zero =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1614 MachineSDNode *MovZero =
1615 CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32,
DL, MVT::i32, Zero);
1616 Base = SDValue(MovZero, 0);
1617 Offset0 =
CurDAG->getTargetConstant(OffsetValue0 /
Size,
DL, MVT::i32);
1618 Offset1 =
CurDAG->getTargetConstant(OffsetValue1 /
Size,
DL, MVT::i32);
1626 Offset0 =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1627 Offset1 =
CurDAG->getTargetConstant(1,
DL, MVT::i32);
1637 if (Subtarget->useFlatForGlobal())
1642 Idxen =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
1643 Offen =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
1644 Addr64 =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
1645 SOffset = Subtarget->hasRestrictedSOffset()
1646 ?
CurDAG->getRegister(AMDGPU::SGPR_NULL, MVT::i32)
1647 :
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1649 ConstantSDNode *
C1 =
nullptr;
1651 if (
CurDAG->isBaseWithConstantOffset(Addr)) {
1664 Addr64 =
CurDAG->getTargetConstant(1,
DL, MVT::i1);
1670 Ptr = SDValue(buildSMovImm64(
DL, 0, MVT::v2i32), 0);
1686 Ptr = SDValue(buildSMovImm64(
DL, 0, MVT::v2i32), 0);
1688 Addr64 =
CurDAG->getTargetConstant(1,
DL, MVT::i1);
1692 VAddr =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1702 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
1703 if (
TII->isLegalMUBUFImmOffset(
C1->getZExtValue())) {
1712 SDValue(
CurDAG->getMachineNode(
1713 AMDGPU::S_MOV_B32,
DL, MVT::i32,
1714 CurDAG->getTargetConstant(
C1->getZExtValue(),
DL, MVT::i32)),
1719bool AMDGPUDAGToDAGISel::SelectMUBUFAddr64(
SDValue Addr,
SDValue &SRsrc,
1722 SDValue Ptr, Offen, Idxen, Addr64;
1726 if (!Subtarget->hasAddr64())
1729 if (!SelectMUBUF(Addr, Ptr, VAddr, SOffset,
Offset, Offen, Idxen, Addr64))
1733 if (
C->getSExtValue()) {
1746std::pair<SDValue, SDValue> AMDGPUDAGToDAGISel::foldFrameIndex(
SDValue N)
const {
1751 FI ?
CurDAG->getTargetFrameIndex(FI->getIndex(), FI->getValueType(0)) :
N;
1757 return std::pair(TFI,
CurDAG->getTargetConstant(0,
DL, MVT::i32));
1760bool AMDGPUDAGToDAGISel::SelectMUBUFScratchOffen(
SDNode *Parent,
1767 const SIMachineFunctionInfo *
Info =
MF.getInfo<SIMachineFunctionInfo>();
1769 Rsrc =
CurDAG->getRegister(
Info->getScratchRSrcReg(), MVT::v4i32);
1772 int64_t
Imm = CAddr->getSExtValue();
1773 const int64_t NullPtr =
1776 if (
Imm != NullPtr) {
1779 CurDAG->getTargetConstant(
Imm & ~MaxOffset,
DL, MVT::i32);
1780 MachineSDNode *MovHighBits =
CurDAG->getMachineNode(
1781 AMDGPU::V_MOV_B32_e32,
DL, MVT::i32, HighBits);
1782 VAddr = SDValue(MovHighBits, 0);
1784 SOffset =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1785 ImmOffset =
CurDAG->getTargetConstant(
Imm & MaxOffset,
DL, MVT::i32);
1790 if (
CurDAG->isBaseWithConstantOffset(Addr)) {
1811 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
1812 if (
TII->isLegalMUBUFImmOffset(
C1) &&
1813 (!Subtarget->privateMemoryResourceIsRangeChecked() ||
1814 CurDAG->SignBitIsZero(N0))) {
1815 std::tie(VAddr, SOffset) = foldFrameIndex(N0);
1816 ImmOffset =
CurDAG->getTargetConstant(
C1,
DL, MVT::i32);
1822 std::tie(VAddr, SOffset) = foldFrameIndex(Addr);
1823 ImmOffset =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1831 if (!
Reg.isPhysical())
1833 const auto *RC =
TRI.getPhysRegBaseClass(
Reg);
1834 return RC &&
TRI.isSGPRClass(RC);
1837bool AMDGPUDAGToDAGISel::SelectMUBUFScratchOffset(
SDNode *Parent,
1842 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
1843 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
1845 const SIMachineFunctionInfo *
Info =
MF.getInfo<SIMachineFunctionInfo>();
1850 SRsrc =
CurDAG->getRegister(
Info->getScratchRSrcReg(), MVT::v4i32);
1856 ConstantSDNode *CAddr;
1869 SOffset =
CurDAG->getTargetConstant(0,
DL, MVT::i32);
1874 SRsrc =
CurDAG->getRegister(
Info->getScratchRSrcReg(), MVT::v4i32);
1880bool AMDGPUDAGToDAGISel::SelectMUBUFOffset(
SDValue Addr,
SDValue &SRsrc,
1883 SDValue Ptr, VAddr, Offen, Idxen, Addr64;
1884 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
1886 if (!SelectMUBUF(Addr, Ptr, VAddr, SOffset,
Offset, Offen, Idxen, Addr64))
1905bool AMDGPUDAGToDAGISel::SelectBUFSOffset(
SDValue ByteOffsetNode,
1907 if (Subtarget->hasRestrictedSOffset() &&
isNullConstant(ByteOffsetNode)) {
1908 SOffset =
CurDAG->getRegister(AMDGPU::SGPR_NULL, MVT::i32);
1912 SOffset = ByteOffsetNode;
1930bool AMDGPUDAGToDAGISel::SelectFlatOffsetImpl(
1934 int64_t OffsetVal = 0;
1938 bool CanHaveFlatSegmentOffsetBug =
1939 Subtarget->hasFlatSegmentOffsetBug() &&
1940 FlatVariant == FlatAddrSpace::FLAT &&
1943 if (Subtarget->hasFlatInstOffsets() && !CanHaveFlatSegmentOffsetBug) {
1945 if (isBaseWithConstantOffset64(Addr, N0, N1) &&
1946 (FlatVariant != FlatAddrSpace::FlatScratch ||
1947 isFlatScratchBaseLegal(Addr))) {
1955 if (COffsetVal == 0 || FlatVariant != FlatAddrSpace::FLAT || IsInBounds) {
1956 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
1957 if (
TII->isLegalFLATOffset(COffsetVal, AS, FlatVariant)) {
1959 OffsetVal = COffsetVal;
1974 std::tie(OffsetVal, RemainderOffset) =
1975 TII->splitFlatOffset(COffsetVal, AS, FlatVariant);
1977 SDValue AddOffsetLo =
1978 getMaterializedScalarImm32(
Lo_32(RemainderOffset),
DL);
1979 SDValue Clamp =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
1985 unsigned AddOp = AMDGPU::V_ADD_CO_U32_e32;
1986 if (Subtarget->hasAddNoCarryInsts()) {
1987 AddOp = AMDGPU::V_ADD_U32_e64;
1991 SDValue(
CurDAG->getMachineNode(AddOp,
DL, MVT::i32, Opnds), 0);
1996 CurDAG->getTargetConstant(AMDGPU::sub0,
DL, MVT::i32);
1998 CurDAG->getTargetConstant(AMDGPU::sub1,
DL, MVT::i32);
2000 SDNode *N0Lo =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
2001 DL, MVT::i32, N0, Sub0);
2002 SDNode *N0Hi =
CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
2003 DL, MVT::i32, N0, Sub1);
2005 SDValue AddOffsetHi =
2006 getMaterializedScalarImm32(
Hi_32(RemainderOffset),
DL);
2008 SDVTList VTs =
CurDAG->getVTList(MVT::i32, MVT::i1);
2011 CurDAG->getMachineNode(AMDGPU::V_ADD_CO_U32_e64,
DL, VTs,
2012 {AddOffsetLo, SDValue(N0Lo, 0), Clamp});
2014 SDNode *Addc =
CurDAG->getMachineNode(
2015 AMDGPU::V_ADDC_U32_e64,
DL, VTs,
2016 {AddOffsetHi, SDValue(N0Hi, 0), SDValue(
Add, 1), Clamp});
2018 SDValue RegSequenceArgs[] = {
2019 CurDAG->getTargetConstant(AMDGPU::VReg_64RegClassID,
DL,
2021 SDValue(
Add, 0), Sub0, SDValue(Addc, 0), Sub1};
2023 Addr = SDValue(
CurDAG->getMachineNode(AMDGPU::REG_SEQUENCE,
DL,
2024 MVT::i64, RegSequenceArgs),
2033 Offset =
CurDAG->getSignedTargetConstant(OffsetVal, SDLoc(), MVT::i32);
2037bool AMDGPUDAGToDAGISel::SelectFlatOffset(
SDNode *
N,
SDValue Addr,
2040 return SelectFlatOffsetImpl(
N, Addr, VAddr,
Offset,
2044bool AMDGPUDAGToDAGISel::SelectGlobalOffset(
SDNode *
N,
SDValue Addr,
2047 return SelectFlatOffsetImpl(
N, Addr, VAddr,
Offset,
2051bool AMDGPUDAGToDAGISel::SelectScratchOffset(
SDNode *
N,
SDValue Addr,
2054 return SelectFlatOffsetImpl(
N, Addr, VAddr,
Offset,
2062 if (
Op.getValueType() == MVT::i32)
2077bool AMDGPUDAGToDAGISel::SelectGlobalSAddr(
SDNode *
N,
SDValue Addr,
2080 bool NeedIOffset)
const {
2082 int64_t ImmOffset = 0;
2083 ScaleOffset =
false;
2089 if (isBaseWithConstantOffset64(Addr,
LHS,
RHS)) {
2091 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
2095 FlatAddrSpace::FlatGlobal)) {
2097 ImmOffset = COffsetVal;
2098 }
else if (!
LHS->isDivergent()) {
2099 if (COffsetVal != 0) {
2104 int64_t SplitImmOffset = 0, RemainderOffset = COffsetVal;
2106 std::tie(SplitImmOffset, RemainderOffset) =
TII->splitFlatOffset(
2110 if (Subtarget->hasSignedGVSOffset() ?
isInt<32>(RemainderOffset)
2112 SDNode *VMov =
CurDAG->getMachineNode(
2113 AMDGPU::V_MOV_B32_e32, SL, MVT::i32,
2114 CurDAG->getTargetConstant(
Lo_32(RemainderOffset), SDLoc(),
2116 VOffset = SDValue(VMov, 0);
2118 Offset =
CurDAG->getSignedTargetConstant(SplitImmOffset, SDLoc(),
2129 unsigned NumLiterals =
2130 !
TII->isInlineConstant(APInt(32,
Lo_32(COffsetVal))) +
2131 !
TII->isInlineConstant(APInt(32,
Hi_32(COffsetVal)));
2132 if (Subtarget->getConstantBusLimit(AMDGPU::V_ADD_U32_e64) > NumLiterals)
2141 if (!
LHS->isDivergent()) {
2144 ScaleOffset = SelectScaleOffset(
N,
RHS, Subtarget->hasSignedGVSOffset());
2146 RHS, Subtarget->hasSignedGVSOffset(),
CurDAG)) {
2153 if (!SAddr && !
RHS->isDivergent()) {
2155 ScaleOffset = SelectScaleOffset(
N,
LHS, Subtarget->hasSignedGVSOffset());
2157 LHS, Subtarget->hasSignedGVSOffset(),
CurDAG)) {
2164 Offset =
CurDAG->getSignedTargetConstant(ImmOffset, SDLoc(), MVT::i32);
2169 if (Subtarget->hasScaleOffset() &&
2170 (Addr.
getOpcode() == (Subtarget->hasSignedGVSOffset()
2185 Offset =
CurDAG->getTargetConstant(ImmOffset, SDLoc(), MVT::i32);
2197 CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32, SDLoc(Addr), MVT::i32,
2198 CurDAG->getTargetConstant(0, SDLoc(), MVT::i32));
2199 VOffset = SDValue(VMov, 0);
2200 Offset =
CurDAG->getSignedTargetConstant(ImmOffset, SDLoc(), MVT::i32);
2204bool AMDGPUDAGToDAGISel::SelectGlobalSAddr(
SDNode *
N,
SDValue Addr,
2209 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset,
Offset, ScaleOffset))
2217bool AMDGPUDAGToDAGISel::SelectGlobalSAddrCPol(
SDNode *
N,
SDValue Addr,
2222 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset,
Offset, ScaleOffset))
2227 N->getConstantOperandVal(
N->getNumOperands() - 1) & ~AMDGPU::CPol::SCAL;
2233bool AMDGPUDAGToDAGISel::SelectGlobalSAddrCPolM0(
SDNode *
N,
SDValue Addr,
2239 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset,
Offset, ScaleOffset))
2244 N->getConstantOperandVal(
N->getNumOperands() - 2) & ~AMDGPU::CPol::SCAL;
2250bool AMDGPUDAGToDAGISel::SelectGlobalSAddrGLC(
SDNode *
N,
SDValue Addr,
2255 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset,
Offset, ScaleOffset))
2259 CPol =
CurDAG->getTargetConstant(CPolVal, SDLoc(), MVT::i32);
2263bool AMDGPUDAGToDAGISel::SelectGlobalSAddrNoIOffset(
SDNode *
N,
SDValue Addr,
2268 SDValue DummyOffset;
2269 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset, DummyOffset, ScaleOffset,
2275 N->getConstantOperandVal(
N->getNumOperands() - 1) & ~AMDGPU::CPol::SCAL;
2281bool AMDGPUDAGToDAGISel::SelectGlobalSAddrNoIOffsetM0(
SDNode *
N,
SDValue Addr,
2286 SDValue DummyOffset;
2287 if (!SelectGlobalSAddr(
N, Addr, SAddr, VOffset, DummyOffset, ScaleOffset,
2308 FI->getValueType(0));
2318bool AMDGPUDAGToDAGISel::SelectScratchSAddr(
SDNode *Parent,
SDValue Addr,
2327 int64_t COffsetVal = 0;
2329 if (
CurDAG->isBaseWithConstantOffset(Addr) && isFlatScratchBaseLegal(Addr)) {
2338 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
2341 FlatAddrSpace::FlatScratch)) {
2342 int64_t SplitImmOffset, RemainderOffset;
2343 std::tie(SplitImmOffset, RemainderOffset) =
TII->splitFlatOffset(
2346 COffsetVal = SplitImmOffset;
2350 ? getMaterializedScalarImm32(
Lo_32(RemainderOffset),
DL)
2351 :
CurDAG->getSignedTargetConstant(RemainderOffset,
DL, MVT::i32);
2352 SAddr = SDValue(
CurDAG->getMachineNode(AMDGPU::S_ADD_I32,
DL, MVT::i32,
2357 Offset =
CurDAG->getSignedTargetConstant(COffsetVal,
DL, MVT::i32);
2363bool AMDGPUDAGToDAGISel::checkFlatScratchSVSSwizzleBug(
2365 if (!Subtarget->hasFlatScratchSVSSwizzleBug())
2371 KnownBits VKnown =
CurDAG->computeKnownBits(VAddr);
2378 return (VMax & 3) + (
SMax & 3) >= 4;
2381bool AMDGPUDAGToDAGISel::SelectScratchSVAddr(
SDNode *
N,
SDValue Addr,
2385 int64_t ImmOffset = 0;
2388 SDValue OrigAddr = Addr;
2389 if (isBaseWithConstantOffset64(Addr,
LHS,
RHS)) {
2391 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
2396 ImmOffset = COffsetVal;
2397 }
else if (!
LHS->isDivergent() && COffsetVal > 0) {
2401 int64_t SplitImmOffset, RemainderOffset;
2402 std::tie(SplitImmOffset, RemainderOffset) =
2407 SDNode *VMov =
CurDAG->getMachineNode(
2408 AMDGPU::V_MOV_B32_e32, SL, MVT::i32,
2409 CurDAG->getTargetConstant(RemainderOffset, SDLoc(), MVT::i32));
2410 VAddr = SDValue(VMov, 0);
2412 if (!isFlatScratchBaseLegal(Addr))
2414 if (checkFlatScratchSVSSwizzleBug(VAddr, SAddr, SplitImmOffset))
2416 Offset =
CurDAG->getTargetConstant(SplitImmOffset, SDLoc(), MVT::i32);
2417 CPol =
CurDAG->getTargetConstant(0, SDLoc(), MVT::i32);
2429 if (!
LHS->isDivergent() &&
RHS->isDivergent()) {
2432 }
else if (!
RHS->isDivergent() &&
LHS->isDivergent()) {
2439 if (OrigAddr != Addr) {
2440 if (!isFlatScratchBaseLegalSVImm(OrigAddr))
2443 if (!isFlatScratchBaseLegalSV(OrigAddr))
2447 if (checkFlatScratchSVSSwizzleBug(VAddr, SAddr, ImmOffset))
2450 Offset =
CurDAG->getSignedTargetConstant(ImmOffset, SDLoc(), MVT::i32);
2452 bool ScaleOffset = SelectScaleOffset(
N, VAddr,
true );
2461bool AMDGPUDAGToDAGISel::isSOffsetLegalWithImmOffset(
SDValue *SOffset,
2464 int64_t ImmOffset)
const {
2465 if (!IsBuffer && !Imm32Only && ImmOffset < 0 &&
2467 KnownBits SKnown =
CurDAG->computeKnownBits(*SOffset);
2479 bool IsSigned,
bool IsSMEM)
const {
2480 bool ScaleOffset =
false;
2481 if (!Subtarget->hasScaleOffset() || !
Offset)
2495 (IsSigned &&
Offset.getOpcode() == AMDGPUISD::MUL_I24) ||
2496 Offset.getOpcode() == AMDGPUISD::MUL_U24 ||
2497 (
Offset.isMachineOpcode() &&
2498 Offset.getMachineOpcode() ==
2499 (IsSigned ? AMDGPU::S_MUL_I64_I32_PSEUDO
2500 : AMDGPU::S_MUL_U64_U32_PSEUDO))) {
2502 ScaleOffset =
C->getZExtValue() ==
Size;
2511 if (
Off.getValueType() == MVT::i64) {
2513 if (
Known.countMaxActiveBits() + Bits > 32)
2517 SDNodeFlags
Flags =
Off->getFlags();
2518 SDValue
Idx =
Off.getOperand(0);
2519 if (IsSigned && !
Flags.hasNoSignedWrap() &&
2520 CurDAG->ComputeNumSignBits(Idx) <= Bits)
2522 if (!IsSigned && !
Flags.hasNoUnsignedWrap() &&
2523 CurDAG->computeKnownBits(Idx).countMinLeadingZeros() < Bits)
2534bool AMDGPUDAGToDAGISel::SelectSMRDOffset(
SDNode *
N,
SDValue ByteOffsetNode,
2536 bool Imm32Only,
bool IsBuffer,
2537 bool HasSOffset, int64_t ImmOffset,
2538 bool *ScaleOffset)
const {
2540 "Cannot match both soffset and offset at the same time!");
2545 *ScaleOffset = SelectScaleOffset(
N, ByteOffsetNode,
false ,
2556 *SOffset = ByteOffsetNode;
2557 return isSOffsetLegalWithImmOffset(SOffset, Imm32Only, IsBuffer,
2563 return isSOffsetLegalWithImmOffset(SOffset, Imm32Only, IsBuffer,
2570 SDLoc SL(ByteOffsetNode);
2574 int64_t ByteOffset = IsBuffer ?
C->getZExtValue() :
C->getSExtValue();
2576 *Subtarget, ByteOffset, IsBuffer, HasSOffset);
2577 if (EncodedOffset &&
Offset && !Imm32Only) {
2578 *
Offset =
CurDAG->getSignedTargetConstant(*EncodedOffset, SL, MVT::i32);
2587 if (EncodedOffset &&
Offset && Imm32Only) {
2588 *
Offset =
CurDAG->getTargetConstant(*EncodedOffset, SL, MVT::i32);
2596 SDValue C32Bit =
CurDAG->getTargetConstant(ByteOffset, SL, MVT::i32);
2598 CurDAG->getMachineNode(AMDGPU::S_MOV_B32, SL, MVT::i32, C32Bit), 0);
2605SDValue AMDGPUDAGToDAGISel::Expand32BitAddress(
SDValue Addr)
const {
2613 const SIMachineFunctionInfo *
Info =
MF.getInfo<SIMachineFunctionInfo>();
2614 unsigned AddrHiVal =
Info->get32BitAddressHighBits();
2615 SDValue AddrHi =
CurDAG->getTargetConstant(AddrHiVal, SL, MVT::i32);
2617 const SDValue
Ops[] = {
2618 CurDAG->getTargetConstant(AMDGPU::SReg_64_XEXECRegClassID, SL, MVT::i32),
2620 CurDAG->getTargetConstant(AMDGPU::sub0, SL, MVT::i32),
2621 SDValue(
CurDAG->getMachineNode(AMDGPU::S_MOV_B32, SL, MVT::i32, AddrHi),
2623 CurDAG->getTargetConstant(AMDGPU::sub1, SL, MVT::i32),
2626 return SDValue(
CurDAG->getMachineNode(AMDGPU::REG_SEQUENCE, SL, MVT::i64,
2633bool AMDGPUDAGToDAGISel::SelectSMRDBaseOffset(
SDNode *
N,
SDValue Addr,
2636 bool IsBuffer,
bool HasSOffset,
2638 bool *ScaleOffset)
const {
2640 assert(!Imm32Only && !IsBuffer);
2643 if (!SelectSMRDBaseOffset(
N, Addr,
B,
nullptr,
Offset,
false,
false,
true))
2648 ImmOff =
C->getSExtValue();
2650 return SelectSMRDBaseOffset(
N,
B, SBase, SOffset,
nullptr,
false,
false,
2651 true, ImmOff, ScaleOffset);
2671 if (SelectSMRDOffset(
N, N1, SOffset,
Offset, Imm32Only, IsBuffer, HasSOffset,
2672 ImmOffset, ScaleOffset)) {
2676 if (SelectSMRDOffset(
N, N0, SOffset,
Offset, Imm32Only, IsBuffer, HasSOffset,
2677 ImmOffset, ScaleOffset)) {
2686 bool Imm32Only,
bool *ScaleOffset)
const {
2687 if (SelectSMRDBaseOffset(
N, Addr, SBase, SOffset,
Offset, Imm32Only,
2690 SBase = Expand32BitAddress(SBase);
2695 SBase = Expand32BitAddress(Addr);
2696 *
Offset =
CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
2703bool AMDGPUDAGToDAGISel::SelectSMRDImm(
SDValue Addr,
SDValue &SBase,
2705 return SelectSMRD(
nullptr, Addr, SBase,
nullptr,
2709bool AMDGPUDAGToDAGISel::SelectSMRDImm32(
SDValue Addr,
SDValue &SBase,
2712 return SelectSMRD(
nullptr, Addr, SBase,
nullptr,
2719 if (!SelectSMRD(
N, Addr, SBase, &SOffset,
nullptr,
2720 false, &ScaleOffset))
2724 SDLoc(
N), MVT::i32);
2728bool AMDGPUDAGToDAGISel::SelectSMRDSgprImm(
SDNode *
N,
SDValue Addr,
2733 if (!SelectSMRD(
N, Addr, SBase, &SOffset, &
Offset,
false, &ScaleOffset))
2737 SDLoc(
N), MVT::i32);
2742 return SelectSMRDOffset(
nullptr,
N,
nullptr, &
Offset,
2746bool AMDGPUDAGToDAGISel::SelectSMRDBufferImm32(
SDValue N,
2749 return SelectSMRDOffset(
nullptr,
N,
nullptr, &
Offset,
2753bool AMDGPUDAGToDAGISel::SelectSMRDBufferSgprImm(
SDValue N,
SDValue &SOffset,
2757 return N.getValueType() == MVT::i32 &&
2758 SelectSMRDBaseOffset(
nullptr,
N, SOffset,
2763bool AMDGPUDAGToDAGISel::SelectMOVRELOffset(
SDValue Index,
2768 if (
CurDAG->isBaseWithConstantOffset(Index)) {
2769 SDValue N0 =
Index.getOperand(0);
2770 SDValue N1 =
Index.getOperand(1);
2777 if (
C1->getSExtValue() <= 0 ||
CurDAG->SignBitIsZero(N0) ||
2793SDNode *AMDGPUDAGToDAGISel::getBFE32(
bool IsSigned,
const SDLoc &
DL,
2797 unsigned Opcode = IsSigned ? AMDGPU::V_BFE_I32_e64 : AMDGPU::V_BFE_U32_e64;
2799 SDValue
W =
CurDAG->getTargetConstant(Width,
DL, MVT::i32);
2801 return CurDAG->getMachineNode(Opcode,
DL, MVT::i32, Val,
Off, W);
2803 unsigned Opcode = IsSigned ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32;
2807 uint32_t PackedVal =
Offset | (Width << 16);
2808 SDValue PackedConst =
CurDAG->getTargetConstant(PackedVal,
DL, MVT::i32);
2810 return CurDAG->getMachineNode(Opcode,
DL, MVT::i32, Val, PackedConst);
2813void AMDGPUDAGToDAGISel::SelectS_BFEFromShifts(
SDNode *
N) {
2818 const SDValue &Shl =
N->getOperand(0);
2823 uint32_t BVal =
B->getZExtValue();
2824 uint32_t CVal =
C->getZExtValue();
2826 if (0 < BVal && BVal <= CVal && CVal < 32) {
2836void AMDGPUDAGToDAGISel::SelectS_BFE(
SDNode *
N) {
2837 switch (
N->getOpcode()) {
2839 if (
N->getOperand(0).getOpcode() ==
ISD::SRL) {
2842 const SDValue &Srl =
N->getOperand(0);
2846 if (Shift && Mask) {
2848 uint32_t MaskVal =
Mask->getZExtValue();
2860 if (
N->getOperand(0).getOpcode() ==
ISD::AND) {
2863 const SDValue &
And =
N->getOperand(0);
2867 if (Shift && Mask) {
2869 uint32_t MaskVal =
Mask->getZExtValue() >> ShiftVal;
2878 }
else if (
N->getOperand(0).getOpcode() ==
ISD::SHL) {
2879 SelectS_BFEFromShifts(
N);
2884 if (
N->getOperand(0).getOpcode() ==
ISD::SHL) {
2885 SelectS_BFEFromShifts(
N);
2892 SDValue Src =
N->getOperand(0);
2900 unsigned Width =
cast<VTSDNode>(
N->getOperand(1))->getVT().getSizeInBits();
2910bool AMDGPUDAGToDAGISel::isCBranchSCC(
const SDNode *
N)
const {
2912 if (!
N->hasOneUse())
2915 SDValue
Cond =
N->getOperand(1);
2922 MVT VT =
Cond.getOperand(0).getSimpleValueType();
2926 if (VT == MVT::i64) {
2929 Subtarget->hasScalarCompareEq64();
2932 if ((VT == MVT::f16 || VT == MVT::f32) && Subtarget->hasSALUFloatInsts())
2965void AMDGPUDAGToDAGISel::SelectBRCOND(
SDNode *
N) {
2966 SDValue
Cond =
N->getOperand(1);
2968 if (
Cond.isUndef()) {
2969 CurDAG->SelectNodeTo(
N, AMDGPU::SI_BR_UNDEF, MVT::Other,
2970 N->getOperand(2),
N->getOperand(0));
2974 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
2976 bool UseSCCBr = isCBranchSCC(
N) && isUniformBr(
N);
2977 bool AndExec = !UseSCCBr;
2978 bool Negate =
false;
2981 Cond->getOperand(0)->getOpcode() == AMDGPUISD::SETCC) {
2982 SDValue VCMP =
Cond->getOperand(0);
2996 bool NegatedBallot =
false;
2999 UseSCCBr = !BallotCond->isDivergent();
3000 Negate = Negate ^ NegatedBallot;
3015 UseSCCBr ? (Negate ? AMDGPU::S_CBRANCH_SCC0 : AMDGPU::S_CBRANCH_SCC1)
3016 : (Negate ? AMDGPU::S_CBRANCH_VCCZ : AMDGPU::S_CBRANCH_VCCNZ);
3017 Register CondReg = UseSCCBr ? AMDGPU::SCC :
TRI->getVCC();
3036 Subtarget->isWave32() ? AMDGPU::S_AND_B32 : AMDGPU::S_AND_B64, SL,
3038 CurDAG->getRegister(Subtarget->isWave32() ? AMDGPU::EXEC_LO
3045 SDValue VCC =
CurDAG->getCopyToReg(
N->getOperand(0), SL, CondReg,
Cond);
3046 CurDAG->SelectNodeTo(
N, BrOp, MVT::Other,
3051void AMDGPUDAGToDAGISel::SelectFP_EXTEND(
SDNode *
N) {
3052 if (Subtarget->hasSALUFloatInsts() &&
N->getValueType(0) == MVT::f32 &&
3053 !
N->isDivergent()) {
3054 SDValue Src =
N->getOperand(0);
3055 if (Src.getValueType() == MVT::f16) {
3057 CurDAG->SelectNodeTo(
N, AMDGPU::S_CVT_HI_F32_F16,
N->getVTList(),
3067void AMDGPUDAGToDAGISel::SelectDSAppendConsume(
SDNode *
N,
unsigned IntrID) {
3070 unsigned Opc = IntrID == Intrinsic::amdgcn_ds_append ?
3071 AMDGPU::DS_APPEND : AMDGPU::DS_CONSUME;
3073 SDValue Chain =
N->getOperand(0);
3076 MachineMemOperand *MMO =
M->getMemOperand();
3080 if (
CurDAG->isBaseWithConstantOffset(Ptr)) {
3085 if (isDSOffsetLegal(PtrBase, OffsetVal.
getZExtValue())) {
3086 N = glueCopyToM0(
N, PtrBase);
3087 Offset =
CurDAG->getTargetConstant(OffsetVal, SDLoc(), MVT::i32);
3092 N = glueCopyToM0(
N, Ptr);
3093 Offset =
CurDAG->getTargetConstant(0, SDLoc(), MVT::i32);
3098 CurDAG->getTargetConstant(IsGDS, SDLoc(), MVT::i32),
3103 SDNode *Selected =
CurDAG->SelectNodeTo(
N,
Opc,
N->getVTList(),
Ops);
3109void AMDGPUDAGToDAGISel::SelectDSBvhStackIntrinsic(
SDNode *
N,
unsigned IntrID) {
3112 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
3113 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
3114 Opc = AMDGPU::DS_BVH_STACK_RTN_B32;
3116 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
3117 Opc = AMDGPU::DS_BVH_STACK_PUSH8_POP1_RTN_B32;
3119 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn:
3120 Opc = AMDGPU::DS_BVH_STACK_PUSH8_POP2_RTN_B64;
3123 SDValue
Ops[] = {
N->getOperand(2),
N->getOperand(3),
N->getOperand(4),
3124 N->getOperand(5),
N->getOperand(0)};
3127 MachineMemOperand *MMO =
M->getMemOperand();
3128 SDNode *Selected =
CurDAG->SelectNodeTo(
N,
Opc,
N->getVTList(),
Ops);
3132void AMDGPUDAGToDAGISel::SelectTensorLoadStore(
SDNode *
N,
unsigned IntrID) {
3133 bool IsLoad = IntrID == Intrinsic::amdgcn_tensor_load_to_lds;
3135 IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d4 : AMDGPU::TENSOR_STORE_FROM_LDS_d4;
3143 SDValue Group2 =
N->getOperand(4);
3144 SDValue Group3 =
N->getOperand(5);
3147 Opc = IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d2
3148 : AMDGPU::TENSOR_STORE_FROM_LDS_d2;
3160 (void)
CurDAG->SelectNodeTo(
N,
Opc, MVT::Other, TensorOps);
3165 case Intrinsic::amdgcn_ds_gws_init:
3166 return AMDGPU::DS_GWS_INIT;
3167 case Intrinsic::amdgcn_ds_gws_barrier:
3168 return AMDGPU::DS_GWS_BARRIER;
3169 case Intrinsic::amdgcn_ds_gws_sema_v:
3170 return AMDGPU::DS_GWS_SEMA_V;
3171 case Intrinsic::amdgcn_ds_gws_sema_br:
3172 return AMDGPU::DS_GWS_SEMA_BR;
3173 case Intrinsic::amdgcn_ds_gws_sema_p:
3174 return AMDGPU::DS_GWS_SEMA_P;
3175 case Intrinsic::amdgcn_ds_gws_sema_release_all:
3176 return AMDGPU::DS_GWS_SEMA_RELEASE_ALL;
3182void AMDGPUDAGToDAGISel::SelectDS_GWS(
SDNode *
N,
unsigned IntrID) {
3183 if (!Subtarget->hasGWS() ||
3184 (IntrID == Intrinsic::amdgcn_ds_gws_sema_release_all &&
3185 !Subtarget->hasGWSSemaReleaseAll())) {
3192 const bool HasVSrc =
N->getNumOperands() == 4;
3193 assert(HasVSrc ||
N->getNumOperands() == 3);
3196 SDValue BaseOffset =
N->getOperand(HasVSrc ? 3 : 2);
3199 MachineMemOperand *MMO =
M->getMemOperand();
3212 glueCopyToM0(
N,
CurDAG->getTargetConstant(0, SL, MVT::i32));
3213 ImmOffset = ConstOffset->getZExtValue();
3215 if (
CurDAG->isBaseWithConstantOffset(BaseOffset)) {
3224 =
CurDAG->getMachineNode(AMDGPU::V_READFIRSTLANE_B32, SL, MVT::i32,
3228 =
CurDAG->getMachineNode(AMDGPU::S_LSHL_B32, SL, MVT::i32,
3229 SDValue(SGPROffset, 0),
3230 CurDAG->getTargetConstant(16, SL, MVT::i32));
3231 glueCopyToM0(
N, SDValue(M0Base, 0));
3235 SDValue OffsetField =
CurDAG->getTargetConstant(ImmOffset, SL, MVT::i32);
3239 const MCInstrDesc &InstrDesc =
TII->get(
Opc);
3240 int Data0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::data0);
3246 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3248 SDValue
Data =
N->getOperand(2);
3249 MVT DataVT =
Data.getValueType().getSimpleVT();
3250 if (
TRI->isTypeLegalForClass(*DataRC, DataVT)) {
3252 Ops.push_back(
N->getOperand(2));
3256 const SDValue RegSeqOps[] = {
3258 CurDAG->getTargetConstant(AMDGPU::sub0, SL, MVT::i32),
3260 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, SL, MVT::i32),
3262 CurDAG->getTargetConstant(AMDGPU::sub1, SL, MVT::i32)};
3264 Ops.push_back(SDValue(
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
3265 SL, MVT::v2i32, RegSeqOps),
3270 Ops.push_back(OffsetField);
3271 Ops.push_back(Chain);
3273 SDNode *Selected =
CurDAG->SelectNodeTo(
N,
Opc,
N->getVTList(),
Ops);
3277void AMDGPUDAGToDAGISel::SelectInterpP1F16(
SDNode *
N) {
3278 if (Subtarget->getLDSBankCount() != 16) {
3305 SDValue ToM0 =
CurDAG->getCopyToReg(
CurDAG->getEntryNode(),
DL, AMDGPU::M0,
3306 N->getOperand(5), SDValue());
3308 SDVTList VTs =
CurDAG->getVTList(MVT::f32, MVT::Other);
3311 CurDAG->getMachineNode(AMDGPU::V_INTERP_MOV_F32,
DL, VTs, {
3312 CurDAG->getTargetConstant(2,
DL, MVT::i32),
3318 SDNode *InterpP1LV =
3319 CurDAG->getMachineNode(AMDGPU::V_INTERP_P1LV_F16,
DL, MVT::f32, {
3320 CurDAG->getTargetConstant(0,
DL, MVT::i32),
3324 CurDAG->getTargetConstant(0,
DL, MVT::i32),
3325 SDValue(InterpMov, 0),
3327 CurDAG->getTargetConstant(0,
DL, MVT::i1),
3328 CurDAG->getTargetConstant(0,
DL, MVT::i32),
3329 SDValue(InterpMov, 1)
3332 CurDAG->ReplaceAllUsesOfValueWith(SDValue(
N, 0), SDValue(InterpP1LV, 0));
3335void AMDGPUDAGToDAGISel::SelectINTRINSIC_W_CHAIN(
SDNode *
N) {
3336 unsigned IntrID =
N->getConstantOperandVal(1);
3338 case Intrinsic::amdgcn_ds_append:
3339 case Intrinsic::amdgcn_ds_consume: {
3340 if (
N->getValueType(0) != MVT::i32)
3342 SelectDSAppendConsume(
N, IntrID);
3345 case Intrinsic::amdgcn_ds_bvh_stack_rtn:
3346 case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
3347 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
3348 case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn:
3349 SelectDSBvhStackIntrinsic(
N, IntrID);
3351 case Intrinsic::amdgcn_init_whole_wave:
3352 CurDAG->getMachineFunction()
3353 .getInfo<SIMachineFunctionInfo>()
3354 ->setInitWholeWave();
3361void AMDGPUDAGToDAGISel::SelectINTRINSIC_WO_CHAIN(
SDNode *
N) {
3362 unsigned IntrID =
N->getConstantOperandVal(0);
3363 unsigned Opcode = AMDGPU::INSTRUCTION_LIST_END;
3364 SDNode *ConvGlueNode =
N->getGluedNode();
3370 CurDAG->getMachineNode(TargetOpcode::CONVERGENCECTRL_GLUE, {},
3371 MVT::Glue, SDValue(ConvGlueNode, 0));
3373 ConvGlueNode =
nullptr;
3376 case Intrinsic::amdgcn_wqm:
3377 Opcode = AMDGPU::WQM;
3379 case Intrinsic::amdgcn_softwqm:
3380 Opcode = AMDGPU::SOFT_WQM;
3382 case Intrinsic::amdgcn_wwm:
3383 case Intrinsic::amdgcn_strict_wwm:
3384 Opcode = AMDGPU::STRICT_WWM;
3386 case Intrinsic::amdgcn_strict_wqm:
3387 Opcode = AMDGPU::STRICT_WQM;
3389 case Intrinsic::amdgcn_interp_p1_f16:
3390 SelectInterpP1F16(
N);
3392 case Intrinsic::amdgcn_permlane16_swap:
3393 case Intrinsic::amdgcn_permlane32_swap: {
3394 if ((IntrID == Intrinsic::amdgcn_permlane16_swap &&
3395 !Subtarget->hasPermlane16Swap()) ||
3396 (IntrID == Intrinsic::amdgcn_permlane32_swap &&
3397 !Subtarget->hasPermlane32Swap())) {
3402 Opcode = IntrID == Intrinsic::amdgcn_permlane16_swap
3403 ? AMDGPU::V_PERMLANE16_SWAP_B32_e64
3404 : AMDGPU::V_PERMLANE32_SWAP_B32_e64;
3408 NewOps.push_back(SDValue(ConvGlueNode, 0));
3410 bool FI =
N->getConstantOperandVal(3);
3411 NewOps[2] =
CurDAG->getTargetConstant(
3414 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(), NewOps);
3422 if (Opcode != AMDGPU::INSTRUCTION_LIST_END) {
3423 SDValue Src =
N->getOperand(1);
3424 CurDAG->SelectNodeTo(
N, Opcode,
N->getVTList(), {Src});
3429 NewOps.push_back(SDValue(ConvGlueNode, 0));
3430 CurDAG->MorphNodeTo(
N,
N->getOpcode(),
N->getVTList(), NewOps);
3434void AMDGPUDAGToDAGISel::SelectINTRINSIC_VOID(
SDNode *
N) {
3435 unsigned IntrID =
N->getConstantOperandVal(1);
3437 case Intrinsic::amdgcn_ds_gws_init:
3438 case Intrinsic::amdgcn_ds_gws_barrier:
3439 case Intrinsic::amdgcn_ds_gws_sema_v:
3440 case Intrinsic::amdgcn_ds_gws_sema_br:
3441 case Intrinsic::amdgcn_ds_gws_sema_p:
3442 case Intrinsic::amdgcn_ds_gws_sema_release_all:
3443 SelectDS_GWS(
N, IntrID);
3445 case Intrinsic::amdgcn_tensor_load_to_lds:
3446 case Intrinsic::amdgcn_tensor_store_from_lds:
3447 SelectTensorLoadStore(
N, IntrID);
3456void AMDGPUDAGToDAGISel::SelectWAVE_ADDRESS(
SDNode *
N) {
3457 SDValue Log2WaveSize =
3458 CurDAG->getTargetConstant(Subtarget->getWavefrontSizeLog2(), SDLoc(
N), MVT::i32);
3459 CurDAG->SelectNodeTo(
N, AMDGPU::S_LSHR_B32,
N->getVTList(),
3460 {N->getOperand(0), Log2WaveSize});
3463void AMDGPUDAGToDAGISel::SelectSTACKRESTORE(
SDNode *
N) {
3464 SDValue SrcVal =
N->getOperand(1);
3477 SDValue Log2WaveSize =
CurDAG->getTargetConstant(
3478 Subtarget->getWavefrontSizeLog2(), SL, MVT::i32);
3480 if (
N->isDivergent()) {
3481 SrcVal = SDValue(
CurDAG->getMachineNode(AMDGPU::V_READFIRSTLANE_B32, SL,
3486 CopyVal = SDValue(
CurDAG->getMachineNode(AMDGPU::S_LSHL_B32, SL, MVT::i32,
3487 {SrcVal, Log2WaveSize}),
3491 SDValue CopyToSP =
CurDAG->getCopyToReg(
N->getOperand(0), SL,
SP, CopyVal);
3492 CurDAG->ReplaceAllUsesOfValueWith(SDValue(
N, 0), CopyToSP);
3495void AMDGPUDAGToDAGISel::SelectWRITE_REGISTER(
SDNode *
N) {
3502 CurDAG->getMachineFunction());
3506 "invalid register \"" + Twine(RegStr->
getString()) +
3507 "\" for llvm.write_register",
3508 Fn,
N->getDebugLoc()));
3520 }
else if (VT == MVT::i32) {
3521 CopyVal = SDValue(
CurDAG->getMachineNode(AMDGPU::V_READFIRSTLANE_B32, SL,
3527 CurDAG->getTargetExtractSubreg(AMDGPU::sub0, SL, MVT::i32, SrcVal);
3529 CurDAG->getTargetExtractSubreg(AMDGPU::sub1, SL, MVT::i32, SrcVal);
3531 CurDAG->getMachineNode(AMDGPU::V_READFIRSTLANE_B32, SL, MVT::i32,
Lo),
3534 CurDAG->getMachineNode(AMDGPU::V_READFIRSTLANE_B32, SL, MVT::i32,
Hi),
3536 CopyVal = emitRegSequence(*
CurDAG, AMDGPU::SReg_64RegClassID, VT, {
Lo,
Hi},
3537 {AMDGPU::sub0, AMDGPU::sub1}, SL);
3541 CurDAG->ReplaceAllUsesOfValueWith(SDValue(
N, 0), CopyToReg);
3544bool AMDGPUDAGToDAGISel::SelectVOP3ModsImpl(
SDValue In,
SDValue &Src,
3546 bool IsCanonicalizing,
3547 bool AllowAbs)
const {
3553 Src = Src.getOperand(0);
3554 }
else if (Src.getOpcode() ==
ISD::FSUB && IsCanonicalizing) {
3558 if (
LHS &&
LHS->isZero()) {
3560 Src = Src.getOperand(1);
3564 if (AllowAbs && Src.getOpcode() ==
ISD::FABS) {
3566 Src = Src.getOperand(0);
3579 if (IsCanonicalizing)
3594 EVT VT = Src.getValueType();
3596 (VT != MVT::i32 && VT != MVT::v2i32 && VT != MVT::i64))
3603 auto ReplaceSrc = [&]() -> SDValue {
3605 return Src.getOperand(0);
3608 SDValue
Index = Src->getOperand(1);
3610 Src.getValueType(),
LHS, Index);
3636 if (SelectVOP3ModsImpl(In, Src, Mods,
true,
3638 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3645bool AMDGPUDAGToDAGISel::SelectVOP3ModsNonCanonicalizing(
3648 if (SelectVOP3ModsImpl(In, Src, Mods,
false,
3650 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3657bool AMDGPUDAGToDAGISel::SelectVOP3BMods(
SDValue In,
SDValue &Src,
3660 if (SelectVOP3ModsImpl(In, Src, Mods,
3663 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3670bool AMDGPUDAGToDAGISel::SelectVOP3NoMods(
SDValue In,
SDValue &Src)
const {
3678bool AMDGPUDAGToDAGISel::SelectVINTERPModsImpl(
SDValue In,
SDValue &Src,
3682 if (SelectVOP3ModsImpl(In, Src, Mods,
3687 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3694bool AMDGPUDAGToDAGISel::SelectVINTERPMods(
SDValue In,
SDValue &Src,
3696 return SelectVINTERPModsImpl(In, Src, SrcMods,
false);
3699bool AMDGPUDAGToDAGISel::SelectVINTERPModsHi(
SDValue In,
SDValue &Src,
3701 return SelectVINTERPModsImpl(In, Src, SrcMods,
true);
3704bool AMDGPUDAGToDAGISel::SelectVOP3Mods0(
SDValue In,
SDValue &Src,
3708 Clamp =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3709 Omod =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3711 return SelectVOP3Mods(In, Src, SrcMods);
3714bool AMDGPUDAGToDAGISel::SelectVOP3BMods0(
SDValue In,
SDValue &Src,
3718 Clamp =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3719 Omod =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3721 return SelectVOP3BMods(In, Src, SrcMods);
3724bool AMDGPUDAGToDAGISel::SelectVOP3OMods(
SDValue In,
SDValue &Src,
3729 Clamp =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3730 Omod =
CurDAG->getTargetConstant(0,
DL, MVT::i1);
3735bool AMDGPUDAGToDAGISel::SelectVOP3PModsPkFmaOpSel0(
SDValue In,
SDValue &Src,
3737 return SelectVOP3PMods(In, Src, SrcMods,
false,
3738 Subtarget->hasPkF32InvalidOpSel() &&
3739 In.getValueType() == MVT::v2f32);
3742bool AMDGPUDAGToDAGISel::SelectVOP3PModsPkAddMulOpSel0(
SDValue In,
SDValue &Src,
3744 if (!SelectVOP3PMods(In, Src, SrcMods))
3747 return !Subtarget->hasPkF32InvalidOpSel() ||
3748 In.getValueType() != MVT::v2f32 ||
3753bool AMDGPUDAGToDAGISel::SelectVOP3PMods(
SDValue In,
SDValue &Src,
3755 bool NoOpSel0)
const {
3762 Src = Src.getOperand(0);
3766 bool HasOpSel = Src.getValueSizeInBits() != 128;
3769 (!IsDOT || !Subtarget->hasDOTOpSelHazard()) &&
3770 (!NoOpSel0 || !isLoEltExtractHi(Src))) {
3771 unsigned VecMods = Mods;
3773 SDValue
Lo = stripBitcast(Src.getOperand(0));
3774 SDValue
Hi = stripBitcast(Src.getOperand(1));
3777 Lo = stripBitcast(
Lo.getOperand(0));
3782 Hi = stripBitcast(
Hi.getOperand(0));
3794 unsigned VecSize = Src.getValueSizeInBits();
3795 Lo = stripExtractLoElt(
Lo);
3796 Hi = stripExtractLoElt(
Hi);
3798 if (
Lo.getValueSizeInBits() > VecSize) {
3799 Lo =
CurDAG->getTargetExtractSubreg(
3800 (VecSize > 32) ? AMDGPU::sub0_sub1 : AMDGPU::sub0, SDLoc(In),
3804 if (
Hi.getValueSizeInBits() > VecSize) {
3805 Hi =
CurDAG->getTargetExtractSubreg(
3806 (VecSize > 32) ? AMDGPU::sub0_sub1 : AMDGPU::sub0, SDLoc(In),
3810 assert(
Lo.getValueSizeInBits() <= VecSize &&
3811 Hi.getValueSizeInBits() <= VecSize);
3813 if (
Lo ==
Hi && !isInlineImmediate(
Lo.getNode())) {
3817 if (VecSize ==
Lo.getValueSizeInBits()) {
3819 }
else if (VecSize == 32) {
3820 Src = createVOP3PSrc32FromLo16(
Lo, Src,
CurDAG, Subtarget);
3822 assert((
Lo.getValueSizeInBits() == 32 && VecSize == 64) ||
3823 (
Lo.getValueSizeInBits() == 64 && VecSize == 128));
3826 SDValue
Undef = SDValue(
3827 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, SL,
3828 Lo.getValueType()), 0);
3829 const SIRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3834 auto RC =
Lo->isDivergent() ?
TRI->getVGPRClassForBitWidth(VecSize)
3835 :
TRI->getSGPRClassForBitWidth(VecSize);
3836 unsigned NumRegs =
Lo.getValueSizeInBits() == 32 ? 1 : 2;
3837 const SDValue
Ops[] = {
3838 CurDAG->getTargetConstant(RC->getID(), SL, MVT::i32),
Lo,
3839 CurDAG->getTargetConstant(
TRI->getSubRegFromChannel(0, NumRegs), SL,
3844 CurDAG->getTargetConstant(
3845 TRI->getSubRegFromChannel(NumRegs, NumRegs), SL, MVT::i32)};
3847 Src = SDValue(
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, SL,
3848 Src.getValueType(),
Ops), 0);
3852 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3858 .bitcastToAPInt().getZExtValue();
3860 Src =
CurDAG->getTargetConstant(
Lit, SDLoc(In), MVT::i64);
3861 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3868 Src.getNumOperands() == 2) {
3873 assert(Src.getValueSizeInBits() != 128 &&
3874 "<2 x 64> VECTOR_SHUFFLE should not be legal.");
3877 ArrayRef<int>
Mask = SVN->getMask();
3879 if (Mask[0] < 2 && Mask[1] < 2 && (!NoOpSel0 || Mask[0] != 1)) {
3881 SDValue ShuffleSrc = SVN->getOperand(0);
3894 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3902 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3906bool AMDGPUDAGToDAGISel::SelectVOP3PModsDOT(
SDValue In,
SDValue &Src,
3908 return SelectVOP3PMods(In, Src, SrcMods,
true);
3911bool AMDGPUDAGToDAGISel::SelectVOP3PNoModsDOT(
SDValue In,
SDValue &Src)
const {
3912 SDValue SrcTmp, SrcModsTmp;
3913 SelectVOP3PMods(In, SrcTmp, SrcModsTmp,
true);
3922bool AMDGPUDAGToDAGISel::SelectVOP3PModsF32(
SDValue In,
SDValue &Src,
3924 SelectVOP3Mods(In, Src, SrcMods);
3927 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3931bool AMDGPUDAGToDAGISel::SelectVOP3PNoModsF32(
SDValue In,
SDValue &Src)
const {
3932 SDValue SrcTmp, SrcModsTmp;
3933 SelectVOP3PModsF32(In, SrcTmp, SrcModsTmp);
3942bool AMDGPUDAGToDAGISel::SelectWMMAOpSelVOP3PMods(
SDValue In,
3945 assert(
C->getAPIntValue().getBitWidth() == 1 &&
"expected i1 value");
3948 unsigned SrcVal =
C->getZExtValue();
3952 Src =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
3959 unsigned DstRegClass;
3961 switch (Elts.
size()) {
3963 DstRegClass = AMDGPU::VReg_256RegClassID;
3967 DstRegClass = AMDGPU::VReg_128RegClassID;
3971 DstRegClass = AMDGPU::VReg_64RegClassID;
3979 Ops.push_back(
CurDAG->getTargetConstant(DstRegClass,
DL, MVT::i32));
3980 for (
unsigned i = 0; i < Elts.
size(); ++i) {
3981 Ops.push_back(Elts[i]);
3982 Ops.push_back(
CurDAG->getTargetConstant(
3985 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL, DstTy,
Ops);
3992 assert(
"unhandled Reg sequence size" &&
3993 (Elts.
size() == 8 || Elts.
size() == 16));
3997 for (
unsigned i = 0; i < Elts.
size(); i += 2) {
3998 SDValue LoSrc = stripExtractLoElt(stripBitcast(Elts[i]));
4003 if (Subtarget->useRealTrue16Insts()) {
4007 SDValue
Undef = SDValue(
4008 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, MVT::i16),
4011 emitRegSequence(*
CurDAG, AMDGPU::VGPR_32RegClassID, MVT::i32,
4012 {Elts[i],
Undef}, {AMDGPU::lo16, AMDGPU::hi16},
DL);
4013 Elts[i + 1] = emitRegSequence(*
CurDAG, AMDGPU::VGPR_32RegClassID,
4014 MVT::i32, {Elts[i + 1],
Undef},
4015 {AMDGPU::lo16, AMDGPU::hi16},
DL);
4017 SDValue PackLoLo =
CurDAG->getTargetConstant(0x05040100,
DL, MVT::i32);
4019 CurDAG->getMachineNode(AMDGPU::V_PERM_B32_e64,
DL, MVT::i32,
4020 {Elts[i + 1], Elts[i], PackLoLo});
4021 PackedElts.
push_back(SDValue(Packed, 0));
4024 return buildRegSequence32(PackedElts,
DL);
4030 unsigned ElementSize)
const {
4031 if (ElementSize == 16)
4032 return buildRegSequence16(Elts,
DL);
4033 if (ElementSize == 32)
4034 return buildRegSequence32(Elts,
DL);
4038void AMDGPUDAGToDAGISel::selectWMMAModsNegAbs(
unsigned ModOpcode,
4042 unsigned ElementSize)
const {
4047 for (
auto El : Elts) {
4050 NegAbsElts.
push_back(El->getOperand(0));
4052 if (Elts.size() != NegAbsElts.
size()) {
4054 Src = SDValue(buildRegSequence(Elts,
DL, ElementSize), 0);
4058 Src = SDValue(buildRegSequence(NegAbsElts,
DL, ElementSize), 0);
4064 Src = SDValue(buildRegSequence(Elts,
DL, ElementSize), 0);
4072 std::function<
bool(
SDValue)> ModifierCheck) {
4076 for (
unsigned i = 0; i < F16Pair->getNumOperands(); ++i) {
4077 SDValue ElF16 = stripBitcast(F16Pair->getOperand(i));
4078 if (!ModifierCheck(ElF16))
4085bool AMDGPUDAGToDAGISel::SelectWMMAModsF16Neg(
SDValue In,
SDValue &Src,
4103 Src = SDValue(buildRegSequence16(EltsF16, SDLoc(In)), 0);
4113 SDValue ElV2f16 = stripBitcast(BV->
getOperand(i));
4122 Src = SDValue(buildRegSequence32(EltsV2F16, SDLoc(In)), 0);
4128 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4132bool AMDGPUDAGToDAGISel::SelectWMMAModsF16NegAbs(
SDValue In,
SDValue &Src,
4143 if (EltsF16.
empty())
4153 selectWMMAModsNegAbs(ModOpcode, Mods, EltsF16, Src, SDLoc(In), 16);
4161 SDValue ElV2f16 = stripBitcast(BV->
getOperand(i));
4163 if (EltsV2F16.
empty())
4172 selectWMMAModsNegAbs(ModOpcode, Mods, EltsV2F16, Src, SDLoc(In), 32);
4175 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4179bool AMDGPUDAGToDAGISel::SelectWMMAModsF32NegAbs(
SDValue In,
SDValue &Src,
4188 SDValue ElF32 = stripBitcast(BV->
getOperand(0));
4189 unsigned ModOpcode =
4192 SDValue ElF32 = stripBitcast(BV->
getOperand(i));
4200 selectWMMAModsNegAbs(ModOpcode, Mods, EltsF32, Src, SDLoc(In), 32);
4203 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4207bool AMDGPUDAGToDAGISel::SelectWMMAVISrc(
SDValue In,
SDValue &Src)
const {
4209 BitVector UndefElements;
4211 if (isInlineImmediate(
Splat.getNode())) {
4213 unsigned Imm =
C->getAPIntValue().getSExtValue();
4214 Src =
CurDAG->getTargetConstant(
Imm, SDLoc(In), MVT::i32);
4218 unsigned Imm =
C->getValueAPF().bitcastToAPInt().getSExtValue();
4219 Src =
CurDAG->getTargetConstant(
Imm, SDLoc(In), MVT::i32);
4227 SDValue SplatSrc32 = stripBitcast(In);
4229 if (SDValue Splat32 = SplatSrc32BV->getSplatValue()) {
4230 SDValue SplatSrc16 = stripBitcast(Splat32);
4232 if (SDValue
Splat = SplatSrc16BV->getSplatValue()) {
4233 const SIInstrInfo *
TII = Subtarget->getInstrInfo();
4234 std::optional<APInt> RawValue;
4236 RawValue =
C->getValueAPF().bitcastToAPInt();
4238 RawValue =
C->getAPIntValue();
4240 if (RawValue.has_value()) {
4241 EVT VT =
In.getValueType().getScalarType();
4247 if (
TII->isInlineConstant(FloatVal)) {
4248 Src =
CurDAG->getTargetConstant(RawValue.value(), SDLoc(In),
4253 if (
TII->isInlineConstant(RawValue.value())) {
4254 Src =
CurDAG->getTargetConstant(RawValue.value(), SDLoc(In),
4267 if (
CurDAG->isConstantIntBuildVectorOrConstantInt(SplatSrc32)) {
4272 int64_t LoImm = Lo32->getAPIntValue().getSExtValue();
4273 int64_t HiImm = Hi32->getAPIntValue().getSExtValue();
4274 int64_t Imm64I = (HiImm << 32) + LoImm;
4276 if (!isInlineImmediate(APInt(64, Imm64I)))
4279 }
else if (Imm64I != Imm64)
4283 Src =
CurDAG->getTargetConstant(Imm64, SDLoc(In), MVT::i64);
4290bool AMDGPUDAGToDAGISel::SelectSWMMACIndex8(
SDValue In,
SDValue &Src,
4296 const llvm::SDValue &ShiftSrc =
In.getOperand(0);
4305 IndexKey =
CurDAG->getTargetConstant(
Key, SDLoc(In), MVT::i32);
4309bool AMDGPUDAGToDAGISel::SelectSWMMACIndex16(
SDValue In,
SDValue &Src,
4315 const llvm::SDValue &ShiftSrc =
In.getOperand(0);
4324 IndexKey =
CurDAG->getTargetConstant(
Key, SDLoc(In), MVT::i32);
4328bool AMDGPUDAGToDAGISel::SelectSWMMACIndex32(
SDValue In,
SDValue &Src,
4336 const SDValue &ExtendSrc =
In.getOperand(0);
4340 const SDValue &CastSrc =
In.getOperand(0);
4344 if (Zero &&
Zero->getZExtValue() == 0)
4350 const SDValue &ExtractVecEltSrc = InI32.
getOperand(0);
4355 Src = ExtractVecEltSrc;
4359 IndexKey =
CurDAG->getTargetConstant(
Key, SDLoc(In), MVT::i32);
4363bool AMDGPUDAGToDAGISel::SelectVOP3OpSel(
SDValue In,
SDValue &Src,
4367 if (!Subtarget->useRealTrue16Insts() &&
In.getValueSizeInBits() == 16 &&
4370 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4374bool AMDGPUDAGToDAGISel::SelectVOP3OpSelMods(
SDValue In,
SDValue &Src,
4377 if (!SelectVOP3ModsImpl(In, Src, Mods,
true,
4381 if (!Subtarget->useRealTrue16Insts() &&
In.getValueSizeInBits() == 16 &&
4385 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4398 Op =
Op.getOperand(0);
4400 IsExtractHigh =
false;
4403 if (!Low16 || !Low16->isZero())
4405 Op = stripBitcast(
Op.getOperand(1));
4406 if (
Op.getValueType() != MVT::bf16)
4411 if (
Op.getValueType() != MVT::i32)
4416 if (Mask->getZExtValue() == 0xffff0000) {
4417 IsExtractHigh =
true;
4418 return Op.getOperand(0);
4427 return Op.getOperand(0);
4436bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixModsImpl(
SDValue In,
SDValue &Src,
4440 SelectVOP3ModsImpl(In, Src, Mods);
4442 bool IsExtractHigh =
false;
4444 Src.getOperand(0).getValueType() == VT) {
4445 Src = Src.getOperand(0);
4446 }
else if (VT == MVT::bf16) {
4454 if (Src.getValueType() != VT &&
4455 (VT != MVT::bf16 || Src.getValueType() != MVT::i32))
4458 Src = stripBitcast(Src);
4464 SelectVOP3ModsImpl(Src, Src, ModsTmp);
4479 if (Src.getValueSizeInBits() == 16) {
4488 Src.getOperand(0).getValueType() == MVT::i32) {
4489 Src = Src.getOperand(0);
4493 if (Subtarget->useRealTrue16Insts())
4495 Src = createVOP3PSrc32FromLo16(Src, In,
CurDAG, Subtarget);
4496 }
else if (IsExtractHigh)
4502bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixModsExt(
SDValue In,
SDValue &Src,
4505 if (!SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::f16))
4507 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4511bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixMods(
SDValue In,
SDValue &Src,
4514 SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::f16);
4515 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4519bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixModsExtNeg(
SDValue In,
SDValue &Src,
4522 if (!SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::f16))
4529bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixModsNeg(
SDValue In,
SDValue &Src,
4532 SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::f16);
4538bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixBF16ModsExt(
SDValue In,
SDValue &Src,
4541 if (!SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::bf16))
4543 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4547bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixBF16Mods(
SDValue In,
SDValue &Src,
4550 SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::bf16);
4551 SrcMods =
CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
4555bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixBF16ModsExtNeg(
4558 if (!SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::bf16))
4565bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixBF16ModsNeg(
SDValue In,
SDValue &Src,
4568 SelectVOP3PMadMixModsImpl(In, Src, Mods, MVT::bf16);
4578 unsigned NumOpcodes = 0;
4591 const uint8_t SrcBits[3] = { 0xf0, 0xcc, 0xaa };
4594 if (
C->isAllOnes()) {
4604 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4618 if (Src.size() == 3) {
4624 if (
C->isAllOnes()) {
4626 for (
unsigned I = 0;
I < Src.size(); ++
I) {
4627 if (Src[
I] ==
LHS) {
4639 Bits = SrcBits[Src.size()];
4644 switch (In.getOpcode()) {
4652 if (!getOperandBits(
LHS, LHSBits) ||
4653 !getOperandBits(
RHS, RHSBits)) {
4654 Src = std::move(Backup);
4655 return std::make_pair(0, 0);
4676 uint8_t LHSBitsOrig = LHSBits;
4677 uint8_t RHSBitsOrig = RHSBits;
4681 NumOpcodes += LHSOp.first;
4682 LHSBits = LHSOp.second;
4689 NumOpcodes += RHSOp.first;
4690 RHSBits = RHSOp.second;
4694 auto dependsOnSlot = [](
uint8_t TT,
int Slot) ->
bool {
4695 if (Slot < 0 || Slot > 2)
4697 const uint8_t Masks[3] = {0x0f, 0x33, 0x55};
4698 const int Shifts[3] = {4, 2, 1};
4699 return ((TT ^ (TT >> Shifts[Slot])) & Masks[Slot]) != 0;
4705 const uint8_t SrcBitsConst[3] = {0xf0, 0xcc, 0xaa};
4712 NegatedInner =
Op.getOperand(0);
4713 for (
int I = 0;
I < (int)S.size();
I++) {
4714 if (Bits == SrcBitsConst[
I] && S[
I] ==
Op)
4716 if (IsNegationOp && Bits == (
uint8_t)~SrcBitsConst[
I] &&
4717 S[
I] == NegatedInner)
4728 for (
int I = 0;
I < (int)SrcAfterLHS.
size() &&
I < 3;
I++) {
4729 if (
I < (
int)Src.size() && Src[
I] != SrcAfterLHS[
I] &&
4730 dependsOnSlot(LHSBits,
I)) {
4739 if (!Stale && !RHSOp.first) {
4740 int Slot = findSlot(RHSBitsOrig,
RHS, SrcBeforeRecurse);
4742 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4748 if (!Stale && !LHSOp.first) {
4749 int Slot = findSlot(LHSBitsOrig,
LHS, SrcBeforeRecurse);
4751 (Slot >= (
int)Src.size() || Src[Slot] != SrcBeforeRecurse[Slot]))
4756 Src = std::move(SrcBeforeRecurse);
4757 LHSBits = LHSBitsOrig;
4758 RHSBits = RHSBitsOrig;
4764 return std::make_pair(0, 0);
4768 switch (In.getOpcode()) {
4770 TTbl = LHSBits & RHSBits;
4773 TTbl = LHSBits | RHSBits;
4776 TTbl = LHSBits ^ RHSBits;
4782 return std::make_pair(NumOpcodes + 1, TTbl);
4789 unsigned NumOpcodes;
4791 std::tie(NumOpcodes, TTbl) =
BitOp3_Op(In, Src);
4795 if (NumOpcodes < 2 || Src.empty())
4801 if (NumOpcodes < 4 && !In->isDivergent())
4804 if (NumOpcodes == 2 &&
In.getValueType() == MVT::i32) {
4809 (
In.getOperand(0).getOpcode() ==
In.getOpcode() ||
4810 In.getOperand(1).getOpcode() ==
In.getOpcode()))
4824 while (Src.size() < 3)
4825 Src.push_back(Src[0]);
4831 Tbl =
CurDAG->getTargetConstant(TTbl, SDLoc(In), MVT::i32);
4837 return CurDAG->getPOISON(MVT::i32);
4840 return CurDAG->getUNDEF(MVT::i32);
4844 return CurDAG->getConstant(
C->getZExtValue() << 16, SL, MVT::i32);
4849 return CurDAG->getConstant(
4850 C->getValueAPF().bitcastToAPInt().getZExtValue() << 16, SL, MVT::i32);
4860bool AMDGPUDAGToDAGISel::isVGPRImm(
const SDNode *
N)
const {
4861 assert(
CurDAG->getTarget().getTargetTriple().isAMDGCN());
4863 const SIRegisterInfo *SIRI = Subtarget->getRegisterInfo();
4864 const SIInstrInfo *SII = Subtarget->getInstrInfo();
4867 bool AllUsesAcceptSReg =
true;
4869 Limit < 10 && U !=
E; ++U, ++Limit) {
4871 getOperandRegClass(
U->getUser(),
U->getOperandNo());
4879 if (RC != &AMDGPU::VS_32RegClass && RC != &AMDGPU::VS_64RegClass &&
4880 RC != &AMDGPU::VS_64_Align2RegClass) {
4881 AllUsesAcceptSReg =
false;
4882 SDNode *
User =
U->getUser();
4883 if (
User->isMachineOpcode()) {
4884 unsigned Opc =
User->getMachineOpcode();
4885 const MCInstrDesc &
Desc = SII->get(
Opc);
4886 if (
Desc.isCommutable()) {
4887 unsigned OpIdx =
Desc.getNumDefs() +
U->getOperandNo();
4890 unsigned CommutedOpNo = CommuteIdx1 -
Desc.getNumDefs();
4892 getOperandRegClass(
U->getUser(), CommutedOpNo);
4893 if (CommutedRC == &AMDGPU::VS_32RegClass ||
4894 CommutedRC == &AMDGPU::VS_64RegClass ||
4895 CommutedRC == &AMDGPU::VS_64_Align2RegClass)
4896 AllUsesAcceptSReg =
true;
4904 if (!AllUsesAcceptSReg)
4908 return !AllUsesAcceptSReg && (Limit < 10);
4914 bool IsModified =
false;
4920 while (Position !=
CurDAG->allnodes_end()) {
4927 if (ResNode !=
Node) {
4933 CurDAG->RemoveDeadNodes();
4934 }
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.
SmallVector< MachineOperand, 4 > Cond
MachineRegisterInfo & MRI
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,...
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 LLVM_READONLY const TargetRegisterClass * getSGPRClassForBitWidth(unsigned BitWidth)
static unsigned getSubRegFromChannel(uint64_t Channel, uint64_t NumRegs=1)
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.
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
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.
@ Known
Known to have no common set bits.
@ 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.