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 if ((Subtarget.hasVendorXCVbitmanip() || Subtarget.hasVendorXqcibm()) &&
385 !Subtarget.is64Bit()) {
391 if (Subtarget.hasStdExtZbkb())
395 if (Subtarget.hasStdExtZbb() ||
396 (Subtarget.hasVendorXCValu() && !Subtarget.is64Bit())) {
401 if (Subtarget.hasCTZLike()) {
402 if (Subtarget.is64Bit())
408 if (!Subtarget.hasCPOPLike()) {
411 if (Subtarget.is64Bit())
418 if (Subtarget.hasCLZLike()) {
422 if (Subtarget.is64Bit() && Subtarget.hasStdExtZbb())
428 if (Subtarget.hasVendorXCValu() && !Subtarget.is64Bit()) {
430 }
else if (Subtarget.hasShortForwardBranchOpt()) {
433 }
else if (Subtarget.is64Bit()) {
437 if (!Subtarget.useMIPSCCMovInsn() && !Subtarget.hasVendorXTHeadCondMov())
440 if (Subtarget.hasVendorXqcia() && !Subtarget.is64Bit()) {
449 static const unsigned FPLegalNodeTypes[] = {
450 ISD::FMINNUM, ISD::FMAXNUM, ISD::FMINIMUMNUM,
451 ISD::FMAXIMUMNUM, ISD::LRINT, ISD::LLRINT,
463 static const unsigned FPOpToExpand[] = {
464 ISD::FSIN, ISD::FCOS, ISD::FSINCOS, ISD::FPOW,
467 static const unsigned FPRndMode[] = {
468 ISD::FCEIL, ISD::FFLOOR, ISD::FTRUNC, ISD::FRINT, ISD::FROUND,
471 static const unsigned ZfhminZfbfminPromoteOps[] = {
472 ISD::FMINNUM, ISD::FMAXNUM, ISD::FMAXIMUMNUM,
479 ISD::FTRUNC, ISD::FRINT, ISD::FROUND,
482 if (Subtarget.hasStdExtZfbfmin()) {
497 if (Subtarget.hasStdExtZfhminOrZhinxmin()) {
498 if (Subtarget.hasStdExtZfhOrZhinx()) {
505 if (Subtarget.hasStdExtZfa())
510 for (
auto Op : {ISD::LROUND, ISD::LLROUND, ISD::LRINT, ISD::LLRINT,
531 ISD::FNEARBYINT, MVT::f16,
532 Subtarget.hasStdExtZfh() && Subtarget.hasStdExtZfa() ?
Legal :
Promote);
534 ISD::FCOS, ISD::FSIN, ISD::FSINCOS, ISD::FEXP,
535 ISD::FEXP2, ISD::FEXP10, ISD::FLOG, ISD::FLOG2,
536 ISD::FLOG10, ISD::FLDEXP, ISD::FFREXP, ISD::FMODF},
548 if (Subtarget.is64Bit())
552 if (Subtarget.hasStdExtFOrZfinx()) {
574 if (Subtarget.hasStdExtZfa()) {
583 if (Subtarget.hasStdExtFOrZfinx() && Subtarget.is64Bit())
586 if (Subtarget.hasStdExtDOrZdinx()) {
589 if (!Subtarget.is64Bit())
592 if (Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
593 !Subtarget.is64Bit()) {
598 if (Subtarget.hasStdExtZfa()) {
604 if (Subtarget.is64Bit())
633 if (Subtarget.is64Bit()) {
640 if (Subtarget.hasStdExtFOrZfinx()) {
666 if (Subtarget.is64Bit())
676 if (Subtarget.is64Bit()) {
683 if (Subtarget.is64Bit())
686 if (Subtarget.hasVendorXMIPSCBOP())
688 else if (Subtarget.hasStdExtZicbop())
691 if (Subtarget.hasStdExtA()) {
693 if (Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas())
697 }
else if (Subtarget.hasForcedAtomics()) {
712 if (Subtarget.hasVInstructions()) {
721 {MVT::i8, MVT::i16},
Custom);
722 if (Subtarget.is64Bit())
732 static const unsigned IntegerVPOps[] = {
733 ISD::VP_ADD, ISD::VP_SUB, ISD::VP_MUL,
734 ISD::VP_SDIV, ISD::VP_UDIV, ISD::VP_SREM,
735 ISD::VP_UREM, ISD::VP_AND, ISD::VP_OR,
736 ISD::VP_XOR, ISD::VP_SRA, ISD::VP_SRL,
737 ISD::VP_SHL, ISD::VP_REDUCE_ADD, ISD::VP_REDUCE_AND,
738 ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR, ISD::VP_REDUCE_SMAX,
739 ISD::VP_REDUCE_SMIN, ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN,
740 ISD::VP_MERGE, ISD::VP_SELECT, ISD::VP_FP_TO_SINT,
741 ISD::VP_FP_TO_UINT, ISD::VP_SETCC, ISD::VP_SIGN_EXTEND,
742 ISD::VP_ZERO_EXTEND, ISD::VP_TRUNCATE, ISD::VP_SMIN,
743 ISD::VP_SMAX, ISD::VP_UMIN, ISD::VP_UMAX,
744 ISD::VP_ABS, ISD::EXPERIMENTAL_VP_REVERSE, ISD::EXPERIMENTAL_VP_SPLICE,
745 ISD::VP_SADDSAT, ISD::VP_UADDSAT, ISD::VP_SSUBSAT,
746 ISD::VP_USUBSAT, ISD::VP_CTTZ_ELTS, ISD::VP_CTTZ_ELTS_ZERO_UNDEF,
747 ISD::EXPERIMENTAL_VP_SPLAT};
749 static const unsigned FloatingPointVPOps[] = {
750 ISD::VP_FADD, ISD::VP_FSUB, ISD::VP_FMUL,
751 ISD::VP_FDIV, ISD::VP_FNEG, ISD::VP_FABS,
752 ISD::VP_FMA, ISD::VP_REDUCE_FADD, ISD::VP_REDUCE_SEQ_FADD,
753 ISD::VP_REDUCE_FMIN, ISD::VP_REDUCE_FMAX, ISD::VP_MERGE,
754 ISD::VP_SELECT, ISD::VP_SINT_TO_FP, ISD::VP_UINT_TO_FP,
755 ISD::VP_SETCC, ISD::VP_FP_ROUND, ISD::VP_FP_EXTEND,
756 ISD::VP_SQRT, ISD::VP_FMINNUM, ISD::VP_FMAXNUM,
757 ISD::VP_FCEIL, ISD::VP_FFLOOR, ISD::VP_FROUND,
758 ISD::VP_FROUNDEVEN, ISD::VP_FCOPYSIGN, ISD::VP_FROUNDTOZERO,
759 ISD::VP_FRINT, ISD::VP_FNEARBYINT, ISD::VP_IS_FPCLASS,
760 ISD::VP_FMINIMUM, ISD::VP_FMAXIMUM, ISD::VP_LRINT,
761 ISD::VP_LLRINT, ISD::VP_REDUCE_FMINIMUM,
762 ISD::VP_REDUCE_FMAXIMUM, ISD::EXPERIMENTAL_VP_SPLAT};
764 static const unsigned IntegerVecReduceOps[] = {
765 ISD::VECREDUCE_ADD, ISD::VECREDUCE_AND, ISD::VECREDUCE_OR,
766 ISD::VECREDUCE_XOR, ISD::VECREDUCE_SMAX, ISD::VECREDUCE_SMIN,
767 ISD::VECREDUCE_UMAX, ISD::VECREDUCE_UMIN};
769 static const unsigned FloatingPointVecReduceOps[] = {
770 ISD::VECREDUCE_FADD, ISD::VECREDUCE_SEQ_FADD, ISD::VECREDUCE_FMIN,
771 ISD::VECREDUCE_FMAX, ISD::VECREDUCE_FMINIMUM, ISD::VECREDUCE_FMAXIMUM};
773 static const unsigned FloatingPointLibCallOps[] = {
774 ISD::FREM, ISD::FPOW, ISD::FCOS, ISD::FSIN, ISD::FSINCOS, ISD::FEXP,
775 ISD::FEXP2, ISD::FEXP10, ISD::FLOG, ISD::FLOG2, ISD::FLOG10};
777 if (!Subtarget.is64Bit()) {
786 ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR,
787 ISD::VP_REDUCE_SMAX, ISD::VP_REDUCE_SMIN,
788 ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN},
792 for (
MVT VT : BoolVecVTs) {
818 {ISD::VECREDUCE_AND, ISD::VECREDUCE_OR, ISD::VECREDUCE_XOR}, VT,
822 {ISD::VP_REDUCE_AND, ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR}, VT,
846 ISD::VP_TRUNCATE, ISD::VP_SETCC},
863 for (
MVT VT : IntVecVTs) {
874 if (VT.getVectorElementType() == MVT::i64 && !Subtarget.hasStdExtV())
924 {ISD::VP_LOAD, ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
925 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER, ISD::VP_SCATTER},
950 if (Subtarget.hasStdExtZvkb()) {
958 if (Subtarget.hasStdExtZvbb()) {
962 ISD::VP_CTTZ_ZERO_UNDEF, ISD::VP_CTPOP},
968 ISD::VP_CTTZ_ZERO_UNDEF, ISD::VP_CTPOP},
977 ISD::VP_CTLZ_ZERO_UNDEF, ISD::VP_CTTZ_ZERO_UNDEF},
985 for (
MVT VT : VecTupleVTs) {
1006 static const unsigned ZvfhminZvfbfminPromoteOps[] = {
1034 ISD::VECREDUCE_FMIN,
1035 ISD::VECREDUCE_FMAX,
1036 ISD::VECREDUCE_FMINIMUM,
1037 ISD::VECREDUCE_FMAXIMUM};
1040 static const unsigned ZvfhminZvfbfminPromoteVPOps[] = {
1046 ISD::VP_REDUCE_FMIN,
1047 ISD::VP_REDUCE_FMAX,
1055 ISD::VP_FROUNDTOZERO,
1061 ISD::VP_REDUCE_FMINIMUM,
1062 ISD::VP_REDUCE_FMAXIMUM};
1065 const auto SetCommonVFPActions = [&](
MVT VT) {
1081 {ISD::FMINNUM, ISD::FMAXNUM, ISD::FMAXIMUMNUM, ISD::FMINIMUMNUM}, VT,
1086 ISD::FROUNDEVEN, ISD::FRINT, ISD::FNEARBYINT,
1103 {ISD::VP_LOAD, ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1104 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER, ISD::VP_SCATTER},
1140 const auto SetCommonVFPExtLoadTruncStoreActions =
1142 for (
auto SmallVT : SmallerVTs) {
1150 const auto SetCommonPromoteToF32Actions = [&](
MVT VT) {
1178 ISD::MGATHER, ISD::MSCATTER, ISD::VP_LOAD,
1179 ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1180 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1203 if (Subtarget.hasVInstructionsF16()) {
1204 for (
MVT VT : F16VecVTs) {
1207 SetCommonVFPActions(VT);
1209 }
else if (Subtarget.hasVInstructionsF16Minimal()) {
1210 for (
MVT VT : F16VecVTs) {
1213 SetCommonPromoteToF32Actions(VT);
1217 if (Subtarget.hasVInstructionsBF16Minimal()) {
1218 for (
MVT VT : BF16VecVTs) {
1221 SetCommonPromoteToF32Actions(VT);
1225 if (Subtarget.hasVInstructionsF32()) {
1226 for (
MVT VT : F32VecVTs) {
1229 SetCommonVFPActions(VT);
1230 SetCommonVFPExtLoadTruncStoreActions(VT, F16VecVTs);
1231 SetCommonVFPExtLoadTruncStoreActions(VT, BF16VecVTs);
1235 if (Subtarget.hasVInstructionsF64()) {
1236 for (
MVT VT : F64VecVTs) {
1239 SetCommonVFPActions(VT);
1240 SetCommonVFPExtLoadTruncStoreActions(VT, F16VecVTs);
1241 SetCommonVFPExtLoadTruncStoreActions(VT, BF16VecVTs);
1242 SetCommonVFPExtLoadTruncStoreActions(VT, F32VecVTs);
1246 if (Subtarget.useRVVForFixedLengthVectors()) {
1248 if (!useRVVForFixedLengthVectorVT(VT))
1293 {ISD::VECREDUCE_AND, ISD::VECREDUCE_OR, ISD::VECREDUCE_XOR}, VT,
1297 {ISD::VP_REDUCE_AND, ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR}, VT,
1324 ISD::VP_SETCC, ISD::VP_TRUNCATE},
1348 {ISD::MLOAD, ISD::MSTORE, ISD::MGATHER, ISD::MSCATTER}, VT,
Custom);
1351 ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1352 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1384 ISD::VECREDUCE_SMIN, ISD::VECREDUCE_UMAX,
1385 ISD::VECREDUCE_UMIN},
1390 if (Subtarget.hasStdExtZvkb())
1393 if (Subtarget.hasStdExtZvbb()) {
1417 if (!useRVVForFixedLengthVectorVT(VT))
1440 ISD::MGATHER, ISD::MSCATTER},
1443 ISD::VP_SCATTER, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1444 ISD::EXPERIMENTAL_VP_STRIDED_STORE},
1453 !Subtarget.hasVInstructionsF16()) {
1463 if (Subtarget.hasStdExtZfhmin()) {
1489 if (Subtarget.hasStdExtZfbfmin()) {
1515 ISD::FMA, ISD::FMINNUM, ISD::FMAXNUM,
1517 ISD::FMAXIMUM, ISD::FMINIMUM},
1521 ISD::FROUNDEVEN, ISD::FRINT, ISD::LRINT,
1522 ISD::LLRINT, ISD::LROUND, ISD::LLROUND,
1548 if (Subtarget.is64Bit())
1550 if (Subtarget.hasStdExtZfhminOrZhinxmin())
1552 if (Subtarget.hasStdExtZfbfmin())
1554 if (Subtarget.hasStdExtFOrZfinx())
1556 if (Subtarget.hasStdExtDOrZdinx())
1561 if (Subtarget.hasStdExtA())
1564 if (Subtarget.hasForcedAtomics()) {
1567 {ISD::ATOMIC_CMP_SWAP, ISD::ATOMIC_SWAP, ISD::ATOMIC_LOAD_ADD,
1568 ISD::ATOMIC_LOAD_SUB, ISD::ATOMIC_LOAD_AND, ISD::ATOMIC_LOAD_OR,
1569 ISD::ATOMIC_LOAD_XOR, ISD::ATOMIC_LOAD_NAND, ISD::ATOMIC_LOAD_MIN,
1570 ISD::ATOMIC_LOAD_MAX, ISD::ATOMIC_LOAD_UMIN, ISD::ATOMIC_LOAD_UMAX},
1574 if (Subtarget.hasVendorXTHeadMemIdx()) {
1583 if (Subtarget.is64Bit()) {
1590 if (Subtarget.hasVendorXCVmem() && !Subtarget.is64Bit()) {
1601 if (Subtarget.hasStdExtZvqdotq() && Subtarget.getELen() >= 64) {
1602 static const unsigned MLAOps[] = {ISD::PARTIAL_REDUCE_SMLA,
1603 ISD::PARTIAL_REDUCE_UMLA,
1604 ISD::PARTIAL_REDUCE_SUMLA};
1611 if (Subtarget.useRVVForFixedLengthVectors()) {
1613 if (VT.getVectorElementType() != MVT::i32 ||
1614 !useRVVForFixedLengthVectorVT(VT))
1624 if (Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh()) {
1630 const Align FunctionAlignment(Subtarget.hasStdExtZca() ? 2 : 4);
1642 if (Subtarget.hasStdExtFOrZfinx())
1645 if (Subtarget.hasStdExtZbb())
1648 if ((Subtarget.hasStdExtZbs() && Subtarget.is64Bit()) ||
1649 Subtarget.hasVInstructions())
1652 if (Subtarget.hasStdExtZbkb())
1655 if (Subtarget.hasStdExtFOrZfinx())
1658 if (Subtarget.hasVInstructions())
1661 ISD::VP_GATHER, ISD::VP_SCATTER,
ISD::SRA,
1664 ISD::VP_STORE, ISD::VP_TRUNCATE, ISD::EXPERIMENTAL_VP_REVERSE,
1670 if (Subtarget.hasVendorXTHeadMemPair())
1672 if (Subtarget.useRVVForFixedLengthVectors())
1692 Subtarget.getMaxStoresPerMemmove(
true);
1704 if (Subtarget.hasVInstructions() &&
1715bool RISCVTargetLowering::shouldExpandGetVectorLength(
EVT TripCountVT,
1717 bool IsScalable)
const {
1724 if (TripCountVT != MVT::i32 && TripCountVT != Subtarget.
getXLenVT())
1742 return !Subtarget.hasVInstructions() ||
1750 auto &
DL =
I.getDataLayout();
1752 auto SetRVVLoadStoreInfo = [&](
unsigned PtrOp,
bool IsStore,
1753 bool IsUnitStrided,
bool UsePtrVal =
false) {
1758 Info.ptrVal =
I.getArgOperand(PtrOp);
1760 Info.fallbackAddressSpace =
1761 I.getArgOperand(PtrOp)->getType()->getPointerAddressSpace();
1765 MemTy =
I.getArgOperand(0)->getType();
1768 MemTy =
I.getType();
1783 Info.align =
DL.getABITypeAlign(MemTy);
1793 if (
I.hasMetadata(LLVMContext::MD_nontemporal))
1800 case Intrinsic::riscv_masked_atomicrmw_xchg:
1801 case Intrinsic::riscv_masked_atomicrmw_add:
1802 case Intrinsic::riscv_masked_atomicrmw_sub:
1803 case Intrinsic::riscv_masked_atomicrmw_nand:
1804 case Intrinsic::riscv_masked_atomicrmw_max:
1805 case Intrinsic::riscv_masked_atomicrmw_min:
1806 case Intrinsic::riscv_masked_atomicrmw_umax:
1807 case Intrinsic::riscv_masked_atomicrmw_umin:
1808 case Intrinsic::riscv_masked_cmpxchg:
1815 Info.memVT = MVT::i32;
1816 Info.ptrVal =
I.getArgOperand(0);
1818 Info.align =
Align(4);
1822 case Intrinsic::riscv_seg2_load_mask:
1823 case Intrinsic::riscv_seg3_load_mask:
1824 case Intrinsic::riscv_seg4_load_mask:
1825 case Intrinsic::riscv_seg5_load_mask:
1826 case Intrinsic::riscv_seg6_load_mask:
1827 case Intrinsic::riscv_seg7_load_mask:
1828 case Intrinsic::riscv_seg8_load_mask:
1829 case Intrinsic::riscv_sseg2_load_mask:
1830 case Intrinsic::riscv_sseg3_load_mask:
1831 case Intrinsic::riscv_sseg4_load_mask:
1832 case Intrinsic::riscv_sseg5_load_mask:
1833 case Intrinsic::riscv_sseg6_load_mask:
1834 case Intrinsic::riscv_sseg7_load_mask:
1835 case Intrinsic::riscv_sseg8_load_mask:
1836 return SetRVVLoadStoreInfo( 0,
false,
1838 case Intrinsic::riscv_seg2_store_mask:
1839 case Intrinsic::riscv_seg3_store_mask:
1840 case Intrinsic::riscv_seg4_store_mask:
1841 case Intrinsic::riscv_seg5_store_mask:
1842 case Intrinsic::riscv_seg6_store_mask:
1843 case Intrinsic::riscv_seg7_store_mask:
1844 case Intrinsic::riscv_seg8_store_mask:
1846 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1849 case Intrinsic::riscv_sseg2_store_mask:
1850 case Intrinsic::riscv_sseg3_store_mask:
1851 case Intrinsic::riscv_sseg4_store_mask:
1852 case Intrinsic::riscv_sseg5_store_mask:
1853 case Intrinsic::riscv_sseg6_store_mask:
1854 case Intrinsic::riscv_sseg7_store_mask:
1855 case Intrinsic::riscv_sseg8_store_mask:
1857 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
1860 case Intrinsic::riscv_vlm:
1861 return SetRVVLoadStoreInfo( 0,
1865 case Intrinsic::riscv_vle:
1866 case Intrinsic::riscv_vle_mask:
1867 case Intrinsic::riscv_vleff:
1868 case Intrinsic::riscv_vleff_mask:
1869 return SetRVVLoadStoreInfo( 1,
1873 case Intrinsic::riscv_vsm:
1874 case Intrinsic::riscv_vse:
1875 case Intrinsic::riscv_vse_mask:
1876 return SetRVVLoadStoreInfo( 1,
1880 case Intrinsic::riscv_vlse:
1881 case Intrinsic::riscv_vlse_mask:
1882 case Intrinsic::riscv_vloxei:
1883 case Intrinsic::riscv_vloxei_mask:
1884 case Intrinsic::riscv_vluxei:
1885 case Intrinsic::riscv_vluxei_mask:
1886 return SetRVVLoadStoreInfo( 1,
1889 case Intrinsic::riscv_vsse:
1890 case Intrinsic::riscv_vsse_mask:
1891 case Intrinsic::riscv_vsoxei:
1892 case Intrinsic::riscv_vsoxei_mask:
1893 case Intrinsic::riscv_vsuxei:
1894 case Intrinsic::riscv_vsuxei_mask:
1895 return SetRVVLoadStoreInfo( 1,
1898 case Intrinsic::riscv_vlseg2:
1899 case Intrinsic::riscv_vlseg3:
1900 case Intrinsic::riscv_vlseg4:
1901 case Intrinsic::riscv_vlseg5:
1902 case Intrinsic::riscv_vlseg6:
1903 case Intrinsic::riscv_vlseg7:
1904 case Intrinsic::riscv_vlseg8:
1905 case Intrinsic::riscv_vlseg2ff:
1906 case Intrinsic::riscv_vlseg3ff:
1907 case Intrinsic::riscv_vlseg4ff:
1908 case Intrinsic::riscv_vlseg5ff:
1909 case Intrinsic::riscv_vlseg6ff:
1910 case Intrinsic::riscv_vlseg7ff:
1911 case Intrinsic::riscv_vlseg8ff:
1912 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1915 case Intrinsic::riscv_vlseg2_mask:
1916 case Intrinsic::riscv_vlseg3_mask:
1917 case Intrinsic::riscv_vlseg4_mask:
1918 case Intrinsic::riscv_vlseg5_mask:
1919 case Intrinsic::riscv_vlseg6_mask:
1920 case Intrinsic::riscv_vlseg7_mask:
1921 case Intrinsic::riscv_vlseg8_mask:
1922 case Intrinsic::riscv_vlseg2ff_mask:
1923 case Intrinsic::riscv_vlseg3ff_mask:
1924 case Intrinsic::riscv_vlseg4ff_mask:
1925 case Intrinsic::riscv_vlseg5ff_mask:
1926 case Intrinsic::riscv_vlseg6ff_mask:
1927 case Intrinsic::riscv_vlseg7ff_mask:
1928 case Intrinsic::riscv_vlseg8ff_mask:
1929 return SetRVVLoadStoreInfo(
I.arg_size() - 5,
1932 case Intrinsic::riscv_vlsseg2:
1933 case Intrinsic::riscv_vlsseg3:
1934 case Intrinsic::riscv_vlsseg4:
1935 case Intrinsic::riscv_vlsseg5:
1936 case Intrinsic::riscv_vlsseg6:
1937 case Intrinsic::riscv_vlsseg7:
1938 case Intrinsic::riscv_vlsseg8:
1939 case Intrinsic::riscv_vloxseg2:
1940 case Intrinsic::riscv_vloxseg3:
1941 case Intrinsic::riscv_vloxseg4:
1942 case Intrinsic::riscv_vloxseg5:
1943 case Intrinsic::riscv_vloxseg6:
1944 case Intrinsic::riscv_vloxseg7:
1945 case Intrinsic::riscv_vloxseg8:
1946 case Intrinsic::riscv_vluxseg2:
1947 case Intrinsic::riscv_vluxseg3:
1948 case Intrinsic::riscv_vluxseg4:
1949 case Intrinsic::riscv_vluxseg5:
1950 case Intrinsic::riscv_vluxseg6:
1951 case Intrinsic::riscv_vluxseg7:
1952 case Intrinsic::riscv_vluxseg8:
1953 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
1956 case Intrinsic::riscv_vlsseg2_mask:
1957 case Intrinsic::riscv_vlsseg3_mask:
1958 case Intrinsic::riscv_vlsseg4_mask:
1959 case Intrinsic::riscv_vlsseg5_mask:
1960 case Intrinsic::riscv_vlsseg6_mask:
1961 case Intrinsic::riscv_vlsseg7_mask:
1962 case Intrinsic::riscv_vlsseg8_mask:
1963 case Intrinsic::riscv_vloxseg2_mask:
1964 case Intrinsic::riscv_vloxseg3_mask:
1965 case Intrinsic::riscv_vloxseg4_mask:
1966 case Intrinsic::riscv_vloxseg5_mask:
1967 case Intrinsic::riscv_vloxseg6_mask:
1968 case Intrinsic::riscv_vloxseg7_mask:
1969 case Intrinsic::riscv_vloxseg8_mask:
1970 case Intrinsic::riscv_vluxseg2_mask:
1971 case Intrinsic::riscv_vluxseg3_mask:
1972 case Intrinsic::riscv_vluxseg4_mask:
1973 case Intrinsic::riscv_vluxseg5_mask:
1974 case Intrinsic::riscv_vluxseg6_mask:
1975 case Intrinsic::riscv_vluxseg7_mask:
1976 case Intrinsic::riscv_vluxseg8_mask:
1977 return SetRVVLoadStoreInfo(
I.arg_size() - 6,
1980 case Intrinsic::riscv_vsseg2:
1981 case Intrinsic::riscv_vsseg3:
1982 case Intrinsic::riscv_vsseg4:
1983 case Intrinsic::riscv_vsseg5:
1984 case Intrinsic::riscv_vsseg6:
1985 case Intrinsic::riscv_vsseg7:
1986 case Intrinsic::riscv_vsseg8:
1987 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1990 case Intrinsic::riscv_vsseg2_mask:
1991 case Intrinsic::riscv_vsseg3_mask:
1992 case Intrinsic::riscv_vsseg4_mask:
1993 case Intrinsic::riscv_vsseg5_mask:
1994 case Intrinsic::riscv_vsseg6_mask:
1995 case Intrinsic::riscv_vsseg7_mask:
1996 case Intrinsic::riscv_vsseg8_mask:
1997 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
2000 case Intrinsic::riscv_vssseg2:
2001 case Intrinsic::riscv_vssseg3:
2002 case Intrinsic::riscv_vssseg4:
2003 case Intrinsic::riscv_vssseg5:
2004 case Intrinsic::riscv_vssseg6:
2005 case Intrinsic::riscv_vssseg7:
2006 case Intrinsic::riscv_vssseg8:
2007 case Intrinsic::riscv_vsoxseg2:
2008 case Intrinsic::riscv_vsoxseg3:
2009 case Intrinsic::riscv_vsoxseg4:
2010 case Intrinsic::riscv_vsoxseg5:
2011 case Intrinsic::riscv_vsoxseg6:
2012 case Intrinsic::riscv_vsoxseg7:
2013 case Intrinsic::riscv_vsoxseg8:
2014 case Intrinsic::riscv_vsuxseg2:
2015 case Intrinsic::riscv_vsuxseg3:
2016 case Intrinsic::riscv_vsuxseg4:
2017 case Intrinsic::riscv_vsuxseg5:
2018 case Intrinsic::riscv_vsuxseg6:
2019 case Intrinsic::riscv_vsuxseg7:
2020 case Intrinsic::riscv_vsuxseg8:
2021 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
2024 case Intrinsic::riscv_vssseg2_mask:
2025 case Intrinsic::riscv_vssseg3_mask:
2026 case Intrinsic::riscv_vssseg4_mask:
2027 case Intrinsic::riscv_vssseg5_mask:
2028 case Intrinsic::riscv_vssseg6_mask:
2029 case Intrinsic::riscv_vssseg7_mask:
2030 case Intrinsic::riscv_vssseg8_mask:
2031 case Intrinsic::riscv_vsoxseg2_mask:
2032 case Intrinsic::riscv_vsoxseg3_mask:
2033 case Intrinsic::riscv_vsoxseg4_mask:
2034 case Intrinsic::riscv_vsoxseg5_mask:
2035 case Intrinsic::riscv_vsoxseg6_mask:
2036 case Intrinsic::riscv_vsoxseg7_mask:
2037 case Intrinsic::riscv_vsoxseg8_mask:
2038 case Intrinsic::riscv_vsuxseg2_mask:
2039 case Intrinsic::riscv_vsuxseg3_mask:
2040 case Intrinsic::riscv_vsuxseg4_mask:
2041 case Intrinsic::riscv_vsuxseg5_mask:
2042 case Intrinsic::riscv_vsuxseg6_mask:
2043 case Intrinsic::riscv_vsuxseg7_mask:
2044 case Intrinsic::riscv_vsuxseg8_mask:
2045 return SetRVVLoadStoreInfo(
I.arg_size() - 5,
2099 if (Subtarget.is64Bit() || !SrcTy->isIntegerTy() || !DstTy->
isIntegerTy())
2101 unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
2103 return (SrcBits == 64 && DestBits == 32);
2114 return (SrcBits == 64 && DestBits == 32);
2120 if (Subtarget.hasVInstructions() &&
2125 if (SrcBits == DestBits * 2) {
2137 EVT MemVT = LD->getMemoryVT();
2138 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
2148 return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
2156 return Subtarget.hasCTZLike();
2160 return Subtarget.hasCLZLike();
2171 if (!Subtarget.hasBEXTILike())
2176 return !Mask->getValue().isSignedIntN(12) && Mask->getValue().isPowerOf2();
2180 EVT VT =
Y.getValueType();
2185 return (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
2190 EVT VT =
Y.getValueType();
2195 return Subtarget.hasStdExtZvkb();
2200 if (Subtarget.hasStdExtZbs())
2201 return X.getValueType().isScalarInteger();
2204 if (Subtarget.hasVendorXTHeadBs())
2205 return C !=
nullptr;
2207 return C &&
C->getAPIntValue().ule(10);
2211 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
2217 if (!VT.
isVector() || !Subtarget.hasVInstructions())
2228 assert(Ty->isIntegerTy());
2230 unsigned BitSize = Ty->getIntegerBitWidth();
2231 if (BitSize > Subtarget.getXLen())
2235 int64_t Val = Imm.getSExtValue();
2243 if (!Subtarget.enableUnalignedScalarMem())
2253 return Seq.
size() <= Subtarget.getMaxBuildIntsCost();
2259 unsigned OldShiftOpcode,
unsigned NewShiftOpcode,
2266 if (XC && OldShiftOpcode ==
ISD::SRL && XC->isOne())
2314 if (!Subtarget.hasStdExtZfa())
2317 bool IsSupportedVT =
false;
2318 if (VT == MVT::f16) {
2319 IsSupportedVT = Subtarget.hasStdExtZfh() || Subtarget.hasStdExtZvfh();
2320 }
else if (VT == MVT::f32) {
2321 IsSupportedVT =
true;
2322 }
else if (VT == MVT::f64) {
2323 assert(Subtarget.hasStdExtD() &&
"Expect D extension");
2324 IsSupportedVT =
true;
2334 bool ForCodeSize)
const {
2335 bool IsLegalVT =
false;
2337 IsLegalVT = Subtarget.hasStdExtZfhminOrZhinxmin();
2338 else if (VT == MVT::f32)
2339 IsLegalVT = Subtarget.hasStdExtFOrZfinx();
2340 else if (VT == MVT::f64)
2341 IsLegalVT = Subtarget.hasStdExtDOrZdinx();
2342 else if (VT == MVT::bf16)
2343 IsLegalVT = Subtarget.hasStdExtZfbfmin();
2359 return Imm.isZero();
2363 if (Imm.isNegZero())
2368 const int FmvCost = Subtarget.hasStdExtZfinx() ? 0 : 1;
2371 Subtarget.getXLen(), Subtarget);
2377 unsigned Index)
const {
2394 if (EltVT == MVT::i1)
2400 unsigned MinVLen = Subtarget.getRealMinVLen();
2407 if (Index + ResElts <= MinVLMAX && Index < 31)
2416 return (ResElts * 2) == SrcElts && (Index == 0 || Index == ResElts);
2424 if (VT == MVT::f16 && Subtarget.hasStdExtFOrZfinx() &&
2425 !Subtarget.hasStdExtZfhminOrZhinxmin())
2435 std::optional<MVT> RegisterVT)
const {
2437 if (VT == (Subtarget.is64Bit() ? MVT::i128 : MVT::i64) && RegisterVT &&
2438 *RegisterVT == MVT::Untyped)
2449 if (VT == MVT::f16 && Subtarget.hasStdExtFOrZfinx() &&
2450 !Subtarget.hasStdExtZfhminOrZhinxmin())
2458 unsigned &NumIntermediates,
MVT &RegisterVT)
const {
2460 Context, CC, VT, IntermediateVT, NumIntermediates, RegisterVT);
2478 !Subtarget.hasVendorXAndesPerf()) {
2484 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
2498 int64_t
C = RHSC->getSExtValue();
2508 if ((Subtarget.hasVendorXqcicm() || Subtarget.hasVendorXqcicli()) &&
2534 if ((Subtarget.hasVendorXqcicm() || Subtarget.hasVendorXqcicli()) &&
2569 if (VT.
SimpleTy >= MVT::riscv_nxv1i8x2 &&
2570 VT.
SimpleTy <= MVT::riscv_nxv1i8x8)
2572 if (VT.
SimpleTy >= MVT::riscv_nxv2i8x2 &&
2573 VT.
SimpleTy <= MVT::riscv_nxv2i8x8)
2575 if (VT.
SimpleTy >= MVT::riscv_nxv4i8x2 &&
2576 VT.
SimpleTy <= MVT::riscv_nxv4i8x8)
2578 if (VT.
SimpleTy >= MVT::riscv_nxv8i8x2 &&
2579 VT.
SimpleTy <= MVT::riscv_nxv8i8x8)
2581 if (VT.
SimpleTy >= MVT::riscv_nxv16i8x2 &&
2582 VT.
SimpleTy <= MVT::riscv_nxv16i8x4)
2584 if (VT.
SimpleTy == MVT::riscv_nxv32i8x2)
2594 switch (KnownSize) {
2622 return RISCV::VRRegClassID;
2624 return RISCV::VRM2RegClassID;
2626 return RISCV::VRM4RegClassID;
2628 return RISCV::VRM8RegClassID;
2636 static_assert(RISCV::sub_vrm1_7 == RISCV::sub_vrm1_0 + 7,
2637 "Unexpected subreg numbering");
2638 return RISCV::sub_vrm1_0 + Index;
2641 static_assert(RISCV::sub_vrm2_3 == RISCV::sub_vrm2_0 + 3,
2642 "Unexpected subreg numbering");
2643 return RISCV::sub_vrm2_0 + Index;
2646 static_assert(RISCV::sub_vrm4_1 == RISCV::sub_vrm4_0 + 1,
2647 "Unexpected subreg numbering");
2648 return RISCV::sub_vrm4_0 + Index;
2656 unsigned RegsPerField =
2659 switch (RegsPerField) {
2662 return RISCV::VRN2M1RegClassID;
2664 return RISCV::VRN3M1RegClassID;
2666 return RISCV::VRN4M1RegClassID;
2668 return RISCV::VRN5M1RegClassID;
2670 return RISCV::VRN6M1RegClassID;
2672 return RISCV::VRN7M1RegClassID;
2674 return RISCV::VRN8M1RegClassID;
2678 return RISCV::VRN2M2RegClassID;
2680 return RISCV::VRN3M2RegClassID;
2682 return RISCV::VRN4M2RegClassID;
2686 return RISCV::VRN2M4RegClassID;
2694 return RISCV::VRRegClassID;
2703std::pair<unsigned, unsigned>
2705 MVT VecVT,
MVT SubVecVT,
unsigned InsertExtractIdx,
2707 static_assert((RISCV::VRM8RegClassID > RISCV::VRM4RegClassID &&
2708 RISCV::VRM4RegClassID > RISCV::VRM2RegClassID &&
2709 RISCV::VRM2RegClassID > RISCV::VRRegClassID),
2710 "Register classes not ordered");
2717 if (VecRegClassID == SubRegClassID)
2718 return {RISCV::NoSubRegister, 0};
2721 "Only allow scalable vector subvector.");
2723 "Invalid vector tuple insert/extract for vector and subvector with "
2734 unsigned SubRegIdx = RISCV::NoSubRegister;
2735 for (
const unsigned RCID :
2736 {RISCV::VRM4RegClassID, RISCV::VRM2RegClassID, RISCV::VRRegClassID})
2737 if (VecRegClassID > RCID && SubRegClassID <= RCID) {
2741 SubRegIdx =
TRI->composeSubRegIndices(SubRegIdx,
2746 return {SubRegIdx, InsertExtractIdx};
2751bool RISCVTargetLowering::mergeStoresAfterLegalization(
EVT VT)
const {
2761 return Subtarget.is64Bit() ? Subtarget.hasVInstructionsI64() :
true;
2765 return Subtarget.hasVInstructions();
2767 return Subtarget.hasVInstructionsI64();
2769 return Subtarget.hasVInstructionsF16Minimal();
2771 return Subtarget.hasVInstructionsBF16Minimal();
2773 return Subtarget.hasVInstructionsF32();
2775 return Subtarget.hasVInstructionsF64();
2789 "Unexpected opcode");
2791 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
2793 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
2796 return Op.getOperand(
II->VLOperand + 1 + HasChain);
2870bool RISCVTargetLowering::useRVVForFixedLengthVectorVT(
MVT VT)
const {
2871 return ::useRVVForFixedLengthVectorVT(VT, Subtarget);
2880 "Expected legal fixed length vector!");
2883 unsigned MaxELen = Subtarget.
getELen();
2917 return ::getContainerForFixedLengthVector(*
this, VT,
getSubtarget());
2924 "Expected to convert into a scalable vector!");
2925 assert(V.getValueType().isFixedLengthVector() &&
2926 "Expected a fixed length vector operand!");
2935 "Expected to convert into a fixed length vector!");
2936 assert(V.getValueType().isScalableVector() &&
2937 "Expected a scalable vector operand!");
2956 return DAG.
getNode(RISCVISD::VMSET_VL,
DL, MaskVT, VL);
2959static std::pair<SDValue, SDValue>
2968static std::pair<SDValue, SDValue>
2981static std::pair<SDValue, SDValue>
2998std::pair<unsigned, unsigned>
3006 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
3010 unsigned VectorBitsMin = Subtarget.getRealMinVLen();
3014 return std::make_pair(MinVLMAX, MaxVLMAX);
3026 EVT VT,
unsigned DefinedValues)
const {
3035 unsigned DLenFactor = Subtarget.getDLenFactor();
3040 std::tie(LMul, Fractional) =
3043 Cost = LMul <= DLenFactor ? (DLenFactor / LMul) : 1;
3045 Cost = (LMul * DLenFactor);
3059 bool Log2CostModel =
3061 if (Log2CostModel && LMULCost.isValid()) {
3062 unsigned Log =
Log2_64(LMULCost.getValue());
3064 return LMULCost * Log;
3066 return LMULCost * LMULCost;
3097 Op.getValueType() == MVT::bf16) {
3098 bool IsStrict =
Op->isStrictFPOpcode();
3103 {Op.getOperand(0), Op.getOperand(1)});
3105 {
Op.getValueType(), MVT::Other},
3111 DAG.
getNode(
Op.getOpcode(),
DL, MVT::f32,
Op.getOperand(0)),
3126 MVT DstVT =
Op.getSimpleValueType();
3135 Src.getValueType() == MVT::bf16) {
3141 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
3142 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
3143 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
3150 Opc,
DL, DstVT, Src,
3153 if (
Opc == RISCVISD::FCVT_WU_RV64)
3164 MVT SrcVT = Src.getSimpleValueType();
3170 if (SatVT != DstEltVT)
3173 MVT DstContainerVT = DstVT;
3174 MVT SrcContainerVT = SrcVT;
3180 "Expected same element count");
3189 {Src, Src, DAG.getCondCode(ISD::SETNE),
3190 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
3194 if (DstEltSize > (2 * SrcEltSize)) {
3197 Src = DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, InterVT, Src, Mask, VL);
3200 MVT CvtContainerVT = DstContainerVT;
3201 MVT CvtEltVT = DstEltVT;
3202 if (SrcEltSize > (2 * DstEltSize)) {
3208 IsSigned ? RISCVISD::VFCVT_RTZ_X_F_VL : RISCVISD::VFCVT_RTZ_XU_F_VL;
3211 while (CvtContainerVT != DstContainerVT) {
3215 unsigned ClipOpc = IsSigned ? RISCVISD::TRUNCATE_VECTOR_VL_SSAT
3216 : RISCVISD::TRUNCATE_VECTOR_VL_USAT;
3217 Res = DAG.
getNode(ClipOpc,
DL, CvtContainerVT, Res, Mask, VL);
3221 RISCVISD::VMV_V_X_VL,
DL, DstContainerVT, DAG.
getUNDEF(DstContainerVT),
3223 Res = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, DstContainerVT, IsNan, SplatZero,
3224 Res, DAG.
getUNDEF(DstContainerVT), VL);
3234 bool IsStrict =
Op->isStrictFPOpcode();
3235 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
3245 {
Op.getOperand(0), SrcVal});
3246 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
3247 {Ext.getValue(1), Ext.getValue(0)});
3250 DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, SrcVal));
3259 case ISD::FROUNDEVEN:
3261 case ISD::VP_FROUNDEVEN:
3265 case ISD::VP_FROUNDTOZERO:
3269 case ISD::VP_FFLOOR:
3281 case ISD::VP_FROUND:
3291 case ISD::VP_LLRINT:
3305 MVT VT =
Op.getSimpleValueType();
3315 MVT ContainerVT = VT;
3322 if (
Op->isVPOpcode()) {
3323 Mask =
Op.getOperand(1);
3327 VL =
Op.getOperand(2);
3333 SDValue Abs = DAG.
getNode(RISCVISD::FABS_VL,
DL, ContainerVT, Src, Mask, VL);
3346 DAG.
getUNDEF(ContainerVT), MaxValNode, VL);
3351 DAG.
getNode(RISCVISD::SETCC_VL,
DL, SetccVT,
3360 switch (
Op.getOpcode()) {
3368 case ISD::VP_FFLOOR:
3370 case ISD::FROUNDEVEN:
3371 case ISD::VP_FROUND:
3372 case ISD::VP_FROUNDEVEN:
3373 case ISD::VP_FROUNDTOZERO: {
3376 Truncated = DAG.
getNode(RISCVISD::VFCVT_RM_X_F_VL,
DL, IntVT, Src, Mask,
3381 Truncated = DAG.
getNode(RISCVISD::VFCVT_RTZ_X_F_VL,
DL, IntVT, Src,
3384 case ISD::FNEARBYINT:
3385 case ISD::VP_FNEARBYINT:
3386 Truncated = DAG.
getNode(RISCVISD::VFROUND_NOEXCEPT_VL,
DL, ContainerVT, Src,
3392 if (Truncated.
getOpcode() != RISCVISD::VFROUND_NOEXCEPT_VL)
3393 Truncated = DAG.
getNode(RISCVISD::SINT_TO_FP_VL,
DL, ContainerVT, Truncated,
3397 Truncated = DAG.
getNode(RISCVISD::FCOPYSIGN_VL,
DL, ContainerVT, Truncated,
3398 Src, Src, Mask, VL);
3413 MVT VT =
Op.getSimpleValueType();
3417 MVT ContainerVT = VT;
3429 MVT MaskVT = Mask.getSimpleValueType();
3432 {Chain, Src, Src, DAG.getCondCode(ISD::SETUNE),
3433 DAG.getUNDEF(MaskVT), Mask, VL});
3435 Src = DAG.
getNode(RISCVISD::STRICT_FADD_VL,
DL,
3437 {Chain, Src, Src, Src, Unorder, VL});
3441 SDValue Abs = DAG.
getNode(RISCVISD::FABS_VL,
DL, ContainerVT, Src, Mask, VL);
3454 DAG.
getUNDEF(ContainerVT), MaxValNode, VL);
3458 RISCVISD::SETCC_VL,
DL, MaskVT,
3466 switch (
Op.getOpcode()) {
3476 RISCVISD::STRICT_VFCVT_RM_X_F_VL,
DL, DAG.
getVTList(IntVT, MVT::Other),
3477 {Chain, Src, Mask, DAG.getTargetConstant(FRM, DL, XLenVT), VL});
3482 DAG.
getNode(RISCVISD::STRICT_VFCVT_RTZ_X_F_VL,
DL,
3483 DAG.
getVTList(IntVT, MVT::Other), Chain, Src, Mask, VL);
3486 Truncated = DAG.
getNode(RISCVISD::STRICT_VFROUND_NOEXCEPT_VL,
DL,
3487 DAG.
getVTList(ContainerVT, MVT::Other), Chain, Src,
3495 Truncated = DAG.
getNode(RISCVISD::STRICT_SINT_TO_FP_VL,
DL,
3496 DAG.
getVTList(ContainerVT, MVT::Other), Chain,
3497 Truncated, Mask, VL);
3502 Truncated = DAG.
getNode(RISCVISD::FCOPYSIGN_VL,
DL, ContainerVT, Truncated,
3503 Src, Src, Mask, VL);
3513 MVT VT =
Op.getSimpleValueType();
3534 return DAG.
getNode(RISCVISD::FROUND,
DL, VT, Src, MaxValNode,
3542 MVT DstVT =
Op.getSimpleValueType();
3544 MVT SrcVT = Src.getSimpleValueType();
3549 MVT DstContainerVT = DstVT;
3550 MVT SrcContainerVT = SrcVT;
3562 if (SrcElemType == MVT::f16 || SrcElemType == MVT::bf16) {
3564 Src = DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, F32VT, Src, Mask, VL);
3568 DAG.
getNode(RISCVISD::VFCVT_RM_X_F_VL,
DL, DstContainerVT, Src, Mask,
3588 return DAG.
getNode(RISCVISD::VSLIDEDOWN_VL,
DL, VT,
Ops);
3600 return DAG.
getNode(RISCVISD::VSLIDEUP_VL,
DL, VT,
Ops);
3625 return std::nullopt;
3643 unsigned EltSizeInBits) {
3646 return std::nullopt;
3647 bool IsInteger =
Op.getValueType().isInteger();
3649 std::optional<unsigned> SeqStepDenom;
3650 std::optional<APInt> SeqStepNum;
3651 std::optional<APInt> SeqAddend;
3652 std::optional<std::pair<APInt, unsigned>> PrevElt;
3653 assert(EltSizeInBits >=
Op.getValueType().getScalarSizeInBits());
3658 const unsigned OpSize =
Op.getScalarValueSizeInBits();
3659 for (
auto [Idx, Elt] :
enumerate(
Op->op_values())) {
3660 if (Elt.isUndef()) {
3661 Elts[Idx] = std::nullopt;
3665 Elts[Idx] = Elt->getAsAPIntVal().trunc(OpSize).zext(EltSizeInBits);
3670 return std::nullopt;
3671 Elts[Idx] = *ExactInteger;
3675 for (
auto [Idx, Elt] :
enumerate(Elts)) {
3684 unsigned IdxDiff = Idx - PrevElt->second;
3685 APInt ValDiff = *Elt - PrevElt->first;
3693 int64_t Remainder = ValDiff.
srem(IdxDiff);
3698 return std::nullopt;
3699 ValDiff = ValDiff.
sdiv(IdxDiff);
3704 SeqStepNum = ValDiff;
3705 else if (ValDiff != SeqStepNum)
3706 return std::nullopt;
3709 SeqStepDenom = IdxDiff;
3710 else if (IdxDiff != *SeqStepDenom)
3711 return std::nullopt;
3715 if (!PrevElt || PrevElt->first != *Elt)
3716 PrevElt = std::make_pair(*Elt, Idx);
3720 if (!SeqStepNum || !SeqStepDenom)
3721 return std::nullopt;
3725 for (
auto [Idx, Elt] :
enumerate(Elts)) {
3729 (
APInt(EltSizeInBits, Idx,
false,
true) *
3731 .sdiv(*SeqStepDenom);
3733 APInt Addend = *Elt - ExpectedVal;
3736 else if (Addend != SeqAddend)
3737 return std::nullopt;
3740 assert(SeqAddend &&
"Must have an addend if we have a step");
3742 return VIDSequence{SeqStepNum->getSExtValue(), *SeqStepDenom,
3743 SeqAddend->getSExtValue()};
3758 if (EltTy == MVT::i1 ||
3761 MVT SrcVT = Src.getSimpleValueType();
3777 MVT ContainerVT = VT;
3781 MVT SrcContainerVT = SrcVT;
3796 SDValue Gather = DAG.
getNode(RISCVISD::VRGATHER_VX_VL,
DL, ContainerVT, Src,
3797 Idx, DAG.
getUNDEF(ContainerVT), Mask, VL);
3805 MVT VT =
Op.getSimpleValueType();
3814 int64_t StepNumerator = SimpleVID->StepNumerator;
3815 unsigned StepDenominator = SimpleVID->StepDenominator;
3816 int64_t Addend = SimpleVID->Addend;
3818 assert(StepNumerator != 0 &&
"Invalid step");
3819 bool Negate =
false;
3820 int64_t SplatStepVal = StepNumerator;
3824 if (StepNumerator != 1 && StepNumerator !=
INT64_MIN &&
3826 Negate = StepNumerator < 0;
3828 SplatStepVal =
Log2_64(std::abs(StepNumerator));
3838 (SplatStepVal >= 0 || StepDenominator == 1) &&
isInt<32>(Addend)) {
3841 MVT VIDContainerVT =
3849 if ((StepOpcode ==
ISD::MUL && SplatStepVal != 1) ||
3850 (StepOpcode ==
ISD::SHL && SplatStepVal != 0)) {
3852 VID = DAG.
getNode(StepOpcode,
DL, VIDVT, VID, SplatStep);
3854 if (StepDenominator != 1) {
3859 if (Addend != 0 || Negate) {
3885 MVT VT =
Op.getSimpleValueType();
3894 unsigned NumElts =
Op.getNumOperands();
3897 unsigned MostCommonCount = 0;
3899 unsigned NumUndefElts =
3907 unsigned NumScalarLoads = 0;
3913 unsigned &
Count = ValueCounts[V];
3916 NumScalarLoads += !CFP->isExactlyValue(+0.0);
3921 if (++
Count >= MostCommonCount) {
3923 MostCommonCount =
Count;
3927 assert(DominantValue &&
"Not expecting an all-undef BUILD_VECTOR");
3928 unsigned NumDefElts = NumElts - NumUndefElts;
3929 unsigned DominantValueCountThreshold = NumDefElts <= 2 ? 0 : NumDefElts - 2;
3935 ((MostCommonCount > DominantValueCountThreshold) ||
3947 if (
SDValue LastOp =
Op->getOperand(
Op->getNumOperands() - 1);
3948 !LastOp.isUndef() && ValueCounts[LastOp] == 1 &&
3949 LastOp != DominantValue) {
3952 VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1DOWN_VL : RISCVISD::VSLIDE1DOWN_VL;
3958 Processed.
insert(LastOp);
3964 if (V.isUndef() || !Processed.
insert(V).second)
3966 if (ValueCounts[V] == 1) {
3974 return DAG.getConstant(V == V1, DL, XLenVT);
3990 MVT VT =
Op.getSimpleValueType();
3999 unsigned NumElts =
Op.getNumOperands();
4020 unsigned NumViaIntegerBits = std::clamp(NumElts, 8u, Subtarget.
getXLen());
4021 NumViaIntegerBits = std::min(NumViaIntegerBits, Subtarget.
getELen());
4029 unsigned IntegerViaVecElts =
divideCeil(NumElts, NumViaIntegerBits);
4030 MVT IntegerViaVecVT =
4035 unsigned BitPos = 0, IntegerEltIdx = 0;
4038 for (
unsigned I = 0;
I < NumElts;) {
4040 bool BitValue = !V.isUndef() && V->getAsZExtVal();
4041 Bits |= ((
uint64_t)BitValue << BitPos);
4047 if (
I % NumViaIntegerBits == 0 ||
I == NumElts) {
4048 if (NumViaIntegerBits <= 32)
4051 Elts[IntegerEltIdx] = Elt;
4060 if (NumElts < NumViaIntegerBits) {
4064 assert(IntegerViaVecVT == MVT::v1i8 &&
"Unexpected mask vector type");
4079 : RISCVISD::VMV_V_X_VL;
4099 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32) &&
4100 "Unexpected sequence type");
4104 unsigned ViaVecLen =
4112 const auto &SeqV =
OpIdx.value();
4113 if (!SeqV.isUndef())
4115 ((SeqV->getAsZExtVal() & EltMask) << (
OpIdx.index() * EltBitSize));
4121 if (ViaIntVT == MVT::i32)
4144 BV->getRepeatedSequence(Sequence) &&
4145 (Sequence.size() * EltBitSize) <= Subtarget.
getELen()) {
4146 unsigned SeqLen = Sequence.size();
4148 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32 ||
4149 ViaIntVT == MVT::i64) &&
4150 "Unexpected sequence type");
4155 const unsigned RequiredVL = NumElts / SeqLen;
4156 const unsigned ViaVecLen =
4158 NumElts : RequiredVL;
4161 unsigned EltIdx = 0;
4166 for (
const auto &SeqV : Sequence) {
4167 if (!SeqV.isUndef())
4169 ((SeqV->getAsZExtVal() & EltMask) << (EltIdx * EltBitSize));
4176 if (ViaIntVT == MVT::i32)
4183 (!Subtarget.
is64Bit() && ViaIntVT == MVT::i64)) &&
4184 "Unexpected bitcast sequence");
4188 MVT ViaContainerVT =
4191 DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ViaContainerVT,
4195 if (ViaVecLen != RequiredVL)
4214 Source, DAG, Subtarget);
4215 SDValue Res = DAG.
getNode(RISCVISD::VSEXT_VL,
DL, ContainerVT, Source, Mask, VL);
4234 return RISCV::PACKH;
4236 return Subtarget.
is64Bit() ? RISCV::PACKW : RISCV::PACK;
4251 MVT VT =
Op.getSimpleValueType();
4259 if (!Subtarget.hasStdExtZbb() || !Subtarget.hasStdExtZba())
4264 if (ElemSizeInBits >= std::min(Subtarget.
getELen(), Subtarget.
getXLen()) ||
4278 if (Subtarget.hasStdExtZbkb())
4283 ElemDL, XLenVT,
A,
B),
4295 NewOperands.
reserve(NumElts / 2);
4297 NewOperands.
push_back(pack(
Op.getOperand(i),
Op.getOperand(i + 1)));
4301 return DAG.
getNode(ISD::BITCAST,
DL, VT,
4307 MVT VT =
Op.getSimpleValueType();
4318 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) || EltVT == MVT::bf16) {
4323 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4324 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin())) {
4334 NewOps[
I] = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Elem);
4384 [](
const SDUse &U) { return U.get().isUndef(); })) {
4425 auto OneVRegOfOps =
ArrayRef(BuildVectorOps).slice(i, ElemsPerVReg);
4429 unsigned InsertIdx = (i / ElemsPerVReg) * NumOpElts;
4451 unsigned NumUndefElts =
4453 unsigned NumDefElts = NumElts - NumUndefElts;
4454 if (NumDefElts >= 8 && NumDefElts > NumElts / 2 &&
4461 for (
const auto &[Idx, U] :
enumerate(
Op->ops())) {
4463 if (Idx < NumElts / 2) {
4470 bool SelectMaskVal = (Idx < NumElts / 2);
4473 assert(SubVecAOps.
size() == NumElts && SubVecBOps.
size() == NumElts &&
4474 MaskVals.
size() == NumElts);
4509 unsigned UndefCount = 0;
4516 LinearBudget -= PerSlideCost;
4519 LinearBudget -= PerSlideCost;
4522 LinearBudget -= PerSlideCost;
4525 if (LinearBudget < 0)
4530 "Illegal type which will result in reserved encoding");
4546 bool SlideUp =
false;
4571 if (EVecEltVT != ContainerEltVT)
4620 Vec = getVSlide(ContainerVT, DAG.
getUNDEF(ContainerVT), Vec,
Offset, Mask,
4627 Opcode = SlideUp ? RISCVISD::VFSLIDE1UP_VL : RISCVISD::VFSLIDE1DOWN_VL;
4629 Opcode = SlideUp ? RISCVISD::VSLIDE1UP_VL : RISCVISD::VSLIDE1DOWN_VL;
4638 Vec = getVSlide(ContainerVT, DAG.
getUNDEF(ContainerVT), Vec,
Offset, Mask,
4654 if ((LoC >> 31) == HiC)
4655 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4667 auto InterVec = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, InterVT,
4669 return DAG.
getNode(ISD::BITCAST,
DL, VT, InterVec);
4676 Hi.getConstantOperandVal(1) == 31)
4677 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4682 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4685 return DAG.
getNode(RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL,
DL, VT, Passthru,
Lo,
4695 assert(Scalar.getValueType() == MVT::i64 &&
"Unexpected VT!");
4707 bool HasPassthru = Passthru && !Passthru.
isUndef();
4708 if (!HasPassthru && !Passthru)
4715 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
4716 EltVT == MVT::bf16) {
4717 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4718 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
4719 Scalar = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Scalar);
4721 Scalar = DAG.
getNode(ISD::BITCAST,
DL, MVT::i16, Scalar);
4723 Passthru = DAG.
getNode(ISD::BITCAST,
DL, IVT, Passthru);
4728 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL, VT, Passthru, Scalar, VL);
4732 if (Scalar.getValueType().bitsLE(XLenVT)) {
4739 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4740 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru, Scalar, VL);
4743 assert(XLenVT == MVT::i32 && Scalar.getValueType() == MVT::i64 &&
4744 "Unexpected scalar for splat lowering!");
4747 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, VT, Passthru,
4773 MVT ExtractedContainerVT = ExtractedVT;
4776 DAG, ExtractedContainerVT, Subtarget);
4778 ExtractedVal, DAG, Subtarget);
4780 if (ExtractedContainerVT.
bitsLE(VT))
4792 if (!Scalar.getValueType().bitsLE(XLenVT))
4795 VT,
DL, DAG, Subtarget);
4803 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4844 Src && Src.
getValueType().getVectorNumElements() == (NumElts * 2))
4861 !Subtarget.hasVendorXRivosVizip())
4864 int Size = Mask.size();
4866 assert(
Size == (
int)NumElts &&
"Unexpected mask size");
4872 EvenSrc = StartIndexes[0];
4873 OddSrc = StartIndexes[1];
4876 if (EvenSrc != 0 && OddSrc != 0)
4886 int HalfNumElts = NumElts / 2;
4887 return ((EvenSrc % HalfNumElts) == 0) && ((OddSrc % HalfNumElts) == 0);
4892 std::array<std::pair<int, int>, 2> &SrcInfo) {
4897 if (SrcInfo[0].second == 0 && SrcInfo[1].second == 0)
4901 if ((SrcInfo[0].second > 0 && SrcInfo[1].second < 0) ||
4902 SrcInfo[1].second == 0)
4904 assert(SrcInfo[0].first != -1 &&
"Must find one slide");
4912 if (SrcInfo[1].first == -1)
4914 return SrcInfo[0].second < 0 && SrcInfo[1].second > 0 &&
4915 SrcInfo[1].second - SrcInfo[0].second == (int)NumElts;
4920 bool RequiredPolarity) {
4921 int NumElts = Mask.size();
4922 for (
const auto &[Idx, M] :
enumerate(Mask)) {
4925 int Src = M >= NumElts;
4926 int Diff = (int)Idx - (M % NumElts);
4927 bool C = Src == SrcInfo[1].first && Diff == SrcInfo[1].second;
4928 assert(
C != (Src == SrcInfo[0].first && Diff == SrcInfo[0].second) &&
4929 "Must match exactly one of the two slides");
4930 if (RequiredPolarity != (
C == (Idx / Factor) % 2))
4941static bool isZipEven(
const std::array<std::pair<int, int>, 2> &SrcInfo,
4943 Factor = SrcInfo[1].second;
4945 Mask.size() % Factor == 0 &&
4956static bool isZipOdd(
const std::array<std::pair<int, int>, 2> &SrcInfo,
4958 Factor = -SrcInfo[1].second;
4960 Mask.size() % Factor == 0 &&
4973 ElementCount SrcEC = Src.getValueType().getVectorElementCount();
4980 unsigned Shift = Index * EltBits;
5005 std::optional<int> SplatIdx;
5007 if (M == -1 ||
I == (
unsigned)M)
5009 if (SplatIdx && *SplatIdx != M)
5018 for (
int MaskIndex : Mask) {
5019 bool SelectMaskVal = MaskIndex == *SplatIdx;
5022 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
5047 auto findNonEXTRACT_SUBVECTORParent =
5048 [](
SDValue Parent) -> std::pair<SDValue, uint64_t> {
5053 Parent.getOperand(0).getSimpleValueType().isFixedLengthVector()) {
5054 Offset += Parent.getConstantOperandVal(1);
5055 Parent = Parent.getOperand(0);
5057 return std::make_pair(Parent,
Offset);
5060 auto [V1Src, V1IndexOffset] = findNonEXTRACT_SUBVECTORParent(V1);
5061 auto [V2Src, V2IndexOffset] = findNonEXTRACT_SUBVECTORParent(V2);
5070 for (
size_t i = 0; i != NewMask.
size(); ++i) {
5071 if (NewMask[i] == -1)
5074 if (
static_cast<size_t>(NewMask[i]) < NewMask.
size()) {
5075 NewMask[i] = NewMask[i] + V1IndexOffset;
5079 NewMask[i] = NewMask[i] - NewMask.
size() + V2IndexOffset;
5085 if (NewMask[0] <= 0)
5089 for (
unsigned i = 1; i != NewMask.
size(); ++i)
5090 if (NewMask[i - 1] + 1 != NewMask[i])
5094 MVT SrcVT = Src.getSimpleValueType();
5123 int NumSubElts, Index;
5128 bool OpsSwapped = Mask[Index] < (int)NumElts;
5129 SDValue InPlace = OpsSwapped ? V2 : V1;
5130 SDValue ToInsert = OpsSwapped ? V1 : V2;
5141 if (NumSubElts + Index >= (
int)NumElts)
5152 Res = DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, ContainerVT, InPlace, ToInsert,
5155 Res =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, InPlace, ToInsert,
5167 bool OpsSwapped =
false;
5182 const unsigned E = Mask.size() - ((
Offset > 0) ?
Offset : 0);
5183 for (
unsigned i = S; i !=
E; ++i)
5184 if (Mask[i] >= 0 && (
unsigned)Mask[i] !=
Base + i +
Offset)
5190 bool IsVSlidedown = isSlideMask(Mask, OpsSwapped ? 0 : NumElts, 1);
5191 if (!IsVSlidedown && !isSlideMask(Mask, OpsSwapped ? 0 : NumElts, -1))
5194 const int InsertIdx = Mask[IsVSlidedown ? (NumElts - 1) : 0];
5196 if (InsertIdx < 0 || InsertIdx / NumElts != (
unsigned)OpsSwapped)
5213 IsVSlidedown ? RISCVISD::VSLIDE1DOWN_VL : RISCVISD::VSLIDE1UP_VL,
DL,
5219 auto OpCode = IsVSlidedown ?
5220 (VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1DOWN_VL : RISCVISD::VSLIDE1DOWN_VL) :
5221 (VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1UP_VL : RISCVISD::VSLIDE1UP_VL);
5224 auto Vec = DAG.
getNode(OpCode,
DL, ContainerVT,
5227 Splat, TrueMask, VL);
5239 for (
unsigned i = 0; i < Mask.size(); i++)
5240 LaneIsUndef[i % Factor] &= (Mask[i] == -1);
5243 for (
unsigned i = 0; i < Factor; i++) {
5254 for (
unsigned i = 0; i < Mask.size() / Factor; i++) {
5255 unsigned j = i * Factor + Index;
5256 if (Mask[j] != -1 && (
unsigned)Mask[j] != i)
5265 assert(RISCVISD::RI_VZIPEVEN_VL ==
Opc || RISCVISD::RI_VZIPODD_VL ==
Opc ||
5266 RISCVISD::RI_VZIP2A_VL ==
Opc || RISCVISD::RI_VZIP2B_VL ==
Opc ||
5267 RISCVISD::RI_VUNZIP2A_VL ==
Opc || RISCVISD::RI_VUNZIP2B_VL ==
Opc);
5275 MVT ContainerVT = IntVT;
5282 MVT InnerVT = ContainerVT;
5286 (RISCVISD::RI_VUNZIP2A_VL ==
Opc || RISCVISD::RI_VUNZIP2B_VL ==
Opc)) {
5298 if (InnerVT.
bitsLT(ContainerVT))
5313 MVT VT = V.getSimpleValueType();
5328 EC.multiplyCoefficientBy(Factor));
5347 MVT VecContainerVT = VecVT;
5364 MVT WideContainerVT = WideVT;
5370 EvenV = DAG.
getBitcast(VecContainerVT, EvenV);
5377 if (Subtarget.hasStdExtZvbb()) {
5381 Interleaved = DAG.
getNode(RISCVISD::VWSLL_VL,
DL, WideContainerVT, OddV,
5382 OffsetVec, Passthru, Mask, VL);
5383 Interleaved = DAG.
getNode(RISCVISD::VWADDU_W_VL,
DL, WideContainerVT,
5384 Interleaved, EvenV, Passthru, Mask, VL);
5391 Interleaved = DAG.
getNode(RISCVISD::VWADDU_VL,
DL, WideContainerVT, EvenV,
5392 OddV, Passthru, Mask, VL);
5398 OddV, AllOnesVec, Passthru, Mask, VL);
5405 Interleaved = DAG.
getNode(RISCVISD::ADD_VL,
DL, WideContainerVT,
5406 Interleaved, OddsMul, Passthru, Mask, VL);
5413 Interleaved = DAG.
getBitcast(ResultContainerVT, Interleaved);
5459 if (ViaEltSize > NumElts)
5467 if (ViaEltSize > NumElts)
5473 if (ViaEltSize > NumElts)
5480 MVT &RotateVT,
unsigned &RotateAmt) {
5483 unsigned NumSubElts;
5485 NumElts, NumSubElts, RotateAmt))
5488 NumElts / NumSubElts);
5556 unsigned NumOfSrcRegs = NumElts / NumOpElts;
5557 unsigned NumOfDestRegs = NumElts / NumOpElts;
5566 Mask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs,
5567 [&]() {
Operands.emplace_back(); },
5568 [&](
ArrayRef<int> SrcSubMask,
unsigned SrcVecIdx,
unsigned DstVecIdx) {
5569 Operands.emplace_back().emplace_back(SrcVecIdx, UINT_MAX,
5572 [&](
ArrayRef<int> SrcSubMask,
unsigned Idx1,
unsigned Idx2,
bool NewReg) {
5577 assert(
Operands.size() == NumOfDestRegs &&
"Whole vector must be processed");
5582 unsigned NumShuffles = std::accumulate(
5589 for (const auto &P : Data) {
5590 unsigned Idx2 = std::get<1>(P);
5591 ArrayRef<int> Mask = std::get<2>(P);
5592 if (Idx2 != UINT_MAX)
5594 else if (ShuffleVectorInst::isIdentityMask(Mask, Mask.size()))
5599 if ((NumOfDestRegs > 2 && NumShuffles > NumOfDestRegs) ||
5600 (NumOfDestRegs <= 2 && NumShuffles >= 4))
5602 auto ExtractValue = [&, &DAG = DAG](
SDValue SrcVec,
unsigned ExtractIdx) {
5603 SDValue SubVec = DAG.getExtractSubvector(
DL, M1VT, SrcVec, ExtractIdx);
5607 auto PerformShuffle = [&, &DAG = DAG](
SDValue SubVec1,
SDValue SubVec2,
5609 SDValue SubVec = DAG.getVectorShuffle(OneRegVT,
DL, SubVec1, SubVec2, Mask);
5612 SDValue Vec = DAG.getUNDEF(ContainerVT);
5618 const auto &[Idx1, Idx2,
_] =
Data[
I];
5626 V = ExtractValue(Idx1 >= NumOfSrcRegs ? V2 : V1,
5627 (Idx1 % NumOfSrcRegs) * NumOpElts);
5628 if (Idx2 != UINT_MAX) {
5631 V = ExtractValue(Idx2 >= NumOfSrcRegs ? V2 : V1,
5632 (Idx2 % NumOfSrcRegs) * NumOpElts);
5636 for (
const auto &[Idx1, Idx2, Mask] :
Data) {
5638 SDValue V2 = Idx2 == UINT_MAX ? V1 : Values.
at(Idx2);
5639 V = PerformShuffle(V1, V2, Mask);
5643 unsigned InsertIdx =
I * NumOpElts;
5645 Vec = DAG.getInsertSubvector(
DL, Vec, V, InsertIdx);
5655 bool SawUndef =
false;
5656 for (
const auto &[Idx, M] :
enumerate(Mask)) {
5663 if (Idx > (
unsigned)M)
5696 for (
int Idx : Mask) {
5699 unsigned SrcIdx = Idx % Mask.size();
5700 int Src = (
uint32_t)Idx < Mask.size() ? 0 : 1;
5701 if (Srcs[SrcIdx] == -1)
5704 else if (Srcs[SrcIdx] != Src)
5710 for (
int Lane : Srcs) {
5723 for (
unsigned I = 0;
I < Mask.size();
I++) {
5727 NewMask[
I] = Mask[
I] % Mask.size();
5741 if ((M / Span) != (
int)(
I / Span))
5743 int SpanIdx =
I % Span;
5753 return all_of(Mask, [&](
const auto &Idx) {
return Idx == -1 || Idx < Span; });
5765 int SpanIdx =
I % Span;
5766 if (Mask[SpanIdx] != M)
5780 MVT VT =
Op.getSimpleValueType();
5788 if (ElementSize > 32)
5811 MVT VT =
Op.getSimpleValueType();
5839 auto [TrueMask, VL] = TrueMaskVL;
5854 V.getOperand(0).getSimpleValueType().getVectorNumElements();
5855 V = V.getOperand(
Offset / OpElements);
5885 MVT SplatVT = ContainerVT;
5888 if (SVT == MVT::bf16 ||
5889 (SVT == MVT::f16 && !Subtarget.hasStdExtZfh())) {
5898 V = DAG.
getLoad(SVT,
DL, Ld->getChain(), NewAddr,
5899 Ld->getPointerInfo().getWithOffset(
Offset),
5900 Ld->getBaseAlign(), Ld->getMemOperand()->
getFlags());
5903 Ld->getPointerInfo().getWithOffset(
Offset), SVT,
5905 Ld->getMemOperand()->getFlags());
5909 : RISCVISD::VMV_V_X_VL;
5917 assert(Lane < (
int)NumElts &&
"Unexpected lane!");
5920 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
5942 if (Subtarget.hasStdExtZvkb())
5958 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
5959 for (
unsigned Factor = 2; Factor <= MaxFactor; Factor <<= 1) {
5962 1 <
count_if(Mask, [](
int Idx) {
return Idx != -1; })) {
5966 [&Mask](
int Idx) {
return Idx < (int)Mask.size(); }) &&
5967 1 <
count_if(Mask, [&Mask](
int Idx) {
5968 return Idx >= (int)Mask.size();
5998 if (Subtarget.hasVendorXRivosVizip() &&
6000 1 <
count_if(Mask, [](
int Idx) {
return Idx != -1; })) {
6002 Index == 0 ? RISCVISD::RI_VUNZIP2A_VL : RISCVISD::RI_VUNZIP2B_VL;
6018 [&Mask](
int Idx) {
return Idx < (int)Mask.size(); }) &&
6020 [&Mask](
int Idx) {
return Idx >= (int)Mask.size(); })) {
6024 if (NumElts < MinVLMAX) {
6048 int EvenSrc, OddSrc;
6058 bool LaneIsUndef[2] = {
true,
true};
6059 for (
const auto &[Idx, M] :
enumerate(Mask))
6060 LaneIsUndef[Idx % 2] &= (M == -1);
6062 int Size = Mask.size();
6064 if (LaneIsUndef[0]) {
6067 assert(EvenSrc >= 0 &&
"Undef source?");
6068 EvenV = (EvenSrc /
Size) == 0 ? V1 : V2;
6072 if (LaneIsUndef[1]) {
6075 assert(OddSrc >= 0 &&
"Undef source?");
6076 OddV = (OddSrc /
Size) == 0 ? V1 : V2;
6082 if (Subtarget.hasVendorXRivosVizip()) {
6085 return lowerVZIP(RISCVISD::RI_VZIP2A_VL, EvenV, OddV,
DL, DAG, Subtarget);
6096 std::array<std::pair<int, int>, 2> SrcInfo;
6103 auto GetSourceFor = [&](
const std::pair<int, int> &
Info) {
6104 int SrcIdx =
Info.first;
6105 assert(SrcIdx == 0 || SrcIdx == 1);
6106 SDValue &Src = Sources[SrcIdx];
6108 SDValue SrcV = SrcIdx == 0 ? V1 : V2;
6113 auto GetSlide = [&](
const std::pair<int, int> &Src,
SDValue Mask,
6115 auto [TrueMask, VL] = TrueMaskVL;
6116 SDValue SrcV = GetSourceFor(Src);
6117 int SlideAmt = Src.second;
6118 if (SlideAmt == 0) {
6120 assert(Mask == TrueMask);
6127 return getVSlideup(DAG, Subtarget,
DL, ContainerVT, Passthru, SrcV,
6132 if (SrcInfo[1].first == -1) {
6134 Res = GetSlide(SrcInfo[0], TrueMask, Res);
6138 if (Subtarget.hasVendorXRivosVizip()) {
6139 bool TryWiden =
false;
6143 SDValue Src1 = SrcInfo[0].first == 0 ? V1 : V2;
6144 SDValue Src2 = SrcInfo[1].first == 0 ? V1 : V2;
6145 return lowerVZIP(RISCVISD::RI_VZIPEVEN_VL, Src1, Src2,
DL, DAG,
6150 if (
isZipOdd(SrcInfo, Mask, Factor)) {
6152 SDValue Src1 = SrcInfo[1].first == 0 ? V1 : V2;
6153 SDValue Src2 = SrcInfo[0].first == 0 ? V1 : V2;
6154 return lowerVZIP(RISCVISD::RI_VZIPODD_VL, Src1, Src2,
DL, DAG,
6172 for (
const auto &[Idx, M] :
enumerate(Mask)) {
6174 (SrcInfo[1].second > 0 && Idx < (
unsigned)SrcInfo[1].second)) {
6178 int Src = M >= (int)NumElts;
6179 int Diff = (int)Idx - (M % NumElts);
6180 bool C = Src == SrcInfo[1].first && Diff == SrcInfo[1].second;
6181 assert(
C ^ (Src == SrcInfo[0].first && Diff == SrcInfo[0].second) &&
6182 "Must match exactly one of the two slides");
6185 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
6192 Res = GetSlide(SrcInfo[0], TrueMask, Res);
6193 Res = GetSlide(SrcInfo[1], SelectMask, Res);
6198 assert(!V1.
isUndef() &&
"Unexpected shuffle canonicalization");
6213 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
6214 for (
unsigned Factor = 4; Factor <= MaxFactor; Factor <<= 1) {
6229 if (NumElts > MinVLMAX) {
6230 unsigned MaxIdx = 0;
6234 MaxIdx = std::max(std::max((
unsigned)
I, (
unsigned)M), MaxIdx);
6236 unsigned NewNumElts =
6238 if (NewNumElts != NumElts) {
6242 Mask.take_front(NewNumElts));
6259 for (
auto Idx : Mask) {
6262 assert(Idx >= 0 && (
unsigned)Idx < NumElts);
6272 any_of(Mask, [&](
const auto &Idx) {
return Idx > 255; })) {
6282 unsigned GatherVVOpc = RISCVISD::VRGATHER_VV_VL;
6288 GatherVVOpc = RISCVISD::VRGATHEREI16_VV_VL;
6297 GatherVVOpc = RISCVISD::VRGATHEREI16_VV_VL;
6301 MVT IndexContainerVT =
6306 for (
int MaskIndex : Mask) {
6307 bool IsLHSIndex = MaskIndex < (int)NumElts && MaskIndex >= 0;
6317 if (NumElts <= MinVLMAX) {
6319 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
6325 auto [InnerTrueMask, InnerVL] =
6337 for (
int i = 0; i <
N; i++) {
6341 DAG.
getNode(GatherVVOpc,
DL, M1VT, SubV1, SubIndex,
6342 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6359 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6361 for (
int i = 0; i <
N; i++)
6377 for (
int i = 0; i <
N; i++) {
6380 DAG.
getUNDEF(IndexContainerVT), LHSIndices,
6381 SlideAmt, TrueMask, VL);
6385 DAG.
getNode(GatherVVOpc,
DL, M1VT, SubV1, SubIndex,
6386 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6396 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
6406 for (
int MaskIndex : Mask) {
6407 bool IsLHSOrUndefIndex = MaskIndex < (int)NumElts;
6408 ShuffleMaskLHS.
push_back(IsLHSOrUndefIndex && MaskIndex >= 0
6410 ShuffleMaskRHS.
push_back(IsLHSOrUndefIndex ? -1 : (MaskIndex - NumElts));
6441 for (
int MaskIndex : Mask) {
6442 bool SelectMaskVal = (MaskIndex < (int)NumElts) ^ !SwapOps;
6446 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
6464 const unsigned NumElts = M.size();
6471 std::array<std::pair<int, int>, 2> SrcInfo;
6482RISCVTargetLowering::lowerCTLZ_CTTZ_ZERO_UNDEF(
SDValue Op,
6484 MVT VT =
Op.getSimpleValueType();
6488 MVT ContainerVT = VT;
6491 if (
Op->isVPOpcode()) {
6492 Mask =
Op.getOperand(1);
6496 VL =
Op.getOperand(2);
6502 MVT FloatEltVT = (EltSize >= 32) ? MVT::f64 :
MVT::f32;
6504 FloatEltVT = MVT::f32;
6511 "Expected legal float type!");
6518 }
else if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF) {
6521 Src = DAG.
getNode(ISD::VP_AND,
DL, VT, Src, Neg, Mask, VL);
6526 if (FloatVT.
bitsGT(VT)) {
6527 if (
Op->isVPOpcode())
6528 FloatVal = DAG.
getNode(ISD::VP_UINT_TO_FP,
DL, FloatVT, Src, Mask, VL);
6537 if (!
Op->isVPOpcode())
6541 MVT ContainerFloatVT =
6543 FloatVal = DAG.
getNode(RISCVISD::VFCVT_RM_F_XU_VL,
DL, ContainerFloatVT,
6544 Src, Mask, RTZRM, VL);
6551 unsigned ShiftAmt = FloatEltVT == MVT::f64 ? 52 : 23;
6555 if (
Op->isVPOpcode()) {
6564 else if (IntVT.
bitsGT(VT))
6569 unsigned ExponentBias = FloatEltVT == MVT::f64 ? 1023 : 127;
6574 if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF)
6575 return DAG.
getNode(ISD::VP_SUB,
DL, VT, Exp,
6580 unsigned Adjust = ExponentBias + (EltSize - 1);
6582 if (
Op->isVPOpcode())
6592 else if (
Op.getOpcode() == ISD::VP_CTLZ)
6593 Res = DAG.
getNode(ISD::VP_UMIN,
DL, VT, Res,
6601 MVT XLenVT = Subtarget.getXLenVT();
6603 MVT SrcVT =
Source.getSimpleValueType();
6612 SrcVT = ContainerVT;
6624 SDValue Res = DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Source, Mask, EVL);
6625 if (
Op->getOpcode() == ISD::VP_CTTZ_ELTS_ZERO_UNDEF)
6643 assert(Load &&
Load->getMemoryVT().isVector() &&
"Expected vector load");
6646 Load->getMemoryVT(),
6647 *
Load->getMemOperand()))
6651 MVT VT =
Op.getSimpleValueType();
6653 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
6654 "Unexpected unaligned RVV load type");
6658 "Expecting equally-sized RVV vector types to be legal");
6660 Load->getPointerInfo(),
Load->getBaseAlign(),
6661 Load->getMemOperand()->getFlags());
6672 assert(Store &&
Store->getValue().getValueType().isVector() &&
6673 "Expected vector store");
6676 Store->getMemoryVT(),
6677 *
Store->getMemOperand()))
6684 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
6685 "Unexpected unaligned RVV store type");
6689 "Expecting equally-sized RVV vector types to be legal");
6690 StoredVal = DAG.
getBitcast(NewVT, StoredVal);
6692 Store->getPointerInfo(),
Store->getBaseAlign(),
6693 Store->getMemOperand()->getFlags());
6698 assert(
Op.getValueType() == MVT::i64 &&
"Unexpected VT");
6727 unsigned ShiftAmt, AddOpc;
6738 MVT VT =
Op.getSimpleValueType();
6742 bool Negate =
false;
6746 if (Index < 0 &&
Imm.isNegative()) {
6763 return DAG.
getNode(ISD::FNEG,
DL, VT, Const);
6769 unsigned IsData =
Op.getConstantOperandVal(4);
6772 if (Subtarget.hasVendorXMIPSCBOP() && !IsData)
6773 return Op.getOperand(0);
6785 if (Subtarget.hasStdExtZtso()) {
6793 return DAG.
getNode(ISD::MEMBARRIER, dl, MVT::Other,
Op.getOperand(0));
6801 return DAG.
getNode(ISD::MEMBARRIER, dl, MVT::Other,
Op.getOperand(0));
6809 MVT VT =
Op.getSimpleValueType();
6810 MVT XLenVT = Subtarget.getXLenVT();
6811 unsigned Check =
Op.getConstantOperandVal(1);
6812 unsigned TDCMask = 0;
6840 MVT VT0 =
Op.getOperand(0).getSimpleValueType();
6845 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6847 VL =
Op.getOperand(3);
6850 VL,
Op->getFlags());
6865 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6867 MVT MaskContainerVT =
6870 VL =
Op.getOperand(3);
6874 SDValue FPCLASS = DAG.
getNode(RISCVISD::FCLASS_VL,
DL, ContainerDstVT, Op0,
6875 Mask, VL,
Op->getFlags());
6877 TDCMaskV = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerDstVT,
6878 DAG.
getUNDEF(ContainerDstVT), TDCMaskV, VL);
6881 DAG.
getNode(RISCVISD::SETCC_VL,
DL, ContainerVT,
6887 TDCMaskV, DAG.
getUNDEF(ContainerDstVT), Mask, VL);
6890 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerDstVT,
6891 DAG.
getUNDEF(ContainerDstVT), SplatZero, VL);
6911 MVT VT =
Op.getSimpleValueType();
6937 Op.getOpcode() == ISD::FMAXIMUM ? RISCVISD::FMAX : RISCVISD::FMIN;
6945 MVT ContainerVT = VT;
6953 if (
Op->isVPOpcode()) {
6954 Mask =
Op.getOperand(2);
6958 VL =
Op.getOperand(3);
6965 SDValue XIsNonNan = DAG.
getNode(RISCVISD::SETCC_VL,
DL, Mask.getValueType(),
6966 {X, X, DAG.getCondCode(ISD::SETOEQ),
6967 DAG.getUNDEF(ContainerVT), Mask, VL});
6968 NewY = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, XIsNonNan,
Y,
X,
6974 SDValue YIsNonNan = DAG.
getNode(RISCVISD::SETCC_VL,
DL, Mask.getValueType(),
6975 {Y, Y, DAG.getCondCode(ISD::SETOEQ),
6976 DAG.getUNDEF(ContainerVT), Mask, VL});
6977 NewX = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, YIsNonNan,
X,
Y,
6982 Op.getOpcode() == ISD::FMAXIMUM ||
Op->getOpcode() == ISD::VP_FMAXIMUM
6983 ? RISCVISD::VFMAX_VL
6984 : RISCVISD::VFMIN_VL;
6986 DAG.
getUNDEF(ContainerVT), Mask, VL);
6994 bool IsFABS =
Op.getOpcode() == ISD::FABS;
6995 assert((IsFABS ||
Op.getOpcode() == ISD::FNEG) &&
6996 "Wrong opcode for lowering FABS or FNEG.");
6999 MVT VT =
Op.getSimpleValueType();
7000 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
7004 DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT,
Op.getOperand(0));
7007 Mask = Mask.sext(Subtarget.
getXLen());
7012 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, Logic);
7020 MVT VT =
Op.getSimpleValueType();
7021 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
7031 if (SignSize == Subtarget.
getXLen())
7032 return DAG.
getNode(ISD::BITCAST,
DL, XLenVT, Sign);
7035 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Sign);
7037 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, XLenVT, Sign);
7039 assert(XLenVT == MVT::i32 &&
"Unexpected type");
7042 return DAG.
getNode(RISCVISD::SplitF64,
DL, {MVT::i32, MVT::i32}, Sign)
7072 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, CopiedSign);
7077#define OP_CASE(NODE) \
7079 return RISCVISD::NODE##_VL;
7080#define VP_CASE(NODE) \
7081 case ISD::VP_##NODE: \
7082 return RISCVISD::NODE##_VL;
7084 switch (
Op.getOpcode()) {
7163 case ISD::VP_CTLZ_ZERO_UNDEF:
7164 return RISCVISD::CTLZ_VL;
7166 case ISD::VP_CTTZ_ZERO_UNDEF:
7167 return RISCVISD::CTTZ_VL;
7170 return RISCVISD::VFMADD_VL;
7172 return RISCVISD::STRICT_VFMADD_VL;
7175 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7176 return RISCVISD::VMAND_VL;
7177 return RISCVISD::AND_VL;
7180 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7181 return RISCVISD::VMOR_VL;
7182 return RISCVISD::OR_VL;
7185 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7186 return RISCVISD::VMXOR_VL;
7187 return RISCVISD::XOR_VL;
7190 return RISCVISD::VZEXT_VL;
7192 return RISCVISD::VSEXT_VL;
7194 return RISCVISD::SETCC_VL;
7196 return RISCVISD::VMERGE_VL;
7197 case ISD::VP_SELECT:
7199 return RISCVISD::VMERGE_VL;
7201 return RISCVISD::SRA_VL;
7203 return RISCVISD::SRL_VL;
7205 return RISCVISD::FSQRT_VL;
7206 case ISD::VP_SIGN_EXTEND:
7207 return RISCVISD::VSEXT_VL;
7208 case ISD::VP_ZERO_EXTEND:
7209 return RISCVISD::VZEXT_VL;
7210 case ISD::VP_FP_TO_SINT:
7211 return RISCVISD::VFCVT_RTZ_X_F_VL;
7212 case ISD::VP_FP_TO_UINT:
7213 return RISCVISD::VFCVT_RTZ_XU_F_VL;
7215 case ISD::FMINIMUMNUM:
7216 case ISD::VP_FMINNUM:
7217 return RISCVISD::VFMIN_VL;
7219 case ISD::FMAXIMUMNUM:
7220 case ISD::VP_FMAXNUM:
7221 return RISCVISD::VFMAX_VL;
7225 case ISD::VP_LLRINT:
7226 return RISCVISD::VFCVT_RM_X_F_VL;
7235 return (
Op.getValueType() == MVT::nxv32f16 &&
7238 Op.getValueType() == MVT::nxv32bf16;
7248 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7249 if (!
Op.getOperand(j).getValueType().isVector()) {
7250 LoOperands[j] =
Op.getOperand(j);
7251 HiOperands[j] =
Op.getOperand(j);
7254 std::tie(LoOperands[j], HiOperands[j]) =
7259 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
7261 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
7274 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7276 std::tie(LoOperands[j], HiOperands[j]) =
7280 if (!
Op.getOperand(j).getValueType().isVector()) {
7281 LoOperands[j] =
Op.getOperand(j);
7282 HiOperands[j] =
Op.getOperand(j);
7285 std::tie(LoOperands[j], HiOperands[j]) =
7290 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
7292 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
7302 auto [EVLLo, EVLHi] =
7303 DAG.
SplitEVL(
Op.getOperand(3),
Op.getOperand(1).getValueType(),
DL);
7307 {Op.getOperand(0), Lo, MaskLo, EVLLo},
Op->getFlags());
7309 {ResLo, Hi, MaskHi, EVLHi},
Op->getFlags());
7326 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7327 if (!
Op.getOperand(j).getValueType().isVector()) {
7328 LoOperands[j] =
Op.getOperand(j);
7329 HiOperands[j] =
Op.getOperand(j);
7332 std::tie(LoOperands[j], HiOperands[j]) =
7337 DAG.
getNode(
Op.getOpcode(),
DL, LoVTs, LoOperands,
Op->getFlags());
7340 DAG.
getNode(
Op.getOpcode(),
DL, HiVTs, HiOperands,
Op->getFlags());
7348RISCVTargetLowering::lowerXAndesBfHCvtBFloat16Load(
SDValue Op,
7350 assert(Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh() &&
7351 "Unexpected bfloat16 load lowering");
7355 EVT MemVT =
LD->getMemoryVT();
7360 LD->getMemOperand());
7368 DAG.
getNode(RISCVISD::NDS_FMV_BF16_X,
DL, MVT::bf16, OrSixteenOne);
7373RISCVTargetLowering::lowerXAndesBfHCvtBFloat16Store(
SDValue Op,
7375 assert(Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh() &&
7376 "Unexpected bfloat16 store lowering");
7381 Subtarget.getXLenVT(),
ST->getValue());
7383 ST->getChain(),
DL, FMV,
ST->getBasePtr(),
7385 ST->getMemOperand());
7390 switch (
Op.getOpcode()) {
7393 "Unimplemented RISCVTargetLowering::LowerOperation Case");
7396 case ISD::ATOMIC_FENCE:
7399 return lowerGlobalAddress(
Op, DAG);
7401 return lowerBlockAddress(
Op, DAG);
7403 return lowerConstantPool(
Op, DAG);
7405 return lowerJumpTable(
Op, DAG);
7407 return lowerGlobalTLSAddress(
Op, DAG);
7411 return lowerConstantFP(
Op, DAG);
7413 return lowerSELECT(
Op, DAG);
7415 return lowerBRCOND(
Op, DAG);
7417 return lowerVASTART(
Op, DAG);
7419 return lowerFRAMEADDR(
Op, DAG);
7421 return lowerRETURNADDR(
Op, DAG);
7423 return lowerShiftLeftParts(
Op, DAG);
7425 return lowerShiftRightParts(
Op, DAG,
true);
7427 return lowerShiftRightParts(
Op, DAG,
false);
7430 if (
Op.getValueType().isFixedLengthVector()) {
7431 assert(Subtarget.hasStdExtZvkb());
7432 return lowerToScalableOp(
Op, DAG);
7434 assert(Subtarget.hasVendorXTHeadBb() &&
7435 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
7436 "Unexpected custom legalization");
7441 case ISD::BITCAST: {
7443 EVT VT =
Op.getValueType();
7446 MVT XLenVT = Subtarget.getXLenVT();
7447 if (Op0VT == MVT::i16 &&
7448 ((VT == MVT::f16 && Subtarget.hasStdExtZfhminOrZhinxmin()) ||
7449 (VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
7451 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, NewOp0);
7453 if (VT == MVT::f32 && Op0VT == MVT::i32 && Subtarget.is64Bit() &&
7454 Subtarget.hasStdExtFOrZfinx()) {
7456 return DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, NewOp0);
7458 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit() &&
7459 Subtarget.hasStdExtDOrZdinx()) {
7462 return DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64,
Lo,
Hi);
7474 "Unexpected types");
7506 return LowerINTRINSIC_WO_CHAIN(
Op, DAG);
7508 return LowerINTRINSIC_W_CHAIN(
Op, DAG);
7510 return LowerINTRINSIC_VOID(
Op, DAG);
7512 return LowerIS_FPCLASS(
Op, DAG);
7514 MVT VT =
Op.getSimpleValueType();
7516 assert(Subtarget.hasStdExtZvbb());
7517 return lowerToScalableOp(
Op, DAG);
7520 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected custom legalization");
7524 return DAG.
getNode(RISCVISD::BREV8,
DL, VT, BSwap);
7530 if (!
Op.getSimpleValueType().isVector())
7532 return lowerVectorTruncLike(
Op, DAG);
7535 if (
Op.getOperand(0).getValueType().isVector() &&
7536 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7537 return lowerVectorMaskExt(
Op, DAG, 1);
7538 if (
Op.getValueType().isScalableVector())
7540 return lowerToScalableOp(
Op, DAG);
7542 if (
Op.getOperand(0).getValueType().isVector() &&
7543 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7544 return lowerVectorMaskExt(
Op, DAG, -1);
7545 if (
Op.getValueType().isScalableVector())
7547 return lowerToScalableOp(
Op, DAG);
7549 return lowerSPLAT_VECTOR_PARTS(
Op, DAG);
7551 return lowerINSERT_VECTOR_ELT(
Op, DAG);
7553 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
7555 MVT VT =
Op.getSimpleValueType();
7563 MVT ContainerVT = VT;
7570 V = DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL, ContainerVT,
7571 DAG.
getUNDEF(ContainerVT), Scalar, VL);
7574 V = DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, ContainerVT,
7575 DAG.
getUNDEF(ContainerVT), Scalar, VL);
7582 MVT XLenVT = Subtarget.getXLenVT();
7583 MVT VT =
Op.getSimpleValueType();
7602 }
else if (
Log2 > 3) {
7606 }
else if ((Val % 8) == 0) {
7624 if (
Op.getValueType() == MVT::f16 && Subtarget.is64Bit() &&
7625 Op.getOperand(1).getValueType() == MVT::i32) {
7629 DAG.
getNode(ISD::FPOWI,
DL, MVT::f32, Op0,
Op.getOperand(1));
7640 case ISD::FP_EXTEND:
7642 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
7645 return lowerStrictFPExtendOrRoundLike(
Op, DAG);
7648 if (
Op.getValueType().isVector() &&
7649 ((
Op.getValueType().getScalarType() == MVT::f16 &&
7650 (Subtarget.hasVInstructionsF16Minimal() &&
7651 !Subtarget.hasVInstructionsF16())) ||
7652 Op.getValueType().getScalarType() == MVT::bf16)) {
7668 Op1.getValueType().isVector() &&
7669 ((Op1.getValueType().getScalarType() == MVT::f16 &&
7670 (Subtarget.hasVInstructionsF16Minimal() &&
7671 !Subtarget.hasVInstructionsF16())) ||
7672 Op1.getValueType().getScalarType() == MVT::bf16)) {
7678 Op1.getValueType().getVectorElementCount());
7681 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), WidenVec);
7691 MVT VT =
Op.getSimpleValueType();
7694 bool IsStrict =
Op->isStrictFPOpcode();
7695 SDValue Src =
Op.getOperand(0 + IsStrict);
7696 MVT SrcVT = Src.getSimpleValueType();
7707 "Unexpected vector element types");
7711 if (EltSize > (2 * SrcEltSize)) {
7723 Op.getOperand(0), Ext);
7727 assert(SrcEltVT == MVT::f16 &&
"Unexpected FP_TO_[US]INT lowering");
7732 auto [FExt, Chain] =
7734 return DAG.
getNode(
Op.getOpcode(),
DL,
Op->getVTList(), Chain, FExt);
7741 if (SrcEltSize > (2 * EltSize)) {
7744 assert(EltVT == MVT::f16 &&
"Unexpected [US]_TO_FP lowering");
7749 Op.getOperand(0), Src);
7764 Op.getOperand(0), Src);
7778 unsigned RVVOpc = 0;
7779 switch (
Op.getOpcode()) {
7783 RVVOpc = RISCVISD::VFCVT_RTZ_X_F_VL;
7786 RVVOpc = RISCVISD::VFCVT_RTZ_XU_F_VL;
7789 RVVOpc = RISCVISD::SINT_TO_FP_VL;
7792 RVVOpc = RISCVISD::UINT_TO_FP_VL;
7795 RVVOpc = RISCVISD::STRICT_VFCVT_RTZ_X_F_VL;
7798 RVVOpc = RISCVISD::STRICT_VFCVT_RTZ_XU_F_VL;
7801 RVVOpc = RISCVISD::STRICT_SINT_TO_FP_VL;
7804 RVVOpc = RISCVISD::STRICT_UINT_TO_FP_VL;
7811 "Expected same element count");
7818 Op.getOperand(0), Src, Mask, VL);
7822 Src = DAG.
getNode(RVVOpc,
DL, ContainerVT, Src, Mask, VL);
7828 case ISD::FP_TO_BF16: {
7831 assert(!Subtarget.isSoftFPABI() &&
"Unexpected custom legalization");
7837 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
7838 if (Subtarget.is64Bit())
7839 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Res);
7842 case ISD::BF16_TO_FP: {
7843 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalization");
7844 MVT VT =
Op.getSimpleValueType();
7849 SDValue Res = Subtarget.is64Bit()
7850 ? DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32,
Op)
7854 return DAG.
getNode(ISD::FP_EXTEND,
DL, VT, Res);
7857 case ISD::STRICT_FP_TO_FP16:
7858 case ISD::FP_TO_FP16: {
7861 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalisation");
7864 bool IsStrict =
Op->isStrictFPOpcode();
7865 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7869 std::tie(Res, Chain) =
7870 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
7871 if (Subtarget.is64Bit())
7872 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Res);
7878 case ISD::STRICT_FP16_TO_FP:
7879 case ISD::FP16_TO_FP: {
7882 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalisation");
7885 bool IsStrict =
Op->isStrictFPOpcode();
7886 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7888 SDValue Arg = Subtarget.is64Bit()
7889 ? DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, Op0)
7892 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
7893 CallOptions,
DL, Chain);
7901 case ISD::FNEARBYINT:
7904 case ISD::FROUNDEVEN:
7911 case ISD::LLROUND: {
7912 if (
Op.getValueType().isVector())
7914 assert(
Op.getOperand(0).getValueType() == MVT::f16 &&
7915 "Unexpected custom legalisation");
7918 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), Ext);
7924 assert(
Op.getOperand(1).getValueType() == MVT::f16 &&
7925 "Unexpected custom legalisation");
7928 {
Op.getOperand(0),
Op.getOperand(1)});
7929 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
7930 {Ext.getValue(1), Ext.getValue(0)});
7932 case ISD::VECREDUCE_ADD:
7933 case ISD::VECREDUCE_UMAX:
7934 case ISD::VECREDUCE_SMAX:
7935 case ISD::VECREDUCE_UMIN:
7936 case ISD::VECREDUCE_SMIN:
7937 return lowerVECREDUCE(
Op, DAG);
7938 case ISD::VECREDUCE_AND:
7939 case ISD::VECREDUCE_OR:
7940 case ISD::VECREDUCE_XOR:
7941 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7942 return lowerVectorMaskVecReduction(
Op, DAG,
false);
7943 return lowerVECREDUCE(
Op, DAG);
7944 case ISD::VECREDUCE_FADD:
7945 case ISD::VECREDUCE_SEQ_FADD:
7946 case ISD::VECREDUCE_FMIN:
7947 case ISD::VECREDUCE_FMAX:
7948 case ISD::VECREDUCE_FMAXIMUM:
7949 case ISD::VECREDUCE_FMINIMUM:
7950 return lowerFPVECREDUCE(
Op, DAG);
7951 case ISD::VP_REDUCE_ADD:
7952 case ISD::VP_REDUCE_UMAX:
7953 case ISD::VP_REDUCE_SMAX:
7954 case ISD::VP_REDUCE_UMIN:
7955 case ISD::VP_REDUCE_SMIN:
7956 case ISD::VP_REDUCE_FADD:
7957 case ISD::VP_REDUCE_SEQ_FADD:
7958 case ISD::VP_REDUCE_FMIN:
7959 case ISD::VP_REDUCE_FMAX:
7960 case ISD::VP_REDUCE_FMINIMUM:
7961 case ISD::VP_REDUCE_FMAXIMUM:
7964 return lowerVPREDUCE(
Op, DAG);
7965 case ISD::VP_REDUCE_AND:
7966 case ISD::VP_REDUCE_OR:
7967 case ISD::VP_REDUCE_XOR:
7968 if (
Op.getOperand(1).getValueType().getVectorElementType() == MVT::i1)
7969 return lowerVectorMaskVecReduction(
Op, DAG,
true);
7970 return lowerVPREDUCE(
Op, DAG);
7971 case ISD::VP_CTTZ_ELTS:
7972 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
7973 return lowerVPCttzElements(
Op, DAG);
7977 DAG.
getUNDEF(ContainerVT), DAG, Subtarget);
7980 return lowerINSERT_SUBVECTOR(
Op, DAG);
7982 return lowerEXTRACT_SUBVECTOR(
Op, DAG);
7984 return lowerVECTOR_DEINTERLEAVE(
Op, DAG);
7986 return lowerVECTOR_INTERLEAVE(
Op, DAG);
7988 return lowerSTEP_VECTOR(
Op, DAG);
7990 return lowerVECTOR_REVERSE(
Op, DAG);
7992 return lowerVECTOR_SPLICE(
Op, DAG);
7994 MVT VT =
Op.getSimpleValueType();
7996 if (!Subtarget.is64Bit() && EltVT == MVT::i64)
8001 MVT VT =
Op.getSimpleValueType();
8003 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
8004 EltVT == MVT::bf16) {
8007 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
8008 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
8009 Elt = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, Subtarget.getXLenVT(),
8012 Elt = DAG.
getNode(ISD::BITCAST,
DL, MVT::i16,
Op.getOperand(0));
8014 return DAG.
getNode(ISD::BITCAST,
DL, VT,
8018 if (EltVT == MVT::i1)
8019 return lowerVectorMaskSplat(
Op, DAG);
8028 MVT VT =
Op.getSimpleValueType();
8029 MVT ContainerVT = VT;
8041 if (
Op.getNumOperands() > 2 &&
8045 size_t HalfNumOps =
Op.getNumOperands() / 2;
8047 Op->ops().take_front(HalfNumOps));
8049 Op->ops().drop_front(HalfNumOps));
8053 unsigned NumOpElts =
8054 Op.getOperand(0).getSimpleValueType().getVectorMinNumElements();
8067 EVT VT = Load->getValueType(0);
8068 if (VT == MVT::f64) {
8069 assert(Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
8070 !Subtarget.is64Bit() &&
"Unexpected custom legalisation");
8074 SDValue BasePtr = Load->getBasePtr();
8075 SDValue Chain = Load->getChain();
8078 DAG.
getLoad(MVT::i32,
DL, Chain, BasePtr, Load->getPointerInfo(),
8079 Load->getBaseAlign(), Load->getMemOperand()->getFlags());
8082 MVT::i32,
DL, Chain, BasePtr, Load->getPointerInfo().getWithOffset(4),
8083 Load->getBaseAlign(), Load->getMemOperand()->getFlags());
8091 if (VT == MVT::bf16)
8092 return lowerXAndesBfHCvtBFloat16Load(
Op, DAG);
8097 MVT XLenVT = Subtarget.getXLenVT();
8100 unsigned NumElts = Sz / (NF * 8);
8101 int Log2LMUL =
Log2_64(NumElts) - 3;
8104 Flag.setNoUnsignedWrap(
true);
8106 SDValue BasePtr = Load->getBasePtr();
8114 for (
unsigned i = 0; i < NF; ++i) {
8119 Ret = DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VT, Ret, LoadVal,
8127 if (
auto V = expandUnalignedRVVLoad(
Op, DAG))
8129 if (
Op.getValueType().isFixedLengthVector())
8130 return lowerFixedLengthVectorLoadToRVV(
Op, DAG);
8135 SDValue StoredVal = Store->getValue();
8137 if (VT == MVT::f64) {
8138 assert(Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
8139 !Subtarget.is64Bit() &&
"Unexpected custom legalisation");
8143 SDValue BasePtr = Store->getBasePtr();
8144 SDValue Chain = Store->getChain();
8146 DAG.
getVTList(MVT::i32, MVT::i32), StoredVal);
8149 Store->getPointerInfo(), Store->getBaseAlign(),
8150 Store->getMemOperand()->getFlags());
8153 Store->getPointerInfo().getWithOffset(4),
8154 Store->getBaseAlign(),
8155 Store->getMemOperand()->getFlags());
8158 if (VT == MVT::i64) {
8159 assert(Subtarget.hasStdExtZilsd() && !Subtarget.is64Bit() &&
8160 "Unexpected custom legalisation");
8161 if (Store->isTruncatingStore())
8164 if (!Subtarget.enableUnalignedScalarMem() && Store->getAlign() < 8)
8175 {Store->getChain(), Lo, Hi, Store->getBasePtr()}, MVT::i64,
8176 Store->getMemOperand());
8179 if (VT == MVT::bf16)
8180 return lowerXAndesBfHCvtBFloat16Store(
Op, DAG);
8185 MVT XLenVT = Subtarget.getXLenVT();
8188 unsigned NumElts = Sz / (NF * 8);
8189 int Log2LMUL =
Log2_64(NumElts) - 3;
8192 Flag.setNoUnsignedWrap(
true);
8194 SDValue Chain = Store->getChain();
8195 SDValue BasePtr = Store->getBasePtr();
8202 for (
unsigned i = 0; i < NF; ++i) {
8204 DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL,
8207 Ret = DAG.
getStore(Chain,
DL, Extract, BasePtr,
8209 Store->getBaseAlign(),
8210 Store->getMemOperand()->getFlags());
8211 Chain = Ret.getValue(0);
8217 if (
auto V = expandUnalignedRVVStore(
Op, DAG))
8219 if (
Op.getOperand(1).getValueType().isFixedLengthVector())
8220 return lowerFixedLengthVectorStoreToRVV(
Op, DAG);
8225 return lowerMaskedLoad(
Op, DAG);
8226 case ISD::VP_LOAD_FF:
8227 return lowerLoadFF(
Op, DAG);
8230 return lowerMaskedStore(
Op, DAG);
8232 return lowerVectorCompress(
Op, DAG);
8241 EVT VT =
Op.getValueType();
8252 MVT OpVT =
Op.getOperand(0).getSimpleValueType();
8254 MVT VT =
Op.getSimpleValueType();
8259 "Unexpected CondCode");
8292 return DAG.
getSetCC(
DL, VT, RHS, LHS, CCVal);
8298 return lowerToScalableOp(
Op, DAG);
8315 return lowerToScalableOp(
Op, DAG);
8319 if (
Op.getSimpleValueType().isFixedLengthVector())
8320 return lowerToScalableOp(
Op, DAG);
8322 assert(
Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.is64Bit() &&
8323 "Unexpected custom legalisation");
8327 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
8338 case ISD::FMINIMUMNUM:
8339 case ISD::FMAXIMUMNUM:
8355 return lowerToScalableOp(
Op, DAG);
8359 EVT VT =
Op->getValueType(0);
8374 return lowerABS(
Op, DAG);
8379 if (Subtarget.hasStdExtZvbb())
8380 return lowerToScalableOp(
Op, DAG);
8382 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8384 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
8388 return lowerToScalableOp(
Op, DAG);
8397 return lowerToScalableOp(
Op, DAG);
8400 return lowerVectorStrictFSetcc(
Op, DAG);
8410 case ISD::VP_GATHER:
8411 return lowerMaskedGather(
Op, DAG);
8413 case ISD::VP_SCATTER:
8414 return lowerMaskedScatter(
Op, DAG);
8416 return lowerGET_ROUNDING(
Op, DAG);
8417 case ISD::SET_ROUNDING:
8418 return lowerSET_ROUNDING(
Op, DAG);
8419 case ISD::GET_FPENV:
8420 return lowerGET_FPENV(
Op, DAG);
8421 case ISD::SET_FPENV:
8422 return lowerSET_FPENV(
Op, DAG);
8423 case ISD::RESET_FPENV:
8424 return lowerRESET_FPENV(
Op, DAG);
8425 case ISD::GET_FPMODE:
8426 return lowerGET_FPMODE(
Op, DAG);
8427 case ISD::SET_FPMODE:
8428 return lowerSET_FPMODE(
Op, DAG);
8429 case ISD::RESET_FPMODE:
8430 return lowerRESET_FPMODE(
Op, DAG);
8432 return lowerEH_DWARF_CFA(
Op, DAG);
8434 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
8435 return lowerVPMergeMask(
Op, DAG);
8437 case ISD::VP_SELECT:
8445 case ISD::VP_UADDSAT:
8446 case ISD::VP_USUBSAT:
8447 case ISD::VP_SADDSAT:
8448 case ISD::VP_SSUBSAT:
8450 case ISD::VP_LLRINT:
8451 return lowerVPOp(
Op, DAG);
8455 return lowerLogicVPOp(
Op, DAG);
8464 case ISD::VP_FMINNUM:
8465 case ISD::VP_FMAXNUM:
8466 case ISD::VP_FCOPYSIGN:
8473 return lowerVPOp(
Op, DAG);
8474 case ISD::VP_IS_FPCLASS:
8475 return LowerIS_FPCLASS(
Op, DAG);
8476 case ISD::VP_SIGN_EXTEND:
8477 case ISD::VP_ZERO_EXTEND:
8478 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
8479 return lowerVPExtMaskOp(
Op, DAG);
8480 return lowerVPOp(
Op, DAG);
8481 case ISD::VP_TRUNCATE:
8482 return lowerVectorTruncLike(
Op, DAG);
8483 case ISD::VP_FP_EXTEND:
8484 case ISD::VP_FP_ROUND:
8485 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
8486 case ISD::VP_SINT_TO_FP:
8487 case ISD::VP_UINT_TO_FP:
8488 if (
Op.getValueType().isVector() &&
8489 ((
Op.getValueType().getScalarType() == MVT::f16 &&
8490 (Subtarget.hasVInstructionsF16Minimal() &&
8491 !Subtarget.hasVInstructionsF16())) ||
8492 Op.getValueType().getScalarType() == MVT::bf16)) {
8505 case ISD::VP_FP_TO_SINT:
8506 case ISD::VP_FP_TO_UINT:
8508 Op1.getValueType().isVector() &&
8509 ((Op1.getValueType().getScalarType() == MVT::f16 &&
8510 (Subtarget.hasVInstructionsF16Minimal() &&
8511 !Subtarget.hasVInstructionsF16())) ||
8512 Op1.getValueType().getScalarType() == MVT::bf16)) {
8518 Op1.getValueType().getVectorElementCount());
8522 {WidenVec, Op.getOperand(1), Op.getOperand(2)});
8524 return lowerVPFPIntConvOp(
Op, DAG);
8528 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
8529 return lowerVPSetCCMaskOp(
Op, DAG);
8535 case ISD::VP_BITREVERSE:
8537 return lowerVPOp(
Op, DAG);
8539 case ISD::VP_CTLZ_ZERO_UNDEF:
8540 if (Subtarget.hasStdExtZvbb())
8541 return lowerVPOp(
Op, DAG);
8542 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8544 case ISD::VP_CTTZ_ZERO_UNDEF:
8545 if (Subtarget.hasStdExtZvbb())
8546 return lowerVPOp(
Op, DAG);
8547 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8549 return lowerVPOp(
Op, DAG);
8550 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
8551 return lowerVPStridedLoad(
Op, DAG);
8552 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
8553 return lowerVPStridedStore(
Op, DAG);
8555 case ISD::VP_FFLOOR:
8557 case ISD::VP_FNEARBYINT:
8558 case ISD::VP_FROUND:
8559 case ISD::VP_FROUNDEVEN:
8560 case ISD::VP_FROUNDTOZERO:
8564 case ISD::VP_FMAXIMUM:
8565 case ISD::VP_FMINIMUM:
8569 case ISD::EXPERIMENTAL_VP_SPLICE:
8570 return lowerVPSpliceExperimental(
Op, DAG);
8571 case ISD::EXPERIMENTAL_VP_REVERSE:
8572 return lowerVPReverseExperimental(
Op, DAG);
8573 case ISD::EXPERIMENTAL_VP_SPLAT:
8574 return lowerVPSplatExperimental(
Op, DAG);
8577 "llvm.clear_cache only needs custom lower on Linux targets");
8580 return emitFlushICache(DAG,
Op.getOperand(0),
Op.getOperand(1),
8581 Op.getOperand(2), Flags,
DL);
8583 case ISD::DYNAMIC_STACKALLOC:
8584 return lowerDYNAMIC_STACKALLOC(
Op, DAG);
8585 case ISD::INIT_TRAMPOLINE:
8586 return lowerINIT_TRAMPOLINE(
Op, DAG);
8587 case ISD::ADJUST_TRAMPOLINE:
8588 return lowerADJUST_TRAMPOLINE(
Op, DAG);
8589 case ISD::PARTIAL_REDUCE_UMLA:
8590 case ISD::PARTIAL_REDUCE_SMLA:
8591 case ISD::PARTIAL_REDUCE_SUMLA:
8592 return lowerPARTIAL_REDUCE_MLA(
Op, DAG);
8599 MakeLibCallOptions CallOptions;
8600 std::pair<SDValue, SDValue> CallResult =
8601 makeLibCall(DAG, RTLIB::RISCV_FLUSH_ICACHE, MVT::isVoid,
8602 {Start, End, Flags}, CallOptions,
DL, InChain);
8605 return CallResult.second;
8610 if (!Subtarget.is64Bit())
8618 std::unique_ptr<MCCodeEmitter> CodeEmitter(
8646 const bool HasCFBranch =
8647 Subtarget.hasStdExtZicfilp() &&
8649 "cf-protection-branch");
8650 const unsigned StaticChainIdx = HasCFBranch ? 5 : 4;
8651 const unsigned StaticChainOffset = StaticChainIdx * 4;
8652 const unsigned FunctionAddressOffset = StaticChainOffset + 8;
8656 auto GetEncoding = [&](
const MCInst &MC) {
8659 CodeEmitter->encodeInstruction(MC, CB, Fixups, *STI);
8666 SmallVector<uint32_t> Encodings;
8671 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X7).addImm(0)),
8675 GetEncoding(MCInstBuilder(RISCV::LD)
8678 .addImm(FunctionAddressOffset)),
8681 GetEncoding(MCInstBuilder(RISCV::LD)
8684 .addImm(StaticChainOffset)),
8687 GetEncoding(MCInstBuilder(RISCV::JALR)
8695 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X0).addImm(0)),
8698 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X28).addImm(0)),
8702 GetEncoding(MCInstBuilder(RISCV::LD)
8705 .addImm(FunctionAddressOffset - 4)),
8708 GetEncoding(MCInstBuilder(RISCV::LD)
8711 .addImm(StaticChainOffset - 4)),
8714 GetEncoding(MCInstBuilder(RISCV::JALR)
8726 Root, dl, DAG.
getConstant(Encoding, dl, MVT::i64), Addr,
8727 MachinePointerInfo(TrmpAddr, Idx * 4), MVT::i32));
8731 SDValue FunctionAddress =
Op.getOperand(2);
8735 struct OffsetValuePair {
8739 } OffsetValues[] = {
8740 {StaticChainOffset, StaticChain},
8741 {FunctionAddressOffset, FunctionAddress},
8743 for (
auto &OffsetValue : OffsetValues) {
8746 DAG.
getConstant(OffsetValue.Offset, dl, MVT::i64));
8747 OffsetValue.Addr = Addr;
8749 DAG.
getStore(Root, dl, OffsetValue.Value, Addr,
8750 MachinePointerInfo(TrmpAddr, OffsetValue.Offset)));
8753 assert(OutChains.
size() == StaticChainIdx + 2 &&
8754 "Size of OutChains mismatch");
8759 SDValue EndOfTrmp = OffsetValues[0].Addr;
8770 if (!Subtarget.is64Bit())
8773 return Op.getOperand(0);
8782 MVT VT =
Op.getSimpleValueType();
8788 MVT ArgVT =
A.getSimpleValueType();
8789 assert(ArgVT ==
B.getSimpleValueType() &&
8799 MVT ContainerVT = VT;
8808 switch (
Op.getOpcode()) {
8809 case ISD::PARTIAL_REDUCE_SMLA:
8810 Opc = RISCVISD::VQDOT_VL;
8812 case ISD::PARTIAL_REDUCE_UMLA:
8813 Opc = RISCVISD::VQDOTU_VL;
8815 case ISD::PARTIAL_REDUCE_SUMLA:
8816 Opc = RISCVISD::VQDOTSU_VL;
8842 N->getOffset(), Flags);
8871template <
class NodeTy>
8873 bool IsLocal,
bool IsExternWeak)
const {
8883 if (IsLocal && !Subtarget.allowTaggedGlobals())
8887 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
8910 if (Subtarget.hasVendorXqcili()) {
8914 return DAG.
getNode(RISCVISD::QC_E_LI,
DL, Ty, Addr);
8921 return DAG.
getNode(RISCVISD::ADD_LO,
DL, Ty, MNHi, AddrLo);
8945 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
8953 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
8961 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
8962 const GlobalValue *GV =
N->getGlobal();
8970 return getAddr(
N, DAG);
8977 return getAddr(
N, DAG);
8984 return getAddr(
N, DAG);
8989 bool UseGOT)
const {
8992 const GlobalValue *GV =
N->getGlobal();
8993 MVT XLenVT = Subtarget.getXLenVT();
9030 DAG.
getNode(RISCVISD::ADD_TPREL,
DL, Ty, MNHi, TPReg, AddrAdd);
9031 return DAG.
getNode(RISCVISD::ADD_LO,
DL, Ty, MNAdd, AddrLo);
9039 const GlobalValue *GV =
N->getGlobal();
9050 Args.emplace_back(Load, CallTy);
9053 TargetLowering::CallLoweringInfo CLI(DAG);
9067 const GlobalValue *GV =
N->getGlobal();
9083 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
9097 Addr = getStaticTLSAddr(
N, DAG,
false);
9100 Addr = getStaticTLSAddr(
N, DAG,
true);
9105 : getDynamicTLSAddr(
N, DAG);
9122 if (
LHS == LHS2 &&
RHS == RHS2) {
9127 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
9135 return std::nullopt;
9147 MVT VT =
N->getSimpleValueType(0);
9174 uint64_t TrueM1 = TrueC->getZExtValue() - 1;
9176 unsigned ShAmount =
Log2_64(TrueM1);
9178 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, CondV,
9194 if (~TrueVal == FalseVal) {
9234 if (Subtarget.hasShortForwardBranchOpt())
9237 unsigned SelOpNo = 0;
9247 unsigned ConstSelOpNo = 1;
9248 unsigned OtherSelOpNo = 2;
9255 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
9260 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
9266 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
9268 std::swap(NewConstOps[0], NewConstOps[1]);
9280 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
9282 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
9285 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
9286 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
9295 MVT VT =
Op.getSimpleValueType();
9296 MVT XLenVT = Subtarget.getXLenVT();
9317 return DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV);
9320 return DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV);
9324 auto getNotOperand = [](
const SDValue &
Op) -> std::optional<const SDValue> {
9325 using namespace llvm::SDPatternMatch;
9330 return std::nullopt;
9336 auto NotOperand = (TrueV.
getOperand(0) == FalseV)
9338 : getNotOperand(TrueV.getOperand(0));
9341 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, *NotOperand, CondV);
9347 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV));
9354 auto NotOperand = (FalseV.
getOperand(0) == TrueV)
9356 : getNotOperand(FalseV.getOperand(0));
9359 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, *NotOperand, CondV);
9365 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV));
9382 int64_t TrueImm =
TrueVal.getSExtValue();
9383 int64_t FalseImm =
FalseVal.getSExtValue();
9402 if ((TrueVal - FalseVal).isPowerOf2() &&
FalseVal.isSignedIntN(12)) {
9407 if ((FalseVal - TrueVal).isPowerOf2() &&
TrueVal.isSignedIntN(12)) {
9414 auto getCost = [&](
const APInt &Delta,
const APInt &Addend) {
9416 Delta, Subtarget.getXLen(), Subtarget,
true);
9418 if (Addend.isSignedIntN(12))
9421 Addend, Subtarget.getXLen(), Subtarget,
true);
9422 return AddendCost + DeltaCost;
9424 bool IsCZERO_NEZ =
getCost(FalseVal - TrueVal, TrueVal) <=
9425 getCost(TrueVal - FalseVal, FalseVal);
9427 IsCZERO_NEZ ? FalseVal - TrueVal : TrueVal - FalseVal,
DL, VT);
9429 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9430 DL, VT, LHSVal, CondV);
9438 SDValue ConstVal = IsCZERO_NEZ ? TrueV : FalseV;
9439 SDValue RegV = IsCZERO_NEZ ? FalseV : TrueV;
9442 if (RawConstVal == -0x800) {
9445 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9446 DL, VT, XorOp, CondV);
9454 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9455 DL, VT, SubOp, CondV);
9462 if (!Subtarget.hasConditionalMoveFusion())
9465 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV),
9466 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV),
9470 if (
Op.hasOneUse()) {
9471 unsigned UseOpc =
Op->user_begin()->getOpcode();
9473 SDNode *BinOp = *
Op->user_begin();
9480 return lowerSELECT(NewSel, DAG);
9534 if (TrueVal - 1 == FalseVal)
9536 if (TrueVal + 1 == FalseVal)
9543 RHS == TrueV &&
LHS == FalseV) {
9574 MVT XLenVT = Subtarget.getXLenVT();
9585 return DAG.
getNode(RISCVISD::BR_CC,
DL,
Op.getValueType(),
Op.getOperand(0),
9586 LHS,
RHS, TargetCC,
Op.getOperand(2));
9589 return DAG.
getNode(RISCVISD::BR_CC,
DL,
Op.getValueType(),
Op.getOperand(0),
9596 RISCVMachineFunctionInfo *FuncInfo = MF.
getInfo<RISCVMachineFunctionInfo>();
9606 MachinePointerInfo(SV));
9611 const RISCVRegisterInfo &RI = *Subtarget.getRegisterInfo();
9616 int XLenInBytes = Subtarget.getXLen() / 8;
9618 EVT VT =
Op.getValueType();
9621 unsigned Depth =
Op.getConstantOperandVal(0);
9623 int Offset = -(XLenInBytes * 2);
9635 const RISCVRegisterInfo &RI = *Subtarget.getRegisterInfo();
9639 MVT XLenVT = Subtarget.getXLenVT();
9640 int XLenInBytes = Subtarget.getXLen() / 8;
9642 EVT VT =
Op.getValueType();
9644 unsigned Depth =
Op.getConstantOperandVal(0);
9646 int Off = -XLenInBytes;
9647 SDValue FrameAddr = lowerFRAMEADDR(
Op, DAG);
9651 MachinePointerInfo());
9666 EVT VT =
Lo.getValueType();
9705 EVT VT =
Lo.getValueType();
9756 MVT VT =
Op.getSimpleValueType();
9761 return DAG.
getNode(RISCVISD::VMSET_VL,
DL, VT, VL);
9765 return DAG.
getNode(RISCVISD::VMCLR_VL,
DL, VT, VL);
9782 MVT VecVT =
Op.getSimpleValueType();
9784 "Unexpected SPLAT_VECTOR_PARTS lowering");
9790 MVT ContainerVT = VecVT;
9810 int64_t ExtTrueVal)
const {
9812 MVT VecVT =
Op.getSimpleValueType();
9815 assert(Src.getValueType().isVector() &&
9816 Src.getValueType().getVectorElementType() == MVT::i1);
9836 MVT XLenVT = Subtarget.getXLenVT();
9842 if (
Xor.getOpcode() == RISCVISD::VMXOR_VL) {
9854 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9855 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
9856 SplatTrueVal = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9857 DAG.
getUNDEF(ContainerVT), SplatTrueVal, VL);
9859 DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, CC, SplatTrueVal,
9860 SplatZero, DAG.
getUNDEF(ContainerVT), VL);
9870 bool IsVPTrunc =
Op.getOpcode() == ISD::VP_TRUNCATE;
9872 EVT MaskVT =
Op.getValueType();
9875 "Unexpected type for vector mask lowering");
9877 MVT VecVT = Src.getSimpleValueType();
9881 VL =
Op.getOperand(2);
9884 MVT ContainerVT = VecVT;
9890 MVT MaskContainerVT =
9897 std::tie(Mask, VL) =
9904 SplatOne = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9905 DAG.
getUNDEF(ContainerVT), SplatOne, VL);
9906 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9907 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
9910 SDValue Trunc = DAG.
getNode(RISCVISD::AND_VL,
DL, ContainerVT, Src, SplatOne,
9911 DAG.
getUNDEF(ContainerVT), Mask, VL);
9912 Trunc = DAG.
getNode(RISCVISD::SETCC_VL,
DL, MaskContainerVT,
9922 unsigned Opc =
Op.getOpcode();
9923 bool IsVPTrunc =
Opc == ISD::VP_TRUNCATE;
9926 MVT VT =
Op.getSimpleValueType();
9928 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
9932 return lowerVectorMaskTruncLike(
Op, DAG);
9940 MVT SrcVT = Src.getSimpleValueType();
9945 "Unexpected vector truncate lowering");
9947 MVT ContainerVT = SrcVT;
9951 VL =
Op.getOperand(2);
9964 std::tie(Mask, VL) =
9970 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL_SSAT;
9972 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL_USAT;
9974 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL;
9980 }
while (SrcEltVT != DstEltVT);
9989RISCVTargetLowering::lowerStrictFPExtendOrRoundLike(
SDValue Op,
9994 MVT VT =
Op.getSimpleValueType();
9995 MVT SrcVT = Src.getSimpleValueType();
9996 MVT ContainerVT = VT;
10015 ? RISCVISD::STRICT_FP_EXTEND_VL
10016 : RISCVISD::STRICT_VFNCVT_ROD_VL;
10019 Chain, Src, Mask, VL);
10020 Chain = Src.getValue(1);
10024 ? RISCVISD::STRICT_FP_EXTEND_VL
10025 : RISCVISD::STRICT_FP_ROUND_VL;
10027 Chain, Src, Mask, VL);
10038RISCVTargetLowering::lowerVectorFPExtendOrRoundLike(
SDValue Op,
10041 Op.getOpcode() == ISD::VP_FP_ROUND ||
Op.getOpcode() == ISD::VP_FP_EXTEND;
10043 Op.getOpcode() == ISD::VP_FP_EXTEND ||
Op.getOpcode() == ISD::FP_EXTEND;
10048 MVT VT =
Op.getSimpleValueType();
10050 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
10053 MVT SrcVT = Src.getSimpleValueType();
10055 bool IsDirectExtend =
10063 bool IsDirectConv = IsDirectExtend || IsDirectTrunc;
10070 MVT ContainerVT = VT;
10073 Mask =
Op.getOperand(1);
10074 VL =
Op.getOperand(2);
10088 std::tie(Mask, VL) =
10091 unsigned ConvOpc = IsExtend ? RISCVISD::FP_EXTEND_VL : RISCVISD::FP_ROUND_VL;
10093 if (IsDirectConv) {
10094 Src = DAG.
getNode(ConvOpc,
DL, ContainerVT, Src, Mask, VL);
10100 unsigned InterConvOpc =
10101 IsExtend ? RISCVISD::FP_EXTEND_VL : RISCVISD::VFNCVT_ROD_VL;
10105 DAG.
getNode(InterConvOpc,
DL, InterVT, Src, Mask, VL);
10107 DAG.
getNode(ConvOpc,
DL, ContainerVT, IntermediateConv, Mask, VL);
10118static std::optional<MVT>
10124 const unsigned MinVLMAX = VectorBitsMin / EltSize;
10126 if (MaxIdx < MinVLMAX)
10128 else if (MaxIdx < MinVLMAX * 2)
10131 else if (MaxIdx < MinVLMAX * 4)
10136 return std::nullopt;
10144 return isUInt<5>(IdxC->getZExtValue());
10156 MVT VecVT =
Op.getSimpleValueType();
10157 MVT XLenVT = Subtarget.getXLenVT();
10172 if ((ValVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
10173 ValVT == MVT::bf16) {
10178 DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Val), Idx);
10182 MVT ContainerVT = VecVT;
10192 std::optional<unsigned> AlignedIdx;
10194 const unsigned OrigIdx = IdxC->getZExtValue();
10197 DL, DAG, Subtarget)) {
10198 ContainerVT = *ShrunkVT;
10206 if (
auto VLEN = Subtarget.getRealVLen(); VLEN && ContainerVT.
bitsGT(M1VT)) {
10209 unsigned RemIdx = OrigIdx % ElemsPerVReg;
10210 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
10213 ContainerVT = M1VT;
10220 bool IsLegalInsert = Subtarget.is64Bit() || Val.
getValueType() != MVT::i64;
10228 IsLegalInsert =
true;
10237 if (IsLegalInsert) {
10239 VecVT.
isFloatingPoint() ? RISCVISD::VFMV_S_F_VL : RISCVISD::VMV_S_X_VL;
10243 Vec = DAG.
getNode(
Opc,
DL, ContainerVT, Vec, Val, VL);
10253 if (Subtarget.hasVendorXRivosVisni() && VecVT.
isInteger() &&
10258 Vec = DAG.
getNode(RISCVISD::RI_VINSERT_VL,
DL, ContainerVT, Vec, Val, Idx,
10274 std::tie(ValLo, ValHi) = DAG.
SplitScalar(Val,
DL, MVT::i32, MVT::i32);
10275 MVT I32ContainerVT =
10285 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10286 Vec, Vec, ValLo, I32Mask, InsertI64VL);
10290 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10291 Tail, ValInVec, ValHi, I32Mask, InsertI64VL);
10293 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
10304 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10306 DAG.
getUNDEF(I32ContainerVT), ValLo,
10307 I32Mask, InsertI64VL);
10308 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10309 DAG.
getUNDEF(I32ContainerVT), ValInVec, ValHi,
10310 I32Mask, InsertI64VL);
10312 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
10325 Idx, Mask, InsertVL, Policy);
10343 EVT EltVT =
Op.getValueType();
10345 MVT XLenVT = Subtarget.getXLenVT();
10350 MVT ContainerVT = VecVT;
10357 DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Vec, Mask, VL);
10364 if (NumElts >= 8) {
10366 unsigned WidenVecLen;
10369 unsigned MaxEEW = Subtarget.getELen();
10374 "the number of elements should be power of 2");
10378 ExtractBitIdx = Idx;
10380 WideEltVT = LargestEltVT;
10383 ExtractElementIdx = DAG.
getNode(
10392 Vec = DAG.
getNode(ISD::BITCAST,
DL, WideVT, Vec);
10394 Vec, ExtractElementIdx);
10409 if ((EltVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
10410 EltVT == MVT::bf16) {
10416 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, EltVT, IntExtract);
10420 MVT ContainerVT = VecVT;
10430 const auto VLen = Subtarget.getRealVLen();
10432 IdxC && VLen && VecVT.
getSizeInBits().getKnownMinValue() > *VLen) {
10434 unsigned OrigIdx = IdxC->getZExtValue();
10437 unsigned RemIdx = OrigIdx % ElemsPerVReg;
10438 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
10439 unsigned ExtractIdx =
10443 ContainerVT = M1VT;
10448 std::optional<uint64_t> MaxIdx;
10452 MaxIdx = IdxC->getZExtValue();
10454 if (
auto SmallerVT =
10456 ContainerVT = *SmallerVT;
10463 if (Subtarget.hasVendorXRivosVisni() && EltVT.
isInteger() &&
10491 DAG.
getUNDEF(ContainerVT), Vec, Idx, Mask, VL);
10510 "Unexpected opcode");
10517 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
10522 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
10523 if (!
II || !
II->hasScalarOperand())
10526 unsigned SplatOp =
II->ScalarOperand + 1 + HasChain;
10527 assert(SplatOp <
Op.getNumOperands());
10539 if (OpVT.
bitsLT(XLenVT)) {
10546 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
10556 assert(
II->ScalarOperand > 0 &&
"Unexpected splat operand!");
10557 MVT VT =
Op.getOperand(SplatOp - 1).getSimpleValueType();
10560 assert(XLenVT == MVT::i32 && OpVT == MVT::i64 &&
10571 case Intrinsic::riscv_vslide1up:
10572 case Intrinsic::riscv_vslide1down:
10573 case Intrinsic::riscv_vslide1up_mask:
10574 case Intrinsic::riscv_vslide1down_mask: {
10576 unsigned NumOps =
Op.getNumOperands();
10577 bool IsMasked =
NumOps == 7;
10583 std::tie(ScalarLo, ScalarHi) =
10592 const auto [MinVLMAX, MaxVLMAX] =
10596 if (AVLInt <= MinVLMAX) {
10598 }
else if (AVLInt >= 2 * MaxVLMAX) {
10632 if (IntNo == Intrinsic::riscv_vslide1up ||
10633 IntNo == Intrinsic::riscv_vslide1up_mask) {
10634 Vec = DAG.
getNode(RISCVISD::VSLIDE1UP_VL,
DL, I32VT, Passthru, Vec,
10635 ScalarHi, I32Mask, I32VL);
10636 Vec = DAG.
getNode(RISCVISD::VSLIDE1UP_VL,
DL, I32VT, Passthru, Vec,
10637 ScalarLo, I32Mask, I32VL);
10639 Vec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32VT, Passthru, Vec,
10640 ScalarLo, I32Mask, I32VL);
10641 Vec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32VT, Passthru, Vec,
10642 ScalarHi, I32Mask, I32VL);
10660 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, Mask, Vec, MaskedOff,
10664 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, Mask, Vec, MaskedOff,
10691 const unsigned ElementWidth = 8;
10696 [[maybe_unused]]
unsigned MinVF =
10699 [[maybe_unused]]
unsigned VF =
N->getConstantOperandVal(2);
10703 bool Fractional = VF < LMul1VF;
10704 unsigned LMulVal = Fractional ? LMul1VF / VF : VF / LMul1VF;
10725 MVT ContainerVT = OpVT;
10733 SDValue Res = DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Op0, Mask, VL);
10741 return DAG.
getSelect(
DL, XLenVT, Setcc, VL, Res);
10752 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
10756 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
10757 if (!
II || !
II->hasScalarOperand())
10760 unsigned SplatOp =
II->ScalarOperand + 1;
10761 assert(SplatOp <
Op.getNumOperands());
10773 if (OpVT.
bitsLT(XLenVT)) {
10776 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
10787 EVT ValType = V.getValueType();
10788 if (ValType.isVector() && ValType.isFloatingPoint()) {
10791 ValType.getVectorElementCount());
10794 if (ValType.isFixedLengthVector()) {
10796 DAG, V.getSimpleValueType(), Subtarget);
10812 unsigned IntNo =
Op.getConstantOperandVal(0);
10814 MVT XLenVT = Subtarget.getXLenVT();
10819 case Intrinsic::riscv_tuple_insert: {
10824 return DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL,
Op.getValueType(), Vec,
10827 case Intrinsic::riscv_tuple_extract: {
10831 return DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL,
Op.getValueType(), Vec,
10834 case Intrinsic::thread_pointer: {
10838 case Intrinsic::riscv_orc_b:
10839 case Intrinsic::riscv_brev8:
10840 case Intrinsic::riscv_sha256sig0:
10841 case Intrinsic::riscv_sha256sig1:
10842 case Intrinsic::riscv_sha256sum0:
10843 case Intrinsic::riscv_sha256sum1:
10844 case Intrinsic::riscv_sm3p0:
10845 case Intrinsic::riscv_sm3p1: {
10848 case Intrinsic::riscv_orc_b:
Opc = RISCVISD::ORC_B;
break;
10849 case Intrinsic::riscv_brev8:
Opc = RISCVISD::BREV8;
break;
10850 case Intrinsic::riscv_sha256sig0:
Opc = RISCVISD::SHA256SIG0;
break;
10851 case Intrinsic::riscv_sha256sig1:
Opc = RISCVISD::SHA256SIG1;
break;
10852 case Intrinsic::riscv_sha256sum0:
Opc = RISCVISD::SHA256SUM0;
break;
10853 case Intrinsic::riscv_sha256sum1:
Opc = RISCVISD::SHA256SUM1;
break;
10854 case Intrinsic::riscv_sm3p0:
Opc = RISCVISD::SM3P0;
break;
10855 case Intrinsic::riscv_sm3p1:
Opc = RISCVISD::SM3P1;
break;
10860 case Intrinsic::riscv_sm4ks:
10861 case Intrinsic::riscv_sm4ed: {
10863 IntNo == Intrinsic::riscv_sm4ks ? RISCVISD::SM4KS : RISCVISD::SM4ED;
10868 case Intrinsic::riscv_zip:
10869 case Intrinsic::riscv_unzip: {
10871 IntNo == Intrinsic::riscv_zip ? RISCVISD::ZIP : RISCVISD::UNZIP;
10874 case Intrinsic::riscv_mopr:
10875 return DAG.
getNode(RISCVISD::MOP_R,
DL, XLenVT,
Op.getOperand(1),
10878 case Intrinsic::riscv_moprr: {
10879 return DAG.
getNode(RISCVISD::MOP_RR,
DL, XLenVT,
Op.getOperand(1),
10880 Op.getOperand(2),
Op.getOperand(3));
10882 case Intrinsic::riscv_clmul:
10883 return DAG.
getNode(RISCVISD::CLMUL,
DL, XLenVT,
Op.getOperand(1),
10885 case Intrinsic::riscv_clmulh:
10886 case Intrinsic::riscv_clmulr: {
10888 IntNo == Intrinsic::riscv_clmulh ? RISCVISD::CLMULH : RISCVISD::CLMULR;
10891 case Intrinsic::experimental_get_vector_length:
10893 case Intrinsic::experimental_cttz_elts:
10895 case Intrinsic::riscv_vmv_x_s: {
10899 case Intrinsic::riscv_vfmv_f_s:
10901 case Intrinsic::riscv_vmv_v_x:
10903 Op.getOperand(3),
Op.getSimpleValueType(),
DL, DAG,
10905 case Intrinsic::riscv_vfmv_v_f:
10906 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL,
Op.getValueType(),
10907 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
10908 case Intrinsic::riscv_vmv_s_x: {
10911 if (
Scalar.getValueType().bitsLE(XLenVT)) {
10913 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL,
Op.getValueType(),
10914 Op.getOperand(1), Scalar,
Op.getOperand(3));
10917 assert(
Scalar.getValueType() == MVT::i64 &&
"Unexpected scalar VT!");
10934 MVT VT =
Op.getSimpleValueType();
10939 if (
Op.getOperand(1).isUndef())
10940 return SplattedVal;
10949 DAG.
getNode(RISCVISD::SETCC_VL,
DL, MaskVT,
10952 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, SelectCond, SplattedVal,
10955 case Intrinsic::riscv_vfmv_s_f:
10956 return DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL,
Op.getSimpleValueType(),
10957 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
10959 case Intrinsic::riscv_vaesdf_vv:
10960 case Intrinsic::riscv_vaesdf_vs:
10961 case Intrinsic::riscv_vaesdm_vv:
10962 case Intrinsic::riscv_vaesdm_vs:
10963 case Intrinsic::riscv_vaesef_vv:
10964 case Intrinsic::riscv_vaesef_vs:
10965 case Intrinsic::riscv_vaesem_vv:
10966 case Intrinsic::riscv_vaesem_vs:
10967 case Intrinsic::riscv_vaeskf1:
10968 case Intrinsic::riscv_vaeskf2:
10969 case Intrinsic::riscv_vaesz_vs:
10970 case Intrinsic::riscv_vsm4k:
10971 case Intrinsic::riscv_vsm4r_vv:
10972 case Intrinsic::riscv_vsm4r_vs: {
10973 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
10974 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
10975 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
10980 case Intrinsic::riscv_vsm3c:
10981 case Intrinsic::riscv_vsm3me: {
10982 if (!
isValidEGW(8,
Op.getSimpleValueType(), Subtarget) ||
10983 !
isValidEGW(8,
Op->getOperand(1).getSimpleValueType(), Subtarget))
10988 case Intrinsic::riscv_vsha2ch:
10989 case Intrinsic::riscv_vsha2cl:
10990 case Intrinsic::riscv_vsha2ms: {
10991 if (
Op->getSimpleValueType(0).getScalarSizeInBits() == 64 &&
10992 !Subtarget.hasStdExtZvknhb())
10994 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
10995 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
10996 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
11000 case Intrinsic::riscv_sf_vc_v_x:
11001 case Intrinsic::riscv_sf_vc_v_i:
11002 case Intrinsic::riscv_sf_vc_v_xv:
11003 case Intrinsic::riscv_sf_vc_v_iv:
11004 case Intrinsic::riscv_sf_vc_v_vv:
11005 case Intrinsic::riscv_sf_vc_v_fv:
11006 case Intrinsic::riscv_sf_vc_v_xvv:
11007 case Intrinsic::riscv_sf_vc_v_ivv:
11008 case Intrinsic::riscv_sf_vc_v_vvv:
11009 case Intrinsic::riscv_sf_vc_v_fvv:
11010 case Intrinsic::riscv_sf_vc_v_xvw:
11011 case Intrinsic::riscv_sf_vc_v_ivw:
11012 case Intrinsic::riscv_sf_vc_v_vvw:
11013 case Intrinsic::riscv_sf_vc_v_fvw: {
11014 MVT VT =
Op.getSimpleValueType();
11051 MVT VT =
Op.getSimpleValueType();
11055 if (VT.isFloatingPoint()) {
11057 VT.getVectorElementCount());
11060 if (VT.isFixedLengthVector())
11070 if (VT.isFixedLengthVector())
11072 if (VT.isFloatingPoint())
11095 case Intrinsic::riscv_seg2_load_mask:
11096 case Intrinsic::riscv_seg3_load_mask:
11097 case Intrinsic::riscv_seg4_load_mask:
11098 case Intrinsic::riscv_seg5_load_mask:
11099 case Intrinsic::riscv_seg6_load_mask:
11100 case Intrinsic::riscv_seg7_load_mask:
11101 case Intrinsic::riscv_seg8_load_mask:
11104 case Intrinsic::riscv_sseg2_load_mask:
11105 case Intrinsic::riscv_sseg3_load_mask:
11106 case Intrinsic::riscv_sseg4_load_mask:
11107 case Intrinsic::riscv_sseg5_load_mask:
11108 case Intrinsic::riscv_sseg6_load_mask:
11109 case Intrinsic::riscv_sseg7_load_mask:
11110 case Intrinsic::riscv_sseg8_load_mask:
11118 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
11119 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
11120 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
11121 Intrinsic::riscv_vlseg8_mask};
11123 Intrinsic::riscv_vlsseg2_mask, Intrinsic::riscv_vlsseg3_mask,
11124 Intrinsic::riscv_vlsseg4_mask, Intrinsic::riscv_vlsseg5_mask,
11125 Intrinsic::riscv_vlsseg6_mask, Intrinsic::riscv_vlsseg7_mask,
11126 Intrinsic::riscv_vlsseg8_mask};
11129 unsigned NF =
Op->getNumValues() - 1;
11130 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
11132 MVT VT =
Op->getSimpleValueType(0);
11140 SDValue VL =
Op.getOperand(
Op.getNumOperands() - 1);
11141 SDValue Mask =
Op.getOperand(
Op.getNumOperands() - 2);
11142 MVT MaskVT = Mask.getSimpleValueType();
11143 MVT MaskContainerVT =
11148 IsStrided ? VlssegInts[NF - 2] : VlsegInts[NF - 2],
DL, XLenVT);
11164 Ops.insert(std::next(
Ops.begin(), 4),
Op.getOperand(3));
11168 Load->getMemoryVT(), Load->getMemOperand());
11170 for (
unsigned int RetIdx = 0; RetIdx < NF; RetIdx++) {
11172 Result.getValue(0),
11176 Results.push_back(Result.getValue(1));
11182 unsigned IntNo =
Op.getConstantOperandVal(1);
11186 case Intrinsic::riscv_seg2_load_mask:
11187 case Intrinsic::riscv_seg3_load_mask:
11188 case Intrinsic::riscv_seg4_load_mask:
11189 case Intrinsic::riscv_seg5_load_mask:
11190 case Intrinsic::riscv_seg6_load_mask:
11191 case Intrinsic::riscv_seg7_load_mask:
11192 case Intrinsic::riscv_seg8_load_mask:
11193 case Intrinsic::riscv_sseg2_load_mask:
11194 case Intrinsic::riscv_sseg3_load_mask:
11195 case Intrinsic::riscv_sseg4_load_mask:
11196 case Intrinsic::riscv_sseg5_load_mask:
11197 case Intrinsic::riscv_sseg6_load_mask:
11198 case Intrinsic::riscv_sseg7_load_mask:
11199 case Intrinsic::riscv_sseg8_load_mask:
11202 case Intrinsic::riscv_sf_vc_v_x_se:
11204 case Intrinsic::riscv_sf_vc_v_i_se:
11206 case Intrinsic::riscv_sf_vc_v_xv_se:
11208 case Intrinsic::riscv_sf_vc_v_iv_se:
11210 case Intrinsic::riscv_sf_vc_v_vv_se:
11212 case Intrinsic::riscv_sf_vc_v_fv_se:
11214 case Intrinsic::riscv_sf_vc_v_xvv_se:
11216 case Intrinsic::riscv_sf_vc_v_ivv_se:
11218 case Intrinsic::riscv_sf_vc_v_vvv_se:
11220 case Intrinsic::riscv_sf_vc_v_fvv_se:
11222 case Intrinsic::riscv_sf_vc_v_xvw_se:
11224 case Intrinsic::riscv_sf_vc_v_ivw_se:
11226 case Intrinsic::riscv_sf_vc_v_vvw_se:
11228 case Intrinsic::riscv_sf_vc_v_fvw_se:
11241 case Intrinsic::riscv_seg2_store_mask:
11242 case Intrinsic::riscv_seg3_store_mask:
11243 case Intrinsic::riscv_seg4_store_mask:
11244 case Intrinsic::riscv_seg5_store_mask:
11245 case Intrinsic::riscv_seg6_store_mask:
11246 case Intrinsic::riscv_seg7_store_mask:
11247 case Intrinsic::riscv_seg8_store_mask:
11250 case Intrinsic::riscv_sseg2_store_mask:
11251 case Intrinsic::riscv_sseg3_store_mask:
11252 case Intrinsic::riscv_sseg4_store_mask:
11253 case Intrinsic::riscv_sseg5_store_mask:
11254 case Intrinsic::riscv_sseg6_store_mask:
11255 case Intrinsic::riscv_sseg7_store_mask:
11256 case Intrinsic::riscv_sseg8_store_mask:
11265 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
11266 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
11267 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
11268 Intrinsic::riscv_vsseg8_mask};
11270 Intrinsic::riscv_vssseg2_mask, Intrinsic::riscv_vssseg3_mask,
11271 Intrinsic::riscv_vssseg4_mask, Intrinsic::riscv_vssseg5_mask,
11272 Intrinsic::riscv_vssseg6_mask, Intrinsic::riscv_vssseg7_mask,
11273 Intrinsic::riscv_vssseg8_mask};
11277 unsigned NF =
Op->getNumOperands() - (IsStrided ? 6 : 5);
11278 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
11280 MVT VT =
Op->getOperand(2).getSimpleValueType();
11286 SDValue VL =
Op.getOperand(
Op.getNumOperands() - 1);
11287 SDValue Mask =
Op.getOperand(
Op.getNumOperands() - 2);
11288 MVT MaskVT = Mask.getSimpleValueType();
11289 MVT MaskContainerVT =
11294 IsStrided ? VsssegInts[NF - 2] : VssegInts[NF - 2],
DL, XLenVT);
11300 for (
unsigned i = 0; i < NF; i++)
11302 RISCVISD::TUPLE_INSERT,
DL, VecTupTy, StoredVal,
11308 FixedIntrinsic->getChain(),
11317 Ops.insert(std::next(
Ops.begin(), 4),
11318 Op.getOperand(
Op.getNumOperands() - 3));
11322 FixedIntrinsic->getMemoryVT(), FixedIntrinsic->getMemOperand());
11327 unsigned IntNo =
Op.getConstantOperandVal(1);
11331 case Intrinsic::riscv_seg2_store_mask:
11332 case Intrinsic::riscv_seg3_store_mask:
11333 case Intrinsic::riscv_seg4_store_mask:
11334 case Intrinsic::riscv_seg5_store_mask:
11335 case Intrinsic::riscv_seg6_store_mask:
11336 case Intrinsic::riscv_seg7_store_mask:
11337 case Intrinsic::riscv_seg8_store_mask:
11338 case Intrinsic::riscv_sseg2_store_mask:
11339 case Intrinsic::riscv_sseg3_store_mask:
11340 case Intrinsic::riscv_sseg4_store_mask:
11341 case Intrinsic::riscv_sseg5_store_mask:
11342 case Intrinsic::riscv_sseg6_store_mask:
11343 case Intrinsic::riscv_sseg7_store_mask:
11344 case Intrinsic::riscv_sseg8_store_mask:
11347 case Intrinsic::riscv_sf_vc_xv_se:
11349 case Intrinsic::riscv_sf_vc_iv_se:
11351 case Intrinsic::riscv_sf_vc_vv_se:
11353 case Intrinsic::riscv_sf_vc_fv_se:
11355 case Intrinsic::riscv_sf_vc_xvv_se:
11357 case Intrinsic::riscv_sf_vc_ivv_se:
11359 case Intrinsic::riscv_sf_vc_vvv_se:
11361 case Intrinsic::riscv_sf_vc_fvv_se:
11363 case Intrinsic::riscv_sf_vc_xvw_se:
11365 case Intrinsic::riscv_sf_vc_ivw_se:
11367 case Intrinsic::riscv_sf_vc_vvw_se:
11369 case Intrinsic::riscv_sf_vc_fvw_se:
11377 switch (ISDOpcode) {
11380 case ISD::VP_REDUCE_ADD:
11381 case ISD::VECREDUCE_ADD:
11382 return RISCVISD::VECREDUCE_ADD_VL;
11383 case ISD::VP_REDUCE_UMAX:
11384 case ISD::VECREDUCE_UMAX:
11385 return RISCVISD::VECREDUCE_UMAX_VL;
11386 case ISD::VP_REDUCE_SMAX:
11387 case ISD::VECREDUCE_SMAX:
11388 return RISCVISD::VECREDUCE_SMAX_VL;
11389 case ISD::VP_REDUCE_UMIN:
11390 case ISD::VECREDUCE_UMIN:
11391 return RISCVISD::VECREDUCE_UMIN_VL;
11392 case ISD::VP_REDUCE_SMIN:
11393 case ISD::VECREDUCE_SMIN:
11394 return RISCVISD::VECREDUCE_SMIN_VL;
11395 case ISD::VP_REDUCE_AND:
11396 case ISD::VECREDUCE_AND:
11397 return RISCVISD::VECREDUCE_AND_VL;
11398 case ISD::VP_REDUCE_OR:
11399 case ISD::VECREDUCE_OR:
11400 return RISCVISD::VECREDUCE_OR_VL;
11401 case ISD::VP_REDUCE_XOR:
11402 case ISD::VECREDUCE_XOR:
11403 return RISCVISD::VECREDUCE_XOR_VL;
11404 case ISD::VP_REDUCE_FADD:
11405 return RISCVISD::VECREDUCE_FADD_VL;
11406 case ISD::VP_REDUCE_SEQ_FADD:
11407 return RISCVISD::VECREDUCE_SEQ_FADD_VL;
11408 case ISD::VP_REDUCE_FMAX:
11409 case ISD::VP_REDUCE_FMAXIMUM:
11410 return RISCVISD::VECREDUCE_FMAX_VL;
11411 case ISD::VP_REDUCE_FMIN:
11412 case ISD::VP_REDUCE_FMINIMUM:
11413 return RISCVISD::VECREDUCE_FMIN_VL;
11422 SDValue Vec =
Op.getOperand(IsVP ? 1 : 0);
11424 assert((
Op.getOpcode() == ISD::VECREDUCE_AND ||
11425 Op.getOpcode() == ISD::VECREDUCE_OR ||
11426 Op.getOpcode() == ISD::VECREDUCE_XOR ||
11427 Op.getOpcode() == ISD::VP_REDUCE_AND ||
11428 Op.getOpcode() == ISD::VP_REDUCE_OR ||
11429 Op.getOpcode() == ISD::VP_REDUCE_XOR) &&
11430 "Unexpected reduction lowering");
11432 MVT XLenVT = Subtarget.getXLenVT();
11434 MVT ContainerVT = VecVT;
11442 Mask =
Op.getOperand(2);
11443 VL =
Op.getOperand(3);
11445 std::tie(Mask, VL) =
11450 switch (
Op.getOpcode()) {
11453 case ISD::VECREDUCE_AND:
11454 case ISD::VP_REDUCE_AND: {
11458 Vec = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Vec, TrueMask, VL);
11461 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11465 case ISD::VECREDUCE_OR:
11466 case ISD::VP_REDUCE_OR:
11468 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11471 case ISD::VECREDUCE_XOR:
11472 case ISD::VP_REDUCE_XOR: {
11475 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11496 return DAG.
getNode(BaseOpc,
DL,
Op.getValueType(), SetCC,
Op.getOperand(0));
11502 return (RegisterAVL && RegisterAVL->getReg() == RISCV::X0) ||
11503 (ImmAVL && ImmAVL->getZExtValue() >= 1);
11519 auto InnerVT = VecVT.
bitsLE(M1VT) ? VecVT : M1VT;
11523 auto InnerVL = NonZeroAVL ? VL : DAG.
getConstant(1,
DL, XLenVT);
11526 if (M1VT != InnerVT)
11531 SDValue Ops[] = {PassThru, Vec, InitialValue, Mask, VL, Policy};
11549 VecEVT =
Lo.getValueType();
11562 MVT ContainerVT = VecVT;
11581 Mask, VL,
DL, DAG, Subtarget);
11587static std::tuple<unsigned, SDValue, SDValue>
11591 auto Flags =
Op->getFlags();
11592 unsigned Opcode =
Op.getOpcode();
11596 case ISD::VECREDUCE_FADD: {
11600 return std::make_tuple(RISCVISD::VECREDUCE_FADD_VL,
Op.getOperand(0), Zero);
11602 case ISD::VECREDUCE_SEQ_FADD:
11603 return std::make_tuple(RISCVISD::VECREDUCE_SEQ_FADD_VL,
Op.getOperand(1),
11605 case ISD::VECREDUCE_FMINIMUM:
11606 case ISD::VECREDUCE_FMAXIMUM:
11607 case ISD::VECREDUCE_FMIN:
11608 case ISD::VECREDUCE_FMAX: {
11611 (Opcode == ISD::VECREDUCE_FMIN || Opcode == ISD::VECREDUCE_FMINIMUM)
11612 ? RISCVISD::VECREDUCE_FMIN_VL
11613 : RISCVISD::VECREDUCE_FMAX_VL;
11614 return std::make_tuple(RVVOpc,
Op.getOperand(0), Front);
11622 MVT VecEltVT =
Op.getSimpleValueType();
11624 unsigned RVVOpcode;
11625 SDValue VectorVal, ScalarVal;
11626 std::tie(RVVOpcode, VectorVal, ScalarVal) =
11630 MVT ContainerVT = VecVT;
11636 MVT ResVT =
Op.getSimpleValueType();
11639 VL,
DL, DAG, Subtarget);
11640 if (
Op.getOpcode() != ISD::VECREDUCE_FMINIMUM &&
11641 Op.getOpcode() != ISD::VECREDUCE_FMAXIMUM)
11644 if (
Op->getFlags().hasNoNaNs())
11650 {VectorVal, VectorVal, DAG.getCondCode(ISD::SETNE),
11651 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
11652 MVT XLenVT = Subtarget.getXLenVT();
11653 SDValue CPop = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, IsNan, Mask, VL);
11657 DL, ResVT, NoNaNs, Res,
11664 unsigned Opc =
Op.getOpcode();
11668 MVT XLenVT = Subtarget.getXLenVT();
11687 Vec, Mask, VL,
DL, DAG, Subtarget);
11688 if ((
Opc != ISD::VP_REDUCE_FMINIMUM &&
Opc != ISD::VP_REDUCE_FMAXIMUM) ||
11689 Op->getFlags().hasNoNaNs())
11696 RISCVISD::SETCC_VL,
DL, PredVT,
11698 SDValue VCPop = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, IsNaN, Mask, VL);
11706 DL, ResVT, NoNaNs, Res,
11718 MVT XLenVT = Subtarget.getXLenVT();
11719 unsigned OrigIdx =
Op.getConstantOperandVal(2);
11720 const RISCVRegisterInfo *
TRI = Subtarget.getRegisterInfo();
11722 if (OrigIdx == 0 && Vec.
isUndef())
11733 assert(OrigIdx % 8 == 0 &&
"Invalid index");
11736 "Unexpected mask vector lowering");
11766 const auto VLen = Subtarget.getRealVLen();
11768 MVT ContainerVT = VecVT;
11790 if (OrigIdx == 0) {
11792 DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, ContainerVT, Vec, SubVec, VL);
11795 SubVec =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, Vec, SubVec,
11796 SlideupAmt, Mask, VL, Policy);
11804 MVT ContainerVecVT = VecVT;
11810 MVT ContainerSubVecVT = SubVecVT;
11816 unsigned SubRegIdx;
11817 ElementCount RemIdx;
11826 ContainerVecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
11827 SubRegIdx = Decompose.first;
11829 (OrigIdx % Vscale));
11833 ContainerVecVT, ContainerSubVecVT, OrigIdx,
TRI);
11834 SubRegIdx = Decompose.first;
11840 Subtarget.expandVScale(SubVecVT.
getSizeInBits()).getKnownMinValue()));
11841 bool ExactlyVecRegSized =
11843 .isKnownMultipleOf(Subtarget.expandVScale(VecRegSize));
11858 if (RemIdx.
isZero() && (ExactlyVecRegSized || Vec.
isUndef())) {
11862 if (SubRegIdx == RISCV::NoSubRegister) {
11884 MVT InterSubVT = ContainerVecVT;
11885 SDValue AlignedExtract = Vec;
11907 if (Subtarget.expandVScale(EndIndex) ==
11914 SubVec = DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, InterSubVT, AlignedExtract,
11922 SubVec =
getVSlideup(DAG, Subtarget,
DL, InterSubVT, AlignedExtract, SubVec,
11923 SlideupAmt, Mask, VL, Policy);
11928 if (ContainerVecVT.
bitsGT(InterSubVT))
11936 return DAG.
getBitcast(
Op.getSimpleValueType(), SubVec);
11942 MVT SubVecVT =
Op.getSimpleValueType();
11946 MVT XLenVT = Subtarget.getXLenVT();
11947 unsigned OrigIdx =
Op.getConstantOperandVal(1);
11948 const RISCVRegisterInfo *
TRI = Subtarget.getRegisterInfo();
11963 assert(OrigIdx % 8 == 0 &&
"Invalid index");
11966 "Unexpected mask vector lowering");
11992 const auto VLen = Subtarget.getRealVLen();
12000 MVT ContainerVT = VecVT;
12008 if (
auto ShrunkVT =
12010 ContainerVT = *ShrunkVT;
12022 DAG.
getUNDEF(ContainerVT), Vec, SlidedownAmt, Mask, VL);
12033 MVT ContainerSubVecVT = SubVecVT;
12037 unsigned SubRegIdx;
12038 ElementCount RemIdx;
12047 VecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
12048 SubRegIdx = Decompose.first;
12050 (OrigIdx % Vscale));
12054 VecVT, ContainerSubVecVT, OrigIdx,
TRI);
12055 SubRegIdx = Decompose.first;
12082 MVT InterSubVT = VecVT;
12087 assert(SubRegIdx != RISCV::NoSubRegister);
12106 Vec, SlidedownAmt, Mask, VL);
12114 return DAG.
getBitcast(
Op.getSimpleValueType(), Slidedown);
12121 MVT VT =
N.getSimpleValueType();
12125 assert(
Op.getSimpleValueType() == VT &&
12126 "Operands and result must be same type");
12130 unsigned NumVals =
N->getNumValues();
12133 NumVals,
N.getValueType().changeVectorElementType(MVT::i8)));
12136 for (
unsigned I = 0;
I < NumVals;
I++) {
12142 if (TruncVals.
size() > 1)
12144 return TruncVals.
front();
12150 MVT VecVT =
Op.getSimpleValueType();
12152 const unsigned Factor =
Op->getNumValues();
12163 for (
unsigned i = 0U; i < Factor; ++i)
12172 for (
unsigned i = 0U; i < Factor; ++i)
12182 for (
unsigned i = 0; i != Factor; ++i) {
12185 Ops[i * 2 + 1] = OpHi;
12196 for (
unsigned i = 0; i != Factor; ++i)
12203 if (Subtarget.hasVendorXRivosVizip() && Factor == 2) {
12204 MVT VT =
Op->getSimpleValueType(0);
12229 lowerVZIP(RISCVISD::RI_VUNZIP2A_VL, V1, V2,
DL, DAG, Subtarget);
12231 lowerVZIP(RISCVISD::RI_VUNZIP2B_VL, V1, V2,
DL, DAG, Subtarget);
12264 EvenSplat = DAG.
getBitcast(MVT::nxv64i1, EvenSplat);
12268 OddSplat = DAG.
getBitcast(MVT::nxv64i1, OddSplat);
12273 EvenMask, DAG.
getUNDEF(ConcatVT));
12285 MVT XLenVT = Subtarget.getXLenVT();
12307 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
12308 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
12309 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
12310 Intrinsic::riscv_vlseg8_mask};
12334 for (
unsigned i = 0U; i < Factor; ++i)
12335 Res[i] = DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL, VecVT, Load,
12344 MVT VecVT =
Op.getSimpleValueType();
12357 for (
unsigned i = 0U; i < Factor; ++i)
12365 for (
unsigned i = 0U; i < Factor; ++i)
12371 MVT XLenVT = Subtarget.getXLenVT();
12378 for (
unsigned i = 0; i != Factor; ++i) {
12381 Ops[i + Factor] = OpHi;
12392 for (
unsigned i = 0; i != Factor; ++i) {
12393 unsigned IdxLo = 2 * i;
12394 unsigned IdxHi = 2 * i + 1;
12396 Res[IdxLo / Factor].getValue(IdxLo % Factor),
12397 Res[IdxHi / Factor].getValue(IdxHi % Factor));
12415 EVT PtrVT =
StackPtr.getValueType();
12421 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
12422 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
12423 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
12424 Intrinsic::riscv_vsseg8_mask,
12432 for (
unsigned i = 0; i < Factor; i++)
12434 DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VecTupTy, StoredVal,
12457 for (
unsigned i = 0; i != Factor; ++i) {
12461 Loads[i] = DAG.
getLoad(VecVT,
DL, Chain, StackPtr, PtrInfo);
12469 if (Subtarget.hasVendorXRivosVizip() && !
Op.getOperand(0).isUndef() &&
12470 !
Op.getOperand(1).isUndef()) {
12490 Op.getOperand(0),
Op.getOperand(1));
12514 DAG.
getNode(RISCVISD::ADD_VL,
DL, IdxVT, Idx, VLMax, Idx, OddMask, VL);
12519 Interleaved = DAG.
getNode(RISCVISD::VRGATHEREI16_VV_VL,
DL, ConcatVT,
12536 MVT VT =
Op.getSimpleValueType();
12538 MVT XLenVT = Subtarget.getXLenVT();
12541 uint64_t StepValImm =
Op.getConstantOperandVal(0);
12542 if (StepValImm != 1) {
12551 VL, VT,
DL, DAG, Subtarget);
12566 MVT VecVT =
Op.getSimpleValueType();
12575 MVT ContainerVT = VecVT;
12582 MVT XLenVT = Subtarget.getXLenVT();
12628 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
12629 unsigned MaxVLMAX =
12634 unsigned GatherOpc = RISCVISD::VRGATHER_VV_VL;
12639 if (MaxVLMAX > 256 && EltSize == 8) {
12653 LoVT.getVectorMinNumElements());
12658 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
12666 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
12691 DAG.
getUNDEF(ContainerVT), Mask, VL);
12702 MVT XLenVT = Subtarget.getXLenVT();
12703 MVT VecVT =
Op.getSimpleValueType();
12708 SDValue DownOffset, UpOffset;
12709 if (ImmValue >= 0) {
12724 DAG, Subtarget,
DL, VecVT, DAG.
getUNDEF(VecVT), V1, DownOffset, TrueMask,
12725 Subtarget.hasVLDependentLatency() ? UpOffset
12727 return getVSlideup(DAG, Subtarget,
DL, VecVT, SlideDown, V2, UpOffset,
12733RISCVTargetLowering::lowerFixedLengthVectorLoadToRVV(
SDValue Op,
12739 Load->getMemoryVT(),
12740 *
Load->getMemOperand()) &&
12741 "Expecting a correctly-aligned load");
12743 MVT VT =
Op.getSimpleValueType();
12744 MVT XLenVT = Subtarget.getXLenVT();
12749 const auto [MinVLMAX, MaxVLMAX] =
12753 MachineMemOperand *MMO =
Load->getMemOperand();
12766 IsMaskOp ? Intrinsic::riscv_vlm : Intrinsic::riscv_vle,
DL, XLenVT);
12770 Ops.push_back(
Load->getBasePtr());
12772 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
12775 Load->getMemoryVT(),
Load->getMemOperand());
12782RISCVTargetLowering::lowerFixedLengthVectorStoreToRVV(
SDValue Op,
12788 Store->getMemoryVT(),
12789 *
Store->getMemOperand()) &&
12790 "Expecting a correctly-aligned store");
12794 MVT XLenVT = Subtarget.getXLenVT();
12810 const auto [MinVLMAX, MaxVLMAX] =
12814 MachineMemOperand *MMO =
Store->getMemOperand();
12824 IsMaskOp ? Intrinsic::riscv_vsm : Intrinsic::riscv_vse,
DL, XLenVT);
12827 {Store->getChain(), IntID, NewValue, Store->getBasePtr(), VL},
12828 Store->getMemoryVT(),
Store->getMemOperand());
12834 MVT VT =
Op.getSimpleValueType();
12837 EVT MemVT = MemSD->getMemoryVT();
12838 MachineMemOperand *MMO = MemSD->getMemOperand();
12839 SDValue Chain = MemSD->getChain();
12843 bool IsExpandingLoad =
false;
12845 Mask = VPLoad->getMask();
12847 VL = VPLoad->getVectorLength();
12850 Mask = MLoad->getMask();
12851 PassThru = MLoad->getPassThru();
12852 IsExpandingLoad = MLoad->isExpandingLoad();
12857 MVT XLenVT = Subtarget.getXLenVT();
12859 MVT ContainerVT = VT;
12873 if (!IsUnmasked && IsExpandingLoad) {
12876 DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Mask,
12880 unsigned IntID = IsUnmasked || IsExpandingLoad ? Intrinsic::riscv_vle
12881 : Intrinsic::riscv_vle_mask;
12883 if (IntID == Intrinsic::riscv_vle)
12886 Ops.push_back(PassThru);
12887 Ops.push_back(BasePtr);
12888 if (IntID == Intrinsic::riscv_vle_mask)
12889 Ops.push_back(Mask);
12891 if (IntID == Intrinsic::riscv_vle_mask)
12894 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
12898 Chain =
Result.getValue(1);
12900 MVT IndexVT = ContainerVT;
12905 bool UseVRGATHEREI16 =
false;
12913 UseVRGATHEREI16 =
true;
12919 DAG.
getUNDEF(IndexVT), Mask, ExpandingVL);
12921 DAG.
getNode(UseVRGATHEREI16 ? RISCVISD::VRGATHEREI16_VV_VL
12922 : RISCVISD::VRGATHER_VV_VL,
12923 DL, ContainerVT, Result, Iota, PassThru, Mask, ExpandingVL);
12934 MVT VT =
Op->getSimpleValueType(0);
12937 EVT MemVT = VPLoadFF->getMemoryVT();
12938 MachineMemOperand *MMO = VPLoadFF->getMemOperand();
12939 SDValue Chain = VPLoadFF->getChain();
12943 SDValue VL = VPLoadFF->getVectorLength();
12945 MVT XLenVT = Subtarget.getXLenVT();
12947 MVT ContainerVT = VT;
12954 unsigned IntID = Intrinsic::riscv_vleff_mask;
12964 SDVTList VTs = DAG.
getVTList({ContainerVT,
Op->getValueType(1), MVT::Other});
12969 Chain =
Result.getValue(2);
12982 EVT MemVT = MemSD->getMemoryVT();
12983 MachineMemOperand *MMO = MemSD->getMemOperand();
12984 SDValue Chain = MemSD->getChain();
12988 bool IsCompressingStore =
false;
12990 Val = VPStore->getValue();
12991 Mask = VPStore->getMask();
12992 VL = VPStore->getVectorLength();
12995 Val = MStore->getValue();
12996 Mask = MStore->getMask();
12997 IsCompressingStore = MStore->isCompressingStore();
13004 MVT XLenVT = Subtarget.getXLenVT();
13006 MVT ContainerVT = VT;
13011 if (!IsUnmasked || IsCompressingStore) {
13020 if (IsCompressingStore) {
13023 DAG.
getUNDEF(ContainerVT), Val, Mask, VL);
13025 DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Mask,
13030 IsUnmasked ? Intrinsic::riscv_vse : Intrinsic::riscv_vse_mask;
13032 Ops.push_back(Val);
13033 Ops.push_back(BasePtr);
13035 Ops.push_back(Mask);
13050 MVT XLenVT = Subtarget.getXLenVT();
13051 MVT ContainerVT = VT;
13064 Passthru, Val, Mask, VL);
13074 unsigned Opc =
Op.getOpcode();
13081 MVT VT =
Op.getSimpleValueType();
13089 SDVTList VTList =
Op->getVTList();
13114 MVT ContainerInVT = InVT;
13132 RISCVISD::STRICT_FSETCC_VL,
DL, DAG.
getVTList(MaskVT, MVT::Other),
13133 {Chain, Op1, Op1, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
13136 RISCVISD::STRICT_FSETCC_VL,
DL, DAG.
getVTList(MaskVT, MVT::Other),
13137 {Chain, Op2, Op2, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
13140 DAG.
getNode(RISCVISD::VMAND_VL,
DL, MaskVT, OrderMask1, OrderMask2, VL);
13143 Res = DAG.
getNode(RISCVISD::STRICT_FSETCCS_VL,
DL,
13145 {Chain, Op1, Op2, CC, Mask, Mask, VL});
13148 : RISCVISD::STRICT_FSETCCS_VL;
13150 {Chain, Op1, Op2, CC, DAG.getUNDEF(MaskVT), Mask, VL});
13163 MVT VT =
Op.getSimpleValueType();
13167 "Unexpected type for ISD::ABS");
13169 MVT ContainerVT = VT;
13176 if (
Op->getOpcode() == ISD::VP_ABS) {
13177 Mask =
Op->getOperand(1);
13181 VL =
Op->getOperand(2);
13186 RISCVISD::VMV_V_X_VL,
DL, ContainerVT, DAG.
getUNDEF(ContainerVT),
13189 DAG.
getUNDEF(ContainerVT), Mask, VL);
13191 DAG.
getUNDEF(ContainerVT), Mask, VL);
13200 const auto &TSInfo =
13204 bool HasPassthruOp = TSInfo.hasPassthruOp(NewOpc);
13205 bool HasMask = TSInfo.hasMaskOp(NewOpc);
13207 MVT VT =
Op.getSimpleValueType();
13212 for (
const SDValue &V :
Op->op_values()) {
13216 if (!
V.getValueType().isVector()) {
13222 assert(useRVVForFixedLengthVectorVT(
V.getSimpleValueType()) &&
13223 "Only fixed length vectors are supported!");
13225 V.getSimpleValueType().getVectorElementType());
13234 Ops.push_back(Mask);
13239 if (
Op->isStrictFPOpcode()) {
13258 const auto &TSInfo =
13262 bool HasPassthruOp = TSInfo.hasPassthruOp(RISCVISDOpc);
13265 MVT VT =
Op.getSimpleValueType();
13268 MVT ContainerVT = VT;
13277 if (HasPassthruOp) {
13280 if (*MaskIdx ==
OpIdx.index())
13284 if (
Op.getOpcode() == ISD::VP_MERGE) {
13286 Ops.push_back(
Ops.back());
13288 assert(
Op.getOpcode() == ISD::VP_SELECT);
13295 if (RISCVISDOpc == RISCVISD::VFCVT_RM_X_F_VL &&
13298 Subtarget.getXLenVT()));
13300 if (!
V.getValueType().isFixedLengthVector()) {
13305 MVT OpVT =
V.getSimpleValueType();
13307 assert(useRVVForFixedLengthVectorVT(OpVT) &&
13308 "Only fixed length vectors are supported!");
13323 MVT VT =
Op.getSimpleValueType();
13329 MVT ContainerVT = VT;
13336 MVT XLenVT = Subtarget.getXLenVT();
13339 DAG.
getUNDEF(ContainerVT), Zero, VL);
13342 Op.getOpcode() == ISD::VP_ZERO_EXTEND ? 1 : -1,
DL, XLenVT);
13344 DAG.
getUNDEF(ContainerVT), SplatValue, VL);
13347 ZeroSplat, DAG.
getUNDEF(ContainerVT), VL);
13356 MVT VT =
Op.getSimpleValueType();
13364 MVT ContainerVT = VT;
13372 SDValue AllOneMask = DAG.
getNode(RISCVISD::VMSET_VL,
DL, ContainerVT, VL);
13374 switch (Condition) {
13379 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, Op2, VL);
13384 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, Op2, VL);
13386 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, AllOneMask, VL);
13394 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, AllOneMask, VL);
13395 Result = DAG.
getNode(RISCVISD::VMAND_VL,
DL, ContainerVT, Temp, Op2, VL);
13403 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op2, AllOneMask, VL);
13404 Result = DAG.
getNode(RISCVISD::VMAND_VL,
DL, ContainerVT, Op1, Temp, VL);
13412 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, AllOneMask, VL);
13413 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, Op2, VL);
13421 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op2, AllOneMask, VL);
13422 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, Op1, VL);
13442 MVT DstVT =
Op.getSimpleValueType();
13443 MVT SrcVT = Src.getSimpleValueType();
13456 if (DstEltSize >= SrcEltSize) {
13460 unsigned RISCVISDExtOpc = RISCVISDOpc == RISCVISD::SINT_TO_FP_VL
13461 ? RISCVISD::VSEXT_VL
13462 : RISCVISD::VZEXT_VL;
13465 if (SrcEltSize == 1) {
13467 MVT XLenVT = Subtarget.getXLenVT();
13472 RISCVISDExtOpc == RISCVISD::VZEXT_VL ? 1 : -1,
DL, XLenVT);
13475 Src = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, IntVT, Src, OneSplat,
13476 ZeroSplat, DAG.
getUNDEF(IntVT), VL);
13477 }
else if (DstEltSize > (2 * SrcEltSize)) {
13481 Src = DAG.
getNode(RISCVISDExtOpc,
DL, IntVT, Src, Mask, VL);
13487 "Wrong input/output vector types");
13490 if (DstEltSize > (2 * SrcEltSize)) {
13495 DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, InterimFVT, Src, Mask, VL);
13506 MVT InterimFVT = DstVT;
13507 if (SrcEltSize > (2 * DstEltSize)) {
13508 assert(SrcEltSize == (4 * DstEltSize) &&
"Unexpected types!");
13515 if (InterimFVT != DstVT) {
13517 Result = DAG.
getNode(RISCVISD::FP_ROUND_VL,
DL, DstVT, Src, Mask, VL);
13521 "Wrong input/output vector types");
13525 if (DstEltSize == 1) {
13528 assert(SrcEltSize >= 16 &&
"Unexpected FP type!");
13535 MVT XLenVT = Subtarget.getXLenVT();
13537 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, InterimIVT,
13538 DAG.
getUNDEF(InterimIVT), SplatZero, VL);
13548 while (InterimIVT != DstVT) {
13560 MVT VT =
Op.getSimpleValueType();
13569 MVT VT =
Op.getSimpleValueType();
13570 MVT XLenVT = Subtarget.getXLenVT();
13583 MVT ContainerVT = VT;
13603 TrueVal = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, PromotedVT, TrueVal, SplatOne,
13604 SplatZero, DAG.
getUNDEF(PromotedVT), VL);
13607 SplatOne, SplatZero, DAG.
getUNDEF(PromotedVT), VLMax);
13611 TrueVal, FalseVal, FalseVal, VL);
13616 RISCVISD::SETCC_VL,
DL, ContainerVT,
13626RISCVTargetLowering::lowerVPSpliceExperimental(
SDValue Op,
13628 using namespace SDPatternMatch;
13639 const MVT XLenVT = Subtarget.getXLenVT();
13640 MVT VT =
Op.getSimpleValueType();
13641 MVT ContainerVT = VT;
13651 if (IsMaskVector) {
13661 Op1 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, Op1, SplatOneOp1,
13662 SplatZeroOp1, DAG.
getUNDEF(ContainerVT), EVL1);
13670 Op2 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, Op2, SplatOneOp2,
13671 SplatZeroOp2, DAG.
getUNDEF(ContainerVT), EVL2);
13674 auto getVectorFirstEle = [](
SDValue Vec) {
13687 if (
auto FirstEle = getVectorFirstEle(
Op->getOperand(0))) {
13690 if ((EltVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
13691 EltVT == MVT::bf16) {
13699 : RISCVISD::VSLIDE1UP_VL,
13700 DL, ContainerVT, DAG.
getUNDEF(ContainerVT), Op2,
13701 FirstEle, Mask, EVL2);
13711 SDValue DownOffset, UpOffset;
13712 if (ImmValue >= 0) {
13726 DAG.
getUNDEF(ContainerVT), Op1, DownOffset, Mask,
13727 Subtarget.hasVLDependentLatency() ? UpOffset : EVL2);
13731 if (IsMaskVector) {
13735 {Result, DAG.getConstant(0, DL, ContainerVT),
13736 DAG.getCondCode(ISD::SETNE), DAG.getUNDEF(getMaskTypeFor(ContainerVT)),
13751 MVT VT =
Op.getSimpleValueType();
13753 MVT ContainerVT = VT;
13764 DAG.
getNode(
C->isZero() ? RISCVISD::VMCLR_VL : RISCVISD::VMSET_VL,
DL,
13787RISCVTargetLowering::lowerVPReverseExperimental(
SDValue Op,
13790 MVT VT =
Op.getSimpleValueType();
13791 MVT XLenVT = Subtarget.getXLenVT();
13797 MVT ContainerVT = VT;
13805 MVT GatherVT = ContainerVT;
13809 if (IsMaskVector) {
13819 Op1 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, IndicesVT, Op1, SplatOne,
13820 SplatZero, DAG.
getUNDEF(IndicesVT), EVL);
13825 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
13826 unsigned MaxVLMAX =
13829 unsigned GatherOpc = RISCVISD::VRGATHER_VV_VL;
13835 if (MaxVLMAX > 256 && EltSize == 8) {
13863 DAG.
getUNDEF(GatherVT), Result, Diff, Mask, EVL);
13865 if (IsMaskVector) {
13868 DAG.
getNode(RISCVISD::SETCC_VL,
DL, ContainerVT,
13881 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
13888 DAG.
getUNDEF(IndicesVT), VecLen, EVL);
13889 SDValue VRSUB = DAG.
getNode(RISCVISD::SUB_VL,
DL, IndicesVT, VecLenSplat, VID,
13890 DAG.
getUNDEF(IndicesVT), Mask, EVL);
13892 DAG.
getUNDEF(GatherVT), Mask, EVL);
13894 if (IsMaskVector) {
13897 RISCVISD::SETCC_VL,
DL, ContainerVT,
13909 MVT VT =
Op.getSimpleValueType();
13911 return lowerVPOp(
Op, DAG);
13918 MVT ContainerVT = VT;
13936 MVT XLenVT = Subtarget.getXLenVT();
13937 MVT VT =
Op.getSimpleValueType();
13938 MVT ContainerVT = VT;
13942 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
13950 : Intrinsic::riscv_vlse_mask,
13953 DAG.
getUNDEF(ContainerVT), VPNode->getBasePtr(),
13954 VPNode->getStride()};
13960 Ops.push_back(Mask);
13962 Ops.push_back(VPNode->getVectorLength());
13966 Ops.push_back(Policy);
13971 VPNode->getMemoryVT(), VPNode->getMemOperand());
13983 MVT XLenVT = Subtarget.getXLenVT();
13986 SDValue StoreVal = VPNode->getValue();
13988 MVT ContainerVT = VT;
13999 : Intrinsic::riscv_vsse_mask,
14002 VPNode->getBasePtr(), VPNode->getStride()};
14008 Ops.push_back(Mask);
14010 Ops.push_back(VPNode->getVectorLength());
14013 Ops, VPNode->getMemoryVT(),
14014 VPNode->getMemOperand());
14026 MVT VT =
Op.getSimpleValueType();
14029 EVT MemVT = MemSD->getMemoryVT();
14030 MachineMemOperand *MMO = MemSD->getMemOperand();
14031 SDValue Chain = MemSD->getChain();
14038 Index = VPGN->getIndex();
14039 Mask = VPGN->getMask();
14041 VL = VPGN->getVectorLength();
14047 Index = MGN->getIndex();
14048 Mask = MGN->getMask();
14049 PassThru = MGN->getPassThru();
14053 MVT IndexVT =
Index.getSimpleValueType();
14054 MVT XLenVT = Subtarget.getXLenVT();
14057 "Unexpected VTs!");
14058 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
14061 "Unexpected extending MGATHER/VP_GATHER");
14067 MVT ContainerVT = VT;
14091 IsUnmasked ? Intrinsic::riscv_vluxei : Intrinsic::riscv_vluxei_mask;
14096 Ops.push_back(PassThru);
14097 Ops.push_back(BasePtr);
14098 Ops.push_back(Index);
14100 Ops.push_back(Mask);
14105 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
14108 Chain =
Result.getValue(1);
14126 EVT MemVT = MemSD->getMemoryVT();
14127 MachineMemOperand *MMO = MemSD->getMemOperand();
14128 SDValue Chain = MemSD->getChain();
14131 [[maybe_unused]]
bool IsTruncatingStore =
false;
14135 Index = VPSN->getIndex();
14136 Mask = VPSN->getMask();
14137 Val = VPSN->getValue();
14138 VL = VPSN->getVectorLength();
14140 IsTruncatingStore =
false;
14144 Index = MSN->getIndex();
14145 Mask = MSN->getMask();
14146 Val = MSN->getValue();
14147 IsTruncatingStore = MSN->isTruncatingStore();
14151 MVT IndexVT =
Index.getSimpleValueType();
14152 MVT XLenVT = Subtarget.getXLenVT();
14155 "Unexpected VTs!");
14156 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
14159 assert(!IsTruncatingStore &&
"Unexpected truncating MSCATTER/VP_SCATTER");
14165 MVT ContainerVT = VT;
14189 IsUnmasked ? Intrinsic::riscv_vsoxei : Intrinsic::riscv_vsoxei_mask;
14191 Ops.push_back(Val);
14192 Ops.push_back(BasePtr);
14193 Ops.push_back(Index);
14195 Ops.push_back(Mask);
14204 const MVT XLenVT = Subtarget.getXLenVT();
14208 SDVTList VTs = DAG.
getVTList(XLenVT, MVT::Other);
14215 static const int Table =
14234 const MVT XLenVT = Subtarget.getXLenVT();
14244 static const unsigned Table =
14259 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14265 const MVT XLenVT = Subtarget.getXLenVT();
14269 SDVTList VTs = DAG.
getVTList(XLenVT, MVT::Other);
14270 return DAG.
getNode(RISCVISD::READ_CSR,
DL, VTs, Chain, SysRegNo);
14275 const MVT XLenVT = Subtarget.getXLenVT();
14282 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14288 const MVT XLenVT = Subtarget.getXLenVT();
14294 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14308 SDValue Result = DAG.
getNode(RISCVISD::READ_CSR,
DL, VTs, Chain, SysRegNo);
14309 Chain = Result.getValue(1);
14315 const MVT XLenVT = Subtarget.getXLenVT();
14325 Chain = DAG.
getNode(RISCVISD::CLEAR_CSR,
DL, MVT::Other, Chain, SysRegNo,
14327 return DAG.
getNode(RISCVISD::SET_CSR,
DL, MVT::Other, Chain, SysRegNo,
14333 const MVT XLenVT = Subtarget.getXLenVT();
14340 return DAG.
getNode(RISCVISD::CLEAR_CSR,
DL, MVT::Other, Chain, SysRegNo,
14348 bool isRISCV64 = Subtarget.is64Bit();
14362 return RISCVISD::SLLW;
14364 return RISCVISD::SRAW;
14366 return RISCVISD::SRLW;
14368 return RISCVISD::DIVW;
14370 return RISCVISD::DIVUW;
14372 return RISCVISD::REMUW;
14374 return RISCVISD::ROLW;
14376 return RISCVISD::RORW;
14412 switch (
N->getOpcode()) {
14414 llvm_unreachable(
"Don't know how to custom type legalize this operation!");
14419 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14420 "Unexpected custom legalisation");
14421 bool IsStrict =
N->isStrictFPOpcode();
14424 SDValue Op0 = IsStrict ?
N->getOperand(1) :
N->getOperand(0);
14433 !Subtarget.hasStdExtZfhOrZhinx()) {
14438 unsigned Opc = IsSigned ? RISCVISD::STRICT_FCVT_W_RV64
14439 : RISCVISD::STRICT_FCVT_WU_RV64;
14442 Opc,
DL, VTs, Chain, Op0,
14451 !Subtarget.hasStdExtZfhOrZhinx()) ||
14453 Op0 = DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, Op0);
14455 unsigned Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
14476 std::tie(Result, Chain) =
14477 makeLibCall(DAG, LC,
N->getValueType(0), Op0, CallOptions,
DL, Chain);
14483 case ISD::LROUND: {
14492 if (Op0.
getValueType() == MVT::f16 && !Subtarget.hasStdExtZfhOrZhinx())
14493 Op0 = DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, Op0);
14496 DAG.
getNode(RISCVISD::FCVT_W_RV64,
DL, MVT::i64, Op0,
14504 RTLIB::Libcall LC =
14505 Op0.
getValueType() == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
14514 case ISD::READCYCLECOUNTER:
14515 case ISD::READSTEADYCOUNTER: {
14516 assert(!Subtarget.is64Bit() &&
"READCYCLECOUNTER/READSTEADYCOUNTER only "
14517 "has custom type legalization on riscv32");
14519 SDValue LoCounter, HiCounter;
14520 MVT XLenVT = Subtarget.getXLenVT();
14521 if (
N->getOpcode() == ISD::READCYCLECOUNTER) {
14530 N->getOperand(0), LoCounter, HiCounter);
14545 if (
N->getValueType(0) == MVT::i64) {
14546 assert(Subtarget.hasStdExtZilsd() && !Subtarget.is64Bit() &&
14547 "Unexpected custom legalisation");
14549 if (!Subtarget.enableUnalignedScalarMem() && Ld->
getAlign() < 8)
14554 RISCVISD::LD_RV32,
DL,
14555 DAG.
getVTList({MVT::i32, MVT::i32, MVT::Other}),
14556 {Ld->getChain(), Ld->getBasePtr()}, MVT::i64, Ld->
getMemOperand());
14560 Results.append({Pair, Result.getValue(2)});
14564 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14565 "Unexpected custom legalisation");
14576 unsigned Size =
N->getSimpleValueType(0).getSizeInBits();
14577 unsigned XLen = Subtarget.getXLen();
14580 assert(
Size == (XLen * 2) &&
"Unexpected custom legalisation");
14588 if (LHSIsU == RHSIsU)
14592 MVT XLenVT = Subtarget.getXLenVT();
14605 if (RHSIsU && LHSIsS && !RHSIsS)
14606 Results.push_back(MakeMULPair(LHS, RHS));
14607 else if (LHSIsU && RHSIsS && !LHSIsS)
14608 Results.push_back(MakeMULPair(RHS, LHS));
14616 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14617 "Unexpected custom legalisation");
14623 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14624 "Unexpected custom legalisation");
14627 if (
N->getOpcode() ==
ISD::SHL && Subtarget.hasStdExtZbs() &&
14652 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14653 "Unexpected custom legalisation");
14654 assert((Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb() ||
14655 Subtarget.hasVendorXTHeadBb()) &&
14656 "Unexpected custom legalization");
14658 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()))
14666 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14667 "Unexpected custom legalisation");
14673 unsigned Opc = IsCTZ ? RISCVISD::CTZW : RISCVISD::CLZW;
14681 MVT VT =
N->getSimpleValueType(0);
14682 assert((VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32) &&
14683 Subtarget.is64Bit() && Subtarget.hasStdExtM() &&
14684 "Unexpected custom legalisation");
14696 if (VT != MVT::i32)
14704 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14705 "Unexpected custom legalisation");
14726 EVT OType =
N->getValueType(1);
14738 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14739 "Unexpected custom legalisation");
14756 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1), Res,
14760 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1),
N->getOperand(0),
14767 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1), Res, LHS,
14777 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14778 !Subtarget.hasStdExtZbb() &&
"Unexpected custom legalisation");
14786 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14787 "Unexpected custom legalisation");
14792 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14793 "Unexpected custom legalisation");
14795 if (Subtarget.hasStdExtZbb()) {
14828 case ISD::BITCAST: {
14829 EVT VT =
N->getValueType(0);
14833 MVT XLenVT = Subtarget.getXLenVT();
14834 if (VT == MVT::i16 &&
14835 ((Op0VT == MVT::f16 && Subtarget.hasStdExtZfhminOrZhinxmin()) ||
14836 (Op0VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
14839 }
else if (VT == MVT::i32 && Op0VT == MVT::f32 && Subtarget.is64Bit() &&
14840 Subtarget.hasStdExtFOrZfinx()) {
14842 DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Op0);
14844 }
else if (VT == MVT::i64 && Op0VT == MVT::f64 && !Subtarget.is64Bit() &&
14845 Subtarget.hasStdExtDOrZdinx()) {
14847 DAG.
getVTList(MVT::i32, MVT::i32), Op0);
14866 assert(
N->getValueType(0) == MVT::i8 && Subtarget.hasStdExtZbkb() &&
14867 "Unexpected custom legalisation");
14868 MVT XLenVT = Subtarget.getXLenVT();
14876 case RISCVISD::BREV8:
14877 case RISCVISD::ORC_B: {
14878 MVT VT =
N->getSimpleValueType(0);
14879 MVT XLenVT = Subtarget.getXLenVT();
14880 assert((VT == MVT::i16 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
14881 "Unexpected custom legalisation");
14882 assert(((
N->getOpcode() == RISCVISD::BREV8 && Subtarget.hasStdExtZbkb()) ||
14883 (
N->getOpcode() == RISCVISD::ORC_B && Subtarget.hasStdExtZbb())) &&
14884 "Unexpected extension");
14910 assert(!Subtarget.is64Bit() &&
N->getValueType(0) == MVT::i64 &&
14912 "Unexpected EXTRACT_VECTOR_ELT legalization");
14915 MVT ContainerVT = VecVT;
14921 MVT XLenVT = Subtarget.getXLenVT();
14930 DAG.
getUNDEF(ContainerVT), Vec, Idx, Mask, VL);
14942 DAG.
getNode(RISCVISD::SRL_VL,
DL, ContainerVT, Vec, ThirtyTwoV,
14943 DAG.
getUNDEF(ContainerVT), Mask, VL);
14951 unsigned IntNo =
N->getConstantOperandVal(0);
14955 "Don't know how to custom type legalize this intrinsic!");
14956 case Intrinsic::experimental_get_vector_length: {
14961 case Intrinsic::experimental_cttz_elts: {
14967 case Intrinsic::riscv_orc_b:
14968 case Intrinsic::riscv_brev8:
14969 case Intrinsic::riscv_sha256sig0:
14970 case Intrinsic::riscv_sha256sig1:
14971 case Intrinsic::riscv_sha256sum0:
14972 case Intrinsic::riscv_sha256sum1:
14973 case Intrinsic::riscv_sm3p0:
14974 case Intrinsic::riscv_sm3p1: {
14975 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
14979 case Intrinsic::riscv_orc_b:
Opc = RISCVISD::ORC_B;
break;
14980 case Intrinsic::riscv_brev8:
Opc = RISCVISD::BREV8;
break;
14981 case Intrinsic::riscv_sha256sig0:
Opc = RISCVISD::SHA256SIG0;
break;
14982 case Intrinsic::riscv_sha256sig1:
Opc = RISCVISD::SHA256SIG1;
break;
14983 case Intrinsic::riscv_sha256sum0:
Opc = RISCVISD::SHA256SUM0;
break;
14984 case Intrinsic::riscv_sha256sum1:
Opc = RISCVISD::SHA256SUM1;
break;
14985 case Intrinsic::riscv_sm3p0:
Opc = RISCVISD::SM3P0;
break;
14986 case Intrinsic::riscv_sm3p1:
Opc = RISCVISD::SM3P1;
break;
14995 case Intrinsic::riscv_sm4ks:
14996 case Intrinsic::riscv_sm4ed: {
14998 IntNo == Intrinsic::riscv_sm4ks ? RISCVISD::SM4KS : RISCVISD::SM4ED;
15004 DAG.
getNode(
Opc,
DL, MVT::i64, NewOp0, NewOp1,
N->getOperand(3));
15008 case Intrinsic::riscv_mopr: {
15009 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15014 RISCVISD::MOP_R,
DL, MVT::i64, NewOp,
15019 case Intrinsic::riscv_moprr: {
15020 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15027 RISCVISD::MOP_RR,
DL, MVT::i64, NewOp0, NewOp1,
15032 case Intrinsic::riscv_clmul: {
15033 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15044 case Intrinsic::riscv_clmulh:
15045 case Intrinsic::riscv_clmulr: {
15046 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15066 unsigned Opc = IntNo == Intrinsic::riscv_clmulh ? RISCVISD::CLMULH
15067 : RISCVISD::CLMULR;
15074 case Intrinsic::riscv_vmv_x_s: {
15075 EVT VT =
N->getValueType(0);
15076 MVT XLenVT = Subtarget.getXLenVT();
15077 if (VT.
bitsLT(XLenVT)) {
15080 Subtarget.getXLenVT(),
N->getOperand(1));
15085 assert(VT == MVT::i64 && !Subtarget.is64Bit() &&
15086 "Unexpected custom legalization");
15102 SDValue LShr32 = DAG.
getNode(RISCVISD::SRL_VL,
DL, VecVT, Vec, ThirtyTwoV,
15113 case ISD::VECREDUCE_ADD:
15114 case ISD::VECREDUCE_AND:
15115 case ISD::VECREDUCE_OR:
15116 case ISD::VECREDUCE_XOR:
15117 case ISD::VECREDUCE_SMAX:
15118 case ISD::VECREDUCE_UMAX:
15119 case ISD::VECREDUCE_SMIN:
15120 case ISD::VECREDUCE_UMIN:
15124 case ISD::VP_REDUCE_ADD:
15125 case ISD::VP_REDUCE_AND:
15126 case ISD::VP_REDUCE_OR:
15127 case ISD::VP_REDUCE_XOR:
15128 case ISD::VP_REDUCE_SMAX:
15129 case ISD::VP_REDUCE_UMAX:
15130 case ISD::VP_REDUCE_SMIN:
15131 case ISD::VP_REDUCE_UMIN:
15152 return ISD::VECREDUCE_ADD;
15154 return ISD::VECREDUCE_UMAX;
15156 return ISD::VECREDUCE_SMAX;
15158 return ISD::VECREDUCE_UMIN;
15160 return ISD::VECREDUCE_SMIN;
15162 return ISD::VECREDUCE_AND;
15164 return ISD::VECREDUCE_OR;
15166 return ISD::VECREDUCE_XOR;
15169 return ISD::VECREDUCE_FADD;
15171 return ISD::VECREDUCE_FMAX;
15173 return ISD::VECREDUCE_FMIN;
15199 const EVT VT =
N->getValueType(0);
15200 const unsigned Opc =
N->getOpcode();
15210 if (!
N->getFlags().hasAllowReassociation())
15221 "Inconsistent mappings");
15225 if (!
LHS.hasOneUse() || !
RHS.hasOneUse())
15253 if (0 == std::min(LHSIdx, RHSIdx) && 1 == std::max(LHSIdx, RHSIdx)) {
15256 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
N->getFlags());
15263 if (
LHS.getOpcode() != ReduceOpc)
15277 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
15278 ReduceVec->
getFlags() &
N->getFlags());
15288 auto BinOpToRVVReduce = [](
unsigned Opc) {
15293 return RISCVISD::VECREDUCE_ADD_VL;
15295 return RISCVISD::VECREDUCE_UMAX_VL;
15297 return RISCVISD::VECREDUCE_SMAX_VL;
15299 return RISCVISD::VECREDUCE_UMIN_VL;
15301 return RISCVISD::VECREDUCE_SMIN_VL;
15303 return RISCVISD::VECREDUCE_AND_VL;
15305 return RISCVISD::VECREDUCE_OR_VL;
15307 return RISCVISD::VECREDUCE_XOR_VL;
15309 return RISCVISD::VECREDUCE_FADD_VL;
15311 return RISCVISD::VECREDUCE_FMAX_VL;
15313 return RISCVISD::VECREDUCE_FMIN_VL;
15317 auto IsReduction = [&BinOpToRVVReduce](
SDValue V,
unsigned Opc) {
15320 V.getOperand(0).getOpcode() == BinOpToRVVReduce(
Opc);
15323 unsigned Opc =
N->getOpcode();
15324 unsigned ReduceIdx;
15325 if (IsReduction(
N->getOperand(0),
Opc))
15327 else if (IsReduction(
N->getOperand(1),
Opc))
15333 if (
Opc ==
ISD::FADD && !
N->getFlags().hasAllowReassociation())
15336 SDValue Extract =
N->getOperand(ReduceIdx);
15349 if (ScalarV.
getOpcode() != RISCVISD::VFMV_S_F_VL &&
15350 ScalarV.
getOpcode() != RISCVISD::VMV_S_X_VL &&
15351 ScalarV.
getOpcode() != RISCVISD::VMV_V_X_VL)
15368 SDValue NewStart =
N->getOperand(1 - ReduceIdx);
15401 EVT VT =
N->getValueType(0);
15417 int64_t C0 = N0C->getSExtValue();
15418 int64_t C1 = N1C->getSExtValue();
15419 if (C0 <= 0 || C1 <= 0)
15422 int64_t Diff = std::abs(C0 - C1);
15428 int64_t Bits = std::min(C0, C1);
15460 if (VShift.
slt(1) || VShift.
sgt(3))
15464 EVT VT =
N->getValueType(0);
15484 EVT VT =
N->getValueType(0);
15512 EVT VT =
N->getValueType(0);
15533 Slct.
getOpcode() != RISCVISD::SELECT_CC) ||
15541 bool SwapSelectOps;
15542 unsigned OpOffset = Slct.
getOpcode() == RISCVISD::SELECT_CC ? 2 : 0;
15547 SwapSelectOps =
false;
15548 NonConstantVal = FalseVal;
15550 SwapSelectOps =
true;
15551 NonConstantVal = TrueVal;
15557 FalseVal = DAG.
getNode(
N->getOpcode(),
SDLoc(
N), VT, OtherOp, NonConstantVal);
15562 if (Slct.
getOpcode() == RISCVISD::SELECT_CC)
15605 EVT VT =
N->getValueType(0);
15620 if (!N0C->hasOneUse())
15622 int64_t C0 = N0C->getSExtValue();
15623 int64_t C1 = N1C->getSExtValue();
15625 if (C0 == -1 || C0 == 0 || C0 == 1 ||
isInt<12>(C1))
15632 }
else if ((C1 / C0 + 1) != 0 &&
isInt<12>(C1 / C0 + 1) &&
15636 }
else if ((C1 / C0 - 1) != 0 &&
isInt<12>(C1 / C0 - 1) &&
15664 EVT VT =
N->getValueType(0);
15695 unsigned OuterExtend =
15699 OuterExtend,
SDLoc(
N), VT,
15707 EVT VT =
N->getValueType(0);
15757 EVT VT =
N->getValueType(0);
15767 APInt ImmValMinus1 = N0C->getAPIntValue() - 1;
15777 if (!isIntEqualitySetCC(CCVal) || !SetCCOpVT.
isInteger())
15800 if (!Subtarget.hasStdExtZbb())
15803 EVT VT =
N->getValueType(0);
15805 if (VT != Subtarget.
getXLenVT() && VT != MVT::i32 && VT != MVT::i16)
15817 unsigned ShiftedAmount = 8 - ShAmtCLeft->getZExtValue();
15819 if (ShiftedAmount >= 8)
15823 SDValue RightShiftOperand = N1;
15825 if (ShiftedAmount != 0) {
15829 if (!ShAmtCRight || ShAmtCRight->getZExtValue() != ShiftedAmount)
15838 if (LeftShiftOperand != RightShiftOperand)
15842 Mask <<= ShiftedAmount;
15848 return DAG.
getNode(RISCVISD::ORC_B,
SDLoc(
N), VT, LeftShiftOperand);
15856 EVT VT =
N->getValueType(0);
15888 bool IsAnd =
N->getOpcode() ==
ISD::AND;
15912 EVT VT =
N->getValueType(0);
15936 EVT VT =
N->getValueType(0);
15963 if (CondLHS != True)
15970 if (!CondRHSC || CondRHSC->
getAPIntValue() != (1ULL << ScalarBits))
15982 if (!FalseRHSC || !FalseRHSC->
isZero())
16002 EVT VT =
N->getValueType(0);
16009 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() && VT == MVT::i1 &&
16052 EVT VT =
N->getValueType(0);
16071 EVT WideVT =
X.getValueType();
16093 if (N0.
getOpcode() != ISD::ATOMIC_LOAD)
16108 if (Mask != ExpectedMask)
16134 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
16172 if (N0.
getOpcode() != RISCVISD::CZERO_EQZ ||
16173 N1.
getOpcode() != RISCVISD::CZERO_NEZ ||
16191 EVT VT =
N->getValueType(0);
16209 if (!Subtarget.hasVendorXqcibm())
16221 if (
N->getValueType(0) != MVT::i32)
16223 unsigned Width, ShAmt;
16240 return DAG.
getNode(RISCVISD::QC_INSB,
DL, MVT::i32,
Ops);
16245 if (!Subtarget.hasVendorXqcibm())
16255 unsigned ShAmt, Width;
16259 if (
N->getValueType(0) != MVT::i32)
16264 if (Width == 1 && Subtarget.hasStdExtZbs())
16276 return DAG.
getNode(RISCVISD::QC_INSB,
DL, MVT::i32,
Ops);
16284 if (!Subtarget.hasVendorXqcibm())
16290 APInt MaskImm, OrImm;
16309 unsigned ShAmt, Width;
16322 return DAG.
getNode(RISCVISD::QC_INSB,
DL, MVT::i32,
Ops);
16364 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
16379 if (N0.
getOpcode() == RISCVISD::SLLW &&
16383 return DAG.
getNode(RISCVISD::ROLW,
DL, MVT::i64,
16394 const APInt &Imm = ConstN00->getAPIntValue();
16395 if ((Imm + 1).isSignedIntN(12))
16419 EVT VT =
N->getValueType(0);
16428 bool IsAdd = (
E & 3) == 1;
16429 E -= IsAdd ? 1 : -1;
16433 Result = DAG.
getNode(AddSubOp,
DL, VT, Result, ShiftVal);
16443 uint64_t MulAmtLowBit = MulAmt & (-MulAmt);
16448 ShiftAmt1 = MulAmt + MulAmtLowBit;
16451 ShiftAmt1 = MulAmt - MulAmtLowBit;
16455 EVT VT =
N->getValueType(0);
16469 EVT VT =
N->getValueType(0);
16478 bool ShouldExpandMul =
16480 !Subtarget.hasStdExtZmmul();
16481 if (!ShouldExpandMul)
16508 X.getConstantOperandVal(1) == UINT64_C(0xffffffff)) {
16511 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, Shl,
16552 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, Mul359,
16561 if (ScaleShift >= 1 && ScaleShift < 4) {
16562 unsigned ShiftAmt =
Log2_64((MulAmt & (MulAmt - 1)));
16566 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT,
X,
16576 if (
int ShXAmount =
isShifted359(MulAmt - 1, Shift)) {
16577 assert(Shift != 0 &&
"MulAmt=4,6,10 handled before");
16582 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, Mul359,
16588 if (MulAmt > 2 &&
isPowerOf2_64((MulAmt - 1) & (MulAmt - 2))) {
16590 if (ScaleShift >= 1 && ScaleShift < 4) {
16617 for (
uint64_t Divisor : {3, 5, 9}) {
16618 if (MulAmt % Divisor != 0)
16620 uint64_t MulAmt2 = MulAmt / Divisor;
16629 DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, Mul359A,
16640 if (!Subtarget.hasStdExtZmmul())
16650 EVT VT =
N->getValueType(0);
16657 if (
N->getOperand(0).getOpcode() !=
ISD::AND ||
16658 N->getOperand(0).getOperand(0).getOpcode() !=
ISD::SRL)
16671 if (!V1.
isMask(HalfSize) || V2 != (1ULL | 1ULL << HalfSize) ||
16672 V3 != (HalfSize - 1))
16682 return DAG.
getNode(ISD::BITCAST,
DL, VT, Sra);
16688 EVT VT =
N->getValueType(0);
16696 unsigned AddSubOpc;
16702 auto IsAddSubWith1 = [&](
SDValue V) ->
bool {
16703 AddSubOpc = V->getOpcode();
16715 if (IsAddSubWith1(N0)) {
16717 return DAG.
getNode(AddSubOpc,
DL, VT, N1, MulVal);
16720 if (IsAddSubWith1(N1)) {
16722 return DAG.
getNode(AddSubOpc,
DL, VT, N0, MulVal);
16737 if (isIndexTypeSigned(IndexType))
16740 if (!
N->hasOneUse())
16743 EVT VT =
N.getValueType();
16782 EVT SrcVT = Src.getValueType();
16786 NewElen = std::max(NewElen, 8U);
16813 EVT OpVT =
X.getValueType();
16821 if (OpSize <= Subtarget.
getXLen() ||
16827 auto IsVectorBitCastCheap = [](
SDValue X) {
16830 X.getOpcode() == ISD::LOAD;
16832 if (!IsVectorBitCastCheap(
X) || !IsVectorBitCastCheap(
Y))
16836 Attribute::NoImplicitFloat))
16843 unsigned VecSize = OpSize / 8;
16855 DAG.
getNode(ISD::VP_REDUCE_OR,
DL, XLenVT,
16868 EVT VT =
N->getValueType(0);
16873 if (!isIntEqualitySetCC(
Cond))
16898 if (OpVT == MVT::i64 &&
isUInt<32>(AndRHSInt) &&
16902 if (NewC >= -2048 && NewC <= 2048) {
16908 return DAG.
getSetCC(dl, VT, Shift,
16918 if (OpVT != MVT::i64 || !Subtarget.
is64Bit())
16938 const APInt &C1 = N1C->getAPIntValue();
16956 EVT VT =
N->getValueType(0);
16958 unsigned Opc = Src.getOpcode();
16963 if (
Opc == RISCVISD::FMV_X_ANYEXTH && SrcVT.
bitsGE(MVT::i16) &&
16964 Subtarget.hasStdExtZfhmin())
16965 return DAG.
getNode(RISCVISD::FMV_X_SIGNEXTH,
DL, VT, Src.getOperand(0));
16971 return DAG.
getNode(RISCVISD::SLLW,
DL, VT, Src.getOperand(0),
16972 Src.getOperand(1));
16991struct CombineResult;
16993enum ExtKind : uint8_t {
17025struct NodeExtensionHelper {
17034 bool SupportsFPExt;
17036 bool SupportsBF16Ext;
17039 bool EnforceOneUse;
17049 case RISCVISD::VSEXT_VL:
17050 case RISCVISD::VZEXT_VL:
17051 case RISCVISD::FP_EXTEND_VL:
17054 return OrigOperand;
17060 return OrigOperand.
getOpcode() == RISCVISD::VMV_V_X_VL ||
17065 unsigned getExtOpc(ExtKind SupportsExt)
const {
17066 switch (SupportsExt) {
17067 case ExtKind::SExt:
17068 return RISCVISD::VSEXT_VL;
17069 case ExtKind::ZExt:
17070 return RISCVISD::VZEXT_VL;
17071 case ExtKind::FPExt:
17072 case ExtKind::BF16Ext:
17073 return RISCVISD::FP_EXTEND_VL;
17081 SDValue getOrCreateExtendedOp(SDNode *Root, SelectionDAG &DAG,
17082 const RISCVSubtarget &Subtarget,
17083 std::optional<ExtKind> SupportsExt)
const {
17084 if (!SupportsExt.has_value())
17085 return OrigOperand;
17087 MVT NarrowVT = getNarrowType(Root, *SupportsExt);
17091 if (
Source.getValueType() == NarrowVT)
17094 unsigned ExtOpc = getExtOpc(*SupportsExt);
17097 SDLoc
DL(OrigOperand);
17098 auto [
Mask, VL] = getMaskAndVL(Root, DAG, Subtarget);
17102 case RISCVISD::VSEXT_VL:
17103 case RISCVISD::VZEXT_VL:
17104 case RISCVISD::FP_EXTEND_VL:
17105 return DAG.
getNode(ExtOpc,
DL, NarrowVT, Source, Mask, VL);
17108 case RISCVISD::VMV_V_X_VL:
17109 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, NarrowVT,
17111 case RISCVISD::VFMV_V_F_VL:
17113 assert(
Source.getOpcode() == ISD::FP_EXTEND &&
"Unexpected source");
17116 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL, NarrowVT,
17117 DAG.
getUNDEF(NarrowVT), Source, VL);
17130 static MVT getNarrowType(
const SDNode *Root, ExtKind SupportsExt) {
17136 MVT EltVT = SupportsExt == ExtKind::BF16Ext ? MVT::bf16
17137 : SupportsExt == ExtKind::FPExt
17139 : MVT::getIntegerVT(NarrowSize);
17141 assert((
int)NarrowSize >= (SupportsExt == ExtKind::FPExt ? 16 : 8) &&
17142 "Trying to extend something we can't represent");
17149 static unsigned getSExtOpcode(
unsigned Opcode) {
17152 case RISCVISD::ADD_VL:
17153 case RISCVISD::VWADD_W_VL:
17154 case RISCVISD::VWADDU_W_VL:
17156 case RISCVISD::OR_VL:
17157 return RISCVISD::VWADD_VL;
17159 case RISCVISD::SUB_VL:
17160 case RISCVISD::VWSUB_W_VL:
17161 case RISCVISD::VWSUBU_W_VL:
17162 return RISCVISD::VWSUB_VL;
17164 case RISCVISD::MUL_VL:
17165 return RISCVISD::VWMUL_VL;
17173 static unsigned getZExtOpcode(
unsigned Opcode) {
17176 case RISCVISD::ADD_VL:
17177 case RISCVISD::VWADD_W_VL:
17178 case RISCVISD::VWADDU_W_VL:
17180 case RISCVISD::OR_VL:
17181 return RISCVISD::VWADDU_VL;
17183 case RISCVISD::SUB_VL:
17184 case RISCVISD::VWSUB_W_VL:
17185 case RISCVISD::VWSUBU_W_VL:
17186 return RISCVISD::VWSUBU_VL;
17188 case RISCVISD::MUL_VL:
17189 return RISCVISD::VWMULU_VL;
17191 case RISCVISD::SHL_VL:
17192 return RISCVISD::VWSLL_VL;
17200 static unsigned getFPExtOpcode(
unsigned Opcode) {
17202 case RISCVISD::FADD_VL:
17203 case RISCVISD::VFWADD_W_VL:
17204 return RISCVISD::VFWADD_VL;
17205 case RISCVISD::FSUB_VL:
17206 case RISCVISD::VFWSUB_W_VL:
17207 return RISCVISD::VFWSUB_VL;
17208 case RISCVISD::FMUL_VL:
17209 return RISCVISD::VFWMUL_VL;
17210 case RISCVISD::VFMADD_VL:
17211 return RISCVISD::VFWMADD_VL;
17212 case RISCVISD::VFMSUB_VL:
17213 return RISCVISD::VFWMSUB_VL;
17214 case RISCVISD::VFNMADD_VL:
17215 return RISCVISD::VFWNMADD_VL;
17216 case RISCVISD::VFNMSUB_VL:
17217 return RISCVISD::VFWNMSUB_VL;
17225 static unsigned getSUOpcode(
unsigned Opcode) {
17227 "SU is only supported for MUL");
17228 return RISCVISD::VWMULSU_VL;
17233 static unsigned getWOpcode(
unsigned Opcode, ExtKind SupportsExt) {
17236 case RISCVISD::ADD_VL:
17238 case RISCVISD::OR_VL:
17239 return SupportsExt == ExtKind::SExt ? RISCVISD::VWADD_W_VL
17240 : RISCVISD::VWADDU_W_VL;
17242 case RISCVISD::SUB_VL:
17243 return SupportsExt == ExtKind::SExt ? RISCVISD::VWSUB_W_VL
17244 : RISCVISD::VWSUBU_W_VL;
17245 case RISCVISD::FADD_VL:
17246 return RISCVISD::VFWADD_W_VL;
17247 case RISCVISD::FSUB_VL:
17248 return RISCVISD::VFWSUB_W_VL;
17254 using CombineToTry = std::function<std::optional<CombineResult>(
17255 SDNode * ,
const NodeExtensionHelper & ,
17256 const NodeExtensionHelper & , SelectionDAG &,
17257 const RISCVSubtarget &)>;
17260 bool needToPromoteOtherUsers()
const {
return EnforceOneUse; }
17262 void fillUpExtensionSupportForSplat(SDNode *Root, SelectionDAG &DAG,
17263 const RISCVSubtarget &Subtarget) {
17268 "Unexpected Opcode");
17281 unsigned ScalarBits =
Op.getValueSizeInBits();
17283 if (ScalarBits < EltBits) {
17285 assert(
Opc == RISCVISD::VMV_V_X_VL && EltBits == 64 && ScalarBits == 32 &&
17286 !Subtarget.
is64Bit() &&
"Unexpected splat");
17288 SupportsSExt =
true;
17292 SupportsZExt =
true;
17294 EnforceOneUse =
false;
17298 unsigned NarrowSize = EltBits / 2;
17301 if (NarrowSize < 8)
17305 SupportsSExt =
true;
17309 SupportsZExt =
true;
17311 EnforceOneUse =
false;
17314 bool isSupportedFPExtend(MVT NarrowEltVT,
const RISCVSubtarget &Subtarget) {
17315 return (NarrowEltVT == MVT::f32 ||
17319 bool isSupportedBF16Extend(MVT NarrowEltVT,
const RISCVSubtarget &Subtarget) {
17320 return NarrowEltVT == MVT::bf16 && Subtarget.hasStdExtZvfbfwma();
17325 void fillUpExtensionSupport(SDNode *Root, SelectionDAG &DAG,
17326 const RISCVSubtarget &Subtarget) {
17327 SupportsZExt =
false;
17328 SupportsSExt =
false;
17329 SupportsFPExt =
false;
17330 SupportsBF16Ext =
false;
17331 EnforceOneUse =
true;
17353 case RISCVISD::VZEXT_VL:
17354 SupportsZExt =
true;
17356 case RISCVISD::VSEXT_VL:
17357 SupportsSExt =
true;
17359 case RISCVISD::FP_EXTEND_VL: {
17362 if (isSupportedFPExtend(NarrowEltVT, Subtarget))
17363 SupportsFPExt =
true;
17364 if (isSupportedBF16Extend(NarrowEltVT, Subtarget))
17365 SupportsBF16Ext =
true;
17370 case RISCVISD::VMV_V_X_VL:
17371 fillUpExtensionSupportForSplat(Root, DAG, Subtarget);
17373 case RISCVISD::VFMV_V_F_VL: {
17380 if (
Op.getOpcode() != ISD::FP_EXTEND)
17384 unsigned ScalarBits =
Op.getOperand(0).getValueSizeInBits();
17385 if (NarrowSize != ScalarBits)
17388 if (isSupportedFPExtend(
Op.getOperand(0).getSimpleValueType(), Subtarget))
17389 SupportsFPExt =
true;
17390 if (isSupportedBF16Extend(
Op.getOperand(0).getSimpleValueType(),
17392 SupportsBF16Ext =
true;
17401 static bool isSupportedRoot(
const SDNode *Root,
17402 const RISCVSubtarget &Subtarget) {
17414 case RISCVISD::ADD_VL:
17415 case RISCVISD::MUL_VL:
17416 case RISCVISD::VWADD_W_VL:
17417 case RISCVISD::VWADDU_W_VL:
17418 case RISCVISD::SUB_VL:
17419 case RISCVISD::VWSUB_W_VL:
17420 case RISCVISD::VWSUBU_W_VL:
17422 case RISCVISD::FADD_VL:
17423 case RISCVISD::FSUB_VL:
17424 case RISCVISD::FMUL_VL:
17425 case RISCVISD::VFWADD_W_VL:
17426 case RISCVISD::VFWSUB_W_VL:
17428 case RISCVISD::OR_VL:
17432 Subtarget.hasStdExtZvbb();
17433 case RISCVISD::SHL_VL:
17434 return Subtarget.hasStdExtZvbb();
17435 case RISCVISD::VFMADD_VL:
17436 case RISCVISD::VFNMSUB_VL:
17437 case RISCVISD::VFNMADD_VL:
17438 case RISCVISD::VFMSUB_VL:
17446 NodeExtensionHelper(SDNode *Root,
unsigned OperandIdx, SelectionDAG &DAG,
17447 const RISCVSubtarget &Subtarget) {
17448 assert(isSupportedRoot(Root, Subtarget) &&
17449 "Trying to build an helper with an "
17450 "unsupported root");
17451 assert(OperandIdx < 2 &&
"Requesting something else than LHS or RHS");
17461 case RISCVISD::VWADD_W_VL:
17462 case RISCVISD::VWADDU_W_VL:
17463 case RISCVISD::VWSUB_W_VL:
17464 case RISCVISD::VWSUBU_W_VL:
17465 case RISCVISD::VFWADD_W_VL:
17466 case RISCVISD::VFWSUB_W_VL:
17468 if (OperandIdx == 1)
17472 fillUpExtensionSupport(Root, DAG, Subtarget);
17478 static std::pair<SDValue, SDValue>
17479 getMaskAndVL(
const SDNode *Root, SelectionDAG &DAG,
17480 const RISCVSubtarget &Subtarget) {
17481 assert(isSupportedRoot(Root, Subtarget) &&
"Unexpected root");
17500 switch (
N->getOpcode()) {
17504 case RISCVISD::ADD_VL:
17505 case RISCVISD::MUL_VL:
17506 case RISCVISD::OR_VL:
17507 case RISCVISD::FADD_VL:
17508 case RISCVISD::FMUL_VL:
17509 case RISCVISD::VFMADD_VL:
17510 case RISCVISD::VFNMSUB_VL:
17511 case RISCVISD::VFNMADD_VL:
17512 case RISCVISD::VFMSUB_VL:
17514 case RISCVISD::VWADD_W_VL:
17515 case RISCVISD::VWADDU_W_VL:
17517 case RISCVISD::SUB_VL:
17518 case RISCVISD::VWSUB_W_VL:
17519 case RISCVISD::VWSUBU_W_VL:
17520 case RISCVISD::VFWADD_W_VL:
17521 case RISCVISD::FSUB_VL:
17522 case RISCVISD::VFWSUB_W_VL:
17524 case RISCVISD::SHL_VL:
17543struct CombineResult {
17545 unsigned TargetOpcode;
17547 std::optional<ExtKind> LHSExt;
17548 std::optional<ExtKind> RHSExt;
17552 NodeExtensionHelper
LHS;
17554 NodeExtensionHelper
RHS;
17556 CombineResult(
unsigned TargetOpcode, SDNode *Root,
17557 const NodeExtensionHelper &
LHS, std::optional<ExtKind> LHSExt,
17558 const NodeExtensionHelper &
RHS, std::optional<ExtKind> RHSExt)
17559 : TargetOpcode(TargetOpcode), LHSExt(LHSExt), RHSExt(RHSExt), Root(Root),
17565 SDValue materialize(SelectionDAG &DAG,
17566 const RISCVSubtarget &Subtarget)
const {
17568 std::tie(Mask, VL) =
17569 NodeExtensionHelper::getMaskAndVL(Root, DAG, Subtarget);
17583 LHS.getOrCreateExtendedOp(Root, DAG, Subtarget, LHSExt),
17584 RHS.getOrCreateExtendedOp(Root, DAG, Subtarget, RHSExt),
17585 Passthru, Mask, VL);
17599static std::optional<CombineResult>
17600canFoldToVWWithSameExtensionImpl(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17601 const NodeExtensionHelper &
RHS,
17604 if ((AllowExtMask & ExtKind::ZExt) &&
LHS.SupportsZExt &&
RHS.SupportsZExt)
17605 return CombineResult(NodeExtensionHelper::getZExtOpcode(Root->
getOpcode()),
17606 Root,
LHS, {ExtKind::ZExt},
RHS,
17608 if ((AllowExtMask & ExtKind::SExt) &&
LHS.SupportsSExt &&
RHS.SupportsSExt)
17609 return CombineResult(NodeExtensionHelper::getSExtOpcode(Root->
getOpcode()),
17610 Root,
LHS, {ExtKind::SExt},
RHS,
17612 if ((AllowExtMask & ExtKind::FPExt) &&
LHS.SupportsFPExt &&
RHS.SupportsFPExt)
17613 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
17614 Root,
LHS, {ExtKind::FPExt},
RHS,
17616 if ((AllowExtMask & ExtKind::BF16Ext) &&
LHS.SupportsBF16Ext &&
17617 RHS.SupportsBF16Ext)
17618 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
17619 Root,
LHS, {ExtKind::BF16Ext},
RHS,
17620 {ExtKind::BF16Ext});
17621 return std::nullopt;
17630static std::optional<CombineResult>
17631canFoldToVWWithSameExtension(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17634 return canFoldToVWWithSameExtensionImpl(
17635 Root,
LHS,
RHS, ExtKind::ZExt | ExtKind::SExt | ExtKind::FPExt, DAG,
17643static std::optional<CombineResult>
17644canFoldToVWWithSameExtZEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17647 return canFoldToVWWithSameExtensionImpl(Root,
LHS,
RHS, ExtKind::ZExt, DAG,
17655static std::optional<CombineResult>
17656canFoldToVWWithSameExtBF16(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17659 return canFoldToVWWithSameExtensionImpl(Root,
LHS,
RHS, ExtKind::BF16Ext, DAG,
17667static std::optional<CombineResult>
17668canFoldToVW_W(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17671 if (
RHS.SupportsFPExt)
17672 return CombineResult(
17673 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::FPExt),
17674 Root,
LHS, std::nullopt,
RHS, {ExtKind::FPExt});
17681 return CombineResult(
17682 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::ZExt), Root,
17683 LHS, std::nullopt,
RHS, {ExtKind::ZExt});
17685 return CombineResult(
17686 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::SExt), Root,
17687 LHS, std::nullopt,
RHS, {ExtKind::SExt});
17688 return std::nullopt;
17695static std::optional<CombineResult>
17696canFoldToVWWithSEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17699 if (
LHS.SupportsSExt)
17700 return CombineResult(NodeExtensionHelper::getSExtOpcode(Root->
getOpcode()),
17701 Root,
LHS, {ExtKind::SExt},
RHS,
17703 return std::nullopt;
17710static std::optional<CombineResult>
17711canFoldToVWWithZEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17714 if (
LHS.SupportsZExt)
17715 return CombineResult(NodeExtensionHelper::getZExtOpcode(Root->
getOpcode()),
17716 Root,
LHS, {ExtKind::ZExt},
RHS,
17718 return std::nullopt;
17725static std::optional<CombineResult>
17726canFoldToVWWithFPEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17729 if (
LHS.SupportsFPExt)
17730 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
17731 Root,
LHS, {ExtKind::FPExt},
RHS,
17733 return std::nullopt;
17740static std::optional<CombineResult>
17741canFoldToVW_SU(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17745 if (!
LHS.SupportsSExt || !
RHS.SupportsZExt)
17746 return std::nullopt;
17747 return CombineResult(NodeExtensionHelper::getSUOpcode(Root->
getOpcode()),
17748 Root,
LHS, {ExtKind::SExt},
RHS,
17753NodeExtensionHelper::getSupportedFoldings(
const SDNode *Root) {
17759 case RISCVISD::ADD_VL:
17760 case RISCVISD::SUB_VL:
17761 case RISCVISD::OR_VL:
17762 case RISCVISD::FADD_VL:
17763 case RISCVISD::FSUB_VL:
17765 Strategies.
push_back(canFoldToVWWithSameExtension);
17769 case RISCVISD::FMUL_VL:
17770 case RISCVISD::VFMADD_VL:
17771 case RISCVISD::VFMSUB_VL:
17772 case RISCVISD::VFNMADD_VL:
17773 case RISCVISD::VFNMSUB_VL:
17774 Strategies.
push_back(canFoldToVWWithSameExtension);
17775 if (Root->
getOpcode() == RISCVISD::VFMADD_VL)
17776 Strategies.
push_back(canFoldToVWWithSameExtBF16);
17779 case RISCVISD::MUL_VL:
17781 Strategies.
push_back(canFoldToVWWithSameExtension);
17786 case RISCVISD::SHL_VL:
17788 Strategies.
push_back(canFoldToVWWithSameExtZEXT);
17790 case RISCVISD::VWADD_W_VL:
17791 case RISCVISD::VWSUB_W_VL:
17793 Strategies.
push_back(canFoldToVWWithSEXT);
17795 case RISCVISD::VWADDU_W_VL:
17796 case RISCVISD::VWSUBU_W_VL:
17798 Strategies.
push_back(canFoldToVWWithZEXT);
17800 case RISCVISD::VFWADD_W_VL:
17801 case RISCVISD::VFWSUB_W_VL:
17803 Strategies.
push_back(canFoldToVWWithFPEXT);
17814 assert(
N->getOpcode() == RISCVISD::ADD_VL);
17817 SDValue Passthru =
N->getOperand(2);
17851 if (!NodeExtensionHelper::isSupportedRoot(
N, Subtarget))
17857 Inserted.insert(
N);
17860 while (!Worklist.
empty()) {
17863 NodeExtensionHelper
LHS(Root, 0, DAG, Subtarget);
17864 NodeExtensionHelper
RHS(Root, 1, DAG, Subtarget);
17865 auto AppendUsersIfNeeded = [&Worklist, &Subtarget,
17866 &Inserted](
const NodeExtensionHelper &
Op) {
17867 if (
Op.needToPromoteOtherUsers()) {
17870 if (!NodeExtensionHelper::isSupportedRoot(TheUser, Subtarget))
17875 if (Inserted.insert(TheUser).second)
17888 NodeExtensionHelper::getSupportedFoldings(Root);
17890 assert(!FoldingStrategies.
empty() &&
"Nothing to be folded");
17891 bool Matched =
false;
17892 for (
int Attempt = 0;
17893 (Attempt != 1 + NodeExtensionHelper::isCommutative(Root)) && !Matched;
17896 for (NodeExtensionHelper::CombineToTry FoldingStrategy :
17897 FoldingStrategies) {
17898 std::optional<CombineResult> Res =
17899 FoldingStrategy(Root,
LHS,
RHS, DAG, Subtarget);
17906 if (Res->LHSExt.has_value())
17907 if (!AppendUsersIfNeeded(
LHS))
17909 if (Res->RHSExt.has_value())
17910 if (!AppendUsersIfNeeded(
RHS))
17922 SDValue InputRootReplacement;
17929 for (CombineResult Res : CombinesToApply) {
17930 SDValue NewValue = Res.materialize(DAG, Subtarget);
17931 if (!InputRootReplacement) {
17933 "First element is expected to be the current node");
17934 InputRootReplacement = NewValue;
17939 for (std::pair<SDValue, SDValue> OldNewValues : ValuesToReplace) {
17943 return InputRootReplacement;
17950 unsigned Opc =
N->getOpcode();
17951 assert(
Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWADDU_W_VL ||
17952 Opc == RISCVISD::VWSUB_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL);
17955 SDValue MergeOp =
N->getOperand(1);
17956 unsigned MergeOpc = MergeOp.
getOpcode();
17958 if (MergeOpc != RISCVISD::VMERGE_VL && MergeOpc !=
ISD::VSELECT)
17967 SDValue Passthru =
N->getOperand(2);
17973 if (Mask.getOpcode() != RISCVISD::VMSET_VL)
17981 Z = Z.getOperand(1);
17987 {Y, X, Y, MergeOp->getOperand(0), N->getOperand(4)},
17994 [[maybe_unused]]
unsigned Opc =
N->getOpcode();
17995 assert(
Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWADDU_W_VL ||
17996 Opc == RISCVISD::VWSUB_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL);
18023 EVT NewMemVT = (MemVT == MVT::i32) ? MVT::i64 : MVT::i128;
18028 if (LSNode1->
getOpcode() == ISD::LOAD) {
18031 if (MemVT == MVT::i32)
18032 Opcode = (Ext ==
ISD::ZEXTLOAD) ? RISCVISD::TH_LWUD : RISCVISD::TH_LWD;
18034 Opcode = RISCVISD::TH_LDD;
18037 Opcode,
SDLoc(LSNode1), DAG.
getVTList({XLenVT, XLenVT, MVT::Other}),
18038 {LSNode1->getChain(), BasePtr,
18039 DAG.getConstant(Imm, SDLoc(LSNode1), XLenVT)},
18050 unsigned Opcode = (MemVT == MVT::i32) ? RISCVISD::TH_SWD : RISCVISD::TH_SDD;
18054 {LSNode1->getChain(), LSNode1->getOperand(1), LSNode2->getOperand(1),
18055 BasePtr, DAG.getConstant(Imm, SDLoc(LSNode1), XLenVT)},
18072 if (!Subtarget.hasVendorXTHeadMemPair())
18077 unsigned OpNum = LSNode1->
getOpcode() == ISD::LOAD ? 1 : 2;
18084 auto ExtractBaseAndOffset = [](
SDValue Ptr) -> std::pair<SDValue, uint64_t> {
18087 return {
Ptr->getOperand(0), C1->getZExtValue()};
18091 auto [Base1, Offset1] = ExtractBaseAndOffset(LSNode1->
getOperand(OpNum));
18112 auto [Base2, Offset2] = ExtractBaseAndOffset(LSNode2->
getOperand(OpNum));
18115 if (Base1 != Base2)
18119 bool Valid =
false;
18120 if (MemVT == MVT::i32) {
18124 }
else if (MemVT == MVT::i64) {
18160 if (Src->isStrictFPOpcode())
18168 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
18178 EVT VT =
N->getValueType(0);
18181 MVT SrcVT = Src.getSimpleValueType();
18182 MVT SrcContainerVT = SrcVT;
18210 IsSigned ? RISCVISD::VFCVT_RTZ_X_F_VL : RISCVISD::VFCVT_RTZ_XU_F_VL;
18211 FpToInt = DAG.
getNode(
Opc,
DL, ContainerVT, XVal, Mask, VL);
18214 IsSigned ? RISCVISD::VFCVT_RM_X_F_VL : RISCVISD::VFCVT_RM_XU_F_VL;
18215 FpToInt = DAG.
getNode(
Opc,
DL, ContainerVT, XVal, Mask,
18228 if (VT != MVT::i32 && VT != XLenVT)
18233 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
18235 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
18258 EVT DstVT =
N->getValueType(0);
18259 if (DstVT != XLenVT)
18265 if (Src->isStrictFPOpcode())
18273 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
18285 if (SatVT == DstVT)
18286 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
18287 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
18288 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
18293 Src = Src.getOperand(0);
18301 if (
Opc == RISCVISD::FCVT_WU_RV64)
18314 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected extension");
18320 EVT VT =
N->getValueType(0);
18326 return DAG.
getNode(RISCVISD::BREV8,
DL, VT, Src.getOperand(0));
18339 EVT LoadVT = VPLoad->getValueType(0);
18343 N->getOperand(2) != VPLoad->getVectorLength() ||
18344 !
N->getOperand(0).hasOneUse())
18351 SDValue LoadMask = VPLoad->getMask();
18356 if (LoadMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
18358 LoadMask.
getOperand(2) != VPLoad->getVectorLength())
18366 SDValue NumElem = VPLoad->getVectorLength();
18367 uint64_t ElemWidthByte = VPLoad->getValueType(0).getScalarSizeInBits() / 8;
18379 PtrInfo, VPLoad->getMemOperand()->getFlags(),
18383 LoadVT,
DL, VPLoad->getChain(),
Base, Stride, LoadMask,
18384 VPLoad->getVectorLength(), MMO, VPLoad->isExpandingLoad());
18398 if (VPStore->getValue().getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE)
18401 SDValue VPReverse = VPStore->getValue();
18407 VPStore->getVectorLength() != VPReverse.
getOperand(2) ||
18411 SDValue StoreMask = VPStore->getMask();
18416 if (StoreMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
18418 StoreMask.
getOperand(2) != VPStore->getVectorLength())
18426 SDValue NumElem = VPStore->getVectorLength();
18440 PtrInfo, VPStore->getMemOperand()->getFlags(),
18445 VPStore->getOffset(), Stride, StoreMask, VPStore->getVectorLength(),
18446 VPStore->getMemoryVT(), MMO, VPStore->getAddressingMode(),
18447 VPStore->isTruncatingStore(), VPStore->isCompressingStore());
18459 EVT VT =
N->getValueType(0);
18471 if (In.getOpcode() != ISD::VP_SRL || In.getOperand(2) != Mask ||
18472 In.getOperand(3) != VL)
18481 if (
LHS.getOpcode() != ISD::VP_ADD ||
LHS.getOperand(2) != Mask ||
18482 LHS.getOperand(3) != VL)
18489 if (V.getOpcode() != ISD::VP_ADD || V.getOperand(2) != Mask ||
18490 V.getOperand(3) != VL)
18502 if (!FindAdd(LHS0, LHS1) && !FindAdd(LHS1, LHS0))
18516 if (
Op.getOpcode() != ISD::VP_ZERO_EXTEND ||
Op.getOperand(1) != Mask ||
18517 Op.getOperand(2) != VL)
18527 Operands[0].getOperand(0), Mask, VL);
18529 Operands[1].getOperand(0), Mask, VL);
18533 return DAG.
getNode(RISCVISD::AVGCEILU_VL,
DL, VT,
18534 {NewOp0, NewOp1, DAG.
getUNDEF(VT), Mask, VL});
18546 case RISCVISD::VFMADD_VL: Opcode = RISCVISD::VFNMSUB_VL;
break;
18547 case RISCVISD::VFNMSUB_VL: Opcode = RISCVISD::VFMADD_VL;
break;
18548 case RISCVISD::VFNMADD_VL: Opcode = RISCVISD::VFMSUB_VL;
break;
18549 case RISCVISD::VFMSUB_VL: Opcode = RISCVISD::VFNMADD_VL;
break;
18550 case RISCVISD::STRICT_VFMADD_VL: Opcode = RISCVISD::STRICT_VFNMSUB_VL;
break;
18551 case RISCVISD::STRICT_VFNMSUB_VL: Opcode = RISCVISD::STRICT_VFMADD_VL;
break;
18552 case RISCVISD::STRICT_VFNMADD_VL: Opcode = RISCVISD::STRICT_VFMSUB_VL;
break;
18553 case RISCVISD::STRICT_VFMSUB_VL: Opcode = RISCVISD::STRICT_VFNMADD_VL;
break;
18563 case RISCVISD::VFMADD_VL: Opcode = RISCVISD::VFMSUB_VL;
break;
18564 case RISCVISD::VFMSUB_VL: Opcode = RISCVISD::VFMADD_VL;
break;
18565 case RISCVISD::VFNMADD_VL: Opcode = RISCVISD::VFNMSUB_VL;
break;
18566 case RISCVISD::VFNMSUB_VL: Opcode = RISCVISD::VFNMADD_VL;
break;
18567 case RISCVISD::STRICT_VFMADD_VL: Opcode = RISCVISD::STRICT_VFMSUB_VL;
break;
18568 case RISCVISD::STRICT_VFMSUB_VL: Opcode = RISCVISD::STRICT_VFMADD_VL;
break;
18569 case RISCVISD::STRICT_VFNMADD_VL: Opcode = RISCVISD::STRICT_VFNMSUB_VL;
break;
18570 case RISCVISD::STRICT_VFNMSUB_VL: Opcode = RISCVISD::STRICT_VFNMADD_VL;
break;
18583 unsigned Offset = IsStrict ? 1 : 0;
18590 auto invertIfNegative = [&Mask, &VL](
SDValue &V) {
18591 if (V.getOpcode() == RISCVISD::FNEG_VL && V.getOperand(1) == Mask &&
18592 V.getOperand(2) == VL) {
18594 V = V.getOperand(0);
18601 bool NegA = invertIfNegative(
A);
18602 bool NegB = invertIfNegative(
B);
18603 bool NegC = invertIfNegative(
C);
18606 if (!NegA && !NegB && !NegC)
18612 {N->getOperand(0), A, B, C, Mask, VL});
18636 EVT VT =
N->getValueType(0);
18643 uint64_t ShAmt =
N->getConstantOperandVal(1);
18656 if (LShAmt < ExtSize) {
18669 if (ShAmt > 32 || VT != MVT::i64)
18699 U->getConstantOperandVal(1) > 32)
18754 if (!
Cond.hasOneUse())
18773 EVT VT =
Cond.getValueType();
18818 LHS =
LHS.getOperand(0);
18828 LHS.getOperand(0).getValueType() == Subtarget.
getXLenVT()) {
18836 RHS =
LHS.getOperand(1);
18837 LHS =
LHS.getOperand(0);
18846 auto isXorImmediate = [](
const SDValue &
Op) ->
bool {
18848 return isInt<12>(XorCnst->getSExtValue());
18852 auto singleBitOp = [&DAG](
const SDValue &VarOp,
18853 const SDValue &ConstOp) ->
bool {
18856 return (XorCnst->getSExtValue() == 1) &&
18861 auto onlyUsedBySelectOrBR = [](
const SDValue &
Op) ->
bool {
18862 for (
const SDNode *UserNode :
Op->users()) {
18863 const unsigned Opcode = UserNode->getOpcode();
18864 if (Opcode != RISCVISD::SELECT_CC && Opcode != RISCVISD::BR_CC)
18869 auto isFoldableXorEq = [isXorImmediate, singleBitOp, onlyUsedBySelectOrBR](
18872 (!isXorImmediate(
LHS.getOperand(1)) ||
18873 singleBitOp(
LHS.getOperand(0),
LHS.getOperand(1)) ||
18874 onlyUsedBySelectOrBR(
LHS));
18877 if (isFoldableXorEq(
LHS,
RHS)) {
18878 RHS =
LHS.getOperand(1);
18879 LHS =
LHS.getOperand(0);
18905 if (Subtarget.hasVendorXAndesPerf()) {
18915 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
18958 bool Commutative =
true;
18959 unsigned Opc = TrueVal.getOpcode();
18969 Commutative =
false;
18979 if (!TrueVal.hasOneUse())
18983 if (FalseVal == TrueVal.getOperand(0))
18985 else if (Commutative && FalseVal == TrueVal.getOperand(1))
18990 EVT VT =
N->getValueType(0);
18992 SDValue OtherOp = TrueVal.getOperand(1 - OpToFold);
18998 assert(IdentityOperand &&
"No identity operand!");
19003 DAG.
getSelect(
DL, OtherOpVT,
N->getOperand(0), OtherOp, IdentityOperand);
19004 return DAG.
getNode(TrueVal.getOpcode(),
DL, VT, FalseVal, NewSel);
19025 CountZeroes =
N->getOperand(2);
19026 ValOnZero =
N->getOperand(1);
19028 CountZeroes =
N->getOperand(1);
19029 ValOnZero =
N->getOperand(2);
19048 if (
Cond->getOperand(0) != CountZeroesArgument)
19067 CountZeroes, BitWidthMinusOne);
19077 EVT VT =
N->getValueType(0);
19078 EVT CondVT =
Cond.getValueType();
19086 (Subtarget.
hasCZEROLike() || Subtarget.hasVendorXTHeadCondMov())) {
19092 const APInt &MaskVal =
LHS.getConstantOperandAPInt(1);
19103 if (!TrueVal.hasOneUse() || !FalseVal.hasOneUse())
19107 if (TrueVal.getOpcode() ==
ISD::SUB && FalseVal.getOpcode() ==
ISD::ADD) {
19115 SDValue A = FalseVal.getOperand(0);
19116 SDValue B = FalseVal.getOperand(1);
19118 return ((TrueVal.getOperand(0) ==
A && TrueVal.getOperand(1) ==
B) ||
19119 (TrueVal.getOperand(1) ==
A && TrueVal.getOperand(0) ==
B));
19127 EVT VT =
N->getValueType(0);
19129 SDValue TrueVal =
N->getOperand(1);
19130 SDValue FalseVal =
N->getOperand(2);
19160 SDValue TrueVal =
N->getOperand(1);
19161 SDValue FalseVal =
N->getOperand(2);
19176 EVT VT =
N->getValueType(0);
19183 const unsigned Opcode =
N->op_begin()->getNode()->getOpcode();
19198 if (
Op.isUndef()) {
19211 if (
Op.getOpcode() != Opcode || !
Op.hasOneUse())
19220 if (
Op.getOperand(0).getValueType() !=
Op.getOperand(1).getValueType())
19244 EVT AVT =
A.getValueType();
19245 EVT BVT =
B.getValueType();
19275 if (AOpt || BOpt) {
19293 EVT OpVT =
A.getValueType();
19301 IsSigned ? ISD::PARTIAL_REDUCE_SMLA : ISD::PARTIAL_REDUCE_UMLA;
19315 EVT OpVT =
A.getOperand(0).getValueType();
19317 OpVT !=
B.getOperand(0).getValueType() ||
19323 Opc = ISD::PARTIAL_REDUCE_SMLA;
19326 Opc = ISD::PARTIAL_REDUCE_UMLA;
19329 Opc = ISD::PARTIAL_REDUCE_SUMLA;
19332 Opc = ISD::PARTIAL_REDUCE_SUMLA;
19346 if (!Subtarget.hasStdExtZvqdotq())
19350 EVT VT =
N->getValueType(0);
19353 return DAG.
getNode(ISD::VECREDUCE_ADD,
DL, VT, V);
19375 const unsigned InVecOpcode = InVec->
getOpcode();
19392 InVecLHS, InValLHS, EltNo);
19394 InVecRHS, InValRHS, EltNo);
19406 unsigned Elt = IndexC->getZExtValue();
19412 unsigned NewIdx = Elt % ConcatNumElts;
19414 unsigned ConcatOpIdx = Elt / ConcatNumElts;
19419 ConcatOps[ConcatOpIdx] = ConcatOp;
19431 EVT VT =
N->getValueType(0);
19443 !
SDValue(BaseLd, 0).hasOneUse())
19446 EVT BaseLdVT = BaseLd->getValueType(0);
19454 if (!Ld || !Ld->isSimple() || !
Op.hasOneUse() ||
19456 Ld->getValueType(0) != BaseLdVT)
19465 using PtrDiff = std::pair<std::variant<int64_t, SDValue>,
bool>;
19467 LoadSDNode *Ld2) -> std::optional<PtrDiff> {
19472 if (BIO1.equalBaseIndex(BIO2, DAG))
19477 SDValue P2 = Ld2->getBasePtr();
19480 if (P1.getOpcode() ==
ISD::ADD && P1.getOperand(0) == P2)
19481 return {{P1.getOperand(1),
true}};
19483 return std::nullopt;
19487 auto BaseDiff = GetPtrDiff(Lds[0], Lds[1]);
19492 for (
auto *It = Lds.
begin() + 1; It != Lds.
end() - 1; It++)
19493 if (GetPtrDiff(*It, *std::next(It)) != BaseDiff)
19501 unsigned WideScalarBitWidth =
19514 auto [StrideVariant, MustNegateStride] = *BaseDiff;
19516 std::holds_alternative<SDValue>(StrideVariant)
19517 ? std::get<SDValue>(StrideVariant)
19520 if (MustNegateStride)
19529 ConstStride && ConstStride->getSExtValue() >= 0)
19533 ConstStride->getSExtValue() * (
N->getNumOperands() - 1);
19539 BaseLd->getPointerInfo(), BaseLd->getMemOperand()->getFlags(), MemSize,
19543 WideVecVT,
DL, BaseLd->getChain(), BaseLd->getBasePtr(), Stride,
19557 EVT VT =
N->getValueType(0);
19574 for (
int MaskIndex : Mask) {
19575 bool SelectMaskVal = (MaskIndex < (int)NumElts);
19578 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
19615 if (
N->getValueType(0).isFixedLengthVector())
19618 SDValue Addend =
N->getOperand(0);
19621 if (
N->getOpcode() == RISCVISD::ADD_VL) {
19622 SDValue AddPassthruOp =
N->getOperand(2);
19623 if (!AddPassthruOp.
isUndef())
19627 auto IsVWMulOpc = [](
unsigned Opc) {
19629 case RISCVISD::VWMUL_VL:
19630 case RISCVISD::VWMULU_VL:
19631 case RISCVISD::VWMULSU_VL:
19646 if (!MulPassthruOp.
isUndef())
19656 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
19657 }(
N, DAG, Subtarget);
19662 if (AddMask != MulMask || AddVL != MulVL)
19665 const auto &TSInfo =
19667 unsigned Opc = TSInfo.getMAccOpcode(MulOp.
getOpcode());
19670 EVT VT =
N->getValueType(0);
19681 if (!
N->getValueType(0).isVector())
19684 SDValue Addend =
N->getOperand(0);
19687 if (
N->getOpcode() == RISCVISD::ADD_VL) {
19688 SDValue AddPassthruOp =
N->getOperand(2);
19689 if (!AddPassthruOp.
isUndef())
19693 auto IsVqdotqOpc = [](
unsigned Opc) {
19695 case RISCVISD::VQDOT_VL:
19696 case RISCVISD::VQDOTU_VL:
19697 case RISCVISD::VQDOTSU_VL:
19717 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
19718 }(
N, DAG, Subtarget);
19721 if (AddVL != MulVL)
19724 if (AddMask.getOpcode() != RISCVISD::VMSET_VL ||
19725 AddMask.getOperand(0) != MulVL)
19730 EVT VT =
N->getValueType(0);
19731 Addend = DAG.
getNode(RISCVISD::ADD_VL,
DL, VT, Addend, AccumOp,
19732 DAG.
getUNDEF(VT), AddMask, AddVL);
19750 const EVT IndexVT = Index.getValueType();
19754 if (!isIndexTypeSigned(IndexType))
19784 assert(ShuffleMask.empty());
19786 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
19789 if (Index->getOperand(i)->isUndef())
19791 uint64_t C = Index->getConstantOperandVal(i);
19792 if (
C % ElementSize != 0)
19794 C =
C / ElementSize;
19797 ShuffleMask.push_back(
C);
19798 ActiveLanes.
set(
C);
19800 return ActiveLanes.
all();
19818 if (NumElems % 2 != 0)
19822 const unsigned WiderElementSize = ElementSize * 2;
19823 if (WiderElementSize > ST.getELen()/8)
19826 if (!ST.enableUnalignedVectorMem() && BaseAlign < WiderElementSize)
19829 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
19832 if (Index->getOperand(i)->isUndef())
19836 uint64_t C = Index->getConstantOperandVal(i);
19838 if (
C % WiderElementSize != 0)
19843 if (
C !=
Last + ElementSize)
19862 if (!IsVLMAX || Mask.getOpcode() != RISCVISD::VMSET_VL ||
19863 Mask.getOperand(0) != VL)
19866 auto IsTruncNode = [&](
SDValue V) {
19867 return V.getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL &&
19868 V.getOperand(1) == Mask && V.getOperand(2) == VL;
19875 while (IsTruncNode(
Op)) {
19876 if (!
Op.hasOneUse())
19878 Op =
Op.getOperand(0);
19911 assert(
N->getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL);
19913 MVT VT =
N->getSimpleValueType(0);
19918 auto MatchMinMax = [&VL, &Mask](
SDValue V,
unsigned Opc,
unsigned OpcVL,
19920 if (V.getOpcode() !=
Opc &&
19921 !(V.getOpcode() == OpcVL && V.getOperand(2).isUndef() &&
19922 V.getOperand(3) == Mask && V.getOperand(4) == VL))
19930 Op.getOperand(1).getValueType().isFixedLengthVector() &&
19932 Op.getOperand(1).getOperand(0).getValueType() ==
Op.getValueType() &&
19934 Op =
Op.getOperand(1).getOperand(0);
19937 return V.getOperand(0);
19939 if (
Op.getOpcode() == RISCVISD::VMV_V_X_VL &&
Op.getOperand(0).isUndef() &&
19940 Op.getOperand(2) == VL) {
19943 Op1->getAPIntValue().sextOrTrunc(
Op.getScalarValueSizeInBits());
19953 auto DetectUSatPattern = [&](
SDValue V) {
19965 MatchMinMax(SMinOp,
ISD::SMAX, RISCVISD::SMAX_VL, LoC))
19974 MatchMinMax(SMaxOp,
ISD::SMIN, RISCVISD::SMIN_VL, HiC))
19977 return DAG.
getNode(RISCVISD::SMAX_VL,
DL, V.getValueType(), SMinOp,
19978 V.getOperand(1), DAG.
getUNDEF(V.getValueType()),
19984 auto DetectSSatPattern = [&](
SDValue V) {
19986 unsigned NumSrcBits = V.getScalarValueSizeInBits();
19993 MatchMinMax(SMinOp,
ISD::SMAX, RISCVISD::SMAX_VL, LoC))
19994 if (HiC == SignedMax && LoC == SignedMin)
19999 MatchMinMax(SMaxOp,
ISD::SMIN, RISCVISD::SMIN_VL, HiC))
20000 if (HiC == SignedMax && LoC == SignedMin)
20009 while (Src.getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL &&
20010 Src.getOperand(1) == Mask && Src.getOperand(2) == VL &&
20012 Src = Src.getOperand(0);
20016 if ((Val = DetectUSatPattern(Src)))
20017 ClipOpc = RISCVISD::TRUNCATE_VECTOR_VL_USAT;
20018 else if ((Val = DetectSSatPattern(Src)))
20019 ClipOpc = RISCVISD::TRUNCATE_VECTOR_VL_SSAT;
20028 Val = DAG.
getNode(ClipOpc,
DL, ValVT, Val, Mask, VL);
20029 }
while (ValVT != VT);
20047 unsigned Opc =
N->getOpcode();
20049 "Unexpected opcode");
20050 EVT VT =
N->getValueType(0);
20059 Src = Src.getOperand(0);
20061 if (Src.getOpcode() != ISD::BITCAST)
20063 Src = Src.getOperand(0);
20064 }
else if (
Opc == ISD::VECREDUCE_ADD) {
20067 Src = Src.getOperand(0);
20070 EVT SrcEVT = Src.getValueType();
20085 if (
Opc == ISD::VECREDUCE_ADD) {
20092 VectorBitsMax, EltSize, MinSize);
20097 MVT ContainerVT = SrcMVT;
20125 if (!
LHS.hasOneUse())
20128 switch (
LHS.getOpcode()) {
20130 case RISCVISD::VSEXT_VL:
20131 Opcode = RISCVISD::VWMULSU_VL;
20134 case RISCVISD::VZEXT_VL:
20135 Opcode = RISCVISD::VWMULU_VL;
20146 else if (
RHS.getOpcode() == RISCVISD::VMV_V_X_VL &&
20148 ShAmtInt =
RHS.getConstantOperandVal(1);
20161 if (ShAmtInt >= NarrowBits)
20163 MVT VT =
N->getSimpleValueType(0);
20170 switch (
N->getOpcode()) {
20175 case RISCVISD::SHL_VL:
20176 Passthru =
N->getOperand(2);
20177 Mask =
N->getOperand(3);
20178 VL =
N->getOperand(4);
20183 return DAG.
getNode(Opcode,
DL, VT, NarrowOp,
20185 Passthru, Mask, VL);
20191 const MVT XLenVT = Subtarget.getXLenVT();
20197 auto SimplifyDemandedLowBitsHelper = [&](
unsigned OpNo,
unsigned LowBits) {
20208 switch (
N->getOpcode()) {
20211 case RISCVISD::SplitF64: {
20215 if (Op0->
getOpcode() == RISCVISD::BuildPairF64)
20228 APInt V =
C->getValueAPF().bitcastToAPInt();
20257 case RISCVISD::SLLW:
20258 case RISCVISD::SRAW:
20259 case RISCVISD::SRLW:
20260 case RISCVISD::RORW:
20261 case RISCVISD::ROLW: {
20263 if (SimplifyDemandedLowBitsHelper(0, 32) ||
20264 SimplifyDemandedLowBitsHelper(1, 5))
20269 case RISCVISD::CLZW:
20270 case RISCVISD::CTZW: {
20272 if (SimplifyDemandedLowBitsHelper(0, 32))
20276 case RISCVISD::FMV_W_X_RV64: {
20281 if (Op0.
getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64)
20285 case RISCVISD::FMV_X_ANYEXTH:
20286 case RISCVISD::FMV_X_ANYEXTW_RV64: {
20289 MVT VT =
N->getSimpleValueType(0);
20300 if ((
N->getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64 &&
20301 Op0->
getOpcode() == RISCVISD::FMV_W_X_RV64) ||
20302 (
N->getOpcode() == RISCVISD::FMV_X_ANYEXTH &&
20303 Op0->
getOpcode() == RISCVISD::FMV_H_X)) {
20305 "Unexpected value type!");
20315 LN0->getBasePtr(), IVT, LN0->getMemOperand());
20328 unsigned FPBits =
N->getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64 ? 32 : 16;
20339 EVT VT =
N->getValueType(0);
20388 EVT VT =
N->getValueType(0);
20405 if (!
C || !
C->getValueAPF().isExactlyValue(+1.0))
20420 case ISD::FMINNUM: {
20435 if (
N->getValueType(0) == MVT::i64 && Subtarget.is64Bit()) {
20440 Src.getOperand(0));
20445 Src.getOperand(0), Src.getOperand(1));
20453 case RISCVISD::TRUNCATE_VECTOR_VL:
20457 case ISD::VP_TRUNCATE:
20465 case RISCVISD::CZERO_EQZ:
20466 case RISCVISD::CZERO_NEZ: {
20470 unsigned Opc =
N->getOpcode();
20473 if (
Opc == RISCVISD::CZERO_EQZ && Val ==
Cond)
20477 Opc == RISCVISD::CZERO_EQZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ;
20485 return DAG.
getNode(InvOpc,
SDLoc(
N),
N->getValueType(0), Val, NewCond);
20495 N->getValueType(0), Val,
Cond.getOperand(0));
20499 case RISCVISD::SELECT_CC: {
20506 SDValue FalseV =
N->getOperand(4);
20508 EVT VT =
N->getValueType(0);
20511 if (TrueV == FalseV)
20542 return DAG.
getNode(RISCVISD::SELECT_CC,
DL,
N->getValueType(0),
20543 {LHS, RHS, CC, TrueV, FalseV});
20545 if (!Subtarget.hasConditionalMoveFusion()) {
20602 case RISCVISD::BR_CC: {
20609 return DAG.
getNode(RISCVISD::BR_CC,
DL,
N->getValueType(0),
20610 N->getOperand(0), LHS, RHS, CC,
N->getOperand(4));
20623 EVT VT =
N->getValueType(0);
20635 if (In2.
getOpcode() != ISD::FP_EXTEND &&
20644 DAG.
getNode(ISD::FNEG,
DL, VT, NewFPExtRound));
20646 case ISD::MGATHER: {
20648 const EVT VT =
N->getValueType(0);
20649 SDValue Index = MGN->getIndex();
20650 SDValue ScaleOp = MGN->getScale();
20652 assert(!MGN->isIndexScaled() &&
20653 "Scaled gather/scatter should not be formed");
20658 N->getVTList(), MGN->getMemoryVT(),
DL,
20659 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
20660 MGN->getBasePtr(), Index, ScaleOp},
20661 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
20665 N->getVTList(), MGN->getMemoryVT(),
DL,
20666 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
20667 MGN->getBasePtr(), Index, ScaleOp},
20668 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
20674 if (std::optional<VIDSequence> SimpleVID =
20676 SimpleVID && SimpleVID->StepDenominator == 1) {
20677 const int64_t StepNumerator = SimpleVID->StepNumerator;
20678 const int64_t Addend = SimpleVID->Addend;
20685 assert(MGN->getBasePtr()->getValueType(0) == PtrVT);
20693 VT,
DL, MGN->getChain(), BasePtr,
20695 EVL, MGN->getMemOperand());
20697 MGN->getPassThru());
20707 MGN->getBasePtr(), DAG.
getUNDEF(XLenVT),
20709 MGN->getMemoryVT(), MGN->getMemOperand(),
20718 MGN->getMemOperand()->getBaseAlign(), Subtarget)) {
20720 for (
unsigned i = 0; i < Index->getNumOperands(); i += 2)
20721 NewIndices.
push_back(Index.getOperand(i));
20722 EVT IndexVT = Index.getValueType()
20729 assert(EltCnt.isKnownEven() &&
"Splitting vector, but not in half!");
20731 EltCnt.divideCoefficientBy(2));
20734 EltCnt.divideCoefficientBy(2));
20739 {MGN->getChain(), Passthru, Mask, MGN->getBasePtr(),
20747 case ISD::MSCATTER:{
20749 SDValue Index = MSN->getIndex();
20750 SDValue ScaleOp = MSN->getScale();
20752 assert(!MSN->isIndexScaled() &&
20753 "Scaled gather/scatter should not be formed");
20758 N->getVTList(), MSN->getMemoryVT(),
DL,
20759 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
20761 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
20765 N->getVTList(), MSN->getMemoryVT(),
DL,
20766 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
20768 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
20770 EVT VT = MSN->getValue()->getValueType(0);
20772 if (!MSN->isTruncatingStore() &&
20776 return DAG.
getMaskedStore(MSN->getChain(),
DL, Shuffle, MSN->getBasePtr(),
20777 DAG.
getUNDEF(XLenVT), MSN->getMask(),
20778 MSN->getMemoryVT(), MSN->getMemOperand(),
20783 case ISD::VP_GATHER: {
20785 SDValue Index = VPGN->getIndex();
20786 SDValue ScaleOp = VPGN->getScale();
20788 assert(!VPGN->isIndexScaled() &&
20789 "Scaled gather/scatter should not be formed");
20794 {VPGN->getChain(), VPGN->getBasePtr(), Index,
20795 ScaleOp, VPGN->getMask(),
20796 VPGN->getVectorLength()},
20797 VPGN->getMemOperand(), IndexType);
20801 {VPGN->getChain(), VPGN->getBasePtr(), Index,
20802 ScaleOp, VPGN->getMask(),
20803 VPGN->getVectorLength()},
20804 VPGN->getMemOperand(), IndexType);
20808 case ISD::VP_SCATTER: {
20810 SDValue Index = VPSN->getIndex();
20811 SDValue ScaleOp = VPSN->getScale();
20813 assert(!VPSN->isIndexScaled() &&
20814 "Scaled gather/scatter should not be formed");
20819 {VPSN->getChain(), VPSN->getValue(),
20820 VPSN->getBasePtr(), Index, ScaleOp,
20821 VPSN->getMask(), VPSN->getVectorLength()},
20822 VPSN->getMemOperand(), IndexType);
20826 {VPSN->getChain(), VPSN->getValue(),
20827 VPSN->getBasePtr(), Index, ScaleOp,
20828 VPSN->getMask(), VPSN->getVectorLength()},
20829 VPSN->getMemOperand(), IndexType);
20832 case RISCVISD::SHL_VL:
20836 case RISCVISD::SRA_VL:
20837 case RISCVISD::SRL_VL: {
20839 if (ShAmt.
getOpcode() == RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL) {
20843 EVT VT =
N->getValueType(0);
20846 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt,
20847 N->getOperand(2),
N->getOperand(3),
N->getOperand(4));
20862 if (ShAmt.
getOpcode() == RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL) {
20865 EVT VT =
N->getValueType(0);
20868 DAG.
getRegister(RISCV::X0, Subtarget.getXLenVT()));
20869 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt);
20873 case RISCVISD::ADD_VL:
20881 case RISCVISD::VWADD_W_VL:
20882 case RISCVISD::VWADDU_W_VL:
20883 case RISCVISD::VWSUB_W_VL:
20884 case RISCVISD::VWSUBU_W_VL:
20886 case RISCVISD::OR_VL:
20887 case RISCVISD::SUB_VL:
20888 case RISCVISD::MUL_VL:
20890 case RISCVISD::VFMADD_VL:
20891 case RISCVISD::VFNMADD_VL:
20892 case RISCVISD::VFMSUB_VL:
20893 case RISCVISD::VFNMSUB_VL:
20894 case RISCVISD::STRICT_VFMADD_VL:
20895 case RISCVISD::STRICT_VFNMADD_VL:
20896 case RISCVISD::STRICT_VFMSUB_VL:
20897 case RISCVISD::STRICT_VFNMSUB_VL:
20899 case RISCVISD::FADD_VL:
20900 case RISCVISD::FSUB_VL:
20901 case RISCVISD::FMUL_VL:
20902 case RISCVISD::VFWADD_W_VL:
20903 case RISCVISD::VFWSUB_W_VL:
20911 if (
N->getOpcode() != ISD::STORE)
20915 SDValue Chain = Store->getChain();
20916 EVT MemVT = Store->getMemoryVT();
20917 SDValue Val = Store->getValue();
20920 bool IsScalarizable =
20922 Store->isSimple() &&
20952 NewVT, *Store->getMemOperand())) {
20954 return DAG.
getStore(Chain,
DL, NewV, Store->getBasePtr(),
20955 Store->getPointerInfo(), Store->getBaseAlign(),
20956 Store->getMemOperand()->getFlags());
20966 L->hasNUsesOfValue(1, 0) && L->hasNUsesOfValue(1, 1) &&
20968 L->getMemoryVT() == MemVT) {
20971 NewVT, *Store->getMemOperand()) &&
20973 NewVT, *L->getMemOperand())) {
20975 L->getPointerInfo(), L->getBaseAlign(),
20976 L->getMemOperand()->getFlags());
20977 return DAG.
getStore(Chain,
DL, NewL, Store->getBasePtr(),
20978 Store->getPointerInfo(), Store->getBaseAlign(),
20979 Store->getMemOperand()->getFlags());
20986 if ((Val.
getOpcode() == RISCVISD::VMV_X_S ||
20992 MVT VecVT = Src.getSimpleValueType();
20999 Store->getChain(),
DL, Src, Store->getBasePtr(), Store->getOffset(),
21002 Store->getMemOperand(), Store->getAddressingMode(),
21003 Store->isTruncatingStore(),
false);
21010 EVT VT =
N->getValueType(0);
21035 case RISCVISD::VFMV_V_F_VL: {
21036 const MVT VT =
N->getSimpleValueType(0);
21037 SDValue Passthru =
N->getOperand(0);
21038 SDValue Scalar =
N->getOperand(1);
21043 return DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL, VT, Passthru, Scalar, VL);
21046 case RISCVISD::VMV_V_X_VL: {
21047 const MVT VT =
N->getSimpleValueType(0);
21048 SDValue Passthru =
N->getOperand(0);
21049 SDValue Scalar =
N->getOperand(1);
21054 unsigned ScalarSize = Scalar.getValueSizeInBits();
21056 if (ScalarSize > EltWidth && Passthru.
isUndef())
21057 if (SimplifyDemandedLowBitsHelper(1, EltWidth))
21064 (!Const || Const->isZero() ||
21065 !Const->getAPIntValue().sextOrTrunc(EltWidth).isSignedIntN(5)))
21066 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, VT, Passthru, Scalar, VL);
21070 case RISCVISD::VFMV_S_F_VL: {
21075 if (
N->getOperand(0).isUndef() &&
21078 Src.getOperand(0).getValueType().isScalableVector()) {
21079 EVT VT =
N->getValueType(0);
21099 case RISCVISD::VMV_S_X_VL: {
21100 const MVT VT =
N->getSimpleValueType(0);
21101 SDValue Passthru =
N->getOperand(0);
21102 SDValue Scalar =
N->getOperand(1);
21108 unsigned ScalarSize = Scalar.getValueSizeInBits();
21110 if (ScalarSize > EltWidth && SimplifyDemandedLowBitsHelper(1, EltWidth))
21113 if (Scalar.getOpcode() == RISCVISD::VMV_X_S && Passthru.
isUndef() &&
21114 Scalar.getOperand(0).getValueType() ==
N->getValueType(0))
21115 return Scalar.getOperand(0);
21122 DAG.
getNode(
N->getOpcode(),
DL, M1VT, M1Passthru, Scalar, VL);
21131 Const && !Const->isZero() &&
isInt<5>(Const->getSExtValue()) &&
21133 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru, Scalar, VL);
21137 case RISCVISD::VMV_X_S: {
21139 MVT VecVT =
N->getOperand(0).getSimpleValueType();
21141 if (M1VT.
bitsLT(VecVT)) {
21143 return DAG.
getNode(RISCVISD::VMV_X_S,
DL,
N->getSimpleValueType(0), Vec);
21151 unsigned IntNo =
N->getConstantOperandVal(IntOpNo);
21156 case Intrinsic::riscv_vcpop:
21157 case Intrinsic::riscv_vcpop_mask:
21158 case Intrinsic::riscv_vfirst:
21159 case Intrinsic::riscv_vfirst_mask: {
21161 if (IntNo == Intrinsic::riscv_vcpop_mask ||
21162 IntNo == Intrinsic::riscv_vfirst_mask)
21163 VL =
N->getOperand(3);
21168 EVT VT =
N->getValueType(0);
21169 if (IntNo == Intrinsic::riscv_vfirst ||
21170 IntNo == Intrinsic::riscv_vfirst_mask)
21174 case Intrinsic::riscv_vsseg2_mask:
21175 case Intrinsic::riscv_vsseg3_mask:
21176 case Intrinsic::riscv_vsseg4_mask:
21177 case Intrinsic::riscv_vsseg5_mask:
21178 case Intrinsic::riscv_vsseg6_mask:
21179 case Intrinsic::riscv_vsseg7_mask:
21180 case Intrinsic::riscv_vsseg8_mask: {
21182 unsigned NF = Tuple.getValueType().getRISCVVectorTupleNumFields();
21184 if (Subtarget.hasOptimizedSegmentLoadStore(NF) || !Tuple.hasOneUse() ||
21185 Tuple.getOpcode() != RISCVISD::TUPLE_INSERT ||
21186 !Tuple.getOperand(0).isUndef())
21194 "Type mismatch without bitcast?");
21195 unsigned Stride = SEW / 8 * NF;
21196 unsigned Offset = SEW / 8 * Idx;
21223 case ISD::EXPERIMENTAL_VP_REVERSE:
21225 case ISD::VP_STORE:
21227 case ISD::BITCAST: {
21228 assert(Subtarget.useRVVForFixedLengthVectors());
21230 EVT VT =
N->getValueType(0);
21241 for (
unsigned i = 0; i < NF; ++i)
21242 Result = DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VT, Result,
Splat,
21248 if ((SrcVT == MVT::v1i1 || SrcVT == MVT::v2i1 || SrcVT == MVT::v4i1) &&
21261 case ISD::VECREDUCE_ADD:
21269 case RISCVISD::VRGATHER_VX_VL: {
21272 EVT VT =
N->getValueType(0);
21275 SDValue Passthru =
N->getOperand(2);
21282 Src = Src.getOperand(1);
21284 switch (Src.getOpcode()) {
21287 case RISCVISD::VMV_V_X_VL:
21288 case RISCVISD::VFMV_V_F_VL:
21296 case RISCVISD::VMV_S_X_VL:
21297 case RISCVISD::VFMV_S_F_VL:
21313 case RISCVISD::TUPLE_EXTRACT: {
21314 EVT VT =
N->getValueType(0);
21316 unsigned Idx =
N->getConstantOperandVal(1);
21321 switch (Tuple.getConstantOperandVal(1)) {
21324 case Intrinsic::riscv_vlseg2_mask:
21325 case Intrinsic::riscv_vlseg3_mask:
21326 case Intrinsic::riscv_vlseg4_mask:
21327 case Intrinsic::riscv_vlseg5_mask:
21328 case Intrinsic::riscv_vlseg6_mask:
21329 case Intrinsic::riscv_vlseg7_mask:
21330 case Intrinsic::riscv_vlseg8_mask:
21331 NF = Tuple.getValueType().getRISCVVectorTupleNumFields();
21335 if (!NF || Subtarget.hasOptimizedSegmentLoadStore(NF))
21340 "Type mismatch without bitcast?");
21341 unsigned Stride = SEW / 8 * NF;
21342 unsigned Offset = SEW / 8 * Idx;
21345 Tuple.getOperand(0),
21367 return Result.getValue(0);
21369 case RISCVISD::TUPLE_INSERT: {
21371 if (
N->getOperand(1).isUndef())
21372 return N->getOperand(0);
21375 case RISCVISD::VSLIDE1UP_VL:
21376 case RISCVISD::VFSLIDE1UP_VL: {
21380 MVT VT =
N->getSimpleValueType(0);
21384 if (!
N->getOperand(0).isUndef() ||
21403 return getVSlideup(DAG, Subtarget,
DL, VT, SrcVec,
N->getOperand(1),
21413 EVT XVT,
unsigned KeptBits)
const {
21418 if (XVT != MVT::i32 && XVT != MVT::i64)
21422 if (KeptBits == 32 || KeptBits == 64)
21426 return Subtarget.hasStdExtZbb() &&
21427 ((KeptBits == 8 && XVT == MVT::i64 && !Subtarget.is64Bit()) ||
21435 "Expected shift op");
21459 if (Ty.isScalarInteger() &&
21462 return isUsedByLdSt(N0.
getNode(),
N);
21468 if (C2 && Subtarget.hasShlAdd(C2->getZExtValue()) &&
N->hasOneUse() &&
21469 N->user_begin()->getOpcode() ==
ISD::ADD &&
21470 !isUsedByLdSt(*
N->user_begin(),
nullptr) &&
21475 const APInt &C1Int = C1->getAPIntValue();
21476 APInt ShiftedC1Int = C1Int << C2->getAPIntValue();
21497 ShiftedC1Int, Ty.getSizeInBits(), Subtarget,
21502 if (C1Cost < ShiftedC1Cost)
21525 EVT VT =
Op.getValueType();
21529 unsigned Opcode =
Op.getOpcode();
21537 const APInt &Mask =
C->getAPIntValue();
21546 auto IsLegalMask = [ShrunkMask, ExpandedMask](
const APInt &Mask) ->
bool {
21547 return ShrunkMask.
isSubsetOf(Mask) && Mask.isSubsetOf(ExpandedMask);
21549 auto UseMask = [Mask,
Op, &TLO](
const APInt &NewMask) ->
bool {
21550 if (NewMask == Mask)
21555 Op.getOperand(0), NewC);
21568 APInt NewMask =
APInt(Mask.getBitWidth(), 0xffff);
21569 if (IsLegalMask(NewMask))
21570 return UseMask(NewMask);
21573 if (VT == MVT::i64) {
21575 if (IsLegalMask(NewMask))
21576 return UseMask(NewMask);
21591 APInt NewMask = ShrunkMask;
21592 if (MinSignedBits <= 12)
21594 else if (!
C->isOpaque() && MinSignedBits <= 32 && !ShrunkMask.
isSignedIntN(32))
21600 assert(IsLegalMask(NewMask));
21601 return UseMask(NewMask);
21605 static const uint64_t GREVMasks[] = {
21606 0x5555555555555555ULL, 0x3333333333333333ULL, 0x0F0F0F0F0F0F0F0FULL,
21607 0x00FF00FF00FF00FFULL, 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL};
21609 for (
unsigned Stage = 0; Stage != 6; ++Stage) {
21610 unsigned Shift = 1 << Stage;
21611 if (ShAmt & Shift) {
21613 uint64_t Res = ((x & Mask) << Shift) | ((x >> Shift) & Mask);
21625 const APInt &DemandedElts,
21627 unsigned Depth)
const {
21629 unsigned Opc =
Op.getOpcode();
21634 "Should use MaskedValueIsZero if you don't know whether Op"
21635 " is a target node!");
21640 case RISCVISD::SELECT_CC: {
21651 case RISCVISD::VCPOP_VL: {
21656 case RISCVISD::CZERO_EQZ:
21657 case RISCVISD::CZERO_NEZ:
21663 case RISCVISD::REMUW: {
21673 case RISCVISD::DIVUW: {
21683 case RISCVISD::SLLW: {
21692 case RISCVISD::SRLW: {
21701 case RISCVISD::SRAW: {
21710 case RISCVISD::SHL_ADD: {
21713 unsigned ShAmt =
Op.getConstantOperandVal(1);
21720 case RISCVISD::CTZW: {
21727 case RISCVISD::CLZW: {
21734 case RISCVISD::BREV8:
21735 case RISCVISD::ORC_B: {
21739 bool IsGORC =
Op.getOpcode() == RISCVISD::ORC_B;
21747 case RISCVISD::READ_VLENB: {
21750 const unsigned MinVLenB = Subtarget.getRealMinVLen() / 8;
21751 const unsigned MaxVLenB = Subtarget.getRealMaxVLen() / 8;
21752 assert(MinVLenB > 0 &&
"READ_VLENB without vector extension enabled?");
21755 if (MaxVLenB == MinVLenB)
21759 case RISCVISD::FCLASS: {
21772 case Intrinsic::riscv_vsetvli:
21773 case Intrinsic::riscv_vsetvlimax: {
21774 bool HasAVL = IntNo == Intrinsic::riscv_vsetvli;
21775 unsigned VSEW =
Op.getConstantOperandVal(HasAVL + 1);
21780 uint64_t MaxVL = Subtarget.getRealMaxVLen() / SEW;
21781 MaxVL = (Fractional) ? MaxVL / LMul : MaxVL * LMul;
21785 MaxVL = std::min(MaxVL,
Op.getConstantOperandVal(1));
21787 unsigned KnownZeroFirstBit =
Log2_32(MaxVL) + 1;
21800 unsigned Depth)
const {
21801 switch (
Op.getOpcode()) {
21804 case RISCVISD::SELECT_CC: {
21807 if (Tmp == 1)
return 1;
21810 return std::min(Tmp, Tmp2);
21812 case RISCVISD::CZERO_EQZ:
21813 case RISCVISD::CZERO_NEZ:
21817 case RISCVISD::ABSW: {
21822 if (Tmp < 33)
return 1;
21825 case RISCVISD::SRAW: {
21832 return std::max(Tmp, 33U);
21834 case RISCVISD::SLLW:
21835 case RISCVISD::SRLW:
21836 case RISCVISD::DIVW:
21837 case RISCVISD::DIVUW:
21838 case RISCVISD::REMUW:
21839 case RISCVISD::ROLW:
21840 case RISCVISD::RORW:
21841 case RISCVISD::FCVT_W_RV64:
21842 case RISCVISD::FCVT_WU_RV64:
21843 case RISCVISD::STRICT_FCVT_W_RV64:
21844 case RISCVISD::STRICT_FCVT_WU_RV64:
21847 case RISCVISD::VMV_X_S: {
21853 unsigned XLen = Subtarget.getXLen();
21854 unsigned EltBits =
Op.getOperand(0).getScalarValueSizeInBits();
21855 if (EltBits <= XLen)
21856 return XLen - EltBits + 1;
21860 unsigned IntNo =
Op.getConstantOperandVal(1);
21864 case Intrinsic::riscv_masked_atomicrmw_xchg:
21865 case Intrinsic::riscv_masked_atomicrmw_add:
21866 case Intrinsic::riscv_masked_atomicrmw_sub:
21867 case Intrinsic::riscv_masked_atomicrmw_nand:
21868 case Intrinsic::riscv_masked_atomicrmw_max:
21869 case Intrinsic::riscv_masked_atomicrmw_min:
21870 case Intrinsic::riscv_masked_atomicrmw_umax:
21871 case Intrinsic::riscv_masked_atomicrmw_umin:
21872 case Intrinsic::riscv_masked_cmpxchg:
21879 assert(Subtarget.hasStdExtA());
21880 return Op.getValueSizeInBits() - 31;
21892 unsigned Depth)
const {
21895 switch (
Op.getOpcode()) {
21896 case RISCVISD::BREV8:
21897 case RISCVISD::ORC_B: {
21899 bool IsGORC =
Op.getOpcode() == RISCVISD::ORC_B;
21907 OriginalDemandedElts, Known2, TLO,
Depth + 1))
21919 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
21927 switch (
Op.getOpcode()) {
21928 case RISCVISD::SLLW:
21929 case RISCVISD::SRAW:
21930 case RISCVISD::SRLW:
21931 case RISCVISD::RORW:
21932 case RISCVISD::ROLW:
21936 case RISCVISD::SELECT_CC:
21938 assert(
Op.getOperand(0).getValueType().isInteger() &&
21939 "RISCVISD::SELECT_CC only compares integers");
21948 assert(Ld &&
"Unexpected null LoadSDNode");
21957 if (!CNode || CNode->isMachineConstantPoolEntry() ||
21958 CNode->getOffset() != 0)
21965 if (
Ptr.getOpcode() == RISCVISD::LLA) {
21966 auto *CNode = GetSupportedConstantPool(
Ptr.getOperand(0));
21967 if (!CNode || CNode->getTargetFlags() != 0)
21970 return CNode->getConstVal();
21974 if (
Ptr.getOpcode() != RISCVISD::ADD_LO ||
21975 Ptr.getOperand(0).getOpcode() != RISCVISD::HI)
21978 auto *CNodeLo = GetSupportedConstantPool(
Ptr.getOperand(1));
21979 auto *CNodeHi = GetSupportedConstantPool(
Ptr.getOperand(0).getOperand(0));
21985 if (CNodeLo->getConstVal() != CNodeHi->getConstVal())
21988 return CNodeLo->getConstVal();
21993 assert(
MI.getOpcode() == RISCV::ReadCounterWide &&
"Unexpected instruction");
22025 Register ReadAgainReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
22028 int64_t LoCounter =
MI.getOperand(2).getImm();
22029 int64_t HiCounter =
MI.getOperand(3).getImm();
22039 BuildMI(LoopMBB,
DL,
TII->get(RISCV::CSRRS), ReadAgainReg)
22051 MI.eraseFromParent();
22059 assert(
MI.getOpcode() == RISCV::SplitF64Pseudo &&
"Unexpected instruction");
22067 Register SrcReg =
MI.getOperand(2).getReg();
22072 TII.storeRegToStackSlot(*BB,
MI, SrcReg,
MI.getOperand(2).isKill(), FI, SrcRC,
22087 MI.eraseFromParent();
22094 assert(
MI.getOpcode() == RISCV::BuildPairF64Pseudo &&
22095 "Unexpected instruction");
22101 Register DstReg =
MI.getOperand(0).getReg();
22123 TII.loadRegFromStackSlot(*BB,
MI, DstReg, FI, DstRC, RI,
Register());
22124 MI.eraseFromParent();
22129 unsigned RelOpcode,
unsigned EqOpcode,
22132 Register DstReg =
MI.getOperand(0).getReg();
22133 Register Src1Reg =
MI.getOperand(1).getReg();
22134 Register Src2Reg =
MI.getOperand(2).getReg();
22136 Register SavedFFlags =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22160 MI.eraseFromParent();
22211 F->insert(It, FirstMBB);
22212 F->insert(It, SecondMBB);
22213 F->insert(It, SinkMBB);
22263 First.eraseFromParent();
22303 if (
MI.getOpcode() != RISCV::Select_GPR_Using_CC_GPR &&
22304 MI.getOperand(1).isReg() &&
MI.getOperand(2).isReg() &&
22305 Next != BB->
end() &&
Next->getOpcode() ==
MI.getOpcode() &&
22306 Next->getOperand(5).getReg() ==
MI.getOperand(0).getReg() &&
22307 Next->getOperand(5).isKill())
22312 if (
MI.getOperand(2).isReg())
22313 RHS =
MI.getOperand(2).getReg();
22318 SelectDests.
insert(
MI.getOperand(0).getReg());
22324 SequenceMBBI !=
E; ++SequenceMBBI) {
22325 if (SequenceMBBI->isDebugInstr())
22327 if (RISCVInstrInfo::isSelectPseudo(*SequenceMBBI)) {
22328 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
22329 !SequenceMBBI->getOperand(2).isReg() ||
22330 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
22331 SequenceMBBI->getOperand(3).getImm() != CC ||
22332 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
22333 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
22335 LastSelectPseudo = &*SequenceMBBI;
22337 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
22340 if (SequenceMBBI->hasUnmodeledSideEffects() ||
22341 SequenceMBBI->mayLoadOrStore() ||
22342 SequenceMBBI->usesCustomInsertionHook() ||
22343 TII.isFrameInstr(*SequenceMBBI) ||
22344 SequenceMBBI->isStackAligningInlineAsm())
22347 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
22361 F->insert(
I, IfFalseMBB);
22362 F->insert(
I, TailMBB);
22365 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
22371 TailMBB->
push_back(DebugInstr->removeFromParent());
22375 TailMBB->
splice(TailMBB->
end(), HeadMBB,
22385 if (
MI.getOperand(2).isImm())
22388 .
addImm(
MI.getOperand(2).getImm())
22400 auto SelectMBBI =
MI.getIterator();
22401 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
22403 while (SelectMBBI != SelectEnd) {
22404 auto Next = std::next(SelectMBBI);
22405 if (RISCVInstrInfo::isSelectPseudo(*SelectMBBI)) {
22408 TII.get(RISCV::PHI), SelectMBBI->getOperand(0).getReg())
22409 .
addReg(SelectMBBI->getOperand(4).getReg())
22411 .
addReg(SelectMBBI->getOperand(5).getReg())
22418 F->getProperties().resetNoPHIs();
22426 RISCVVInversePseudosTable::getBaseInfo(MCOpcode, LMul, SEW);
22427 assert(
Inverse &&
"Unexpected LMUL and SEW pair for instruction");
22429 RISCV::lookupMaskedIntrinsicByUnmasked(
Inverse->Pseudo);
22430 assert(
Masked &&
"Could not find masked instruction for LMUL and SEW pair");
22436 unsigned CVTXOpc) {
22442 Register SavedFFLAGS =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22455 .
add(
MI.getOperand(1))
22456 .
add(
MI.getOperand(2))
22457 .
add(
MI.getOperand(3))
22459 .
add(
MI.getOperand(4))
22460 .
add(
MI.getOperand(5))
22461 .
add(
MI.getOperand(6))
22476 .
add(
MI.getOperand(0))
22477 .
add(
MI.getOperand(1))
22479 .
add(
MI.getOperand(3))
22481 .
add(
MI.getOperand(4))
22482 .
add(
MI.getOperand(5))
22483 .
add(
MI.getOperand(6))
22493 MI.eraseFromParent();
22499 unsigned CmpOpc, F2IOpc, I2FOpc, FSGNJOpc, FSGNJXOpc;
22501 switch (
MI.getOpcode()) {
22504 case RISCV::PseudoFROUND_H:
22505 CmpOpc = RISCV::FLT_H;
22506 F2IOpc = RISCV::FCVT_W_H;
22507 I2FOpc = RISCV::FCVT_H_W;
22508 FSGNJOpc = RISCV::FSGNJ_H;
22509 FSGNJXOpc = RISCV::FSGNJX_H;
22510 RC = &RISCV::FPR16RegClass;
22512 case RISCV::PseudoFROUND_H_INX:
22513 CmpOpc = RISCV::FLT_H_INX;
22514 F2IOpc = RISCV::FCVT_W_H_INX;
22515 I2FOpc = RISCV::FCVT_H_W_INX;
22516 FSGNJOpc = RISCV::FSGNJ_H_INX;
22517 FSGNJXOpc = RISCV::FSGNJX_H_INX;
22518 RC = &RISCV::GPRF16RegClass;
22520 case RISCV::PseudoFROUND_S:
22521 CmpOpc = RISCV::FLT_S;
22522 F2IOpc = RISCV::FCVT_W_S;
22523 I2FOpc = RISCV::FCVT_S_W;
22524 FSGNJOpc = RISCV::FSGNJ_S;
22525 FSGNJXOpc = RISCV::FSGNJX_S;
22526 RC = &RISCV::FPR32RegClass;
22528 case RISCV::PseudoFROUND_S_INX:
22529 CmpOpc = RISCV::FLT_S_INX;
22530 F2IOpc = RISCV::FCVT_W_S_INX;
22531 I2FOpc = RISCV::FCVT_S_W_INX;
22532 FSGNJOpc = RISCV::FSGNJ_S_INX;
22533 FSGNJXOpc = RISCV::FSGNJX_S_INX;
22534 RC = &RISCV::GPRF32RegClass;
22536 case RISCV::PseudoFROUND_D:
22538 CmpOpc = RISCV::FLT_D;
22539 F2IOpc = RISCV::FCVT_L_D;
22540 I2FOpc = RISCV::FCVT_D_L;
22541 FSGNJOpc = RISCV::FSGNJ_D;
22542 FSGNJXOpc = RISCV::FSGNJX_D;
22543 RC = &RISCV::FPR64RegClass;
22545 case RISCV::PseudoFROUND_D_INX:
22547 CmpOpc = RISCV::FLT_D_INX;
22548 F2IOpc = RISCV::FCVT_L_D_INX;
22549 I2FOpc = RISCV::FCVT_D_L_INX;
22550 FSGNJOpc = RISCV::FSGNJ_D_INX;
22551 FSGNJXOpc = RISCV::FSGNJX_D_INX;
22552 RC = &RISCV::GPRRegClass;
22564 F->insert(
I, CvtMBB);
22565 F->insert(
I, DoneMBB);
22573 MBB->addSuccessor(CvtMBB);
22574 MBB->addSuccessor(DoneMBB);
22576 Register DstReg =
MI.getOperand(0).getReg();
22577 Register SrcReg =
MI.getOperand(1).getReg();
22578 Register MaxReg =
MI.getOperand(2).getReg();
22579 int64_t FRM =
MI.getOperand(3).getImm();
22584 Register FabsReg =
MRI.createVirtualRegister(RC);
22588 Register CmpReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22603 Register F2IReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22625 MI.eraseFromParent();
22632 switch (
MI.getOpcode()) {
22635 case RISCV::ReadCounterWide:
22636 assert(!Subtarget.is64Bit() &&
22637 "ReadCounterWide is only to be used on riscv32");
22639 case RISCV::Select_GPR_Using_CC_GPR:
22640 case RISCV::Select_GPR_Using_CC_Imm5_Zibi:
22641 case RISCV::Select_GPR_Using_CC_SImm5_CV:
22642 case RISCV::Select_GPRNoX0_Using_CC_SImm5NonZero_QC:
22643 case RISCV::Select_GPRNoX0_Using_CC_UImm5NonZero_QC:
22644 case RISCV::Select_GPRNoX0_Using_CC_SImm16NonZero_QC:
22645 case RISCV::Select_GPRNoX0_Using_CC_UImm16NonZero_QC:
22646 case RISCV::Select_GPR_Using_CC_UImmLog2XLen_NDS:
22647 case RISCV::Select_GPR_Using_CC_UImm7_NDS:
22648 case RISCV::Select_FPR16_Using_CC_GPR:
22649 case RISCV::Select_FPR16INX_Using_CC_GPR:
22650 case RISCV::Select_FPR32_Using_CC_GPR:
22651 case RISCV::Select_FPR32INX_Using_CC_GPR:
22652 case RISCV::Select_FPR64_Using_CC_GPR:
22653 case RISCV::Select_FPR64INX_Using_CC_GPR:
22654 case RISCV::Select_FPR64IN32X_Using_CC_GPR:
22656 case RISCV::BuildPairF64Pseudo:
22658 case RISCV::SplitF64Pseudo:
22660 case RISCV::PseudoQuietFLE_H:
22662 case RISCV::PseudoQuietFLE_H_INX:
22663 return emitQuietFCMP(
MI, BB, RISCV::FLE_H_INX, RISCV::FEQ_H_INX, Subtarget);
22664 case RISCV::PseudoQuietFLT_H:
22666 case RISCV::PseudoQuietFLT_H_INX:
22667 return emitQuietFCMP(
MI, BB, RISCV::FLT_H_INX, RISCV::FEQ_H_INX, Subtarget);
22668 case RISCV::PseudoQuietFLE_S:
22670 case RISCV::PseudoQuietFLE_S_INX:
22671 return emitQuietFCMP(
MI, BB, RISCV::FLE_S_INX, RISCV::FEQ_S_INX, Subtarget);
22672 case RISCV::PseudoQuietFLT_S:
22674 case RISCV::PseudoQuietFLT_S_INX:
22675 return emitQuietFCMP(
MI, BB, RISCV::FLT_S_INX, RISCV::FEQ_S_INX, Subtarget);
22676 case RISCV::PseudoQuietFLE_D:
22678 case RISCV::PseudoQuietFLE_D_INX:
22679 return emitQuietFCMP(
MI, BB, RISCV::FLE_D_INX, RISCV::FEQ_D_INX, Subtarget);
22680 case RISCV::PseudoQuietFLE_D_IN32X:
22683 case RISCV::PseudoQuietFLT_D:
22685 case RISCV::PseudoQuietFLT_D_INX:
22686 return emitQuietFCMP(
MI, BB, RISCV::FLT_D_INX, RISCV::FEQ_D_INX, Subtarget);
22687 case RISCV::PseudoQuietFLT_D_IN32X:
22691 case RISCV::PseudoVFROUND_NOEXCEPT_V_M1_MASK:
22693 case RISCV::PseudoVFROUND_NOEXCEPT_V_M2_MASK:
22695 case RISCV::PseudoVFROUND_NOEXCEPT_V_M4_MASK:
22697 case RISCV::PseudoVFROUND_NOEXCEPT_V_M8_MASK:
22699 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF2_MASK:
22701 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF4_MASK:
22703 case RISCV::PseudoFROUND_H:
22704 case RISCV::PseudoFROUND_H_INX:
22705 case RISCV::PseudoFROUND_S:
22706 case RISCV::PseudoFROUND_S_INX:
22707 case RISCV::PseudoFROUND_D:
22708 case RISCV::PseudoFROUND_D_INX:
22709 case RISCV::PseudoFROUND_D_IN32X:
22711 case RISCV::PROBED_STACKALLOC_DYN:
22713 case TargetOpcode::STATEPOINT:
22719 MI.addOperand(*
MI.getMF(),
22725 case TargetOpcode::STACKMAP:
22726 case TargetOpcode::PATCHPOINT:
22727 if (!Subtarget.is64Bit())
22729 "supported on 64-bit targets");
22739 if (
auto *FRMDef =
MI.findRegisterDefOperand(RISCV::FRM,
nullptr)) {
22740 FRMDef->setIsDead(
false);
22744 int Idx = RISCV::getNamedOperandIdx(
MI.getOpcode(), RISCV::OpName::frm);
22754 if (
MI.readsRegister(RISCV::FRM,
nullptr))
22760void RISCVTargetLowering::analyzeInputArgs(
22764 for (
const auto &[Idx, In] :
enumerate(Ins)) {
22770 LLVM_DEBUG(
dbgs() <<
"InputArg #" << Idx <<
" has unhandled type "
22777void RISCVTargetLowering::analyzeOutputArgs(
22781 for (
const auto &[Idx, Out] :
enumerate(Outs)) {
22782 MVT ArgVT = Out.VT;
22783 ISD::ArgFlagsTy ArgFlags = Out.Flags;
22787 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << Idx <<
" has unhandled type "
22804 return DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, Val);
22838 if (In.isOrigArg()) {
22843 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
22844 (
BitWidth < 32 && In.Flags.isZExt())) {
22865 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, LocVT, Val);
22866 if (LocVT == MVT::i64 && VA.
getValVT() == MVT::f32)
22867 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Val);
22879 Val = DAG.
getNode(ISD::BITCAST,
DL, LocVT, Val);
22915 ExtType,
DL, LocVT, Chain, FIN,
22932 Register LoVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
22945 Register HiVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
22949 return DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64,
Lo,
Hi);
22960 switch (CallConv) {
22969#define CC_VLS_CASE(ABI_VLEN) case CallingConv::RISCV_VLSCall_##ABI_VLEN:
22985 if (Subtarget.hasStdExtE())
22987 if (!Subtarget.hasStdExtFOrZfinx() || !Subtarget.hasStdExtDOrZdinx())
22989 "(Zdinx/D) instruction set extensions");
22993 if (Func.hasFnAttribute(
"interrupt")) {
22994 if (!Func.arg_empty())
22996 "Functions with the interrupt attribute cannot have arguments!");
23007 "SiFive-CLIC-preemptible",
23008 "SiFive-CLIC-stack-swap",
23009 "SiFive-CLIC-preemptible-stack-swap",
23013 "Function interrupt attribute argument not supported!");
23015 if (Kind.starts_with(
"qci-") && !Subtarget.hasVendorXqciint())
23017 "'qci-*' interrupt kinds require Xqciint extension");
23019 if (Kind.starts_with(
"SiFive-CLIC-") && !Subtarget.hasVendorXSfmclic())
23021 "'SiFive-CLIC-*' interrupt kinds require XSfmclic extension");
23023 if (Kind ==
"rnmi" && !Subtarget.hasStdExtSmrnmi())
23026 if (Kind.starts_with(
"SiFive-CLIC-preemptible") && TFI->
hasFP(MF))
23028 "have a frame pointer");
23032 MVT XLenVT = Subtarget.getXLenVT();
23033 unsigned XLenInBytes = Subtarget.getXLen() / 8;
23035 std::vector<SDValue> OutChains;
23044 analyzeInputArgs(MF, CCInfo, Ins,
false,
23048 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
23069 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
23070 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
23072 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
23074 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
23103 int VarArgsSaveSize = XLenInBytes * (ArgRegs.
size() - Idx);
23108 if (VarArgsSaveSize == 0) {
23112 int VaArgOffset = -VarArgsSaveSize;
23120 XLenInBytes, VaArgOffset -
static_cast<int>(XLenInBytes),
true);
23121 VarArgsSaveSize += XLenInBytes;
23128 for (
unsigned I = Idx;
I < ArgRegs.
size(); ++
I) {
23129 const Register Reg = RegInfo.createVirtualRegister(RC);
23130 RegInfo.addLiveIn(ArgRegs[
I], Reg);
23133 Chain,
DL, ArgValue, FIN,
23135 OutChains.push_back(Store);
23149 if (!OutChains.empty()) {
23150 OutChains.push_back(Chain);
23160bool RISCVTargetLowering::isEligibleForTailCallOptimization(
23164 auto CalleeCC = CLI.CallConv;
23165 auto &Outs = CLI.Outs;
23167 auto CallerCC = Caller.getCallingConv();
23174 if (Caller.hasFnAttribute(
"interrupt"))
23189 for (
auto &VA : ArgLocs)
23195 auto IsCallerStructRet = Caller.hasStructRetAttr();
23196 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
23197 if (IsCallerStructRet || IsCalleeStructRet)
23202 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
23203 if (CalleeCC != CallerCC) {
23204 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
23205 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
23212 for (
auto &Arg : Outs)
23213 if (Arg.Flags.isByVal())
23239 MVT XLenVT = Subtarget.getXLenVT();
23254 if (Subtarget.hasStdExtE())
23258 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
23264 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
23270 "call site marked musttail");
23277 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
23279 if (!Flags.isByVal())
23283 unsigned Size = Flags.getByValSize();
23284 Align Alignment = Flags.getNonZeroByValAlign();
23291 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
23293 false,
nullptr, IsTailCall,
23305 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
23308 SDValue ArgValue = OutVals[OutIdx];
23316 RISCVISD::SplitF64,
DL, DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
23328 if (!StackPtr.getNode())
23340 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
23358 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
23359 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
23365 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
23366 SDValue PartValue = OutVals[OutIdx + 1];
23367 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
23381 DAG.
getStore(Chain,
DL, ArgValue, SpillSlot,
23383 for (
const auto &Part : Parts) {
23384 SDValue PartValue = Part.first;
23385 SDValue PartOffset = Part.second;
23392 ArgValue = SpillSlot;
23398 if (Flags.isByVal())
23399 ArgValue = ByValArgs[j++];
23406 if (
Options.EmitCallSiteInfo)
23410 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
23411 "for passing parameters");
23414 if (!StackPtr.getNode())
23428 if (!MemOpChains.
empty())
23434 for (
auto &Reg : RegsToPass) {
23435 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
23442 validateCCReservedRegs(RegsToPass, MF);
23446 "Return address register required, but has been reserved."});
23451 bool CalleeIsLargeExternalSymbol =
false;
23457 CalleeIsLargeExternalSymbol =
true;
23468 Ops.push_back(Chain);
23469 Ops.push_back(Callee);
23473 for (
auto &Reg : RegsToPass)
23474 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
23478 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
23479 assert(Mask &&
"Missing call preserved mask for calling convention");
23484 Ops.push_back(Glue);
23487 "Unexpected CFI type for a direct call");
23495 bool NeedSWGuarded =
false;
23497 Subtarget.hasStdExtZicfilp() &&
23499 NeedSWGuarded =
true;
23504 NeedSWGuarded ? RISCVISD::SW_GUARDED_TAIL : RISCVISD::TAIL;
23513 unsigned CallOpc = NeedSWGuarded ? RISCVISD::SW_GUARDED_CALL : RISCVISD::CALL;
23529 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_RISCV);
23532 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
23533 auto &VA = RVLocs[i];
23541 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
23542 assert(VA.needsCustom());
23547 RetValue = DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64, RetValue,
23561 const Type *RetTy)
const {
23563 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
23565 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
23566 MVT VT = Outs[i].VT;
23569 true, Outs[i].OrigTy))
23600 for (
unsigned i = 0, e = RVLocs.
size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
23601 SDValue Val = OutVals[OutIdx];
23610 DAG.
getVTList(MVT::i32, MVT::i32), Val);
23614 Register RegHi = RVLocs[++i].getLocReg();
23616 if (Subtarget.isRegisterReservedByUser(RegLo) ||
23617 Subtarget.isRegisterReservedByUser(RegHi))
23620 "Return value register required, but has been reserved."});
23633 if (Subtarget.isRegisterReservedByUser(VA.
getLocReg()))
23636 "Return value register required, but has been reserved."});
23655 unsigned RetOpc = RISCVISD::RET_GLUE;
23658 if (Func.hasFnAttribute(
"interrupt")) {
23659 if (!Func.getReturnType()->isVoidTy())
23661 "Functions with the interrupt attribute must have void return type!");
23667 if (Kind ==
"supervisor")
23668 RetOpc = RISCVISD::SRET_GLUE;
23669 else if (Kind ==
"rnmi") {
23670 assert(Subtarget.hasFeature(RISCV::FeatureStdExtSmrnmi) &&
23671 "Need Smrnmi extension for rnmi");
23672 RetOpc = RISCVISD::MNRET_GLUE;
23673 }
else if (Kind ==
"qci-nest" || Kind ==
"qci-nonest") {
23674 assert(Subtarget.hasFeature(RISCV::FeatureVendorXqciint) &&
23675 "Need Xqciint for qci-(no)nest");
23676 RetOpc = RISCVISD::QC_C_MILEAVERET_GLUE;
23678 RetOpc = RISCVISD::MRET_GLUE;
23681 return DAG.
getNode(RetOpc,
DL, MVT::Other, RetOps);
23684void RISCVTargetLowering::validateCCReservedRegs(
23685 const SmallVectorImpl<std::pair<llvm::Register, llvm::SDValue>> &Regs,
23693 F,
"Argument register required, but has been reserved."});
23699 if (
N->getNumValues() != 1)
23701 if (!
N->hasNUsesOfValue(1, 0))
23704 SDNode *Copy = *
N->user_begin();
23706 if (Copy->getOpcode() == ISD::BITCAST) {
23718 if (Copy->getOperand(Copy->getNumOperands() - 1).getValueType() == MVT::Glue)
23722 bool HasRet =
false;
23724 if (
Node->getOpcode() != RISCVISD::RET_GLUE)
23731 Chain = Copy->getOperand(0);
23743 if (Constraint.
size() == 1) {
23744 switch (Constraint[0]) {
23761 if (Constraint ==
"vr" || Constraint ==
"vd" || Constraint ==
"vm")
23763 if (Constraint ==
"cr" || Constraint ==
"cR" || Constraint ==
"cf")
23769std::pair<unsigned, const TargetRegisterClass *>
23775 if (Constraint.
size() == 1) {
23776 switch (Constraint[0]) {
23781 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
23782 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
23783 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
23784 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
23785 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23786 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23787 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
23789 if (VT == MVT::f16) {
23790 if (Subtarget.hasStdExtZfhmin())
23791 return std::make_pair(0U, &RISCV::FPR16RegClass);
23792 if (Subtarget.hasStdExtZhinxmin())
23793 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
23794 }
else if (VT == MVT::f32) {
23795 if (Subtarget.hasStdExtF())
23796 return std::make_pair(0U, &RISCV::FPR32RegClass);
23797 if (Subtarget.hasStdExtZfinx())
23798 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
23799 }
else if (VT == MVT::f64) {
23800 if (Subtarget.hasStdExtD())
23801 return std::make_pair(0U, &RISCV::FPR64RegClass);
23802 if (Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23803 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23804 if (Subtarget.hasStdExtZdinx() && Subtarget.is64Bit())
23805 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
23809 if (((VT == MVT::i64 || VT == MVT::f64) && !Subtarget.is64Bit()) ||
23810 (VT == MVT::i128 && Subtarget.is64Bit()))
23811 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23816 }
else if (Constraint ==
"vr") {
23817 for (
const auto *RC :
23818 {&RISCV::VRRegClass, &RISCV::VRM2RegClass, &RISCV::VRM4RegClass,
23819 &RISCV::VRM8RegClass, &RISCV::VRN2M1RegClass, &RISCV::VRN3M1RegClass,
23820 &RISCV::VRN4M1RegClass, &RISCV::VRN5M1RegClass,
23821 &RISCV::VRN6M1RegClass, &RISCV::VRN7M1RegClass,
23822 &RISCV::VRN8M1RegClass, &RISCV::VRN2M2RegClass,
23823 &RISCV::VRN3M2RegClass, &RISCV::VRN4M2RegClass,
23824 &RISCV::VRN2M4RegClass}) {
23826 return std::make_pair(0U, RC);
23830 if (
TRI->isTypeLegalForClass(*RC, ContainerVT))
23831 return std::make_pair(0U, RC);
23834 }
else if (Constraint ==
"vd") {
23835 for (
const auto *RC :
23836 {&RISCV::VRNoV0RegClass, &RISCV::VRM2NoV0RegClass,
23837 &RISCV::VRM4NoV0RegClass, &RISCV::VRM8NoV0RegClass,
23838 &RISCV::VRN2M1NoV0RegClass, &RISCV::VRN3M1NoV0RegClass,
23839 &RISCV::VRN4M1NoV0RegClass, &RISCV::VRN5M1NoV0RegClass,
23840 &RISCV::VRN6M1NoV0RegClass, &RISCV::VRN7M1NoV0RegClass,
23841 &RISCV::VRN8M1NoV0RegClass, &RISCV::VRN2M2NoV0RegClass,
23842 &RISCV::VRN3M2NoV0RegClass, &RISCV::VRN4M2NoV0RegClass,
23843 &RISCV::VRN2M4NoV0RegClass}) {
23845 return std::make_pair(0U, RC);
23849 if (
TRI->isTypeLegalForClass(*RC, ContainerVT))
23850 return std::make_pair(0U, RC);
23853 }
else if (Constraint ==
"vm") {
23854 if (
TRI->isTypeLegalForClass(RISCV::VMV0RegClass, VT.
SimpleTy))
23855 return std::make_pair(0U, &RISCV::VMV0RegClass);
23861 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, ContainerVT))
23862 return std::make_pair(0U, &RISCV::VMV0RegClass);
23864 }
else if (Constraint ==
"cr") {
23865 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
23866 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
23867 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
23868 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
23869 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23870 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23872 return std::make_pair(0U, &RISCV::GPRCRegClass);
23873 }
else if (Constraint ==
"cR") {
23874 if (((VT == MVT::i64 || VT == MVT::f64) && !Subtarget.is64Bit()) ||
23875 (VT == MVT::i128 && Subtarget.is64Bit()))
23876 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23877 }
else if (Constraint ==
"cf") {
23878 if (VT == MVT::f16) {
23879 if (Subtarget.hasStdExtZfhmin())
23880 return std::make_pair(0U, &RISCV::FPR16CRegClass);
23881 if (Subtarget.hasStdExtZhinxmin())
23882 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
23883 }
else if (VT == MVT::f32) {
23884 if (Subtarget.hasStdExtF())
23885 return std::make_pair(0U, &RISCV::FPR32CRegClass);
23886 if (Subtarget.hasStdExtZfinx())
23887 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
23888 }
else if (VT == MVT::f64) {
23889 if (Subtarget.hasStdExtD())
23890 return std::make_pair(0U, &RISCV::FPR64CRegClass);
23891 if (Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23892 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23893 if (Subtarget.hasStdExtZdinx() && Subtarget.is64Bit())
23894 return std::make_pair(0U, &RISCV::GPRCRegClass);
23903 .
Case(
"{zero}", RISCV::X0)
23904 .
Case(
"{ra}", RISCV::X1)
23905 .
Case(
"{sp}", RISCV::X2)
23906 .
Case(
"{gp}", RISCV::X3)
23907 .
Case(
"{tp}", RISCV::X4)
23908 .
Case(
"{t0}", RISCV::X5)
23909 .
Case(
"{t1}", RISCV::X6)
23910 .
Case(
"{t2}", RISCV::X7)
23911 .
Cases(
"{s0}",
"{fp}", RISCV::X8)
23912 .
Case(
"{s1}", RISCV::X9)
23913 .
Case(
"{a0}", RISCV::X10)
23914 .
Case(
"{a1}", RISCV::X11)
23915 .
Case(
"{a2}", RISCV::X12)
23916 .
Case(
"{a3}", RISCV::X13)
23917 .
Case(
"{a4}", RISCV::X14)
23918 .
Case(
"{a5}", RISCV::X15)
23919 .
Case(
"{a6}", RISCV::X16)
23920 .
Case(
"{a7}", RISCV::X17)
23921 .
Case(
"{s2}", RISCV::X18)
23922 .
Case(
"{s3}", RISCV::X19)
23923 .
Case(
"{s4}", RISCV::X20)
23924 .
Case(
"{s5}", RISCV::X21)
23925 .
Case(
"{s6}", RISCV::X22)
23926 .
Case(
"{s7}", RISCV::X23)
23927 .
Case(
"{s8}", RISCV::X24)
23928 .
Case(
"{s9}", RISCV::X25)
23929 .
Case(
"{s10}", RISCV::X26)
23930 .
Case(
"{s11}", RISCV::X27)
23931 .
Case(
"{t3}", RISCV::X28)
23932 .
Case(
"{t4}", RISCV::X29)
23933 .
Case(
"{t5}", RISCV::X30)
23934 .
Case(
"{t6}", RISCV::X31)
23936 if (XRegFromAlias != RISCV::NoRegister)
23937 return std::make_pair(XRegFromAlias, &RISCV::GPRRegClass);
23946 if (Subtarget.hasStdExtF()) {
23948 .
Cases(
"{f0}",
"{ft0}", RISCV::F0_F)
23949 .
Cases(
"{f1}",
"{ft1}", RISCV::F1_F)
23950 .
Cases(
"{f2}",
"{ft2}", RISCV::F2_F)
23951 .
Cases(
"{f3}",
"{ft3}", RISCV::F3_F)
23952 .
Cases(
"{f4}",
"{ft4}", RISCV::F4_F)
23953 .
Cases(
"{f5}",
"{ft5}", RISCV::F5_F)
23954 .
Cases(
"{f6}",
"{ft6}", RISCV::F6_F)
23955 .
Cases(
"{f7}",
"{ft7}", RISCV::F7_F)
23956 .
Cases(
"{f8}",
"{fs0}", RISCV::F8_F)
23957 .
Cases(
"{f9}",
"{fs1}", RISCV::F9_F)
23958 .
Cases(
"{f10}",
"{fa0}", RISCV::F10_F)
23959 .
Cases(
"{f11}",
"{fa1}", RISCV::F11_F)
23960 .
Cases(
"{f12}",
"{fa2}", RISCV::F12_F)
23961 .
Cases(
"{f13}",
"{fa3}", RISCV::F13_F)
23962 .
Cases(
"{f14}",
"{fa4}", RISCV::F14_F)
23963 .
Cases(
"{f15}",
"{fa5}", RISCV::F15_F)
23964 .
Cases(
"{f16}",
"{fa6}", RISCV::F16_F)
23965 .
Cases(
"{f17}",
"{fa7}", RISCV::F17_F)
23966 .
Cases(
"{f18}",
"{fs2}", RISCV::F18_F)
23967 .
Cases(
"{f19}",
"{fs3}", RISCV::F19_F)
23968 .
Cases(
"{f20}",
"{fs4}", RISCV::F20_F)
23969 .
Cases(
"{f21}",
"{fs5}", RISCV::F21_F)
23970 .
Cases(
"{f22}",
"{fs6}", RISCV::F22_F)
23971 .
Cases(
"{f23}",
"{fs7}", RISCV::F23_F)
23972 .
Cases(
"{f24}",
"{fs8}", RISCV::F24_F)
23973 .
Cases(
"{f25}",
"{fs9}", RISCV::F25_F)
23974 .
Cases(
"{f26}",
"{fs10}", RISCV::F26_F)
23975 .
Cases(
"{f27}",
"{fs11}", RISCV::F27_F)
23976 .
Cases(
"{f28}",
"{ft8}", RISCV::F28_F)
23977 .
Cases(
"{f29}",
"{ft9}", RISCV::F29_F)
23978 .
Cases(
"{f30}",
"{ft10}", RISCV::F30_F)
23979 .
Cases(
"{f31}",
"{ft11}", RISCV::F31_F)
23981 if (FReg != RISCV::NoRegister) {
23982 assert(RISCV::F0_F <= FReg && FReg <= RISCV::F31_F &&
"Unknown fp-reg");
23983 if (Subtarget.hasStdExtD() && (VT == MVT::f64 || VT == MVT::Other)) {
23984 unsigned RegNo = FReg - RISCV::F0_F;
23985 unsigned DReg = RISCV::F0_D + RegNo;
23986 return std::make_pair(DReg, &RISCV::FPR64RegClass);
23988 if (VT == MVT::f32 || VT == MVT::Other)
23989 return std::make_pair(FReg, &RISCV::FPR32RegClass);
23990 if (Subtarget.hasStdExtZfhmin() && VT == MVT::f16) {
23991 unsigned RegNo = FReg - RISCV::F0_F;
23992 unsigned HReg = RISCV::F0_H + RegNo;
23993 return std::make_pair(HReg, &RISCV::FPR16RegClass);
23998 if (Subtarget.hasVInstructions()) {
24000 .
Case(
"{v0}", RISCV::V0)
24001 .
Case(
"{v1}", RISCV::V1)
24002 .
Case(
"{v2}", RISCV::V2)
24003 .
Case(
"{v3}", RISCV::V3)
24004 .
Case(
"{v4}", RISCV::V4)
24005 .
Case(
"{v5}", RISCV::V5)
24006 .
Case(
"{v6}", RISCV::V6)
24007 .
Case(
"{v7}", RISCV::V7)
24008 .
Case(
"{v8}", RISCV::V8)
24009 .
Case(
"{v9}", RISCV::V9)
24010 .
Case(
"{v10}", RISCV::V10)
24011 .
Case(
"{v11}", RISCV::V11)
24012 .
Case(
"{v12}", RISCV::V12)
24013 .
Case(
"{v13}", RISCV::V13)
24014 .
Case(
"{v14}", RISCV::V14)
24015 .
Case(
"{v15}", RISCV::V15)
24016 .
Case(
"{v16}", RISCV::V16)
24017 .
Case(
"{v17}", RISCV::V17)
24018 .
Case(
"{v18}", RISCV::V18)
24019 .
Case(
"{v19}", RISCV::V19)
24020 .
Case(
"{v20}", RISCV::V20)
24021 .
Case(
"{v21}", RISCV::V21)
24022 .
Case(
"{v22}", RISCV::V22)
24023 .
Case(
"{v23}", RISCV::V23)
24024 .
Case(
"{v24}", RISCV::V24)
24025 .
Case(
"{v25}", RISCV::V25)
24026 .
Case(
"{v26}", RISCV::V26)
24027 .
Case(
"{v27}", RISCV::V27)
24028 .
Case(
"{v28}", RISCV::V28)
24029 .
Case(
"{v29}", RISCV::V29)
24030 .
Case(
"{v30}", RISCV::V30)
24031 .
Case(
"{v31}", RISCV::V31)
24033 if (VReg != RISCV::NoRegister) {
24034 if (
TRI->isTypeLegalForClass(RISCV::VMRegClass, VT.
SimpleTy))
24035 return std::make_pair(VReg, &RISCV::VMRegClass);
24036 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, VT.
SimpleTy))
24037 return std::make_pair(VReg, &RISCV::VRRegClass);
24038 for (
const auto *RC :
24039 {&RISCV::VRM2RegClass, &RISCV::VRM4RegClass, &RISCV::VRM8RegClass}) {
24040 if (
TRI->isTypeLegalForClass(*RC, VT.
SimpleTy)) {
24041 VReg =
TRI->getMatchingSuperReg(VReg, RISCV::sub_vrm1_0, RC);
24042 return std::make_pair(VReg, RC);
24048 std::pair<Register, const TargetRegisterClass *> Res =
24054 if (Res.second == &RISCV::GPRF16RegClass ||
24055 Res.second == &RISCV::GPRF32RegClass ||
24056 Res.second == &RISCV::GPRPairRegClass)
24057 return std::make_pair(Res.first, &RISCV::GPRRegClass);
24065 if (ConstraintCode.
size() == 1) {
24066 switch (ConstraintCode[0]) {
24081 if (Constraint.
size() == 1) {
24082 switch (Constraint[0]) {
24089 Subtarget.getXLenVT()));
24120 if (Subtarget.hasStdExtZtso()) {
24122 return Builder.CreateFence(Ord);
24127 return Builder.CreateFence(Ord);
24136 if (Subtarget.hasStdExtZtso()) {
24138 return Builder.CreateFence(Ord);
24144 if (Subtarget.enableTrailingSeqCstFence() &&
isa<StoreInst>(Inst) &&
24163 if (Subtarget.hasForcedAtomics())
24168 if (Subtarget.hasStdExtZacas() &&
24169 (
Size >= 32 || Subtarget.hasStdExtZabha()))
24175 if (
Size < 32 && !Subtarget.hasStdExtZabha())
24187 return Intrinsic::riscv_masked_atomicrmw_xchg;
24189 return Intrinsic::riscv_masked_atomicrmw_add;
24191 return Intrinsic::riscv_masked_atomicrmw_sub;
24193 return Intrinsic::riscv_masked_atomicrmw_nand;
24195 return Intrinsic::riscv_masked_atomicrmw_max;
24197 return Intrinsic::riscv_masked_atomicrmw_min;
24199 return Intrinsic::riscv_masked_atomicrmw_umax;
24201 return Intrinsic::riscv_masked_atomicrmw_umin;
24217 Builder.CreateNot(Mask,
"Inv_Mask"),
24224 unsigned XLen = Subtarget.getXLen();
24227 Type *Tys[] = {Builder.getIntNTy(XLen), AlignedAddr->
getType()};
24233 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
24234 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
24235 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
24248 unsigned ValWidth =
24251 Builder.CreateSub(Builder.getIntN(XLen, XLen - ValWidth), ShiftAmt);
24252 Result = Builder.CreateCall(LrwOpScwLoop,
24253 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
24256 Builder.CreateCall(LrwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
24260 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
24268 if (Subtarget.hasForcedAtomics())
24272 if (!(Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas()) &&
24281 unsigned XLen = Subtarget.getXLen();
24282 Value *Ordering = Builder.getIntN(XLen,
static_cast<uint64_t>(Ord));
24283 Intrinsic::ID CmpXchgIntrID = Intrinsic::riscv_masked_cmpxchg;
24285 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
24286 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
24287 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
24289 Type *Tys[] = {Builder.getIntNTy(XLen), AlignedAddr->
getType()};
24290 Value *Result = Builder.CreateIntrinsic(
24291 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, Ordering});
24293 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
24298 EVT DataVT)
const {
24314 return Subtarget.hasStdExtZfhmin();
24316 return Subtarget.hasStdExtF();
24318 return Subtarget.hasStdExtD();
24348 assert(Subtarget.getRealMinVLen() >= 64 &&
"zve32* unsupported");
24350 "RVVBitsPerBlock changed, audit needed");
24359 if (!Subtarget.hasVendorXTHeadMemIdx())
24365 Base =
Op->getOperand(0);
24367 int64_t RHSC = RHS->getSExtValue();
24373 bool isLegalIndexedOffset =
false;
24374 for (
unsigned i = 0; i < 4; i++)
24375 if (
isInt<5>(RHSC >> i) && ((RHSC % (1LL << i)) == 0)) {
24376 isLegalIndexedOffset =
true;
24380 if (!isLegalIndexedOffset)
24397 VT = LD->getMemoryVT();
24398 Ptr = LD->getBasePtr();
24400 VT = ST->getMemoryVT();
24401 Ptr = ST->getBasePtr();
24417 if (Subtarget.hasVendorXCVmem() && !Subtarget.is64Bit()) {
24422 Base = LS->getBasePtr();
24426 if (
Base ==
Op->getOperand(0))
24428 else if (
Base ==
Op->getOperand(1))
24440 VT = LD->getMemoryVT();
24441 Ptr = LD->getBasePtr();
24443 VT = ST->getMemoryVT();
24444 Ptr = ST->getBasePtr();
24468 return VT.
isVector() ? Subtarget.hasVInstructionsF16()
24469 : Subtarget.hasStdExtZfhOrZhinx();
24471 return Subtarget.hasStdExtFOrZfinx();
24473 return Subtarget.hasStdExtDOrZdinx();
24487 const Constant *PersonalityFn)
const {
24492 const Constant *PersonalityFn)
const {
24499 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
24500 Type.getSizeInBits() < Subtarget.getXLen()))
24507 bool IsSigned)
const {
24508 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
24522 const bool HasZmmul = Subtarget.hasStdExtZmmul();
24527 const APInt &Imm = ConstNode->getAPIntValue();
24530 if (Subtarget.hasVendorXqciac() && Imm.isSignedIntN(12))
24534 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
24535 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
24539 if (Subtarget.hasShlAdd(3) && !Imm.isSignedIntN(12) &&
24540 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
24541 (Imm - 8).isPowerOf2()))
24546 if (!Imm.isSignedIntN(12) && Imm.countr_zero() < 12 &&
24547 ConstNode->hasOneUse()) {
24548 APInt ImmS = Imm.ashr(Imm.countr_zero());
24549 if ((ImmS + 1).isPowerOf2() || (ImmS - 1).isPowerOf2() ||
24550 (1 - ImmS).isPowerOf2())
24573 if (C1.
isSignedIntN(12) && !(C1 * C2).isSignedIntN(12))
24582 unsigned *
Fast)
const {
24585 *
Fast = Subtarget.enableUnalignedScalarMem();
24586 return Subtarget.enableUnalignedScalarMem();
24602 *
Fast = Subtarget.enableUnalignedVectorMem();
24603 return Subtarget.enableUnalignedVectorMem();
24608 const AttributeList &FuncAttributes)
const {
24609 if (!Subtarget.hasVInstructions())
24612 if (FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat))
24624 const unsigned MinVLenInBytes =
24625 std::min(Subtarget.getRealMinVLen() / 8, 1024U);
24627 if (
Op.size() < MinVLenInBytes)
24642 MVT PreferredVT = (
Op.isMemset() && !
Op.isZeroMemset()) ? MVT::i8 : ELenVT;
24646 if (PreferredVT != MVT::i8 && !Subtarget.enableUnalignedVectorMem()) {
24648 if (
Op.isFixedDstAlign())
24649 RequiredAlign = std::min(RequiredAlign,
Op.getDstAlign());
24651 RequiredAlign = std::min(RequiredAlign,
Op.getSrcAlign());
24659 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
24660 bool IsABIRegCopy = CC.has_value();
24663 MVT PairVT = Subtarget.is64Bit() ? MVT::i128 : MVT::i64;
24664 if ((ValueVT == PairVT ||
24665 (!Subtarget.is64Bit() && Subtarget.hasStdExtZdinx() &&
24666 ValueVT == MVT::f64)) &&
24667 NumParts == 1 && PartVT == MVT::Untyped) {
24669 MVT XLenVT = Subtarget.getXLenVT();
24670 if (ValueVT == MVT::f64)
24675 Parts[0] = DAG.
getNode(RISCVISD::BuildGPRPair,
DL, PartVT,
Lo,
Hi);
24679 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
24680 PartVT == MVT::f32) {
24683 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::i16, Val);
24687 Val = DAG.
getNode(ISD::BITCAST,
DL, PartVT, Val);
24695 [[maybe_unused]]
unsigned ValLMUL =
24699 [[maybe_unused]]
unsigned PartLMUL =
24702 assert(ValNF == PartNF && ValLMUL == PartLMUL &&
24703 "RISC-V vector tuple type only accepts same register class type "
24724 if (PartVTBitSize % ValueVTBitSize == 0) {
24725 assert(PartVTBitSize >= ValueVTBitSize);
24732 if (ValueEltVT != PartEltVT) {
24733 if (PartVTBitSize > ValueVTBitSize) {
24735 assert(
Count != 0 &&
"The number of element should not be zero.");
24736 EVT SameEltTypeVT =
24740 Val = DAG.
getNode(ISD::BITCAST,
DL, PartVT, Val);
24754 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
24755 bool IsABIRegCopy = CC.has_value();
24757 MVT PairVT = Subtarget.is64Bit() ? MVT::i128 : MVT::i64;
24758 if ((ValueVT == PairVT ||
24759 (!Subtarget.is64Bit() && Subtarget.hasStdExtZdinx() &&
24760 ValueVT == MVT::f64)) &&
24761 NumParts == 1 && PartVT == MVT::Untyped) {
24763 MVT XLenVT = Subtarget.getXLenVT();
24772 if (ValueVT == MVT::f64)
24777 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
24778 PartVT == MVT::f32) {
24782 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::i32, Val);
24784 Val = DAG.
getNode(ISD::BITCAST,
DL, ValueVT, Val);
24800 if (PartVTBitSize % ValueVTBitSize == 0) {
24801 assert(PartVTBitSize >= ValueVTBitSize);
24802 EVT SameEltTypeVT = ValueVT;
24809 if (ValueEltVT != PartEltVT) {
24811 assert(
Count != 0 &&
"The number of element should not be zero.");
24814 Val = DAG.
getNode(ISD::BITCAST,
DL, SameEltTypeVT, Val);
24830 bool OptSize = Attr.hasFnAttr(Attribute::MinSize);
24837 unsigned Opc =
N->getOpcode();
24846 M, Intrinsic::thread_pointer, IRB.
getPtrTy());
24854 if (Subtarget.isTargetFuchsia())
24860 if (Subtarget.isTargetAndroid())
24865 if (M->getStackProtectorGuard() ==
"tls") {
24867 int Offset = M->getStackProtectorGuardOffset();
24875 Align Alignment)
const {
24876 if (!Subtarget.hasVInstructions())
24880 if (DataType.isFixedLengthVector() && !Subtarget.useRVVForFixedLengthVectors())
24887 if (!Subtarget.enableUnalignedVectorMem() &&
24899 "Invalid call instruction for a KCFI check");
24901 MBBI->getOpcode()));
24904 Target.setIsRenamable(
false);
24912#define GET_REGISTER_MATCHER
24913#include "RISCVGenAsmMatcher.inc"
24924 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
24925 if (!ReservedRegs.
test(Reg) && !Subtarget.isRegisterReservedByUser(Reg))
24933 const MDNode *NontemporalInfo =
I.getMetadata(LLVMContext::MD_nontemporal);
24935 if (NontemporalInfo ==
nullptr)
24943 int NontemporalLevel = 5;
24944 const MDNode *RISCVNontemporalInfo =
24945 I.getMetadata(
"riscv-nontemporal-domain");
24946 if (RISCVNontemporalInfo !=
nullptr)
24953 assert((1 <= NontemporalLevel && NontemporalLevel <= 5) &&
24954 "RISC-V target doesn't support this non-temporal domain.");
24956 NontemporalLevel -= 2;
24958 if (NontemporalLevel & 0b1)
24960 if (NontemporalLevel & 0b10)
24973 return TargetFlags;
24986 return Subtarget.hasStdExtZvbb();
24991 return Subtarget.hasCPOPLike() && (VT == MVT::i32 || VT == MVT::i64);
25001 if (Subtarget.hasStdExtZalasr()) {
25002 if (Subtarget.hasStdExtZtso()) {
25032 if (
Op == Instruction::Add ||
Op == Instruction::Sub ||
25033 Op == Instruction::And ||
Op == Instruction::Or ||
25034 Op == Instruction::Xor ||
Op == Instruction::InsertElement ||
25035 Op == Instruction::ShuffleVector ||
Op == Instruction::Load ||
25036 Op == Instruction::Freeze ||
Op == Instruction::Store)
25041 if (RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(
II->getIntrinsicID())) {
25046 for (
unsigned i = 0; i <
II->arg_size(); ++i)
25047 if (
II->getArgOperand(i)->getType()->isRISCVVectorTupleTy())
25063 if (AI->getAllocatedType()->isScalableTy())
25071RISCVTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
25079 if (!Subtarget.hasShortForwardBranchOpt())
25081 EVT VT =
N->getValueType(0);
25082 if (!(VT == MVT::i32 || (VT == MVT::i64 && Subtarget.
is64Bit())))
25086 if (Divisor.
sgt(2048) || Divisor.
slt(-2048))
25091bool RISCVTargetLowering::shouldFoldSelectWithSingleBitTest(
25092 EVT VT,
const APInt &AndMask)
const {
25093 if (Subtarget.
hasCZEROLike() || Subtarget.hasVendorXTHeadCondMov())
25099 return Subtarget.getMinimumJumpTableEntries();
25106 if (Subtarget.hasStdExtZicfilp()) {
25113 return DAG.
getNode(RISCVISD::SW_GUARDED_BRIND, dl, MVT::Other, Chain, Addr);
25130std::pair<const TargetRegisterClass *, uint8_t>
25150#define GET_RISCVVIntrinsicsTable_IMPL
25151#include "RISCVGenSearchableTables.inc"
25166 Align StackAlign)
const {
25170 unsigned StackProbeSize =
25174 return StackProbeSize ? StackProbeSize : StackAlign.
value();
25191 EVT VT =
Op.getValueType();
25202 Chain = DAG.
getNode(RISCVISD::PROBED_ALLOCA, dl, MVT::Other, Chain, SP);
25212 Register TargetReg =
MI.getOperand(0).getReg();
25215 bool IsRV64 = Subtarget.is64Bit();
25216 Align StackAlign = Subtarget.getFrameLowering()->getStackAlign();
25223 MF.
insert(MBBInsertPoint, LoopTestMBB);
25225 MF.
insert(MBBInsertPoint, ExitMBB);
25241 TII->get(IsRV64 ? RISCV::SD : RISCV::SW))
25262 MBB->addSuccessor(LoopTestMBB);
25264 MI.eraseFromParent();
25266 return ExitMBB->
begin()->getParent();
25270 if (Subtarget.hasStdExtFOrZfinx()) {
25271 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(ConstantPoolSDNode *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 void processVCIXOperands(SDValue OrigOp, MutableArrayRef< SDValue > Operands, SelectionDAG &DAG)
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 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 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 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(3))
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 void promoteVCIXScalar(SDValue Op, MutableArrayRef< SDValue > Operands, 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 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 SDValue combineOrToBitfieldInsert(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue getVCIXISDNodeVOID(SDValue Op, SelectionDAG &DAG, unsigned Type)
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 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 getVCIXISDNodeWCHAIN(SDValue Op, SelectionDAG &DAG, unsigned Type)
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 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 SDValue combineOrAndToBitfieldInsert(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
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.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
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 bool isRISCVVectorTupleTy() const
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)
BinaryOp_match< LHS, RHS, Instruction::Or > m_Or(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)
auto m_SpecificVT(EVT RefVT, const Pattern &P)
Match a specific ValueType.
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)
int isShifted359(T Value, int &Shift)
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.
constexpr 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 KnownBits add(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false)
Compute knownbits resulting from addition of LHS and RHS.
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)