42#include "llvm/IR/IntrinsicsRISCV.h"
56#define DEBUG_TYPE "riscv-lower"
62 cl::desc(
"Give the maximum size (in number of nodes) of the web of "
63 "instructions that we will consider for VW expansion"),
68 cl::desc(
"Allow the formation of VW_W operations (e.g., "
69 "VWADD_W) with splat constants"),
74 cl::desc(
"Set the minimum number of repetitions of a divisor to allow "
75 "transformation to multiplications by the reciprocal"),
80 cl::desc(
"Give the maximum number of instructions that we will "
81 "use for creating a floating-point immediate value"),
86 cl::desc(
"Swap add and addi in cases where the add may "
87 "be combined with a shift"),
98 !Subtarget.hasStdExtF()) {
99 errs() <<
"Hard-float 'f' ABI can't be used for a target that "
100 "doesn't support the F instruction set extension (ignoring "
104 !Subtarget.hasStdExtD()) {
105 errs() <<
"Hard-float 'd' ABI can't be used for a target that "
106 "doesn't support the D instruction set extension (ignoring "
125 MVT XLenVT = Subtarget.getXLenVT();
130 if (Subtarget.hasStdExtZfhmin())
132 if (Subtarget.hasStdExtZfbfmin() || Subtarget.hasVendorXAndesBFHCvt())
134 if (Subtarget.hasStdExtF())
136 if (Subtarget.hasStdExtD())
138 if (Subtarget.hasStdExtZhinxmin())
140 if (Subtarget.hasStdExtZfinx())
142 if (Subtarget.hasStdExtZdinx()) {
143 if (Subtarget.is64Bit())
150 MVT::nxv1i1, MVT::nxv2i1, MVT::nxv4i1, MVT::nxv8i1,
151 MVT::nxv16i1, MVT::nxv32i1, MVT::nxv64i1};
153 MVT::nxv1i8, MVT::nxv2i8, MVT::nxv4i8, MVT::nxv8i8, MVT::nxv16i8,
154 MVT::nxv32i8, MVT::nxv64i8, MVT::nxv1i16, MVT::nxv2i16, MVT::nxv4i16,
155 MVT::nxv8i16, MVT::nxv16i16, MVT::nxv32i16, MVT::nxv1i32, MVT::nxv2i32,
156 MVT::nxv4i32, MVT::nxv8i32, MVT::nxv16i32, MVT::nxv1i64, MVT::nxv2i64,
157 MVT::nxv4i64, MVT::nxv8i64};
159 MVT::nxv1f16, MVT::nxv2f16, MVT::nxv4f16,
160 MVT::nxv8f16, MVT::nxv16f16, MVT::nxv32f16};
162 MVT::nxv1bf16, MVT::nxv2bf16, MVT::nxv4bf16,
163 MVT::nxv8bf16, MVT::nxv16bf16, MVT::nxv32bf16};
165 MVT::nxv1f32, MVT::nxv2f32, MVT::nxv4f32, MVT::nxv8f32, MVT::nxv16f32};
167 MVT::nxv1f64, MVT::nxv2f64, MVT::nxv4f64, MVT::nxv8f64};
169 MVT::riscv_nxv1i8x2, MVT::riscv_nxv1i8x3, MVT::riscv_nxv1i8x4,
170 MVT::riscv_nxv1i8x5, MVT::riscv_nxv1i8x6, MVT::riscv_nxv1i8x7,
171 MVT::riscv_nxv1i8x8, MVT::riscv_nxv2i8x2, MVT::riscv_nxv2i8x3,
172 MVT::riscv_nxv2i8x4, MVT::riscv_nxv2i8x5, MVT::riscv_nxv2i8x6,
173 MVT::riscv_nxv2i8x7, MVT::riscv_nxv2i8x8, MVT::riscv_nxv4i8x2,
174 MVT::riscv_nxv4i8x3, MVT::riscv_nxv4i8x4, MVT::riscv_nxv4i8x5,
175 MVT::riscv_nxv4i8x6, MVT::riscv_nxv4i8x7, MVT::riscv_nxv4i8x8,
176 MVT::riscv_nxv8i8x2, MVT::riscv_nxv8i8x3, MVT::riscv_nxv8i8x4,
177 MVT::riscv_nxv8i8x5, MVT::riscv_nxv8i8x6, MVT::riscv_nxv8i8x7,
178 MVT::riscv_nxv8i8x8, MVT::riscv_nxv16i8x2, MVT::riscv_nxv16i8x3,
179 MVT::riscv_nxv16i8x4, MVT::riscv_nxv32i8x2};
181 if (Subtarget.hasVInstructions()) {
182 auto addRegClassForRVV = [
this](
MVT VT) {
186 if (VT.getVectorMinNumElements() < MinElts)
189 unsigned Size = VT.getSizeInBits().getKnownMinValue();
192 RC = &RISCV::VRRegClass;
194 RC = &RISCV::VRM2RegClass;
196 RC = &RISCV::VRM4RegClass;
198 RC = &RISCV::VRM8RegClass;
205 for (
MVT VT : BoolVecVTs)
206 addRegClassForRVV(VT);
207 for (
MVT VT : IntVecVTs) {
208 if (VT.getVectorElementType() == MVT::i64 &&
209 !Subtarget.hasVInstructionsI64())
211 addRegClassForRVV(VT);
214 if (Subtarget.hasVInstructionsF16Minimal() ||
215 Subtarget.hasVendorXAndesVPackFPH())
216 for (
MVT VT : F16VecVTs)
217 addRegClassForRVV(VT);
219 if (Subtarget.hasVInstructionsBF16Minimal() ||
220 Subtarget.hasVendorXAndesVBFHCvt())
221 for (
MVT VT : BF16VecVTs)
222 addRegClassForRVV(VT);
224 if (Subtarget.hasVInstructionsF32())
225 for (
MVT VT : F32VecVTs)
226 addRegClassForRVV(VT);
228 if (Subtarget.hasVInstructionsF64())
229 for (
MVT VT : F64VecVTs)
230 addRegClassForRVV(VT);
232 if (Subtarget.useRVVForFixedLengthVectors()) {
233 auto addRegClassForFixedVectors = [
this](
MVT VT) {
240 if (useRVVForFixedLengthVectorVT(VT))
241 addRegClassForFixedVectors(VT);
244 if (useRVVForFixedLengthVectorVT(VT))
245 addRegClassForFixedVectors(VT);
305 if (!(Subtarget.hasVendorXCValu() && !Subtarget.is64Bit())) {
315 if (!Subtarget.hasVendorXTHeadBb() && !Subtarget.hasVendorXqcibm() &&
316 !Subtarget.hasVendorXAndesPerf())
321 if (!Subtarget.hasStdExtZbb() && !Subtarget.hasVendorXTHeadBb() &&
322 !Subtarget.hasVendorXqcibm() && !Subtarget.hasVendorXAndesPerf() &&
323 !(Subtarget.hasVendorXCValu() && !Subtarget.is64Bit()))
326 if (Subtarget.hasStdExtZilsd() && !Subtarget.is64Bit()) {
331 if (Subtarget.is64Bit()) {
338 if (!Subtarget.hasStdExtZbb())
344 if (!Subtarget.hasStdExtZmmul()) {
346 }
else if (Subtarget.is64Bit()) {
353 if (!Subtarget.hasStdExtM()) {
356 }
else if (Subtarget.is64Bit()) {
358 {MVT::i8, MVT::i16, MVT::i32},
Custom);
368 if (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) {
369 if (Subtarget.is64Bit())
371 }
else if (Subtarget.hasVendorXTHeadBb()) {
372 if (Subtarget.is64Bit())
375 }
else if (Subtarget.hasVendorXCVbitmanip() && !Subtarget.is64Bit()) {
384 (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb() ||
385 Subtarget.hasVendorXTHeadBb())
389 if ((Subtarget.hasVendorXCVbitmanip() || Subtarget.hasVendorXqcibm()) &&
390 !Subtarget.is64Bit()) {
396 if (Subtarget.hasStdExtZbkb())
400 if (Subtarget.hasStdExtZbb() ||
401 (Subtarget.hasVendorXCValu() && !Subtarget.is64Bit())) {
406 if (Subtarget.hasCTZLike()) {
407 if (Subtarget.is64Bit())
413 if (!Subtarget.hasCPOPLike()) {
416 if (Subtarget.is64Bit())
423 if (Subtarget.hasCLZLike()) {
427 if (Subtarget.is64Bit() && Subtarget.hasStdExtZbb())
433 if (Subtarget.hasVendorXCValu() && !Subtarget.is64Bit()) {
435 }
else if (Subtarget.hasShortForwardBranchOpt()) {
438 }
else if (Subtarget.is64Bit()) {
442 if (!Subtarget.useCCMovInsn() && !Subtarget.hasVendorXTHeadCondMov() &&
443 !Subtarget.hasVendorXqcicm() && !Subtarget.hasVendorXqcics())
446 if (Subtarget.hasVendorXqcia() && !Subtarget.is64Bit()) {
455 static const unsigned FPLegalNodeTypes[] = {
456 ISD::FMINNUM, ISD::FMAXNUM, ISD::FMINIMUMNUM,
457 ISD::FMAXIMUMNUM, ISD::LRINT, ISD::LLRINT,
469 static const unsigned FPOpToExpand[] = {
470 ISD::FSIN, ISD::FCOS, ISD::FSINCOS, ISD::FPOW,
473 static const unsigned FPRndMode[] = {
474 ISD::FCEIL, ISD::FFLOOR, ISD::FTRUNC, ISD::FRINT, ISD::FROUND,
477 static const unsigned ZfhminZfbfminPromoteOps[] = {
478 ISD::FMINNUM, ISD::FMAXNUM, ISD::FMAXIMUMNUM,
485 ISD::FTRUNC, ISD::FRINT, ISD::FROUND,
488 if (Subtarget.hasStdExtZfbfmin()) {
503 if (Subtarget.hasStdExtZfhminOrZhinxmin()) {
504 if (Subtarget.hasStdExtZfhOrZhinx()) {
511 if (Subtarget.hasStdExtZfa())
516 for (
auto Op : {ISD::LROUND, ISD::LLROUND, ISD::LRINT, ISD::LLRINT,
537 ISD::FNEARBYINT, MVT::f16,
538 Subtarget.hasStdExtZfh() && Subtarget.hasStdExtZfa() ?
Legal :
Promote);
540 ISD::FCOS, ISD::FSIN, ISD::FSINCOS, ISD::FEXP,
541 ISD::FEXP2, ISD::FEXP10, ISD::FLOG, ISD::FLOG2,
542 ISD::FLOG10, ISD::FLDEXP, ISD::FFREXP},
554 if (Subtarget.is64Bit())
558 if (Subtarget.hasStdExtFOrZfinx()) {
580 if (Subtarget.hasStdExtZfa()) {
589 if (Subtarget.hasStdExtFOrZfinx() && Subtarget.is64Bit())
592 if (Subtarget.hasStdExtDOrZdinx()) {
595 if (!Subtarget.is64Bit())
598 if (Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
599 !Subtarget.is64Bit()) {
604 if (Subtarget.hasStdExtZfa()) {
610 if (Subtarget.is64Bit())
639 if (Subtarget.is64Bit()) {
646 if (Subtarget.hasStdExtFOrZfinx()) {
672 if (Subtarget.is64Bit())
682 if (Subtarget.is64Bit()) {
689 if (Subtarget.is64Bit())
692 if (Subtarget.hasVendorXMIPSCBOP())
694 else if (Subtarget.hasStdExtZicbop())
697 if (Subtarget.hasStdExtA()) {
699 if (Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas())
703 }
else if (Subtarget.hasForcedAtomics()) {
718 if (Subtarget.hasVInstructions()) {
727 {MVT::i8, MVT::i16},
Custom);
728 if (Subtarget.is64Bit())
738 static const unsigned IntegerVPOps[] = {
739 ISD::VP_ADD, ISD::VP_SUB, ISD::VP_MUL,
740 ISD::VP_SDIV, ISD::VP_UDIV, ISD::VP_SREM,
741 ISD::VP_UREM, ISD::VP_AND, ISD::VP_OR,
742 ISD::VP_XOR, ISD::VP_SRA, ISD::VP_SRL,
743 ISD::VP_SHL, ISD::VP_REDUCE_ADD, ISD::VP_REDUCE_AND,
744 ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR, ISD::VP_REDUCE_SMAX,
745 ISD::VP_REDUCE_SMIN, ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN,
746 ISD::VP_MERGE, ISD::VP_SELECT, ISD::VP_FP_TO_SINT,
747 ISD::VP_FP_TO_UINT, ISD::VP_SETCC, ISD::VP_SIGN_EXTEND,
748 ISD::VP_ZERO_EXTEND, ISD::VP_TRUNCATE, ISD::VP_SMIN,
749 ISD::VP_SMAX, ISD::VP_UMIN, ISD::VP_UMAX,
750 ISD::VP_ABS, ISD::EXPERIMENTAL_VP_REVERSE, ISD::EXPERIMENTAL_VP_SPLICE,
751 ISD::VP_SADDSAT, ISD::VP_UADDSAT, ISD::VP_SSUBSAT,
752 ISD::VP_USUBSAT, ISD::VP_CTTZ_ELTS, ISD::VP_CTTZ_ELTS_ZERO_UNDEF,
753 ISD::EXPERIMENTAL_VP_SPLAT};
755 static const unsigned FloatingPointVPOps[] = {
756 ISD::VP_FADD, ISD::VP_FSUB, ISD::VP_FMUL,
757 ISD::VP_FDIV, ISD::VP_FNEG, ISD::VP_FABS,
758 ISD::VP_FMA, ISD::VP_REDUCE_FADD, ISD::VP_REDUCE_SEQ_FADD,
759 ISD::VP_REDUCE_FMIN, ISD::VP_REDUCE_FMAX, ISD::VP_MERGE,
760 ISD::VP_SELECT, ISD::VP_SINT_TO_FP, ISD::VP_UINT_TO_FP,
761 ISD::VP_SETCC, ISD::VP_FP_ROUND, ISD::VP_FP_EXTEND,
762 ISD::VP_SQRT, ISD::VP_FMINNUM, ISD::VP_FMAXNUM,
763 ISD::VP_FCEIL, ISD::VP_FFLOOR, ISD::VP_FROUND,
764 ISD::VP_FROUNDEVEN, ISD::VP_FCOPYSIGN, ISD::VP_FROUNDTOZERO,
765 ISD::VP_FRINT, ISD::VP_FNEARBYINT, ISD::VP_IS_FPCLASS,
766 ISD::VP_FMINIMUM, ISD::VP_FMAXIMUM, ISD::VP_LRINT,
767 ISD::VP_LLRINT, ISD::VP_REDUCE_FMINIMUM,
768 ISD::VP_REDUCE_FMAXIMUM, ISD::EXPERIMENTAL_VP_SPLAT};
770 static const unsigned IntegerVecReduceOps[] = {
771 ISD::VECREDUCE_ADD, ISD::VECREDUCE_AND, ISD::VECREDUCE_OR,
772 ISD::VECREDUCE_XOR, ISD::VECREDUCE_SMAX, ISD::VECREDUCE_SMIN,
773 ISD::VECREDUCE_UMAX, ISD::VECREDUCE_UMIN};
775 static const unsigned FloatingPointVecReduceOps[] = {
776 ISD::VECREDUCE_FADD, ISD::VECREDUCE_SEQ_FADD, ISD::VECREDUCE_FMIN,
777 ISD::VECREDUCE_FMAX, ISD::VECREDUCE_FMINIMUM, ISD::VECREDUCE_FMAXIMUM};
779 static const unsigned FloatingPointLibCallOps[] = {
780 ISD::FREM, ISD::FPOW, ISD::FCOS, ISD::FSIN, ISD::FSINCOS, ISD::FEXP,
781 ISD::FEXP2, ISD::FEXP10, ISD::FLOG, ISD::FLOG2, ISD::FLOG10};
783 if (!Subtarget.is64Bit()) {
792 ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR,
793 ISD::VP_REDUCE_SMAX, ISD::VP_REDUCE_SMIN,
794 ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN},
798 for (
MVT VT : BoolVecVTs) {
824 {ISD::VECREDUCE_AND, ISD::VECREDUCE_OR, ISD::VECREDUCE_XOR}, VT,
828 {ISD::VP_REDUCE_AND, ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR}, VT,
852 ISD::VP_TRUNCATE, ISD::VP_SETCC},
869 for (
MVT VT : IntVecVTs) {
880 if (VT.getVectorElementType() == MVT::i64 && !Subtarget.hasStdExtV())
930 {ISD::VP_LOAD, ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
931 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER, ISD::VP_SCATTER},
956 if (Subtarget.hasStdExtZvkb()) {
964 if (Subtarget.hasStdExtZvbb()) {
968 ISD::VP_CTTZ_ZERO_UNDEF, ISD::VP_CTPOP},
974 ISD::VP_CTTZ_ZERO_UNDEF, ISD::VP_CTPOP},
983 ISD::VP_CTLZ_ZERO_UNDEF, ISD::VP_CTTZ_ZERO_UNDEF},
991 for (
MVT VT : VecTupleVTs) {
1012 static const unsigned ZvfhminZvfbfminPromoteOps[] = {
1040 ISD::VECREDUCE_FMIN,
1041 ISD::VECREDUCE_FMAX,
1042 ISD::VECREDUCE_FMINIMUM,
1043 ISD::VECREDUCE_FMAXIMUM};
1046 static const unsigned ZvfhminZvfbfminPromoteVPOps[] = {
1052 ISD::VP_REDUCE_FMIN,
1053 ISD::VP_REDUCE_FMAX,
1061 ISD::VP_FROUNDTOZERO,
1067 ISD::VP_REDUCE_FMINIMUM,
1068 ISD::VP_REDUCE_FMAXIMUM};
1071 const auto SetCommonVFPActions = [&](
MVT VT) {
1087 {ISD::FMINNUM, ISD::FMAXNUM, ISD::FMAXIMUMNUM, ISD::FMINIMUMNUM}, VT,
1092 ISD::FROUNDEVEN, ISD::FRINT, ISD::FNEARBYINT,
1109 {ISD::VP_LOAD, ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1110 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER, ISD::VP_SCATTER},
1146 const auto SetCommonVFPExtLoadTruncStoreActions =
1148 for (
auto SmallVT : SmallerVTs) {
1156 const auto SetCommonPromoteToF32Actions = [&](
MVT VT) {
1184 ISD::MGATHER, ISD::MSCATTER, ISD::VP_LOAD,
1185 ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1186 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1209 if (Subtarget.hasVInstructionsF16()) {
1210 for (
MVT VT : F16VecVTs) {
1213 SetCommonVFPActions(VT);
1215 }
else if (Subtarget.hasVInstructionsF16Minimal()) {
1216 for (
MVT VT : F16VecVTs) {
1219 SetCommonPromoteToF32Actions(VT);
1223 if (Subtarget.hasVInstructionsBF16Minimal()) {
1224 for (
MVT VT : BF16VecVTs) {
1227 SetCommonPromoteToF32Actions(VT);
1231 if (Subtarget.hasVInstructionsF32()) {
1232 for (
MVT VT : F32VecVTs) {
1235 SetCommonVFPActions(VT);
1236 SetCommonVFPExtLoadTruncStoreActions(VT, F16VecVTs);
1237 SetCommonVFPExtLoadTruncStoreActions(VT, BF16VecVTs);
1241 if (Subtarget.hasVInstructionsF64()) {
1242 for (
MVT VT : F64VecVTs) {
1245 SetCommonVFPActions(VT);
1246 SetCommonVFPExtLoadTruncStoreActions(VT, F16VecVTs);
1247 SetCommonVFPExtLoadTruncStoreActions(VT, BF16VecVTs);
1248 SetCommonVFPExtLoadTruncStoreActions(VT, F32VecVTs);
1252 if (Subtarget.useRVVForFixedLengthVectors()) {
1254 if (!useRVVForFixedLengthVectorVT(VT))
1299 {ISD::VECREDUCE_AND, ISD::VECREDUCE_OR, ISD::VECREDUCE_XOR}, VT,
1303 {ISD::VP_REDUCE_AND, ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR}, VT,
1330 ISD::VP_SETCC, ISD::VP_TRUNCATE},
1354 {ISD::MLOAD, ISD::MSTORE, ISD::MGATHER, ISD::MSCATTER}, VT,
Custom);
1357 ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1358 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1390 ISD::VECREDUCE_SMIN, ISD::VECREDUCE_UMAX,
1391 ISD::VECREDUCE_UMIN},
1396 if (Subtarget.hasStdExtZvkb())
1399 if (Subtarget.hasStdExtZvbb()) {
1423 if (!useRVVForFixedLengthVectorVT(VT))
1446 ISD::MGATHER, ISD::MSCATTER},
1449 ISD::VP_SCATTER, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1450 ISD::EXPERIMENTAL_VP_STRIDED_STORE},
1459 !Subtarget.hasVInstructionsF16()) {
1469 if (Subtarget.hasStdExtZfhmin()) {
1495 if (Subtarget.hasStdExtZfbfmin()) {
1521 ISD::FMA, ISD::FMINNUM, ISD::FMAXNUM,
1523 ISD::FMAXIMUM, ISD::FMINIMUM},
1527 ISD::FROUNDEVEN, ISD::FRINT, ISD::LRINT,
1528 ISD::LLRINT, ISD::LROUND, ISD::LLROUND,
1554 if (Subtarget.is64Bit())
1556 if (Subtarget.hasStdExtZfhminOrZhinxmin())
1558 if (Subtarget.hasStdExtZfbfmin())
1560 if (Subtarget.hasStdExtFOrZfinx())
1562 if (Subtarget.hasStdExtDOrZdinx())
1567 if (Subtarget.hasStdExtA())
1570 if (Subtarget.hasForcedAtomics()) {
1573 {ISD::ATOMIC_CMP_SWAP, ISD::ATOMIC_SWAP, ISD::ATOMIC_LOAD_ADD,
1574 ISD::ATOMIC_LOAD_SUB, ISD::ATOMIC_LOAD_AND, ISD::ATOMIC_LOAD_OR,
1575 ISD::ATOMIC_LOAD_XOR, ISD::ATOMIC_LOAD_NAND, ISD::ATOMIC_LOAD_MIN,
1576 ISD::ATOMIC_LOAD_MAX, ISD::ATOMIC_LOAD_UMIN, ISD::ATOMIC_LOAD_UMAX},
1580 if (Subtarget.hasVendorXTHeadMemIdx()) {
1589 if (Subtarget.is64Bit()) {
1596 if (Subtarget.hasVendorXCVmem() && !Subtarget.is64Bit()) {
1607 if (Subtarget.hasStdExtZvqdotq() && Subtarget.getELen() >= 64) {
1608 static const unsigned MLAOps[] = {ISD::PARTIAL_REDUCE_SMLA,
1609 ISD::PARTIAL_REDUCE_UMLA,
1610 ISD::PARTIAL_REDUCE_SUMLA};
1617 if (Subtarget.useRVVForFixedLengthVectors()) {
1619 if (VT.getVectorElementType() != MVT::i32 ||
1620 !useRVVForFixedLengthVectorVT(VT))
1630 if (Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh()) {
1636 const Align FunctionAlignment(Subtarget.hasStdExtZca() ? 2 : 4);
1648 if (Subtarget.hasStdExtFOrZfinx())
1651 if (Subtarget.hasStdExtZbb())
1654 if ((Subtarget.hasStdExtZbs() && Subtarget.is64Bit()) ||
1655 Subtarget.hasVInstructions())
1658 if (Subtarget.hasStdExtZbkb())
1661 if (Subtarget.hasStdExtFOrZfinx())
1664 if (Subtarget.hasVInstructions())
1667 ISD::VP_GATHER, ISD::VP_SCATTER,
ISD::SRA,
1670 ISD::VP_STORE, ISD::VP_TRUNCATE, ISD::EXPERIMENTAL_VP_REVERSE,
1676 if (Subtarget.hasVendorXTHeadMemPair())
1678 if (Subtarget.useRVVForFixedLengthVectors())
1698 Subtarget.getMaxStoresPerMemmove(
true);
1710 if (Subtarget.hasVInstructions() &&
1721bool RISCVTargetLowering::shouldExpandGetVectorLength(
EVT TripCountVT,
1723 bool IsScalable)
const {
1730 if (TripCountVT != MVT::i32 && TripCountVT != Subtarget.
getXLenVT())
1748 return !Subtarget.hasVInstructions() ||
1756 auto &
DL =
I.getDataLayout();
1758 auto SetRVVLoadStoreInfo = [&](
unsigned PtrOp,
bool IsStore,
1759 bool IsUnitStrided,
bool UsePtrVal =
false) {
1764 Info.ptrVal =
I.getArgOperand(PtrOp);
1766 Info.fallbackAddressSpace =
1767 I.getArgOperand(PtrOp)->getType()->getPointerAddressSpace();
1771 MemTy =
I.getArgOperand(0)->getType();
1774 MemTy =
I.getType();
1789 Info.align =
DL.getABITypeAlign(MemTy);
1799 if (
I.hasMetadata(LLVMContext::MD_nontemporal))
1806 case Intrinsic::riscv_masked_atomicrmw_xchg:
1807 case Intrinsic::riscv_masked_atomicrmw_add:
1808 case Intrinsic::riscv_masked_atomicrmw_sub:
1809 case Intrinsic::riscv_masked_atomicrmw_nand:
1810 case Intrinsic::riscv_masked_atomicrmw_max:
1811 case Intrinsic::riscv_masked_atomicrmw_min:
1812 case Intrinsic::riscv_masked_atomicrmw_umax:
1813 case Intrinsic::riscv_masked_atomicrmw_umin:
1814 case Intrinsic::riscv_masked_cmpxchg:
1821 Info.memVT = MVT::i32;
1822 Info.ptrVal =
I.getArgOperand(0);
1824 Info.align =
Align(4);
1828 case Intrinsic::riscv_seg2_load_mask:
1829 case Intrinsic::riscv_seg3_load_mask:
1830 case Intrinsic::riscv_seg4_load_mask:
1831 case Intrinsic::riscv_seg5_load_mask:
1832 case Intrinsic::riscv_seg6_load_mask:
1833 case Intrinsic::riscv_seg7_load_mask:
1834 case Intrinsic::riscv_seg8_load_mask:
1835 case Intrinsic::riscv_sseg2_load_mask:
1836 case Intrinsic::riscv_sseg3_load_mask:
1837 case Intrinsic::riscv_sseg4_load_mask:
1838 case Intrinsic::riscv_sseg5_load_mask:
1839 case Intrinsic::riscv_sseg6_load_mask:
1840 case Intrinsic::riscv_sseg7_load_mask:
1841 case Intrinsic::riscv_sseg8_load_mask:
1842 return SetRVVLoadStoreInfo( 0,
false,
1844 case Intrinsic::riscv_seg2_store_mask:
1845 case Intrinsic::riscv_seg3_store_mask:
1846 case Intrinsic::riscv_seg4_store_mask:
1847 case Intrinsic::riscv_seg5_store_mask:
1848 case Intrinsic::riscv_seg6_store_mask:
1849 case Intrinsic::riscv_seg7_store_mask:
1850 case Intrinsic::riscv_seg8_store_mask:
1852 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1855 case Intrinsic::riscv_sseg2_store_mask:
1856 case Intrinsic::riscv_sseg3_store_mask:
1857 case Intrinsic::riscv_sseg4_store_mask:
1858 case Intrinsic::riscv_sseg5_store_mask:
1859 case Intrinsic::riscv_sseg6_store_mask:
1860 case Intrinsic::riscv_sseg7_store_mask:
1861 case Intrinsic::riscv_sseg8_store_mask:
1863 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
1866 case Intrinsic::riscv_vlm:
1867 return SetRVVLoadStoreInfo( 0,
1871 case Intrinsic::riscv_vle:
1872 case Intrinsic::riscv_vle_mask:
1873 case Intrinsic::riscv_vleff:
1874 case Intrinsic::riscv_vleff_mask:
1875 return SetRVVLoadStoreInfo( 1,
1879 case Intrinsic::riscv_vsm:
1880 case Intrinsic::riscv_vse:
1881 case Intrinsic::riscv_vse_mask:
1882 return SetRVVLoadStoreInfo( 1,
1886 case Intrinsic::riscv_vlse:
1887 case Intrinsic::riscv_vlse_mask:
1888 case Intrinsic::riscv_vloxei:
1889 case Intrinsic::riscv_vloxei_mask:
1890 case Intrinsic::riscv_vluxei:
1891 case Intrinsic::riscv_vluxei_mask:
1892 return SetRVVLoadStoreInfo( 1,
1895 case Intrinsic::riscv_vsse:
1896 case Intrinsic::riscv_vsse_mask:
1897 case Intrinsic::riscv_vsoxei:
1898 case Intrinsic::riscv_vsoxei_mask:
1899 case Intrinsic::riscv_vsuxei:
1900 case Intrinsic::riscv_vsuxei_mask:
1901 return SetRVVLoadStoreInfo( 1,
1904 case Intrinsic::riscv_vlseg2:
1905 case Intrinsic::riscv_vlseg3:
1906 case Intrinsic::riscv_vlseg4:
1907 case Intrinsic::riscv_vlseg5:
1908 case Intrinsic::riscv_vlseg6:
1909 case Intrinsic::riscv_vlseg7:
1910 case Intrinsic::riscv_vlseg8:
1911 case Intrinsic::riscv_vlseg2ff:
1912 case Intrinsic::riscv_vlseg3ff:
1913 case Intrinsic::riscv_vlseg4ff:
1914 case Intrinsic::riscv_vlseg5ff:
1915 case Intrinsic::riscv_vlseg6ff:
1916 case Intrinsic::riscv_vlseg7ff:
1917 case Intrinsic::riscv_vlseg8ff:
1918 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1921 case Intrinsic::riscv_vlseg2_mask:
1922 case Intrinsic::riscv_vlseg3_mask:
1923 case Intrinsic::riscv_vlseg4_mask:
1924 case Intrinsic::riscv_vlseg5_mask:
1925 case Intrinsic::riscv_vlseg6_mask:
1926 case Intrinsic::riscv_vlseg7_mask:
1927 case Intrinsic::riscv_vlseg8_mask:
1928 case Intrinsic::riscv_vlseg2ff_mask:
1929 case Intrinsic::riscv_vlseg3ff_mask:
1930 case Intrinsic::riscv_vlseg4ff_mask:
1931 case Intrinsic::riscv_vlseg5ff_mask:
1932 case Intrinsic::riscv_vlseg6ff_mask:
1933 case Intrinsic::riscv_vlseg7ff_mask:
1934 case Intrinsic::riscv_vlseg8ff_mask:
1935 return SetRVVLoadStoreInfo(
I.arg_size() - 5,
1938 case Intrinsic::riscv_vlsseg2:
1939 case Intrinsic::riscv_vlsseg3:
1940 case Intrinsic::riscv_vlsseg4:
1941 case Intrinsic::riscv_vlsseg5:
1942 case Intrinsic::riscv_vlsseg6:
1943 case Intrinsic::riscv_vlsseg7:
1944 case Intrinsic::riscv_vlsseg8:
1945 case Intrinsic::riscv_vloxseg2:
1946 case Intrinsic::riscv_vloxseg3:
1947 case Intrinsic::riscv_vloxseg4:
1948 case Intrinsic::riscv_vloxseg5:
1949 case Intrinsic::riscv_vloxseg6:
1950 case Intrinsic::riscv_vloxseg7:
1951 case Intrinsic::riscv_vloxseg8:
1952 case Intrinsic::riscv_vluxseg2:
1953 case Intrinsic::riscv_vluxseg3:
1954 case Intrinsic::riscv_vluxseg4:
1955 case Intrinsic::riscv_vluxseg5:
1956 case Intrinsic::riscv_vluxseg6:
1957 case Intrinsic::riscv_vluxseg7:
1958 case Intrinsic::riscv_vluxseg8:
1959 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
1962 case Intrinsic::riscv_vlsseg2_mask:
1963 case Intrinsic::riscv_vlsseg3_mask:
1964 case Intrinsic::riscv_vlsseg4_mask:
1965 case Intrinsic::riscv_vlsseg5_mask:
1966 case Intrinsic::riscv_vlsseg6_mask:
1967 case Intrinsic::riscv_vlsseg7_mask:
1968 case Intrinsic::riscv_vlsseg8_mask:
1969 case Intrinsic::riscv_vloxseg2_mask:
1970 case Intrinsic::riscv_vloxseg3_mask:
1971 case Intrinsic::riscv_vloxseg4_mask:
1972 case Intrinsic::riscv_vloxseg5_mask:
1973 case Intrinsic::riscv_vloxseg6_mask:
1974 case Intrinsic::riscv_vloxseg7_mask:
1975 case Intrinsic::riscv_vloxseg8_mask:
1976 case Intrinsic::riscv_vluxseg2_mask:
1977 case Intrinsic::riscv_vluxseg3_mask:
1978 case Intrinsic::riscv_vluxseg4_mask:
1979 case Intrinsic::riscv_vluxseg5_mask:
1980 case Intrinsic::riscv_vluxseg6_mask:
1981 case Intrinsic::riscv_vluxseg7_mask:
1982 case Intrinsic::riscv_vluxseg8_mask:
1983 return SetRVVLoadStoreInfo(
I.arg_size() - 6,
1986 case Intrinsic::riscv_vsseg2:
1987 case Intrinsic::riscv_vsseg3:
1988 case Intrinsic::riscv_vsseg4:
1989 case Intrinsic::riscv_vsseg5:
1990 case Intrinsic::riscv_vsseg6:
1991 case Intrinsic::riscv_vsseg7:
1992 case Intrinsic::riscv_vsseg8:
1993 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1996 case Intrinsic::riscv_vsseg2_mask:
1997 case Intrinsic::riscv_vsseg3_mask:
1998 case Intrinsic::riscv_vsseg4_mask:
1999 case Intrinsic::riscv_vsseg5_mask:
2000 case Intrinsic::riscv_vsseg6_mask:
2001 case Intrinsic::riscv_vsseg7_mask:
2002 case Intrinsic::riscv_vsseg8_mask:
2003 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
2006 case Intrinsic::riscv_vssseg2:
2007 case Intrinsic::riscv_vssseg3:
2008 case Intrinsic::riscv_vssseg4:
2009 case Intrinsic::riscv_vssseg5:
2010 case Intrinsic::riscv_vssseg6:
2011 case Intrinsic::riscv_vssseg7:
2012 case Intrinsic::riscv_vssseg8:
2013 case Intrinsic::riscv_vsoxseg2:
2014 case Intrinsic::riscv_vsoxseg3:
2015 case Intrinsic::riscv_vsoxseg4:
2016 case Intrinsic::riscv_vsoxseg5:
2017 case Intrinsic::riscv_vsoxseg6:
2018 case Intrinsic::riscv_vsoxseg7:
2019 case Intrinsic::riscv_vsoxseg8:
2020 case Intrinsic::riscv_vsuxseg2:
2021 case Intrinsic::riscv_vsuxseg3:
2022 case Intrinsic::riscv_vsuxseg4:
2023 case Intrinsic::riscv_vsuxseg5:
2024 case Intrinsic::riscv_vsuxseg6:
2025 case Intrinsic::riscv_vsuxseg7:
2026 case Intrinsic::riscv_vsuxseg8:
2027 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
2030 case Intrinsic::riscv_vssseg2_mask:
2031 case Intrinsic::riscv_vssseg3_mask:
2032 case Intrinsic::riscv_vssseg4_mask:
2033 case Intrinsic::riscv_vssseg5_mask:
2034 case Intrinsic::riscv_vssseg6_mask:
2035 case Intrinsic::riscv_vssseg7_mask:
2036 case Intrinsic::riscv_vssseg8_mask:
2037 case Intrinsic::riscv_vsoxseg2_mask:
2038 case Intrinsic::riscv_vsoxseg3_mask:
2039 case Intrinsic::riscv_vsoxseg4_mask:
2040 case Intrinsic::riscv_vsoxseg5_mask:
2041 case Intrinsic::riscv_vsoxseg6_mask:
2042 case Intrinsic::riscv_vsoxseg7_mask:
2043 case Intrinsic::riscv_vsoxseg8_mask:
2044 case Intrinsic::riscv_vsuxseg2_mask:
2045 case Intrinsic::riscv_vsuxseg3_mask:
2046 case Intrinsic::riscv_vsuxseg4_mask:
2047 case Intrinsic::riscv_vsuxseg5_mask:
2048 case Intrinsic::riscv_vsuxseg6_mask:
2049 case Intrinsic::riscv_vsuxseg7_mask:
2050 case Intrinsic::riscv_vsuxseg8_mask:
2051 return SetRVVLoadStoreInfo(
I.arg_size() - 5,
2105 if (Subtarget.is64Bit() || !SrcTy->isIntegerTy() || !DstTy->
isIntegerTy())
2107 unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
2109 return (SrcBits == 64 && DestBits == 32);
2120 return (SrcBits == 64 && DestBits == 32);
2126 if (Subtarget.hasVInstructions() &&
2131 if (SrcBits == DestBits * 2) {
2143 EVT MemVT = LD->getMemoryVT();
2144 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
2154 return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
2162 return Subtarget.hasCTZLike();
2166 return Subtarget.hasCLZLike();
2177 if (!Subtarget.hasBEXTILike())
2182 return !Mask->getValue().isSignedIntN(12) && Mask->getValue().isPowerOf2();
2186 EVT VT =
Y.getValueType();
2191 return (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
2196 EVT VT =
Y.getValueType();
2201 return Subtarget.hasStdExtZvkb();
2206 if (Subtarget.hasStdExtZbs())
2207 return X.getValueType().isScalarInteger();
2210 if (Subtarget.hasVendorXTHeadBs())
2211 return C !=
nullptr;
2213 return C &&
C->getAPIntValue().ule(10);
2217 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
2223 if (!VT.
isVector() || !Subtarget.hasVInstructions())
2234 assert(Ty->isIntegerTy());
2236 unsigned BitSize = Ty->getIntegerBitWidth();
2237 if (BitSize > Subtarget.getXLen())
2241 int64_t Val = Imm.getSExtValue();
2249 if (!Subtarget.enableUnalignedScalarMem())
2259 return Seq.
size() <= Subtarget.getMaxBuildIntsCost();
2265 unsigned OldShiftOpcode,
unsigned NewShiftOpcode,
2272 if (XC && OldShiftOpcode ==
ISD::SRL && XC->isOne())
2320 if (!Subtarget.hasStdExtZfa())
2323 bool IsSupportedVT =
false;
2324 if (VT == MVT::f16) {
2325 IsSupportedVT = Subtarget.hasStdExtZfh() || Subtarget.hasStdExtZvfh();
2326 }
else if (VT == MVT::f32) {
2327 IsSupportedVT =
true;
2328 }
else if (VT == MVT::f64) {
2329 assert(Subtarget.hasStdExtD() &&
"Expect D extension");
2330 IsSupportedVT =
true;
2340 bool ForCodeSize)
const {
2341 bool IsLegalVT =
false;
2343 IsLegalVT = Subtarget.hasStdExtZfhminOrZhinxmin();
2344 else if (VT == MVT::f32)
2345 IsLegalVT = Subtarget.hasStdExtFOrZfinx();
2346 else if (VT == MVT::f64)
2347 IsLegalVT = Subtarget.hasStdExtDOrZdinx();
2348 else if (VT == MVT::bf16)
2349 IsLegalVT = Subtarget.hasStdExtZfbfmin();
2365 return Imm.isZero();
2369 if (Imm.isNegZero())
2374 const int FmvCost = Subtarget.hasStdExtZfinx() ? 0 : 1;
2377 Subtarget.getXLen(), Subtarget);
2383 unsigned Index)
const {
2400 if (EltVT == MVT::i1)
2406 unsigned MinVLen = Subtarget.getRealMinVLen();
2413 if (Index + ResElts <= MinVLMAX && Index < 31)
2422 return (ResElts * 2) == SrcElts && (Index == 0 || Index == ResElts);
2430 if (VT == MVT::f16 && Subtarget.hasStdExtFOrZfinx() &&
2431 !Subtarget.hasStdExtZfhminOrZhinxmin())
2441 std::optional<MVT> RegisterVT)
const {
2443 if (VT == (Subtarget.is64Bit() ? MVT::i128 : MVT::i64) && RegisterVT &&
2444 *RegisterVT == MVT::Untyped)
2455 if (VT == MVT::f16 && Subtarget.hasStdExtFOrZfinx() &&
2456 !Subtarget.hasStdExtZfhminOrZhinxmin())
2464 unsigned &NumIntermediates,
MVT &RegisterVT)
const {
2466 Context, CC, VT, IntermediateVT, NumIntermediates, RegisterVT);
2484 !Subtarget.hasVendorXAndesPerf()) {
2490 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
2504 int64_t
C = RHSC->getSExtValue();
2559 if (VT.
SimpleTy >= MVT::riscv_nxv1i8x2 &&
2560 VT.
SimpleTy <= MVT::riscv_nxv1i8x8)
2562 if (VT.
SimpleTy >= MVT::riscv_nxv2i8x2 &&
2563 VT.
SimpleTy <= MVT::riscv_nxv2i8x8)
2565 if (VT.
SimpleTy >= MVT::riscv_nxv4i8x2 &&
2566 VT.
SimpleTy <= MVT::riscv_nxv4i8x8)
2568 if (VT.
SimpleTy >= MVT::riscv_nxv8i8x2 &&
2569 VT.
SimpleTy <= MVT::riscv_nxv8i8x8)
2571 if (VT.
SimpleTy >= MVT::riscv_nxv16i8x2 &&
2572 VT.
SimpleTy <= MVT::riscv_nxv16i8x4)
2574 if (VT.
SimpleTy == MVT::riscv_nxv32i8x2)
2584 switch (KnownSize) {
2612 return RISCV::VRRegClassID;
2614 return RISCV::VRM2RegClassID;
2616 return RISCV::VRM4RegClassID;
2618 return RISCV::VRM8RegClassID;
2626 static_assert(RISCV::sub_vrm1_7 == RISCV::sub_vrm1_0 + 7,
2627 "Unexpected subreg numbering");
2628 return RISCV::sub_vrm1_0 + Index;
2631 static_assert(RISCV::sub_vrm2_3 == RISCV::sub_vrm2_0 + 3,
2632 "Unexpected subreg numbering");
2633 return RISCV::sub_vrm2_0 + Index;
2636 static_assert(RISCV::sub_vrm4_1 == RISCV::sub_vrm4_0 + 1,
2637 "Unexpected subreg numbering");
2638 return RISCV::sub_vrm4_0 + Index;
2646 unsigned RegsPerField =
2649 switch (RegsPerField) {
2652 return RISCV::VRN2M1RegClassID;
2654 return RISCV::VRN3M1RegClassID;
2656 return RISCV::VRN4M1RegClassID;
2658 return RISCV::VRN5M1RegClassID;
2660 return RISCV::VRN6M1RegClassID;
2662 return RISCV::VRN7M1RegClassID;
2664 return RISCV::VRN8M1RegClassID;
2668 return RISCV::VRN2M2RegClassID;
2670 return RISCV::VRN3M2RegClassID;
2672 return RISCV::VRN4M2RegClassID;
2676 return RISCV::VRN2M4RegClassID;
2684 return RISCV::VRRegClassID;
2693std::pair<unsigned, unsigned>
2695 MVT VecVT,
MVT SubVecVT,
unsigned InsertExtractIdx,
2697 static_assert((RISCV::VRM8RegClassID > RISCV::VRM4RegClassID &&
2698 RISCV::VRM4RegClassID > RISCV::VRM2RegClassID &&
2699 RISCV::VRM2RegClassID > RISCV::VRRegClassID),
2700 "Register classes not ordered");
2707 if (VecRegClassID == SubRegClassID)
2708 return {RISCV::NoSubRegister, 0};
2711 "Only allow scalable vector subvector.");
2713 "Invalid vector tuple insert/extract for vector and subvector with "
2724 unsigned SubRegIdx = RISCV::NoSubRegister;
2725 for (
const unsigned RCID :
2726 {RISCV::VRM4RegClassID, RISCV::VRM2RegClassID, RISCV::VRRegClassID})
2727 if (VecRegClassID > RCID && SubRegClassID <= RCID) {
2731 SubRegIdx =
TRI->composeSubRegIndices(SubRegIdx,
2736 return {SubRegIdx, InsertExtractIdx};
2741bool RISCVTargetLowering::mergeStoresAfterLegalization(
EVT VT)
const {
2751 return Subtarget.is64Bit() ? Subtarget.hasVInstructionsI64() :
true;
2757 return Subtarget.hasVInstructionsI64();
2759 return Subtarget.hasVInstructionsF16Minimal();
2761 return Subtarget.hasVInstructionsBF16Minimal();
2763 return Subtarget.hasVInstructionsF32();
2765 return Subtarget.hasVInstructionsF64();
2779 "Unexpected opcode");
2781 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
2783 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
2786 return Op.getOperand(
II->VLOperand + 1 + HasChain);
2860bool RISCVTargetLowering::useRVVForFixedLengthVectorVT(
MVT VT)
const {
2861 return ::useRVVForFixedLengthVectorVT(VT, Subtarget);
2870 "Expected legal fixed length vector!");
2873 unsigned MaxELen = Subtarget.
getELen();
2907 return ::getContainerForFixedLengthVector(*
this, VT,
getSubtarget());
2914 "Expected to convert into a scalable vector!");
2915 assert(V.getValueType().isFixedLengthVector() &&
2916 "Expected a fixed length vector operand!");
2925 "Expected to convert into a fixed length vector!");
2926 assert(V.getValueType().isScalableVector() &&
2927 "Expected a scalable vector operand!");
2946 return DAG.
getNode(RISCVISD::VMSET_VL,
DL, MaskVT, VL);
2949static std::pair<SDValue, SDValue>
2958static std::pair<SDValue, SDValue>
2971static std::pair<SDValue, SDValue>
2988std::pair<unsigned, unsigned>
2996 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
3000 unsigned VectorBitsMin = Subtarget.getRealMinVLen();
3004 return std::make_pair(MinVLMAX, MaxVLMAX);
3016 EVT VT,
unsigned DefinedValues)
const {
3025 unsigned DLenFactor = Subtarget.getDLenFactor();
3030 std::tie(LMul, Fractional) =
3033 Cost = LMul <= DLenFactor ? (DLenFactor / LMul) : 1;
3035 Cost = (LMul * DLenFactor);
3049 bool Log2CostModel =
3051 if (Log2CostModel && LMULCost.isValid()) {
3052 unsigned Log =
Log2_64(LMULCost.getValue());
3054 return LMULCost * Log;
3056 return LMULCost * LMULCost;
3087 Op.getValueType() == MVT::bf16) {
3088 bool IsStrict =
Op->isStrictFPOpcode();
3093 {Op.getOperand(0), Op.getOperand(1)});
3095 {
Op.getValueType(), MVT::Other},
3101 DAG.
getNode(
Op.getOpcode(),
DL, MVT::f32,
Op.getOperand(0)),
3116 MVT DstVT =
Op.getSimpleValueType();
3125 Src.getValueType() == MVT::bf16) {
3131 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
3132 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
3133 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
3140 Opc,
DL, DstVT, Src,
3143 if (
Opc == RISCVISD::FCVT_WU_RV64)
3154 MVT SrcVT = Src.getSimpleValueType();
3160 if (SatVT != DstEltVT)
3163 MVT DstContainerVT = DstVT;
3164 MVT SrcContainerVT = SrcVT;
3170 "Expected same element count");
3179 {Src, Src, DAG.getCondCode(ISD::SETNE),
3180 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
3184 if (DstEltSize > (2 * SrcEltSize)) {
3187 Src = DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, InterVT, Src, Mask, VL);
3190 MVT CvtContainerVT = DstContainerVT;
3191 MVT CvtEltVT = DstEltVT;
3192 if (SrcEltSize > (2 * DstEltSize)) {
3198 IsSigned ? RISCVISD::VFCVT_RTZ_X_F_VL : RISCVISD::VFCVT_RTZ_XU_F_VL;
3201 while (CvtContainerVT != DstContainerVT) {
3205 unsigned ClipOpc = IsSigned ? RISCVISD::TRUNCATE_VECTOR_VL_SSAT
3206 : RISCVISD::TRUNCATE_VECTOR_VL_USAT;
3207 Res = DAG.
getNode(ClipOpc,
DL, CvtContainerVT, Res, Mask, VL);
3211 RISCVISD::VMV_V_X_VL,
DL, DstContainerVT, DAG.
getUNDEF(DstContainerVT),
3213 Res = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, DstContainerVT, IsNan, SplatZero,
3214 Res, DAG.
getUNDEF(DstContainerVT), VL);
3224 bool IsStrict =
Op->isStrictFPOpcode();
3225 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
3235 {
Op.getOperand(0), SrcVal});
3236 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
3237 {Ext.getValue(1), Ext.getValue(0)});
3240 DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, SrcVal));
3249 case ISD::FROUNDEVEN:
3251 case ISD::VP_FROUNDEVEN:
3255 case ISD::VP_FROUNDTOZERO:
3259 case ISD::VP_FFLOOR:
3271 case ISD::VP_FROUND:
3281 case ISD::VP_LLRINT:
3295 MVT VT =
Op.getSimpleValueType();
3305 MVT ContainerVT = VT;
3312 if (
Op->isVPOpcode()) {
3313 Mask =
Op.getOperand(1);
3317 VL =
Op.getOperand(2);
3323 SDValue Abs = DAG.
getNode(RISCVISD::FABS_VL,
DL, ContainerVT, Src, Mask, VL);
3336 DAG.
getUNDEF(ContainerVT), MaxValNode, VL);
3341 DAG.
getNode(RISCVISD::SETCC_VL,
DL, SetccVT,
3350 switch (
Op.getOpcode()) {
3358 case ISD::VP_FFLOOR:
3360 case ISD::FROUNDEVEN:
3361 case ISD::VP_FROUND:
3362 case ISD::VP_FROUNDEVEN:
3363 case ISD::VP_FROUNDTOZERO: {
3366 Truncated = DAG.
getNode(RISCVISD::VFCVT_RM_X_F_VL,
DL, IntVT, Src, Mask,
3371 Truncated = DAG.
getNode(RISCVISD::VFCVT_RTZ_X_F_VL,
DL, IntVT, Src,
3374 case ISD::FNEARBYINT:
3375 case ISD::VP_FNEARBYINT:
3376 Truncated = DAG.
getNode(RISCVISD::VFROUND_NOEXCEPT_VL,
DL, ContainerVT, Src,
3382 if (Truncated.
getOpcode() != RISCVISD::VFROUND_NOEXCEPT_VL)
3383 Truncated = DAG.
getNode(RISCVISD::SINT_TO_FP_VL,
DL, ContainerVT, Truncated,
3387 Truncated = DAG.
getNode(RISCVISD::FCOPYSIGN_VL,
DL, ContainerVT, Truncated,
3388 Src, Src, Mask, VL);
3403 MVT VT =
Op.getSimpleValueType();
3407 MVT ContainerVT = VT;
3419 MVT MaskVT = Mask.getSimpleValueType();
3422 {Chain, Src, Src, DAG.getCondCode(ISD::SETUNE),
3423 DAG.getUNDEF(MaskVT), Mask, VL});
3425 Src = DAG.
getNode(RISCVISD::STRICT_FADD_VL,
DL,
3427 {Chain, Src, Src, Src, Unorder, VL});
3431 SDValue Abs = DAG.
getNode(RISCVISD::FABS_VL,
DL, ContainerVT, Src, Mask, VL);
3444 DAG.
getUNDEF(ContainerVT), MaxValNode, VL);
3448 RISCVISD::SETCC_VL,
DL, MaskVT,
3456 switch (
Op.getOpcode()) {
3466 RISCVISD::STRICT_VFCVT_RM_X_F_VL,
DL, DAG.
getVTList(IntVT, MVT::Other),
3467 {Chain, Src, Mask, DAG.getTargetConstant(FRM, DL, XLenVT), VL});
3472 DAG.
getNode(RISCVISD::STRICT_VFCVT_RTZ_X_F_VL,
DL,
3473 DAG.
getVTList(IntVT, MVT::Other), Chain, Src, Mask, VL);
3476 Truncated = DAG.
getNode(RISCVISD::STRICT_VFROUND_NOEXCEPT_VL,
DL,
3477 DAG.
getVTList(ContainerVT, MVT::Other), Chain, Src,
3485 Truncated = DAG.
getNode(RISCVISD::STRICT_SINT_TO_FP_VL,
DL,
3486 DAG.
getVTList(ContainerVT, MVT::Other), Chain,
3487 Truncated, Mask, VL);
3492 Truncated = DAG.
getNode(RISCVISD::FCOPYSIGN_VL,
DL, ContainerVT, Truncated,
3493 Src, Src, Mask, VL);
3503 MVT VT =
Op.getSimpleValueType();
3524 return DAG.
getNode(RISCVISD::FROUND,
DL, VT, Src, MaxValNode,
3532 MVT DstVT =
Op.getSimpleValueType();
3534 MVT SrcVT = Src.getSimpleValueType();
3539 MVT DstContainerVT = DstVT;
3540 MVT SrcContainerVT = SrcVT;
3552 if (SrcElemType == MVT::f16 || SrcElemType == MVT::bf16) {
3554 Src = DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, F32VT, Src, Mask, VL);
3558 DAG.
getNode(RISCVISD::VFCVT_RM_X_F_VL,
DL, DstContainerVT, Src, Mask,
3578 return DAG.
getNode(RISCVISD::VSLIDEDOWN_VL,
DL, VT,
Ops);
3590 return DAG.
getNode(RISCVISD::VSLIDEUP_VL,
DL, VT,
Ops);
3615 return std::nullopt;
3633 unsigned EltSizeInBits) {
3636 return std::nullopt;
3637 bool IsInteger =
Op.getValueType().isInteger();
3639 std::optional<unsigned> SeqStepDenom;
3640 std::optional<APInt> SeqStepNum;
3641 std::optional<APInt> SeqAddend;
3642 std::optional<std::pair<APInt, unsigned>> PrevElt;
3643 assert(EltSizeInBits >=
Op.getValueType().getScalarSizeInBits());
3648 const unsigned OpSize =
Op.getScalarValueSizeInBits();
3649 for (
auto [Idx, Elt] :
enumerate(
Op->op_values())) {
3650 if (Elt.isUndef()) {
3651 Elts[Idx] = std::nullopt;
3655 Elts[Idx] = Elt->getAsAPIntVal().trunc(OpSize).zext(EltSizeInBits);
3660 return std::nullopt;
3661 Elts[Idx] = *ExactInteger;
3665 for (
auto [Idx, Elt] :
enumerate(Elts)) {
3674 unsigned IdxDiff = Idx - PrevElt->second;
3675 APInt ValDiff = *Elt - PrevElt->first;
3683 int64_t Remainder = ValDiff.
srem(IdxDiff);
3688 return std::nullopt;
3689 ValDiff = ValDiff.
sdiv(IdxDiff);
3694 SeqStepNum = ValDiff;
3695 else if (ValDiff != SeqStepNum)
3696 return std::nullopt;
3699 SeqStepDenom = IdxDiff;
3700 else if (IdxDiff != *SeqStepDenom)
3701 return std::nullopt;
3705 if (!PrevElt || PrevElt->first != *Elt)
3706 PrevElt = std::make_pair(*Elt, Idx);
3710 if (!SeqStepNum || !SeqStepDenom)
3711 return std::nullopt;
3715 for (
auto [Idx, Elt] :
enumerate(Elts)) {
3719 (
APInt(EltSizeInBits, Idx,
false,
true) *
3721 .sdiv(*SeqStepDenom);
3723 APInt Addend = *Elt - ExpectedVal;
3726 else if (Addend != SeqAddend)
3727 return std::nullopt;
3730 assert(SeqAddend &&
"Must have an addend if we have a step");
3732 return VIDSequence{SeqStepNum->getSExtValue(), *SeqStepDenom,
3733 SeqAddend->getSExtValue()};
3748 if (EltTy == MVT::i1 ||
3751 MVT SrcVT = Src.getSimpleValueType();
3767 MVT ContainerVT = VT;
3771 MVT SrcContainerVT = SrcVT;
3786 SDValue Gather = DAG.
getNode(RISCVISD::VRGATHER_VX_VL,
DL, ContainerVT, Src,
3787 Idx, DAG.
getUNDEF(ContainerVT), Mask, VL);
3795 MVT VT =
Op.getSimpleValueType();
3804 int64_t StepNumerator = SimpleVID->StepNumerator;
3805 unsigned StepDenominator = SimpleVID->StepDenominator;
3806 int64_t Addend = SimpleVID->Addend;
3808 assert(StepNumerator != 0 &&
"Invalid step");
3809 bool Negate =
false;
3810 int64_t SplatStepVal = StepNumerator;
3814 if (StepNumerator != 1 && StepNumerator !=
INT64_MIN &&
3816 Negate = StepNumerator < 0;
3818 SplatStepVal =
Log2_64(std::abs(StepNumerator));
3828 (SplatStepVal >= 0 || StepDenominator == 1) &&
isInt<32>(Addend)) {
3831 MVT VIDContainerVT =
3839 if ((StepOpcode ==
ISD::MUL && SplatStepVal != 1) ||
3840 (StepOpcode ==
ISD::SHL && SplatStepVal != 0)) {
3842 VID = DAG.
getNode(StepOpcode,
DL, VIDVT, VID, SplatStep);
3844 if (StepDenominator != 1) {
3849 if (Addend != 0 || Negate) {
3875 MVT VT =
Op.getSimpleValueType();
3884 unsigned NumElts =
Op.getNumOperands();
3887 unsigned MostCommonCount = 0;
3889 unsigned NumUndefElts =
3897 unsigned NumScalarLoads = 0;
3903 unsigned &
Count = ValueCounts[V];
3906 NumScalarLoads += !CFP->isExactlyValue(+0.0);
3911 if (++
Count >= MostCommonCount) {
3913 MostCommonCount =
Count;
3917 assert(DominantValue &&
"Not expecting an all-undef BUILD_VECTOR");
3918 unsigned NumDefElts = NumElts - NumUndefElts;
3919 unsigned DominantValueCountThreshold = NumDefElts <= 2 ? 0 : NumDefElts - 2;
3925 ((MostCommonCount > DominantValueCountThreshold) ||
3937 if (
SDValue LastOp =
Op->getOperand(
Op->getNumOperands() - 1);
3938 !LastOp.isUndef() && ValueCounts[LastOp] == 1 &&
3939 LastOp != DominantValue) {
3942 VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1DOWN_VL : RISCVISD::VSLIDE1DOWN_VL;
3948 Processed.
insert(LastOp);
3954 if (V.isUndef() || !Processed.
insert(V).second)
3956 if (ValueCounts[V] == 1) {
3964 return DAG.getConstant(V == V1, DL, XLenVT);
3980 MVT VT =
Op.getSimpleValueType();
3989 unsigned NumElts =
Op.getNumOperands();
4010 unsigned NumViaIntegerBits = std::clamp(NumElts, 8u, Subtarget.
getXLen());
4011 NumViaIntegerBits = std::min(NumViaIntegerBits, Subtarget.
getELen());
4019 unsigned IntegerViaVecElts =
divideCeil(NumElts, NumViaIntegerBits);
4020 MVT IntegerViaVecVT =
4025 unsigned BitPos = 0, IntegerEltIdx = 0;
4028 for (
unsigned I = 0;
I < NumElts;) {
4030 bool BitValue = !V.isUndef() && V->getAsZExtVal();
4031 Bits |= ((
uint64_t)BitValue << BitPos);
4037 if (
I % NumViaIntegerBits == 0 ||
I == NumElts) {
4038 if (NumViaIntegerBits <= 32)
4041 Elts[IntegerEltIdx] = Elt;
4050 if (NumElts < NumViaIntegerBits) {
4054 assert(IntegerViaVecVT == MVT::v1i8 &&
"Unexpected mask vector type");
4069 : RISCVISD::VMV_V_X_VL;
4089 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32) &&
4090 "Unexpected sequence type");
4094 unsigned ViaVecLen =
4102 const auto &SeqV =
OpIdx.value();
4103 if (!SeqV.isUndef())
4105 ((SeqV->getAsZExtVal() & EltMask) << (
OpIdx.index() * EltBitSize));
4111 if (ViaIntVT == MVT::i32)
4134 BV->getRepeatedSequence(Sequence) &&
4135 (Sequence.size() * EltBitSize) <= Subtarget.
getELen()) {
4136 unsigned SeqLen = Sequence.size();
4138 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32 ||
4139 ViaIntVT == MVT::i64) &&
4140 "Unexpected sequence type");
4145 const unsigned RequiredVL = NumElts / SeqLen;
4146 const unsigned ViaVecLen =
4148 NumElts : RequiredVL;
4151 unsigned EltIdx = 0;
4156 for (
const auto &SeqV : Sequence) {
4157 if (!SeqV.isUndef())
4159 ((SeqV->getAsZExtVal() & EltMask) << (EltIdx * EltBitSize));
4166 if (ViaIntVT == MVT::i32)
4173 (!Subtarget.
is64Bit() && ViaIntVT == MVT::i64)) &&
4174 "Unexpected bitcast sequence");
4178 MVT ViaContainerVT =
4181 DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ViaContainerVT,
4185 if (ViaVecLen != RequiredVL)
4204 Source, DAG, Subtarget);
4205 SDValue Res = DAG.
getNode(RISCVISD::VSEXT_VL,
DL, ContainerVT, Source, Mask, VL);
4224 return RISCV::PACKH;
4226 return Subtarget.
is64Bit() ? RISCV::PACKW : RISCV::PACK;
4241 MVT VT =
Op.getSimpleValueType();
4249 if (!Subtarget.hasStdExtZbb() || !Subtarget.hasStdExtZba())
4254 if (ElemSizeInBits >= std::min(Subtarget.
getELen(), Subtarget.
getXLen()) ||
4268 if (Subtarget.hasStdExtZbkb())
4273 ElemDL, XLenVT,
A,
B),
4285 NewOperands.
reserve(NumElts / 2);
4287 NewOperands.
push_back(pack(
Op.getOperand(i),
Op.getOperand(i + 1)));
4291 return DAG.
getNode(ISD::BITCAST,
DL, VT,
4297 MVT VT =
Op.getSimpleValueType();
4308 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) || EltVT == MVT::bf16) {
4313 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4314 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin())) {
4324 NewOps[
I] = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Elem);
4374 [](
const SDUse &U) { return U.get().isUndef(); })) {
4415 auto OneVRegOfOps =
ArrayRef(BuildVectorOps).slice(i, ElemsPerVReg);
4419 unsigned InsertIdx = (i / ElemsPerVReg) * NumOpElts;
4441 unsigned NumUndefElts =
4443 unsigned NumDefElts = NumElts - NumUndefElts;
4444 if (NumDefElts >= 8 && NumDefElts > NumElts / 2 &&
4451 for (
const auto &[Idx, U] :
enumerate(
Op->ops())) {
4453 if (Idx < NumElts / 2) {
4460 bool SelectMaskVal = (Idx < NumElts / 2);
4463 assert(SubVecAOps.
size() == NumElts && SubVecBOps.
size() == NumElts &&
4464 MaskVals.
size() == NumElts);
4499 unsigned UndefCount = 0;
4506 LinearBudget -= PerSlideCost;
4509 LinearBudget -= PerSlideCost;
4512 LinearBudget -= PerSlideCost;
4515 if (LinearBudget < 0)
4520 "Illegal type which will result in reserved encoding");
4536 bool SlideUp =
false;
4602 Vec = getVSlide(ContainerVT, DAG.
getUNDEF(ContainerVT), Vec,
Offset, Mask,
4609 Opcode = SlideUp ? RISCVISD::VFSLIDE1UP_VL : RISCVISD::VFSLIDE1DOWN_VL;
4611 Opcode = SlideUp ? RISCVISD::VSLIDE1UP_VL : RISCVISD::VSLIDE1DOWN_VL;
4620 Vec = getVSlide(ContainerVT, DAG.
getUNDEF(ContainerVT), Vec,
Offset, Mask,
4636 if ((LoC >> 31) == HiC)
4637 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4649 auto InterVec = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, InterVT,
4651 return DAG.
getNode(ISD::BITCAST,
DL, VT, InterVec);
4658 Hi.getConstantOperandVal(1) == 31)
4659 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4664 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4667 return DAG.
getNode(RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL,
DL, VT, Passthru,
Lo,
4677 assert(Scalar.getValueType() == MVT::i64 &&
"Unexpected VT!");
4689 bool HasPassthru = Passthru && !Passthru.
isUndef();
4690 if (!HasPassthru && !Passthru)
4697 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
4698 EltVT == MVT::bf16) {
4699 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4700 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
4701 Scalar = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Scalar);
4703 Scalar = DAG.
getNode(ISD::BITCAST,
DL, MVT::i16, Scalar);
4705 Passthru = DAG.
getNode(ISD::BITCAST,
DL, IVT, Passthru);
4710 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL, VT, Passthru, Scalar, VL);
4714 if (Scalar.getValueType().bitsLE(XLenVT)) {
4721 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4722 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru, Scalar, VL);
4725 assert(XLenVT == MVT::i32 && Scalar.getValueType() == MVT::i64 &&
4726 "Unexpected scalar for splat lowering!");
4729 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, VT, Passthru,
4755 MVT ExtractedContainerVT = ExtractedVT;
4758 DAG, ExtractedContainerVT, Subtarget);
4760 ExtractedVal, DAG, Subtarget);
4762 if (ExtractedContainerVT.
bitsLE(VT))
4774 if (!Scalar.getValueType().bitsLE(XLenVT))
4777 VT,
DL, DAG, Subtarget);
4785 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4826 Src && Src.
getValueType().getVectorNumElements() == (NumElts * 2))
4843 !Subtarget.hasVendorXRivosVizip())
4846 int Size = Mask.size();
4848 assert(
Size == (
int)NumElts &&
"Unexpected mask size");
4854 EvenSrc = StartIndexes[0];
4855 OddSrc = StartIndexes[1];
4858 if (EvenSrc != 0 && OddSrc != 0)
4868 int HalfNumElts = NumElts / 2;
4869 return ((EvenSrc % HalfNumElts) == 0) && ((OddSrc % HalfNumElts) == 0);
4874 std::array<std::pair<int, int>, 2> &SrcInfo) {
4879 if (SrcInfo[0].second == 0 && SrcInfo[1].second == 0)
4883 if ((SrcInfo[0].second > 0 && SrcInfo[1].second < 0) ||
4884 SrcInfo[1].second == 0)
4886 assert(SrcInfo[0].first != -1 &&
"Must find one slide");
4894 if (SrcInfo[1].first == -1)
4896 return SrcInfo[0].second < 0 && SrcInfo[1].second > 0 &&
4897 SrcInfo[1].second - SrcInfo[0].second == (int)NumElts;
4902 bool RequiredPolarity) {
4903 int NumElts = Mask.size();
4904 for (
const auto &[Idx, M] :
enumerate(Mask)) {
4907 int Src = M >= NumElts;
4908 int Diff = (int)Idx - (M % NumElts);
4909 bool C = Src == SrcInfo[1].first && Diff == SrcInfo[1].second;
4910 assert(
C != (Src == SrcInfo[0].first && Diff == SrcInfo[0].second) &&
4911 "Must match exactly one of the two slides");
4912 if (RequiredPolarity != (
C == (Idx / Factor) % 2))
4923static bool isZipEven(
const std::array<std::pair<int, int>, 2> &SrcInfo,
4925 Factor = SrcInfo[1].second;
4927 Mask.size() % Factor == 0 &&
4938static bool isZipOdd(
const std::array<std::pair<int, int>, 2> &SrcInfo,
4940 Factor = -SrcInfo[1].second;
4942 Mask.size() % Factor == 0 &&
4955 ElementCount SrcEC = Src.getValueType().getVectorElementCount();
4962 unsigned Shift = Index * EltBits;
4987 std::optional<int> SplatIdx;
4989 if (M == -1 ||
I == (
unsigned)M)
4991 if (SplatIdx && *SplatIdx != M)
5000 for (
int MaskIndex : Mask) {
5001 bool SelectMaskVal = MaskIndex == *SplatIdx;
5004 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
5029 auto findNonEXTRACT_SUBVECTORParent =
5030 [](
SDValue Parent) -> std::pair<SDValue, uint64_t> {
5035 Parent.getOperand(0).getSimpleValueType().isFixedLengthVector()) {
5036 Offset += Parent.getConstantOperandVal(1);
5037 Parent = Parent.getOperand(0);
5039 return std::make_pair(Parent,
Offset);
5042 auto [V1Src, V1IndexOffset] = findNonEXTRACT_SUBVECTORParent(V1);
5043 auto [V2Src, V2IndexOffset] = findNonEXTRACT_SUBVECTORParent(V2);
5052 for (
size_t i = 0; i != NewMask.
size(); ++i) {
5053 if (NewMask[i] == -1)
5056 if (
static_cast<size_t>(NewMask[i]) < NewMask.
size()) {
5057 NewMask[i] = NewMask[i] + V1IndexOffset;
5061 NewMask[i] = NewMask[i] - NewMask.
size() + V2IndexOffset;
5067 if (NewMask[0] <= 0)
5071 for (
unsigned i = 1; i != NewMask.
size(); ++i)
5072 if (NewMask[i - 1] + 1 != NewMask[i])
5076 MVT SrcVT = Src.getSimpleValueType();
5105 int NumSubElts, Index;
5110 bool OpsSwapped = Mask[Index] < (int)NumElts;
5111 SDValue InPlace = OpsSwapped ? V2 : V1;
5112 SDValue ToInsert = OpsSwapped ? V1 : V2;
5123 if (NumSubElts + Index >= (
int)NumElts)
5134 Res = DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, ContainerVT, InPlace, ToInsert,
5137 Res =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, InPlace, ToInsert,
5149 bool OpsSwapped =
false;
5164 const unsigned E = Mask.size() - ((
Offset > 0) ?
Offset : 0);
5165 for (
unsigned i = S; i !=
E; ++i)
5166 if (Mask[i] >= 0 && (
unsigned)Mask[i] !=
Base + i +
Offset)
5172 bool IsVSlidedown = isSlideMask(Mask, OpsSwapped ? 0 : NumElts, 1);
5173 if (!IsVSlidedown && !isSlideMask(Mask, OpsSwapped ? 0 : NumElts, -1))
5176 const int InsertIdx = Mask[IsVSlidedown ? (NumElts - 1) : 0];
5178 if (InsertIdx < 0 || InsertIdx / NumElts != (
unsigned)OpsSwapped)
5195 IsVSlidedown ? RISCVISD::VSLIDE1DOWN_VL : RISCVISD::VSLIDE1UP_VL,
DL,
5201 auto OpCode = IsVSlidedown ?
5202 (VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1DOWN_VL : RISCVISD::VSLIDE1DOWN_VL) :
5203 (VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1UP_VL : RISCVISD::VSLIDE1UP_VL);
5206 auto Vec = DAG.
getNode(OpCode,
DL, ContainerVT,
5209 Splat, TrueMask, VL);
5221 for (
unsigned i = 0; i < Mask.size(); i++)
5222 LaneIsUndef[i % Factor] &= (Mask[i] == -1);
5225 for (
unsigned i = 0; i < Factor; i++) {
5236 for (
unsigned i = 0; i < Mask.size() / Factor; i++) {
5237 unsigned j = i * Factor + Index;
5238 if (Mask[j] != -1 && (
unsigned)Mask[j] != i)
5247 assert(RISCVISD::RI_VZIPEVEN_VL ==
Opc || RISCVISD::RI_VZIPODD_VL ==
Opc ||
5248 RISCVISD::RI_VZIP2A_VL ==
Opc || RISCVISD::RI_VZIP2B_VL ==
Opc ||
5249 RISCVISD::RI_VUNZIP2A_VL ==
Opc || RISCVISD::RI_VUNZIP2B_VL ==
Opc);
5257 MVT ContainerVT = IntVT;
5264 MVT InnerVT = ContainerVT;
5268 (RISCVISD::RI_VUNZIP2A_VL ==
Opc || RISCVISD::RI_VUNZIP2B_VL ==
Opc)) {
5280 if (InnerVT.
bitsLT(ContainerVT))
5295 MVT VT = V.getSimpleValueType();
5310 EC.multiplyCoefficientBy(Factor));
5329 MVT VecContainerVT = VecVT;
5346 MVT WideContainerVT = WideVT;
5352 EvenV = DAG.
getBitcast(VecContainerVT, EvenV);
5359 if (Subtarget.hasStdExtZvbb()) {
5363 Interleaved = DAG.
getNode(RISCVISD::VWSLL_VL,
DL, WideContainerVT, OddV,
5364 OffsetVec, Passthru, Mask, VL);
5365 Interleaved = DAG.
getNode(RISCVISD::VWADDU_W_VL,
DL, WideContainerVT,
5366 Interleaved, EvenV, Passthru, Mask, VL);
5373 Interleaved = DAG.
getNode(RISCVISD::VWADDU_VL,
DL, WideContainerVT, EvenV,
5374 OddV, Passthru, Mask, VL);
5380 OddV, AllOnesVec, Passthru, Mask, VL);
5387 Interleaved = DAG.
getNode(RISCVISD::ADD_VL,
DL, WideContainerVT,
5388 Interleaved, OddsMul, Passthru, Mask, VL);
5395 Interleaved = DAG.
getBitcast(ResultContainerVT, Interleaved);
5441 if (ViaEltSize > NumElts)
5449 if (ViaEltSize > NumElts)
5455 if (ViaEltSize > NumElts)
5462 MVT &RotateVT,
unsigned &RotateAmt) {
5465 unsigned NumSubElts;
5467 NumElts, NumSubElts, RotateAmt))
5470 NumElts / NumSubElts);
5538 unsigned NumOfSrcRegs = NumElts / NumOpElts;
5539 unsigned NumOfDestRegs = NumElts / NumOpElts;
5548 Mask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs,
5549 [&]() {
Operands.emplace_back(); },
5550 [&](
ArrayRef<int> SrcSubMask,
unsigned SrcVecIdx,
unsigned DstVecIdx) {
5551 Operands.emplace_back().emplace_back(SrcVecIdx, UINT_MAX,
5554 [&](
ArrayRef<int> SrcSubMask,
unsigned Idx1,
unsigned Idx2,
bool NewReg) {
5559 assert(
Operands.size() == NumOfDestRegs &&
"Whole vector must be processed");
5564 unsigned NumShuffles = std::accumulate(
5571 for (const auto &P : Data) {
5572 unsigned Idx2 = std::get<1>(P);
5573 ArrayRef<int> Mask = std::get<2>(P);
5574 if (Idx2 != UINT_MAX)
5576 else if (ShuffleVectorInst::isIdentityMask(Mask, Mask.size()))
5581 if ((NumOfDestRegs > 2 && NumShuffles > NumOfDestRegs) ||
5582 (NumOfDestRegs <= 2 && NumShuffles >= 4))
5584 auto ExtractValue = [&, &DAG = DAG](
SDValue SrcVec,
unsigned ExtractIdx) {
5585 SDValue SubVec = DAG.getExtractSubvector(
DL, M1VT, SrcVec, ExtractIdx);
5589 auto PerformShuffle = [&, &DAG = DAG](
SDValue SubVec1,
SDValue SubVec2,
5591 SDValue SubVec = DAG.getVectorShuffle(OneRegVT,
DL, SubVec1, SubVec2, Mask);
5594 SDValue Vec = DAG.getUNDEF(ContainerVT);
5600 const auto &[Idx1, Idx2,
_] =
Data[
I];
5608 V = ExtractValue(Idx1 >= NumOfSrcRegs ? V2 : V1,
5609 (Idx1 % NumOfSrcRegs) * NumOpElts);
5610 if (Idx2 != UINT_MAX) {
5613 V = ExtractValue(Idx2 >= NumOfSrcRegs ? V2 : V1,
5614 (Idx2 % NumOfSrcRegs) * NumOpElts);
5618 for (
const auto &[Idx1, Idx2, Mask] :
Data) {
5620 SDValue V2 = Idx2 == UINT_MAX ? V1 : Values.
at(Idx2);
5621 V = PerformShuffle(V1, V2, Mask);
5625 unsigned InsertIdx =
I * NumOpElts;
5627 Vec = DAG.getInsertSubvector(
DL, Vec, V, InsertIdx);
5637 bool SawUndef =
false;
5638 for (
const auto &[Idx, M] :
enumerate(Mask)) {
5645 if (Idx > (
unsigned)M)
5678 for (
int Idx : Mask) {
5681 unsigned SrcIdx = Idx % Mask.size();
5682 int Src = (
uint32_t)Idx < Mask.size() ? 0 : 1;
5683 if (Srcs[SrcIdx] == -1)
5686 else if (Srcs[SrcIdx] != Src)
5692 for (
int Lane : Srcs) {
5705 for (
unsigned I = 0;
I < Mask.size();
I++) {
5709 NewMask[
I] = Mask[
I] % Mask.size();
5723 if ((M / Span) != (
int)(
I / Span))
5725 int SpanIdx =
I % Span;
5735 return all_of(Mask, [&](
const auto &Idx) {
return Idx == -1 || Idx < Span; });
5747 int SpanIdx =
I % Span;
5748 if (Mask[SpanIdx] != M)
5762 MVT VT =
Op.getSimpleValueType();
5770 if (ElementSize > 32)
5793 MVT VT =
Op.getSimpleValueType();
5821 auto [TrueMask, VL] = TrueMaskVL;
5836 V.getOperand(0).getSimpleValueType().getVectorNumElements();
5837 V = V.getOperand(
Offset / OpElements);
5867 MVT SplatVT = ContainerVT;
5870 if (SVT == MVT::bf16 ||
5871 (SVT == MVT::f16 && !Subtarget.hasStdExtZfh())) {
5880 V = DAG.
getLoad(SVT,
DL, Ld->getChain(), NewAddr,
5881 Ld->getPointerInfo().getWithOffset(
Offset),
5882 Ld->getBaseAlign(), Ld->getMemOperand()->
getFlags());
5885 Ld->getPointerInfo().getWithOffset(
Offset), SVT,
5887 Ld->getMemOperand()->getFlags());
5891 : RISCVISD::VMV_V_X_VL;
5899 assert(Lane < (
int)NumElts &&
"Unexpected lane!");
5902 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
5924 if (Subtarget.hasStdExtZvkb())
5940 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
5941 for (
unsigned Factor = 2; Factor <= MaxFactor; Factor <<= 1) {
5944 1 <
count_if(Mask, [](
int Idx) {
return Idx != -1; })) {
5948 [&Mask](
int Idx) {
return Idx < (int)Mask.size(); }) &&
5949 1 <
count_if(Mask, [&Mask](
int Idx) {
5950 return Idx >= (int)Mask.size();
5980 if (Subtarget.hasVendorXRivosVizip() &&
5982 1 <
count_if(Mask, [](
int Idx) {
return Idx != -1; })) {
5984 Index == 0 ? RISCVISD::RI_VUNZIP2A_VL : RISCVISD::RI_VUNZIP2B_VL;
6000 [&Mask](
int Idx) {
return Idx < (int)Mask.size(); }) &&
6002 [&Mask](
int Idx) {
return Idx >= (int)Mask.size(); })) {
6006 if (NumElts < MinVLMAX) {
6030 int EvenSrc, OddSrc;
6040 bool LaneIsUndef[2] = {
true,
true};
6041 for (
const auto &[Idx, M] :
enumerate(Mask))
6042 LaneIsUndef[Idx % 2] &= (M == -1);
6044 int Size = Mask.size();
6046 if (LaneIsUndef[0]) {
6049 assert(EvenSrc >= 0 &&
"Undef source?");
6050 EvenV = (EvenSrc /
Size) == 0 ? V1 : V2;
6054 if (LaneIsUndef[1]) {
6057 assert(OddSrc >= 0 &&
"Undef source?");
6058 OddV = (OddSrc /
Size) == 0 ? V1 : V2;
6064 if (Subtarget.hasVendorXRivosVizip()) {
6067 return lowerVZIP(RISCVISD::RI_VZIP2A_VL, EvenV, OddV,
DL, DAG, Subtarget);
6078 std::array<std::pair<int, int>, 2> SrcInfo;
6085 auto GetSourceFor = [&](
const std::pair<int, int> &
Info) {
6086 int SrcIdx =
Info.first;
6087 assert(SrcIdx == 0 || SrcIdx == 1);
6088 SDValue &Src = Sources[SrcIdx];
6090 SDValue SrcV = SrcIdx == 0 ? V1 : V2;
6095 auto GetSlide = [&](
const std::pair<int, int> &Src,
SDValue Mask,
6097 auto [TrueMask, VL] = TrueMaskVL;
6098 SDValue SrcV = GetSourceFor(Src);
6099 int SlideAmt = Src.second;
6100 if (SlideAmt == 0) {
6102 assert(Mask == TrueMask);
6109 return getVSlideup(DAG, Subtarget,
DL, ContainerVT, Passthru, SrcV,
6114 if (SrcInfo[1].first == -1) {
6116 Res = GetSlide(SrcInfo[0], TrueMask, Res);
6120 if (Subtarget.hasVendorXRivosVizip()) {
6121 bool TryWiden =
false;
6125 SDValue Src1 = SrcInfo[0].first == 0 ? V1 : V2;
6126 SDValue Src2 = SrcInfo[1].first == 0 ? V1 : V2;
6127 return lowerVZIP(RISCVISD::RI_VZIPEVEN_VL, Src1, Src2,
DL, DAG,
6132 if (
isZipOdd(SrcInfo, Mask, Factor)) {
6134 SDValue Src1 = SrcInfo[1].first == 0 ? V1 : V2;
6135 SDValue Src2 = SrcInfo[0].first == 0 ? V1 : V2;
6136 return lowerVZIP(RISCVISD::RI_VZIPODD_VL, Src1, Src2,
DL, DAG,
6154 for (
const auto &[Idx, M] :
enumerate(Mask)) {
6156 (SrcInfo[1].second > 0 && Idx < (
unsigned)SrcInfo[1].second)) {
6160 int Src = M >= (int)NumElts;
6161 int Diff = (int)Idx - (M % NumElts);
6162 bool C = Src == SrcInfo[1].first && Diff == SrcInfo[1].second;
6163 assert(
C ^ (Src == SrcInfo[0].first && Diff == SrcInfo[0].second) &&
6164 "Must match exactly one of the two slides");
6167 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
6174 Res = GetSlide(SrcInfo[0], TrueMask, Res);
6175 Res = GetSlide(SrcInfo[1], SelectMask, Res);
6180 assert(!V1.
isUndef() &&
"Unexpected shuffle canonicalization");
6195 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
6196 for (
unsigned Factor = 4; Factor <= MaxFactor; Factor <<= 1) {
6211 if (NumElts > MinVLMAX) {
6212 unsigned MaxIdx = 0;
6216 MaxIdx = std::max(std::max((
unsigned)
I, (
unsigned)M), MaxIdx);
6218 unsigned NewNumElts =
6220 if (NewNumElts != NumElts) {
6224 Mask.take_front(NewNumElts));
6241 for (
auto Idx : Mask) {
6244 assert(Idx >= 0 && (
unsigned)Idx < NumElts);
6254 any_of(Mask, [&](
const auto &Idx) {
return Idx > 255; })) {
6264 unsigned GatherVVOpc = RISCVISD::VRGATHER_VV_VL;
6270 GatherVVOpc = RISCVISD::VRGATHEREI16_VV_VL;
6279 GatherVVOpc = RISCVISD::VRGATHEREI16_VV_VL;
6283 MVT IndexContainerVT =
6288 for (
int MaskIndex : Mask) {
6289 bool IsLHSIndex = MaskIndex < (int)NumElts && MaskIndex >= 0;
6299 if (NumElts <= MinVLMAX) {
6301 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
6307 auto [InnerTrueMask, InnerVL] =
6319 for (
int i = 0; i <
N; i++) {
6323 DAG.
getNode(GatherVVOpc,
DL, M1VT, SubV1, SubIndex,
6324 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6341 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6343 for (
int i = 0; i <
N; i++)
6359 for (
int i = 0; i <
N; i++) {
6362 DAG.
getUNDEF(IndexContainerVT), LHSIndices,
6363 SlideAmt, TrueMask, VL);
6367 DAG.
getNode(GatherVVOpc,
DL, M1VT, SubV1, SubIndex,
6368 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6378 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
6388 for (
int MaskIndex : Mask) {
6389 bool IsLHSOrUndefIndex = MaskIndex < (int)NumElts;
6390 ShuffleMaskLHS.
push_back(IsLHSOrUndefIndex && MaskIndex >= 0
6392 ShuffleMaskRHS.
push_back(IsLHSOrUndefIndex ? -1 : (MaskIndex - NumElts));
6423 for (
int MaskIndex : Mask) {
6424 bool SelectMaskVal = (MaskIndex < (int)NumElts) ^ !SwapOps;
6428 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
6446 const unsigned NumElts = M.size();
6453 std::array<std::pair<int, int>, 2> SrcInfo;
6464RISCVTargetLowering::lowerCTLZ_CTTZ_ZERO_UNDEF(
SDValue Op,
6466 MVT VT =
Op.getSimpleValueType();
6470 MVT ContainerVT = VT;
6473 if (
Op->isVPOpcode()) {
6474 Mask =
Op.getOperand(1);
6478 VL =
Op.getOperand(2);
6484 MVT FloatEltVT = (EltSize >= 32) ? MVT::f64 :
MVT::f32;
6486 FloatEltVT = MVT::f32;
6493 "Expected legal float type!");
6500 }
else if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF) {
6503 Src = DAG.
getNode(ISD::VP_AND,
DL, VT, Src, Neg, Mask, VL);
6508 if (FloatVT.
bitsGT(VT)) {
6509 if (
Op->isVPOpcode())
6510 FloatVal = DAG.
getNode(ISD::VP_UINT_TO_FP,
DL, FloatVT, Src, Mask, VL);
6519 if (!
Op->isVPOpcode())
6523 MVT ContainerFloatVT =
6525 FloatVal = DAG.
getNode(RISCVISD::VFCVT_RM_F_XU_VL,
DL, ContainerFloatVT,
6526 Src, Mask, RTZRM, VL);
6533 unsigned ShiftAmt = FloatEltVT == MVT::f64 ? 52 : 23;
6537 if (
Op->isVPOpcode()) {
6546 else if (IntVT.
bitsGT(VT))
6551 unsigned ExponentBias = FloatEltVT == MVT::f64 ? 1023 : 127;
6556 if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF)
6557 return DAG.
getNode(ISD::VP_SUB,
DL, VT, Exp,
6562 unsigned Adjust = ExponentBias + (EltSize - 1);
6564 if (
Op->isVPOpcode())
6574 else if (
Op.getOpcode() == ISD::VP_CTLZ)
6575 Res = DAG.
getNode(ISD::VP_UMIN,
DL, VT, Res,
6583 MVT XLenVT = Subtarget.getXLenVT();
6585 MVT SrcVT =
Source.getSimpleValueType();
6594 SrcVT = ContainerVT;
6606 SDValue Res = DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Source, Mask, EVL);
6607 if (
Op->getOpcode() == ISD::VP_CTTZ_ELTS_ZERO_UNDEF)
6625 assert(Load &&
Load->getMemoryVT().isVector() &&
"Expected vector load");
6628 Load->getMemoryVT(),
6629 *
Load->getMemOperand()))
6633 MVT VT =
Op.getSimpleValueType();
6635 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
6636 "Unexpected unaligned RVV load type");
6640 "Expecting equally-sized RVV vector types to be legal");
6642 Load->getPointerInfo(),
Load->getBaseAlign(),
6643 Load->getMemOperand()->getFlags());
6654 assert(Store &&
Store->getValue().getValueType().isVector() &&
6655 "Expected vector store");
6658 Store->getMemoryVT(),
6659 *
Store->getMemOperand()))
6666 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
6667 "Unexpected unaligned RVV store type");
6671 "Expecting equally-sized RVV vector types to be legal");
6672 StoredVal = DAG.
getBitcast(NewVT, StoredVal);
6674 Store->getPointerInfo(),
Store->getBaseAlign(),
6675 Store->getMemOperand()->getFlags());
6680 assert(
Op.getValueType() == MVT::i64 &&
"Unexpected VT");
6709 unsigned ShiftAmt, AddOpc;
6720 MVT VT =
Op.getSimpleValueType();
6724 bool Negate =
false;
6728 if (Index < 0 &&
Imm.isNegative()) {
6745 return DAG.
getNode(ISD::FNEG,
DL, VT, Const);
6751 unsigned IsData =
Op.getConstantOperandVal(4);
6754 if (Subtarget.hasVendorXMIPSCBOP() && !IsData)
6755 return Op.getOperand(0);
6767 if (Subtarget.hasStdExtZtso()) {
6775 return DAG.
getNode(ISD::MEMBARRIER, dl, MVT::Other,
Op.getOperand(0));
6783 return DAG.
getNode(ISD::MEMBARRIER, dl, MVT::Other,
Op.getOperand(0));
6791 MVT VT =
Op.getSimpleValueType();
6792 MVT XLenVT = Subtarget.getXLenVT();
6793 unsigned Check =
Op.getConstantOperandVal(1);
6794 unsigned TDCMask = 0;
6822 MVT VT0 =
Op.getOperand(0).getSimpleValueType();
6827 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6829 VL =
Op.getOperand(3);
6832 VL,
Op->getFlags());
6847 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6849 MVT MaskContainerVT =
6852 VL =
Op.getOperand(3);
6856 SDValue FPCLASS = DAG.
getNode(RISCVISD::FCLASS_VL,
DL, ContainerDstVT, Op0,
6857 Mask, VL,
Op->getFlags());
6859 TDCMaskV = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerDstVT,
6860 DAG.
getUNDEF(ContainerDstVT), TDCMaskV, VL);
6863 DAG.
getNode(RISCVISD::SETCC_VL,
DL, ContainerVT,
6869 TDCMaskV, DAG.
getUNDEF(ContainerDstVT), Mask, VL);
6872 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerDstVT,
6873 DAG.
getUNDEF(ContainerDstVT), SplatZero, VL);
6893 MVT VT =
Op.getSimpleValueType();
6919 Op.getOpcode() == ISD::FMAXIMUM ? RISCVISD::FMAX : RISCVISD::FMIN;
6927 MVT ContainerVT = VT;
6935 if (
Op->isVPOpcode()) {
6936 Mask =
Op.getOperand(2);
6940 VL =
Op.getOperand(3);
6947 SDValue XIsNonNan = DAG.
getNode(RISCVISD::SETCC_VL,
DL, Mask.getValueType(),
6948 {X, X, DAG.getCondCode(ISD::SETOEQ),
6949 DAG.getUNDEF(ContainerVT), Mask, VL});
6950 NewY = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, XIsNonNan,
Y,
X,
6956 SDValue YIsNonNan = DAG.
getNode(RISCVISD::SETCC_VL,
DL, Mask.getValueType(),
6957 {Y, Y, DAG.getCondCode(ISD::SETOEQ),
6958 DAG.getUNDEF(ContainerVT), Mask, VL});
6959 NewX = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, YIsNonNan,
X,
Y,
6964 Op.getOpcode() == ISD::FMAXIMUM ||
Op->getOpcode() == ISD::VP_FMAXIMUM
6965 ? RISCVISD::VFMAX_VL
6966 : RISCVISD::VFMIN_VL;
6968 DAG.
getUNDEF(ContainerVT), Mask, VL);
6976 bool IsFABS =
Op.getOpcode() == ISD::FABS;
6977 assert((IsFABS ||
Op.getOpcode() == ISD::FNEG) &&
6978 "Wrong opcode for lowering FABS or FNEG.");
6981 MVT VT =
Op.getSimpleValueType();
6982 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
6986 DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT,
Op.getOperand(0));
6989 Mask = Mask.sext(Subtarget.
getXLen());
6994 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, Logic);
7002 MVT VT =
Op.getSimpleValueType();
7003 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
7013 if (SignSize == Subtarget.
getXLen())
7014 return DAG.
getNode(ISD::BITCAST,
DL, XLenVT, Sign);
7017 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Sign);
7019 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, XLenVT, Sign);
7021 assert(XLenVT == MVT::i32 &&
"Unexpected type");
7024 return DAG.
getNode(RISCVISD::SplitF64,
DL, {MVT::i32, MVT::i32}, Sign)
7054 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, CopiedSign);
7059#define OP_CASE(NODE) \
7061 return RISCVISD::NODE##_VL;
7062#define VP_CASE(NODE) \
7063 case ISD::VP_##NODE: \
7064 return RISCVISD::NODE##_VL;
7066 switch (
Op.getOpcode()) {
7145 case ISD::VP_CTLZ_ZERO_UNDEF:
7146 return RISCVISD::CTLZ_VL;
7148 case ISD::VP_CTTZ_ZERO_UNDEF:
7149 return RISCVISD::CTTZ_VL;
7152 return RISCVISD::VFMADD_VL;
7154 return RISCVISD::STRICT_VFMADD_VL;
7157 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7158 return RISCVISD::VMAND_VL;
7159 return RISCVISD::AND_VL;
7162 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7163 return RISCVISD::VMOR_VL;
7164 return RISCVISD::OR_VL;
7167 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7168 return RISCVISD::VMXOR_VL;
7169 return RISCVISD::XOR_VL;
7172 return RISCVISD::VZEXT_VL;
7174 return RISCVISD::VSEXT_VL;
7176 return RISCVISD::SETCC_VL;
7178 return RISCVISD::VMERGE_VL;
7179 case ISD::VP_SELECT:
7181 return RISCVISD::VMERGE_VL;
7183 return RISCVISD::SRA_VL;
7185 return RISCVISD::SRL_VL;
7187 return RISCVISD::FSQRT_VL;
7188 case ISD::VP_SIGN_EXTEND:
7189 return RISCVISD::VSEXT_VL;
7190 case ISD::VP_ZERO_EXTEND:
7191 return RISCVISD::VZEXT_VL;
7192 case ISD::VP_FP_TO_SINT:
7193 return RISCVISD::VFCVT_RTZ_X_F_VL;
7194 case ISD::VP_FP_TO_UINT:
7195 return RISCVISD::VFCVT_RTZ_XU_F_VL;
7197 case ISD::FMINIMUMNUM:
7198 case ISD::VP_FMINNUM:
7199 return RISCVISD::VFMIN_VL;
7201 case ISD::FMAXIMUMNUM:
7202 case ISD::VP_FMAXNUM:
7203 return RISCVISD::VFMAX_VL;
7207 case ISD::VP_LLRINT:
7208 return RISCVISD::VFCVT_RM_X_F_VL;
7217 return (
Op.getValueType() == MVT::nxv32f16 &&
7220 Op.getValueType() == MVT::nxv32bf16;
7230 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7231 if (!
Op.getOperand(j).getValueType().isVector()) {
7232 LoOperands[j] =
Op.getOperand(j);
7233 HiOperands[j] =
Op.getOperand(j);
7236 std::tie(LoOperands[j], HiOperands[j]) =
7241 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
7243 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
7256 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7258 std::tie(LoOperands[j], HiOperands[j]) =
7262 if (!
Op.getOperand(j).getValueType().isVector()) {
7263 LoOperands[j] =
Op.getOperand(j);
7264 HiOperands[j] =
Op.getOperand(j);
7267 std::tie(LoOperands[j], HiOperands[j]) =
7272 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
7274 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
7284 auto [EVLLo, EVLHi] =
7285 DAG.
SplitEVL(
Op.getOperand(3),
Op.getOperand(1).getValueType(),
DL);
7289 {Op.getOperand(0), Lo, MaskLo, EVLLo},
Op->getFlags());
7291 {ResLo, Hi, MaskHi, EVLHi},
Op->getFlags());
7308 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7309 if (!
Op.getOperand(j).getValueType().isVector()) {
7310 LoOperands[j] =
Op.getOperand(j);
7311 HiOperands[j] =
Op.getOperand(j);
7314 std::tie(LoOperands[j], HiOperands[j]) =
7319 DAG.
getNode(
Op.getOpcode(),
DL, LoVTs, LoOperands,
Op->getFlags());
7322 DAG.
getNode(
Op.getOpcode(),
DL, HiVTs, HiOperands,
Op->getFlags());
7330RISCVTargetLowering::lowerXAndesBfHCvtBFloat16Load(
SDValue Op,
7332 assert(Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh() &&
7333 "Unexpected bfloat16 load lowering");
7337 EVT MemVT =
LD->getMemoryVT();
7342 LD->getMemOperand());
7350 DAG.
getNode(RISCVISD::NDS_FMV_BF16_X,
DL, MVT::bf16, OrSixteenOne);
7355RISCVTargetLowering::lowerXAndesBfHCvtBFloat16Store(
SDValue Op,
7357 assert(Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh() &&
7358 "Unexpected bfloat16 store lowering");
7363 Subtarget.getXLenVT(),
ST->getValue());
7365 ST->getChain(),
DL, FMV,
ST->getBasePtr(),
7367 ST->getMemOperand());
7372 switch (
Op.getOpcode()) {
7375 "Unimplemented RISCVTargetLowering::LowerOperation Case");
7378 case ISD::ATOMIC_FENCE:
7381 return lowerGlobalAddress(
Op, DAG);
7383 return lowerBlockAddress(
Op, DAG);
7385 return lowerConstantPool(
Op, DAG);
7387 return lowerJumpTable(
Op, DAG);
7389 return lowerGlobalTLSAddress(
Op, DAG);
7393 return lowerConstantFP(
Op, DAG);
7395 return lowerSELECT(
Op, DAG);
7397 return lowerBRCOND(
Op, DAG);
7399 return lowerVASTART(
Op, DAG);
7401 return lowerFRAMEADDR(
Op, DAG);
7403 return lowerRETURNADDR(
Op, DAG);
7405 return lowerShiftLeftParts(
Op, DAG);
7407 return lowerShiftRightParts(
Op, DAG,
true);
7409 return lowerShiftRightParts(
Op, DAG,
false);
7412 if (
Op.getValueType().isFixedLengthVector()) {
7413 assert(Subtarget.hasStdExtZvkb());
7414 return lowerToScalableOp(
Op, DAG);
7416 assert(Subtarget.hasVendorXTHeadBb() &&
7417 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
7418 "Unexpected custom legalization");
7423 case ISD::BITCAST: {
7425 EVT VT =
Op.getValueType();
7428 MVT XLenVT = Subtarget.getXLenVT();
7429 if (Op0VT == MVT::i16 &&
7430 ((VT == MVT::f16 && Subtarget.hasStdExtZfhminOrZhinxmin()) ||
7431 (VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
7433 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, NewOp0);
7435 if (VT == MVT::f32 && Op0VT == MVT::i32 && Subtarget.is64Bit() &&
7436 Subtarget.hasStdExtFOrZfinx()) {
7438 return DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, NewOp0);
7440 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit() &&
7441 Subtarget.hasStdExtDOrZdinx()) {
7444 return DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64,
Lo,
Hi);
7456 "Unexpected types");
7488 return LowerINTRINSIC_WO_CHAIN(
Op, DAG);
7490 return LowerINTRINSIC_W_CHAIN(
Op, DAG);
7492 return LowerINTRINSIC_VOID(
Op, DAG);
7494 return LowerIS_FPCLASS(
Op, DAG);
7496 MVT VT =
Op.getSimpleValueType();
7498 assert(Subtarget.hasStdExtZvbb());
7499 return lowerToScalableOp(
Op, DAG);
7502 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected custom legalization");
7506 return DAG.
getNode(RISCVISD::BREV8,
DL, VT, BSwap);
7512 if (!
Op.getSimpleValueType().isVector())
7514 return lowerVectorTruncLike(
Op, DAG);
7517 if (
Op.getOperand(0).getValueType().isVector() &&
7518 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7519 return lowerVectorMaskExt(
Op, DAG, 1);
7520 if (
Op.getValueType().isScalableVector())
7522 return lowerToScalableOp(
Op, DAG);
7524 if (
Op.getOperand(0).getValueType().isVector() &&
7525 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7526 return lowerVectorMaskExt(
Op, DAG, -1);
7527 if (
Op.getValueType().isScalableVector())
7529 return lowerToScalableOp(
Op, DAG);
7531 return lowerSPLAT_VECTOR_PARTS(
Op, DAG);
7533 return lowerINSERT_VECTOR_ELT(
Op, DAG);
7535 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
7537 MVT VT =
Op.getSimpleValueType();
7545 MVT ContainerVT = VT;
7552 V = DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL, ContainerVT,
7553 DAG.
getUNDEF(ContainerVT), Scalar, VL);
7556 V = DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, ContainerVT,
7557 DAG.
getUNDEF(ContainerVT), Scalar, VL);
7564 MVT XLenVT = Subtarget.getXLenVT();
7565 MVT VT =
Op.getSimpleValueType();
7584 }
else if (
Log2 > 3) {
7588 }
else if ((Val % 8) == 0) {
7606 if (
Op.getValueType() == MVT::f16 && Subtarget.is64Bit() &&
7607 Op.getOperand(1).getValueType() == MVT::i32) {
7611 DAG.
getNode(ISD::FPOWI,
DL, MVT::f32, Op0,
Op.getOperand(1));
7622 case ISD::FP_EXTEND:
7624 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
7627 return lowerStrictFPExtendOrRoundLike(
Op, DAG);
7630 if (
Op.getValueType().isVector() &&
7631 ((
Op.getValueType().getScalarType() == MVT::f16 &&
7632 (Subtarget.hasVInstructionsF16Minimal() &&
7633 !Subtarget.hasVInstructionsF16())) ||
7634 Op.getValueType().getScalarType() == MVT::bf16)) {
7650 Op1.getValueType().isVector() &&
7651 ((Op1.getValueType().getScalarType() == MVT::f16 &&
7652 (Subtarget.hasVInstructionsF16Minimal() &&
7653 !Subtarget.hasVInstructionsF16())) ||
7654 Op1.getValueType().getScalarType() == MVT::bf16)) {
7660 Op1.getValueType().getVectorElementCount());
7663 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), WidenVec);
7673 MVT VT =
Op.getSimpleValueType();
7676 bool IsStrict =
Op->isStrictFPOpcode();
7677 SDValue Src =
Op.getOperand(0 + IsStrict);
7678 MVT SrcVT = Src.getSimpleValueType();
7689 "Unexpected vector element types");
7693 if (EltSize > (2 * SrcEltSize)) {
7705 Op.getOperand(0), Ext);
7709 assert(SrcEltVT == MVT::f16 &&
"Unexpected FP_TO_[US]INT lowering");
7714 auto [FExt, Chain] =
7716 return DAG.
getNode(
Op.getOpcode(),
DL,
Op->getVTList(), Chain, FExt);
7723 if (SrcEltSize > (2 * EltSize)) {
7726 assert(EltVT == MVT::f16 &&
"Unexpected [US]_TO_FP lowering");
7731 Op.getOperand(0), Src);
7746 Op.getOperand(0), Src);
7760 unsigned RVVOpc = 0;
7761 switch (
Op.getOpcode()) {
7765 RVVOpc = RISCVISD::VFCVT_RTZ_X_F_VL;
7768 RVVOpc = RISCVISD::VFCVT_RTZ_XU_F_VL;
7771 RVVOpc = RISCVISD::SINT_TO_FP_VL;
7774 RVVOpc = RISCVISD::UINT_TO_FP_VL;
7777 RVVOpc = RISCVISD::STRICT_VFCVT_RTZ_X_F_VL;
7780 RVVOpc = RISCVISD::STRICT_VFCVT_RTZ_XU_F_VL;
7783 RVVOpc = RISCVISD::STRICT_SINT_TO_FP_VL;
7786 RVVOpc = RISCVISD::STRICT_UINT_TO_FP_VL;
7793 "Expected same element count");
7800 Op.getOperand(0), Src, Mask, VL);
7804 Src = DAG.
getNode(RVVOpc,
DL, ContainerVT, Src, Mask, VL);
7810 case ISD::FP_TO_BF16: {
7813 assert(!Subtarget.isSoftFPABI() &&
"Unexpected custom legalization");
7819 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
7820 if (Subtarget.is64Bit())
7821 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Res);
7824 case ISD::BF16_TO_FP: {
7825 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalization");
7826 MVT VT =
Op.getSimpleValueType();
7831 SDValue Res = Subtarget.is64Bit()
7832 ? DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32,
Op)
7836 return DAG.
getNode(ISD::FP_EXTEND,
DL, VT, Res);
7839 case ISD::STRICT_FP_TO_FP16:
7840 case ISD::FP_TO_FP16: {
7843 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalisation");
7846 bool IsStrict =
Op->isStrictFPOpcode();
7847 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7851 std::tie(Res, Chain) =
7852 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
7853 if (Subtarget.is64Bit())
7854 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Res);
7860 case ISD::STRICT_FP16_TO_FP:
7861 case ISD::FP16_TO_FP: {
7864 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalisation");
7867 bool IsStrict =
Op->isStrictFPOpcode();
7868 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7870 SDValue Arg = Subtarget.is64Bit()
7871 ? DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, Op0)
7874 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
7875 CallOptions,
DL, Chain);
7883 case ISD::FNEARBYINT:
7886 case ISD::FROUNDEVEN:
7893 case ISD::LLROUND: {
7894 if (
Op.getValueType().isVector())
7896 assert(
Op.getOperand(0).getValueType() == MVT::f16 &&
7897 "Unexpected custom legalisation");
7900 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), Ext);
7906 assert(
Op.getOperand(1).getValueType() == MVT::f16 &&
7907 "Unexpected custom legalisation");
7910 {
Op.getOperand(0),
Op.getOperand(1)});
7911 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
7912 {Ext.getValue(1), Ext.getValue(0)});
7914 case ISD::VECREDUCE_ADD:
7915 case ISD::VECREDUCE_UMAX:
7916 case ISD::VECREDUCE_SMAX:
7917 case ISD::VECREDUCE_UMIN:
7918 case ISD::VECREDUCE_SMIN:
7919 return lowerVECREDUCE(
Op, DAG);
7920 case ISD::VECREDUCE_AND:
7921 case ISD::VECREDUCE_OR:
7922 case ISD::VECREDUCE_XOR:
7923 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7924 return lowerVectorMaskVecReduction(
Op, DAG,
false);
7925 return lowerVECREDUCE(
Op, DAG);
7926 case ISD::VECREDUCE_FADD:
7927 case ISD::VECREDUCE_SEQ_FADD:
7928 case ISD::VECREDUCE_FMIN:
7929 case ISD::VECREDUCE_FMAX:
7930 case ISD::VECREDUCE_FMAXIMUM:
7931 case ISD::VECREDUCE_FMINIMUM:
7932 return lowerFPVECREDUCE(
Op, DAG);
7933 case ISD::VP_REDUCE_ADD:
7934 case ISD::VP_REDUCE_UMAX:
7935 case ISD::VP_REDUCE_SMAX:
7936 case ISD::VP_REDUCE_UMIN:
7937 case ISD::VP_REDUCE_SMIN:
7938 case ISD::VP_REDUCE_FADD:
7939 case ISD::VP_REDUCE_SEQ_FADD:
7940 case ISD::VP_REDUCE_FMIN:
7941 case ISD::VP_REDUCE_FMAX:
7942 case ISD::VP_REDUCE_FMINIMUM:
7943 case ISD::VP_REDUCE_FMAXIMUM:
7946 return lowerVPREDUCE(
Op, DAG);
7947 case ISD::VP_REDUCE_AND:
7948 case ISD::VP_REDUCE_OR:
7949 case ISD::VP_REDUCE_XOR:
7950 if (
Op.getOperand(1).getValueType().getVectorElementType() == MVT::i1)
7951 return lowerVectorMaskVecReduction(
Op, DAG,
true);
7952 return lowerVPREDUCE(
Op, DAG);
7953 case ISD::VP_CTTZ_ELTS:
7954 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
7955 return lowerVPCttzElements(
Op, DAG);
7959 DAG.
getUNDEF(ContainerVT), DAG, Subtarget);
7962 return lowerINSERT_SUBVECTOR(
Op, DAG);
7964 return lowerEXTRACT_SUBVECTOR(
Op, DAG);
7966 return lowerVECTOR_DEINTERLEAVE(
Op, DAG);
7968 return lowerVECTOR_INTERLEAVE(
Op, DAG);
7970 return lowerSTEP_VECTOR(
Op, DAG);
7972 return lowerVECTOR_REVERSE(
Op, DAG);
7974 return lowerVECTOR_SPLICE(
Op, DAG);
7976 MVT VT =
Op.getSimpleValueType();
7978 if (!Subtarget.is64Bit() && EltVT == MVT::i64)
7983 MVT VT =
Op.getSimpleValueType();
7985 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
7986 EltVT == MVT::bf16) {
7989 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
7990 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
7991 Elt = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, Subtarget.getXLenVT(),
7994 Elt = DAG.
getNode(ISD::BITCAST,
DL, MVT::i16,
Op.getOperand(0));
7996 return DAG.
getNode(ISD::BITCAST,
DL, VT,
8000 if (EltVT == MVT::i1)
8001 return lowerVectorMaskSplat(
Op, DAG);
8010 MVT VT =
Op.getSimpleValueType();
8011 MVT ContainerVT = VT;
8023 if (
Op.getNumOperands() > 2 &&
8027 size_t HalfNumOps =
Op.getNumOperands() / 2;
8029 Op->ops().take_front(HalfNumOps));
8031 Op->ops().drop_front(HalfNumOps));
8035 unsigned NumOpElts =
8036 Op.getOperand(0).getSimpleValueType().getVectorMinNumElements();
8049 EVT VT = Load->getValueType(0);
8050 if (VT == MVT::f64) {
8051 assert(Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
8052 !Subtarget.is64Bit() &&
"Unexpected custom legalisation");
8056 SDValue BasePtr = Load->getBasePtr();
8057 SDValue Chain = Load->getChain();
8060 DAG.
getLoad(MVT::i32,
DL, Chain, BasePtr, Load->getPointerInfo(),
8061 Load->getBaseAlign(), Load->getMemOperand()->getFlags());
8064 MVT::i32,
DL, Chain, BasePtr, Load->getPointerInfo().getWithOffset(4),
8065 Load->getBaseAlign(), Load->getMemOperand()->getFlags());
8073 if (VT == MVT::bf16)
8074 return lowerXAndesBfHCvtBFloat16Load(
Op, DAG);
8079 MVT XLenVT = Subtarget.getXLenVT();
8082 unsigned NumElts = Sz / (NF * 8);
8083 int Log2LMUL =
Log2_64(NumElts) - 3;
8086 Flag.setNoUnsignedWrap(
true);
8088 SDValue BasePtr = Load->getBasePtr();
8096 for (
unsigned i = 0; i < NF; ++i) {
8101 Ret = DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VT, Ret, LoadVal,
8109 if (
auto V = expandUnalignedRVVLoad(
Op, DAG))
8111 if (
Op.getValueType().isFixedLengthVector())
8112 return lowerFixedLengthVectorLoadToRVV(
Op, DAG);
8117 SDValue StoredVal = Store->getValue();
8119 if (VT == MVT::f64) {
8120 assert(Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
8121 !Subtarget.is64Bit() &&
"Unexpected custom legalisation");
8125 SDValue BasePtr = Store->getBasePtr();
8126 SDValue Chain = Store->getChain();
8128 DAG.
getVTList(MVT::i32, MVT::i32), StoredVal);
8131 Store->getPointerInfo(), Store->getBaseAlign(),
8132 Store->getMemOperand()->getFlags());
8135 Store->getPointerInfo().getWithOffset(4),
8136 Store->getBaseAlign(),
8137 Store->getMemOperand()->getFlags());
8140 if (VT == MVT::i64) {
8141 assert(Subtarget.hasStdExtZilsd() && !Subtarget.is64Bit() &&
8142 "Unexpected custom legalisation");
8143 if (Store->isTruncatingStore())
8146 if (!Subtarget.enableUnalignedScalarMem() && Store->getAlign() < 8)
8157 {Store->getChain(), Lo, Hi, Store->getBasePtr()}, MVT::i64,
8158 Store->getMemOperand());
8161 if (VT == MVT::bf16)
8162 return lowerXAndesBfHCvtBFloat16Store(
Op, DAG);
8167 MVT XLenVT = Subtarget.getXLenVT();
8170 unsigned NumElts = Sz / (NF * 8);
8171 int Log2LMUL =
Log2_64(NumElts) - 3;
8174 Flag.setNoUnsignedWrap(
true);
8176 SDValue Chain = Store->getChain();
8177 SDValue BasePtr = Store->getBasePtr();
8184 for (
unsigned i = 0; i < NF; ++i) {
8186 DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL,
8189 Ret = DAG.
getStore(Chain,
DL, Extract, BasePtr,
8191 Store->getBaseAlign(),
8192 Store->getMemOperand()->getFlags());
8193 Chain = Ret.getValue(0);
8199 if (
auto V = expandUnalignedRVVStore(
Op, DAG))
8201 if (
Op.getOperand(1).getValueType().isFixedLengthVector())
8202 return lowerFixedLengthVectorStoreToRVV(
Op, DAG);
8207 return lowerMaskedLoad(
Op, DAG);
8208 case ISD::VP_LOAD_FF:
8209 return lowerLoadFF(
Op, DAG);
8212 return lowerMaskedStore(
Op, DAG);
8214 return lowerVectorCompress(
Op, DAG);
8223 EVT VT =
Op.getValueType();
8234 MVT OpVT =
Op.getOperand(0).getSimpleValueType();
8236 MVT VT =
Op.getSimpleValueType();
8241 "Unexpected CondCode");
8274 return DAG.
getSetCC(
DL, VT, RHS, LHS, CCVal);
8280 return lowerToScalableOp(
Op, DAG);
8297 return lowerToScalableOp(
Op, DAG);
8301 if (
Op.getSimpleValueType().isFixedLengthVector())
8302 return lowerToScalableOp(
Op, DAG);
8304 assert(
Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.is64Bit() &&
8305 "Unexpected custom legalisation");
8309 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
8320 case ISD::FMINIMUMNUM:
8321 case ISD::FMAXIMUMNUM:
8337 return lowerToScalableOp(
Op, DAG);
8341 EVT VT =
Op->getValueType(0);
8356 return lowerABS(
Op, DAG);
8361 if (Subtarget.hasStdExtZvbb())
8362 return lowerToScalableOp(
Op, DAG);
8364 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8366 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
8370 return lowerToScalableOp(
Op, DAG);
8379 return lowerToScalableOp(
Op, DAG);
8382 return lowerVectorStrictFSetcc(
Op, DAG);
8392 case ISD::VP_GATHER:
8393 return lowerMaskedGather(
Op, DAG);
8395 case ISD::VP_SCATTER:
8396 return lowerMaskedScatter(
Op, DAG);
8398 return lowerGET_ROUNDING(
Op, DAG);
8399 case ISD::SET_ROUNDING:
8400 return lowerSET_ROUNDING(
Op, DAG);
8401 case ISD::GET_FPENV:
8402 return lowerGET_FPENV(
Op, DAG);
8403 case ISD::SET_FPENV:
8404 return lowerSET_FPENV(
Op, DAG);
8405 case ISD::RESET_FPENV:
8406 return lowerRESET_FPENV(
Op, DAG);
8407 case ISD::GET_FPMODE:
8408 return lowerGET_FPMODE(
Op, DAG);
8409 case ISD::SET_FPMODE:
8410 return lowerSET_FPMODE(
Op, DAG);
8411 case ISD::RESET_FPMODE:
8412 return lowerRESET_FPMODE(
Op, DAG);
8414 return lowerEH_DWARF_CFA(
Op, DAG);
8416 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
8417 return lowerVPMergeMask(
Op, DAG);
8419 case ISD::VP_SELECT:
8427 case ISD::VP_UADDSAT:
8428 case ISD::VP_USUBSAT:
8429 case ISD::VP_SADDSAT:
8430 case ISD::VP_SSUBSAT:
8432 case ISD::VP_LLRINT:
8433 return lowerVPOp(
Op, DAG);
8437 return lowerLogicVPOp(
Op, DAG);
8446 case ISD::VP_FMINNUM:
8447 case ISD::VP_FMAXNUM:
8448 case ISD::VP_FCOPYSIGN:
8455 return lowerVPOp(
Op, DAG);
8456 case ISD::VP_IS_FPCLASS:
8457 return LowerIS_FPCLASS(
Op, DAG);
8458 case ISD::VP_SIGN_EXTEND:
8459 case ISD::VP_ZERO_EXTEND:
8460 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
8461 return lowerVPExtMaskOp(
Op, DAG);
8462 return lowerVPOp(
Op, DAG);
8463 case ISD::VP_TRUNCATE:
8464 return lowerVectorTruncLike(
Op, DAG);
8465 case ISD::VP_FP_EXTEND:
8466 case ISD::VP_FP_ROUND:
8467 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
8468 case ISD::VP_SINT_TO_FP:
8469 case ISD::VP_UINT_TO_FP:
8470 if (
Op.getValueType().isVector() &&
8471 ((
Op.getValueType().getScalarType() == MVT::f16 &&
8472 (Subtarget.hasVInstructionsF16Minimal() &&
8473 !Subtarget.hasVInstructionsF16())) ||
8474 Op.getValueType().getScalarType() == MVT::bf16)) {
8487 case ISD::VP_FP_TO_SINT:
8488 case ISD::VP_FP_TO_UINT:
8490 Op1.getValueType().isVector() &&
8491 ((Op1.getValueType().getScalarType() == MVT::f16 &&
8492 (Subtarget.hasVInstructionsF16Minimal() &&
8493 !Subtarget.hasVInstructionsF16())) ||
8494 Op1.getValueType().getScalarType() == MVT::bf16)) {
8500 Op1.getValueType().getVectorElementCount());
8504 {WidenVec, Op.getOperand(1), Op.getOperand(2)});
8506 return lowerVPFPIntConvOp(
Op, DAG);
8510 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
8511 return lowerVPSetCCMaskOp(
Op, DAG);
8517 case ISD::VP_BITREVERSE:
8519 return lowerVPOp(
Op, DAG);
8521 case ISD::VP_CTLZ_ZERO_UNDEF:
8522 if (Subtarget.hasStdExtZvbb())
8523 return lowerVPOp(
Op, DAG);
8524 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8526 case ISD::VP_CTTZ_ZERO_UNDEF:
8527 if (Subtarget.hasStdExtZvbb())
8528 return lowerVPOp(
Op, DAG);
8529 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8531 return lowerVPOp(
Op, DAG);
8532 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
8533 return lowerVPStridedLoad(
Op, DAG);
8534 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
8535 return lowerVPStridedStore(
Op, DAG);
8537 case ISD::VP_FFLOOR:
8539 case ISD::VP_FNEARBYINT:
8540 case ISD::VP_FROUND:
8541 case ISD::VP_FROUNDEVEN:
8542 case ISD::VP_FROUNDTOZERO:
8546 case ISD::VP_FMAXIMUM:
8547 case ISD::VP_FMINIMUM:
8551 case ISD::EXPERIMENTAL_VP_SPLICE:
8552 return lowerVPSpliceExperimental(
Op, DAG);
8553 case ISD::EXPERIMENTAL_VP_REVERSE:
8554 return lowerVPReverseExperimental(
Op, DAG);
8555 case ISD::EXPERIMENTAL_VP_SPLAT:
8556 return lowerVPSplatExperimental(
Op, DAG);
8559 "llvm.clear_cache only needs custom lower on Linux targets");
8562 return emitFlushICache(DAG,
Op.getOperand(0),
Op.getOperand(1),
8563 Op.getOperand(2), Flags,
DL);
8565 case ISD::DYNAMIC_STACKALLOC:
8566 return lowerDYNAMIC_STACKALLOC(
Op, DAG);
8567 case ISD::INIT_TRAMPOLINE:
8568 return lowerINIT_TRAMPOLINE(
Op, DAG);
8569 case ISD::ADJUST_TRAMPOLINE:
8570 return lowerADJUST_TRAMPOLINE(
Op, DAG);
8571 case ISD::PARTIAL_REDUCE_UMLA:
8572 case ISD::PARTIAL_REDUCE_SMLA:
8573 case ISD::PARTIAL_REDUCE_SUMLA:
8574 return lowerPARTIAL_REDUCE_MLA(
Op, DAG);
8581 MakeLibCallOptions CallOptions;
8582 std::pair<SDValue, SDValue> CallResult =
8583 makeLibCall(DAG, RTLIB::RISCV_FLUSH_ICACHE, MVT::isVoid,
8584 {Start, End, Flags}, CallOptions,
DL, InChain);
8587 return CallResult.second;
8592 if (!Subtarget.is64Bit())
8600 std::unique_ptr<MCCodeEmitter> CodeEmitter(
8628 const bool HasCFBranch =
8629 Subtarget.hasStdExtZicfilp() &&
8631 "cf-protection-branch");
8632 const unsigned StaticChainIdx = HasCFBranch ? 5 : 4;
8633 const unsigned StaticChainOffset = StaticChainIdx * 4;
8634 const unsigned FunctionAddressOffset = StaticChainOffset + 8;
8638 auto GetEncoding = [&](
const MCInst &MC) {
8641 CodeEmitter->encodeInstruction(MC, CB, Fixups, *STI);
8648 SmallVector<uint32_t> Encodings;
8653 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X7).addImm(0)),
8657 GetEncoding(MCInstBuilder(RISCV::LD)
8660 .addImm(FunctionAddressOffset)),
8663 GetEncoding(MCInstBuilder(RISCV::LD)
8666 .addImm(StaticChainOffset)),
8669 GetEncoding(MCInstBuilder(RISCV::JALR)
8677 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X0).addImm(0)),
8680 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X28).addImm(0)),
8684 GetEncoding(MCInstBuilder(RISCV::LD)
8687 .addImm(FunctionAddressOffset - 4)),
8690 GetEncoding(MCInstBuilder(RISCV::LD)
8693 .addImm(StaticChainOffset - 4)),
8696 GetEncoding(MCInstBuilder(RISCV::JALR)
8708 Root, dl, DAG.
getConstant(Encoding, dl, MVT::i64), Addr,
8709 MachinePointerInfo(TrmpAddr, Idx * 4), MVT::i32));
8713 SDValue FunctionAddress =
Op.getOperand(2);
8717 struct OffsetValuePair {
8721 } OffsetValues[] = {
8722 {StaticChainOffset, StaticChain},
8723 {FunctionAddressOffset, FunctionAddress},
8725 for (
auto &OffsetValue : OffsetValues) {
8728 DAG.
getConstant(OffsetValue.Offset, dl, MVT::i64));
8729 OffsetValue.Addr = Addr;
8731 DAG.
getStore(Root, dl, OffsetValue.Value, Addr,
8732 MachinePointerInfo(TrmpAddr, OffsetValue.Offset)));
8735 assert(OutChains.
size() == StaticChainIdx + 2 &&
8736 "Size of OutChains mismatch");
8741 SDValue EndOfTrmp = OffsetValues[0].Addr;
8752 if (!Subtarget.is64Bit())
8755 return Op.getOperand(0);
8764 MVT VT =
Op.getSimpleValueType();
8770 MVT ArgVT =
A.getSimpleValueType();
8771 assert(ArgVT ==
B.getSimpleValueType() &&
8781 MVT ContainerVT = VT;
8790 switch (
Op.getOpcode()) {
8791 case ISD::PARTIAL_REDUCE_SMLA:
8792 Opc = RISCVISD::VQDOT_VL;
8794 case ISD::PARTIAL_REDUCE_UMLA:
8795 Opc = RISCVISD::VQDOTU_VL;
8797 case ISD::PARTIAL_REDUCE_SUMLA:
8798 Opc = RISCVISD::VQDOTSU_VL;
8824 N->getOffset(), Flags);
8853template <
class NodeTy>
8855 bool IsLocal,
bool IsExternWeak)
const {
8865 if (IsLocal && !Subtarget.allowTaggedGlobals())
8869 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
8892 if (Subtarget.hasVendorXqcili()) {
8896 return DAG.
getNode(RISCVISD::QC_E_LI,
DL, Ty, Addr);
8903 return DAG.
getNode(RISCVISD::ADD_LO,
DL, Ty, MNHi, AddrLo);
8927 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
8935 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
8943 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
8944 const GlobalValue *GV =
N->getGlobal();
8952 return getAddr(
N, DAG);
8959 return getAddr(
N, DAG);
8966 return getAddr(
N, DAG);
8971 bool UseGOT)
const {
8974 const GlobalValue *GV =
N->getGlobal();
8975 MVT XLenVT = Subtarget.getXLenVT();
9012 DAG.
getNode(RISCVISD::ADD_TPREL,
DL, Ty, MNHi, TPReg, AddrAdd);
9013 return DAG.
getNode(RISCVISD::ADD_LO,
DL, Ty, MNAdd, AddrLo);
9021 const GlobalValue *GV =
N->getGlobal();
9032 Args.emplace_back(Load, CallTy);
9035 TargetLowering::CallLoweringInfo CLI(DAG);
9049 const GlobalValue *GV =
N->getGlobal();
9065 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
9079 Addr = getStaticTLSAddr(
N, DAG,
false);
9082 Addr = getStaticTLSAddr(
N, DAG,
true);
9087 : getDynamicTLSAddr(
N, DAG);
9104 if (
LHS == LHS2 &&
RHS == RHS2) {
9109 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
9117 return std::nullopt;
9129 MVT VT =
N->getSimpleValueType(0);
9164 if (~TrueVal == FalseVal) {
9204 if (Subtarget.hasShortForwardBranchOpt())
9207 unsigned SelOpNo = 0;
9217 unsigned ConstSelOpNo = 1;
9218 unsigned OtherSelOpNo = 2;
9225 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
9230 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
9236 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
9238 std::swap(NewConstOps[0], NewConstOps[1]);
9250 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
9252 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
9255 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
9256 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
9265 MVT VT =
Op.getSimpleValueType();
9266 MVT XLenVT = Subtarget.getXLenVT();
9287 return DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV);
9290 return DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV);
9294 auto getNotOperand = [](
const SDValue &
Op) -> std::optional<const SDValue> {
9295 using namespace llvm::SDPatternMatch;
9300 return std::nullopt;
9306 auto NotOperand = (TrueV.
getOperand(0) == FalseV)
9308 : getNotOperand(TrueV.getOperand(0));
9311 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, *NotOperand, CondV);
9317 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV));
9324 auto NotOperand = (FalseV.
getOperand(0) == TrueV)
9326 : getNotOperand(FalseV.getOperand(0));
9329 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, *NotOperand, CondV);
9335 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV));
9352 int64_t TrueImm =
TrueVal.getSExtValue();
9353 int64_t FalseImm =
FalseVal.getSExtValue();
9372 if ((TrueVal - FalseVal).isPowerOf2() &&
FalseVal.isSignedIntN(12)) {
9377 if ((FalseVal - TrueVal).isPowerOf2() &&
TrueVal.isSignedIntN(12)) {
9384 auto getCost = [&](
const APInt &Delta,
const APInt &Addend) {
9386 Delta, Subtarget.getXLen(), Subtarget,
true);
9388 if (Addend.isSignedIntN(12))
9391 Addend, Subtarget.getXLen(), Subtarget,
true);
9392 return AddendCost + DeltaCost;
9394 bool IsCZERO_NEZ =
getCost(FalseVal - TrueVal, TrueVal) <=
9395 getCost(TrueVal - FalseVal, FalseVal);
9397 IsCZERO_NEZ ? FalseVal - TrueVal : TrueVal - FalseVal,
DL, VT);
9399 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9400 DL, VT, LHSVal, CondV);
9408 SDValue ConstVal = IsCZERO_NEZ ? TrueV : FalseV;
9409 SDValue RegV = IsCZERO_NEZ ? FalseV : TrueV;
9412 if (RawConstVal == -0x800) {
9415 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9416 DL, VT, XorOp, CondV);
9424 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9425 DL, VT, SubOp, CondV);
9432 if (!Subtarget.hasConditionalMoveFusion())
9435 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV),
9436 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV),
9440 if (
Op.hasOneUse()) {
9441 unsigned UseOpc =
Op->user_begin()->getOpcode();
9443 SDNode *BinOp = *
Op->user_begin();
9450 return lowerSELECT(NewSel, DAG);
9504 if (TrueVal - 1 == FalseVal)
9506 if (TrueVal + 1 == FalseVal)
9513 RHS == TrueV &&
LHS == FalseV) {
9544 MVT XLenVT = Subtarget.getXLenVT();
9555 return DAG.
getNode(RISCVISD::BR_CC,
DL,
Op.getValueType(),
Op.getOperand(0),
9556 LHS,
RHS, TargetCC,
Op.getOperand(2));
9559 return DAG.
getNode(RISCVISD::BR_CC,
DL,
Op.getValueType(),
Op.getOperand(0),
9566 RISCVMachineFunctionInfo *FuncInfo = MF.
getInfo<RISCVMachineFunctionInfo>();
9576 MachinePointerInfo(SV));
9581 const RISCVRegisterInfo &RI = *Subtarget.getRegisterInfo();
9586 int XLenInBytes = Subtarget.getXLen() / 8;
9588 EVT VT =
Op.getValueType();
9591 unsigned Depth =
Op.getConstantOperandVal(0);
9593 int Offset = -(XLenInBytes * 2);
9605 const RISCVRegisterInfo &RI = *Subtarget.getRegisterInfo();
9609 MVT XLenVT = Subtarget.getXLenVT();
9610 int XLenInBytes = Subtarget.getXLen() / 8;
9612 EVT VT =
Op.getValueType();
9614 unsigned Depth =
Op.getConstantOperandVal(0);
9616 int Off = -XLenInBytes;
9617 SDValue FrameAddr = lowerFRAMEADDR(
Op, DAG);
9621 MachinePointerInfo());
9636 EVT VT =
Lo.getValueType();
9675 EVT VT =
Lo.getValueType();
9726 MVT VT =
Op.getSimpleValueType();
9731 return DAG.
getNode(RISCVISD::VMSET_VL,
DL, VT, VL);
9735 return DAG.
getNode(RISCVISD::VMCLR_VL,
DL, VT, VL);
9752 MVT VecVT =
Op.getSimpleValueType();
9754 "Unexpected SPLAT_VECTOR_PARTS lowering");
9760 MVT ContainerVT = VecVT;
9780 int64_t ExtTrueVal)
const {
9782 MVT VecVT =
Op.getSimpleValueType();
9785 assert(Src.getValueType().isVector() &&
9786 Src.getValueType().getVectorElementType() == MVT::i1);
9806 MVT XLenVT = Subtarget.getXLenVT();
9812 if (
Xor.getOpcode() == RISCVISD::VMXOR_VL) {
9824 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9825 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
9826 SplatTrueVal = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9827 DAG.
getUNDEF(ContainerVT), SplatTrueVal, VL);
9829 DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, CC, SplatTrueVal,
9830 SplatZero, DAG.
getUNDEF(ContainerVT), VL);
9840 bool IsVPTrunc =
Op.getOpcode() == ISD::VP_TRUNCATE;
9842 EVT MaskVT =
Op.getValueType();
9845 "Unexpected type for vector mask lowering");
9847 MVT VecVT = Src.getSimpleValueType();
9851 VL =
Op.getOperand(2);
9854 MVT ContainerVT = VecVT;
9860 MVT MaskContainerVT =
9867 std::tie(Mask, VL) =
9874 SplatOne = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9875 DAG.
getUNDEF(ContainerVT), SplatOne, VL);
9876 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9877 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
9880 SDValue Trunc = DAG.
getNode(RISCVISD::AND_VL,
DL, ContainerVT, Src, SplatOne,
9881 DAG.
getUNDEF(ContainerVT), Mask, VL);
9882 Trunc = DAG.
getNode(RISCVISD::SETCC_VL,
DL, MaskContainerVT,
9892 unsigned Opc =
Op.getOpcode();
9893 bool IsVPTrunc =
Opc == ISD::VP_TRUNCATE;
9896 MVT VT =
Op.getSimpleValueType();
9898 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
9902 return lowerVectorMaskTruncLike(
Op, DAG);
9910 MVT SrcVT = Src.getSimpleValueType();
9915 "Unexpected vector truncate lowering");
9917 MVT ContainerVT = SrcVT;
9921 VL =
Op.getOperand(2);
9934 std::tie(Mask, VL) =
9940 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL_SSAT;
9942 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL_USAT;
9944 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL;
9950 }
while (SrcEltVT != DstEltVT);
9959RISCVTargetLowering::lowerStrictFPExtendOrRoundLike(
SDValue Op,
9964 MVT VT =
Op.getSimpleValueType();
9965 MVT SrcVT = Src.getSimpleValueType();
9966 MVT ContainerVT = VT;
9985 ? RISCVISD::STRICT_FP_EXTEND_VL
9986 : RISCVISD::STRICT_VFNCVT_ROD_VL;
9989 Chain, Src, Mask, VL);
9990 Chain = Src.getValue(1);
9994 ? RISCVISD::STRICT_FP_EXTEND_VL
9995 : RISCVISD::STRICT_FP_ROUND_VL;
9997 Chain, Src, Mask, VL);
10008RISCVTargetLowering::lowerVectorFPExtendOrRoundLike(
SDValue Op,
10011 Op.getOpcode() == ISD::VP_FP_ROUND ||
Op.getOpcode() == ISD::VP_FP_EXTEND;
10013 Op.getOpcode() == ISD::VP_FP_EXTEND ||
Op.getOpcode() == ISD::FP_EXTEND;
10018 MVT VT =
Op.getSimpleValueType();
10020 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
10023 MVT SrcVT = Src.getSimpleValueType();
10025 bool IsDirectExtend =
10033 bool IsDirectConv = IsDirectExtend || IsDirectTrunc;
10040 MVT ContainerVT = VT;
10043 Mask =
Op.getOperand(1);
10044 VL =
Op.getOperand(2);
10058 std::tie(Mask, VL) =
10061 unsigned ConvOpc = IsExtend ? RISCVISD::FP_EXTEND_VL : RISCVISD::FP_ROUND_VL;
10063 if (IsDirectConv) {
10064 Src = DAG.
getNode(ConvOpc,
DL, ContainerVT, Src, Mask, VL);
10070 unsigned InterConvOpc =
10071 IsExtend ? RISCVISD::FP_EXTEND_VL : RISCVISD::VFNCVT_ROD_VL;
10075 DAG.
getNode(InterConvOpc,
DL, InterVT, Src, Mask, VL);
10077 DAG.
getNode(ConvOpc,
DL, ContainerVT, IntermediateConv, Mask, VL);
10088static std::optional<MVT>
10094 const unsigned MinVLMAX = VectorBitsMin / EltSize;
10096 if (MaxIdx < MinVLMAX)
10098 else if (MaxIdx < MinVLMAX * 2)
10101 else if (MaxIdx < MinVLMAX * 4)
10106 return std::nullopt;
10114 return isUInt<5>(IdxC->getZExtValue());
10126 MVT VecVT =
Op.getSimpleValueType();
10127 MVT XLenVT = Subtarget.getXLenVT();
10142 if ((ValVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
10143 ValVT == MVT::bf16) {
10148 DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Val), Idx);
10152 MVT ContainerVT = VecVT;
10162 std::optional<unsigned> AlignedIdx;
10164 const unsigned OrigIdx = IdxC->getZExtValue();
10167 DL, DAG, Subtarget)) {
10168 ContainerVT = *ShrunkVT;
10176 if (
auto VLEN = Subtarget.getRealVLen(); VLEN && ContainerVT.
bitsGT(M1VT)) {
10179 unsigned RemIdx = OrigIdx % ElemsPerVReg;
10180 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
10183 ContainerVT = M1VT;
10190 bool IsLegalInsert = Subtarget.is64Bit() || Val.
getValueType() != MVT::i64;
10198 IsLegalInsert =
true;
10207 if (IsLegalInsert) {
10209 VecVT.
isFloatingPoint() ? RISCVISD::VFMV_S_F_VL : RISCVISD::VMV_S_X_VL;
10213 Vec = DAG.
getNode(
Opc,
DL, ContainerVT, Vec, Val, VL);
10223 if (Subtarget.hasVendorXRivosVisni() && VecVT.
isInteger() &&
10228 Vec = DAG.
getNode(RISCVISD::RI_VINSERT_VL,
DL, ContainerVT, Vec, Val, Idx,
10244 std::tie(ValLo, ValHi) = DAG.
SplitScalar(Val,
DL, MVT::i32, MVT::i32);
10245 MVT I32ContainerVT =
10255 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10256 Vec, Vec, ValLo, I32Mask, InsertI64VL);
10260 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10261 Tail, ValInVec, ValHi, I32Mask, InsertI64VL);
10263 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
10274 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10276 DAG.
getUNDEF(I32ContainerVT), ValLo,
10277 I32Mask, InsertI64VL);
10278 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10279 DAG.
getUNDEF(I32ContainerVT), ValInVec, ValHi,
10280 I32Mask, InsertI64VL);
10282 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
10295 Idx, Mask, InsertVL, Policy);
10313 EVT EltVT =
Op.getValueType();
10315 MVT XLenVT = Subtarget.getXLenVT();
10320 MVT ContainerVT = VecVT;
10327 DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Vec, Mask, VL);
10334 if (NumElts >= 8) {
10336 unsigned WidenVecLen;
10339 unsigned MaxEEW = Subtarget.getELen();
10344 "the number of elements should be power of 2");
10348 ExtractBitIdx = Idx;
10350 WideEltVT = LargestEltVT;
10353 ExtractElementIdx = DAG.
getNode(
10362 Vec = DAG.
getNode(ISD::BITCAST,
DL, WideVT, Vec);
10364 Vec, ExtractElementIdx);
10379 if ((EltVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
10380 EltVT == MVT::bf16) {
10386 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, EltVT, IntExtract);
10390 MVT ContainerVT = VecVT;
10400 const auto VLen = Subtarget.getRealVLen();
10402 IdxC && VLen && VecVT.
getSizeInBits().getKnownMinValue() > *VLen) {
10404 unsigned OrigIdx = IdxC->getZExtValue();
10407 unsigned RemIdx = OrigIdx % ElemsPerVReg;
10408 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
10409 unsigned ExtractIdx =
10413 ContainerVT = M1VT;
10418 std::optional<uint64_t> MaxIdx;
10422 MaxIdx = IdxC->getZExtValue();
10424 if (
auto SmallerVT =
10426 ContainerVT = *SmallerVT;
10433 if (Subtarget.hasVendorXRivosVisni() && EltVT.
isInteger() &&
10461 DAG.
getUNDEF(ContainerVT), Vec, Idx, Mask, VL);
10480 "Unexpected opcode");
10487 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
10492 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
10493 if (!
II || !
II->hasScalarOperand())
10496 unsigned SplatOp =
II->ScalarOperand + 1 + HasChain;
10497 assert(SplatOp <
Op.getNumOperands());
10509 if (OpVT.
bitsLT(XLenVT)) {
10516 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
10526 assert(
II->ScalarOperand > 0 &&
"Unexpected splat operand!");
10527 MVT VT =
Op.getOperand(SplatOp - 1).getSimpleValueType();
10530 assert(XLenVT == MVT::i32 && OpVT == MVT::i64 &&
10541 case Intrinsic::riscv_vslide1up:
10542 case Intrinsic::riscv_vslide1down:
10543 case Intrinsic::riscv_vslide1up_mask:
10544 case Intrinsic::riscv_vslide1down_mask: {
10546 unsigned NumOps =
Op.getNumOperands();
10547 bool IsMasked =
NumOps == 7;
10553 std::tie(ScalarLo, ScalarHi) =
10562 const auto [MinVLMAX, MaxVLMAX] =
10566 if (AVLInt <= MinVLMAX) {
10568 }
else if (AVLInt >= 2 * MaxVLMAX) {
10602 if (IntNo == Intrinsic::riscv_vslide1up ||
10603 IntNo == Intrinsic::riscv_vslide1up_mask) {
10604 Vec = DAG.
getNode(RISCVISD::VSLIDE1UP_VL,
DL, I32VT, Passthru, Vec,
10605 ScalarHi, I32Mask, I32VL);
10606 Vec = DAG.
getNode(RISCVISD::VSLIDE1UP_VL,
DL, I32VT, Passthru, Vec,
10607 ScalarLo, I32Mask, I32VL);
10609 Vec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32VT, Passthru, Vec,
10610 ScalarLo, I32Mask, I32VL);
10611 Vec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32VT, Passthru, Vec,
10612 ScalarHi, I32Mask, I32VL);
10630 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, Mask, Vec, MaskedOff,
10634 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, Mask, Vec, MaskedOff,
10661 const unsigned ElementWidth = 8;
10666 [[maybe_unused]]
unsigned MinVF =
10669 [[maybe_unused]]
unsigned VF =
N->getConstantOperandVal(2);
10673 bool Fractional = VF < LMul1VF;
10674 unsigned LMulVal = Fractional ? LMul1VF / VF : VF / LMul1VF;
10695 MVT ContainerVT = OpVT;
10703 SDValue Res = DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Op0, Mask, VL);
10711 return DAG.
getSelect(
DL, XLenVT, Setcc, VL, Res);
10722 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
10726 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
10727 if (!
II || !
II->hasScalarOperand())
10730 unsigned SplatOp =
II->ScalarOperand + 1;
10731 assert(SplatOp <
Op.getNumOperands());
10743 if (OpVT.
bitsLT(XLenVT)) {
10746 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
10757 EVT ValType = V.getValueType();
10758 if (ValType.isVector() && ValType.isFloatingPoint()) {
10761 ValType.getVectorElementCount());
10764 if (ValType.isFixedLengthVector()) {
10766 DAG, V.getSimpleValueType(), Subtarget);
10782 unsigned IntNo =
Op.getConstantOperandVal(0);
10784 MVT XLenVT = Subtarget.getXLenVT();
10789 case Intrinsic::riscv_tuple_insert: {
10794 return DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL,
Op.getValueType(), Vec,
10797 case Intrinsic::riscv_tuple_extract: {
10801 return DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL,
Op.getValueType(), Vec,
10804 case Intrinsic::thread_pointer: {
10808 case Intrinsic::riscv_orc_b:
10809 case Intrinsic::riscv_brev8:
10810 case Intrinsic::riscv_sha256sig0:
10811 case Intrinsic::riscv_sha256sig1:
10812 case Intrinsic::riscv_sha256sum0:
10813 case Intrinsic::riscv_sha256sum1:
10814 case Intrinsic::riscv_sm3p0:
10815 case Intrinsic::riscv_sm3p1: {
10818 case Intrinsic::riscv_orc_b:
Opc = RISCVISD::ORC_B;
break;
10819 case Intrinsic::riscv_brev8:
Opc = RISCVISD::BREV8;
break;
10820 case Intrinsic::riscv_sha256sig0:
Opc = RISCVISD::SHA256SIG0;
break;
10821 case Intrinsic::riscv_sha256sig1:
Opc = RISCVISD::SHA256SIG1;
break;
10822 case Intrinsic::riscv_sha256sum0:
Opc = RISCVISD::SHA256SUM0;
break;
10823 case Intrinsic::riscv_sha256sum1:
Opc = RISCVISD::SHA256SUM1;
break;
10824 case Intrinsic::riscv_sm3p0:
Opc = RISCVISD::SM3P0;
break;
10825 case Intrinsic::riscv_sm3p1:
Opc = RISCVISD::SM3P1;
break;
10830 case Intrinsic::riscv_sm4ks:
10831 case Intrinsic::riscv_sm4ed: {
10833 IntNo == Intrinsic::riscv_sm4ks ? RISCVISD::SM4KS : RISCVISD::SM4ED;
10838 case Intrinsic::riscv_zip:
10839 case Intrinsic::riscv_unzip: {
10841 IntNo == Intrinsic::riscv_zip ? RISCVISD::ZIP : RISCVISD::UNZIP;
10844 case Intrinsic::riscv_mopr:
10845 return DAG.
getNode(RISCVISD::MOP_R,
DL, XLenVT,
Op.getOperand(1),
10848 case Intrinsic::riscv_moprr: {
10849 return DAG.
getNode(RISCVISD::MOP_RR,
DL, XLenVT,
Op.getOperand(1),
10850 Op.getOperand(2),
Op.getOperand(3));
10852 case Intrinsic::riscv_clmul:
10853 return DAG.
getNode(RISCVISD::CLMUL,
DL, XLenVT,
Op.getOperand(1),
10855 case Intrinsic::riscv_clmulh:
10856 case Intrinsic::riscv_clmulr: {
10858 IntNo == Intrinsic::riscv_clmulh ? RISCVISD::CLMULH : RISCVISD::CLMULR;
10861 case Intrinsic::experimental_get_vector_length:
10863 case Intrinsic::experimental_cttz_elts:
10865 case Intrinsic::riscv_vmv_x_s: {
10869 case Intrinsic::riscv_vfmv_f_s:
10871 case Intrinsic::riscv_vmv_v_x:
10873 Op.getOperand(3),
Op.getSimpleValueType(),
DL, DAG,
10875 case Intrinsic::riscv_vfmv_v_f:
10876 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL,
Op.getValueType(),
10877 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
10878 case Intrinsic::riscv_vmv_s_x: {
10881 if (
Scalar.getValueType().bitsLE(XLenVT)) {
10883 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL,
Op.getValueType(),
10884 Op.getOperand(1), Scalar,
Op.getOperand(3));
10887 assert(
Scalar.getValueType() == MVT::i64 &&
"Unexpected scalar VT!");
10904 MVT VT =
Op.getSimpleValueType();
10909 if (
Op.getOperand(1).isUndef())
10910 return SplattedVal;
10919 DAG.
getNode(RISCVISD::SETCC_VL,
DL, MaskVT,
10922 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, SelectCond, SplattedVal,
10925 case Intrinsic::riscv_vfmv_s_f:
10926 return DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL,
Op.getSimpleValueType(),
10927 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
10929 case Intrinsic::riscv_vaesdf_vv:
10930 case Intrinsic::riscv_vaesdf_vs:
10931 case Intrinsic::riscv_vaesdm_vv:
10932 case Intrinsic::riscv_vaesdm_vs:
10933 case Intrinsic::riscv_vaesef_vv:
10934 case Intrinsic::riscv_vaesef_vs:
10935 case Intrinsic::riscv_vaesem_vv:
10936 case Intrinsic::riscv_vaesem_vs:
10937 case Intrinsic::riscv_vaeskf1:
10938 case Intrinsic::riscv_vaeskf2:
10939 case Intrinsic::riscv_vaesz_vs:
10940 case Intrinsic::riscv_vsm4k:
10941 case Intrinsic::riscv_vsm4r_vv:
10942 case Intrinsic::riscv_vsm4r_vs: {
10943 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
10944 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
10945 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
10950 case Intrinsic::riscv_vsm3c:
10951 case Intrinsic::riscv_vsm3me: {
10952 if (!
isValidEGW(8,
Op.getSimpleValueType(), Subtarget) ||
10953 !
isValidEGW(8,
Op->getOperand(1).getSimpleValueType(), Subtarget))
10958 case Intrinsic::riscv_vsha2ch:
10959 case Intrinsic::riscv_vsha2cl:
10960 case Intrinsic::riscv_vsha2ms: {
10961 if (
Op->getSimpleValueType(0).getScalarSizeInBits() == 64 &&
10962 !Subtarget.hasStdExtZvknhb())
10964 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
10965 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
10966 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
10970 case Intrinsic::riscv_sf_vc_v_x:
10971 case Intrinsic::riscv_sf_vc_v_i:
10972 case Intrinsic::riscv_sf_vc_v_xv:
10973 case Intrinsic::riscv_sf_vc_v_iv:
10974 case Intrinsic::riscv_sf_vc_v_vv:
10975 case Intrinsic::riscv_sf_vc_v_fv:
10976 case Intrinsic::riscv_sf_vc_v_xvv:
10977 case Intrinsic::riscv_sf_vc_v_ivv:
10978 case Intrinsic::riscv_sf_vc_v_vvv:
10979 case Intrinsic::riscv_sf_vc_v_fvv:
10980 case Intrinsic::riscv_sf_vc_v_xvw:
10981 case Intrinsic::riscv_sf_vc_v_ivw:
10982 case Intrinsic::riscv_sf_vc_v_vvw:
10983 case Intrinsic::riscv_sf_vc_v_fvw: {
10984 MVT VT =
Op.getSimpleValueType();
11021 MVT VT =
Op.getSimpleValueType();
11025 if (VT.isFloatingPoint()) {
11027 VT.getVectorElementCount());
11030 if (VT.isFixedLengthVector())
11040 if (VT.isFixedLengthVector())
11042 if (VT.isFloatingPoint())
11065 case Intrinsic::riscv_seg2_load_mask:
11066 case Intrinsic::riscv_seg3_load_mask:
11067 case Intrinsic::riscv_seg4_load_mask:
11068 case Intrinsic::riscv_seg5_load_mask:
11069 case Intrinsic::riscv_seg6_load_mask:
11070 case Intrinsic::riscv_seg7_load_mask:
11071 case Intrinsic::riscv_seg8_load_mask:
11074 case Intrinsic::riscv_sseg2_load_mask:
11075 case Intrinsic::riscv_sseg3_load_mask:
11076 case Intrinsic::riscv_sseg4_load_mask:
11077 case Intrinsic::riscv_sseg5_load_mask:
11078 case Intrinsic::riscv_sseg6_load_mask:
11079 case Intrinsic::riscv_sseg7_load_mask:
11080 case Intrinsic::riscv_sseg8_load_mask:
11088 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
11089 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
11090 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
11091 Intrinsic::riscv_vlseg8_mask};
11093 Intrinsic::riscv_vlsseg2_mask, Intrinsic::riscv_vlsseg3_mask,
11094 Intrinsic::riscv_vlsseg4_mask, Intrinsic::riscv_vlsseg5_mask,
11095 Intrinsic::riscv_vlsseg6_mask, Intrinsic::riscv_vlsseg7_mask,
11096 Intrinsic::riscv_vlsseg8_mask};
11099 unsigned NF =
Op->getNumValues() - 1;
11100 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
11102 MVT VT =
Op->getSimpleValueType(0);
11110 SDValue VL =
Op.getOperand(
Op.getNumOperands() - 1);
11111 SDValue Mask =
Op.getOperand(
Op.getNumOperands() - 2);
11112 MVT MaskVT = Mask.getSimpleValueType();
11113 MVT MaskContainerVT =
11118 IsStrided ? VlssegInts[NF - 2] : VlsegInts[NF - 2],
DL, XLenVT);
11134 Ops.insert(std::next(
Ops.begin(), 4),
Op.getOperand(3));
11138 Load->getMemoryVT(), Load->getMemOperand());
11140 for (
unsigned int RetIdx = 0; RetIdx < NF; RetIdx++) {
11142 Result.getValue(0),
11146 Results.push_back(Result.getValue(1));
11152 unsigned IntNo =
Op.getConstantOperandVal(1);
11156 case Intrinsic::riscv_seg2_load_mask:
11157 case Intrinsic::riscv_seg3_load_mask:
11158 case Intrinsic::riscv_seg4_load_mask:
11159 case Intrinsic::riscv_seg5_load_mask:
11160 case Intrinsic::riscv_seg6_load_mask:
11161 case Intrinsic::riscv_seg7_load_mask:
11162 case Intrinsic::riscv_seg8_load_mask:
11163 case Intrinsic::riscv_sseg2_load_mask:
11164 case Intrinsic::riscv_sseg3_load_mask:
11165 case Intrinsic::riscv_sseg4_load_mask:
11166 case Intrinsic::riscv_sseg5_load_mask:
11167 case Intrinsic::riscv_sseg6_load_mask:
11168 case Intrinsic::riscv_sseg7_load_mask:
11169 case Intrinsic::riscv_sseg8_load_mask:
11172 case Intrinsic::riscv_sf_vc_v_x_se:
11174 case Intrinsic::riscv_sf_vc_v_i_se:
11176 case Intrinsic::riscv_sf_vc_v_xv_se:
11178 case Intrinsic::riscv_sf_vc_v_iv_se:
11180 case Intrinsic::riscv_sf_vc_v_vv_se:
11182 case Intrinsic::riscv_sf_vc_v_fv_se:
11184 case Intrinsic::riscv_sf_vc_v_xvv_se:
11186 case Intrinsic::riscv_sf_vc_v_ivv_se:
11188 case Intrinsic::riscv_sf_vc_v_vvv_se:
11190 case Intrinsic::riscv_sf_vc_v_fvv_se:
11192 case Intrinsic::riscv_sf_vc_v_xvw_se:
11194 case Intrinsic::riscv_sf_vc_v_ivw_se:
11196 case Intrinsic::riscv_sf_vc_v_vvw_se:
11198 case Intrinsic::riscv_sf_vc_v_fvw_se:
11211 case Intrinsic::riscv_seg2_store_mask:
11212 case Intrinsic::riscv_seg3_store_mask:
11213 case Intrinsic::riscv_seg4_store_mask:
11214 case Intrinsic::riscv_seg5_store_mask:
11215 case Intrinsic::riscv_seg6_store_mask:
11216 case Intrinsic::riscv_seg7_store_mask:
11217 case Intrinsic::riscv_seg8_store_mask:
11220 case Intrinsic::riscv_sseg2_store_mask:
11221 case Intrinsic::riscv_sseg3_store_mask:
11222 case Intrinsic::riscv_sseg4_store_mask:
11223 case Intrinsic::riscv_sseg5_store_mask:
11224 case Intrinsic::riscv_sseg6_store_mask:
11225 case Intrinsic::riscv_sseg7_store_mask:
11226 case Intrinsic::riscv_sseg8_store_mask:
11235 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
11236 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
11237 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
11238 Intrinsic::riscv_vsseg8_mask};
11240 Intrinsic::riscv_vssseg2_mask, Intrinsic::riscv_vssseg3_mask,
11241 Intrinsic::riscv_vssseg4_mask, Intrinsic::riscv_vssseg5_mask,
11242 Intrinsic::riscv_vssseg6_mask, Intrinsic::riscv_vssseg7_mask,
11243 Intrinsic::riscv_vssseg8_mask};
11247 unsigned NF =
Op->getNumOperands() - (IsStrided ? 6 : 5);
11248 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
11250 MVT VT =
Op->getOperand(2).getSimpleValueType();
11256 SDValue VL =
Op.getOperand(
Op.getNumOperands() - 1);
11257 SDValue Mask =
Op.getOperand(
Op.getNumOperands() - 2);
11258 MVT MaskVT = Mask.getSimpleValueType();
11259 MVT MaskContainerVT =
11264 IsStrided ? VsssegInts[NF - 2] : VssegInts[NF - 2],
DL, XLenVT);
11270 for (
unsigned i = 0; i < NF; i++)
11272 RISCVISD::TUPLE_INSERT,
DL, VecTupTy, StoredVal,
11278 FixedIntrinsic->getChain(),
11287 Ops.insert(std::next(
Ops.begin(), 4),
11288 Op.getOperand(
Op.getNumOperands() - 3));
11292 FixedIntrinsic->getMemoryVT(), FixedIntrinsic->getMemOperand());
11297 unsigned IntNo =
Op.getConstantOperandVal(1);
11301 case Intrinsic::riscv_seg2_store_mask:
11302 case Intrinsic::riscv_seg3_store_mask:
11303 case Intrinsic::riscv_seg4_store_mask:
11304 case Intrinsic::riscv_seg5_store_mask:
11305 case Intrinsic::riscv_seg6_store_mask:
11306 case Intrinsic::riscv_seg7_store_mask:
11307 case Intrinsic::riscv_seg8_store_mask:
11308 case Intrinsic::riscv_sseg2_store_mask:
11309 case Intrinsic::riscv_sseg3_store_mask:
11310 case Intrinsic::riscv_sseg4_store_mask:
11311 case Intrinsic::riscv_sseg5_store_mask:
11312 case Intrinsic::riscv_sseg6_store_mask:
11313 case Intrinsic::riscv_sseg7_store_mask:
11314 case Intrinsic::riscv_sseg8_store_mask:
11317 case Intrinsic::riscv_sf_vc_xv_se:
11319 case Intrinsic::riscv_sf_vc_iv_se:
11321 case Intrinsic::riscv_sf_vc_vv_se:
11323 case Intrinsic::riscv_sf_vc_fv_se:
11325 case Intrinsic::riscv_sf_vc_xvv_se:
11327 case Intrinsic::riscv_sf_vc_ivv_se:
11329 case Intrinsic::riscv_sf_vc_vvv_se:
11331 case Intrinsic::riscv_sf_vc_fvv_se:
11333 case Intrinsic::riscv_sf_vc_xvw_se:
11335 case Intrinsic::riscv_sf_vc_ivw_se:
11337 case Intrinsic::riscv_sf_vc_vvw_se:
11339 case Intrinsic::riscv_sf_vc_fvw_se:
11347 switch (ISDOpcode) {
11350 case ISD::VP_REDUCE_ADD:
11351 case ISD::VECREDUCE_ADD:
11352 return RISCVISD::VECREDUCE_ADD_VL;
11353 case ISD::VP_REDUCE_UMAX:
11354 case ISD::VECREDUCE_UMAX:
11355 return RISCVISD::VECREDUCE_UMAX_VL;
11356 case ISD::VP_REDUCE_SMAX:
11357 case ISD::VECREDUCE_SMAX:
11358 return RISCVISD::VECREDUCE_SMAX_VL;
11359 case ISD::VP_REDUCE_UMIN:
11360 case ISD::VECREDUCE_UMIN:
11361 return RISCVISD::VECREDUCE_UMIN_VL;
11362 case ISD::VP_REDUCE_SMIN:
11363 case ISD::VECREDUCE_SMIN:
11364 return RISCVISD::VECREDUCE_SMIN_VL;
11365 case ISD::VP_REDUCE_AND:
11366 case ISD::VECREDUCE_AND:
11367 return RISCVISD::VECREDUCE_AND_VL;
11368 case ISD::VP_REDUCE_OR:
11369 case ISD::VECREDUCE_OR:
11370 return RISCVISD::VECREDUCE_OR_VL;
11371 case ISD::VP_REDUCE_XOR:
11372 case ISD::VECREDUCE_XOR:
11373 return RISCVISD::VECREDUCE_XOR_VL;
11374 case ISD::VP_REDUCE_FADD:
11375 return RISCVISD::VECREDUCE_FADD_VL;
11376 case ISD::VP_REDUCE_SEQ_FADD:
11377 return RISCVISD::VECREDUCE_SEQ_FADD_VL;
11378 case ISD::VP_REDUCE_FMAX:
11379 case ISD::VP_REDUCE_FMAXIMUM:
11380 return RISCVISD::VECREDUCE_FMAX_VL;
11381 case ISD::VP_REDUCE_FMIN:
11382 case ISD::VP_REDUCE_FMINIMUM:
11383 return RISCVISD::VECREDUCE_FMIN_VL;
11392 SDValue Vec =
Op.getOperand(IsVP ? 1 : 0);
11394 assert((
Op.getOpcode() == ISD::VECREDUCE_AND ||
11395 Op.getOpcode() == ISD::VECREDUCE_OR ||
11396 Op.getOpcode() == ISD::VECREDUCE_XOR ||
11397 Op.getOpcode() == ISD::VP_REDUCE_AND ||
11398 Op.getOpcode() == ISD::VP_REDUCE_OR ||
11399 Op.getOpcode() == ISD::VP_REDUCE_XOR) &&
11400 "Unexpected reduction lowering");
11402 MVT XLenVT = Subtarget.getXLenVT();
11404 MVT ContainerVT = VecVT;
11412 Mask =
Op.getOperand(2);
11413 VL =
Op.getOperand(3);
11415 std::tie(Mask, VL) =
11420 switch (
Op.getOpcode()) {
11423 case ISD::VECREDUCE_AND:
11424 case ISD::VP_REDUCE_AND: {
11428 Vec = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Vec, TrueMask, VL);
11431 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11435 case ISD::VECREDUCE_OR:
11436 case ISD::VP_REDUCE_OR:
11438 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11441 case ISD::VECREDUCE_XOR:
11442 case ISD::VP_REDUCE_XOR: {
11445 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11466 return DAG.
getNode(BaseOpc,
DL,
Op.getValueType(), SetCC,
Op.getOperand(0));
11472 return (RegisterAVL && RegisterAVL->getReg() == RISCV::X0) ||
11473 (ImmAVL && ImmAVL->getZExtValue() >= 1);
11489 auto InnerVT = VecVT.
bitsLE(M1VT) ? VecVT : M1VT;
11493 auto InnerVL = NonZeroAVL ? VL : DAG.
getConstant(1,
DL, XLenVT);
11496 if (M1VT != InnerVT)
11501 SDValue Ops[] = {PassThru, Vec, InitialValue, Mask, VL, Policy};
11519 VecEVT =
Lo.getValueType();
11532 MVT ContainerVT = VecVT;
11551 Mask, VL,
DL, DAG, Subtarget);
11557static std::tuple<unsigned, SDValue, SDValue>
11561 auto Flags =
Op->getFlags();
11562 unsigned Opcode =
Op.getOpcode();
11566 case ISD::VECREDUCE_FADD: {
11570 return std::make_tuple(RISCVISD::VECREDUCE_FADD_VL,
Op.getOperand(0), Zero);
11572 case ISD::VECREDUCE_SEQ_FADD:
11573 return std::make_tuple(RISCVISD::VECREDUCE_SEQ_FADD_VL,
Op.getOperand(1),
11575 case ISD::VECREDUCE_FMINIMUM:
11576 case ISD::VECREDUCE_FMAXIMUM:
11577 case ISD::VECREDUCE_FMIN:
11578 case ISD::VECREDUCE_FMAX: {
11581 (Opcode == ISD::VECREDUCE_FMIN || Opcode == ISD::VECREDUCE_FMINIMUM)
11582 ? RISCVISD::VECREDUCE_FMIN_VL
11583 : RISCVISD::VECREDUCE_FMAX_VL;
11584 return std::make_tuple(RVVOpc,
Op.getOperand(0), Front);
11592 MVT VecEltVT =
Op.getSimpleValueType();
11594 unsigned RVVOpcode;
11595 SDValue VectorVal, ScalarVal;
11596 std::tie(RVVOpcode, VectorVal, ScalarVal) =
11600 MVT ContainerVT = VecVT;
11606 MVT ResVT =
Op.getSimpleValueType();
11609 VL,
DL, DAG, Subtarget);
11610 if (
Op.getOpcode() != ISD::VECREDUCE_FMINIMUM &&
11611 Op.getOpcode() != ISD::VECREDUCE_FMAXIMUM)
11614 if (
Op->getFlags().hasNoNaNs())
11620 {VectorVal, VectorVal, DAG.getCondCode(ISD::SETNE),
11621 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
11622 MVT XLenVT = Subtarget.getXLenVT();
11623 SDValue CPop = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, IsNan, Mask, VL);
11627 DL, ResVT, NoNaNs, Res,
11634 unsigned Opc =
Op.getOpcode();
11638 MVT XLenVT = Subtarget.getXLenVT();
11657 Vec, Mask, VL,
DL, DAG, Subtarget);
11658 if ((
Opc != ISD::VP_REDUCE_FMINIMUM &&
Opc != ISD::VP_REDUCE_FMAXIMUM) ||
11659 Op->getFlags().hasNoNaNs())
11666 RISCVISD::SETCC_VL,
DL, PredVT,
11668 SDValue VCPop = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, IsNaN, Mask, VL);
11676 DL, ResVT, NoNaNs, Res,
11688 MVT XLenVT = Subtarget.getXLenVT();
11689 unsigned OrigIdx =
Op.getConstantOperandVal(2);
11690 const RISCVRegisterInfo *
TRI = Subtarget.getRegisterInfo();
11692 if (OrigIdx == 0 && Vec.
isUndef())
11703 assert(OrigIdx % 8 == 0 &&
"Invalid index");
11706 "Unexpected mask vector lowering");
11736 const auto VLen = Subtarget.getRealVLen();
11738 MVT ContainerVT = VecVT;
11760 if (OrigIdx == 0) {
11762 DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, ContainerVT, Vec, SubVec, VL);
11765 SubVec =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, Vec, SubVec,
11766 SlideupAmt, Mask, VL, Policy);
11774 MVT ContainerVecVT = VecVT;
11780 MVT ContainerSubVecVT = SubVecVT;
11786 unsigned SubRegIdx;
11787 ElementCount RemIdx;
11796 ContainerVecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
11797 SubRegIdx = Decompose.first;
11799 (OrigIdx % Vscale));
11803 ContainerVecVT, ContainerSubVecVT, OrigIdx,
TRI);
11804 SubRegIdx = Decompose.first;
11810 Subtarget.expandVScale(SubVecVT.
getSizeInBits()).getKnownMinValue()));
11811 bool ExactlyVecRegSized =
11813 .isKnownMultipleOf(Subtarget.expandVScale(VecRegSize));
11828 if (RemIdx.
isZero() && (ExactlyVecRegSized || Vec.
isUndef())) {
11832 if (SubRegIdx == RISCV::NoSubRegister) {
11854 MVT InterSubVT = ContainerVecVT;
11855 SDValue AlignedExtract = Vec;
11877 if (Subtarget.expandVScale(EndIndex) ==
11884 SubVec = DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, InterSubVT, AlignedExtract,
11892 SubVec =
getVSlideup(DAG, Subtarget,
DL, InterSubVT, AlignedExtract, SubVec,
11893 SlideupAmt, Mask, VL, Policy);
11898 if (ContainerVecVT.
bitsGT(InterSubVT))
11906 return DAG.
getBitcast(
Op.getSimpleValueType(), SubVec);
11912 MVT SubVecVT =
Op.getSimpleValueType();
11916 MVT XLenVT = Subtarget.getXLenVT();
11917 unsigned OrigIdx =
Op.getConstantOperandVal(1);
11918 const RISCVRegisterInfo *
TRI = Subtarget.getRegisterInfo();
11933 assert(OrigIdx % 8 == 0 &&
"Invalid index");
11936 "Unexpected mask vector lowering");
11962 const auto VLen = Subtarget.getRealVLen();
11970 MVT ContainerVT = VecVT;
11978 if (
auto ShrunkVT =
11980 ContainerVT = *ShrunkVT;
11992 DAG.
getUNDEF(ContainerVT), Vec, SlidedownAmt, Mask, VL);
12003 MVT ContainerSubVecVT = SubVecVT;
12007 unsigned SubRegIdx;
12008 ElementCount RemIdx;
12017 VecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
12018 SubRegIdx = Decompose.first;
12020 (OrigIdx % Vscale));
12024 VecVT, ContainerSubVecVT, OrigIdx,
TRI);
12025 SubRegIdx = Decompose.first;
12052 MVT InterSubVT = VecVT;
12057 assert(SubRegIdx != RISCV::NoSubRegister);
12076 Vec, SlidedownAmt, Mask, VL);
12084 return DAG.
getBitcast(
Op.getSimpleValueType(), Slidedown);
12091 MVT VT =
N.getSimpleValueType();
12095 assert(
Op.getSimpleValueType() == VT &&
12096 "Operands and result must be same type");
12100 unsigned NumVals =
N->getNumValues();
12103 NumVals,
N.getValueType().changeVectorElementType(MVT::i8)));
12106 for (
unsigned I = 0;
I < NumVals;
I++) {
12112 if (TruncVals.
size() > 1)
12114 return TruncVals.
front();
12120 MVT VecVT =
Op.getSimpleValueType();
12122 const unsigned Factor =
Op->getNumValues();
12133 for (
unsigned i = 0U; i < Factor; ++i)
12142 for (
unsigned i = 0U; i < Factor; ++i)
12152 for (
unsigned i = 0; i != Factor; ++i) {
12155 Ops[i * 2 + 1] = OpHi;
12166 for (
unsigned i = 0; i != Factor; ++i)
12173 if (Subtarget.hasVendorXRivosVizip() && Factor == 2) {
12174 MVT VT =
Op->getSimpleValueType(0);
12199 lowerVZIP(RISCVISD::RI_VUNZIP2A_VL, V1, V2,
DL, DAG, Subtarget);
12201 lowerVZIP(RISCVISD::RI_VUNZIP2B_VL, V1, V2,
DL, DAG, Subtarget);
12234 EvenSplat = DAG.
getBitcast(MVT::nxv64i1, EvenSplat);
12238 OddSplat = DAG.
getBitcast(MVT::nxv64i1, OddSplat);
12243 EvenMask, DAG.
getUNDEF(ConcatVT));
12255 MVT XLenVT = Subtarget.getXLenVT();
12277 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
12278 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
12279 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
12280 Intrinsic::riscv_vlseg8_mask};
12304 for (
unsigned i = 0U; i < Factor; ++i)
12305 Res[i] = DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL, VecVT, Load,
12314 MVT VecVT =
Op.getSimpleValueType();
12327 for (
unsigned i = 0U; i < Factor; ++i)
12335 for (
unsigned i = 0U; i < Factor; ++i)
12341 MVT XLenVT = Subtarget.getXLenVT();
12348 for (
unsigned i = 0; i != Factor; ++i) {
12351 Ops[i + Factor] = OpHi;
12362 for (
unsigned i = 0; i != Factor; ++i) {
12363 unsigned IdxLo = 2 * i;
12364 unsigned IdxHi = 2 * i + 1;
12366 Res[IdxLo / Factor].getValue(IdxLo % Factor),
12367 Res[IdxHi / Factor].getValue(IdxHi % Factor));
12385 EVT PtrVT =
StackPtr.getValueType();
12391 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
12392 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
12393 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
12394 Intrinsic::riscv_vsseg8_mask,
12402 for (
unsigned i = 0; i < Factor; i++)
12404 DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VecTupTy, StoredVal,
12427 for (
unsigned i = 0; i != Factor; ++i) {
12431 Loads[i] = DAG.
getLoad(VecVT,
DL, Chain, StackPtr, PtrInfo);
12439 if (Subtarget.hasVendorXRivosVizip() && !
Op.getOperand(0).isUndef() &&
12440 !
Op.getOperand(1).isUndef()) {
12460 Op.getOperand(0),
Op.getOperand(1));
12484 DAG.
getNode(RISCVISD::ADD_VL,
DL, IdxVT, Idx, VLMax, Idx, OddMask, VL);
12489 Interleaved = DAG.
getNode(RISCVISD::VRGATHEREI16_VV_VL,
DL, ConcatVT,
12506 MVT VT =
Op.getSimpleValueType();
12508 MVT XLenVT = Subtarget.getXLenVT();
12511 uint64_t StepValImm =
Op.getConstantOperandVal(0);
12512 if (StepValImm != 1) {
12521 VL, VT,
DL, DAG, Subtarget);
12536 MVT VecVT =
Op.getSimpleValueType();
12545 MVT ContainerVT = VecVT;
12552 MVT XLenVT = Subtarget.getXLenVT();
12598 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
12599 unsigned MaxVLMAX =
12604 unsigned GatherOpc = RISCVISD::VRGATHER_VV_VL;
12609 if (MaxVLMAX > 256 && EltSize == 8) {
12623 LoVT.getVectorMinNumElements());
12628 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
12636 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
12661 DAG.
getUNDEF(ContainerVT), Mask, VL);
12672 MVT XLenVT = Subtarget.getXLenVT();
12673 MVT VecVT =
Op.getSimpleValueType();
12678 SDValue DownOffset, UpOffset;
12679 if (ImmValue >= 0) {
12694 DAG, Subtarget,
DL, VecVT, DAG.
getUNDEF(VecVT), V1, DownOffset, TrueMask,
12695 Subtarget.hasVLDependentLatency() ? UpOffset
12697 return getVSlideup(DAG, Subtarget,
DL, VecVT, SlideDown, V2, UpOffset,
12703RISCVTargetLowering::lowerFixedLengthVectorLoadToRVV(
SDValue Op,
12709 Load->getMemoryVT(),
12710 *
Load->getMemOperand()) &&
12711 "Expecting a correctly-aligned load");
12713 MVT VT =
Op.getSimpleValueType();
12714 MVT XLenVT = Subtarget.getXLenVT();
12719 const auto [MinVLMAX, MaxVLMAX] =
12723 MachineMemOperand *MMO =
Load->getMemOperand();
12736 IsMaskOp ? Intrinsic::riscv_vlm : Intrinsic::riscv_vle,
DL, XLenVT);
12740 Ops.push_back(
Load->getBasePtr());
12742 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
12745 Load->getMemoryVT(),
Load->getMemOperand());
12752RISCVTargetLowering::lowerFixedLengthVectorStoreToRVV(
SDValue Op,
12758 Store->getMemoryVT(),
12759 *
Store->getMemOperand()) &&
12760 "Expecting a correctly-aligned store");
12764 MVT XLenVT = Subtarget.getXLenVT();
12780 const auto [MinVLMAX, MaxVLMAX] =
12784 MachineMemOperand *MMO =
Store->getMemOperand();
12794 IsMaskOp ? Intrinsic::riscv_vsm : Intrinsic::riscv_vse,
DL, XLenVT);
12797 {Store->getChain(), IntID, NewValue, Store->getBasePtr(), VL},
12798 Store->getMemoryVT(),
Store->getMemOperand());
12804 MVT VT =
Op.getSimpleValueType();
12807 EVT MemVT = MemSD->getMemoryVT();
12808 MachineMemOperand *MMO = MemSD->getMemOperand();
12809 SDValue Chain = MemSD->getChain();
12813 bool IsExpandingLoad =
false;
12815 Mask = VPLoad->getMask();
12817 VL = VPLoad->getVectorLength();
12820 Mask = MLoad->getMask();
12821 PassThru = MLoad->getPassThru();
12822 IsExpandingLoad = MLoad->isExpandingLoad();
12827 MVT XLenVT = Subtarget.getXLenVT();
12829 MVT ContainerVT = VT;
12843 if (!IsUnmasked && IsExpandingLoad) {
12846 DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Mask,
12850 unsigned IntID = IsUnmasked || IsExpandingLoad ? Intrinsic::riscv_vle
12851 : Intrinsic::riscv_vle_mask;
12853 if (IntID == Intrinsic::riscv_vle)
12856 Ops.push_back(PassThru);
12857 Ops.push_back(BasePtr);
12858 if (IntID == Intrinsic::riscv_vle_mask)
12859 Ops.push_back(Mask);
12861 if (IntID == Intrinsic::riscv_vle_mask)
12864 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
12868 Chain =
Result.getValue(1);
12870 MVT IndexVT = ContainerVT;
12875 bool UseVRGATHEREI16 =
false;
12883 UseVRGATHEREI16 =
true;
12889 DAG.
getUNDEF(IndexVT), Mask, ExpandingVL);
12891 DAG.
getNode(UseVRGATHEREI16 ? RISCVISD::VRGATHEREI16_VV_VL
12892 : RISCVISD::VRGATHER_VV_VL,
12893 DL, ContainerVT, Result, Iota, PassThru, Mask, ExpandingVL);
12904 MVT VT =
Op->getSimpleValueType(0);
12907 EVT MemVT = VPLoadFF->getMemoryVT();
12908 MachineMemOperand *MMO = VPLoadFF->getMemOperand();
12909 SDValue Chain = VPLoadFF->getChain();
12913 SDValue VL = VPLoadFF->getVectorLength();
12915 MVT XLenVT = Subtarget.getXLenVT();
12917 MVT ContainerVT = VT;
12924 unsigned IntID = Intrinsic::riscv_vleff_mask;
12934 SDVTList VTs = DAG.
getVTList({ContainerVT,
Op->getValueType(1), MVT::Other});
12939 Chain =
Result.getValue(2);
12952 EVT MemVT = MemSD->getMemoryVT();
12953 MachineMemOperand *MMO = MemSD->getMemOperand();
12954 SDValue Chain = MemSD->getChain();
12958 bool IsCompressingStore =
false;
12960 Val = VPStore->getValue();
12961 Mask = VPStore->getMask();
12962 VL = VPStore->getVectorLength();
12965 Val = MStore->getValue();
12966 Mask = MStore->getMask();
12967 IsCompressingStore = MStore->isCompressingStore();
12974 MVT XLenVT = Subtarget.getXLenVT();
12976 MVT ContainerVT = VT;
12981 if (!IsUnmasked || IsCompressingStore) {
12990 if (IsCompressingStore) {
12993 DAG.
getUNDEF(ContainerVT), Val, Mask, VL);
12995 DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Mask,
13000 IsUnmasked ? Intrinsic::riscv_vse : Intrinsic::riscv_vse_mask;
13002 Ops.push_back(Val);
13003 Ops.push_back(BasePtr);
13005 Ops.push_back(Mask);
13020 MVT XLenVT = Subtarget.getXLenVT();
13021 MVT ContainerVT = VT;
13034 Passthru, Val, Mask, VL);
13044 unsigned Opc =
Op.getOpcode();
13051 MVT VT =
Op.getSimpleValueType();
13059 SDVTList VTList =
Op->getVTList();
13084 MVT ContainerInVT = InVT;
13102 RISCVISD::STRICT_FSETCC_VL,
DL, DAG.
getVTList(MaskVT, MVT::Other),
13103 {Chain, Op1, Op1, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
13106 RISCVISD::STRICT_FSETCC_VL,
DL, DAG.
getVTList(MaskVT, MVT::Other),
13107 {Chain, Op2, Op2, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
13110 DAG.
getNode(RISCVISD::VMAND_VL,
DL, MaskVT, OrderMask1, OrderMask2, VL);
13113 Res = DAG.
getNode(RISCVISD::STRICT_FSETCCS_VL,
DL,
13115 {Chain, Op1, Op2, CC, Mask, Mask, VL});
13118 : RISCVISD::STRICT_FSETCCS_VL;
13120 {Chain, Op1, Op2, CC, DAG.getUNDEF(MaskVT), Mask, VL});
13133 MVT VT =
Op.getSimpleValueType();
13137 "Unexpected type for ISD::ABS");
13139 MVT ContainerVT = VT;
13146 if (
Op->getOpcode() == ISD::VP_ABS) {
13147 Mask =
Op->getOperand(1);
13151 VL =
Op->getOperand(2);
13156 RISCVISD::VMV_V_X_VL,
DL, ContainerVT, DAG.
getUNDEF(ContainerVT),
13159 DAG.
getUNDEF(ContainerVT), Mask, VL);
13161 DAG.
getUNDEF(ContainerVT), Mask, VL);
13170 const auto &TSInfo =
13174 bool HasPassthruOp = TSInfo.hasPassthruOp(NewOpc);
13175 bool HasMask = TSInfo.hasMaskOp(NewOpc);
13177 MVT VT =
Op.getSimpleValueType();
13182 for (
const SDValue &V :
Op->op_values()) {
13186 if (!
V.getValueType().isVector()) {
13192 assert(useRVVForFixedLengthVectorVT(
V.getSimpleValueType()) &&
13193 "Only fixed length vectors are supported!");
13195 V.getSimpleValueType().getVectorElementType());
13204 Ops.push_back(Mask);
13209 if (
Op->isStrictFPOpcode()) {
13228 const auto &TSInfo =
13232 bool HasPassthruOp = TSInfo.hasPassthruOp(RISCVISDOpc);
13235 MVT VT =
Op.getSimpleValueType();
13238 MVT ContainerVT = VT;
13247 if (HasPassthruOp) {
13250 if (*MaskIdx ==
OpIdx.index())
13254 if (
Op.getOpcode() == ISD::VP_MERGE) {
13256 Ops.push_back(
Ops.back());
13258 assert(
Op.getOpcode() == ISD::VP_SELECT);
13265 if (RISCVISDOpc == RISCVISD::VFCVT_RM_X_F_VL &&
13268 Subtarget.getXLenVT()));
13270 if (!
V.getValueType().isFixedLengthVector()) {
13275 MVT OpVT =
V.getSimpleValueType();
13277 assert(useRVVForFixedLengthVectorVT(OpVT) &&
13278 "Only fixed length vectors are supported!");
13293 MVT VT =
Op.getSimpleValueType();
13299 MVT ContainerVT = VT;
13306 MVT XLenVT = Subtarget.getXLenVT();
13309 DAG.
getUNDEF(ContainerVT), Zero, VL);
13312 Op.getOpcode() == ISD::VP_ZERO_EXTEND ? 1 : -1,
DL, XLenVT);
13314 DAG.
getUNDEF(ContainerVT), SplatValue, VL);
13317 ZeroSplat, DAG.
getUNDEF(ContainerVT), VL);
13326 MVT VT =
Op.getSimpleValueType();
13334 MVT ContainerVT = VT;
13342 SDValue AllOneMask = DAG.
getNode(RISCVISD::VMSET_VL,
DL, ContainerVT, VL);
13344 switch (Condition) {
13349 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, Op2, VL);
13354 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, Op2, VL);
13356 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, AllOneMask, VL);
13364 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, AllOneMask, VL);
13365 Result = DAG.
getNode(RISCVISD::VMAND_VL,
DL, ContainerVT, Temp, Op2, VL);
13373 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op2, AllOneMask, VL);
13374 Result = DAG.
getNode(RISCVISD::VMAND_VL,
DL, ContainerVT, Op1, Temp, VL);
13382 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, AllOneMask, VL);
13383 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, Op2, VL);
13391 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op2, AllOneMask, VL);
13392 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, Op1, VL);
13412 MVT DstVT =
Op.getSimpleValueType();
13413 MVT SrcVT = Src.getSimpleValueType();
13426 if (DstEltSize >= SrcEltSize) {
13430 unsigned RISCVISDExtOpc = RISCVISDOpc == RISCVISD::SINT_TO_FP_VL
13431 ? RISCVISD::VSEXT_VL
13432 : RISCVISD::VZEXT_VL;
13435 if (SrcEltSize == 1) {
13437 MVT XLenVT = Subtarget.getXLenVT();
13442 RISCVISDExtOpc == RISCVISD::VZEXT_VL ? 1 : -1,
DL, XLenVT);
13445 Src = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, IntVT, Src, OneSplat,
13446 ZeroSplat, DAG.
getUNDEF(IntVT), VL);
13447 }
else if (DstEltSize > (2 * SrcEltSize)) {
13451 Src = DAG.
getNode(RISCVISDExtOpc,
DL, IntVT, Src, Mask, VL);
13457 "Wrong input/output vector types");
13460 if (DstEltSize > (2 * SrcEltSize)) {
13465 DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, InterimFVT, Src, Mask, VL);
13476 MVT InterimFVT = DstVT;
13477 if (SrcEltSize > (2 * DstEltSize)) {
13478 assert(SrcEltSize == (4 * DstEltSize) &&
"Unexpected types!");
13485 if (InterimFVT != DstVT) {
13487 Result = DAG.
getNode(RISCVISD::FP_ROUND_VL,
DL, DstVT, Src, Mask, VL);
13491 "Wrong input/output vector types");
13495 if (DstEltSize == 1) {
13498 assert(SrcEltSize >= 16 &&
"Unexpected FP type!");
13505 MVT XLenVT = Subtarget.getXLenVT();
13507 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, InterimIVT,
13508 DAG.
getUNDEF(InterimIVT), SplatZero, VL);
13518 while (InterimIVT != DstVT) {
13530 MVT VT =
Op.getSimpleValueType();
13539 MVT VT =
Op.getSimpleValueType();
13540 MVT XLenVT = Subtarget.getXLenVT();
13553 MVT ContainerVT = VT;
13573 TrueVal = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, PromotedVT, TrueVal, SplatOne,
13574 SplatZero, DAG.
getUNDEF(PromotedVT), VL);
13577 SplatOne, SplatZero, DAG.
getUNDEF(PromotedVT), VLMax);
13581 TrueVal, FalseVal, FalseVal, VL);
13586 RISCVISD::SETCC_VL,
DL, ContainerVT,
13596RISCVTargetLowering::lowerVPSpliceExperimental(
SDValue Op,
13598 using namespace SDPatternMatch;
13609 const MVT XLenVT = Subtarget.getXLenVT();
13610 MVT VT =
Op.getSimpleValueType();
13611 MVT ContainerVT = VT;
13621 if (IsMaskVector) {
13631 Op1 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, Op1, SplatOneOp1,
13632 SplatZeroOp1, DAG.
getUNDEF(ContainerVT), EVL1);
13640 Op2 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, Op2, SplatOneOp2,
13641 SplatZeroOp2, DAG.
getUNDEF(ContainerVT), EVL2);
13644 auto getVectorFirstEle = [](
SDValue Vec) {
13657 if (
auto FirstEle = getVectorFirstEle(
Op->getOperand(0))) {
13660 if ((EltVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
13661 EltVT == MVT::bf16) {
13669 : RISCVISD::VSLIDE1UP_VL,
13670 DL, ContainerVT, DAG.
getUNDEF(ContainerVT), Op2,
13671 FirstEle, Mask, EVL2);
13681 SDValue DownOffset, UpOffset;
13682 if (ImmValue >= 0) {
13696 DAG.
getUNDEF(ContainerVT), Op1, DownOffset, Mask,
13697 Subtarget.hasVLDependentLatency() ? UpOffset : EVL2);
13701 if (IsMaskVector) {
13705 {Result, DAG.getConstant(0, DL, ContainerVT),
13706 DAG.getCondCode(ISD::SETNE), DAG.getUNDEF(getMaskTypeFor(ContainerVT)),
13721 MVT VT =
Op.getSimpleValueType();
13723 MVT ContainerVT = VT;
13734 DAG.
getNode(
C->isZero() ? RISCVISD::VMCLR_VL : RISCVISD::VMSET_VL,
DL,
13757RISCVTargetLowering::lowerVPReverseExperimental(
SDValue Op,
13760 MVT VT =
Op.getSimpleValueType();
13761 MVT XLenVT = Subtarget.getXLenVT();
13767 MVT ContainerVT = VT;
13775 MVT GatherVT = ContainerVT;
13779 if (IsMaskVector) {
13789 Op1 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, IndicesVT, Op1, SplatOne,
13790 SplatZero, DAG.
getUNDEF(IndicesVT), EVL);
13795 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
13796 unsigned MaxVLMAX =
13799 unsigned GatherOpc = RISCVISD::VRGATHER_VV_VL;
13805 if (MaxVLMAX > 256 && EltSize == 8) {
13833 DAG.
getUNDEF(GatherVT), Result, Diff, Mask, EVL);
13835 if (IsMaskVector) {
13838 DAG.
getNode(RISCVISD::SETCC_VL,
DL, ContainerVT,
13851 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
13858 DAG.
getUNDEF(IndicesVT), VecLen, EVL);
13859 SDValue VRSUB = DAG.
getNode(RISCVISD::SUB_VL,
DL, IndicesVT, VecLenSplat, VID,
13860 DAG.
getUNDEF(IndicesVT), Mask, EVL);
13862 DAG.
getUNDEF(GatherVT), Mask, EVL);
13864 if (IsMaskVector) {
13867 RISCVISD::SETCC_VL,
DL, ContainerVT,
13879 MVT VT =
Op.getSimpleValueType();
13881 return lowerVPOp(
Op, DAG);
13888 MVT ContainerVT = VT;
13906 MVT XLenVT = Subtarget.getXLenVT();
13907 MVT VT =
Op.getSimpleValueType();
13908 MVT ContainerVT = VT;
13912 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
13920 : Intrinsic::riscv_vlse_mask,
13923 DAG.
getUNDEF(ContainerVT), VPNode->getBasePtr(),
13924 VPNode->getStride()};
13930 Ops.push_back(Mask);
13932 Ops.push_back(VPNode->getVectorLength());
13936 Ops.push_back(Policy);
13941 VPNode->getMemoryVT(), VPNode->getMemOperand());
13953 MVT XLenVT = Subtarget.getXLenVT();
13956 SDValue StoreVal = VPNode->getValue();
13958 MVT ContainerVT = VT;
13969 : Intrinsic::riscv_vsse_mask,
13972 VPNode->getBasePtr(), VPNode->getStride()};
13978 Ops.push_back(Mask);
13980 Ops.push_back(VPNode->getVectorLength());
13983 Ops, VPNode->getMemoryVT(),
13984 VPNode->getMemOperand());
13996 MVT VT =
Op.getSimpleValueType();
13999 EVT MemVT = MemSD->getMemoryVT();
14000 MachineMemOperand *MMO = MemSD->getMemOperand();
14001 SDValue Chain = MemSD->getChain();
14008 Index = VPGN->getIndex();
14009 Mask = VPGN->getMask();
14011 VL = VPGN->getVectorLength();
14017 Index = MGN->getIndex();
14018 Mask = MGN->getMask();
14019 PassThru = MGN->getPassThru();
14023 MVT IndexVT =
Index.getSimpleValueType();
14024 MVT XLenVT = Subtarget.getXLenVT();
14027 "Unexpected VTs!");
14028 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
14031 "Unexpected extending MGATHER/VP_GATHER");
14037 MVT ContainerVT = VT;
14061 IsUnmasked ? Intrinsic::riscv_vluxei : Intrinsic::riscv_vluxei_mask;
14066 Ops.push_back(PassThru);
14067 Ops.push_back(BasePtr);
14068 Ops.push_back(Index);
14070 Ops.push_back(Mask);
14075 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
14078 Chain =
Result.getValue(1);
14096 EVT MemVT = MemSD->getMemoryVT();
14097 MachineMemOperand *MMO = MemSD->getMemOperand();
14098 SDValue Chain = MemSD->getChain();
14101 [[maybe_unused]]
bool IsTruncatingStore =
false;
14105 Index = VPSN->getIndex();
14106 Mask = VPSN->getMask();
14107 Val = VPSN->getValue();
14108 VL = VPSN->getVectorLength();
14110 IsTruncatingStore =
false;
14114 Index = MSN->getIndex();
14115 Mask = MSN->getMask();
14116 Val = MSN->getValue();
14117 IsTruncatingStore = MSN->isTruncatingStore();
14121 MVT IndexVT =
Index.getSimpleValueType();
14122 MVT XLenVT = Subtarget.getXLenVT();
14125 "Unexpected VTs!");
14126 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
14129 assert(!IsTruncatingStore &&
"Unexpected truncating MSCATTER/VP_SCATTER");
14135 MVT ContainerVT = VT;
14159 IsUnmasked ? Intrinsic::riscv_vsoxei : Intrinsic::riscv_vsoxei_mask;
14161 Ops.push_back(Val);
14162 Ops.push_back(BasePtr);
14163 Ops.push_back(Index);
14165 Ops.push_back(Mask);
14174 const MVT XLenVT = Subtarget.getXLenVT();
14178 SDVTList VTs = DAG.
getVTList(XLenVT, MVT::Other);
14185 static const int Table =
14204 const MVT XLenVT = Subtarget.getXLenVT();
14214 static const unsigned Table =
14229 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14235 const MVT XLenVT = Subtarget.getXLenVT();
14239 SDVTList VTs = DAG.
getVTList(XLenVT, MVT::Other);
14240 return DAG.
getNode(RISCVISD::READ_CSR,
DL, VTs, Chain, SysRegNo);
14245 const MVT XLenVT = Subtarget.getXLenVT();
14252 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14258 const MVT XLenVT = Subtarget.getXLenVT();
14264 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14278 SDValue Result = DAG.
getNode(RISCVISD::READ_CSR,
DL, VTs, Chain, SysRegNo);
14279 Chain = Result.getValue(1);
14285 const MVT XLenVT = Subtarget.getXLenVT();
14295 Chain = DAG.
getNode(RISCVISD::CLEAR_CSR,
DL, MVT::Other, Chain, SysRegNo,
14297 return DAG.
getNode(RISCVISD::SET_CSR,
DL, MVT::Other, Chain, SysRegNo,
14303 const MVT XLenVT = Subtarget.getXLenVT();
14310 return DAG.
getNode(RISCVISD::CLEAR_CSR,
DL, MVT::Other, Chain, SysRegNo,
14318 bool isRISCV64 = Subtarget.is64Bit();
14332 return RISCVISD::SLLW;
14334 return RISCVISD::SRAW;
14336 return RISCVISD::SRLW;
14338 return RISCVISD::DIVW;
14340 return RISCVISD::DIVUW;
14342 return RISCVISD::REMUW;
14344 return RISCVISD::ROLW;
14346 return RISCVISD::RORW;
14382 switch (
N->getOpcode()) {
14384 llvm_unreachable(
"Don't know how to custom type legalize this operation!");
14389 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14390 "Unexpected custom legalisation");
14391 bool IsStrict =
N->isStrictFPOpcode();
14394 SDValue Op0 = IsStrict ?
N->getOperand(1) :
N->getOperand(0);
14403 !Subtarget.hasStdExtZfhOrZhinx()) {
14408 unsigned Opc = IsSigned ? RISCVISD::STRICT_FCVT_W_RV64
14409 : RISCVISD::STRICT_FCVT_WU_RV64;
14412 Opc,
DL, VTs, Chain, Op0,
14421 !Subtarget.hasStdExtZfhOrZhinx()) ||
14423 Op0 = DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, Op0);
14425 unsigned Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
14446 std::tie(Result, Chain) =
14447 makeLibCall(DAG, LC,
N->getValueType(0), Op0, CallOptions,
DL, Chain);
14453 case ISD::LROUND: {
14462 if (Op0.
getValueType() == MVT::f16 && !Subtarget.hasStdExtZfhOrZhinx())
14463 Op0 = DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, Op0);
14466 DAG.
getNode(RISCVISD::FCVT_W_RV64,
DL, MVT::i64, Op0,
14474 RTLIB::Libcall LC =
14475 Op0.
getValueType() == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
14484 case ISD::READCYCLECOUNTER:
14485 case ISD::READSTEADYCOUNTER: {
14486 assert(!Subtarget.is64Bit() &&
"READCYCLECOUNTER/READSTEADYCOUNTER only "
14487 "has custom type legalization on riscv32");
14489 SDValue LoCounter, HiCounter;
14490 MVT XLenVT = Subtarget.getXLenVT();
14491 if (
N->getOpcode() == ISD::READCYCLECOUNTER) {
14500 N->getOperand(0), LoCounter, HiCounter);
14515 if (
N->getValueType(0) == MVT::i64) {
14516 assert(Subtarget.hasStdExtZilsd() && !Subtarget.is64Bit() &&
14517 "Unexpected custom legalisation");
14519 if (!Subtarget.enableUnalignedScalarMem() && Ld->
getAlign() < 8)
14524 RISCVISD::LD_RV32,
DL,
14525 DAG.
getVTList({MVT::i32, MVT::i32, MVT::Other}),
14526 {Ld->getChain(), Ld->getBasePtr()}, MVT::i64, Ld->
getMemOperand());
14530 Results.append({Pair, Result.getValue(2)});
14534 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14535 "Unexpected custom legalisation");
14546 unsigned Size =
N->getSimpleValueType(0).getSizeInBits();
14547 unsigned XLen = Subtarget.getXLen();
14550 assert(
Size == (XLen * 2) &&
"Unexpected custom legalisation");
14558 if (LHSIsU == RHSIsU)
14562 MVT XLenVT = Subtarget.getXLenVT();
14575 if (RHSIsU && LHSIsS && !RHSIsS)
14576 Results.push_back(MakeMULPair(LHS, RHS));
14577 else if (LHSIsU && RHSIsS && !LHSIsS)
14578 Results.push_back(MakeMULPair(RHS, LHS));
14586 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14587 "Unexpected custom legalisation");
14593 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14594 "Unexpected custom legalisation");
14597 if (
N->getOpcode() ==
ISD::SHL && Subtarget.hasStdExtZbs() &&
14622 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14623 "Unexpected custom legalisation");
14624 assert((Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb() ||
14625 Subtarget.hasVendorXTHeadBb()) &&
14626 "Unexpected custom legalization");
14628 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()))
14636 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14637 "Unexpected custom legalisation");
14643 unsigned Opc = IsCTZ ? RISCVISD::CTZW : RISCVISD::CLZW;
14651 MVT VT =
N->getSimpleValueType(0);
14652 assert((VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32) &&
14653 Subtarget.is64Bit() && Subtarget.hasStdExtM() &&
14654 "Unexpected custom legalisation");
14666 if (VT != MVT::i32)
14674 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14675 "Unexpected custom legalisation");
14696 EVT OType =
N->getValueType(1);
14708 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14709 "Unexpected custom legalisation");
14726 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1), Res,
14730 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1),
N->getOperand(0),
14737 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1), Res, LHS,
14747 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14748 !Subtarget.hasStdExtZbb() &&
"Unexpected custom legalisation");
14756 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14757 "Unexpected custom legalisation");
14762 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14763 "Unexpected custom legalisation");
14765 if (Subtarget.hasStdExtZbb()) {
14798 case ISD::BITCAST: {
14799 EVT VT =
N->getValueType(0);
14803 MVT XLenVT = Subtarget.getXLenVT();
14804 if (VT == MVT::i16 &&
14805 ((Op0VT == MVT::f16 && Subtarget.hasStdExtZfhminOrZhinxmin()) ||
14806 (Op0VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
14809 }
else if (VT == MVT::i32 && Op0VT == MVT::f32 && Subtarget.is64Bit() &&
14810 Subtarget.hasStdExtFOrZfinx()) {
14812 DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Op0);
14814 }
else if (VT == MVT::i64 && Op0VT == MVT::f64 && !Subtarget.is64Bit() &&
14815 Subtarget.hasStdExtDOrZdinx()) {
14817 DAG.
getVTList(MVT::i32, MVT::i32), Op0);
14836 assert(
N->getValueType(0) == MVT::i8 && Subtarget.hasStdExtZbkb() &&
14837 "Unexpected custom legalisation");
14838 MVT XLenVT = Subtarget.getXLenVT();
14846 case RISCVISD::BREV8:
14847 case RISCVISD::ORC_B: {
14848 MVT VT =
N->getSimpleValueType(0);
14849 MVT XLenVT = Subtarget.getXLenVT();
14850 assert((VT == MVT::i16 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
14851 "Unexpected custom legalisation");
14852 assert(((
N->getOpcode() == RISCVISD::BREV8 && Subtarget.hasStdExtZbkb()) ||
14853 (
N->getOpcode() == RISCVISD::ORC_B && Subtarget.hasStdExtZbb())) &&
14854 "Unexpected extension");
14880 assert(!Subtarget.is64Bit() &&
N->getValueType(0) == MVT::i64 &&
14882 "Unexpected EXTRACT_VECTOR_ELT legalization");
14885 MVT ContainerVT = VecVT;
14891 MVT XLenVT = Subtarget.getXLenVT();
14900 DAG.
getUNDEF(ContainerVT), Vec, Idx, Mask, VL);
14912 DAG.
getNode(RISCVISD::SRL_VL,
DL, ContainerVT, Vec, ThirtyTwoV,
14913 DAG.
getUNDEF(ContainerVT), Mask, VL);
14921 unsigned IntNo =
N->getConstantOperandVal(0);
14925 "Don't know how to custom type legalize this intrinsic!");
14926 case Intrinsic::experimental_get_vector_length: {
14931 case Intrinsic::experimental_cttz_elts: {
14937 case Intrinsic::riscv_orc_b:
14938 case Intrinsic::riscv_brev8:
14939 case Intrinsic::riscv_sha256sig0:
14940 case Intrinsic::riscv_sha256sig1:
14941 case Intrinsic::riscv_sha256sum0:
14942 case Intrinsic::riscv_sha256sum1:
14943 case Intrinsic::riscv_sm3p0:
14944 case Intrinsic::riscv_sm3p1: {
14945 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
14949 case Intrinsic::riscv_orc_b:
Opc = RISCVISD::ORC_B;
break;
14950 case Intrinsic::riscv_brev8:
Opc = RISCVISD::BREV8;
break;
14951 case Intrinsic::riscv_sha256sig0:
Opc = RISCVISD::SHA256SIG0;
break;
14952 case Intrinsic::riscv_sha256sig1:
Opc = RISCVISD::SHA256SIG1;
break;
14953 case Intrinsic::riscv_sha256sum0:
Opc = RISCVISD::SHA256SUM0;
break;
14954 case Intrinsic::riscv_sha256sum1:
Opc = RISCVISD::SHA256SUM1;
break;
14955 case Intrinsic::riscv_sm3p0:
Opc = RISCVISD::SM3P0;
break;
14956 case Intrinsic::riscv_sm3p1:
Opc = RISCVISD::SM3P1;
break;
14965 case Intrinsic::riscv_sm4ks:
14966 case Intrinsic::riscv_sm4ed: {
14968 IntNo == Intrinsic::riscv_sm4ks ? RISCVISD::SM4KS : RISCVISD::SM4ED;
14974 DAG.
getNode(
Opc,
DL, MVT::i64, NewOp0, NewOp1,
N->getOperand(3));
14978 case Intrinsic::riscv_mopr: {
14979 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
14984 RISCVISD::MOP_R,
DL, MVT::i64, NewOp,
14989 case Intrinsic::riscv_moprr: {
14990 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
14997 RISCVISD::MOP_RR,
DL, MVT::i64, NewOp0, NewOp1,
15002 case Intrinsic::riscv_clmul: {
15003 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15014 case Intrinsic::riscv_clmulh:
15015 case Intrinsic::riscv_clmulr: {
15016 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15036 unsigned Opc = IntNo == Intrinsic::riscv_clmulh ? RISCVISD::CLMULH
15037 : RISCVISD::CLMULR;
15044 case Intrinsic::riscv_vmv_x_s: {
15045 EVT VT =
N->getValueType(0);
15046 MVT XLenVT = Subtarget.getXLenVT();
15047 if (VT.
bitsLT(XLenVT)) {
15050 Subtarget.getXLenVT(),
N->getOperand(1));
15055 assert(VT == MVT::i64 && !Subtarget.is64Bit() &&
15056 "Unexpected custom legalization");
15072 SDValue LShr32 = DAG.
getNode(RISCVISD::SRL_VL,
DL, VecVT, Vec, ThirtyTwoV,
15083 case ISD::VECREDUCE_ADD:
15084 case ISD::VECREDUCE_AND:
15085 case ISD::VECREDUCE_OR:
15086 case ISD::VECREDUCE_XOR:
15087 case ISD::VECREDUCE_SMAX:
15088 case ISD::VECREDUCE_UMAX:
15089 case ISD::VECREDUCE_SMIN:
15090 case ISD::VECREDUCE_UMIN:
15094 case ISD::VP_REDUCE_ADD:
15095 case ISD::VP_REDUCE_AND:
15096 case ISD::VP_REDUCE_OR:
15097 case ISD::VP_REDUCE_XOR:
15098 case ISD::VP_REDUCE_SMAX:
15099 case ISD::VP_REDUCE_UMAX:
15100 case ISD::VP_REDUCE_SMIN:
15101 case ISD::VP_REDUCE_UMIN:
15122 return ISD::VECREDUCE_ADD;
15124 return ISD::VECREDUCE_UMAX;
15126 return ISD::VECREDUCE_SMAX;
15128 return ISD::VECREDUCE_UMIN;
15130 return ISD::VECREDUCE_SMIN;
15132 return ISD::VECREDUCE_AND;
15134 return ISD::VECREDUCE_OR;
15136 return ISD::VECREDUCE_XOR;
15139 return ISD::VECREDUCE_FADD;
15165 const EVT VT =
N->getValueType(0);
15166 const unsigned Opc =
N->getOpcode();
15173 (
Opc !=
ISD::FADD || !
N->getFlags().hasAllowReassociation()))
15178 "Inconsistent mappings");
15182 if (!
LHS.hasOneUse() || !
RHS.hasOneUse())
15210 if (0 == std::min(LHSIdx, RHSIdx) && 1 == std::max(LHSIdx, RHSIdx)) {
15213 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
N->getFlags());
15220 if (
LHS.getOpcode() != ReduceOpc)
15234 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
15235 ReduceVec->
getFlags() &
N->getFlags());
15245 auto BinOpToRVVReduce = [](
unsigned Opc) {
15250 return RISCVISD::VECREDUCE_ADD_VL;
15252 return RISCVISD::VECREDUCE_UMAX_VL;
15254 return RISCVISD::VECREDUCE_SMAX_VL;
15256 return RISCVISD::VECREDUCE_UMIN_VL;
15258 return RISCVISD::VECREDUCE_SMIN_VL;
15260 return RISCVISD::VECREDUCE_AND_VL;
15262 return RISCVISD::VECREDUCE_OR_VL;
15264 return RISCVISD::VECREDUCE_XOR_VL;
15266 return RISCVISD::VECREDUCE_FADD_VL;
15268 return RISCVISD::VECREDUCE_FMAX_VL;
15270 return RISCVISD::VECREDUCE_FMIN_VL;
15274 auto IsReduction = [&BinOpToRVVReduce](
SDValue V,
unsigned Opc) {
15277 V.getOperand(0).getOpcode() == BinOpToRVVReduce(
Opc);
15280 unsigned Opc =
N->getOpcode();
15281 unsigned ReduceIdx;
15282 if (IsReduction(
N->getOperand(0),
Opc))
15284 else if (IsReduction(
N->getOperand(1),
Opc))
15290 if (
Opc ==
ISD::FADD && !
N->getFlags().hasAllowReassociation())
15293 SDValue Extract =
N->getOperand(ReduceIdx);
15306 if (ScalarV.
getOpcode() != RISCVISD::VFMV_S_F_VL &&
15307 ScalarV.
getOpcode() != RISCVISD::VMV_S_X_VL &&
15308 ScalarV.
getOpcode() != RISCVISD::VMV_V_X_VL)
15325 SDValue NewStart =
N->getOperand(1 - ReduceIdx);
15358 EVT VT =
N->getValueType(0);
15374 int64_t C0 = N0C->getSExtValue();
15375 int64_t C1 = N1C->getSExtValue();
15376 if (C0 <= 0 || C1 <= 0)
15379 int64_t Diff = std::abs(C0 - C1);
15385 int64_t Bits = std::min(C0, C1);
15417 if (VShift.
slt(1) || VShift.
sgt(3))
15421 EVT VT =
N->getValueType(0);
15441 EVT VT =
N->getValueType(0);
15469 EVT VT =
N->getValueType(0);
15490 Slct.
getOpcode() != RISCVISD::SELECT_CC) ||
15498 bool SwapSelectOps;
15499 unsigned OpOffset = Slct.
getOpcode() == RISCVISD::SELECT_CC ? 2 : 0;
15504 SwapSelectOps =
false;
15505 NonConstantVal = FalseVal;
15507 SwapSelectOps =
true;
15508 NonConstantVal = TrueVal;
15514 FalseVal = DAG.
getNode(
N->getOpcode(),
SDLoc(
N), VT, OtherOp, NonConstantVal);
15519 if (Slct.
getOpcode() == RISCVISD::SELECT_CC)
15562 EVT VT =
N->getValueType(0);
15577 if (!N0C->hasOneUse())
15579 int64_t C0 = N0C->getSExtValue();
15580 int64_t C1 = N1C->getSExtValue();
15582 if (C0 == -1 || C0 == 0 || C0 == 1 ||
isInt<12>(C1))
15589 }
else if ((C1 / C0 + 1) != 0 &&
isInt<12>(C1 / C0 + 1) &&
15593 }
else if ((C1 / C0 - 1) != 0 &&
isInt<12>(C1 / C0 - 1) &&
15621 EVT VT =
N->getValueType(0);
15652 unsigned OuterExtend =
15656 OuterExtend,
SDLoc(
N), VT,
15664 EVT VT =
N->getValueType(0);
15715 EVT VT =
N->getValueType(0);
15725 APInt ImmValMinus1 = N0C->getAPIntValue() - 1;
15735 if (!isIntEqualitySetCC(CCVal) || !SetCCOpVT.
isInteger())
15758 if (!Subtarget.hasStdExtZbb())
15761 EVT VT =
N->getValueType(0);
15763 if (VT != Subtarget.
getXLenVT() && VT != MVT::i32 && VT != MVT::i16)
15775 unsigned ShiftedAmount = 8 - ShAmtCLeft->getZExtValue();
15777 if (ShiftedAmount >= 8)
15781 SDValue RightShiftOperand = N1;
15783 if (ShiftedAmount != 0) {
15787 if (!ShAmtCRight || ShAmtCRight->getZExtValue() != ShiftedAmount)
15796 if (LeftShiftOperand != RightShiftOperand)
15800 Mask <<= ShiftedAmount;
15806 return DAG.
getNode(RISCVISD::ORC_B,
SDLoc(
N), VT, LeftShiftOperand);
15814 EVT VT =
N->getValueType(0);
15846 bool IsAnd =
N->getOpcode() ==
ISD::AND;
15870 EVT VT =
N->getValueType(0);
15894 EVT VT =
N->getValueType(0);
15921 if (CondLHS != True)
15928 if (!CondRHSC || CondRHSC->
getAPIntValue() != (1ULL << ScalarBits))
15940 if (!FalseRHSC || !FalseRHSC->
isZero())
15960 EVT VT =
N->getValueType(0);
15967 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() && VT == MVT::i1 &&
16010 EVT VT =
N->getValueType(0);
16029 EVT WideVT =
X.getValueType();
16051 if (N0.
getOpcode() != ISD::ATOMIC_LOAD)
16066 if (Mask != ExpectedMask)
16092 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
16130 if (N0.
getOpcode() != RISCVISD::CZERO_EQZ ||
16131 N1.
getOpcode() != RISCVISD::CZERO_NEZ ||
16149 EVT VT =
N->getValueType(0);
16167 if (!Subtarget.hasVendorXqcibm())
16180 if (
N->getValueType(0) != MVT::i32)
16183 unsigned Width, ShAmt;
16200 return DAG.
getNode(RISCVISD::QC_INSB,
DL, MVT::i32,
Ops);
16238 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
16253 if (N0.
getOpcode() == RISCVISD::SLLW &&
16257 return DAG.
getNode(RISCVISD::ROLW,
DL, MVT::i64,
16268 const APInt &Imm = ConstN00->getAPIntValue();
16269 if ((Imm + 1).isSignedIntN(12))
16293 EVT VT =
N->getValueType(0);
16302 bool IsAdd = (
E & 3) == 1;
16303 E -= IsAdd ? 1 : -1;
16307 Result = DAG.
getNode(AddSubOp,
DL, VT, Result, ShiftVal);
16317 uint64_t MulAmtLowBit = MulAmt & (-MulAmt);
16322 ShiftAmt1 = MulAmt + MulAmtLowBit;
16325 ShiftAmt1 = MulAmt - MulAmtLowBit;
16329 EVT VT =
N->getValueType(0);
16343 EVT VT =
N->getValueType(0);
16352 bool ShouldExpandMul =
16354 !Subtarget.hasStdExtZmmul();
16355 if (!ShouldExpandMul)
16374 for (
uint64_t Divisor : {3, 5, 9}) {
16375 if (MulAmt % Divisor != 0)
16377 uint64_t MulAmt2 = MulAmt / Divisor;
16385 X.getConstantOperandVal(1) == UINT64_C(0xffffffff)) {
16388 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, Shl,
16402 if (MulAmt2 == 3 || MulAmt2 == 5 || MulAmt2 == 9) {
16407 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, Mul359,
16418 if (ScaleShift >= 1 && ScaleShift < 4) {
16419 unsigned ShiftAmt =
Log2_64((MulAmt & (MulAmt - 1)));
16423 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT,
X,
16433 for (
uint64_t Divisor : {3, 5, 9}) {
16438 if ((
C >> TZ) == Divisor && (TZ == 1 || TZ == 2 || TZ == 3)) {
16443 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, Mul359,
16449 if (MulAmt > 2 &&
isPowerOf2_64((MulAmt - 1) & (MulAmt - 2))) {
16451 if (ScaleShift >= 1 && ScaleShift < 4) {
16452 unsigned ShiftAmt =
Log2_64(((MulAmt - 1) & (MulAmt - 2)));
16478 for (
uint64_t Divisor : {3, 5, 9}) {
16479 if (MulAmt % Divisor != 0)
16481 uint64_t MulAmt2 = MulAmt / Divisor;
16484 for (
uint64_t Divisor2 : {3, 5, 9}) {
16485 if (MulAmt2 % Divisor2 != 0)
16487 uint64_t MulAmt3 = MulAmt2 / Divisor2;
16494 RISCVISD::SHL_ADD,
DL, VT, Mul359A,
16506 if (!Subtarget.hasStdExtZmmul())
16516 EVT VT =
N->getValueType(0);
16523 if (
N->getOperand(0).getOpcode() !=
ISD::AND ||
16524 N->getOperand(0).getOperand(0).getOpcode() !=
ISD::SRL)
16537 if (!V1.
isMask(HalfSize) || V2 != (1ULL | 1ULL << HalfSize) ||
16538 V3 != (HalfSize - 1))
16548 return DAG.
getNode(ISD::BITCAST,
DL, VT, Sra);
16554 EVT VT =
N->getValueType(0);
16562 unsigned AddSubOpc;
16568 auto IsAddSubWith1 = [&](
SDValue V) ->
bool {
16569 AddSubOpc = V->getOpcode();
16581 if (IsAddSubWith1(N0)) {
16583 return DAG.
getNode(AddSubOpc,
DL, VT, N1, MulVal);
16586 if (IsAddSubWith1(N1)) {
16588 return DAG.
getNode(AddSubOpc,
DL, VT, N0, MulVal);
16603 if (isIndexTypeSigned(IndexType))
16606 if (!
N->hasOneUse())
16609 EVT VT =
N.getValueType();
16648 EVT SrcVT = Src.getValueType();
16652 NewElen = std::max(NewElen, 8U);
16679 EVT OpVT =
X.getValueType();
16687 if (OpSize <= Subtarget.
getXLen() ||
16693 auto IsVectorBitCastCheap = [](
SDValue X) {
16696 X.getOpcode() == ISD::LOAD;
16698 if (!IsVectorBitCastCheap(
X) || !IsVectorBitCastCheap(
Y))
16702 Attribute::NoImplicitFloat))
16709 unsigned VecSize = OpSize / 8;
16721 DAG.
getNode(ISD::VP_REDUCE_OR,
DL, XLenVT,
16734 EVT VT =
N->getValueType(0);
16739 if (!isIntEqualitySetCC(
Cond))
16764 if (OpVT == MVT::i64 && AndRHSInt <= 0xffffffff &&
16768 if (NewC >= -2048 && NewC <= 2048) {
16774 return DAG.
getSetCC(dl, VT, Shift,
16784 if (OpVT != MVT::i64 || !Subtarget.
is64Bit())
16804 const APInt &C1 = N1C->getAPIntValue();
16822 EVT VT =
N->getValueType(0);
16824 unsigned Opc = Src.getOpcode();
16829 if (
Opc == RISCVISD::FMV_X_ANYEXTH && SrcVT.
bitsGE(MVT::i16) &&
16830 Subtarget.hasStdExtZfhmin())
16831 return DAG.
getNode(RISCVISD::FMV_X_SIGNEXTH,
DL, VT, Src.getOperand(0));
16837 return DAG.
getNode(RISCVISD::SLLW,
DL, VT, Src.getOperand(0),
16838 Src.getOperand(1));
16857struct CombineResult;
16859enum ExtKind : uint8_t {
16891struct NodeExtensionHelper {
16900 bool SupportsFPExt;
16902 bool SupportsBF16Ext;
16905 bool EnforceOneUse;
16915 case RISCVISD::VSEXT_VL:
16916 case RISCVISD::VZEXT_VL:
16917 case RISCVISD::FP_EXTEND_VL:
16920 return OrigOperand;
16926 return OrigOperand.
getOpcode() == RISCVISD::VMV_V_X_VL ||
16931 unsigned getExtOpc(ExtKind SupportsExt)
const {
16932 switch (SupportsExt) {
16933 case ExtKind::SExt:
16934 return RISCVISD::VSEXT_VL;
16935 case ExtKind::ZExt:
16936 return RISCVISD::VZEXT_VL;
16937 case ExtKind::FPExt:
16938 case ExtKind::BF16Ext:
16939 return RISCVISD::FP_EXTEND_VL;
16947 SDValue getOrCreateExtendedOp(SDNode *Root, SelectionDAG &DAG,
16948 const RISCVSubtarget &Subtarget,
16949 std::optional<ExtKind> SupportsExt)
const {
16950 if (!SupportsExt.has_value())
16951 return OrigOperand;
16953 MVT NarrowVT = getNarrowType(Root, *SupportsExt);
16957 if (
Source.getValueType() == NarrowVT)
16960 unsigned ExtOpc = getExtOpc(*SupportsExt);
16963 SDLoc
DL(OrigOperand);
16964 auto [
Mask, VL] = getMaskAndVL(Root, DAG, Subtarget);
16968 case RISCVISD::VSEXT_VL:
16969 case RISCVISD::VZEXT_VL:
16970 case RISCVISD::FP_EXTEND_VL:
16971 return DAG.
getNode(ExtOpc,
DL, NarrowVT, Source, Mask, VL);
16974 case RISCVISD::VMV_V_X_VL:
16975 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, NarrowVT,
16977 case RISCVISD::VFMV_V_F_VL:
16979 assert(
Source.getOpcode() == ISD::FP_EXTEND &&
"Unexpected source");
16982 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL, NarrowVT,
16983 DAG.
getUNDEF(NarrowVT), Source, VL);
16996 static MVT getNarrowType(
const SDNode *Root, ExtKind SupportsExt) {
17002 MVT EltVT = SupportsExt == ExtKind::BF16Ext ? MVT::bf16
17003 : SupportsExt == ExtKind::FPExt
17005 : MVT::getIntegerVT(NarrowSize);
17007 assert((
int)NarrowSize >= (SupportsExt == ExtKind::FPExt ? 16 : 8) &&
17008 "Trying to extend something we can't represent");
17015 static unsigned getSExtOpcode(
unsigned Opcode) {
17018 case RISCVISD::ADD_VL:
17019 case RISCVISD::VWADD_W_VL:
17020 case RISCVISD::VWADDU_W_VL:
17022 case RISCVISD::OR_VL:
17023 return RISCVISD::VWADD_VL;
17025 case RISCVISD::SUB_VL:
17026 case RISCVISD::VWSUB_W_VL:
17027 case RISCVISD::VWSUBU_W_VL:
17028 return RISCVISD::VWSUB_VL;
17030 case RISCVISD::MUL_VL:
17031 return RISCVISD::VWMUL_VL;
17039 static unsigned getZExtOpcode(
unsigned Opcode) {
17042 case RISCVISD::ADD_VL:
17043 case RISCVISD::VWADD_W_VL:
17044 case RISCVISD::VWADDU_W_VL:
17046 case RISCVISD::OR_VL:
17047 return RISCVISD::VWADDU_VL;
17049 case RISCVISD::SUB_VL:
17050 case RISCVISD::VWSUB_W_VL:
17051 case RISCVISD::VWSUBU_W_VL:
17052 return RISCVISD::VWSUBU_VL;
17054 case RISCVISD::MUL_VL:
17055 return RISCVISD::VWMULU_VL;
17057 case RISCVISD::SHL_VL:
17058 return RISCVISD::VWSLL_VL;
17066 static unsigned getFPExtOpcode(
unsigned Opcode) {
17068 case RISCVISD::FADD_VL:
17069 case RISCVISD::VFWADD_W_VL:
17070 return RISCVISD::VFWADD_VL;
17071 case RISCVISD::FSUB_VL:
17072 case RISCVISD::VFWSUB_W_VL:
17073 return RISCVISD::VFWSUB_VL;
17074 case RISCVISD::FMUL_VL:
17075 return RISCVISD::VFWMUL_VL;
17076 case RISCVISD::VFMADD_VL:
17077 return RISCVISD::VFWMADD_VL;
17078 case RISCVISD::VFMSUB_VL:
17079 return RISCVISD::VFWMSUB_VL;
17080 case RISCVISD::VFNMADD_VL:
17081 return RISCVISD::VFWNMADD_VL;
17082 case RISCVISD::VFNMSUB_VL:
17083 return RISCVISD::VFWNMSUB_VL;
17091 static unsigned getSUOpcode(
unsigned Opcode) {
17093 "SU is only supported for MUL");
17094 return RISCVISD::VWMULSU_VL;
17099 static unsigned getWOpcode(
unsigned Opcode, ExtKind SupportsExt) {
17102 case RISCVISD::ADD_VL:
17104 case RISCVISD::OR_VL:
17105 return SupportsExt == ExtKind::SExt ? RISCVISD::VWADD_W_VL
17106 : RISCVISD::VWADDU_W_VL;
17108 case RISCVISD::SUB_VL:
17109 return SupportsExt == ExtKind::SExt ? RISCVISD::VWSUB_W_VL
17110 : RISCVISD::VWSUBU_W_VL;
17111 case RISCVISD::FADD_VL:
17112 return RISCVISD::VFWADD_W_VL;
17113 case RISCVISD::FSUB_VL:
17114 return RISCVISD::VFWSUB_W_VL;
17120 using CombineToTry = std::function<std::optional<CombineResult>(
17121 SDNode * ,
const NodeExtensionHelper & ,
17122 const NodeExtensionHelper & , SelectionDAG &,
17123 const RISCVSubtarget &)>;
17126 bool needToPromoteOtherUsers()
const {
return EnforceOneUse; }
17128 void fillUpExtensionSupportForSplat(SDNode *Root, SelectionDAG &DAG,
17129 const RISCVSubtarget &Subtarget) {
17134 "Unexpected Opcode");
17147 unsigned ScalarBits =
Op.getValueSizeInBits();
17149 if (ScalarBits < EltBits) {
17151 assert(
Opc == RISCVISD::VMV_V_X_VL && EltBits == 64 && ScalarBits == 32 &&
17152 !Subtarget.
is64Bit() &&
"Unexpected splat");
17154 SupportsSExt =
true;
17158 SupportsZExt =
true;
17160 EnforceOneUse =
false;
17164 unsigned NarrowSize = EltBits / 2;
17167 if (NarrowSize < 8)
17171 SupportsSExt =
true;
17175 SupportsZExt =
true;
17177 EnforceOneUse =
false;
17180 bool isSupportedFPExtend(MVT NarrowEltVT,
const RISCVSubtarget &Subtarget) {
17181 return (NarrowEltVT == MVT::f32 ||
17185 bool isSupportedBF16Extend(MVT NarrowEltVT,
const RISCVSubtarget &Subtarget) {
17186 return NarrowEltVT == MVT::bf16 && Subtarget.hasStdExtZvfbfwma();
17191 void fillUpExtensionSupport(SDNode *Root, SelectionDAG &DAG,
17192 const RISCVSubtarget &Subtarget) {
17193 SupportsZExt =
false;
17194 SupportsSExt =
false;
17195 SupportsFPExt =
false;
17196 SupportsBF16Ext =
false;
17197 EnforceOneUse =
true;
17219 case RISCVISD::VZEXT_VL:
17220 SupportsZExt =
true;
17222 case RISCVISD::VSEXT_VL:
17223 SupportsSExt =
true;
17225 case RISCVISD::FP_EXTEND_VL: {
17228 if (isSupportedFPExtend(NarrowEltVT, Subtarget))
17229 SupportsFPExt =
true;
17230 if (isSupportedBF16Extend(NarrowEltVT, Subtarget))
17231 SupportsBF16Ext =
true;
17236 case RISCVISD::VMV_V_X_VL:
17237 fillUpExtensionSupportForSplat(Root, DAG, Subtarget);
17239 case RISCVISD::VFMV_V_F_VL: {
17246 if (
Op.getOpcode() != ISD::FP_EXTEND)
17250 unsigned ScalarBits =
Op.getOperand(0).getValueSizeInBits();
17251 if (NarrowSize != ScalarBits)
17254 if (isSupportedFPExtend(
Op.getOperand(0).getSimpleValueType(), Subtarget))
17255 SupportsFPExt =
true;
17256 if (isSupportedBF16Extend(
Op.getOperand(0).getSimpleValueType(),
17258 SupportsBF16Ext =
true;
17267 static bool isSupportedRoot(
const SDNode *Root,
17268 const RISCVSubtarget &Subtarget) {
17280 case RISCVISD::ADD_VL:
17281 case RISCVISD::MUL_VL:
17282 case RISCVISD::VWADD_W_VL:
17283 case RISCVISD::VWADDU_W_VL:
17284 case RISCVISD::SUB_VL:
17285 case RISCVISD::VWSUB_W_VL:
17286 case RISCVISD::VWSUBU_W_VL:
17288 case RISCVISD::FADD_VL:
17289 case RISCVISD::FSUB_VL:
17290 case RISCVISD::FMUL_VL:
17291 case RISCVISD::VFWADD_W_VL:
17292 case RISCVISD::VFWSUB_W_VL:
17294 case RISCVISD::OR_VL:
17298 Subtarget.hasStdExtZvbb();
17299 case RISCVISD::SHL_VL:
17300 return Subtarget.hasStdExtZvbb();
17301 case RISCVISD::VFMADD_VL:
17302 case RISCVISD::VFNMSUB_VL:
17303 case RISCVISD::VFNMADD_VL:
17304 case RISCVISD::VFMSUB_VL:
17312 NodeExtensionHelper(SDNode *Root,
unsigned OperandIdx, SelectionDAG &DAG,
17313 const RISCVSubtarget &Subtarget) {
17314 assert(isSupportedRoot(Root, Subtarget) &&
17315 "Trying to build an helper with an "
17316 "unsupported root");
17317 assert(OperandIdx < 2 &&
"Requesting something else than LHS or RHS");
17327 case RISCVISD::VWADD_W_VL:
17328 case RISCVISD::VWADDU_W_VL:
17329 case RISCVISD::VWSUB_W_VL:
17330 case RISCVISD::VWSUBU_W_VL:
17331 case RISCVISD::VFWADD_W_VL:
17332 case RISCVISD::VFWSUB_W_VL:
17333 if (OperandIdx == 1) {
17335 Opc == RISCVISD::VWADDU_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL;
17337 Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWSUB_W_VL;
17339 Opc == RISCVISD::VFWADD_W_VL ||
Opc == RISCVISD::VFWSUB_W_VL;
17342 EnforceOneUse =
false;
17347 fillUpExtensionSupport(Root, DAG, Subtarget);
17353 static std::pair<SDValue, SDValue>
17354 getMaskAndVL(
const SDNode *Root, SelectionDAG &DAG,
17355 const RISCVSubtarget &Subtarget) {
17356 assert(isSupportedRoot(Root, Subtarget) &&
"Unexpected root");
17375 switch (
N->getOpcode()) {
17379 case RISCVISD::ADD_VL:
17380 case RISCVISD::MUL_VL:
17381 case RISCVISD::OR_VL:
17382 case RISCVISD::VWADD_W_VL:
17383 case RISCVISD::VWADDU_W_VL:
17384 case RISCVISD::FADD_VL:
17385 case RISCVISD::FMUL_VL:
17386 case RISCVISD::VFWADD_W_VL:
17387 case RISCVISD::VFMADD_VL:
17388 case RISCVISD::VFNMSUB_VL:
17389 case RISCVISD::VFNMADD_VL:
17390 case RISCVISD::VFMSUB_VL:
17393 case RISCVISD::SUB_VL:
17394 case RISCVISD::VWSUB_W_VL:
17395 case RISCVISD::VWSUBU_W_VL:
17396 case RISCVISD::FSUB_VL:
17397 case RISCVISD::VFWSUB_W_VL:
17399 case RISCVISD::SHL_VL:
17418struct CombineResult {
17420 unsigned TargetOpcode;
17422 std::optional<ExtKind> LHSExt;
17423 std::optional<ExtKind> RHSExt;
17427 NodeExtensionHelper
LHS;
17429 NodeExtensionHelper
RHS;
17431 CombineResult(
unsigned TargetOpcode, SDNode *Root,
17432 const NodeExtensionHelper &
LHS, std::optional<ExtKind> LHSExt,
17433 const NodeExtensionHelper &
RHS, std::optional<ExtKind> RHSExt)
17434 : TargetOpcode(TargetOpcode), LHSExt(LHSExt), RHSExt(RHSExt), Root(Root),
17440 SDValue materialize(SelectionDAG &DAG,
17441 const RISCVSubtarget &Subtarget)
const {
17443 std::tie(Mask, VL) =
17444 NodeExtensionHelper::getMaskAndVL(Root, DAG, Subtarget);
17458 LHS.getOrCreateExtendedOp(Root, DAG, Subtarget, LHSExt),
17459 RHS.getOrCreateExtendedOp(Root, DAG, Subtarget, RHSExt),
17460 Passthru, Mask, VL);
17474static std::optional<CombineResult>
17475canFoldToVWWithSameExtensionImpl(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17476 const NodeExtensionHelper &
RHS,
17479 if ((AllowExtMask & ExtKind::ZExt) &&
LHS.SupportsZExt &&
RHS.SupportsZExt)
17480 return CombineResult(NodeExtensionHelper::getZExtOpcode(Root->
getOpcode()),
17481 Root,
LHS, {ExtKind::ZExt},
RHS,
17483 if ((AllowExtMask & ExtKind::SExt) &&
LHS.SupportsSExt &&
RHS.SupportsSExt)
17484 return CombineResult(NodeExtensionHelper::getSExtOpcode(Root->
getOpcode()),
17485 Root,
LHS, {ExtKind::SExt},
RHS,
17487 if ((AllowExtMask & ExtKind::FPExt) &&
LHS.SupportsFPExt &&
RHS.SupportsFPExt)
17488 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
17489 Root,
LHS, {ExtKind::FPExt},
RHS,
17491 if ((AllowExtMask & ExtKind::BF16Ext) &&
LHS.SupportsBF16Ext &&
17492 RHS.SupportsBF16Ext)
17493 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
17494 Root,
LHS, {ExtKind::BF16Ext},
RHS,
17495 {ExtKind::BF16Ext});
17496 return std::nullopt;
17505static std::optional<CombineResult>
17506canFoldToVWWithSameExtension(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17509 return canFoldToVWWithSameExtensionImpl(
17510 Root,
LHS,
RHS, ExtKind::ZExt | ExtKind::SExt | ExtKind::FPExt, DAG,
17518static std::optional<CombineResult>
17519canFoldToVW_W(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17522 if (
RHS.SupportsFPExt)
17523 return CombineResult(
17524 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::FPExt),
17525 Root,
LHS, std::nullopt,
RHS, {ExtKind::FPExt});
17532 return CombineResult(
17533 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::ZExt), Root,
17534 LHS, std::nullopt,
RHS, {ExtKind::ZExt});
17536 return CombineResult(
17537 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::SExt), Root,
17538 LHS, std::nullopt,
RHS, {ExtKind::SExt});
17539 return std::nullopt;
17546static std::optional<CombineResult>
17547canFoldToVWWithSEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17550 return canFoldToVWWithSameExtensionImpl(Root,
LHS,
RHS, ExtKind::SExt, DAG,
17558static std::optional<CombineResult>
17559canFoldToVWWithZEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17562 return canFoldToVWWithSameExtensionImpl(Root,
LHS,
RHS, ExtKind::ZExt, DAG,
17570static std::optional<CombineResult>
17571canFoldToVWWithFPEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17574 return canFoldToVWWithSameExtensionImpl(Root,
LHS,
RHS, ExtKind::FPExt, DAG,
17582static std::optional<CombineResult>
17583canFoldToVWWithBF16EXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17586 return canFoldToVWWithSameExtensionImpl(Root,
LHS,
RHS, ExtKind::BF16Ext, DAG,
17594static std::optional<CombineResult>
17595canFoldToVW_SU(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17599 if (!
LHS.SupportsSExt || !
RHS.SupportsZExt)
17600 return std::nullopt;
17601 return CombineResult(NodeExtensionHelper::getSUOpcode(Root->
getOpcode()),
17602 Root,
LHS, {ExtKind::SExt},
RHS,
17607NodeExtensionHelper::getSupportedFoldings(
const SDNode *Root) {
17613 case RISCVISD::ADD_VL:
17614 case RISCVISD::SUB_VL:
17615 case RISCVISD::OR_VL:
17616 case RISCVISD::FADD_VL:
17617 case RISCVISD::FSUB_VL:
17619 Strategies.
push_back(canFoldToVWWithSameExtension);
17623 case RISCVISD::FMUL_VL:
17624 case RISCVISD::VFMADD_VL:
17625 case RISCVISD::VFMSUB_VL:
17626 case RISCVISD::VFNMADD_VL:
17627 case RISCVISD::VFNMSUB_VL:
17628 Strategies.
push_back(canFoldToVWWithSameExtension);
17629 if (Root->
getOpcode() == RISCVISD::VFMADD_VL)
17630 Strategies.
push_back(canFoldToVWWithBF16EXT);
17633 case RISCVISD::MUL_VL:
17635 Strategies.
push_back(canFoldToVWWithSameExtension);
17640 case RISCVISD::SHL_VL:
17642 Strategies.
push_back(canFoldToVWWithZEXT);
17644 case RISCVISD::VWADD_W_VL:
17645 case RISCVISD::VWSUB_W_VL:
17647 Strategies.
push_back(canFoldToVWWithSEXT);
17649 case RISCVISD::VWADDU_W_VL:
17650 case RISCVISD::VWSUBU_W_VL:
17652 Strategies.
push_back(canFoldToVWWithZEXT);
17654 case RISCVISD::VFWADD_W_VL:
17655 case RISCVISD::VFWSUB_W_VL:
17657 Strategies.
push_back(canFoldToVWWithFPEXT);
17668 assert(
N->getOpcode() == RISCVISD::ADD_VL);
17671 SDValue Passthru =
N->getOperand(2);
17705 if (!NodeExtensionHelper::isSupportedRoot(
N, Subtarget))
17711 Inserted.insert(
N);
17714 while (!Worklist.
empty()) {
17717 NodeExtensionHelper
LHS(Root, 0, DAG, Subtarget);
17718 NodeExtensionHelper
RHS(Root, 1, DAG, Subtarget);
17719 auto AppendUsersIfNeeded = [&Worklist, &Subtarget,
17720 &Inserted](
const NodeExtensionHelper &
Op) {
17721 if (
Op.needToPromoteOtherUsers()) {
17724 if (!NodeExtensionHelper::isSupportedRoot(TheUser, Subtarget))
17729 if (Inserted.insert(TheUser).second)
17742 NodeExtensionHelper::getSupportedFoldings(Root);
17744 assert(!FoldingStrategies.
empty() &&
"Nothing to be folded");
17745 bool Matched =
false;
17746 for (
int Attempt = 0;
17747 (Attempt != 1 + NodeExtensionHelper::isCommutative(Root)) && !Matched;
17750 for (NodeExtensionHelper::CombineToTry FoldingStrategy :
17751 FoldingStrategies) {
17752 std::optional<CombineResult> Res =
17753 FoldingStrategy(Root,
LHS,
RHS, DAG, Subtarget);
17760 if (Res->LHSExt.has_value())
17761 if (!AppendUsersIfNeeded(
LHS))
17763 if (Res->RHSExt.has_value())
17764 if (!AppendUsersIfNeeded(
RHS))
17776 SDValue InputRootReplacement;
17783 for (CombineResult Res : CombinesToApply) {
17784 SDValue NewValue = Res.materialize(DAG, Subtarget);
17785 if (!InputRootReplacement) {
17787 "First element is expected to be the current node");
17788 InputRootReplacement = NewValue;
17793 for (std::pair<SDValue, SDValue> OldNewValues : ValuesToReplace) {
17797 return InputRootReplacement;
17804 unsigned Opc =
N->getOpcode();
17805 assert(
Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWADDU_W_VL ||
17806 Opc == RISCVISD::VWSUB_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL);
17809 SDValue MergeOp =
N->getOperand(1);
17810 unsigned MergeOpc = MergeOp.
getOpcode();
17812 if (MergeOpc != RISCVISD::VMERGE_VL && MergeOpc !=
ISD::VSELECT)
17821 SDValue Passthru =
N->getOperand(2);
17827 if (Mask.getOpcode() != RISCVISD::VMSET_VL)
17835 Z = Z.getOperand(1);
17841 {Y, X, Y, MergeOp->getOperand(0), N->getOperand(4)},
17848 [[maybe_unused]]
unsigned Opc =
N->getOpcode();
17849 assert(
Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWADDU_W_VL ||
17850 Opc == RISCVISD::VWSUB_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL);
17877 EVT NewMemVT = (MemVT == MVT::i32) ? MVT::i64 : MVT::i128;
17882 if (LSNode1->
getOpcode() == ISD::LOAD) {
17885 if (MemVT == MVT::i32)
17886 Opcode = (Ext ==
ISD::ZEXTLOAD) ? RISCVISD::TH_LWUD : RISCVISD::TH_LWD;
17888 Opcode = RISCVISD::TH_LDD;
17891 Opcode,
SDLoc(LSNode1), DAG.
getVTList({XLenVT, XLenVT, MVT::Other}),
17892 {LSNode1->getChain(), BasePtr,
17893 DAG.getConstant(Imm, SDLoc(LSNode1), XLenVT)},
17904 unsigned Opcode = (MemVT == MVT::i32) ? RISCVISD::TH_SWD : RISCVISD::TH_SDD;
17908 {LSNode1->getChain(), LSNode1->getOperand(1), LSNode2->getOperand(1),
17909 BasePtr, DAG.getConstant(Imm, SDLoc(LSNode1), XLenVT)},
17926 if (!Subtarget.hasVendorXTHeadMemPair())
17931 unsigned OpNum = LSNode1->
getOpcode() == ISD::LOAD ? 1 : 2;
17938 auto ExtractBaseAndOffset = [](
SDValue Ptr) -> std::pair<SDValue, uint64_t> {
17941 return {
Ptr->getOperand(0), C1->getZExtValue()};
17945 auto [Base1, Offset1] = ExtractBaseAndOffset(LSNode1->
getOperand(OpNum));
17966 auto [Base2, Offset2] = ExtractBaseAndOffset(LSNode2->
getOperand(OpNum));
17969 if (Base1 != Base2)
17973 bool Valid =
false;
17974 if (MemVT == MVT::i32) {
17978 }
else if (MemVT == MVT::i64) {
18014 if (Src->isStrictFPOpcode())
18022 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
18032 EVT VT =
N->getValueType(0);
18035 MVT SrcVT = Src.getSimpleValueType();
18036 MVT SrcContainerVT = SrcVT;
18064 IsSigned ? RISCVISD::VFCVT_RTZ_X_F_VL : RISCVISD::VFCVT_RTZ_XU_F_VL;
18065 FpToInt = DAG.
getNode(
Opc,
DL, ContainerVT, XVal, Mask, VL);
18068 IsSigned ? RISCVISD::VFCVT_RM_X_F_VL : RISCVISD::VFCVT_RM_XU_F_VL;
18069 FpToInt = DAG.
getNode(
Opc,
DL, ContainerVT, XVal, Mask,
18082 if (VT != MVT::i32 && VT != XLenVT)
18087 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
18089 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
18112 EVT DstVT =
N->getValueType(0);
18113 if (DstVT != XLenVT)
18119 if (Src->isStrictFPOpcode())
18127 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
18139 if (SatVT == DstVT)
18140 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
18141 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
18142 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
18147 Src = Src.getOperand(0);
18155 if (
Opc == RISCVISD::FCVT_WU_RV64)
18168 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected extension");
18174 EVT VT =
N->getValueType(0);
18180 return DAG.
getNode(RISCVISD::BREV8,
DL, VT, Src.getOperand(0));
18193 EVT LoadVT = VPLoad->getValueType(0);
18197 N->getOperand(2) != VPLoad->getVectorLength() ||
18198 !
N->getOperand(0).hasOneUse())
18205 SDValue LoadMask = VPLoad->getMask();
18210 if (LoadMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
18212 LoadMask.
getOperand(2) != VPLoad->getVectorLength())
18220 SDValue NumElem = VPLoad->getVectorLength();
18221 uint64_t ElemWidthByte = VPLoad->getValueType(0).getScalarSizeInBits() / 8;
18233 PtrInfo, VPLoad->getMemOperand()->getFlags(),
18237 LoadVT,
DL, VPLoad->getChain(),
Base, Stride, LoadMask,
18238 VPLoad->getVectorLength(), MMO, VPLoad->isExpandingLoad());
18252 if (VPStore->getValue().getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE)
18255 SDValue VPReverse = VPStore->getValue();
18261 VPStore->getVectorLength() != VPReverse.
getOperand(2) ||
18265 SDValue StoreMask = VPStore->getMask();
18270 if (StoreMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
18272 StoreMask.
getOperand(2) != VPStore->getVectorLength())
18280 SDValue NumElem = VPStore->getVectorLength();
18294 PtrInfo, VPStore->getMemOperand()->getFlags(),
18299 VPStore->getOffset(), Stride, StoreMask, VPStore->getVectorLength(),
18300 VPStore->getMemoryVT(), MMO, VPStore->getAddressingMode(),
18301 VPStore->isTruncatingStore(), VPStore->isCompressingStore());
18313 EVT VT =
N->getValueType(0);
18325 if (In.getOpcode() != ISD::VP_SRL || In.getOperand(2) != Mask ||
18326 In.getOperand(3) != VL)
18335 if (
LHS.getOpcode() != ISD::VP_ADD ||
LHS.getOperand(2) != Mask ||
18336 LHS.getOperand(3) != VL)
18343 if (V.getOpcode() != ISD::VP_ADD || V.getOperand(2) != Mask ||
18344 V.getOperand(3) != VL)
18356 if (!FindAdd(LHS0, LHS1) && !FindAdd(LHS1, LHS0))
18370 if (
Op.getOpcode() != ISD::VP_ZERO_EXTEND ||
Op.getOperand(1) != Mask ||
18371 Op.getOperand(2) != VL)
18381 Operands[0].getOperand(0), Mask, VL);
18383 Operands[1].getOperand(0), Mask, VL);
18387 return DAG.
getNode(RISCVISD::AVGCEILU_VL,
DL, VT,
18388 {NewOp0, NewOp1, DAG.
getUNDEF(VT), Mask, VL});
18400 case RISCVISD::VFMADD_VL: Opcode = RISCVISD::VFNMSUB_VL;
break;
18401 case RISCVISD::VFNMSUB_VL: Opcode = RISCVISD::VFMADD_VL;
break;
18402 case RISCVISD::VFNMADD_VL: Opcode = RISCVISD::VFMSUB_VL;
break;
18403 case RISCVISD::VFMSUB_VL: Opcode = RISCVISD::VFNMADD_VL;
break;
18404 case RISCVISD::STRICT_VFMADD_VL: Opcode = RISCVISD::STRICT_VFNMSUB_VL;
break;
18405 case RISCVISD::STRICT_VFNMSUB_VL: Opcode = RISCVISD::STRICT_VFMADD_VL;
break;
18406 case RISCVISD::STRICT_VFNMADD_VL: Opcode = RISCVISD::STRICT_VFMSUB_VL;
break;
18407 case RISCVISD::STRICT_VFMSUB_VL: Opcode = RISCVISD::STRICT_VFNMADD_VL;
break;
18417 case RISCVISD::VFMADD_VL: Opcode = RISCVISD::VFMSUB_VL;
break;
18418 case RISCVISD::VFMSUB_VL: Opcode = RISCVISD::VFMADD_VL;
break;
18419 case RISCVISD::VFNMADD_VL: Opcode = RISCVISD::VFNMSUB_VL;
break;
18420 case RISCVISD::VFNMSUB_VL: Opcode = RISCVISD::VFNMADD_VL;
break;
18421 case RISCVISD::STRICT_VFMADD_VL: Opcode = RISCVISD::STRICT_VFMSUB_VL;
break;
18422 case RISCVISD::STRICT_VFMSUB_VL: Opcode = RISCVISD::STRICT_VFMADD_VL;
break;
18423 case RISCVISD::STRICT_VFNMADD_VL: Opcode = RISCVISD::STRICT_VFNMSUB_VL;
break;
18424 case RISCVISD::STRICT_VFNMSUB_VL: Opcode = RISCVISD::STRICT_VFNMADD_VL;
break;
18437 unsigned Offset = IsStrict ? 1 : 0;
18444 auto invertIfNegative = [&Mask, &VL](
SDValue &V) {
18445 if (V.getOpcode() == RISCVISD::FNEG_VL && V.getOperand(1) == Mask &&
18446 V.getOperand(2) == VL) {
18448 V = V.getOperand(0);
18455 bool NegA = invertIfNegative(
A);
18456 bool NegB = invertIfNegative(
B);
18457 bool NegC = invertIfNegative(
C);
18460 if (!NegA && !NegB && !NegC)
18466 {N->getOperand(0), A, B, C, Mask, VL});
18490 EVT VT =
N->getValueType(0);
18497 uint64_t ShAmt =
N->getConstantOperandVal(1);
18510 if (LShAmt < ExtSize) {
18523 if (ShAmt > 32 || VT != MVT::i64)
18553 U->getConstantOperandVal(1) > 32)
18608 if (!
Cond.hasOneUse())
18627 EVT VT =
Cond.getValueType();
18672 LHS =
LHS.getOperand(0);
18682 LHS.getOperand(0).getValueType() == Subtarget.
getXLenVT()) {
18690 RHS =
LHS.getOperand(1);
18691 LHS =
LHS.getOperand(0);
18700 auto isXorImmediate = [](
const SDValue &
Op) ->
bool {
18702 return isInt<12>(XorCnst->getSExtValue());
18706 auto singleBitOp = [&DAG](
const SDValue &VarOp,
18707 const SDValue &ConstOp) ->
bool {
18710 return (XorCnst->getSExtValue() == 1) &&
18715 auto onlyUsedBySelectOrBR = [](
const SDValue &
Op) ->
bool {
18716 for (
const SDNode *UserNode :
Op->users()) {
18717 const unsigned Opcode = UserNode->getOpcode();
18718 if (Opcode != RISCVISD::SELECT_CC && Opcode != RISCVISD::BR_CC)
18723 auto isFoldableXorEq = [isXorImmediate, singleBitOp, onlyUsedBySelectOrBR](
18726 (!isXorImmediate(
LHS.getOperand(1)) ||
18727 singleBitOp(
LHS.getOperand(0),
LHS.getOperand(1)) ||
18728 onlyUsedBySelectOrBR(
LHS));
18731 if (isFoldableXorEq(
LHS,
RHS)) {
18732 RHS =
LHS.getOperand(1);
18733 LHS =
LHS.getOperand(0);
18759 if (Subtarget.hasVendorXAndesPerf()) {
18769 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
18812 bool Commutative =
true;
18813 unsigned Opc = TrueVal.getOpcode();
18823 Commutative =
false;
18833 if (!TrueVal.hasOneUse())
18837 if (FalseVal == TrueVal.getOperand(0))
18839 else if (Commutative && FalseVal == TrueVal.getOperand(1))
18844 EVT VT =
N->getValueType(0);
18846 SDValue OtherOp = TrueVal.getOperand(1 - OpToFold);
18852 assert(IdentityOperand &&
"No identity operand!");
18857 DAG.
getSelect(
DL, OtherOpVT,
N->getOperand(0), OtherOp, IdentityOperand);
18858 return DAG.
getNode(TrueVal.getOpcode(),
DL, VT, FalseVal, NewSel);
18879 CountZeroes =
N->getOperand(2);
18880 ValOnZero =
N->getOperand(1);
18882 CountZeroes =
N->getOperand(1);
18883 ValOnZero =
N->getOperand(2);
18902 if (
Cond->getOperand(0) != CountZeroesArgument)
18921 CountZeroes, BitWidthMinusOne);
18931 EVT VT =
N->getValueType(0);
18932 EVT CondVT =
Cond.getValueType();
18940 (Subtarget.
hasCZEROLike() || Subtarget.hasVendorXTHeadCondMov())) {
18946 const APInt &MaskVal =
LHS.getConstantOperandAPInt(1);
18957 if (!TrueVal.hasOneUse() || !FalseVal.hasOneUse())
18961 if (TrueVal.getOpcode() ==
ISD::SUB && FalseVal.getOpcode() ==
ISD::ADD) {
18969 SDValue A = FalseVal.getOperand(0);
18970 SDValue B = FalseVal.getOperand(1);
18972 return ((TrueVal.getOperand(0) ==
A && TrueVal.getOperand(1) ==
B) ||
18973 (TrueVal.getOperand(1) ==
A && TrueVal.getOperand(0) ==
B));
18981 EVT VT =
N->getValueType(0);
18983 SDValue TrueVal =
N->getOperand(1);
18984 SDValue FalseVal =
N->getOperand(2);
19014 SDValue TrueVal =
N->getOperand(1);
19015 SDValue FalseVal =
N->getOperand(2);
19030 EVT VT =
N->getValueType(0);
19037 const unsigned Opcode =
N->op_begin()->getNode()->getOpcode();
19052 if (
Op.isUndef()) {
19065 if (
Op.getOpcode() != Opcode || !
Op.hasOneUse())
19074 if (
Op.getOperand(0).getValueType() !=
Op.getOperand(1).getValueType())
19098 EVT AVT =
A.getValueType();
19099 EVT BVT =
B.getValueType();
19129 if (AOpt || BOpt) {
19147 EVT OpVT =
A.getValueType();
19155 IsSigned ? ISD::PARTIAL_REDUCE_SMLA : ISD::PARTIAL_REDUCE_UMLA;
19169 EVT OpVT =
A.getOperand(0).getValueType();
19171 OpVT !=
B.getOperand(0).getValueType() ||
19177 Opc = ISD::PARTIAL_REDUCE_SMLA;
19180 Opc = ISD::PARTIAL_REDUCE_UMLA;
19183 Opc = ISD::PARTIAL_REDUCE_SUMLA;
19186 Opc = ISD::PARTIAL_REDUCE_SUMLA;
19200 if (!Subtarget.hasStdExtZvqdotq())
19204 EVT VT =
N->getValueType(0);
19207 return DAG.
getNode(ISD::VECREDUCE_ADD,
DL, VT, V);
19229 const unsigned InVecOpcode = InVec->
getOpcode();
19246 InVecLHS, InValLHS, EltNo);
19248 InVecRHS, InValRHS, EltNo);
19260 unsigned Elt = IndexC->getZExtValue();
19266 unsigned NewIdx = Elt % ConcatNumElts;
19268 unsigned ConcatOpIdx = Elt / ConcatNumElts;
19273 ConcatOps[ConcatOpIdx] = ConcatOp;
19285 EVT VT =
N->getValueType(0);
19297 !
SDValue(BaseLd, 0).hasOneUse())
19300 EVT BaseLdVT = BaseLd->getValueType(0);
19308 if (!Ld || !Ld->isSimple() || !
Op.hasOneUse() ||
19310 Ld->getValueType(0) != BaseLdVT)
19319 using PtrDiff = std::pair<std::variant<int64_t, SDValue>,
bool>;
19321 LoadSDNode *Ld2) -> std::optional<PtrDiff> {
19326 if (BIO1.equalBaseIndex(BIO2, DAG))
19331 SDValue P2 = Ld2->getBasePtr();
19334 if (P1.getOpcode() ==
ISD::ADD && P1.getOperand(0) == P2)
19335 return {{P1.getOperand(1),
true}};
19337 return std::nullopt;
19341 auto BaseDiff = GetPtrDiff(Lds[0], Lds[1]);
19346 for (
auto *It = Lds.
begin() + 1; It != Lds.
end() - 1; It++)
19347 if (GetPtrDiff(*It, *std::next(It)) != BaseDiff)
19355 unsigned WideScalarBitWidth =
19368 auto [StrideVariant, MustNegateStride] = *BaseDiff;
19370 std::holds_alternative<SDValue>(StrideVariant)
19371 ? std::get<SDValue>(StrideVariant)
19374 if (MustNegateStride)
19383 ConstStride && ConstStride->getSExtValue() >= 0)
19387 ConstStride->getSExtValue() * (
N->getNumOperands() - 1);
19393 BaseLd->getPointerInfo(), BaseLd->getMemOperand()->getFlags(), MemSize,
19397 WideVecVT,
DL, BaseLd->getChain(), BaseLd->getBasePtr(), Stride,
19411 EVT VT =
N->getValueType(0);
19428 for (
int MaskIndex : Mask) {
19429 bool SelectMaskVal = (MaskIndex < (int)NumElts);
19432 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
19469 if (
N->getValueType(0).isFixedLengthVector())
19472 SDValue Addend =
N->getOperand(0);
19475 if (
N->getOpcode() == RISCVISD::ADD_VL) {
19476 SDValue AddPassthruOp =
N->getOperand(2);
19477 if (!AddPassthruOp.
isUndef())
19481 auto IsVWMulOpc = [](
unsigned Opc) {
19483 case RISCVISD::VWMUL_VL:
19484 case RISCVISD::VWMULU_VL:
19485 case RISCVISD::VWMULSU_VL:
19500 if (!MulPassthruOp.
isUndef())
19510 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
19511 }(
N, DAG, Subtarget);
19516 if (AddMask != MulMask || AddVL != MulVL)
19519 const auto &TSInfo =
19521 unsigned Opc = TSInfo.getMAccOpcode(MulOp.
getOpcode());
19524 EVT VT =
N->getValueType(0);
19535 if (!
N->getValueType(0).isVector())
19538 SDValue Addend =
N->getOperand(0);
19541 if (
N->getOpcode() == RISCVISD::ADD_VL) {
19542 SDValue AddPassthruOp =
N->getOperand(2);
19543 if (!AddPassthruOp.
isUndef())
19547 auto IsVqdotqOpc = [](
unsigned Opc) {
19549 case RISCVISD::VQDOT_VL:
19550 case RISCVISD::VQDOTU_VL:
19551 case RISCVISD::VQDOTSU_VL:
19571 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
19572 }(
N, DAG, Subtarget);
19575 if (AddVL != MulVL)
19578 if (AddMask.getOpcode() != RISCVISD::VMSET_VL ||
19579 AddMask.getOperand(0) != MulVL)
19584 EVT VT =
N->getValueType(0);
19585 Addend = DAG.
getNode(RISCVISD::ADD_VL,
DL, VT, Addend, AccumOp,
19586 DAG.
getUNDEF(VT), AddMask, AddVL);
19604 const EVT IndexVT = Index.getValueType();
19608 if (!isIndexTypeSigned(IndexType))
19638 assert(ShuffleMask.empty());
19640 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
19643 if (Index->getOperand(i)->isUndef())
19645 uint64_t C = Index->getConstantOperandVal(i);
19646 if (
C % ElementSize != 0)
19648 C =
C / ElementSize;
19651 ShuffleMask.push_back(
C);
19652 ActiveLanes.
set(
C);
19654 return ActiveLanes.
all();
19672 if (NumElems % 2 != 0)
19676 const unsigned WiderElementSize = ElementSize * 2;
19677 if (WiderElementSize > ST.getELen()/8)
19680 if (!ST.enableUnalignedVectorMem() && BaseAlign < WiderElementSize)
19683 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
19686 if (Index->getOperand(i)->isUndef())
19690 uint64_t C = Index->getConstantOperandVal(i);
19692 if (
C % WiderElementSize != 0)
19697 if (
C !=
Last + ElementSize)
19716 if (!IsVLMAX || Mask.getOpcode() != RISCVISD::VMSET_VL ||
19717 Mask.getOperand(0) != VL)
19720 auto IsTruncNode = [&](
SDValue V) {
19721 return V.getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL &&
19722 V.getOperand(1) == Mask && V.getOperand(2) == VL;
19729 while (IsTruncNode(
Op)) {
19730 if (!
Op.hasOneUse())
19732 Op =
Op.getOperand(0);
19765 assert(
N->getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL);
19767 MVT VT =
N->getSimpleValueType(0);
19772 auto MatchMinMax = [&VL, &Mask](
SDValue V,
unsigned Opc,
unsigned OpcVL,
19774 if (V.getOpcode() !=
Opc &&
19775 !(V.getOpcode() == OpcVL && V.getOperand(2).isUndef() &&
19776 V.getOperand(3) == Mask && V.getOperand(4) == VL))
19784 Op.getOperand(1).getValueType().isFixedLengthVector() &&
19786 Op.getOperand(1).getOperand(0).getValueType() ==
Op.getValueType() &&
19788 Op =
Op.getOperand(1).getOperand(0);
19791 return V.getOperand(0);
19793 if (
Op.getOpcode() == RISCVISD::VMV_V_X_VL &&
Op.getOperand(0).isUndef() &&
19794 Op.getOperand(2) == VL) {
19797 Op1->getAPIntValue().sextOrTrunc(
Op.getScalarValueSizeInBits());
19807 auto DetectUSatPattern = [&](
SDValue V) {
19819 MatchMinMax(SMinOp,
ISD::SMAX, RISCVISD::SMAX_VL, LoC))
19828 MatchMinMax(SMaxOp,
ISD::SMIN, RISCVISD::SMIN_VL, HiC))
19831 return DAG.
getNode(RISCVISD::SMAX_VL,
DL, V.getValueType(), SMinOp,
19832 V.getOperand(1), DAG.
getUNDEF(V.getValueType()),
19838 auto DetectSSatPattern = [&](
SDValue V) {
19840 unsigned NumSrcBits = V.getScalarValueSizeInBits();
19847 MatchMinMax(SMinOp,
ISD::SMAX, RISCVISD::SMAX_VL, LoC))
19848 if (HiC == SignedMax && LoC == SignedMin)
19853 MatchMinMax(SMaxOp,
ISD::SMIN, RISCVISD::SMIN_VL, HiC))
19854 if (HiC == SignedMax && LoC == SignedMin)
19863 while (Src.getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL &&
19864 Src.getOperand(1) == Mask && Src.getOperand(2) == VL &&
19866 Src = Src.getOperand(0);
19870 if ((Val = DetectUSatPattern(Src)))
19871 ClipOpc = RISCVISD::TRUNCATE_VECTOR_VL_USAT;
19872 else if ((Val = DetectSSatPattern(Src)))
19873 ClipOpc = RISCVISD::TRUNCATE_VECTOR_VL_SSAT;
19882 Val = DAG.
getNode(ClipOpc,
DL, ValVT, Val, Mask, VL);
19883 }
while (ValVT != VT);
19901 unsigned Opc =
N->getOpcode();
19903 "Unexpected opcode");
19904 EVT VT =
N->getValueType(0);
19913 Src = Src.getOperand(0);
19915 if (Src.getOpcode() != ISD::BITCAST)
19917 Src = Src.getOperand(0);
19918 }
else if (
Opc == ISD::VECREDUCE_ADD) {
19921 Src = Src.getOperand(0);
19924 EVT SrcEVT = Src.getValueType();
19939 if (
Opc == ISD::VECREDUCE_ADD) {
19946 VectorBitsMax, EltSize, MinSize);
19951 MVT ContainerVT = SrcMVT;
19979 if (!
LHS.hasOneUse())
19982 switch (
LHS.getOpcode()) {
19984 case RISCVISD::VSEXT_VL:
19985 Opcode = RISCVISD::VWMULSU_VL;
19988 case RISCVISD::VZEXT_VL:
19989 Opcode = RISCVISD::VWMULU_VL;
20000 else if (
RHS.getOpcode() == RISCVISD::VMV_V_X_VL &&
20002 ShAmtInt =
RHS.getConstantOperandVal(1);
20015 if (ShAmtInt >= NarrowBits)
20017 MVT VT =
N->getSimpleValueType(0);
20024 switch (
N->getOpcode()) {
20029 case RISCVISD::SHL_VL:
20030 Passthru =
N->getOperand(2);
20031 Mask =
N->getOperand(3);
20032 VL =
N->getOperand(4);
20037 return DAG.
getNode(Opcode,
DL, VT, NarrowOp,
20039 Passthru, Mask, VL);
20045 const MVT XLenVT = Subtarget.getXLenVT();
20051 auto SimplifyDemandedLowBitsHelper = [&](
unsigned OpNo,
unsigned LowBits) {
20062 switch (
N->getOpcode()) {
20065 case RISCVISD::SplitF64: {
20069 if (Op0->
getOpcode() == RISCVISD::BuildPairF64)
20082 APInt V =
C->getValueAPF().bitcastToAPInt();
20111 case RISCVISD::SLLW:
20112 case RISCVISD::SRAW:
20113 case RISCVISD::SRLW:
20114 case RISCVISD::RORW:
20115 case RISCVISD::ROLW: {
20117 if (SimplifyDemandedLowBitsHelper(0, 32) ||
20118 SimplifyDemandedLowBitsHelper(1, 5))
20123 case RISCVISD::CLZW:
20124 case RISCVISD::CTZW: {
20126 if (SimplifyDemandedLowBitsHelper(0, 32))
20130 case RISCVISD::FMV_W_X_RV64: {
20135 if (Op0.
getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64)
20139 case RISCVISD::FMV_X_ANYEXTH:
20140 case RISCVISD::FMV_X_ANYEXTW_RV64: {
20143 MVT VT =
N->getSimpleValueType(0);
20154 if ((
N->getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64 &&
20155 Op0->
getOpcode() == RISCVISD::FMV_W_X_RV64) ||
20156 (
N->getOpcode() == RISCVISD::FMV_X_ANYEXTH &&
20157 Op0->
getOpcode() == RISCVISD::FMV_H_X)) {
20159 "Unexpected value type!");
20169 LN0->getBasePtr(), IVT, LN0->getMemOperand());
20182 unsigned FPBits =
N->getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64 ? 32 : 16;
20193 EVT VT =
N->getValueType(0);
20242 EVT VT =
N->getValueType(0);
20259 if (!
C || !
C->getValueAPF().isExactlyValue(+1.0))
20274 case ISD::FMINNUM: {
20289 if (
N->getValueType(0) == MVT::i64 && Subtarget.is64Bit()) {
20294 Src.getOperand(0));
20299 Src.getOperand(0), Src.getOperand(1));
20307 case RISCVISD::TRUNCATE_VECTOR_VL:
20311 case ISD::VP_TRUNCATE:
20319 case RISCVISD::CZERO_EQZ:
20320 case RISCVISD::CZERO_NEZ: {
20324 unsigned Opc =
N->getOpcode();
20327 if (
Opc == RISCVISD::CZERO_EQZ && Val ==
Cond)
20331 Opc == RISCVISD::CZERO_EQZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ;
20339 return DAG.
getNode(InvOpc,
SDLoc(
N),
N->getValueType(0), Val, NewCond);
20349 N->getValueType(0), Val,
Cond.getOperand(0));
20353 case RISCVISD::SELECT_CC: {
20360 SDValue FalseV =
N->getOperand(4);
20362 EVT VT =
N->getValueType(0);
20365 if (TrueV == FalseV)
20396 return DAG.
getNode(RISCVISD::SELECT_CC,
DL,
N->getValueType(0),
20397 {LHS, RHS, CC, TrueV, FalseV});
20399 if (!Subtarget.hasConditionalMoveFusion()) {
20456 case RISCVISD::BR_CC: {
20463 return DAG.
getNode(RISCVISD::BR_CC,
DL,
N->getValueType(0),
20464 N->getOperand(0), LHS, RHS, CC,
N->getOperand(4));
20477 EVT VT =
N->getValueType(0);
20489 if (In2.
getOpcode() != ISD::FP_EXTEND &&
20498 DAG.
getNode(ISD::FNEG,
DL, VT, NewFPExtRound));
20500 case ISD::MGATHER: {
20502 const EVT VT =
N->getValueType(0);
20503 SDValue Index = MGN->getIndex();
20504 SDValue ScaleOp = MGN->getScale();
20506 assert(!MGN->isIndexScaled() &&
20507 "Scaled gather/scatter should not be formed");
20512 N->getVTList(), MGN->getMemoryVT(),
DL,
20513 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
20514 MGN->getBasePtr(), Index, ScaleOp},
20515 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
20519 N->getVTList(), MGN->getMemoryVT(),
DL,
20520 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
20521 MGN->getBasePtr(), Index, ScaleOp},
20522 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
20528 if (std::optional<VIDSequence> SimpleVID =
20530 SimpleVID && SimpleVID->StepDenominator == 1) {
20531 const int64_t StepNumerator = SimpleVID->StepNumerator;
20532 const int64_t Addend = SimpleVID->Addend;
20539 assert(MGN->getBasePtr()->getValueType(0) == PtrVT);
20547 VT,
DL, MGN->getChain(), BasePtr,
20549 EVL, MGN->getMemOperand());
20551 MGN->getPassThru());
20561 MGN->getBasePtr(), DAG.
getUNDEF(XLenVT),
20563 MGN->getMemoryVT(), MGN->getMemOperand(),
20572 MGN->getMemOperand()->getBaseAlign(), Subtarget)) {
20574 for (
unsigned i = 0; i < Index->getNumOperands(); i += 2)
20575 NewIndices.
push_back(Index.getOperand(i));
20576 EVT IndexVT = Index.getValueType()
20583 assert(EltCnt.isKnownEven() &&
"Splitting vector, but not in half!");
20585 EltCnt.divideCoefficientBy(2));
20588 EltCnt.divideCoefficientBy(2));
20593 {MGN->getChain(), Passthru, Mask, MGN->getBasePtr(),
20601 case ISD::MSCATTER:{
20603 SDValue Index = MSN->getIndex();
20604 SDValue ScaleOp = MSN->getScale();
20606 assert(!MSN->isIndexScaled() &&
20607 "Scaled gather/scatter should not be formed");
20612 N->getVTList(), MSN->getMemoryVT(),
DL,
20613 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
20615 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
20619 N->getVTList(), MSN->getMemoryVT(),
DL,
20620 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
20622 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
20624 EVT VT = MSN->getValue()->getValueType(0);
20626 if (!MSN->isTruncatingStore() &&
20630 return DAG.
getMaskedStore(MSN->getChain(),
DL, Shuffle, MSN->getBasePtr(),
20631 DAG.
getUNDEF(XLenVT), MSN->getMask(),
20632 MSN->getMemoryVT(), MSN->getMemOperand(),
20637 case ISD::VP_GATHER: {
20639 SDValue Index = VPGN->getIndex();
20640 SDValue ScaleOp = VPGN->getScale();
20642 assert(!VPGN->isIndexScaled() &&
20643 "Scaled gather/scatter should not be formed");
20648 {VPGN->getChain(), VPGN->getBasePtr(), Index,
20649 ScaleOp, VPGN->getMask(),
20650 VPGN->getVectorLength()},
20651 VPGN->getMemOperand(), IndexType);
20655 {VPGN->getChain(), VPGN->getBasePtr(), Index,
20656 ScaleOp, VPGN->getMask(),
20657 VPGN->getVectorLength()},
20658 VPGN->getMemOperand(), IndexType);
20662 case ISD::VP_SCATTER: {
20664 SDValue Index = VPSN->getIndex();
20665 SDValue ScaleOp = VPSN->getScale();
20667 assert(!VPSN->isIndexScaled() &&
20668 "Scaled gather/scatter should not be formed");
20673 {VPSN->getChain(), VPSN->getValue(),
20674 VPSN->getBasePtr(), Index, ScaleOp,
20675 VPSN->getMask(), VPSN->getVectorLength()},
20676 VPSN->getMemOperand(), IndexType);
20680 {VPSN->getChain(), VPSN->getValue(),
20681 VPSN->getBasePtr(), Index, ScaleOp,
20682 VPSN->getMask(), VPSN->getVectorLength()},
20683 VPSN->getMemOperand(), IndexType);
20686 case RISCVISD::SHL_VL:
20690 case RISCVISD::SRA_VL:
20691 case RISCVISD::SRL_VL: {
20693 if (ShAmt.
getOpcode() == RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL) {
20697 EVT VT =
N->getValueType(0);
20700 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt,
20701 N->getOperand(2),
N->getOperand(3),
N->getOperand(4));
20716 if (ShAmt.
getOpcode() == RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL) {
20719 EVT VT =
N->getValueType(0);
20722 DAG.
getRegister(RISCV::X0, Subtarget.getXLenVT()));
20723 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt);
20727 case RISCVISD::ADD_VL:
20735 case RISCVISD::VWADD_W_VL:
20736 case RISCVISD::VWADDU_W_VL:
20737 case RISCVISD::VWSUB_W_VL:
20738 case RISCVISD::VWSUBU_W_VL:
20740 case RISCVISD::OR_VL:
20741 case RISCVISD::SUB_VL:
20742 case RISCVISD::MUL_VL:
20744 case RISCVISD::VFMADD_VL:
20745 case RISCVISD::VFNMADD_VL:
20746 case RISCVISD::VFMSUB_VL:
20747 case RISCVISD::VFNMSUB_VL:
20748 case RISCVISD::STRICT_VFMADD_VL:
20749 case RISCVISD::STRICT_VFNMADD_VL:
20750 case RISCVISD::STRICT_VFMSUB_VL:
20751 case RISCVISD::STRICT_VFNMSUB_VL:
20753 case RISCVISD::FADD_VL:
20754 case RISCVISD::FSUB_VL:
20755 case RISCVISD::FMUL_VL:
20756 case RISCVISD::VFWADD_W_VL:
20757 case RISCVISD::VFWSUB_W_VL:
20765 if (
N->getOpcode() != ISD::STORE)
20769 SDValue Chain = Store->getChain();
20770 EVT MemVT = Store->getMemoryVT();
20771 SDValue Val = Store->getValue();
20774 bool IsScalarizable =
20776 Store->isSimple() &&
20806 NewVT, *Store->getMemOperand())) {
20808 return DAG.
getStore(Chain,
DL, NewV, Store->getBasePtr(),
20809 Store->getPointerInfo(), Store->getBaseAlign(),
20810 Store->getMemOperand()->getFlags());
20820 L->hasNUsesOfValue(1, 0) && L->hasNUsesOfValue(1, 1) &&
20822 L->getMemoryVT() == MemVT) {
20825 NewVT, *Store->getMemOperand()) &&
20827 NewVT, *L->getMemOperand())) {
20829 L->getPointerInfo(), L->getBaseAlign(),
20830 L->getMemOperand()->getFlags());
20831 return DAG.
getStore(Chain,
DL, NewL, Store->getBasePtr(),
20832 Store->getPointerInfo(), Store->getBaseAlign(),
20833 Store->getMemOperand()->getFlags());
20840 if ((Val.
getOpcode() == RISCVISD::VMV_X_S ||
20846 MVT VecVT = Src.getSimpleValueType();
20853 Store->getChain(),
DL, Src, Store->getBasePtr(), Store->getOffset(),
20856 Store->getMemOperand(), Store->getAddressingMode(),
20857 Store->isTruncatingStore(),
false);
20864 EVT VT =
N->getValueType(0);
20889 case RISCVISD::VFMV_V_F_VL: {
20890 const MVT VT =
N->getSimpleValueType(0);
20891 SDValue Passthru =
N->getOperand(0);
20892 SDValue Scalar =
N->getOperand(1);
20897 return DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL, VT, Passthru, Scalar, VL);
20900 case RISCVISD::VMV_V_X_VL: {
20901 const MVT VT =
N->getSimpleValueType(0);
20902 SDValue Passthru =
N->getOperand(0);
20903 SDValue Scalar =
N->getOperand(1);
20908 unsigned ScalarSize = Scalar.getValueSizeInBits();
20910 if (ScalarSize > EltWidth && Passthru.
isUndef())
20911 if (SimplifyDemandedLowBitsHelper(1, EltWidth))
20918 (!Const || Const->isZero() ||
20919 !Const->getAPIntValue().sextOrTrunc(EltWidth).isSignedIntN(5)))
20920 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, VT, Passthru, Scalar, VL);
20924 case RISCVISD::VFMV_S_F_VL: {
20929 if (
N->getOperand(0).isUndef() &&
20932 Src.getOperand(0).getValueType().isScalableVector()) {
20933 EVT VT =
N->getValueType(0);
20953 case RISCVISD::VMV_S_X_VL: {
20954 const MVT VT =
N->getSimpleValueType(0);
20955 SDValue Passthru =
N->getOperand(0);
20956 SDValue Scalar =
N->getOperand(1);
20962 unsigned ScalarSize = Scalar.getValueSizeInBits();
20964 if (ScalarSize > EltWidth && SimplifyDemandedLowBitsHelper(1, EltWidth))
20967 if (Scalar.getOpcode() == RISCVISD::VMV_X_S && Passthru.
isUndef() &&
20968 Scalar.getOperand(0).getValueType() ==
N->getValueType(0))
20969 return Scalar.getOperand(0);
20976 DAG.
getNode(
N->getOpcode(),
DL, M1VT, M1Passthru, Scalar, VL);
20985 Const && !Const->isZero() &&
isInt<5>(Const->getSExtValue()) &&
20987 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru, Scalar, VL);
20991 case RISCVISD::VMV_X_S: {
20993 MVT VecVT =
N->getOperand(0).getSimpleValueType();
20995 if (M1VT.
bitsLT(VecVT)) {
20997 return DAG.
getNode(RISCVISD::VMV_X_S,
DL,
N->getSimpleValueType(0), Vec);
21005 unsigned IntNo =
N->getConstantOperandVal(IntOpNo);
21010 case Intrinsic::riscv_vcpop:
21011 case Intrinsic::riscv_vcpop_mask:
21012 case Intrinsic::riscv_vfirst:
21013 case Intrinsic::riscv_vfirst_mask: {
21015 if (IntNo == Intrinsic::riscv_vcpop_mask ||
21016 IntNo == Intrinsic::riscv_vfirst_mask)
21017 VL =
N->getOperand(3);
21022 EVT VT =
N->getValueType(0);
21023 if (IntNo == Intrinsic::riscv_vfirst ||
21024 IntNo == Intrinsic::riscv_vfirst_mask)
21028 case Intrinsic::riscv_vsseg2_mask:
21029 case Intrinsic::riscv_vsseg3_mask:
21030 case Intrinsic::riscv_vsseg4_mask:
21031 case Intrinsic::riscv_vsseg5_mask:
21032 case Intrinsic::riscv_vsseg6_mask:
21033 case Intrinsic::riscv_vsseg7_mask:
21034 case Intrinsic::riscv_vsseg8_mask: {
21036 unsigned NF = Tuple.getValueType().getRISCVVectorTupleNumFields();
21038 if (Subtarget.hasOptimizedSegmentLoadStore(NF) || !Tuple.hasOneUse() ||
21039 Tuple.getOpcode() != RISCVISD::TUPLE_INSERT ||
21040 !Tuple.getOperand(0).isUndef())
21048 "Type mismatch without bitcast?");
21049 unsigned Stride = SEW / 8 * NF;
21050 unsigned Offset = SEW / 8 * Idx;
21077 case ISD::EXPERIMENTAL_VP_REVERSE:
21079 case ISD::VP_STORE:
21081 case ISD::BITCAST: {
21082 assert(Subtarget.useRVVForFixedLengthVectors());
21084 EVT VT =
N->getValueType(0);
21095 for (
unsigned i = 0; i < NF; ++i)
21096 Result = DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VT, Result,
Splat,
21102 if ((SrcVT == MVT::v1i1 || SrcVT == MVT::v2i1 || SrcVT == MVT::v4i1) &&
21115 case ISD::VECREDUCE_ADD:
21123 case RISCVISD::VRGATHER_VX_VL: {
21126 EVT VT =
N->getValueType(0);
21129 SDValue Passthru =
N->getOperand(2);
21136 Src = Src.getOperand(1);
21138 switch (Src.getOpcode()) {
21141 case RISCVISD::VMV_V_X_VL:
21142 case RISCVISD::VFMV_V_F_VL:
21150 case RISCVISD::VMV_S_X_VL:
21151 case RISCVISD::VFMV_S_F_VL:
21167 case RISCVISD::TUPLE_EXTRACT: {
21168 EVT VT =
N->getValueType(0);
21170 unsigned Idx =
N->getConstantOperandVal(1);
21175 switch (Tuple.getConstantOperandVal(1)) {
21178 case Intrinsic::riscv_vlseg2_mask:
21179 case Intrinsic::riscv_vlseg3_mask:
21180 case Intrinsic::riscv_vlseg4_mask:
21181 case Intrinsic::riscv_vlseg5_mask:
21182 case Intrinsic::riscv_vlseg6_mask:
21183 case Intrinsic::riscv_vlseg7_mask:
21184 case Intrinsic::riscv_vlseg8_mask:
21185 NF = Tuple.getValueType().getRISCVVectorTupleNumFields();
21189 if (!NF || Subtarget.hasOptimizedSegmentLoadStore(NF))
21194 "Type mismatch without bitcast?");
21195 unsigned Stride = SEW / 8 * NF;
21196 unsigned Offset = SEW / 8 * Idx;
21199 Tuple.getOperand(0),
21221 return Result.getValue(0);
21223 case RISCVISD::TUPLE_INSERT: {
21225 if (
N->getOperand(1).isUndef())
21226 return N->getOperand(0);
21229 case RISCVISD::VSLIDE1UP_VL:
21230 case RISCVISD::VFSLIDE1UP_VL: {
21234 MVT VT =
N->getSimpleValueType(0);
21238 if (!
N->getOperand(0).isUndef() ||
21257 return getVSlideup(DAG, Subtarget,
DL, VT, SrcVec,
N->getOperand(1),
21267 EVT XVT,
unsigned KeptBits)
const {
21272 if (XVT != MVT::i32 && XVT != MVT::i64)
21276 if (KeptBits == 32 || KeptBits == 64)
21280 return Subtarget.hasStdExtZbb() &&
21281 ((KeptBits == 8 && XVT == MVT::i64 && !Subtarget.is64Bit()) ||
21289 "Expected shift op");
21313 if (Ty.isScalarInteger() &&
21316 return isUsedByLdSt(N0.
getNode(),
N);
21322 if (C2 && Subtarget.hasShlAdd(C2->getZExtValue()) &&
N->hasOneUse() &&
21323 N->user_begin()->getOpcode() ==
ISD::ADD &&
21324 !isUsedByLdSt(*
N->user_begin(),
nullptr) &&
21329 const APInt &C1Int = C1->getAPIntValue();
21330 APInt ShiftedC1Int = C1Int << C2->getAPIntValue();
21351 ShiftedC1Int, Ty.getSizeInBits(), Subtarget,
21356 if (C1Cost < ShiftedC1Cost)
21379 EVT VT =
Op.getValueType();
21383 unsigned Opcode =
Op.getOpcode();
21391 const APInt &Mask =
C->getAPIntValue();
21400 auto IsLegalMask = [ShrunkMask, ExpandedMask](
const APInt &Mask) ->
bool {
21401 return ShrunkMask.
isSubsetOf(Mask) && Mask.isSubsetOf(ExpandedMask);
21403 auto UseMask = [Mask,
Op, &TLO](
const APInt &NewMask) ->
bool {
21404 if (NewMask == Mask)
21409 Op.getOperand(0), NewC);
21422 APInt NewMask =
APInt(Mask.getBitWidth(), 0xffff);
21423 if (IsLegalMask(NewMask))
21424 return UseMask(NewMask);
21427 if (VT == MVT::i64) {
21429 if (IsLegalMask(NewMask))
21430 return UseMask(NewMask);
21445 APInt NewMask = ShrunkMask;
21446 if (MinSignedBits <= 12)
21448 else if (!
C->isOpaque() && MinSignedBits <= 32 && !ShrunkMask.
isSignedIntN(32))
21454 assert(IsLegalMask(NewMask));
21455 return UseMask(NewMask);
21459 static const uint64_t GREVMasks[] = {
21460 0x5555555555555555ULL, 0x3333333333333333ULL, 0x0F0F0F0F0F0F0F0FULL,
21461 0x00FF00FF00FF00FFULL, 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL};
21463 for (
unsigned Stage = 0; Stage != 6; ++Stage) {
21464 unsigned Shift = 1 << Stage;
21465 if (ShAmt & Shift) {
21467 uint64_t Res = ((x & Mask) << Shift) | ((x >> Shift) & Mask);
21479 const APInt &DemandedElts,
21481 unsigned Depth)
const {
21483 unsigned Opc =
Op.getOpcode();
21488 "Should use MaskedValueIsZero if you don't know whether Op"
21489 " is a target node!");
21494 case RISCVISD::SELECT_CC: {
21505 case RISCVISD::VCPOP_VL: {
21510 case RISCVISD::CZERO_EQZ:
21511 case RISCVISD::CZERO_NEZ:
21517 case RISCVISD::REMUW: {
21527 case RISCVISD::DIVUW: {
21537 case RISCVISD::SLLW: {
21546 case RISCVISD::SRLW: {
21555 case RISCVISD::SRAW: {
21564 case RISCVISD::CTZW: {
21571 case RISCVISD::CLZW: {
21578 case RISCVISD::BREV8:
21579 case RISCVISD::ORC_B: {
21583 bool IsGORC =
Op.getOpcode() == RISCVISD::ORC_B;
21591 case RISCVISD::READ_VLENB: {
21594 const unsigned MinVLenB = Subtarget.getRealMinVLen() / 8;
21595 const unsigned MaxVLenB = Subtarget.getRealMaxVLen() / 8;
21596 assert(MinVLenB > 0 &&
"READ_VLENB without vector extension enabled?");
21599 if (MaxVLenB == MinVLenB)
21603 case RISCVISD::FCLASS: {
21616 case Intrinsic::riscv_vsetvli:
21617 case Intrinsic::riscv_vsetvlimax: {
21618 bool HasAVL = IntNo == Intrinsic::riscv_vsetvli;
21619 unsigned VSEW =
Op.getConstantOperandVal(HasAVL + 1);
21624 uint64_t MaxVL = Subtarget.getRealMaxVLen() / SEW;
21625 MaxVL = (Fractional) ? MaxVL / LMul : MaxVL * LMul;
21629 MaxVL = std::min(MaxVL,
Op.getConstantOperandVal(1));
21631 unsigned KnownZeroFirstBit =
Log2_32(MaxVL) + 1;
21644 unsigned Depth)
const {
21645 switch (
Op.getOpcode()) {
21648 case RISCVISD::SELECT_CC: {
21651 if (Tmp == 1)
return 1;
21654 return std::min(Tmp, Tmp2);
21656 case RISCVISD::CZERO_EQZ:
21657 case RISCVISD::CZERO_NEZ:
21661 case RISCVISD::ABSW: {
21666 if (Tmp < 33)
return 1;
21669 case RISCVISD::SRAW: {
21676 return std::max(Tmp, 33U);
21678 case RISCVISD::SLLW:
21679 case RISCVISD::SRLW:
21680 case RISCVISD::DIVW:
21681 case RISCVISD::DIVUW:
21682 case RISCVISD::REMUW:
21683 case RISCVISD::ROLW:
21684 case RISCVISD::RORW:
21685 case RISCVISD::FCVT_W_RV64:
21686 case RISCVISD::FCVT_WU_RV64:
21687 case RISCVISD::STRICT_FCVT_W_RV64:
21688 case RISCVISD::STRICT_FCVT_WU_RV64:
21691 case RISCVISD::VMV_X_S: {
21697 unsigned XLen = Subtarget.getXLen();
21698 unsigned EltBits =
Op.getOperand(0).getScalarValueSizeInBits();
21699 if (EltBits <= XLen)
21700 return XLen - EltBits + 1;
21704 unsigned IntNo =
Op.getConstantOperandVal(1);
21708 case Intrinsic::riscv_masked_atomicrmw_xchg:
21709 case Intrinsic::riscv_masked_atomicrmw_add:
21710 case Intrinsic::riscv_masked_atomicrmw_sub:
21711 case Intrinsic::riscv_masked_atomicrmw_nand:
21712 case Intrinsic::riscv_masked_atomicrmw_max:
21713 case Intrinsic::riscv_masked_atomicrmw_min:
21714 case Intrinsic::riscv_masked_atomicrmw_umax:
21715 case Intrinsic::riscv_masked_atomicrmw_umin:
21716 case Intrinsic::riscv_masked_cmpxchg:
21723 assert(Subtarget.hasStdExtA());
21724 return Op.getValueSizeInBits() - 31;
21736 unsigned Depth)
const {
21739 switch (
Op.getOpcode()) {
21740 case RISCVISD::BREV8:
21741 case RISCVISD::ORC_B: {
21743 bool IsGORC =
Op.getOpcode() == RISCVISD::ORC_B;
21751 OriginalDemandedElts, Known2, TLO,
Depth + 1))
21763 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
21771 switch (
Op.getOpcode()) {
21772 case RISCVISD::SLLW:
21773 case RISCVISD::SRAW:
21774 case RISCVISD::SRLW:
21775 case RISCVISD::RORW:
21776 case RISCVISD::ROLW:
21780 case RISCVISD::SELECT_CC:
21782 assert(
Op.getOperand(0).getValueType().isInteger() &&
21783 "RISCVISD::SELECT_CC only compares integers");
21792 assert(Ld &&
"Unexpected null LoadSDNode");
21801 if (!CNode || CNode->isMachineConstantPoolEntry() ||
21802 CNode->getOffset() != 0)
21809 if (
Ptr.getOpcode() == RISCVISD::LLA) {
21810 auto *CNode = GetSupportedConstantPool(
Ptr.getOperand(0));
21811 if (!CNode || CNode->getTargetFlags() != 0)
21814 return CNode->getConstVal();
21818 if (
Ptr.getOpcode() != RISCVISD::ADD_LO ||
21819 Ptr.getOperand(0).getOpcode() != RISCVISD::HI)
21822 auto *CNodeLo = GetSupportedConstantPool(
Ptr.getOperand(1));
21823 auto *CNodeHi = GetSupportedConstantPool(
Ptr.getOperand(0).getOperand(0));
21829 if (CNodeLo->getConstVal() != CNodeHi->getConstVal())
21832 return CNodeLo->getConstVal();
21837 assert(
MI.getOpcode() == RISCV::ReadCounterWide &&
"Unexpected instruction");
21869 Register ReadAgainReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
21872 int64_t LoCounter =
MI.getOperand(2).getImm();
21873 int64_t HiCounter =
MI.getOperand(3).getImm();
21883 BuildMI(LoopMBB,
DL,
TII->get(RISCV::CSRRS), ReadAgainReg)
21895 MI.eraseFromParent();
21903 assert(
MI.getOpcode() == RISCV::SplitF64Pseudo &&
"Unexpected instruction");
21911 Register SrcReg =
MI.getOperand(2).getReg();
21916 TII.storeRegToStackSlot(*BB,
MI, SrcReg,
MI.getOperand(2).isKill(), FI, SrcRC,
21931 MI.eraseFromParent();
21938 assert(
MI.getOpcode() == RISCV::BuildPairF64Pseudo &&
21939 "Unexpected instruction");
21945 Register DstReg =
MI.getOperand(0).getReg();
21967 TII.loadRegFromStackSlot(*BB,
MI, DstReg, FI, DstRC, RI,
Register());
21968 MI.eraseFromParent();
21973 unsigned RelOpcode,
unsigned EqOpcode,
21976 Register DstReg =
MI.getOperand(0).getReg();
21977 Register Src1Reg =
MI.getOperand(1).getReg();
21978 Register Src2Reg =
MI.getOperand(2).getReg();
21980 Register SavedFFlags =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22004 MI.eraseFromParent();
22055 F->insert(It, FirstMBB);
22056 F->insert(It, SecondMBB);
22057 F->insert(It, SinkMBB);
22107 First.eraseFromParent();
22146 if (
MI.getOpcode() != RISCV::Select_GPR_Using_CC_GPR &&
22147 MI.getOperand(1).isReg() &&
MI.getOperand(2).isReg() &&
22148 Next != BB->
end() &&
Next->getOpcode() ==
MI.getOpcode() &&
22149 Next->getOperand(5).getReg() ==
MI.getOperand(0).getReg() &&
22150 Next->getOperand(5).isKill())
22155 if (
MI.getOperand(2).isReg())
22156 RHS =
MI.getOperand(2).getReg();
22161 SelectDests.
insert(
MI.getOperand(0).getReg());
22165 SequenceMBBI !=
E; ++SequenceMBBI) {
22166 if (SequenceMBBI->isDebugInstr())
22168 if (RISCVInstrInfo::isSelectPseudo(*SequenceMBBI)) {
22169 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
22170 !SequenceMBBI->getOperand(2).isReg() ||
22171 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
22172 SequenceMBBI->getOperand(3).getImm() != CC ||
22173 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
22174 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
22176 LastSelectPseudo = &*SequenceMBBI;
22178 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
22181 if (SequenceMBBI->hasUnmodeledSideEffects() ||
22182 SequenceMBBI->mayLoadOrStore() ||
22183 SequenceMBBI->usesCustomInsertionHook())
22186 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
22201 F->insert(
I, IfFalseMBB);
22202 F->insert(
I, TailMBB);
22205 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
22211 TailMBB->
push_back(DebugInstr->removeFromParent());
22215 TailMBB->
splice(TailMBB->
end(), HeadMBB,
22225 if (
MI.getOperand(2).isImm())
22228 .
addImm(
MI.getOperand(2).getImm())
22240 auto SelectMBBI =
MI.getIterator();
22241 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
22243 while (SelectMBBI != SelectEnd) {
22244 auto Next = std::next(SelectMBBI);
22245 if (RISCVInstrInfo::isSelectPseudo(*SelectMBBI)) {
22248 TII.get(RISCV::PHI), SelectMBBI->getOperand(0).getReg())
22249 .
addReg(SelectMBBI->getOperand(4).getReg())
22251 .
addReg(SelectMBBI->getOperand(5).getReg())
22258 F->getProperties().resetNoPHIs();
22266 RISCVVInversePseudosTable::getBaseInfo(MCOpcode, LMul, SEW);
22267 assert(
Inverse &&
"Unexpected LMUL and SEW pair for instruction");
22269 RISCV::lookupMaskedIntrinsicByUnmasked(
Inverse->Pseudo);
22270 assert(
Masked &&
"Could not find masked instruction for LMUL and SEW pair");
22276 unsigned CVTXOpc) {
22282 Register SavedFFLAGS =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22295 .
add(
MI.getOperand(1))
22296 .
add(
MI.getOperand(2))
22297 .
add(
MI.getOperand(3))
22299 .
add(
MI.getOperand(4))
22300 .
add(
MI.getOperand(5))
22301 .
add(
MI.getOperand(6))
22316 .
add(
MI.getOperand(0))
22317 .
add(
MI.getOperand(1))
22319 .
add(
MI.getOperand(3))
22321 .
add(
MI.getOperand(4))
22322 .
add(
MI.getOperand(5))
22323 .
add(
MI.getOperand(6))
22333 MI.eraseFromParent();
22339 unsigned CmpOpc, F2IOpc, I2FOpc, FSGNJOpc, FSGNJXOpc;
22341 switch (
MI.getOpcode()) {
22344 case RISCV::PseudoFROUND_H:
22345 CmpOpc = RISCV::FLT_H;
22346 F2IOpc = RISCV::FCVT_W_H;
22347 I2FOpc = RISCV::FCVT_H_W;
22348 FSGNJOpc = RISCV::FSGNJ_H;
22349 FSGNJXOpc = RISCV::FSGNJX_H;
22350 RC = &RISCV::FPR16RegClass;
22352 case RISCV::PseudoFROUND_H_INX:
22353 CmpOpc = RISCV::FLT_H_INX;
22354 F2IOpc = RISCV::FCVT_W_H_INX;
22355 I2FOpc = RISCV::FCVT_H_W_INX;
22356 FSGNJOpc = RISCV::FSGNJ_H_INX;
22357 FSGNJXOpc = RISCV::FSGNJX_H_INX;
22358 RC = &RISCV::GPRF16RegClass;
22360 case RISCV::PseudoFROUND_S:
22361 CmpOpc = RISCV::FLT_S;
22362 F2IOpc = RISCV::FCVT_W_S;
22363 I2FOpc = RISCV::FCVT_S_W;
22364 FSGNJOpc = RISCV::FSGNJ_S;
22365 FSGNJXOpc = RISCV::FSGNJX_S;
22366 RC = &RISCV::FPR32RegClass;
22368 case RISCV::PseudoFROUND_S_INX:
22369 CmpOpc = RISCV::FLT_S_INX;
22370 F2IOpc = RISCV::FCVT_W_S_INX;
22371 I2FOpc = RISCV::FCVT_S_W_INX;
22372 FSGNJOpc = RISCV::FSGNJ_S_INX;
22373 FSGNJXOpc = RISCV::FSGNJX_S_INX;
22374 RC = &RISCV::GPRF32RegClass;
22376 case RISCV::PseudoFROUND_D:
22378 CmpOpc = RISCV::FLT_D;
22379 F2IOpc = RISCV::FCVT_L_D;
22380 I2FOpc = RISCV::FCVT_D_L;
22381 FSGNJOpc = RISCV::FSGNJ_D;
22382 FSGNJXOpc = RISCV::FSGNJX_D;
22383 RC = &RISCV::FPR64RegClass;
22385 case RISCV::PseudoFROUND_D_INX:
22387 CmpOpc = RISCV::FLT_D_INX;
22388 F2IOpc = RISCV::FCVT_L_D_INX;
22389 I2FOpc = RISCV::FCVT_D_L_INX;
22390 FSGNJOpc = RISCV::FSGNJ_D_INX;
22391 FSGNJXOpc = RISCV::FSGNJX_D_INX;
22392 RC = &RISCV::GPRRegClass;
22404 F->insert(
I, CvtMBB);
22405 F->insert(
I, DoneMBB);
22413 MBB->addSuccessor(CvtMBB);
22414 MBB->addSuccessor(DoneMBB);
22416 Register DstReg =
MI.getOperand(0).getReg();
22417 Register SrcReg =
MI.getOperand(1).getReg();
22418 Register MaxReg =
MI.getOperand(2).getReg();
22419 int64_t FRM =
MI.getOperand(3).getImm();
22424 Register FabsReg =
MRI.createVirtualRegister(RC);
22428 Register CmpReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22443 Register F2IReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22465 MI.eraseFromParent();
22472 switch (
MI.getOpcode()) {
22475 case RISCV::ReadCounterWide:
22476 assert(!Subtarget.is64Bit() &&
22477 "ReadCounterWide is only to be used on riscv32");
22479 case RISCV::Select_GPR_Using_CC_GPR:
22480 case RISCV::Select_GPR_Using_CC_SImm5_CV:
22481 case RISCV::Select_GPRNoX0_Using_CC_SImm5NonZero_QC:
22482 case RISCV::Select_GPRNoX0_Using_CC_UImm5NonZero_QC:
22483 case RISCV::Select_GPRNoX0_Using_CC_SImm16NonZero_QC:
22484 case RISCV::Select_GPRNoX0_Using_CC_UImm16NonZero_QC:
22485 case RISCV::Select_GPR_Using_CC_UImmLog2XLen_NDS:
22486 case RISCV::Select_GPR_Using_CC_UImm7_NDS:
22487 case RISCV::Select_FPR16_Using_CC_GPR:
22488 case RISCV::Select_FPR16INX_Using_CC_GPR:
22489 case RISCV::Select_FPR32_Using_CC_GPR:
22490 case RISCV::Select_FPR32INX_Using_CC_GPR:
22491 case RISCV::Select_FPR64_Using_CC_GPR:
22492 case RISCV::Select_FPR64INX_Using_CC_GPR:
22493 case RISCV::Select_FPR64IN32X_Using_CC_GPR:
22495 case RISCV::BuildPairF64Pseudo:
22497 case RISCV::SplitF64Pseudo:
22499 case RISCV::PseudoQuietFLE_H:
22501 case RISCV::PseudoQuietFLE_H_INX:
22502 return emitQuietFCMP(
MI, BB, RISCV::FLE_H_INX, RISCV::FEQ_H_INX, Subtarget);
22503 case RISCV::PseudoQuietFLT_H:
22505 case RISCV::PseudoQuietFLT_H_INX:
22506 return emitQuietFCMP(
MI, BB, RISCV::FLT_H_INX, RISCV::FEQ_H_INX, Subtarget);
22507 case RISCV::PseudoQuietFLE_S:
22509 case RISCV::PseudoQuietFLE_S_INX:
22510 return emitQuietFCMP(
MI, BB, RISCV::FLE_S_INX, RISCV::FEQ_S_INX, Subtarget);
22511 case RISCV::PseudoQuietFLT_S:
22513 case RISCV::PseudoQuietFLT_S_INX:
22514 return emitQuietFCMP(
MI, BB, RISCV::FLT_S_INX, RISCV::FEQ_S_INX, Subtarget);
22515 case RISCV::PseudoQuietFLE_D:
22517 case RISCV::PseudoQuietFLE_D_INX:
22518 return emitQuietFCMP(
MI, BB, RISCV::FLE_D_INX, RISCV::FEQ_D_INX, Subtarget);
22519 case RISCV::PseudoQuietFLE_D_IN32X:
22522 case RISCV::PseudoQuietFLT_D:
22524 case RISCV::PseudoQuietFLT_D_INX:
22525 return emitQuietFCMP(
MI, BB, RISCV::FLT_D_INX, RISCV::FEQ_D_INX, Subtarget);
22526 case RISCV::PseudoQuietFLT_D_IN32X:
22530 case RISCV::PseudoVFROUND_NOEXCEPT_V_M1_MASK:
22532 case RISCV::PseudoVFROUND_NOEXCEPT_V_M2_MASK:
22534 case RISCV::PseudoVFROUND_NOEXCEPT_V_M4_MASK:
22536 case RISCV::PseudoVFROUND_NOEXCEPT_V_M8_MASK:
22538 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF2_MASK:
22540 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF4_MASK:
22542 case RISCV::PseudoFROUND_H:
22543 case RISCV::PseudoFROUND_H_INX:
22544 case RISCV::PseudoFROUND_S:
22545 case RISCV::PseudoFROUND_S_INX:
22546 case RISCV::PseudoFROUND_D:
22547 case RISCV::PseudoFROUND_D_INX:
22548 case RISCV::PseudoFROUND_D_IN32X:
22550 case RISCV::PROBED_STACKALLOC_DYN:
22552 case TargetOpcode::STATEPOINT:
22558 MI.addOperand(*
MI.getMF(),
22564 case TargetOpcode::STACKMAP:
22565 case TargetOpcode::PATCHPOINT:
22566 if (!Subtarget.is64Bit())
22568 "supported on 64-bit targets");
22578 if (
auto *FRMDef =
MI.findRegisterDefOperand(RISCV::FRM,
nullptr)) {
22579 FRMDef->setIsDead(
false);
22583 int Idx = RISCV::getNamedOperandIdx(
MI.getOpcode(), RISCV::OpName::frm);
22593 if (
MI.readsRegister(RISCV::FRM,
nullptr))
22599void RISCVTargetLowering::analyzeInputArgs(
22603 for (
const auto &[Idx, In] :
enumerate(Ins)) {
22609 LLVM_DEBUG(
dbgs() <<
"InputArg #" << Idx <<
" has unhandled type "
22616void RISCVTargetLowering::analyzeOutputArgs(
22620 for (
const auto &[Idx, Out] :
enumerate(Outs)) {
22621 MVT ArgVT = Out.VT;
22622 ISD::ArgFlagsTy ArgFlags = Out.Flags;
22626 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << Idx <<
" has unhandled type "
22643 return DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, Val);
22677 if (In.isOrigArg()) {
22682 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
22683 (
BitWidth < 32 && In.Flags.isZExt())) {
22704 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, LocVT, Val);
22705 if (LocVT == MVT::i64 && VA.
getValVT() == MVT::f32)
22706 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Val);
22718 Val = DAG.
getNode(ISD::BITCAST,
DL, LocVT, Val);
22754 ExtType,
DL, LocVT, Chain, FIN,
22771 Register LoVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
22784 Register HiVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
22788 return DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64,
Lo,
Hi);
22799 switch (CallConv) {
22808#define CC_VLS_CASE(ABI_VLEN) case CallingConv::RISCV_VLSCall_##ABI_VLEN:
22824 if (Subtarget.hasStdExtE())
22826 if (!Subtarget.hasStdExtFOrZfinx() || !Subtarget.hasStdExtDOrZdinx())
22828 "(Zdinx/D) instruction set extensions");
22832 if (Func.hasFnAttribute(
"interrupt")) {
22833 if (!Func.arg_empty())
22835 "Functions with the interrupt attribute cannot have arguments!");
22846 "SiFive-CLIC-preemptible",
22847 "SiFive-CLIC-stack-swap",
22848 "SiFive-CLIC-preemptible-stack-swap",
22852 "Function interrupt attribute argument not supported!");
22854 if (Kind.starts_with(
"qci-") && !Subtarget.hasVendorXqciint())
22856 "'qci-*' interrupt kinds require Xqciint extension");
22858 if (Kind.starts_with(
"SiFive-CLIC-") && !Subtarget.hasVendorXSfmclic())
22860 "'SiFive-CLIC-*' interrupt kinds require XSfmclic extension");
22862 if (Kind ==
"rnmi" && !Subtarget.hasStdExtSmrnmi())
22865 if (Kind.starts_with(
"SiFive-CLIC-preemptible") && TFI->
hasFP(MF))
22867 "have a frame pointer");
22871 MVT XLenVT = Subtarget.getXLenVT();
22872 unsigned XLenInBytes = Subtarget.getXLen() / 8;
22874 std::vector<SDValue> OutChains;
22883 analyzeInputArgs(MF, CCInfo, Ins,
false,
22887 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
22908 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
22909 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
22911 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
22913 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
22942 int VarArgsSaveSize = XLenInBytes * (ArgRegs.
size() - Idx);
22947 if (VarArgsSaveSize == 0) {
22951 int VaArgOffset = -VarArgsSaveSize;
22959 XLenInBytes, VaArgOffset -
static_cast<int>(XLenInBytes),
true);
22960 VarArgsSaveSize += XLenInBytes;
22967 for (
unsigned I = Idx;
I < ArgRegs.
size(); ++
I) {
22968 const Register Reg = RegInfo.createVirtualRegister(RC);
22969 RegInfo.addLiveIn(ArgRegs[
I], Reg);
22972 Chain,
DL, ArgValue, FIN,
22974 OutChains.push_back(Store);
22988 if (!OutChains.empty()) {
22989 OutChains.push_back(Chain);
22999bool RISCVTargetLowering::isEligibleForTailCallOptimization(
23003 auto CalleeCC = CLI.CallConv;
23004 auto &Outs = CLI.Outs;
23006 auto CallerCC = Caller.getCallingConv();
23013 if (Caller.hasFnAttribute(
"interrupt"))
23028 for (
auto &VA : ArgLocs)
23034 auto IsCallerStructRet = Caller.hasStructRetAttr();
23035 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
23036 if (IsCallerStructRet || IsCalleeStructRet)
23041 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
23042 if (CalleeCC != CallerCC) {
23043 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
23044 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
23051 for (
auto &Arg : Outs)
23052 if (Arg.Flags.isByVal())
23078 MVT XLenVT = Subtarget.getXLenVT();
23093 if (Subtarget.hasStdExtE())
23097 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
23103 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
23109 "call site marked musttail");
23116 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
23118 if (!Flags.isByVal())
23122 unsigned Size = Flags.getByValSize();
23123 Align Alignment = Flags.getNonZeroByValAlign();
23130 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
23132 false,
nullptr, IsTailCall,
23144 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
23147 SDValue ArgValue = OutVals[OutIdx];
23155 RISCVISD::SplitF64,
DL, DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
23167 if (!StackPtr.getNode())
23179 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
23197 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
23198 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
23204 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
23205 SDValue PartValue = OutVals[OutIdx + 1];
23206 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
23220 DAG.
getStore(Chain,
DL, ArgValue, SpillSlot,
23222 for (
const auto &Part : Parts) {
23223 SDValue PartValue = Part.first;
23224 SDValue PartOffset = Part.second;
23231 ArgValue = SpillSlot;
23237 if (Flags.isByVal())
23238 ArgValue = ByValArgs[j++];
23245 if (
Options.EmitCallSiteInfo)
23249 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
23250 "for passing parameters");
23253 if (!StackPtr.getNode())
23267 if (!MemOpChains.
empty())
23273 for (
auto &Reg : RegsToPass) {
23274 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
23281 validateCCReservedRegs(RegsToPass, MF);
23285 "Return address register required, but has been reserved."});
23290 bool CalleeIsLargeExternalSymbol =
false;
23296 CalleeIsLargeExternalSymbol =
true;
23307 Ops.push_back(Chain);
23308 Ops.push_back(Callee);
23312 for (
auto &Reg : RegsToPass)
23313 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
23317 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
23318 assert(Mask &&
"Missing call preserved mask for calling convention");
23323 Ops.push_back(Glue);
23326 "Unexpected CFI type for a direct call");
23334 bool NeedSWGuarded =
false;
23336 Subtarget.hasStdExtZicfilp() &&
23338 NeedSWGuarded =
true;
23343 NeedSWGuarded ? RISCVISD::SW_GUARDED_TAIL : RISCVISD::TAIL;
23352 unsigned CallOpc = NeedSWGuarded ? RISCVISD::SW_GUARDED_CALL : RISCVISD::CALL;
23368 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_RISCV);
23371 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
23372 auto &VA = RVLocs[i];
23380 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
23381 assert(VA.needsCustom());
23386 RetValue = DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64, RetValue,
23400 const Type *RetTy)
const {
23402 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
23404 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
23405 MVT VT = Outs[i].VT;
23408 true, Outs[i].OrigTy))
23440 for (
unsigned i = 0, e = RVLocs.size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
23441 SDValue Val = OutVals[OutIdx];
23450 DAG.
getVTList(MVT::i32, MVT::i32), Val);
23454 Register RegHi = RVLocs[++i].getLocReg();
23460 "Return value register required, but has been reserved."});
23476 "Return value register required, but has been reserved."});
23495 unsigned RetOpc = RISCVISD::RET_GLUE;
23498 if (Func.hasFnAttribute(
"interrupt")) {
23499 if (!Func.getReturnType()->isVoidTy())
23501 "Functions with the interrupt attribute must have void return type!");
23507 if (Kind ==
"supervisor")
23508 RetOpc = RISCVISD::SRET_GLUE;
23509 else if (Kind ==
"rnmi") {
23510 assert(STI.hasFeature(RISCV::FeatureStdExtSmrnmi) &&
23511 "Need Smrnmi extension for rnmi");
23512 RetOpc = RISCVISD::MNRET_GLUE;
23513 }
else if (Kind ==
"qci-nest" || Kind ==
"qci-nonest") {
23514 assert(STI.hasFeature(RISCV::FeatureVendorXqciint) &&
23515 "Need Xqciint for qci-(no)nest");
23516 RetOpc = RISCVISD::QC_C_MILEAVERET_GLUE;
23518 RetOpc = RISCVISD::MRET_GLUE;
23521 return DAG.
getNode(RetOpc,
DL, MVT::Other, RetOps);
23524void RISCVTargetLowering::validateCCReservedRegs(
23525 const SmallVectorImpl<std::pair<llvm::Register, llvm::SDValue>> &Regs,
23534 F,
"Argument register required, but has been reserved."});
23540 if (
N->getNumValues() != 1)
23542 if (!
N->hasNUsesOfValue(1, 0))
23545 SDNode *Copy = *
N->user_begin();
23547 if (Copy->getOpcode() == ISD::BITCAST) {
23559 if (Copy->getOperand(Copy->getNumOperands() - 1).getValueType() == MVT::Glue)
23563 bool HasRet =
false;
23565 if (
Node->getOpcode() != RISCVISD::RET_GLUE)
23572 Chain = Copy->getOperand(0);
23584 if (Constraint.
size() == 1) {
23585 switch (Constraint[0]) {
23602 if (Constraint ==
"vr" || Constraint ==
"vd" || Constraint ==
"vm")
23604 if (Constraint ==
"cr" || Constraint ==
"cR" || Constraint ==
"cf")
23610std::pair<unsigned, const TargetRegisterClass *>
23616 if (Constraint.
size() == 1) {
23617 switch (Constraint[0]) {
23622 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
23623 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
23624 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
23625 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
23626 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23627 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23628 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
23630 if (VT == MVT::f16) {
23631 if (Subtarget.hasStdExtZfhmin())
23632 return std::make_pair(0U, &RISCV::FPR16RegClass);
23633 if (Subtarget.hasStdExtZhinxmin())
23634 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
23635 }
else if (VT == MVT::f32) {
23636 if (Subtarget.hasStdExtF())
23637 return std::make_pair(0U, &RISCV::FPR32RegClass);
23638 if (Subtarget.hasStdExtZfinx())
23639 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
23640 }
else if (VT == MVT::f64) {
23641 if (Subtarget.hasStdExtD())
23642 return std::make_pair(0U, &RISCV::FPR64RegClass);
23643 if (Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23644 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23645 if (Subtarget.hasStdExtZdinx() && Subtarget.is64Bit())
23646 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
23650 if (((VT == MVT::i64 || VT == MVT::f64) && !Subtarget.is64Bit()) ||
23651 (VT == MVT::i128 && Subtarget.is64Bit()))
23652 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23657 }
else if (Constraint ==
"vr") {
23658 for (
const auto *RC :
23659 {&RISCV::VRRegClass, &RISCV::VRM2RegClass, &RISCV::VRM4RegClass,
23660 &RISCV::VRM8RegClass, &RISCV::VRN2M1RegClass, &RISCV::VRN3M1RegClass,
23661 &RISCV::VRN4M1RegClass, &RISCV::VRN5M1RegClass,
23662 &RISCV::VRN6M1RegClass, &RISCV::VRN7M1RegClass,
23663 &RISCV::VRN8M1RegClass, &RISCV::VRN2M2RegClass,
23664 &RISCV::VRN3M2RegClass, &RISCV::VRN4M2RegClass,
23665 &RISCV::VRN2M4RegClass}) {
23667 return std::make_pair(0U, RC);
23671 if (
TRI->isTypeLegalForClass(*RC, ContainerVT))
23672 return std::make_pair(0U, RC);
23675 }
else if (Constraint ==
"vd") {
23676 for (
const auto *RC :
23677 {&RISCV::VRNoV0RegClass, &RISCV::VRM2NoV0RegClass,
23678 &RISCV::VRM4NoV0RegClass, &RISCV::VRM8NoV0RegClass,
23679 &RISCV::VRN2M1NoV0RegClass, &RISCV::VRN3M1NoV0RegClass,
23680 &RISCV::VRN4M1NoV0RegClass, &RISCV::VRN5M1NoV0RegClass,
23681 &RISCV::VRN6M1NoV0RegClass, &RISCV::VRN7M1NoV0RegClass,
23682 &RISCV::VRN8M1NoV0RegClass, &RISCV::VRN2M2NoV0RegClass,
23683 &RISCV::VRN3M2NoV0RegClass, &RISCV::VRN4M2NoV0RegClass,
23684 &RISCV::VRN2M4NoV0RegClass}) {
23686 return std::make_pair(0U, RC);
23690 if (
TRI->isTypeLegalForClass(*RC, ContainerVT))
23691 return std::make_pair(0U, RC);
23694 }
else if (Constraint ==
"vm") {
23695 if (
TRI->isTypeLegalForClass(RISCV::VMV0RegClass, VT.
SimpleTy))
23696 return std::make_pair(0U, &RISCV::VMV0RegClass);
23702 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, ContainerVT))
23703 return std::make_pair(0U, &RISCV::VMV0RegClass);
23705 }
else if (Constraint ==
"cr") {
23706 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
23707 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
23708 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
23709 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
23710 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23711 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23713 return std::make_pair(0U, &RISCV::GPRCRegClass);
23714 }
else if (Constraint ==
"cR") {
23715 if (((VT == MVT::i64 || VT == MVT::f64) && !Subtarget.is64Bit()) ||
23716 (VT == MVT::i128 && Subtarget.is64Bit()))
23717 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23718 }
else if (Constraint ==
"cf") {
23719 if (VT == MVT::f16) {
23720 if (Subtarget.hasStdExtZfhmin())
23721 return std::make_pair(0U, &RISCV::FPR16CRegClass);
23722 if (Subtarget.hasStdExtZhinxmin())
23723 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
23724 }
else if (VT == MVT::f32) {
23725 if (Subtarget.hasStdExtF())
23726 return std::make_pair(0U, &RISCV::FPR32CRegClass);
23727 if (Subtarget.hasStdExtZfinx())
23728 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
23729 }
else if (VT == MVT::f64) {
23730 if (Subtarget.hasStdExtD())
23731 return std::make_pair(0U, &RISCV::FPR64CRegClass);
23732 if (Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23733 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23734 if (Subtarget.hasStdExtZdinx() && Subtarget.is64Bit())
23735 return std::make_pair(0U, &RISCV::GPRCRegClass);
23744 .
Case(
"{zero}", RISCV::X0)
23745 .
Case(
"{ra}", RISCV::X1)
23746 .
Case(
"{sp}", RISCV::X2)
23747 .
Case(
"{gp}", RISCV::X3)
23748 .
Case(
"{tp}", RISCV::X4)
23749 .
Case(
"{t0}", RISCV::X5)
23750 .
Case(
"{t1}", RISCV::X6)
23751 .
Case(
"{t2}", RISCV::X7)
23752 .
Cases(
"{s0}",
"{fp}", RISCV::X8)
23753 .
Case(
"{s1}", RISCV::X9)
23754 .
Case(
"{a0}", RISCV::X10)
23755 .
Case(
"{a1}", RISCV::X11)
23756 .
Case(
"{a2}", RISCV::X12)
23757 .
Case(
"{a3}", RISCV::X13)
23758 .
Case(
"{a4}", RISCV::X14)
23759 .
Case(
"{a5}", RISCV::X15)
23760 .
Case(
"{a6}", RISCV::X16)
23761 .
Case(
"{a7}", RISCV::X17)
23762 .
Case(
"{s2}", RISCV::X18)
23763 .
Case(
"{s3}", RISCV::X19)
23764 .
Case(
"{s4}", RISCV::X20)
23765 .
Case(
"{s5}", RISCV::X21)
23766 .
Case(
"{s6}", RISCV::X22)
23767 .
Case(
"{s7}", RISCV::X23)
23768 .
Case(
"{s8}", RISCV::X24)
23769 .
Case(
"{s9}", RISCV::X25)
23770 .
Case(
"{s10}", RISCV::X26)
23771 .
Case(
"{s11}", RISCV::X27)
23772 .
Case(
"{t3}", RISCV::X28)
23773 .
Case(
"{t4}", RISCV::X29)
23774 .
Case(
"{t5}", RISCV::X30)
23775 .
Case(
"{t6}", RISCV::X31)
23777 if (XRegFromAlias != RISCV::NoRegister)
23778 return std::make_pair(XRegFromAlias, &RISCV::GPRRegClass);
23787 if (Subtarget.hasStdExtF()) {
23789 .
Cases(
"{f0}",
"{ft0}", RISCV::F0_F)
23790 .
Cases(
"{f1}",
"{ft1}", RISCV::F1_F)
23791 .
Cases(
"{f2}",
"{ft2}", RISCV::F2_F)
23792 .
Cases(
"{f3}",
"{ft3}", RISCV::F3_F)
23793 .
Cases(
"{f4}",
"{ft4}", RISCV::F4_F)
23794 .
Cases(
"{f5}",
"{ft5}", RISCV::F5_F)
23795 .
Cases(
"{f6}",
"{ft6}", RISCV::F6_F)
23796 .
Cases(
"{f7}",
"{ft7}", RISCV::F7_F)
23797 .
Cases(
"{f8}",
"{fs0}", RISCV::F8_F)
23798 .
Cases(
"{f9}",
"{fs1}", RISCV::F9_F)
23799 .
Cases(
"{f10}",
"{fa0}", RISCV::F10_F)
23800 .
Cases(
"{f11}",
"{fa1}", RISCV::F11_F)
23801 .
Cases(
"{f12}",
"{fa2}", RISCV::F12_F)
23802 .
Cases(
"{f13}",
"{fa3}", RISCV::F13_F)
23803 .
Cases(
"{f14}",
"{fa4}", RISCV::F14_F)
23804 .
Cases(
"{f15}",
"{fa5}", RISCV::F15_F)
23805 .
Cases(
"{f16}",
"{fa6}", RISCV::F16_F)
23806 .
Cases(
"{f17}",
"{fa7}", RISCV::F17_F)
23807 .
Cases(
"{f18}",
"{fs2}", RISCV::F18_F)
23808 .
Cases(
"{f19}",
"{fs3}", RISCV::F19_F)
23809 .
Cases(
"{f20}",
"{fs4}", RISCV::F20_F)
23810 .
Cases(
"{f21}",
"{fs5}", RISCV::F21_F)
23811 .
Cases(
"{f22}",
"{fs6}", RISCV::F22_F)
23812 .
Cases(
"{f23}",
"{fs7}", RISCV::F23_F)
23813 .
Cases(
"{f24}",
"{fs8}", RISCV::F24_F)
23814 .
Cases(
"{f25}",
"{fs9}", RISCV::F25_F)
23815 .
Cases(
"{f26}",
"{fs10}", RISCV::F26_F)
23816 .
Cases(
"{f27}",
"{fs11}", RISCV::F27_F)
23817 .
Cases(
"{f28}",
"{ft8}", RISCV::F28_F)
23818 .
Cases(
"{f29}",
"{ft9}", RISCV::F29_F)
23819 .
Cases(
"{f30}",
"{ft10}", RISCV::F30_F)
23820 .
Cases(
"{f31}",
"{ft11}", RISCV::F31_F)
23822 if (FReg != RISCV::NoRegister) {
23823 assert(RISCV::F0_F <= FReg && FReg <= RISCV::F31_F &&
"Unknown fp-reg");
23824 if (Subtarget.hasStdExtD() && (VT == MVT::f64 || VT == MVT::Other)) {
23825 unsigned RegNo = FReg - RISCV::F0_F;
23826 unsigned DReg = RISCV::F0_D + RegNo;
23827 return std::make_pair(DReg, &RISCV::FPR64RegClass);
23829 if (VT == MVT::f32 || VT == MVT::Other)
23830 return std::make_pair(FReg, &RISCV::FPR32RegClass);
23831 if (Subtarget.hasStdExtZfhmin() && VT == MVT::f16) {
23832 unsigned RegNo = FReg - RISCV::F0_F;
23833 unsigned HReg = RISCV::F0_H + RegNo;
23834 return std::make_pair(HReg, &RISCV::FPR16RegClass);
23839 if (Subtarget.hasVInstructions()) {
23841 .
Case(
"{v0}", RISCV::V0)
23842 .
Case(
"{v1}", RISCV::V1)
23843 .
Case(
"{v2}", RISCV::V2)
23844 .
Case(
"{v3}", RISCV::V3)
23845 .
Case(
"{v4}", RISCV::V4)
23846 .
Case(
"{v5}", RISCV::V5)
23847 .
Case(
"{v6}", RISCV::V6)
23848 .
Case(
"{v7}", RISCV::V7)
23849 .
Case(
"{v8}", RISCV::V8)
23850 .
Case(
"{v9}", RISCV::V9)
23851 .
Case(
"{v10}", RISCV::V10)
23852 .
Case(
"{v11}", RISCV::V11)
23853 .
Case(
"{v12}", RISCV::V12)
23854 .
Case(
"{v13}", RISCV::V13)
23855 .
Case(
"{v14}", RISCV::V14)
23856 .
Case(
"{v15}", RISCV::V15)
23857 .
Case(
"{v16}", RISCV::V16)
23858 .
Case(
"{v17}", RISCV::V17)
23859 .
Case(
"{v18}", RISCV::V18)
23860 .
Case(
"{v19}", RISCV::V19)
23861 .
Case(
"{v20}", RISCV::V20)
23862 .
Case(
"{v21}", RISCV::V21)
23863 .
Case(
"{v22}", RISCV::V22)
23864 .
Case(
"{v23}", RISCV::V23)
23865 .
Case(
"{v24}", RISCV::V24)
23866 .
Case(
"{v25}", RISCV::V25)
23867 .
Case(
"{v26}", RISCV::V26)
23868 .
Case(
"{v27}", RISCV::V27)
23869 .
Case(
"{v28}", RISCV::V28)
23870 .
Case(
"{v29}", RISCV::V29)
23871 .
Case(
"{v30}", RISCV::V30)
23872 .
Case(
"{v31}", RISCV::V31)
23874 if (VReg != RISCV::NoRegister) {
23875 if (
TRI->isTypeLegalForClass(RISCV::VMRegClass, VT.
SimpleTy))
23876 return std::make_pair(VReg, &RISCV::VMRegClass);
23877 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, VT.
SimpleTy))
23878 return std::make_pair(VReg, &RISCV::VRRegClass);
23879 for (
const auto *RC :
23880 {&RISCV::VRM2RegClass, &RISCV::VRM4RegClass, &RISCV::VRM8RegClass}) {
23881 if (
TRI->isTypeLegalForClass(*RC, VT.
SimpleTy)) {
23882 VReg =
TRI->getMatchingSuperReg(VReg, RISCV::sub_vrm1_0, RC);
23883 return std::make_pair(VReg, RC);
23889 std::pair<Register, const TargetRegisterClass *> Res =
23895 if (Res.second == &RISCV::GPRF16RegClass ||
23896 Res.second == &RISCV::GPRF32RegClass ||
23897 Res.second == &RISCV::GPRPairRegClass)
23898 return std::make_pair(Res.first, &RISCV::GPRRegClass);
23906 if (ConstraintCode.
size() == 1) {
23907 switch (ConstraintCode[0]) {
23922 if (Constraint.
size() == 1) {
23923 switch (Constraint[0]) {
23930 Subtarget.getXLenVT()));
23961 if (Subtarget.hasStdExtZtso()) {
23963 return Builder.CreateFence(Ord);
23968 return Builder.CreateFence(Ord);
23977 if (Subtarget.hasStdExtZtso()) {
23979 return Builder.CreateFence(Ord);
23985 if (Subtarget.enableTrailingSeqCstFence() &&
isa<StoreInst>(Inst) &&
24004 if (Subtarget.hasForcedAtomics())
24009 if (Subtarget.hasStdExtZacas() &&
24010 (
Size >= 32 || Subtarget.hasStdExtZabha()))
24016 if (
Size < 32 && !Subtarget.hasStdExtZabha())
24028 return Intrinsic::riscv_masked_atomicrmw_xchg;
24030 return Intrinsic::riscv_masked_atomicrmw_add;
24032 return Intrinsic::riscv_masked_atomicrmw_sub;
24034 return Intrinsic::riscv_masked_atomicrmw_nand;
24036 return Intrinsic::riscv_masked_atomicrmw_max;
24038 return Intrinsic::riscv_masked_atomicrmw_min;
24040 return Intrinsic::riscv_masked_atomicrmw_umax;
24042 return Intrinsic::riscv_masked_atomicrmw_umin;
24058 Builder.CreateNot(Mask,
"Inv_Mask"),
24065 unsigned XLen = Subtarget.getXLen();
24068 Type *Tys[] = {Builder.getIntNTy(XLen), AlignedAddr->
getType()};
24074 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
24075 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
24076 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
24089 unsigned ValWidth =
24092 Builder.CreateSub(Builder.getIntN(XLen, XLen - ValWidth), ShiftAmt);
24093 Result = Builder.CreateCall(LrwOpScwLoop,
24094 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
24097 Builder.CreateCall(LrwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
24101 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
24109 if (Subtarget.hasForcedAtomics())
24113 if (!(Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas()) &&
24122 unsigned XLen = Subtarget.getXLen();
24123 Value *Ordering = Builder.getIntN(XLen,
static_cast<uint64_t>(Ord));
24124 Intrinsic::ID CmpXchgIntrID = Intrinsic::riscv_masked_cmpxchg;
24126 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
24127 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
24128 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
24130 Type *Tys[] = {Builder.getIntNTy(XLen), AlignedAddr->
getType()};
24131 Value *Result = Builder.CreateIntrinsic(
24132 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, Ordering});
24134 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
24139 EVT DataVT)
const {
24155 return Subtarget.hasStdExtZfhmin();
24157 return Subtarget.hasStdExtF();
24159 return Subtarget.hasStdExtD();
24189 assert(Subtarget.getRealMinVLen() >= 64 &&
"zve32* unsupported");
24191 "RVVBitsPerBlock changed, audit needed");
24200 if (!Subtarget.hasVendorXTHeadMemIdx())
24206 Base =
Op->getOperand(0);
24208 int64_t RHSC = RHS->getSExtValue();
24214 bool isLegalIndexedOffset =
false;
24215 for (
unsigned i = 0; i < 4; i++)
24216 if (
isInt<5>(RHSC >> i) && ((RHSC % (1LL << i)) == 0)) {
24217 isLegalIndexedOffset =
true;
24221 if (!isLegalIndexedOffset)
24238 VT = LD->getMemoryVT();
24239 Ptr = LD->getBasePtr();
24241 VT = ST->getMemoryVT();
24242 Ptr = ST->getBasePtr();
24258 if (Subtarget.hasVendorXCVmem() && !Subtarget.is64Bit()) {
24263 Base = LS->getBasePtr();
24267 if (
Base ==
Op->getOperand(0))
24269 else if (
Base ==
Op->getOperand(1))
24281 VT = LD->getMemoryVT();
24282 Ptr = LD->getBasePtr();
24284 VT = ST->getMemoryVT();
24285 Ptr = ST->getBasePtr();
24309 return VT.
isVector() ? Subtarget.hasVInstructionsF16()
24310 : Subtarget.hasStdExtZfhOrZhinx();
24312 return Subtarget.hasStdExtFOrZfinx();
24314 return Subtarget.hasStdExtDOrZdinx();
24328 const Constant *PersonalityFn)
const {
24333 const Constant *PersonalityFn)
const {
24340 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
24341 Type.getSizeInBits() < Subtarget.getXLen()))
24348 bool IsSigned)
const {
24349 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
24363 const bool HasZmmul = Subtarget.hasStdExtZmmul();
24368 const APInt &Imm = ConstNode->getAPIntValue();
24371 if (Subtarget.hasVendorXqciac() && Imm.isSignedIntN(12))
24375 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
24376 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
24380 if (Subtarget.hasShlAdd(3) && !Imm.isSignedIntN(12) &&
24381 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
24382 (Imm - 8).isPowerOf2()))
24387 if (!Imm.isSignedIntN(12) && Imm.countr_zero() < 12 &&
24388 ConstNode->hasOneUse()) {
24389 APInt ImmS = Imm.ashr(Imm.countr_zero());
24390 if ((ImmS + 1).isPowerOf2() || (ImmS - 1).isPowerOf2() ||
24391 (1 - ImmS).isPowerOf2())
24414 if (C1.
isSignedIntN(12) && !(C1 * C2).isSignedIntN(12))
24423 unsigned *
Fast)
const {
24426 *
Fast = Subtarget.enableUnalignedScalarMem();
24427 return Subtarget.enableUnalignedScalarMem();
24443 *
Fast = Subtarget.enableUnalignedVectorMem();
24444 return Subtarget.enableUnalignedVectorMem();
24449 const AttributeList &FuncAttributes)
const {
24450 if (!Subtarget.hasVInstructions())
24453 if (FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat))
24465 const unsigned MinVLenInBytes =
24466 std::min(Subtarget.getRealMinVLen() / 8, 1024U);
24468 if (
Op.size() < MinVLenInBytes)
24483 MVT PreferredVT = (
Op.isMemset() && !
Op.isZeroMemset()) ? MVT::i8 : ELenVT;
24487 if (PreferredVT != MVT::i8 && !Subtarget.enableUnalignedVectorMem()) {
24489 if (
Op.isFixedDstAlign())
24490 RequiredAlign = std::min(RequiredAlign,
Op.getDstAlign());
24492 RequiredAlign = std::min(RequiredAlign,
Op.getSrcAlign());
24500 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
24501 bool IsABIRegCopy = CC.has_value();
24504 MVT PairVT = Subtarget.is64Bit() ? MVT::i128 : MVT::i64;
24505 if ((ValueVT == PairVT ||
24506 (!Subtarget.is64Bit() && Subtarget.hasStdExtZdinx() &&
24507 ValueVT == MVT::f64)) &&
24508 NumParts == 1 && PartVT == MVT::Untyped) {
24510 MVT XLenVT = Subtarget.getXLenVT();
24511 if (ValueVT == MVT::f64)
24516 Parts[0] = DAG.
getNode(RISCVISD::BuildGPRPair,
DL, PartVT,
Lo,
Hi);
24520 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
24521 PartVT == MVT::f32) {
24524 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::i16, Val);
24528 Val = DAG.
getNode(ISD::BITCAST,
DL, PartVT, Val);
24536 [[maybe_unused]]
unsigned ValLMUL =
24540 [[maybe_unused]]
unsigned PartLMUL =
24543 assert(ValNF == PartNF && ValLMUL == PartLMUL &&
24544 "RISC-V vector tuple type only accepts same register class type "
24565 if (PartVTBitSize % ValueVTBitSize == 0) {
24566 assert(PartVTBitSize >= ValueVTBitSize);
24573 if (ValueEltVT != PartEltVT) {
24574 if (PartVTBitSize > ValueVTBitSize) {
24576 assert(
Count != 0 &&
"The number of element should not be zero.");
24577 EVT SameEltTypeVT =
24581 Val = DAG.
getNode(ISD::BITCAST,
DL, PartVT, Val);
24595 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
24596 bool IsABIRegCopy = CC.has_value();
24598 MVT PairVT = Subtarget.is64Bit() ? MVT::i128 : MVT::i64;
24599 if ((ValueVT == PairVT ||
24600 (!Subtarget.is64Bit() && Subtarget.hasStdExtZdinx() &&
24601 ValueVT == MVT::f64)) &&
24602 NumParts == 1 && PartVT == MVT::Untyped) {
24604 MVT XLenVT = Subtarget.getXLenVT();
24613 if (ValueVT == MVT::f64)
24618 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
24619 PartVT == MVT::f32) {
24623 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::i32, Val);
24625 Val = DAG.
getNode(ISD::BITCAST,
DL, ValueVT, Val);
24641 if (PartVTBitSize % ValueVTBitSize == 0) {
24642 assert(PartVTBitSize >= ValueVTBitSize);
24643 EVT SameEltTypeVT = ValueVT;
24650 if (ValueEltVT != PartEltVT) {
24652 assert(
Count != 0 &&
"The number of element should not be zero.");
24655 Val = DAG.
getNode(ISD::BITCAST,
DL, SameEltTypeVT, Val);
24671 bool OptSize = Attr.hasFnAttr(Attribute::MinSize);
24678 unsigned Opc =
N->getOpcode();
24687 M, Intrinsic::thread_pointer, IRB.
getPtrTy());
24695 if (Subtarget.isTargetFuchsia())
24701 if (Subtarget.isTargetAndroid())
24706 if (M->getStackProtectorGuard() ==
"tls") {
24708 int Offset = M->getStackProtectorGuardOffset();
24716 Align Alignment)
const {
24717 if (!Subtarget.hasVInstructions())
24721 if (DataType.isFixedLengthVector() && !Subtarget.useRVVForFixedLengthVectors())
24728 if (!Subtarget.enableUnalignedVectorMem() &&
24740 "Invalid call instruction for a KCFI check");
24742 MBBI->getOpcode()));
24745 Target.setIsRenamable(
false);
24753#define GET_REGISTER_MATCHER
24754#include "RISCVGenAsmMatcher.inc"
24765 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
24766 if (!ReservedRegs.
test(Reg) && !Subtarget.isRegisterReservedByUser(Reg))
24774 const MDNode *NontemporalInfo =
I.getMetadata(LLVMContext::MD_nontemporal);
24776 if (NontemporalInfo ==
nullptr)
24784 int NontemporalLevel = 5;
24785 const MDNode *RISCVNontemporalInfo =
24786 I.getMetadata(
"riscv-nontemporal-domain");
24787 if (RISCVNontemporalInfo !=
nullptr)
24794 assert((1 <= NontemporalLevel && NontemporalLevel <= 5) &&
24795 "RISC-V target doesn't support this non-temporal domain.");
24797 NontemporalLevel -= 2;
24799 if (NontemporalLevel & 0b1)
24801 if (NontemporalLevel & 0b10)
24814 return TargetFlags;
24824 return isTypeLegal(VT) && Subtarget.hasStdExtZvbb();
24827 return Subtarget.hasCPOPLike() &&
24838 if (Subtarget.hasStdExtZalasr()) {
24839 if (Subtarget.hasStdExtZtso()) {
24869 if (
Op == Instruction::Add ||
Op == Instruction::Sub ||
24870 Op == Instruction::And ||
Op == Instruction::Or ||
24871 Op == Instruction::Xor ||
Op == Instruction::InsertElement ||
24872 Op == Instruction::ShuffleVector ||
Op == Instruction::Load ||
24873 Op == Instruction::Freeze ||
Op == Instruction::Store)
24878 if (RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(
II->getIntrinsicID()))
24891 if (AI->getAllocatedType()->isScalableTy())
24899RISCVTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
24907 if (!Subtarget.hasShortForwardBranchOpt())
24909 EVT VT =
N->getValueType(0);
24910 if (!(VT == MVT::i32 || (VT == MVT::i64 && Subtarget.
is64Bit())))
24914 if (Divisor.
sgt(2048) || Divisor.
slt(-2048))
24919bool RISCVTargetLowering::shouldFoldSelectWithSingleBitTest(
24920 EVT VT,
const APInt &AndMask)
const {
24921 if (Subtarget.
hasCZEROLike() || Subtarget.hasVendorXTHeadCondMov())
24927 return Subtarget.getMinimumJumpTableEntries();
24934 if (Subtarget.hasStdExtZicfilp()) {
24941 return DAG.
getNode(RISCVISD::SW_GUARDED_BRIND, dl, MVT::Other, Chain, Addr);
24958std::pair<const TargetRegisterClass *, uint8_t>
24978#define GET_RISCVVIntrinsicsTable_IMPL
24979#include "RISCVGenSearchableTables.inc"
24994 Align StackAlign)
const {
24998 unsigned StackProbeSize =
25002 return StackProbeSize ? StackProbeSize : StackAlign.
value();
25019 EVT VT =
Op.getValueType();
25030 Chain = DAG.
getNode(RISCVISD::PROBED_ALLOCA, dl, MVT::Other, Chain, SP);
25040 Register TargetReg =
MI.getOperand(0).getReg();
25043 bool IsRV64 = Subtarget.is64Bit();
25044 Align StackAlign = Subtarget.getFrameLowering()->getStackAlign();
25051 MF.
insert(MBBInsertPoint, LoopTestMBB);
25053 MF.
insert(MBBInsertPoint, ExitMBB);
25069 TII->get(IsRV64 ? RISCV::SD : RISCV::SW))
25090 MBB->addSuccessor(LoopTestMBB);
25092 MI.eraseFromParent();
25094 return ExitMBB->
begin()->getParent();
25098 if (Subtarget.hasStdExtFOrZfinx()) {
25099 static const MCPhysReg RCRegs[] = {RISCV::FRM, RISCV::FFLAGS};
unsigned const MachineRegisterInfo * MRI
static MCRegister MatchRegisterName(StringRef Name)
static EVT getContainerForFixedLengthVector(SelectionDAG &DAG, EVT VT)
static SDValue performSHLCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
If the operand is a bitwise AND with a constant RHS, and the shift has a constant RHS and is the only...
static SDValue performORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const AArch64Subtarget *Subtarget, const AArch64TargetLowering &TLI)
static SDValue performANDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG)
static SDValue tryWidenMaskForShuffle(SDValue Op, SelectionDAG &DAG)
static SDValue performSETCCCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
static SDValue convertToScalableVector(SelectionDAG &DAG, EVT VT, SDValue V)
static SDValue convertFromScalableVector(SelectionDAG &DAG, EVT VT, SDValue V)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isConstant(const MachineInstr &MI)
AMDGPU Register Bank Select
static bool isZeroOrAllOnes(SDValue N, bool AllOnes)
static SDValue combineSelectAndUseCommutative(SDNode *N, bool AllOnes, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp, TargetLowering::DAGCombinerInfo &DCI, bool AllOnes=false)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static MCRegister MatchRegisterAltName(StringRef Name)
Maps from the set of all alternative registernames to a register number.
Function Alias Analysis Results
static SDValue getTargetNode(GlobalAddressSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, unsigned Flags)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static MachineBasicBlock * emitSelectPseudo(MachineInstr &MI, MachineBasicBlock *BB, unsigned Opcode)
static SDValue unpackFromRegLoc(const CSKYSubtarget &Subtarget, SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
static InstructionCost getCost(Instruction &Inst, TTI::TargetCostKind CostKind, TargetTransformInfo &TTI, TargetLibraryInfo &TLI)
const HexagonInstrInfo * TII
This file defines an InstructionCost class that is used when calculating the cost of an instruction,...
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define CC_VLS_CASE(ABIVlen)
static Align getPrefTypeAlign(EVT VT, SelectionDAG &DAG)
static std::optional< bool > matchSetCC(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue Val)
static SDValue customLegalizeToWOpWithSExt(SDNode *N, SelectionDAG &DAG)
static SDValue foldBinOpIntoSelectIfProfitable(SDNode *BO, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue customLegalizeToWOp(SDNode *N, SelectionDAG &DAG, int NumOp, unsigned ExtOpc=ISD::ANY_EXTEND)
static bool combine_CC(SDValue &LHS, SDValue &RHS, SDValue &CC, const SDLoc &DL, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static MachineBasicBlock * emitBuildPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static Intrinsic::ID getIntrinsicForMaskedAtomicRMWBinOp(unsigned GRLen, AtomicRMWInst::BinOp BinOp)
static void translateSetCCForBranch(const SDLoc &DL, SDValue &LHS, SDValue &RHS, ISD::CondCode &CC, SelectionDAG &DAG)
static bool isSplat(Value *V)
Return true if V is a splat of a value (which is used when multiplying a matrix with a scalar).
mir Rename Register Operands
Register const TargetRegisterInfo * TRI
Promote Memory to Register
This file provides utility analysis objects describing memory locations.
static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const MipsSubtarget &Subtarget)
static SDValue performSUBCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const MipsSubtarget &Subtarget)
static SDValue performSELECTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const MipsSubtarget &Subtarget)
static SDValue performMULCombine(SDNode *N, SelectionDAG &DAG, const TargetLowering::DAGCombinerInfo &DCI, const MipsSETargetLowering *TL, const MipsSubtarget &Subtarget)
static SDValue performXORCombine(SDNode *N, SelectionDAG &DAG, const MipsSubtarget &Subtarget)
static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG)
static SDValue performSRACombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const MipsSubtarget &Subtarget)
MachineInstr unsigned OpIdx
uint64_t IntrinsicInst * II
static CodeModel::Model getCodeModel(const PPCSubtarget &S, const TargetMachine &TM, const MachineOperand &MO)
static StringRef getName(Value *V)
static constexpr MCPhysReg SPReg
static StringRef getExtensionType(StringRef Ext)
static SDValue performCONCAT_VECTORSCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue SplitVectorReductionOp(SDValue Op, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static MachineBasicBlock * emitQuietFCMP(MachineInstr &MI, MachineBasicBlock *BB, unsigned RelOpcode, unsigned EqOpcode, const RISCVSubtarget &Subtarget)
static bool isLowSourceShuffle(ArrayRef< int > Mask, int Span)
Is this mask only using elements from the first span of the input?
static bool isZipOdd(const std::array< std::pair< int, int >, 2 > &SrcInfo, ArrayRef< int > Mask, unsigned &Factor)
Given a shuffle which can be represented as a pair of two slides, see if it is a zipodd idiom.
static SDValue lowerVZIP(unsigned Opc, SDValue Op0, SDValue Op1, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerBuildVectorOfConstants(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue performVECREDUCECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue lowerVECTOR_SHUFFLEAsVSlide1(const SDLoc &DL, MVT VT, SDValue V1, SDValue V2, ArrayRef< int > Mask, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
Match v(f)slide1up/down idioms.
static SDValue combineTruncToVnclip(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::optional< APInt > getExactInteger(const APFloat &APF, uint32_t BitWidth)
static SDValue performVP_TRUNCATECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isInterleaveShuffle(ArrayRef< int > Mask, MVT VT, int &EvenSrc, int &OddSrc, const RISCVSubtarget &Subtarget)
Is this shuffle interleaving contiguous elements from one vector into the even elements and contiguou...
static bool narrowIndex(SDValue &N, ISD::MemIndexType IndexType, SelectionDAG &DAG)
According to the property that indexed load/store instructions zero-extend their indices,...
static SDValue getSingleShuffleSrc(MVT VT, SDValue V1, SDValue V2)
static unsigned getPACKOpcode(unsigned DestBW, const RISCVSubtarget &Subtarget)
static void promoteVCIXScalar(const SDValue &Op, SmallVectorImpl< SDValue > &Operands, SelectionDAG &DAG)
static SDValue splatSplitI64WithVL(const SDLoc &DL, MVT VT, SDValue Passthru, SDValue Scalar, SDValue VL, SelectionDAG &DAG)
static bool isLegalBitRotate(ArrayRef< int > Mask, EVT VT, const RISCVSubtarget &Subtarget, MVT &RotateVT, unsigned &RotateAmt)
static SDValue splatPartsI64WithVL(const SDLoc &DL, MVT VT, SDValue Passthru, SDValue Lo, SDValue Hi, SDValue VL, SelectionDAG &DAG)
static SDValue getWideningInterleave(SDValue EvenV, SDValue OddV, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue getAllOnesMask(MVT VecVT, SDValue VL, const SDLoc &DL, SelectionDAG &DAG)
Creates an all ones mask suitable for masking a vector of type VecTy with vector length VL.
static SDValue simplifyOp_VL(SDNode *N)
static cl::opt< int > FPImmCost(DEBUG_TYPE "-fpimm-cost", cl::Hidden, cl::desc("Give the maximum number of instructions that we will " "use for creating a floating-point immediate value"), cl::init(2))
static SDValue lowerScalarSplat(SDValue Passthru, SDValue Scalar, SDValue VL, MVT VT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isAlternating(const std::array< std::pair< int, int >, 2 > &SrcInfo, ArrayRef< int > Mask, unsigned Factor, bool RequiredPolarity)
static const RISCV::RISCVMaskedPseudoInfo * lookupMaskedIntrinsic(uint16_t MCOpcode, RISCVVType::VLMUL LMul, unsigned SEW)
static SDValue expandMul(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue performVWADDSUBW_VLCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static bool matchIndexAsWiderOp(EVT VT, SDValue Index, SDValue Mask, Align BaseAlign, const RISCVSubtarget &ST)
Match the index of a gather or scatter operation as an operation with twice the element width and hal...
static SDValue combineOp_VLToVWOp_VL(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
Combine a binary or FMA operation to its equivalent VW or VW_W form.
static SDValue combineVFMADD_VLWithVFNEG_VL(SDNode *N, SelectionDAG &DAG)
static SDValue combineOrOfCZERO(SDNode *N, SDValue N0, SDValue N1, SelectionDAG &DAG)
static SDValue useInversedSetcc(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static cl::opt< bool > ReassocShlAddiAdd("reassoc-shl-addi-add", cl::Hidden, cl::desc("Swap add and addi in cases where the add may " "be combined with a shift"), cl::init(true))
static SDValue lowerDisjointIndicesShuffle(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Given a shuffle where the indices are disjoint between the two sources, e.g.:
static SDValue combineVWADDSUBWSelect(SDNode *N, SelectionDAG &DAG)
static MachineBasicBlock * EmitLoweredCascadedSelect(MachineInstr &First, MachineInstr &Second, MachineBasicBlock *ThisMBB, const RISCVSubtarget &Subtarget)
static SDValue performINSERT_VECTOR_ELTCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue lowerFABSorFNEG(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerFMAXIMUM_FMINIMUM(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue foldReduceOperandViaVQDOT(SDValue InVec, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue reverseZExtICmpCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue SplitStrictFPVectorOp(SDValue Op, SelectionDAG &DAG)
static SDValue tryDemorganOfBooleanCondition(SDValue Cond, SelectionDAG &DAG)
static SDValue performMemPairCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue combineDeMorganOfBoolean(SDNode *N, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLEAsVSlidedown(const SDLoc &DL, MVT VT, SDValue V1, SDValue V2, ArrayRef< int > Mask, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
static SDValue reduceANDOfAtomicLoad(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static unsigned getRVVReductionOp(unsigned ISDOpcode)
static SDValue combineSubShiftToOrcB(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerShuffleViaVRegSplitting(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue getVCIXISDNodeVOID(SDValue &Op, SelectionDAG &DAG, unsigned Type)
static SDValue lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static cl::opt< unsigned > NumRepeatedDivisors(DEBUG_TYPE "-fp-repeated-divisors", cl::Hidden, cl::desc("Set the minimum number of repetitions of a divisor to allow " "transformation to multiplications by the reciprocal"), cl::init(2))
static SDValue foldSelectOfCTTZOrCTLZ(SDNode *N, SelectionDAG &DAG)
static SDValue lowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerFixedVectorSegLoadIntrinsics(unsigned IntNo, SDValue Op, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
static SDValue combineVectorMulToSraBitcast(SDNode *N, SelectionDAG &DAG)
static bool isLocalRepeatingShuffle(ArrayRef< int > Mask, int Span)
Is this mask local (i.e.
static bool legalizeScatterGatherIndexType(SDLoc DL, SDValue &Index, ISD::MemIndexType &IndexType, RISCVTargetLowering::DAGCombinerInfo &DCI)
static bool isSpanSplatShuffle(ArrayRef< int > Mask, int Span)
Return true for a mask which performs an arbitrary shuffle within the first span, and then repeats th...
static SDValue getVSlidedown(SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const SDLoc &DL, EVT VT, SDValue Passthru, SDValue Op, SDValue Offset, SDValue Mask, SDValue VL, unsigned Policy=RISCVVType::TAIL_UNDISTURBED_MASK_UNDISTURBED)
static unsigned getRISCVVLOp(SDValue Op)
Get a RISC-V target specified VL op for a given SDNode.
static unsigned getVecReduceOpcode(unsigned Opc)
Given a binary operator, return the associative generic ISD::VECREDUCE_OP which corresponds to it.
static std::pair< SDValue, SDValue > getDefaultVLOps(uint64_t NumElts, MVT ContainerVT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isPromotedOpNeedingSplit(SDValue Op, const RISCVSubtarget &Subtarget)
static SDValue performFP_TO_INT_SATCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue lowerReductionSeq(unsigned RVVOpcode, MVT ResVT, SDValue StartValue, SDValue Vec, SDValue Mask, SDValue VL, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Helper to lower a reduction sequence of the form: scalar = reduce_op vec, scalar_start.
static SDValue expandMulToAddOrSubOfShl(SDNode *N, SelectionDAG &DAG, uint64_t MulAmt)
static SDValue performVP_REVERSECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerGetVectorLength(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::pair< SDValue, SDValue > getDefaultScalableVLOps(MVT VecVT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue getVLOperand(SDValue Op)
static SDValue performVECTOR_SHUFFLECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue performVP_STORECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static MachineBasicBlock * emitFROUND(MachineInstr &MI, MachineBasicBlock *MBB, const RISCVSubtarget &Subtarget)
static SDValue getLargeExternalSymbol(ExternalSymbolSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG)
static SDValue lowerCttzElts(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
const uint64_t ModeMask64
static SDValue lowerVectorIntrinsicScalars(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static cl::opt< unsigned > ExtensionMaxWebSize(DEBUG_TYPE "-ext-max-web-size", cl::Hidden, cl::desc("Give the maximum size (in number of nodes) of the web of " "instructions that we will consider for VW expansion"), cl::init(18))
static SDValue combineShlAddIAddImpl(SDNode *N, SDValue AddI, SDValue Other, SelectionDAG &DAG)
static SDValue getDeinterleaveShiftAndTrunc(const SDLoc &DL, MVT VT, SDValue Src, unsigned Factor, unsigned Index, SelectionDAG &DAG)
static SDValue combineBinOpOfZExt(SDNode *N, SelectionDAG &DAG)
static bool matchSelectAddSub(SDValue TrueVal, SDValue FalseVal, bool &SwapCC)
static SDValue performSIGN_EXTEND_INREGCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue combineXorToBitfieldInsert(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::optional< MVT > getSmallestVTForIndex(MVT VecVT, unsigned MaxIdx, SDLoc DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool useRVVForFixedLengthVectorVT(MVT VT, const RISCVSubtarget &Subtarget)
static bool isValidVisniInsertExtractIndex(SDValue Idx)
static Value * useTpOffset(IRBuilderBase &IRB, unsigned Offset)
static SDValue combineAddOfBooleanXor(SDNode *N, SelectionDAG &DAG)
static SDValue getZeroPaddedAdd(const SDLoc &DL, SDValue A, SDValue B, SelectionDAG &DAG)
Given fixed length vectors A and B with equal element types, but possibly different number of element...
const uint32_t ModeMask32
static SDValue combineTruncOfSraSext(SDNode *N, SelectionDAG &DAG)
static SDValue getVSlideup(SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const SDLoc &DL, EVT VT, SDValue Passthru, SDValue Op, SDValue Offset, SDValue Mask, SDValue VL, unsigned Policy=RISCVVType::TAIL_UNDISTURBED_MASK_UNDISTURBED)
static MachineBasicBlock * emitSplitF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const RISCVSubtarget &Subtarget)
static SDValue combineVqdotAccum(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static MachineBasicBlock * emitVFROUND_NOEXCEPT_MASK(MachineInstr &MI, MachineBasicBlock *BB, unsigned CVTXOpc)
static SDValue SplitVectorOp(SDValue Op, SelectionDAG &DAG)
static SDValue combineToVCPOP(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static unsigned negateFMAOpcode(unsigned Opcode, bool NegMul, bool NegAcc)
static SDValue lowerScalarInsert(SDValue Scalar, SDValue VL, MVT VT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerBuildVectorViaVID(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue transformAddShlImm(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue tryFoldSelectIntoOp(SDNode *N, SelectionDAG &DAG, SDValue TrueVal, SDValue FalseVal, bool Swapped)
static SDValue lowerBitreverseShuffle(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerConstant(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool matchIndexAsShuffle(EVT VT, SDValue Index, SDValue Mask, SmallVector< int > &ShuffleMask)
Match the index vector of a scatter or gather node as the shuffle mask which performs the rearrangeme...
static SDValue performVFMADD_VLCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue lowerFixedVectorSegStoreIntrinsics(unsigned IntNo, SDValue Op, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
static SDValue combineBinOpToReduce(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue SplitVPOp(SDValue Op, SelectionDAG &DAG)
static SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static void processVCIXOperands(SDValue &OrigOp, SmallVectorImpl< SDValue > &Operands, SelectionDAG &DAG)
static SDValue widenVectorOpsToi8(SDValue N, const SDLoc &DL, SelectionDAG &DAG)
static SDValue lowerINT_TO_FP(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerVectorFTRUNC_FCEIL_FFLOOR_FROUND(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerFTRUNC_FCEIL_FFLOOR_FROUND(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::optional< VIDSequence > isSimpleVIDSequence(SDValue Op, unsigned EltSizeInBits)
static SDValue lowerVectorXRINT_XROUND(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static uint64_t computeGREVOrGORC(uint64_t x, unsigned ShAmt, bool IsGORC)
static SDValue lowerVECTOR_SHUFFLEAsRotate(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isSimm12Constant(SDValue V)
static RISCVFPRndMode::RoundingMode matchRoundingOp(unsigned Opc)
static SDValue lowerVectorStrictFTRUNC_FCEIL_FFLOOR_FROUND(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue combineTruncSelectToSMaxUSat(SDNode *N, SelectionDAG &DAG)
static bool isElementRotate(const std::array< std::pair< int, int >, 2 > &SrcInfo, unsigned NumElts)
static SDValue performBITREVERSECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue transformAddImmMulImm(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue combineSubOfBoolean(SDNode *N, SelectionDAG &DAG)
static SDValue matchSplatAsGather(SDValue SplatVal, MVT VT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isValidEGW(int EGS, EVT VT, const RISCVSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLEAsVRGatherVX(ShuffleVectorSDNode *SVN, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
Match a single source shuffle which is an identity except that some particular element is repeated.
static bool isNonZeroAVL(SDValue AVL)
static SDValue lowerFP_TO_INT(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static MVT getQDOTXResultType(MVT OpVT)
static SDValue lowerVECTOR_SHUFFLEAsVSlideup(const SDLoc &DL, MVT VT, SDValue V1, SDValue V2, ArrayRef< int > Mask, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
static SDValue getVCIXISDNodeWCHAIN(SDValue &Op, SelectionDAG &DAG, unsigned Type)
static SDValue getLargeGlobalAddress(GlobalAddressSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG)
static MachineBasicBlock * emitReadCounterWidePseudo(MachineInstr &MI, MachineBasicBlock *BB)
static SDValue getWideningSpread(SDValue V, unsigned Factor, unsigned Index, const SDLoc &DL, SelectionDAG &DAG)
static cl::opt< bool > AllowSplatInVW_W(DEBUG_TYPE "-form-vw-w-with-splat", cl::Hidden, cl::desc("Allow the formation of VW_W operations (e.g., " "VWADD_W) with splat constants"), cl::init(false))
static SDValue unpackF64OnRV32DSoftABI(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const CCValAssign &HiVA, const SDLoc &DL)
static SDValue foldConcatVector(SDValue V1, SDValue V2)
If concat_vector(V1,V2) could be folded away to some existing vector source, return it.
static SDValue tryMemPairCombine(SelectionDAG &DAG, LSBaseSDNode *LSNode1, LSBaseSDNode *LSNode2, SDValue BasePtr, uint64_t Imm)
static std::tuple< unsigned, SDValue, SDValue > getRVVFPReductionOpAndOperands(SDValue Op, SelectionDAG &DAG, EVT EltVT, const RISCVSubtarget &Subtarget)
static SDValue performFP_TO_INTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue combineBinOpOfExtractToReduceTree(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Perform two related transforms whose purpose is to incrementally recognize an explode_vector followed...
static SDValue lowerBuildVectorViaPacking(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Double the element size of the build vector to reduce the number of vslide1down in the build vector c...
static SDValue performTRUNCATECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerSelectToBinOp(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue combineShlAddIAdd(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerBuildVectorViaDominantValues(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Try and optimize BUILD_VECTORs with "dominant values" - these are values which constitute a large pro...
static bool isCompressMask(ArrayRef< int > Mask)
static SDValue expandMulToNAFSequence(SDNode *N, SelectionDAG &DAG, uint64_t MulAmt)
static SDValue combineToVWMACC(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isZipEven(const std::array< std::pair< int, int >, 2 > &SrcInfo, ArrayRef< int > Mask, unsigned &Factor)
Given a shuffle which can be represented as a pair of two slides, see if it is a zipeven idiom.
static SDValue combineVectorSizedSetCCEquality(EVT VT, SDValue X, SDValue Y, ISD::CondCode CC, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Try to map an integer comparison with size > XLEN to vector instructions before type legalization spl...
static SDValue performBUILD_VECTORCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
If we have a build_vector where each lane is binop X, C, where C is a constant (but not necessarily t...
static LLT getMaskTypeFor(LLT VecTy)
Return the type of the mask type suitable for masking the provided vector type.
static unsigned getRISCVWOpcode(unsigned Opcode)
const SmallVectorImpl< MachineOperand > & Cond
Contains matchers for matching SelectionDAG nodes and values.
static bool isCommutative(Instruction *I, Value *ValWithUses)
static Type * getValueType(Value *V)
Returns the type of the given value/instruction V.
This file defines the SmallSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static constexpr int Concat[]
opStatus convertFromAPInt(const APInt &Input, bool IsSigned, roundingMode RM)
opStatus convertToInteger(MutableArrayRef< integerPart > Input, unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const
static APFloat getNaN(const fltSemantics &Sem, bool Negative=false, uint64_t payload=0)
Factory for NaN values.
Class for arbitrary precision integers.
bool isNegatedPowerOf2() const
Check if this APInt's negated value is a power of two greater than zero.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
uint64_t getZExtValue() const
Get zero extended value.
void setBitsFrom(unsigned loBit)
Set the top bits starting from loBit.
unsigned getActiveBits() const
Compute the number of active bits in the value.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
bool sgt(const APInt &RHS) const
Signed greater than comparison.
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
bool ugt(const APInt &RHS) const
Unsigned greater than comparison.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
unsigned getBitWidth() const
Return the number of bits in the APInt.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
bool isNegative() const
Determine sign of this APInt.
LLVM_ABI APInt sdiv(const APInt &RHS) const
Signed division function for APInt.
void clearAllBits()
Set every bit to 0.
unsigned countr_zero() const
Count the number of trailing zero bits.
bool isSignedIntN(unsigned N) const
Check if this APInt has an N-bits signed integer value.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
unsigned getSignificantBits() const
Get the minimum bit size for this signed APInt.
LLVM_ABI void insertBits(const APInt &SubBits, unsigned bitPosition)
Insert the bits from a smaller APInt starting at bitPosition.
bool isShiftedMask() const
Return true if this APInt value contains a non-empty sequence of ones with the remainder zero.
LLVM_ABI APInt srem(const APInt &RHS) const
Function for signed remainder operation.
bool isMask(unsigned numBits) const
bool isNonNegative() const
Determine if this APInt Value is non-negative (>= 0)
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
bool slt(const APInt &RHS) const
Signed less than comparison.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
void setLowBits(unsigned loBits)
Set the bottom loBits bits.
LLVM_ABI APInt extractBits(unsigned numBits, unsigned bitPosition) const
Return an APInt with the extracted bits [bitPosition,bitPosition+numBits).
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)
Constructs an APInt value that has a contiguous range of bits set.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
int64_t getSExtValue() const
Get sign extended value.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
An arbitrary precision integer that knows its signedness.
an instruction to allocate memory on the stack
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
An instruction that atomically checks whether a specified value is in a memory location,...
Value * getCompareOperand()
an instruction that atomically reads a memory location, combines it with another value,...
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ USubCond
Subtract only if no unsigned overflow.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ UMax
*p = old >unsigned v ? old : v
@ UDecWrap
Decrement one until a minimum value or zero.
bool isFloatingPointOperation() const
BinOp getOperation() const
AtomicOrdering getOrdering() const
Returns the ordering constraint of this rmw instruction.
This is an SDNode representing atomic operations.
const SDValue & getBasePtr() const
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
static LLVM_ABI BaseIndexOffset match(const SDNode *N, const SelectionDAG &DAG)
Parses tree in N for base, index, offset addresses.
LLVM Basic Block Representation.
LLVM_ABI const Module * getModule() const
Return the module owning the function this basic block belongs to, or nullptr if the function does no...
bool test(unsigned Idx) const
bool all() const
all - Returns true if all bits are set.
CCState - This class holds information needed while lowering arguments and return values.
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
LLVM_ABI void AnalyzeCallOperands(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeCallOperands - Analyze the outgoing arguments to a call, incorporating info about the passed v...
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
LLVM_ABI bool isIndirectCall() const
Return true if the callsite is an indirect call.
This class represents a function call, abstracting a target machine's calling convention.
bool isExactlyValue(double V) const
We don't rely on operator== working on double values, as it returns true for things that are clearly ...
This is the shared class of boolean and integer constants.
bool isMinusOne() const
This function will return true iff every bit in this constant is set to true.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
int64_t getSExtValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
unsigned getPointerSizeInBits(unsigned AS=0) const
The size in bits of the pointer representation in a given address space.
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
const ValueT & at(const_arg_type_t< KeyT > Val) const
at - Return the entry for the specified key, or abort if no such entry exists.
Implements a dense probed hash-table based set.
Diagnostic information for unsupported feature in backend.
static constexpr ElementCount getScalable(ScalarTy MinVal)
static constexpr ElementCount getFixed(ScalarTy MinVal)
Tagged union holding either a T or a Error.
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
uint64_t getFnAttributeAsParsedInteger(StringRef Kind, uint64_t Default=0) const
For a string attribute Kind, parse attribute as an integer.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
AttributeList getAttributes() const
Return the attribute list for this Function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Argument * getArg(unsigned i) const
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Helper struct to store a base, index and offset that forms an address.
int64_t getOffset() const
bool hasExternalWeakLinkage() const
Module * getParent()
Get the module that this global value is contained inside of...
Common base class shared among various IRBuilders.
Value * CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
BasicBlock * GetInsertBlock() const
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
static InstructionCost getInvalid(CostType Val=0)
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
Base class for LoadSDNode and StoreSDNode.
bool isIndexed() const
Return true if this is a pre/post inc/dec load/store.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
static constexpr LocationSize beforeOrAfterPointer()
Any location before or after the base pointer (but still within the underlying object).
Context object for machine code objects.
Base class for the full range of assembler expressions which are needed for parsing.
MCContext & getContext() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
const MDOperand & getOperand(unsigned I) const
static MVT getFloatingPointVT(unsigned BitWidth)
static auto integer_fixedlen_vector_valuetypes()
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
bool isRISCVVectorTuple() const
Return true if this is a RISCV vector tuple type where the runtime length is machine dependent.
uint64_t getScalarSizeInBits() const
MVT changeVectorElementType(MVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
bool bitsLE(MVT VT) const
Return true if this has no more bits than VT.
unsigned getVectorNumElements() const
static MVT getRISCVVectorTupleVT(unsigned Sz, unsigned NFields)
bool isVector() const
Return true if this is a vector value type.
bool isInteger() const
Return true if this is an integer or a vector integer type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
static MVT getScalableVectorVT(MVT VT, unsigned NumElements)
unsigned getRISCVVectorTupleNumFields() const
Given a RISC-V vector tuple type, return the num_fields.
MVT changeTypeToInteger()
Return the type converted to an equivalently sized integer or vector with integer element type.
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
bool bitsLT(MVT VT) const
Return true if this has less bits than VT.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
LLVM_ABI const fltSemantics & getFltSemantics() const
Returns an APFloat semantics tag appropriate for the value type.
bool bitsGT(MVT VT) const
Return true if this has more bits than VT.
bool isFixedLengthVector() const
ElementCount getVectorElementCount() const
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool bitsGE(MVT VT) const
Return true if this has no less bits than VT.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
bool isValid() const
Return true if this is a valid simple valuetype.
static MVT getIntegerVT(unsigned BitWidth)
MVT getDoubleNumVectorElementsVT() const
MVT getHalfNumVectorElementsVT() const
Return a VT for a vector type with the same element type but half the number of elements.
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
static auto integer_scalable_vector_valuetypes()
MVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
static auto fp_fixedlen_vector_valuetypes()
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
void push_back(MachineInstr *MI)
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
Instructions::iterator instr_iterator
instr_iterator instr_end()
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
LLVM_ABI void collectDebugValues(SmallVectorImpl< MachineInstr * > &DbgValues)
Scan instructions immediately following MI and collect any matching DBG_VALUEs.
void setFlag(MIFlag Flag)
Set a MI flag.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
@ EK_Custom32
EK_Custom32 - Each entry is a 32-bit value that is custom lowered by the TargetLowering::LowerCustomJ...
A description of a memory reference used in the backend.
const MDNode * getRanges() const
Return the range tag for the memory reference.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MONonTemporal
The memory access is non-temporal.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
const MachinePointerInfo & getPointerInfo() const
Flags getFlags() const
Return the raw flags of the source value,.
AAMDNodes getAAInfo() const
Return the AA tags for the memory reference.
Align getBaseAlign() const
Return the minimum known alignment in bytes of the base address, without the offset.
MachineOperand class - Representation of each machine instruction operand.
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
This is an abstract virtual class for memory operations.
bool isSimple() const
Returns true if the memory operation is neither atomic or volatile.
AtomicOrdering getSuccessOrdering() const
Return the atomic ordering requirements for this memory operation.
MachineMemOperand * getMemOperand() const
Return a MachineMemOperand object describing the memory reference performed by operation.
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
A Module instance is used to store all the information related to an LLVM module.
Metadata * getModuleFlag(StringRef Key) const
Return the corresponding value if Key appears in module flags, otherwise return null.
A RISCV-specific constant pool value.
static RISCVConstantPoolValue * Create(const GlobalValue *GV)
RISCVMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private RISCV-...
void setVarArgsFrameIndex(int Index)
int getVarArgsFrameIndex() const
void setVarArgsSaveSize(int Size)
void addSExt32Register(Register Reg)
unsigned getMaxLMULForFixedLengthVectors() const
bool hasVInstructionsI64() const
bool hasVInstructionsF64() const
bool hasStdExtZfhOrZhinx() const
bool hasShlAdd(int64_t ShAmt) const
unsigned getRealMinVLen() const
bool useRVVForFixedLengthVectors() const
bool hasVInstructionsBF16Minimal() const
bool hasVInstructionsF16Minimal() const
bool hasConditionalMoveFusion() const
bool hasVInstructionsF16() const
unsigned getMaxBuildIntsCost() const
bool hasVInstructions() const
bool isRegisterReservedByUser(Register i) const override
std::optional< unsigned > getRealVLen() const
bool useConstantPoolForLargeInts() const
unsigned getRealMaxVLen() const
const RISCVRegisterInfo * getRegisterInfo() const override
const RISCVInstrInfo * getInstrInfo() const override
bool hasBEXTILike() const
const RISCVTargetLowering * getTargetLowering() const override
bool hasVInstructionsF32() const
bool hasCZEROLike() const
static std::pair< unsigned, unsigned > computeVLMAXBounds(MVT ContainerVT, const RISCVSubtarget &Subtarget)
static std::pair< unsigned, unsigned > decomposeSubvectorInsertExtractToSubRegs(MVT VecVT, MVT SubVecVT, unsigned InsertExtractIdx, const RISCVRegisterInfo *TRI)
ArrayRef< MCPhysReg > getRoundingControlRegisters() const override
Returns a 0 terminated array of rounding control registers that can be attached into strict FP call.
static MVT getM1VT(MVT VT)
Given a vector (either fixed or scalable), return the scalable vector corresponding to a vector regis...
InstructionCost getVRGatherVVCost(MVT VT) const
Return the cost of a vrgather.vv instruction for the type VT.
bool getIndexedAddressParts(SDNode *Op, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const
static unsigned getSubregIndexByMVT(MVT VT, unsigned Index)
Value * getIRStackGuard(IRBuilderBase &IRB) const override
If the target has a standard location for the stack protector cookie, returns the address of that loc...
bool shouldConvertFpToSat(unsigned Op, EVT FPVT, EVT VT) const override
Should we generate fp_to_si_sat and fp_to_ui_sat from type FPVT to type VT from min(max(fptoi)) satur...
InlineAsm::ConstraintCode getInlineAsmMemConstraint(StringRef ConstraintCode) const override
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
bool mayBeEmittedAsTailCall(const CallInst *CI) const override
Return true if the target may be able emit the call instruction as a tail call.
RISCVTargetLowering(const TargetMachine &TM, const RISCVSubtarget &STI)
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
Instruction * emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
Inserts in the IR a target-specific intrinsic specifying a fence.
bool isTruncateFree(Type *SrcTy, Type *DstTy) const override
Return true if it's free to truncate a value of type FromTy to type ToTy.
bool shouldRemoveExtendFromGSIndex(SDValue Extend, EVT DataVT) const override
Value * emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI, Value *AlignedAddr, Value *Incr, Value *Mask, Value *ShiftAmt, AtomicOrdering Ord) const override
Perform a masked atomicrmw using a target-specific intrinsic.
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const override
Returns true if the target allows unaligned memory accesses of the specified type.
const Constant * getTargetConstantFromLoad(LoadSDNode *LD) const override
This method returns the constant pool value that will be loaded by LD.
const RISCVSubtarget & getSubtarget() const
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
bool preferScalarizeSplat(SDNode *N) const override
bool shouldExtendTypeInLibCall(EVT Type) const override
Returns true if arguments should be extended in lib calls.
bool isLegalAddImmediate(int64_t Imm) const override
Return true if the specified immediate is legal add immediate, that is the target has add instruction...
bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const override
Returns true if arguments should be sign-extended in lib calls.
const MCExpr * LowerCustomJumpTableEntry(const MachineJumpTableInfo *MJTI, const MachineBasicBlock *MBB, unsigned uid, MCContext &Ctx) const override
InstructionCost getVRGatherVICost(MVT VT) const
Return the cost of a vrgather.vi (or vx) instruction for the type VT.
bool shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const override
Return true if it is beneficial to convert a load of a constant to just the constant itself.
bool targetShrinkDemandedConstant(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, TargetLoweringOpt &TLO) const override
bool shouldExpandBuildVectorWithShuffles(EVT VT, unsigned DefinedValues) const override
MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Return the register type for a given MVT, ensuring vectors are treated as a series of gpr sized integ...
bool decomposeMulByConstant(LLVMContext &Context, EVT VT, SDValue C) const override
Return true if it is profitable to transform an integer multiplication-by-constant into simpler opera...
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, LLVMContext &Context, const Type *RetTy) const override
This hook should be implemented to check whether the return values described by the Outs array can fi...
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
bool hasAndNotCompare(SDValue Y) const override
Return true if the target should transform: (X & Y) == Y ---> (~X & Y) == 0 (X & Y) !...
bool shouldScalarizeBinop(SDValue VecOp) const override
Try to convert an extract element of a vector binary operation into an extract element followed by a ...
bool isDesirableToCommuteWithShift(const SDNode *N, CombineLevel Level) const override
Return true if it is profitable to move this shift by a constant amount through its operand,...
bool areTwoSDNodeTargetMMOFlagsMergeable(const MemSDNode &NodeX, const MemSDNode &NodeY) const override
Return true if it is valid to merge the TargetMMOFlags in two SDNodes.
bool hasBitTest(SDValue X, SDValue Y) const override
Return true if the target has a bit-test instruction: (X & (1 << Y)) ==/!= 0 This knowledge can be us...
static unsigned computeVLMAX(unsigned VectorBits, unsigned EltSize, unsigned MinSize)
bool shouldExpandCttzElements(EVT VT) const override
Return true if the @llvm.experimental.cttz.elts intrinsic should be expanded using generic code in Se...
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
Value * emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, AtomicCmpXchgInst *CI, Value *AlignedAddr, Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const override
Perform a masked cmpxchg using a target-specific intrinsic.
bool isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize) const override
Returns true if the target can instruction select the specified FP immediate natively.
InstructionCost getLMULCost(MVT VT) const
Return the cost of LMUL for linear operations.
unsigned getJumpTableEncoding() const override
Return the entry encoding for a jump table in the current function.
bool isMulAddWithConstProfitable(SDValue AddNode, SDValue ConstNode) const override
Return true if it may be profitable to transform (mul (add x, c1), c2) -> (add (mul x,...
InstructionCost getVSlideVICost(MVT VT) const
Return the cost of a vslidedown.vi or vslideup.vi instruction for the type VT.
bool fallBackToDAGISel(const Instruction &Inst) const override
EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
bool isCtpopFast(EVT VT) const override
Return true if ctpop instruction is fast.
unsigned ComputeNumSignBitsForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
This method can be implemented by targets that want to expose additional information about sign bits ...
MVT getContainerForFixedLengthVector(MVT VT) const
static unsigned getRegClassIDForVecVT(MVT VT)
Register getExceptionPointerRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
TargetLowering::AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return true if EXTRACT_SUBVECTOR is cheap for extracting this result type from this source type with ...
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
MachineBasicBlock * emitDynamicProbedAlloc(MachineInstr &MI, MachineBasicBlock *MBB) const
MachineMemOperand::Flags getTargetMMOFlags(const Instruction &I) const override
This callback is used to inspect load/store instructions and add target-specific MachineMemOperand fl...
SDValue computeVLMax(MVT VecVT, const SDLoc &DL, SelectionDAG &DAG) const
bool signExtendConstant(const ConstantInt *CI) const override
Return true if this constant should be sign extended when promoting to a larger type.
bool shouldTransformSignedTruncationCheck(EVT XVT, unsigned KeptBits) const override
Should we tranform the IR-optimal check for whether given truncation down into KeptBits would be trun...
bool shouldProduceAndByConstByHoistingConstFromShiftsLHSOfAnd(SDValue X, ConstantSDNode *XC, ConstantSDNode *CC, SDValue Y, unsigned OldShiftOpcode, unsigned NewShiftOpcode, SelectionDAG &DAG) const override
Given the pattern (X & (C l>>/<< Y)) ==/!= 0 return true if it should be transformed into: ((X <</l>>...
bool hasInlineStackProbe(const MachineFunction &MF) const override
True if stack clash protection is enabled for this functions.
bool hasAndNot(SDValue Y) const override
Return true if the target has a bitwise and-not operation: X = ~A & B This can be used to simplify se...
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Returns the register with the specified architectural or ABI name.
InstructionCost getVSlideVXCost(MVT VT) const
Return the cost of a vslidedown.vx or vslideup.vx instruction for the type VT.
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override
Return true if result of the specified node is used by a return node only.
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const override
Return true if an FMA operation is faster than a pair of fmul and fadd instructions.
TargetLowering::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *CI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
Register getExceptionSelectorRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
unsigned getCustomCtpopCost(EVT VT, ISD::CondCode Cond) const override
Return the maximum number of "x & (x - 1)" operations that can be done instead of deferring to a cust...
void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override
This method should be implemented by targets that mark instructions with the 'hasPostISelHook' flag.
bool isShuffleMaskLegal(ArrayRef< int > M, EVT VT) const override
Return true if the given shuffle mask can be codegen'd directly, or if it should be stack expanded.
bool isCheapToSpeculateCttz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic cttz.
bool isLegalICmpImmediate(int64_t Imm) const override
Return true if the specified immediate is legal icmp immediate, that is the target has icmp instructi...
ISD::NodeType getExtendForAtomicCmpSwapArg() const override
Returns how the platform's atomic compare and swap expects its comparison value to be extended (ZERO_...
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower the incoming (formal) arguments, described by the Ins array,...
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I, MachineFunction &MF, unsigned Intrinsic) const override
Given an intrinsic, checks if on the target the intrinsic will need to map to a MemIntrinsicNode (tou...
unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const override
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
bool isLegalElementTypeForRVV(EVT ScalarTy) const
bool isVScaleKnownToBeAPowerOfTwo() const override
Return true only if vscale must be a power of two.
int getLegalZfaFPImm(const APFloat &Imm, EVT VT) const
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
Lower the specified operand into the Ops vector.
bool splitValueIntoRegisterParts(SelectionDAG &DAG, const SDLoc &DL, SDValue Val, SDValue *Parts, unsigned NumParts, MVT PartVT, std::optional< CallingConv::ID > CC) const override
Target-specific splitting of values into parts that fit a register storing a legal type.
Instruction * emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Return the number of registers for a given MVT, ensuring vectors are treated as a series of gpr sized...
ConstraintType getConstraintType(StringRef Constraint) const override
getConstraintType - Given a constraint letter, return the type of constraint it is for this target.
MachineInstr * EmitKCFICheck(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator &MBBI, const TargetInstrInfo *TII) const override
bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool PoisonOnly, bool ConsiderFlags, unsigned Depth) const override
Return true if Op can create undef or poison from non-undef & non-poison operands.
bool isIntDivCheap(EVT VT, AttributeList Attr) const override
Return true if integer divide is usually cheaper than a sequence of several shifts,...
SDValue expandIndirectJTBranch(const SDLoc &dl, SDValue Value, SDValue Addr, int JTI, SelectionDAG &DAG) const override
Expands target specific indirect branch for the case of JumpTable expansion.
static unsigned getRegClassIDForLMUL(RISCVVType::VLMUL LMul)
unsigned getNumRegisters(LLVMContext &Context, EVT VT, std::optional< MVT > RegisterVT=std::nullopt) const override
Return the number of registers for a given MVT, for inline assembly.
bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
Returns true by value, base pointer and offset pointer and addressing mode by reference if this node ...
bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
Returns true by value, base pointer and offset pointer and addressing mode by reference if the node's...
SDValue joinRegisterPartsIntoValue(SelectionDAG &DAG, const SDLoc &DL, const SDValue *Parts, unsigned NumParts, MVT PartVT, EVT ValueVT, std::optional< CallingConv::ID > CC) const override
Target-specific combining of register parts into its original value.
bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const override
Return if the target supports combining a chain like:
bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override
Return true if sign-extension from FromTy to ToTy is cheaper than zero-extension.
bool isLegalStridedLoadStore(EVT DataType, Align Alignment) const
Return true if a stride load store of the given result type and alignment is legal.
static bool isSpreadMask(ArrayRef< int > Mask, unsigned Factor, unsigned &Index)
Match a mask which "spreads" the leading elements of a vector evenly across the result.
static RISCVVType::VLMUL getLMUL(MVT VT)
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth) const override
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
bool shouldFoldSelectWithIdentityConstant(unsigned BinOpcode, EVT VT, unsigned SelectOpcode, SDValue X, SDValue Y) const override
Return true if pulling a binary operation into a select with an identity constant is profitable.
unsigned getStackProbeSize(const MachineFunction &MF, Align StackAlign) const
bool shouldInsertFencesForAtomic(const Instruction *I) const override
Whether AtomicExpandPass should automatically insert fences and reduce ordering for this atomic.
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.
ArrayRef< SDUse > ops() const
const APInt & getAsAPIntVal() const
Helper method returns the APInt value of a ConstantSDNode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
iterator_range< use_iterator > uses()
SDNodeFlags getFlags() const
size_t use_size() const
Return the number of uses of this node.
MVT getSimpleValueType(unsigned ResNo) const
Return the type of a specified result as a simple type.
static bool hasPredecessorHelper(const SDNode *N, SmallPtrSetImpl< const SDNode * > &Visited, SmallVectorImpl< const SDNode * > &Worklist, unsigned int MaxSteps=0, bool TopologicalPrune=false)
Returns true if N is a predecessor of any node in Worklist.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
const SDValue & getOperand(unsigned Num) const
std::optional< APInt > bitcastToAPInt() const
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
void setCFIType(uint32_t Type)
bool isUndef() const
Returns true if the node type is UNDEF or POISON.
iterator_range< user_iterator > users()
Represents a use of a SDNode.
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
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
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
const APInt & getConstantOperandAPInt(unsigned i) const
uint64_t getScalarValueSizeInBits() const
uint64_t getConstantOperandVal(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getOpcode() const
unsigned getNumOperands() const
virtual bool isTargetStrictFPOpcode(unsigned Opcode) const
Returns true if a node with the given target-specific opcode has strict floating-point semantics.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI Align getReducedAlign(EVT VT, bool UseABI)
In most cases this function returns the ABI alignment for a given type, except for illegal vector typ...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
SDValue getExtractVectorElt(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Extract element at Idx from Vec.
LLVM_ABI unsigned ComputeMaxSignificantBits(SDValue Op, unsigned Depth=0) const
Get the upper bound on bit size for this Value Op as a signed integer.
LLVM_ABI SDValue getMaskedGather(SDVTList VTs, EVT MemVT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType, ISD::LoadExtType ExtTy)
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL)
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
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 getNeutralElement(unsigned Opcode, const SDLoc &DL, EVT VT, SDNodeFlags Flags)
Get the (commutative) neutral element for the given opcode, if it exists.
LLVM_ABI SDValue getAtomicLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT MemVT, EVT VT, SDValue Chain, SDValue Ptr, MachineMemOperand *MMO)
LLVM_ABI SDValue getVScale(const SDLoc &DL, EVT VT, APInt MulImm, bool ConstantFold=true)
Return a node that represents the runtime scaling 'MulImm * RuntimeVL'.
LLVM_ABI SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
LLVM_ABI SDValue getStridedLoadVP(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, const SDLoc &DL, SDValue Chain, SDValue Ptr, SDValue Offset, SDValue Stride, SDValue Mask, SDValue EVL, EVT MemVT, MachineMemOperand *MMO, bool IsExpanding=false)
LLVM_ABI SDValue makeEquivalentMemoryOrdering(SDValue OldChain, SDValue NewMemOpChain)
If an existing load has uses of its chain, create a token factor node with that chain and the new mem...
LLVM_ABI SDValue getJumpTableDebugInfo(int JTI, SDValue Chain, const SDLoc &DL)
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false)
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
bool isSafeToSpeculativelyExecute(unsigned Opcode) const
Some opcodes may create immediate undefined behavior when used with some values (integer division-by-...
LLVM_ABI SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
SDValue getExtractSubvector(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Return the VT typed sub-vector of Vec at Idx.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getElementCount(const SDLoc &DL, EVT VT, ElementCount EC, bool ConstantFold=true)
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
SDValue getInsertSubvector(const SDLoc &DL, SDValue Vec, SDValue SubVec, unsigned Idx)
Insert SubVec at the Idx element of Vec.
LLVM_ABI SDValue getStepVector(const SDLoc &DL, EVT ResVT, const APInt &StepVal)
Returns a vector of type ResVT whose elements contain the linear sequence <0, Step,...
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
LLVM_ABI bool shouldOptForSize() const
std::pair< SDValue, SDValue > SplitVectorOperand(const SDNode *N, unsigned OpNo)
Split the node's operand with EXTRACT_SUBVECTOR and return the low/high part.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
LLVM_ABI SDValue getVPZExtOrTrunc(const SDLoc &DL, EVT VT, SDValue Op, SDValue Mask, SDValue EVL)
Convert a vector-predicated Op, which must be an integer vector, to the vector-type VT,...
const TargetLowering & getTargetLoweringInfo() const
LLVM_ABI SDValue getStridedStoreVP(SDValue Chain, const SDLoc &DL, SDValue Val, SDValue Ptr, SDValue Offset, SDValue Stride, SDValue Mask, SDValue EVL, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
bool NewNodesMustHaveLegalTypes
When true, additional steps are taken to ensure that getConstant() and similar functions return DAG n...
LLVM_ABI std::pair< EVT, EVT > GetSplitDestVTs(const EVT &VT) const
Compute the VTs needed for the low/hi parts of a type which is split (or expanded) into two not neces...
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
LLVM_ABI SDValue getGatherVP(SDVTList VTs, EVT VT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType)
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI bool isSplatValue(SDValue V, const APInt &DemandedElts, APInt &UndefElts, unsigned Depth=0) const
Test whether V has a splatted value for all the demanded elements.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
const SelectionDAGTargetInfo & getSelectionDAGInfo() const
LLVM_ABI SDValue getStoreVP(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, SDValue Offset, SDValue Mask, SDValue EVL, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags=SDNodeFlags())
Returns sum of the base pointer and offset.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue getSplatVector(EVT VT, const SDLoc &DL, SDValue Op)
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI bool SignBitIsZero(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero.
SDValue getInsertVectorElt(const SDLoc &DL, SDValue Vec, SDValue Elt, unsigned Idx)
Insert Elt into Vec at offset Idx.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDValue > Ops, SDNodeFlags Flags=SDNodeFlags())
LLVM_ABI SDValue getMaskedStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Base, SDValue Offset, SDValue Mask, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
LLVM_ABI std::pair< SDValue, SDValue > getStrictFPExtendOrRound(SDValue Op, SDValue Chain, const SDLoc &DL, EVT VT)
Convert Op, which must be a STRICT operation of float type, to the float type VT, by either extending...
LLVM_ABI std::pair< SDValue, SDValue > SplitEVL(SDValue N, EVT VecVT, const SDLoc &DL)
Split the explicit vector length parameter of a VP operation.
LLVM_ABI SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either any-extending or truncat...
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getScatterVP(SDVTList VTs, EVT VT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
LLVM_ABI SDValue getFPExtendOrRound(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of float type, to the float type VT, by either extending or rounding (by tr...
LLVM_ABI bool isKnownNeverNaN(SDValue Op, const APInt &DemandedElts, bool SNaN=false, unsigned Depth=0) const
Test whether the given SDValue (or all elements of it, if it is a vector) is known to never be NaN in...
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI SDValue getBoolConstant(bool V, const SDLoc &DL, EVT VT, EVT OpVT)
Create a true or false constant of type VT using the target's BooleanContent for type OpVT.
SDValue getTargetBlockAddress(const BlockAddress *BA, EVT VT, int64_t Offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
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.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
void addCallSiteInfo(const SDNode *Node, CallSiteInfo &&CallInfo)
Set CallSiteInfo to be associated with Node.
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Base, SDValue Offset, SDValue Mask, SDValue Src0, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, ISD::LoadExtType, bool IsExpanding=false)
SDValue getSplat(EVT VT, const SDLoc &DL, SDValue Op)
Returns a node representing a splat of one value into all lanes of the provided vector type.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
LLVM_ABI SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a logical NOT operation as (XOR Val, BooleanOne).
LLVM_ABI SDValue getMaskedScatter(SDVTList VTs, EVT MemVT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType, bool IsTruncating=false)
static LLVM_ABI bool isSelectMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from its source vectors without lane crossings.
static LLVM_ABI bool isBitRotateMask(ArrayRef< int > Mask, unsigned EltSizeInBits, unsigned MinSubElts, unsigned MaxSubElts, unsigned &NumSubElts, unsigned &RotateAmt)
Checks if the shuffle is a bit rotation of the first operand across multiple subelements,...
static LLVM_ABI bool isSingleSourceMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector.
static LLVM_ABI bool isDeInterleaveMaskOfFactor(ArrayRef< int > Mask, unsigned Factor, unsigned &Index)
Check if the mask is a DE-interleave mask of the given factor Factor like: <Index,...
static LLVM_ABI bool isIdentityMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector without lane crossin...
static LLVM_ABI bool isReverseMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask swaps the order of elements from exactly one source vector.
static LLVM_ABI bool isInsertSubvectorMask(ArrayRef< int > Mask, int NumSrcElts, int &NumSubElts, int &Index)
Return true if this shuffle mask is an insert subvector mask.
static LLVM_ABI bool isInterleaveMask(ArrayRef< int > Mask, unsigned Factor, unsigned NumInputElts, SmallVectorImpl< unsigned > &StartIndexes)
Return true if the mask interleaves one or more input vectors together.
This SDNode is used to implement the code generator support for the llvm IR shufflevector instruction...
int getSplatIndex() const
ArrayRef< int > getMask() const
static LLVM_ABI bool isSplatMask(ArrayRef< int > Mask)
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
pointer data()
Return a pointer to the vector's buffer, even if empty().
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
StringRef - Represent a constant reference to a string, i.e.
constexpr size_t size() const
size - Get the string size.
LLVM_ABI std::string lower() const
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, T Value)
Information about stack frame layout on the target.
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
TargetInstrInfo - Interface to description of machine instruction set.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
bool PredictableSelectIsExpensive
Tells the code generator that select is more expensive than a branch if the branch is usually predict...
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
unsigned MaxStoresPerMemcpyOptSize
Likewise for functions with the OptSize attribute.
MachineBasicBlock * emitPatchPoint(MachineInstr &MI, MachineBasicBlock *MBB) const
Replace/modify any TargetFrameIndex operands with a targte-dependent sequence of memory operands that...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
virtual unsigned getMinimumJumpTableEntries() const
Return lower limit for number of blocks in a jump table.
const TargetMachine & getTargetMachine() const
unsigned MaxLoadsPerMemcmp
Specify maximum number of load instructions per memcmp call.
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
unsigned MaxGluedStoresPerMemcpy
Specify max number of store instructions to glue in inlined memcpy.
virtual bool isZExtFree(Type *FromTy, Type *ToTy) const
Return true if any actual instruction that defines a value of type FromTy implicitly zero-extends the...
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
void setOperationPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
Convenience method to set an operation to Promote and specify the type in a single call.
unsigned getMinCmpXchgSizeInBits() const
Returns the size of the smallest cmpxchg or ll/sc instruction the backend supports.
virtual unsigned getNumRegisters(LLVMContext &Context, EVT VT, std::optional< MVT > RegisterVT=std::nullopt) const
Return the number of registers that this ValueType will eventually require.
void setIndexedLoadAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed load does or does not work with the specified type and indicate w...
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
virtual unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
bool isOperationCustom(unsigned Op, EVT VT) const
Return true if the operation uses custom lowering, regardless of whether the type is legal or not.
unsigned MaxStoresPerMemsetOptSize
Likewise for functions with the OptSize attribute.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
unsigned MaxStoresPerMemmove
Specify maximum number of store instructions per memmove call.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
virtual bool isTruncateFree(Type *FromTy, Type *ToTy) const
Return true if it's free to truncate a value of type FromTy to type ToTy.
unsigned MaxStoresPerMemmoveOptSize
Likewise for functions with the OptSize attribute.
virtual bool shouldFoldSelectWithSingleBitTest(EVT VT, const APInt &AndMask) const
virtual Value * getIRStackGuard(IRBuilderBase &IRB) const
If the target has a standard location for the stack protector guard, returns the address of that loca...
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
bool EnableExtLdPromotion
void setIndexedStoreAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed store does or does not work with the specified type and indicate ...
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
bool isOperationLegal(unsigned Op, EVT VT) const
Return true if the specified operation is legal on this target.
unsigned MaxStoresPerMemset
Specify maximum number of store instructions per memset call.
void setPartialReduceMLAAction(unsigned Opc, MVT AccVT, MVT InputVT, LegalizeAction Action)
Indicate how a PARTIAL_REDUCE_U/SMLA node with Acc type AccVT and Input type InputVT should be treate...
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
unsigned MaxLoadsPerMemcmpOptSize
Likewise for functions with the OptSize attribute.
virtual bool isBinOp(unsigned Opcode) const
Return true if the node is a math/logic binary operator.
void setMinCmpXchgSizeInBits(unsigned SizeInBits)
Sets the minimum cmpxchg or ll/sc size supported by the backend.
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
void setCondCodeAction(ArrayRef< ISD::CondCode > CCs, MVT VT, LegalizeAction Action)
Indicate that the specified condition code is or isn't supported on the target and indicate what to d...
virtual std::pair< const TargetRegisterClass *, uint8_t > findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const
Return the largest legal super-reg register class of the register class for the specified type and it...
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
std::vector< ArgListEntry > ArgListTy
bool allowsMemoryAccessForAlignment(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
This function returns true if the memory access is aligned or if the target allows this specific unal...
unsigned MaxStoresPerMemcpy
Specify maximum number of store instructions per memcpy call.
bool isOperationLegalOrCustomOrPromote(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual MVT getVPExplicitVectorLengthTy() const
Returns the type to be used for the EVL/AVL operand of VP nodes: ISD::VP_ADD, ISD::VP_SUB,...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
SDValue expandAddSubSat(SDNode *Node, SelectionDAG &DAG) const
Method for building the DAG expansion of ISD::[US][ADD|SUB]SAT.
SDValue buildSDIVPow2WithCMov(SDNode *N, const APInt &Divisor, SelectionDAG &DAG, SmallVectorImpl< SDNode * > &Created) const
Build sdiv by power-of-2 with conditional move instructions Ref: "Hacker's Delight" by Henry Warren 1...
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
virtual SDValue expandIndirectJTBranch(const SDLoc &dl, SDValue Value, SDValue Addr, int JTI, SelectionDAG &DAG) const
Expands target specific indirect branch for the case of JumpTable expansion.
virtual InlineAsm::ConstraintCode getInlineAsmMemConstraint(StringRef ConstraintCode) const
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
virtual SDValue LowerToTLSEmulatedModel(const GlobalAddressSDNode *GA, SelectionDAG &DAG) const
Lower TLS global address SDNode for target independent emulated TLS model.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
bool isPositionIndependent() const
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
virtual bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0) const
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
TargetLowering(const TargetLowering &)=delete
virtual unsigned combineRepeatedFPDivisors() const
Indicate whether this target prefers to combine FDIVs with the same divisor.
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
virtual unsigned getJumpTableEncoding() const
Return the entry encoding for a jump table in the current function.
virtual bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool PoisonOnly, bool ConsiderFlags, unsigned Depth) const
Return true if Op can create undef or poison from non-undef & non-poison operands.
Primary interface to the complete machine description for the target machine.
TLSModel::Model getTLSModel(const GlobalValue *GV) const
Returns the TLS model which should be used for the given global variable.
const Triple & getTargetTriple() const
bool useTLSDESC() const
Returns true if this target uses TLS Descriptors.
const MCSubtargetInfo * getMCSubtargetInfo() const
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
virtual TargetLoweringObjectFile * getObjFileLowering() const
unsigned EmitCallGraphSection
Emit section containing call graph metadata.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual bool isRegisterReservedByUser(Register R) const
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
Target - Wrapper for Target specific information.
bool isOSBinFormatCOFF() const
Tests whether the OS uses the COFF binary format.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
LLVM_ABI Type * getStructElementType(unsigned N) const
LLVM_ABI bool isScalableTy(SmallPtrSetImpl< const Type * > &Visited) const
Return true if this is a type whose size is a known multiple of vscale.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
bool isStructTy() const
True if this is an instance of StructType.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isTargetExtTy() const
Return true if this is a target extension type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
A Use represents the edge between a Value definition and its users.
User * getUser() const
Returns the User that contains this Use.
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
std::pair< iterator, bool > insert(const ValueT &V)
constexpr bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
constexpr ScalarTy getFixedValue() const
static constexpr bool isKnownLE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
constexpr LeafTy multiplyCoefficientBy(ScalarTy RHS) const
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
constexpr bool isZero() const
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ RISCV_VectorCall
Calling convention used for RISC-V V-extension.
@ PreserveMost
Used for runtime calls that preserves most registers.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ SPIR_KERNEL
Used for SPIR kernel functions.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
@ GRAAL
Used by GraalVM. Two additional registers are reserved.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI bool isConstantSplatVectorAllOnes(const SDNode *N, bool BuildVectorOnly=false)
Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where all of the elements are ~0 ...
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ ADD
Simple integer binary arithmetic operators.
@ 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)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ FADD
Simple binary floating point operators.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ STRICT_FSQRT
Constrained versions of libm-equivalent floating point intrinsics.
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ SIGN_EXTEND
Conversion operators.
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ CTTZ_ZERO_UNDEF
Bit counting operators with an undefined result for zero inputs.
@ VECTOR_INTERLEAVE
VECTOR_INTERLEAVE(VEC1, VEC2, ...) - Returns N vectors from N input vectors, where N is the factor to...
@ STEP_VECTOR
STEP_VECTOR(IMM) - Returns a scalable vector whose lanes are comprised of a linear sequence of unsign...
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ UNDEF
UNDEF - An undefined node.
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
@ GET_ROUNDING
Returns current rounding mode: -1 Undefined 0 Round to 0 1 Round to nearest, ties to even 2 Round to ...
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ 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.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ SSHLSAT
RESULT = [US]SHLSAT(LHS, RHS) - Perform saturation left shift.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ VECTOR_REVERSE
VECTOR_REVERSE(VECTOR) - Returns a vector, of the same type as VECTOR, whose elements are shuffled us...
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ STRICT_SINT_TO_FP
STRICT_[US]INT_TO_FP - Convert a signed or unsigned integer to a floating point value.
@ EH_DWARF_CFA
EH_DWARF_CFA - This node represents the pointer to the DWARF Canonical Frame Address (CFA),...
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ 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...
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
@ STRICT_FADD
Constrained versions of the binary floating point operators.
@ SPLAT_VECTOR_PARTS
SPLAT_VECTOR_PARTS(SCALAR1, SCALAR2, ...) - Returns a vector with the scalar values joined together a...
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ VECTOR_SPLICE
VECTOR_SPLICE(VEC1, VEC2, IMM) - Returns a subvector of the same type as VEC1/VEC2 from CONCAT_VECTOR...
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ VECTOR_COMPRESS
VECTOR_COMPRESS(Vec, Mask, Passthru) consecutively place vector elements based on mask e....
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ VECTOR_DEINTERLEAVE
VECTOR_DEINTERLEAVE(VEC1, VEC2, ...) - Returns N vectors from N input vectors, where N is the factor ...
@ TRUNCATE_SSAT_S
TRUNCATE_[SU]SAT_[SU] - Truncate for saturated operand [SU] located in middle, prefix for SAT means i...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
@ 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,...
LLVM_ABI bool isBuildVectorOfConstantSDNodes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR node of all ConstantSDNode or undef.
bool isNormalStore(const SDNode *N)
Returns true if the specified node is a non-truncating and unindexed store.
bool isExtOpcode(unsigned Opcode)
LLVM_ABI bool isConstantSplatVectorAllZeros(const SDNode *N, bool BuildVectorOnly=false)
Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where all of the elements are 0 o...
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
LLVM_ABI std::optional< unsigned > getVPMaskIdx(unsigned Opcode)
The operand position of the vector mask.
LLVM_ABI std::optional< unsigned > getVPExplicitVectorLengthIdx(unsigned Opcode)
The operand position of the explicit vector length parameter.
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
MemIndexType
MemIndexType enum - This enum defines how to interpret MGATHER/SCATTER's index parameter when calcula...
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.
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
LLVM_ABI bool isBuildVectorOfConstantFPSDNodes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR node of all ConstantFPSDNode or undef.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LLVM_ABI bool isBuildVectorAllOnes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are ~0 or undef.
LLVM_ABI NodeType getVecReduceBaseOpcode(unsigned VecReduceOpcode)
Get underlying scalar opcode for VECREDUCE opcode.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
LLVM_ABI bool isVPOpcode(unsigned Opcode)
Whether this is a vector-predicated Opcode.
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
bool isIntEqualitySetCC(CondCode Code)
Return true if this is a setcc instruction that performs an equality comparison when used with intege...
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
@ Bitcast
Perform the operation on a different, but equivalently sized type.
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
CastInst_match< OpTy, TruncInst > m_Trunc(const OpTy &Op)
Matches Trunc.
BinaryOp_match< LHS, RHS, Instruction::Xor > m_Xor(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::FMul > m_FMul(const LHS &L, const RHS &R)
TwoOps_match< Val_t, Idx_t, Instruction::ExtractElement > m_ExtractElt(const Val_t &Val, const Idx_t &Idx)
Matches ExtractElementInst.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
deferredval_ty< Value > m_Deferred(Value *const &V)
Like m_Specific(), but works if the specific value to match is determined as part of the same match()...
match_combine_or< BinaryOp_match< LHS, RHS, Instruction::Add >, DisjointOr_match< LHS, RHS > > m_AddLike(const LHS &L, const RHS &R)
Match either "add" or "or disjoint".
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
FNeg_match< OpTy > m_FNeg(const OpTy &X)
Match 'fneg X' as 'fsub -0.0, X'.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
ThreeOps_match< Val_t, Elt_t, Idx_t, Instruction::InsertElement > m_InsertElt(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx)
Matches InsertElementInst.
unsigned getBrCond(CondCode CC, unsigned SelectOpc=0)
static RISCVVType::VLMUL getLMul(uint64_t TSFlags)
static int getFRMOpNum(const MCInstrDesc &Desc)
static unsigned getSEWOpNum(const MCInstrDesc &Desc)
int getLoadFPImm(APFloat FPImm)
getLoadFPImm - Return a 5-bit binary encoding of the floating-point immediate value.
InstSeq generateInstSeq(int64_t Val, const MCSubtargetInfo &STI)
int getIntMatCost(const APInt &Val, unsigned Size, const MCSubtargetInfo &STI, bool CompressionCost, bool FreeZeroes)
InstSeq generateTwoRegInstSeq(int64_t Val, const MCSubtargetInfo &STI, unsigned &ShiftAmt, unsigned &AddOpc)
SmallVector< Inst, 8 > InstSeq
static VLMUL encodeLMUL(unsigned LMUL, bool Fractional)
static unsigned decodeVSEW(unsigned VSEW)
@ TAIL_UNDISTURBED_MASK_UNDISTURBED
LLVM_ABI std::pair< unsigned, bool > decodeVLMUL(VLMUL VLMul)
static unsigned encodeSEW(unsigned SEW)
static constexpr unsigned FPMASK_Negative_Zero
static constexpr unsigned FPMASK_Positive_Subnormal
static constexpr unsigned FPMASK_Positive_Normal
static constexpr unsigned FPMASK_Negative_Subnormal
static constexpr unsigned FPMASK_Negative_Normal
static constexpr unsigned FPMASK_Positive_Infinity
static constexpr unsigned FPMASK_Negative_Infinity
static constexpr unsigned FPMASK_Quiet_NaN
ArrayRef< MCPhysReg > getArgGPRs(const RISCVABI::ABI ABI)
static constexpr unsigned FPMASK_Signaling_NaN
static constexpr unsigned FPMASK_Positive_Zero
static constexpr unsigned RVVBitsPerBlock
static constexpr unsigned RVVBytesPerBlock
LLVM_ABI Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
@ Kill
The last use of a register.
BinaryOpc_match< LHS, RHS > m_Srl(const LHS &L, const RHS &R)
Or< Preds... > m_AnyOf(const Preds &...preds)
auto m_Node(unsigned Opcode, const OpndPreds &...preds)
bool sd_match(SDNode *N, const SelectionDAG *DAG, Pattern &&P)
ConstantInt_match m_ConstInt()
Match any integer constants or splat of an integer constant.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
@ System
Synchronized with respect to all concurrently executing threads.
initializer< Ty > init(const Ty &Val)
uint32_t read32le(const void *P)
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
FunctionAddr VTableAddr Value
bool CC_RISCV_FastCC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
bool CC_RISCV_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static const MachineMemOperand::Flags MONontemporalBit1
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
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.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
MCCodeEmitter * createRISCVMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
static const MachineMemOperand::Flags MONontemporalBit0
bool RISCVCCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
RISCVCCAssignFn - This target-specific function extends the default CCValAssign with additional infor...
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI bool widenShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Try to transform a shuffle mask by replacing elements with the scaled index for an equivalent mask of...
LLVM_ABI Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
LLVM_ABI bool isNullOrNullSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndefs=false)
Return true if the value is a constant 0 integer or a splatted vector of a constant 0 integer (with n...
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
bool isReleaseOrStronger(AtomicOrdering AO)
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere.
constexpr bool has_single_bit(T Value) noexcept
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
FunctionAddr VTableAddr Count
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
bool CC_RISCV(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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_ABI bool isOneOrOneSplat(SDValue V, bool AllowUndefs=false)
Return true if the value is a constant 1 integer or a splatted vector of a constant 1 integer (with n...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
auto drop_end(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the last N elements excluded.
AtomicOrdering
Atomic ordering for LLVM's memory model.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
LLVM_ABI void narrowShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Replace each shuffle mask index with the scaled sequential indices for an equivalent mask of narrowed...
LLVM_ABI bool isMaskedSlidePair(ArrayRef< int > Mask, int NumElts, std::array< std::pair< int, int >, 2 > &SrcInfo)
Does this shuffle mask represent either one slide shuffle or a pair of two slide shuffles,...
@ Xor
Bitwise or logical XOR of integers.
@ SMin
Signed integer min implemented in terms of select(cmp()).
@ Sub
Subtraction of integers.
unsigned getKillRegState(bool B)
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
FunctionAddr VTableAddr Next
DWARFExpression::Operation Op
RoundingMode
Rounding mode.
@ TowardZero
roundTowardZero.
@ NearestTiesToEven
roundTiesToEven.
@ TowardPositive
roundTowardPositive.
@ NearestTiesToAway
roundTiesToAway.
@ TowardNegative
roundTowardNegative.
ArrayRef(const T &OneElt) -> ArrayRef< T >
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.
bool isAcquireOrStronger(AtomicOrdering AO)
constexpr unsigned BitWidth
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
LLVM_ABI void processShuffleMasks(ArrayRef< int > Mask, unsigned NumOfSrcRegs, unsigned NumOfDestRegs, unsigned NumOfUsedRegs, function_ref< void()> NoInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned)> SingleInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned, bool)> ManyInputsAction)
Splits and processes shuffle mask depending on the number of input and output registers.
unsigned Log2(Align A)
Returns the log2 of the alignment.
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
LLVM_ABI bool isNeutralConstant(unsigned Opc, SDNodeFlags Flags, SDValue V, unsigned OperandNo)
Returns true if V is a neutral element of Opc with Flags.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
auto mask(ShuffFunc S, unsigned Length, OptArgs... args) -> MaskT
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
static constexpr roundingMode rmNearestTiesToEven
static LLVM_ABI unsigned int semanticsPrecision(const fltSemantics &)
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint64_t value() const
This is a hole in the type system and should not be abused.
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
uint64_t getScalarStoreSize() const
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
bool isByteSized() const
Return true if the bit size is a multiple of 8.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
unsigned getRISCVVectorTupleNumFields() const
Given a RISCV vector tuple type, return the num_fields.
uint64_t getScalarSizeInBits() const
EVT getHalfSizedIntegerVT(LLVMContext &Context) const
Finds the smallest simple value type that is greater than or equal to half the width of this EVT.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
bool isRISCVVectorTuple() const
Return true if this is a vector value type.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isFixedLengthVector() const
EVT getRoundIntegerType(LLVMContext &Context) const
Rounds the bit-width of the given integer EVT up to the nearest power of two (and at least to eight),...
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
bool bitsGE(EVT VT) const
Return true if this has no less bits than VT.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
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.
EVT changeVectorElementType(EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
bool isInteger() const
Return true if this is an integer or a vector integer type.
static LLVM_ABI KnownBits ashr(const KnownBits &LHS, const KnownBits &RHS, bool ShAmtNonZero=false, bool Exact=false)
Compute known bits for ashr(LHS, RHS).
static LLVM_ABI KnownBits urem(const KnownBits &LHS, const KnownBits &RHS)
Compute known bits for urem(LHS, RHS).
bool isUnknown() const
Returns true if we don't know any bits.
unsigned countMaxTrailingZeros() const
Returns the maximum number of trailing zero bits possible.
KnownBits trunc(unsigned BitWidth) const
Return known bits for a truncation of the value we're tracking.
unsigned getBitWidth() const
Get the bit width of this value.
KnownBits zext(unsigned BitWidth) const
Return known bits for a zero extension of the value we're tracking.
void resetAll()
Resets the known state of all bits.
static LLVM_ABI KnownBits lshr(const KnownBits &LHS, const KnownBits &RHS, bool ShAmtNonZero=false, bool Exact=false)
Compute known bits for lshr(LHS, RHS).
unsigned countMaxActiveBits() const
Returns the maximum number of bits needed to represent all possible unsigned values with these known ...
KnownBits intersectWith(const KnownBits &RHS) const
Returns KnownBits information that is known to be true for both this and RHS.
KnownBits sext(unsigned BitWidth) const
Return known bits for a sign extension of the value we're tracking.
static LLVM_ABI KnownBits udiv(const KnownBits &LHS, const KnownBits &RHS, bool Exact=false)
Compute known bits for udiv(LHS, RHS).
unsigned countMaxLeadingZeros() const
Returns the maximum number of leading zero bits possible.
static LLVM_ABI KnownBits shl(const KnownBits &LHS, const KnownBits &RHS, bool NUW=false, bool NSW=false, bool ShAmtNonZero=false)
Compute known bits for shl(LHS, RHS).
SmallVector< ArgRegPair, 1 > ArgRegPairs
Vector of call argument and its forwarding register.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Register getFrameRegister(const MachineFunction &MF) const override
These are IR-level optimization flags that may be propagated to SDNodes.
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This structure contains all information that is necessary for lowering calls.
SmallVector< ISD::InputArg, 32 > Ins
const ConstantInt * CFIType
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
bool isAfterLegalizeDAG() const
LLVM_ABI void AddToWorklist(SDNode *N)
bool isCalledByLegalizer() const
LLVM_ABI bool recursivelyDeleteUnusedNodes(SDNode *N)
bool isBeforeLegalize() const
LLVM_ABI SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
This structure is used to pass arguments to makeLibCall function.
MakeLibCallOptions & setTypeListBeforeSoften(ArrayRef< EVT > OpsVT, EVT RetVT)
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...
bool CombineTo(SDValue O, SDValue N)