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.useCCMovInsn() && !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},
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;
4612 Vec = getVSlide(ContainerVT, DAG.
getUNDEF(ContainerVT), Vec,
Offset, Mask,
4619 Opcode = SlideUp ? RISCVISD::VFSLIDE1UP_VL : RISCVISD::VFSLIDE1DOWN_VL;
4621 Opcode = SlideUp ? RISCVISD::VSLIDE1UP_VL : RISCVISD::VSLIDE1DOWN_VL;
4630 Vec = getVSlide(ContainerVT, DAG.
getUNDEF(ContainerVT), Vec,
Offset, Mask,
4646 if ((LoC >> 31) == HiC)
4647 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4659 auto InterVec = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, InterVT,
4661 return DAG.
getNode(ISD::BITCAST,
DL, VT, InterVec);
4668 Hi.getConstantOperandVal(1) == 31)
4669 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4674 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4677 return DAG.
getNode(RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL,
DL, VT, Passthru,
Lo,
4687 assert(Scalar.getValueType() == MVT::i64 &&
"Unexpected VT!");
4699 bool HasPassthru = Passthru && !Passthru.
isUndef();
4700 if (!HasPassthru && !Passthru)
4707 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
4708 EltVT == MVT::bf16) {
4709 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4710 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
4711 Scalar = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Scalar);
4713 Scalar = DAG.
getNode(ISD::BITCAST,
DL, MVT::i16, Scalar);
4715 Passthru = DAG.
getNode(ISD::BITCAST,
DL, IVT, Passthru);
4720 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL, VT, Passthru, Scalar, VL);
4724 if (Scalar.getValueType().bitsLE(XLenVT)) {
4731 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4732 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru, Scalar, VL);
4735 assert(XLenVT == MVT::i32 && Scalar.getValueType() == MVT::i64 &&
4736 "Unexpected scalar for splat lowering!");
4739 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, VT, Passthru,
4765 MVT ExtractedContainerVT = ExtractedVT;
4768 DAG, ExtractedContainerVT, Subtarget);
4770 ExtractedVal, DAG, Subtarget);
4772 if (ExtractedContainerVT.
bitsLE(VT))
4784 if (!Scalar.getValueType().bitsLE(XLenVT))
4787 VT,
DL, DAG, Subtarget);
4795 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4836 Src && Src.
getValueType().getVectorNumElements() == (NumElts * 2))
4853 !Subtarget.hasVendorXRivosVizip())
4856 int Size = Mask.size();
4858 assert(
Size == (
int)NumElts &&
"Unexpected mask size");
4864 EvenSrc = StartIndexes[0];
4865 OddSrc = StartIndexes[1];
4868 if (EvenSrc != 0 && OddSrc != 0)
4878 int HalfNumElts = NumElts / 2;
4879 return ((EvenSrc % HalfNumElts) == 0) && ((OddSrc % HalfNumElts) == 0);
4884 std::array<std::pair<int, int>, 2> &SrcInfo) {
4889 if (SrcInfo[0].second == 0 && SrcInfo[1].second == 0)
4893 if ((SrcInfo[0].second > 0 && SrcInfo[1].second < 0) ||
4894 SrcInfo[1].second == 0)
4896 assert(SrcInfo[0].first != -1 &&
"Must find one slide");
4904 if (SrcInfo[1].first == -1)
4906 return SrcInfo[0].second < 0 && SrcInfo[1].second > 0 &&
4907 SrcInfo[1].second - SrcInfo[0].second == (int)NumElts;
4912 bool RequiredPolarity) {
4913 int NumElts = Mask.size();
4914 for (
const auto &[Idx, M] :
enumerate(Mask)) {
4917 int Src = M >= NumElts;
4918 int Diff = (int)Idx - (M % NumElts);
4919 bool C = Src == SrcInfo[1].first && Diff == SrcInfo[1].second;
4920 assert(
C != (Src == SrcInfo[0].first && Diff == SrcInfo[0].second) &&
4921 "Must match exactly one of the two slides");
4922 if (RequiredPolarity != (
C == (Idx / Factor) % 2))
4933static bool isZipEven(
const std::array<std::pair<int, int>, 2> &SrcInfo,
4935 Factor = SrcInfo[1].second;
4937 Mask.size() % Factor == 0 &&
4948static bool isZipOdd(
const std::array<std::pair<int, int>, 2> &SrcInfo,
4950 Factor = -SrcInfo[1].second;
4952 Mask.size() % Factor == 0 &&
4965 ElementCount SrcEC = Src.getValueType().getVectorElementCount();
4972 unsigned Shift = Index * EltBits;
4997 std::optional<int> SplatIdx;
4999 if (M == -1 ||
I == (
unsigned)M)
5001 if (SplatIdx && *SplatIdx != M)
5010 for (
int MaskIndex : Mask) {
5011 bool SelectMaskVal = MaskIndex == *SplatIdx;
5014 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
5039 auto findNonEXTRACT_SUBVECTORParent =
5040 [](
SDValue Parent) -> std::pair<SDValue, uint64_t> {
5045 Parent.getOperand(0).getSimpleValueType().isFixedLengthVector()) {
5046 Offset += Parent.getConstantOperandVal(1);
5047 Parent = Parent.getOperand(0);
5049 return std::make_pair(Parent,
Offset);
5052 auto [V1Src, V1IndexOffset] = findNonEXTRACT_SUBVECTORParent(V1);
5053 auto [V2Src, V2IndexOffset] = findNonEXTRACT_SUBVECTORParent(V2);
5062 for (
size_t i = 0; i != NewMask.
size(); ++i) {
5063 if (NewMask[i] == -1)
5066 if (
static_cast<size_t>(NewMask[i]) < NewMask.
size()) {
5067 NewMask[i] = NewMask[i] + V1IndexOffset;
5071 NewMask[i] = NewMask[i] - NewMask.
size() + V2IndexOffset;
5077 if (NewMask[0] <= 0)
5081 for (
unsigned i = 1; i != NewMask.
size(); ++i)
5082 if (NewMask[i - 1] + 1 != NewMask[i])
5086 MVT SrcVT = Src.getSimpleValueType();
5115 int NumSubElts, Index;
5120 bool OpsSwapped = Mask[Index] < (int)NumElts;
5121 SDValue InPlace = OpsSwapped ? V2 : V1;
5122 SDValue ToInsert = OpsSwapped ? V1 : V2;
5133 if (NumSubElts + Index >= (
int)NumElts)
5144 Res = DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, ContainerVT, InPlace, ToInsert,
5147 Res =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, InPlace, ToInsert,
5159 bool OpsSwapped =
false;
5174 const unsigned E = Mask.size() - ((
Offset > 0) ?
Offset : 0);
5175 for (
unsigned i = S; i !=
E; ++i)
5176 if (Mask[i] >= 0 && (
unsigned)Mask[i] !=
Base + i +
Offset)
5182 bool IsVSlidedown = isSlideMask(Mask, OpsSwapped ? 0 : NumElts, 1);
5183 if (!IsVSlidedown && !isSlideMask(Mask, OpsSwapped ? 0 : NumElts, -1))
5186 const int InsertIdx = Mask[IsVSlidedown ? (NumElts - 1) : 0];
5188 if (InsertIdx < 0 || InsertIdx / NumElts != (
unsigned)OpsSwapped)
5205 IsVSlidedown ? RISCVISD::VSLIDE1DOWN_VL : RISCVISD::VSLIDE1UP_VL,
DL,
5211 auto OpCode = IsVSlidedown ?
5212 (VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1DOWN_VL : RISCVISD::VSLIDE1DOWN_VL) :
5213 (VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1UP_VL : RISCVISD::VSLIDE1UP_VL);
5216 auto Vec = DAG.
getNode(OpCode,
DL, ContainerVT,
5219 Splat, TrueMask, VL);
5231 for (
unsigned i = 0; i < Mask.size(); i++)
5232 LaneIsUndef[i % Factor] &= (Mask[i] == -1);
5235 for (
unsigned i = 0; i < Factor; i++) {
5246 for (
unsigned i = 0; i < Mask.size() / Factor; i++) {
5247 unsigned j = i * Factor + Index;
5248 if (Mask[j] != -1 && (
unsigned)Mask[j] != i)
5257 assert(RISCVISD::RI_VZIPEVEN_VL ==
Opc || RISCVISD::RI_VZIPODD_VL ==
Opc ||
5258 RISCVISD::RI_VZIP2A_VL ==
Opc || RISCVISD::RI_VZIP2B_VL ==
Opc ||
5259 RISCVISD::RI_VUNZIP2A_VL ==
Opc || RISCVISD::RI_VUNZIP2B_VL ==
Opc);
5267 MVT ContainerVT = IntVT;
5274 MVT InnerVT = ContainerVT;
5278 (RISCVISD::RI_VUNZIP2A_VL ==
Opc || RISCVISD::RI_VUNZIP2B_VL ==
Opc)) {
5290 if (InnerVT.
bitsLT(ContainerVT))
5305 MVT VT = V.getSimpleValueType();
5320 EC.multiplyCoefficientBy(Factor));
5339 MVT VecContainerVT = VecVT;
5356 MVT WideContainerVT = WideVT;
5362 EvenV = DAG.
getBitcast(VecContainerVT, EvenV);
5369 if (Subtarget.hasStdExtZvbb()) {
5373 Interleaved = DAG.
getNode(RISCVISD::VWSLL_VL,
DL, WideContainerVT, OddV,
5374 OffsetVec, Passthru, Mask, VL);
5375 Interleaved = DAG.
getNode(RISCVISD::VWADDU_W_VL,
DL, WideContainerVT,
5376 Interleaved, EvenV, Passthru, Mask, VL);
5383 Interleaved = DAG.
getNode(RISCVISD::VWADDU_VL,
DL, WideContainerVT, EvenV,
5384 OddV, Passthru, Mask, VL);
5390 OddV, AllOnesVec, Passthru, Mask, VL);
5397 Interleaved = DAG.
getNode(RISCVISD::ADD_VL,
DL, WideContainerVT,
5398 Interleaved, OddsMul, Passthru, Mask, VL);
5405 Interleaved = DAG.
getBitcast(ResultContainerVT, Interleaved);
5451 if (ViaEltSize > NumElts)
5459 if (ViaEltSize > NumElts)
5465 if (ViaEltSize > NumElts)
5472 MVT &RotateVT,
unsigned &RotateAmt) {
5475 unsigned NumSubElts;
5477 NumElts, NumSubElts, RotateAmt))
5480 NumElts / NumSubElts);
5548 unsigned NumOfSrcRegs = NumElts / NumOpElts;
5549 unsigned NumOfDestRegs = NumElts / NumOpElts;
5558 Mask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs,
5559 [&]() {
Operands.emplace_back(); },
5560 [&](
ArrayRef<int> SrcSubMask,
unsigned SrcVecIdx,
unsigned DstVecIdx) {
5561 Operands.emplace_back().emplace_back(SrcVecIdx, UINT_MAX,
5564 [&](
ArrayRef<int> SrcSubMask,
unsigned Idx1,
unsigned Idx2,
bool NewReg) {
5569 assert(
Operands.size() == NumOfDestRegs &&
"Whole vector must be processed");
5574 unsigned NumShuffles = std::accumulate(
5581 for (const auto &P : Data) {
5582 unsigned Idx2 = std::get<1>(P);
5583 ArrayRef<int> Mask = std::get<2>(P);
5584 if (Idx2 != UINT_MAX)
5586 else if (ShuffleVectorInst::isIdentityMask(Mask, Mask.size()))
5591 if ((NumOfDestRegs > 2 && NumShuffles > NumOfDestRegs) ||
5592 (NumOfDestRegs <= 2 && NumShuffles >= 4))
5594 auto ExtractValue = [&, &DAG = DAG](
SDValue SrcVec,
unsigned ExtractIdx) {
5595 SDValue SubVec = DAG.getExtractSubvector(
DL, M1VT, SrcVec, ExtractIdx);
5599 auto PerformShuffle = [&, &DAG = DAG](
SDValue SubVec1,
SDValue SubVec2,
5601 SDValue SubVec = DAG.getVectorShuffle(OneRegVT,
DL, SubVec1, SubVec2, Mask);
5604 SDValue Vec = DAG.getUNDEF(ContainerVT);
5610 const auto &[Idx1, Idx2,
_] =
Data[
I];
5618 V = ExtractValue(Idx1 >= NumOfSrcRegs ? V2 : V1,
5619 (Idx1 % NumOfSrcRegs) * NumOpElts);
5620 if (Idx2 != UINT_MAX) {
5623 V = ExtractValue(Idx2 >= NumOfSrcRegs ? V2 : V1,
5624 (Idx2 % NumOfSrcRegs) * NumOpElts);
5628 for (
const auto &[Idx1, Idx2, Mask] :
Data) {
5630 SDValue V2 = Idx2 == UINT_MAX ? V1 : Values.
at(Idx2);
5631 V = PerformShuffle(V1, V2, Mask);
5635 unsigned InsertIdx =
I * NumOpElts;
5637 Vec = DAG.getInsertSubvector(
DL, Vec, V, InsertIdx);
5647 bool SawUndef =
false;
5648 for (
const auto &[Idx, M] :
enumerate(Mask)) {
5655 if (Idx > (
unsigned)M)
5688 for (
int Idx : Mask) {
5691 unsigned SrcIdx = Idx % Mask.size();
5692 int Src = (
uint32_t)Idx < Mask.size() ? 0 : 1;
5693 if (Srcs[SrcIdx] == -1)
5696 else if (Srcs[SrcIdx] != Src)
5702 for (
int Lane : Srcs) {
5715 for (
unsigned I = 0;
I < Mask.size();
I++) {
5719 NewMask[
I] = Mask[
I] % Mask.size();
5733 if ((M / Span) != (
int)(
I / Span))
5735 int SpanIdx =
I % Span;
5745 return all_of(Mask, [&](
const auto &Idx) {
return Idx == -1 || Idx < Span; });
5757 int SpanIdx =
I % Span;
5758 if (Mask[SpanIdx] != M)
5772 MVT VT =
Op.getSimpleValueType();
5780 if (ElementSize > 32)
5803 MVT VT =
Op.getSimpleValueType();
5831 auto [TrueMask, VL] = TrueMaskVL;
5846 V.getOperand(0).getSimpleValueType().getVectorNumElements();
5847 V = V.getOperand(
Offset / OpElements);
5877 MVT SplatVT = ContainerVT;
5880 if (SVT == MVT::bf16 ||
5881 (SVT == MVT::f16 && !Subtarget.hasStdExtZfh())) {
5890 V = DAG.
getLoad(SVT,
DL, Ld->getChain(), NewAddr,
5891 Ld->getPointerInfo().getWithOffset(
Offset),
5892 Ld->getBaseAlign(), Ld->getMemOperand()->
getFlags());
5895 Ld->getPointerInfo().getWithOffset(
Offset), SVT,
5897 Ld->getMemOperand()->getFlags());
5901 : RISCVISD::VMV_V_X_VL;
5909 assert(Lane < (
int)NumElts &&
"Unexpected lane!");
5912 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
5934 if (Subtarget.hasStdExtZvkb())
5950 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
5951 for (
unsigned Factor = 2; Factor <= MaxFactor; Factor <<= 1) {
5954 1 <
count_if(Mask, [](
int Idx) {
return Idx != -1; })) {
5958 [&Mask](
int Idx) {
return Idx < (int)Mask.size(); }) &&
5959 1 <
count_if(Mask, [&Mask](
int Idx) {
5960 return Idx >= (int)Mask.size();
5990 if (Subtarget.hasVendorXRivosVizip() &&
5992 1 <
count_if(Mask, [](
int Idx) {
return Idx != -1; })) {
5994 Index == 0 ? RISCVISD::RI_VUNZIP2A_VL : RISCVISD::RI_VUNZIP2B_VL;
6010 [&Mask](
int Idx) {
return Idx < (int)Mask.size(); }) &&
6012 [&Mask](
int Idx) {
return Idx >= (int)Mask.size(); })) {
6016 if (NumElts < MinVLMAX) {
6040 int EvenSrc, OddSrc;
6050 bool LaneIsUndef[2] = {
true,
true};
6051 for (
const auto &[Idx, M] :
enumerate(Mask))
6052 LaneIsUndef[Idx % 2] &= (M == -1);
6054 int Size = Mask.size();
6056 if (LaneIsUndef[0]) {
6059 assert(EvenSrc >= 0 &&
"Undef source?");
6060 EvenV = (EvenSrc /
Size) == 0 ? V1 : V2;
6064 if (LaneIsUndef[1]) {
6067 assert(OddSrc >= 0 &&
"Undef source?");
6068 OddV = (OddSrc /
Size) == 0 ? V1 : V2;
6074 if (Subtarget.hasVendorXRivosVizip()) {
6077 return lowerVZIP(RISCVISD::RI_VZIP2A_VL, EvenV, OddV,
DL, DAG, Subtarget);
6088 std::array<std::pair<int, int>, 2> SrcInfo;
6095 auto GetSourceFor = [&](
const std::pair<int, int> &
Info) {
6096 int SrcIdx =
Info.first;
6097 assert(SrcIdx == 0 || SrcIdx == 1);
6098 SDValue &Src = Sources[SrcIdx];
6100 SDValue SrcV = SrcIdx == 0 ? V1 : V2;
6105 auto GetSlide = [&](
const std::pair<int, int> &Src,
SDValue Mask,
6107 auto [TrueMask, VL] = TrueMaskVL;
6108 SDValue SrcV = GetSourceFor(Src);
6109 int SlideAmt = Src.second;
6110 if (SlideAmt == 0) {
6112 assert(Mask == TrueMask);
6119 return getVSlideup(DAG, Subtarget,
DL, ContainerVT, Passthru, SrcV,
6124 if (SrcInfo[1].first == -1) {
6126 Res = GetSlide(SrcInfo[0], TrueMask, Res);
6130 if (Subtarget.hasVendorXRivosVizip()) {
6131 bool TryWiden =
false;
6135 SDValue Src1 = SrcInfo[0].first == 0 ? V1 : V2;
6136 SDValue Src2 = SrcInfo[1].first == 0 ? V1 : V2;
6137 return lowerVZIP(RISCVISD::RI_VZIPEVEN_VL, Src1, Src2,
DL, DAG,
6142 if (
isZipOdd(SrcInfo, Mask, Factor)) {
6144 SDValue Src1 = SrcInfo[1].first == 0 ? V1 : V2;
6145 SDValue Src2 = SrcInfo[0].first == 0 ? V1 : V2;
6146 return lowerVZIP(RISCVISD::RI_VZIPODD_VL, Src1, Src2,
DL, DAG,
6164 for (
const auto &[Idx, M] :
enumerate(Mask)) {
6166 (SrcInfo[1].second > 0 && Idx < (
unsigned)SrcInfo[1].second)) {
6170 int Src = M >= (int)NumElts;
6171 int Diff = (int)Idx - (M % NumElts);
6172 bool C = Src == SrcInfo[1].first && Diff == SrcInfo[1].second;
6173 assert(
C ^ (Src == SrcInfo[0].first && Diff == SrcInfo[0].second) &&
6174 "Must match exactly one of the two slides");
6177 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
6184 Res = GetSlide(SrcInfo[0], TrueMask, Res);
6185 Res = GetSlide(SrcInfo[1], SelectMask, Res);
6190 assert(!V1.
isUndef() &&
"Unexpected shuffle canonicalization");
6205 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
6206 for (
unsigned Factor = 4; Factor <= MaxFactor; Factor <<= 1) {
6221 if (NumElts > MinVLMAX) {
6222 unsigned MaxIdx = 0;
6226 MaxIdx = std::max(std::max((
unsigned)
I, (
unsigned)M), MaxIdx);
6228 unsigned NewNumElts =
6230 if (NewNumElts != NumElts) {
6234 Mask.take_front(NewNumElts));
6251 for (
auto Idx : Mask) {
6254 assert(Idx >= 0 && (
unsigned)Idx < NumElts);
6264 any_of(Mask, [&](
const auto &Idx) {
return Idx > 255; })) {
6274 unsigned GatherVVOpc = RISCVISD::VRGATHER_VV_VL;
6280 GatherVVOpc = RISCVISD::VRGATHEREI16_VV_VL;
6289 GatherVVOpc = RISCVISD::VRGATHEREI16_VV_VL;
6293 MVT IndexContainerVT =
6298 for (
int MaskIndex : Mask) {
6299 bool IsLHSIndex = MaskIndex < (int)NumElts && MaskIndex >= 0;
6309 if (NumElts <= MinVLMAX) {
6311 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
6317 auto [InnerTrueMask, InnerVL] =
6329 for (
int i = 0; i <
N; i++) {
6333 DAG.
getNode(GatherVVOpc,
DL, M1VT, SubV1, SubIndex,
6334 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6351 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6353 for (
int i = 0; i <
N; i++)
6369 for (
int i = 0; i <
N; i++) {
6372 DAG.
getUNDEF(IndexContainerVT), LHSIndices,
6373 SlideAmt, TrueMask, VL);
6377 DAG.
getNode(GatherVVOpc,
DL, M1VT, SubV1, SubIndex,
6378 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6388 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
6398 for (
int MaskIndex : Mask) {
6399 bool IsLHSOrUndefIndex = MaskIndex < (int)NumElts;
6400 ShuffleMaskLHS.
push_back(IsLHSOrUndefIndex && MaskIndex >= 0
6402 ShuffleMaskRHS.
push_back(IsLHSOrUndefIndex ? -1 : (MaskIndex - NumElts));
6433 for (
int MaskIndex : Mask) {
6434 bool SelectMaskVal = (MaskIndex < (int)NumElts) ^ !SwapOps;
6438 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
6456 const unsigned NumElts = M.size();
6463 std::array<std::pair<int, int>, 2> SrcInfo;
6474RISCVTargetLowering::lowerCTLZ_CTTZ_ZERO_UNDEF(
SDValue Op,
6476 MVT VT =
Op.getSimpleValueType();
6480 MVT ContainerVT = VT;
6483 if (
Op->isVPOpcode()) {
6484 Mask =
Op.getOperand(1);
6488 VL =
Op.getOperand(2);
6494 MVT FloatEltVT = (EltSize >= 32) ? MVT::f64 :
MVT::f32;
6496 FloatEltVT = MVT::f32;
6503 "Expected legal float type!");
6510 }
else if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF) {
6513 Src = DAG.
getNode(ISD::VP_AND,
DL, VT, Src, Neg, Mask, VL);
6518 if (FloatVT.
bitsGT(VT)) {
6519 if (
Op->isVPOpcode())
6520 FloatVal = DAG.
getNode(ISD::VP_UINT_TO_FP,
DL, FloatVT, Src, Mask, VL);
6529 if (!
Op->isVPOpcode())
6533 MVT ContainerFloatVT =
6535 FloatVal = DAG.
getNode(RISCVISD::VFCVT_RM_F_XU_VL,
DL, ContainerFloatVT,
6536 Src, Mask, RTZRM, VL);
6543 unsigned ShiftAmt = FloatEltVT == MVT::f64 ? 52 : 23;
6547 if (
Op->isVPOpcode()) {
6556 else if (IntVT.
bitsGT(VT))
6561 unsigned ExponentBias = FloatEltVT == MVT::f64 ? 1023 : 127;
6566 if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF)
6567 return DAG.
getNode(ISD::VP_SUB,
DL, VT, Exp,
6572 unsigned Adjust = ExponentBias + (EltSize - 1);
6574 if (
Op->isVPOpcode())
6584 else if (
Op.getOpcode() == ISD::VP_CTLZ)
6585 Res = DAG.
getNode(ISD::VP_UMIN,
DL, VT, Res,
6593 MVT XLenVT = Subtarget.getXLenVT();
6595 MVT SrcVT =
Source.getSimpleValueType();
6604 SrcVT = ContainerVT;
6616 SDValue Res = DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Source, Mask, EVL);
6617 if (
Op->getOpcode() == ISD::VP_CTTZ_ELTS_ZERO_UNDEF)
6635 assert(Load &&
Load->getMemoryVT().isVector() &&
"Expected vector load");
6638 Load->getMemoryVT(),
6639 *
Load->getMemOperand()))
6643 MVT VT =
Op.getSimpleValueType();
6645 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
6646 "Unexpected unaligned RVV load type");
6650 "Expecting equally-sized RVV vector types to be legal");
6652 Load->getPointerInfo(),
Load->getBaseAlign(),
6653 Load->getMemOperand()->getFlags());
6664 assert(Store &&
Store->getValue().getValueType().isVector() &&
6665 "Expected vector store");
6668 Store->getMemoryVT(),
6669 *
Store->getMemOperand()))
6676 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
6677 "Unexpected unaligned RVV store type");
6681 "Expecting equally-sized RVV vector types to be legal");
6682 StoredVal = DAG.
getBitcast(NewVT, StoredVal);
6684 Store->getPointerInfo(),
Store->getBaseAlign(),
6685 Store->getMemOperand()->getFlags());
6690 assert(
Op.getValueType() == MVT::i64 &&
"Unexpected VT");
6719 unsigned ShiftAmt, AddOpc;
6730 MVT VT =
Op.getSimpleValueType();
6734 bool Negate =
false;
6738 if (Index < 0 &&
Imm.isNegative()) {
6755 return DAG.
getNode(ISD::FNEG,
DL, VT, Const);
6761 unsigned IsData =
Op.getConstantOperandVal(4);
6764 if (Subtarget.hasVendorXMIPSCBOP() && !IsData)
6765 return Op.getOperand(0);
6777 if (Subtarget.hasStdExtZtso()) {
6785 return DAG.
getNode(ISD::MEMBARRIER, dl, MVT::Other,
Op.getOperand(0));
6793 return DAG.
getNode(ISD::MEMBARRIER, dl, MVT::Other,
Op.getOperand(0));
6801 MVT VT =
Op.getSimpleValueType();
6802 MVT XLenVT = Subtarget.getXLenVT();
6803 unsigned Check =
Op.getConstantOperandVal(1);
6804 unsigned TDCMask = 0;
6832 MVT VT0 =
Op.getOperand(0).getSimpleValueType();
6837 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6839 VL =
Op.getOperand(3);
6842 VL,
Op->getFlags());
6857 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6859 MVT MaskContainerVT =
6862 VL =
Op.getOperand(3);
6866 SDValue FPCLASS = DAG.
getNode(RISCVISD::FCLASS_VL,
DL, ContainerDstVT, Op0,
6867 Mask, VL,
Op->getFlags());
6869 TDCMaskV = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerDstVT,
6870 DAG.
getUNDEF(ContainerDstVT), TDCMaskV, VL);
6873 DAG.
getNode(RISCVISD::SETCC_VL,
DL, ContainerVT,
6879 TDCMaskV, DAG.
getUNDEF(ContainerDstVT), Mask, VL);
6882 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerDstVT,
6883 DAG.
getUNDEF(ContainerDstVT), SplatZero, VL);
6903 MVT VT =
Op.getSimpleValueType();
6929 Op.getOpcode() == ISD::FMAXIMUM ? RISCVISD::FMAX : RISCVISD::FMIN;
6937 MVT ContainerVT = VT;
6945 if (
Op->isVPOpcode()) {
6946 Mask =
Op.getOperand(2);
6950 VL =
Op.getOperand(3);
6957 SDValue XIsNonNan = DAG.
getNode(RISCVISD::SETCC_VL,
DL, Mask.getValueType(),
6958 {X, X, DAG.getCondCode(ISD::SETOEQ),
6959 DAG.getUNDEF(ContainerVT), Mask, VL});
6960 NewY = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, XIsNonNan,
Y,
X,
6966 SDValue YIsNonNan = DAG.
getNode(RISCVISD::SETCC_VL,
DL, Mask.getValueType(),
6967 {Y, Y, DAG.getCondCode(ISD::SETOEQ),
6968 DAG.getUNDEF(ContainerVT), Mask, VL});
6969 NewX = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, YIsNonNan,
X,
Y,
6974 Op.getOpcode() == ISD::FMAXIMUM ||
Op->getOpcode() == ISD::VP_FMAXIMUM
6975 ? RISCVISD::VFMAX_VL
6976 : RISCVISD::VFMIN_VL;
6978 DAG.
getUNDEF(ContainerVT), Mask, VL);
6986 bool IsFABS =
Op.getOpcode() == ISD::FABS;
6987 assert((IsFABS ||
Op.getOpcode() == ISD::FNEG) &&
6988 "Wrong opcode for lowering FABS or FNEG.");
6991 MVT VT =
Op.getSimpleValueType();
6992 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
6996 DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT,
Op.getOperand(0));
6999 Mask = Mask.sext(Subtarget.
getXLen());
7004 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, Logic);
7012 MVT VT =
Op.getSimpleValueType();
7013 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
7023 if (SignSize == Subtarget.
getXLen())
7024 return DAG.
getNode(ISD::BITCAST,
DL, XLenVT, Sign);
7027 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Sign);
7029 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, XLenVT, Sign);
7031 assert(XLenVT == MVT::i32 &&
"Unexpected type");
7034 return DAG.
getNode(RISCVISD::SplitF64,
DL, {MVT::i32, MVT::i32}, Sign)
7064 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, CopiedSign);
7069#define OP_CASE(NODE) \
7071 return RISCVISD::NODE##_VL;
7072#define VP_CASE(NODE) \
7073 case ISD::VP_##NODE: \
7074 return RISCVISD::NODE##_VL;
7076 switch (
Op.getOpcode()) {
7155 case ISD::VP_CTLZ_ZERO_UNDEF:
7156 return RISCVISD::CTLZ_VL;
7158 case ISD::VP_CTTZ_ZERO_UNDEF:
7159 return RISCVISD::CTTZ_VL;
7162 return RISCVISD::VFMADD_VL;
7164 return RISCVISD::STRICT_VFMADD_VL;
7167 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7168 return RISCVISD::VMAND_VL;
7169 return RISCVISD::AND_VL;
7172 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7173 return RISCVISD::VMOR_VL;
7174 return RISCVISD::OR_VL;
7177 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7178 return RISCVISD::VMXOR_VL;
7179 return RISCVISD::XOR_VL;
7182 return RISCVISD::VZEXT_VL;
7184 return RISCVISD::VSEXT_VL;
7186 return RISCVISD::SETCC_VL;
7188 return RISCVISD::VMERGE_VL;
7189 case ISD::VP_SELECT:
7191 return RISCVISD::VMERGE_VL;
7193 return RISCVISD::SRA_VL;
7195 return RISCVISD::SRL_VL;
7197 return RISCVISD::FSQRT_VL;
7198 case ISD::VP_SIGN_EXTEND:
7199 return RISCVISD::VSEXT_VL;
7200 case ISD::VP_ZERO_EXTEND:
7201 return RISCVISD::VZEXT_VL;
7202 case ISD::VP_FP_TO_SINT:
7203 return RISCVISD::VFCVT_RTZ_X_F_VL;
7204 case ISD::VP_FP_TO_UINT:
7205 return RISCVISD::VFCVT_RTZ_XU_F_VL;
7207 case ISD::FMINIMUMNUM:
7208 case ISD::VP_FMINNUM:
7209 return RISCVISD::VFMIN_VL;
7211 case ISD::FMAXIMUMNUM:
7212 case ISD::VP_FMAXNUM:
7213 return RISCVISD::VFMAX_VL;
7217 case ISD::VP_LLRINT:
7218 return RISCVISD::VFCVT_RM_X_F_VL;
7227 return (
Op.getValueType() == MVT::nxv32f16 &&
7230 Op.getValueType() == MVT::nxv32bf16;
7240 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7241 if (!
Op.getOperand(j).getValueType().isVector()) {
7242 LoOperands[j] =
Op.getOperand(j);
7243 HiOperands[j] =
Op.getOperand(j);
7246 std::tie(LoOperands[j], HiOperands[j]) =
7251 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
7253 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
7266 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7268 std::tie(LoOperands[j], HiOperands[j]) =
7272 if (!
Op.getOperand(j).getValueType().isVector()) {
7273 LoOperands[j] =
Op.getOperand(j);
7274 HiOperands[j] =
Op.getOperand(j);
7277 std::tie(LoOperands[j], HiOperands[j]) =
7282 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
7284 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
7294 auto [EVLLo, EVLHi] =
7295 DAG.
SplitEVL(
Op.getOperand(3),
Op.getOperand(1).getValueType(),
DL);
7299 {Op.getOperand(0), Lo, MaskLo, EVLLo},
Op->getFlags());
7301 {ResLo, Hi, MaskHi, EVLHi},
Op->getFlags());
7318 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7319 if (!
Op.getOperand(j).getValueType().isVector()) {
7320 LoOperands[j] =
Op.getOperand(j);
7321 HiOperands[j] =
Op.getOperand(j);
7324 std::tie(LoOperands[j], HiOperands[j]) =
7329 DAG.
getNode(
Op.getOpcode(),
DL, LoVTs, LoOperands,
Op->getFlags());
7332 DAG.
getNode(
Op.getOpcode(),
DL, HiVTs, HiOperands,
Op->getFlags());
7340RISCVTargetLowering::lowerXAndesBfHCvtBFloat16Load(
SDValue Op,
7342 assert(Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh() &&
7343 "Unexpected bfloat16 load lowering");
7347 EVT MemVT =
LD->getMemoryVT();
7352 LD->getMemOperand());
7360 DAG.
getNode(RISCVISD::NDS_FMV_BF16_X,
DL, MVT::bf16, OrSixteenOne);
7365RISCVTargetLowering::lowerXAndesBfHCvtBFloat16Store(
SDValue Op,
7367 assert(Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh() &&
7368 "Unexpected bfloat16 store lowering");
7373 Subtarget.getXLenVT(),
ST->getValue());
7375 ST->getChain(),
DL, FMV,
ST->getBasePtr(),
7377 ST->getMemOperand());
7382 switch (
Op.getOpcode()) {
7385 "Unimplemented RISCVTargetLowering::LowerOperation Case");
7388 case ISD::ATOMIC_FENCE:
7391 return lowerGlobalAddress(
Op, DAG);
7393 return lowerBlockAddress(
Op, DAG);
7395 return lowerConstantPool(
Op, DAG);
7397 return lowerJumpTable(
Op, DAG);
7399 return lowerGlobalTLSAddress(
Op, DAG);
7403 return lowerConstantFP(
Op, DAG);
7405 return lowerSELECT(
Op, DAG);
7407 return lowerBRCOND(
Op, DAG);
7409 return lowerVASTART(
Op, DAG);
7411 return lowerFRAMEADDR(
Op, DAG);
7413 return lowerRETURNADDR(
Op, DAG);
7415 return lowerShiftLeftParts(
Op, DAG);
7417 return lowerShiftRightParts(
Op, DAG,
true);
7419 return lowerShiftRightParts(
Op, DAG,
false);
7422 if (
Op.getValueType().isFixedLengthVector()) {
7423 assert(Subtarget.hasStdExtZvkb());
7424 return lowerToScalableOp(
Op, DAG);
7426 assert(Subtarget.hasVendorXTHeadBb() &&
7427 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
7428 "Unexpected custom legalization");
7433 case ISD::BITCAST: {
7435 EVT VT =
Op.getValueType();
7438 MVT XLenVT = Subtarget.getXLenVT();
7439 if (Op0VT == MVT::i16 &&
7440 ((VT == MVT::f16 && Subtarget.hasStdExtZfhminOrZhinxmin()) ||
7441 (VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
7443 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, NewOp0);
7445 if (VT == MVT::f32 && Op0VT == MVT::i32 && Subtarget.is64Bit() &&
7446 Subtarget.hasStdExtFOrZfinx()) {
7448 return DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, NewOp0);
7450 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit() &&
7451 Subtarget.hasStdExtDOrZdinx()) {
7454 return DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64,
Lo,
Hi);
7466 "Unexpected types");
7498 return LowerINTRINSIC_WO_CHAIN(
Op, DAG);
7500 return LowerINTRINSIC_W_CHAIN(
Op, DAG);
7502 return LowerINTRINSIC_VOID(
Op, DAG);
7504 return LowerIS_FPCLASS(
Op, DAG);
7506 MVT VT =
Op.getSimpleValueType();
7508 assert(Subtarget.hasStdExtZvbb());
7509 return lowerToScalableOp(
Op, DAG);
7512 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected custom legalization");
7516 return DAG.
getNode(RISCVISD::BREV8,
DL, VT, BSwap);
7522 if (!
Op.getSimpleValueType().isVector())
7524 return lowerVectorTruncLike(
Op, DAG);
7527 if (
Op.getOperand(0).getValueType().isVector() &&
7528 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7529 return lowerVectorMaskExt(
Op, DAG, 1);
7530 if (
Op.getValueType().isScalableVector())
7532 return lowerToScalableOp(
Op, DAG);
7534 if (
Op.getOperand(0).getValueType().isVector() &&
7535 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7536 return lowerVectorMaskExt(
Op, DAG, -1);
7537 if (
Op.getValueType().isScalableVector())
7539 return lowerToScalableOp(
Op, DAG);
7541 return lowerSPLAT_VECTOR_PARTS(
Op, DAG);
7543 return lowerINSERT_VECTOR_ELT(
Op, DAG);
7545 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
7547 MVT VT =
Op.getSimpleValueType();
7555 MVT ContainerVT = VT;
7562 V = DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL, ContainerVT,
7563 DAG.
getUNDEF(ContainerVT), Scalar, VL);
7566 V = DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, ContainerVT,
7567 DAG.
getUNDEF(ContainerVT), Scalar, VL);
7574 MVT XLenVT = Subtarget.getXLenVT();
7575 MVT VT =
Op.getSimpleValueType();
7594 }
else if (
Log2 > 3) {
7598 }
else if ((Val % 8) == 0) {
7616 if (
Op.getValueType() == MVT::f16 && Subtarget.is64Bit() &&
7617 Op.getOperand(1).getValueType() == MVT::i32) {
7621 DAG.
getNode(ISD::FPOWI,
DL, MVT::f32, Op0,
Op.getOperand(1));
7632 case ISD::FP_EXTEND:
7634 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
7637 return lowerStrictFPExtendOrRoundLike(
Op, DAG);
7640 if (
Op.getValueType().isVector() &&
7641 ((
Op.getValueType().getScalarType() == MVT::f16 &&
7642 (Subtarget.hasVInstructionsF16Minimal() &&
7643 !Subtarget.hasVInstructionsF16())) ||
7644 Op.getValueType().getScalarType() == MVT::bf16)) {
7660 Op1.getValueType().isVector() &&
7661 ((Op1.getValueType().getScalarType() == MVT::f16 &&
7662 (Subtarget.hasVInstructionsF16Minimal() &&
7663 !Subtarget.hasVInstructionsF16())) ||
7664 Op1.getValueType().getScalarType() == MVT::bf16)) {
7670 Op1.getValueType().getVectorElementCount());
7673 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), WidenVec);
7683 MVT VT =
Op.getSimpleValueType();
7686 bool IsStrict =
Op->isStrictFPOpcode();
7687 SDValue Src =
Op.getOperand(0 + IsStrict);
7688 MVT SrcVT = Src.getSimpleValueType();
7699 "Unexpected vector element types");
7703 if (EltSize > (2 * SrcEltSize)) {
7715 Op.getOperand(0), Ext);
7719 assert(SrcEltVT == MVT::f16 &&
"Unexpected FP_TO_[US]INT lowering");
7724 auto [FExt, Chain] =
7726 return DAG.
getNode(
Op.getOpcode(),
DL,
Op->getVTList(), Chain, FExt);
7733 if (SrcEltSize > (2 * EltSize)) {
7736 assert(EltVT == MVT::f16 &&
"Unexpected [US]_TO_FP lowering");
7741 Op.getOperand(0), Src);
7756 Op.getOperand(0), Src);
7770 unsigned RVVOpc = 0;
7771 switch (
Op.getOpcode()) {
7775 RVVOpc = RISCVISD::VFCVT_RTZ_X_F_VL;
7778 RVVOpc = RISCVISD::VFCVT_RTZ_XU_F_VL;
7781 RVVOpc = RISCVISD::SINT_TO_FP_VL;
7784 RVVOpc = RISCVISD::UINT_TO_FP_VL;
7787 RVVOpc = RISCVISD::STRICT_VFCVT_RTZ_X_F_VL;
7790 RVVOpc = RISCVISD::STRICT_VFCVT_RTZ_XU_F_VL;
7793 RVVOpc = RISCVISD::STRICT_SINT_TO_FP_VL;
7796 RVVOpc = RISCVISD::STRICT_UINT_TO_FP_VL;
7803 "Expected same element count");
7810 Op.getOperand(0), Src, Mask, VL);
7814 Src = DAG.
getNode(RVVOpc,
DL, ContainerVT, Src, Mask, VL);
7820 case ISD::FP_TO_BF16: {
7823 assert(!Subtarget.isSoftFPABI() &&
"Unexpected custom legalization");
7829 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
7830 if (Subtarget.is64Bit())
7831 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Res);
7834 case ISD::BF16_TO_FP: {
7835 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalization");
7836 MVT VT =
Op.getSimpleValueType();
7841 SDValue Res = Subtarget.is64Bit()
7842 ? DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32,
Op)
7846 return DAG.
getNode(ISD::FP_EXTEND,
DL, VT, Res);
7849 case ISD::STRICT_FP_TO_FP16:
7850 case ISD::FP_TO_FP16: {
7853 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalisation");
7856 bool IsStrict =
Op->isStrictFPOpcode();
7857 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7861 std::tie(Res, Chain) =
7862 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
7863 if (Subtarget.is64Bit())
7864 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Res);
7870 case ISD::STRICT_FP16_TO_FP:
7871 case ISD::FP16_TO_FP: {
7874 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalisation");
7877 bool IsStrict =
Op->isStrictFPOpcode();
7878 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7880 SDValue Arg = Subtarget.is64Bit()
7881 ? DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, Op0)
7884 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
7885 CallOptions,
DL, Chain);
7893 case ISD::FNEARBYINT:
7896 case ISD::FROUNDEVEN:
7903 case ISD::LLROUND: {
7904 if (
Op.getValueType().isVector())
7906 assert(
Op.getOperand(0).getValueType() == MVT::f16 &&
7907 "Unexpected custom legalisation");
7910 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), Ext);
7916 assert(
Op.getOperand(1).getValueType() == MVT::f16 &&
7917 "Unexpected custom legalisation");
7920 {
Op.getOperand(0),
Op.getOperand(1)});
7921 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
7922 {Ext.getValue(1), Ext.getValue(0)});
7924 case ISD::VECREDUCE_ADD:
7925 case ISD::VECREDUCE_UMAX:
7926 case ISD::VECREDUCE_SMAX:
7927 case ISD::VECREDUCE_UMIN:
7928 case ISD::VECREDUCE_SMIN:
7929 return lowerVECREDUCE(
Op, DAG);
7930 case ISD::VECREDUCE_AND:
7931 case ISD::VECREDUCE_OR:
7932 case ISD::VECREDUCE_XOR:
7933 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7934 return lowerVectorMaskVecReduction(
Op, DAG,
false);
7935 return lowerVECREDUCE(
Op, DAG);
7936 case ISD::VECREDUCE_FADD:
7937 case ISD::VECREDUCE_SEQ_FADD:
7938 case ISD::VECREDUCE_FMIN:
7939 case ISD::VECREDUCE_FMAX:
7940 case ISD::VECREDUCE_FMAXIMUM:
7941 case ISD::VECREDUCE_FMINIMUM:
7942 return lowerFPVECREDUCE(
Op, DAG);
7943 case ISD::VP_REDUCE_ADD:
7944 case ISD::VP_REDUCE_UMAX:
7945 case ISD::VP_REDUCE_SMAX:
7946 case ISD::VP_REDUCE_UMIN:
7947 case ISD::VP_REDUCE_SMIN:
7948 case ISD::VP_REDUCE_FADD:
7949 case ISD::VP_REDUCE_SEQ_FADD:
7950 case ISD::VP_REDUCE_FMIN:
7951 case ISD::VP_REDUCE_FMAX:
7952 case ISD::VP_REDUCE_FMINIMUM:
7953 case ISD::VP_REDUCE_FMAXIMUM:
7956 return lowerVPREDUCE(
Op, DAG);
7957 case ISD::VP_REDUCE_AND:
7958 case ISD::VP_REDUCE_OR:
7959 case ISD::VP_REDUCE_XOR:
7960 if (
Op.getOperand(1).getValueType().getVectorElementType() == MVT::i1)
7961 return lowerVectorMaskVecReduction(
Op, DAG,
true);
7962 return lowerVPREDUCE(
Op, DAG);
7963 case ISD::VP_CTTZ_ELTS:
7964 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
7965 return lowerVPCttzElements(
Op, DAG);
7969 DAG.
getUNDEF(ContainerVT), DAG, Subtarget);
7972 return lowerINSERT_SUBVECTOR(
Op, DAG);
7974 return lowerEXTRACT_SUBVECTOR(
Op, DAG);
7976 return lowerVECTOR_DEINTERLEAVE(
Op, DAG);
7978 return lowerVECTOR_INTERLEAVE(
Op, DAG);
7980 return lowerSTEP_VECTOR(
Op, DAG);
7982 return lowerVECTOR_REVERSE(
Op, DAG);
7984 return lowerVECTOR_SPLICE(
Op, DAG);
7986 MVT VT =
Op.getSimpleValueType();
7988 if (!Subtarget.is64Bit() && EltVT == MVT::i64)
7993 MVT VT =
Op.getSimpleValueType();
7995 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
7996 EltVT == MVT::bf16) {
7999 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
8000 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
8001 Elt = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, Subtarget.getXLenVT(),
8004 Elt = DAG.
getNode(ISD::BITCAST,
DL, MVT::i16,
Op.getOperand(0));
8006 return DAG.
getNode(ISD::BITCAST,
DL, VT,
8010 if (EltVT == MVT::i1)
8011 return lowerVectorMaskSplat(
Op, DAG);
8020 MVT VT =
Op.getSimpleValueType();
8021 MVT ContainerVT = VT;
8033 if (
Op.getNumOperands() > 2 &&
8037 size_t HalfNumOps =
Op.getNumOperands() / 2;
8039 Op->ops().take_front(HalfNumOps));
8041 Op->ops().drop_front(HalfNumOps));
8045 unsigned NumOpElts =
8046 Op.getOperand(0).getSimpleValueType().getVectorMinNumElements();
8059 EVT VT = Load->getValueType(0);
8060 if (VT == MVT::f64) {
8061 assert(Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
8062 !Subtarget.is64Bit() &&
"Unexpected custom legalisation");
8066 SDValue BasePtr = Load->getBasePtr();
8067 SDValue Chain = Load->getChain();
8070 DAG.
getLoad(MVT::i32,
DL, Chain, BasePtr, Load->getPointerInfo(),
8071 Load->getBaseAlign(), Load->getMemOperand()->getFlags());
8074 MVT::i32,
DL, Chain, BasePtr, Load->getPointerInfo().getWithOffset(4),
8075 Load->getBaseAlign(), Load->getMemOperand()->getFlags());
8083 if (VT == MVT::bf16)
8084 return lowerXAndesBfHCvtBFloat16Load(
Op, DAG);
8089 MVT XLenVT = Subtarget.getXLenVT();
8092 unsigned NumElts = Sz / (NF * 8);
8093 int Log2LMUL =
Log2_64(NumElts) - 3;
8096 Flag.setNoUnsignedWrap(
true);
8098 SDValue BasePtr = Load->getBasePtr();
8106 for (
unsigned i = 0; i < NF; ++i) {
8111 Ret = DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VT, Ret, LoadVal,
8119 if (
auto V = expandUnalignedRVVLoad(
Op, DAG))
8121 if (
Op.getValueType().isFixedLengthVector())
8122 return lowerFixedLengthVectorLoadToRVV(
Op, DAG);
8127 SDValue StoredVal = Store->getValue();
8129 if (VT == MVT::f64) {
8130 assert(Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
8131 !Subtarget.is64Bit() &&
"Unexpected custom legalisation");
8135 SDValue BasePtr = Store->getBasePtr();
8136 SDValue Chain = Store->getChain();
8138 DAG.
getVTList(MVT::i32, MVT::i32), StoredVal);
8141 Store->getPointerInfo(), Store->getBaseAlign(),
8142 Store->getMemOperand()->getFlags());
8145 Store->getPointerInfo().getWithOffset(4),
8146 Store->getBaseAlign(),
8147 Store->getMemOperand()->getFlags());
8150 if (VT == MVT::i64) {
8151 assert(Subtarget.hasStdExtZilsd() && !Subtarget.is64Bit() &&
8152 "Unexpected custom legalisation");
8153 if (Store->isTruncatingStore())
8156 if (!Subtarget.enableUnalignedScalarMem() && Store->getAlign() < 8)
8167 {Store->getChain(), Lo, Hi, Store->getBasePtr()}, MVT::i64,
8168 Store->getMemOperand());
8171 if (VT == MVT::bf16)
8172 return lowerXAndesBfHCvtBFloat16Store(
Op, DAG);
8177 MVT XLenVT = Subtarget.getXLenVT();
8180 unsigned NumElts = Sz / (NF * 8);
8181 int Log2LMUL =
Log2_64(NumElts) - 3;
8184 Flag.setNoUnsignedWrap(
true);
8186 SDValue Chain = Store->getChain();
8187 SDValue BasePtr = Store->getBasePtr();
8194 for (
unsigned i = 0; i < NF; ++i) {
8196 DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL,
8199 Ret = DAG.
getStore(Chain,
DL, Extract, BasePtr,
8201 Store->getBaseAlign(),
8202 Store->getMemOperand()->getFlags());
8203 Chain = Ret.getValue(0);
8209 if (
auto V = expandUnalignedRVVStore(
Op, DAG))
8211 if (
Op.getOperand(1).getValueType().isFixedLengthVector())
8212 return lowerFixedLengthVectorStoreToRVV(
Op, DAG);
8217 return lowerMaskedLoad(
Op, DAG);
8218 case ISD::VP_LOAD_FF:
8219 return lowerLoadFF(
Op, DAG);
8222 return lowerMaskedStore(
Op, DAG);
8224 return lowerVectorCompress(
Op, DAG);
8233 EVT VT =
Op.getValueType();
8244 MVT OpVT =
Op.getOperand(0).getSimpleValueType();
8246 MVT VT =
Op.getSimpleValueType();
8251 "Unexpected CondCode");
8284 return DAG.
getSetCC(
DL, VT, RHS, LHS, CCVal);
8290 return lowerToScalableOp(
Op, DAG);
8307 return lowerToScalableOp(
Op, DAG);
8311 if (
Op.getSimpleValueType().isFixedLengthVector())
8312 return lowerToScalableOp(
Op, DAG);
8314 assert(
Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.is64Bit() &&
8315 "Unexpected custom legalisation");
8319 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
8330 case ISD::FMINIMUMNUM:
8331 case ISD::FMAXIMUMNUM:
8347 return lowerToScalableOp(
Op, DAG);
8351 EVT VT =
Op->getValueType(0);
8366 return lowerABS(
Op, DAG);
8371 if (Subtarget.hasStdExtZvbb())
8372 return lowerToScalableOp(
Op, DAG);
8374 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8376 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
8380 return lowerToScalableOp(
Op, DAG);
8389 return lowerToScalableOp(
Op, DAG);
8392 return lowerVectorStrictFSetcc(
Op, DAG);
8402 case ISD::VP_GATHER:
8403 return lowerMaskedGather(
Op, DAG);
8405 case ISD::VP_SCATTER:
8406 return lowerMaskedScatter(
Op, DAG);
8408 return lowerGET_ROUNDING(
Op, DAG);
8409 case ISD::SET_ROUNDING:
8410 return lowerSET_ROUNDING(
Op, DAG);
8411 case ISD::GET_FPENV:
8412 return lowerGET_FPENV(
Op, DAG);
8413 case ISD::SET_FPENV:
8414 return lowerSET_FPENV(
Op, DAG);
8415 case ISD::RESET_FPENV:
8416 return lowerRESET_FPENV(
Op, DAG);
8417 case ISD::GET_FPMODE:
8418 return lowerGET_FPMODE(
Op, DAG);
8419 case ISD::SET_FPMODE:
8420 return lowerSET_FPMODE(
Op, DAG);
8421 case ISD::RESET_FPMODE:
8422 return lowerRESET_FPMODE(
Op, DAG);
8424 return lowerEH_DWARF_CFA(
Op, DAG);
8426 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
8427 return lowerVPMergeMask(
Op, DAG);
8429 case ISD::VP_SELECT:
8437 case ISD::VP_UADDSAT:
8438 case ISD::VP_USUBSAT:
8439 case ISD::VP_SADDSAT:
8440 case ISD::VP_SSUBSAT:
8442 case ISD::VP_LLRINT:
8443 return lowerVPOp(
Op, DAG);
8447 return lowerLogicVPOp(
Op, DAG);
8456 case ISD::VP_FMINNUM:
8457 case ISD::VP_FMAXNUM:
8458 case ISD::VP_FCOPYSIGN:
8465 return lowerVPOp(
Op, DAG);
8466 case ISD::VP_IS_FPCLASS:
8467 return LowerIS_FPCLASS(
Op, DAG);
8468 case ISD::VP_SIGN_EXTEND:
8469 case ISD::VP_ZERO_EXTEND:
8470 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
8471 return lowerVPExtMaskOp(
Op, DAG);
8472 return lowerVPOp(
Op, DAG);
8473 case ISD::VP_TRUNCATE:
8474 return lowerVectorTruncLike(
Op, DAG);
8475 case ISD::VP_FP_EXTEND:
8476 case ISD::VP_FP_ROUND:
8477 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
8478 case ISD::VP_SINT_TO_FP:
8479 case ISD::VP_UINT_TO_FP:
8480 if (
Op.getValueType().isVector() &&
8481 ((
Op.getValueType().getScalarType() == MVT::f16 &&
8482 (Subtarget.hasVInstructionsF16Minimal() &&
8483 !Subtarget.hasVInstructionsF16())) ||
8484 Op.getValueType().getScalarType() == MVT::bf16)) {
8497 case ISD::VP_FP_TO_SINT:
8498 case ISD::VP_FP_TO_UINT:
8500 Op1.getValueType().isVector() &&
8501 ((Op1.getValueType().getScalarType() == MVT::f16 &&
8502 (Subtarget.hasVInstructionsF16Minimal() &&
8503 !Subtarget.hasVInstructionsF16())) ||
8504 Op1.getValueType().getScalarType() == MVT::bf16)) {
8510 Op1.getValueType().getVectorElementCount());
8514 {WidenVec, Op.getOperand(1), Op.getOperand(2)});
8516 return lowerVPFPIntConvOp(
Op, DAG);
8520 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
8521 return lowerVPSetCCMaskOp(
Op, DAG);
8527 case ISD::VP_BITREVERSE:
8529 return lowerVPOp(
Op, DAG);
8531 case ISD::VP_CTLZ_ZERO_UNDEF:
8532 if (Subtarget.hasStdExtZvbb())
8533 return lowerVPOp(
Op, DAG);
8534 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8536 case ISD::VP_CTTZ_ZERO_UNDEF:
8537 if (Subtarget.hasStdExtZvbb())
8538 return lowerVPOp(
Op, DAG);
8539 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8541 return lowerVPOp(
Op, DAG);
8542 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
8543 return lowerVPStridedLoad(
Op, DAG);
8544 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
8545 return lowerVPStridedStore(
Op, DAG);
8547 case ISD::VP_FFLOOR:
8549 case ISD::VP_FNEARBYINT:
8550 case ISD::VP_FROUND:
8551 case ISD::VP_FROUNDEVEN:
8552 case ISD::VP_FROUNDTOZERO:
8556 case ISD::VP_FMAXIMUM:
8557 case ISD::VP_FMINIMUM:
8561 case ISD::EXPERIMENTAL_VP_SPLICE:
8562 return lowerVPSpliceExperimental(
Op, DAG);
8563 case ISD::EXPERIMENTAL_VP_REVERSE:
8564 return lowerVPReverseExperimental(
Op, DAG);
8565 case ISD::EXPERIMENTAL_VP_SPLAT:
8566 return lowerVPSplatExperimental(
Op, DAG);
8569 "llvm.clear_cache only needs custom lower on Linux targets");
8572 return emitFlushICache(DAG,
Op.getOperand(0),
Op.getOperand(1),
8573 Op.getOperand(2), Flags,
DL);
8575 case ISD::DYNAMIC_STACKALLOC:
8576 return lowerDYNAMIC_STACKALLOC(
Op, DAG);
8577 case ISD::INIT_TRAMPOLINE:
8578 return lowerINIT_TRAMPOLINE(
Op, DAG);
8579 case ISD::ADJUST_TRAMPOLINE:
8580 return lowerADJUST_TRAMPOLINE(
Op, DAG);
8581 case ISD::PARTIAL_REDUCE_UMLA:
8582 case ISD::PARTIAL_REDUCE_SMLA:
8583 case ISD::PARTIAL_REDUCE_SUMLA:
8584 return lowerPARTIAL_REDUCE_MLA(
Op, DAG);
8591 MakeLibCallOptions CallOptions;
8592 std::pair<SDValue, SDValue> CallResult =
8593 makeLibCall(DAG, RTLIB::RISCV_FLUSH_ICACHE, MVT::isVoid,
8594 {Start, End, Flags}, CallOptions,
DL, InChain);
8597 return CallResult.second;
8602 if (!Subtarget.is64Bit())
8610 std::unique_ptr<MCCodeEmitter> CodeEmitter(
8638 const bool HasCFBranch =
8639 Subtarget.hasStdExtZicfilp() &&
8641 "cf-protection-branch");
8642 const unsigned StaticChainIdx = HasCFBranch ? 5 : 4;
8643 const unsigned StaticChainOffset = StaticChainIdx * 4;
8644 const unsigned FunctionAddressOffset = StaticChainOffset + 8;
8648 auto GetEncoding = [&](
const MCInst &MC) {
8651 CodeEmitter->encodeInstruction(MC, CB, Fixups, *STI);
8658 SmallVector<uint32_t> Encodings;
8663 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X7).addImm(0)),
8667 GetEncoding(MCInstBuilder(RISCV::LD)
8670 .addImm(FunctionAddressOffset)),
8673 GetEncoding(MCInstBuilder(RISCV::LD)
8676 .addImm(StaticChainOffset)),
8679 GetEncoding(MCInstBuilder(RISCV::JALR)
8687 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X0).addImm(0)),
8690 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X28).addImm(0)),
8694 GetEncoding(MCInstBuilder(RISCV::LD)
8697 .addImm(FunctionAddressOffset - 4)),
8700 GetEncoding(MCInstBuilder(RISCV::LD)
8703 .addImm(StaticChainOffset - 4)),
8706 GetEncoding(MCInstBuilder(RISCV::JALR)
8718 Root, dl, DAG.
getConstant(Encoding, dl, MVT::i64), Addr,
8719 MachinePointerInfo(TrmpAddr, Idx * 4), MVT::i32));
8723 SDValue FunctionAddress =
Op.getOperand(2);
8727 struct OffsetValuePair {
8731 } OffsetValues[] = {
8732 {StaticChainOffset, StaticChain},
8733 {FunctionAddressOffset, FunctionAddress},
8735 for (
auto &OffsetValue : OffsetValues) {
8738 DAG.
getConstant(OffsetValue.Offset, dl, MVT::i64));
8739 OffsetValue.Addr = Addr;
8741 DAG.
getStore(Root, dl, OffsetValue.Value, Addr,
8742 MachinePointerInfo(TrmpAddr, OffsetValue.Offset)));
8745 assert(OutChains.
size() == StaticChainIdx + 2 &&
8746 "Size of OutChains mismatch");
8751 SDValue EndOfTrmp = OffsetValues[0].Addr;
8762 if (!Subtarget.is64Bit())
8765 return Op.getOperand(0);
8774 MVT VT =
Op.getSimpleValueType();
8780 MVT ArgVT =
A.getSimpleValueType();
8781 assert(ArgVT ==
B.getSimpleValueType() &&
8791 MVT ContainerVT = VT;
8800 switch (
Op.getOpcode()) {
8801 case ISD::PARTIAL_REDUCE_SMLA:
8802 Opc = RISCVISD::VQDOT_VL;
8804 case ISD::PARTIAL_REDUCE_UMLA:
8805 Opc = RISCVISD::VQDOTU_VL;
8807 case ISD::PARTIAL_REDUCE_SUMLA:
8808 Opc = RISCVISD::VQDOTSU_VL;
8834 N->getOffset(), Flags);
8863template <
class NodeTy>
8865 bool IsLocal,
bool IsExternWeak)
const {
8875 if (IsLocal && !Subtarget.allowTaggedGlobals())
8879 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
8902 if (Subtarget.hasVendorXqcili()) {
8906 return DAG.
getNode(RISCVISD::QC_E_LI,
DL, Ty, Addr);
8913 return DAG.
getNode(RISCVISD::ADD_LO,
DL, Ty, MNHi, AddrLo);
8937 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
8945 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
8953 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
8954 const GlobalValue *GV =
N->getGlobal();
8962 return getAddr(
N, DAG);
8969 return getAddr(
N, DAG);
8976 return getAddr(
N, DAG);
8981 bool UseGOT)
const {
8984 const GlobalValue *GV =
N->getGlobal();
8985 MVT XLenVT = Subtarget.getXLenVT();
9022 DAG.
getNode(RISCVISD::ADD_TPREL,
DL, Ty, MNHi, TPReg, AddrAdd);
9023 return DAG.
getNode(RISCVISD::ADD_LO,
DL, Ty, MNAdd, AddrLo);
9031 const GlobalValue *GV =
N->getGlobal();
9042 Args.emplace_back(Load, CallTy);
9045 TargetLowering::CallLoweringInfo CLI(DAG);
9059 const GlobalValue *GV =
N->getGlobal();
9075 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
9089 Addr = getStaticTLSAddr(
N, DAG,
false);
9092 Addr = getStaticTLSAddr(
N, DAG,
true);
9097 : getDynamicTLSAddr(
N, DAG);
9114 if (
LHS == LHS2 &&
RHS == RHS2) {
9119 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
9127 return std::nullopt;
9139 MVT VT =
N->getSimpleValueType(0);
9166 uint64_t TrueM1 = TrueC->getZExtValue() - 1;
9168 unsigned ShAmount =
Log2_64(TrueM1);
9170 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, CondV,
9186 if (~TrueVal == FalseVal) {
9226 if (Subtarget.hasShortForwardBranchOpt())
9229 unsigned SelOpNo = 0;
9239 unsigned ConstSelOpNo = 1;
9240 unsigned OtherSelOpNo = 2;
9247 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
9252 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
9258 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
9260 std::swap(NewConstOps[0], NewConstOps[1]);
9272 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
9274 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
9277 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
9278 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
9287 MVT VT =
Op.getSimpleValueType();
9288 MVT XLenVT = Subtarget.getXLenVT();
9309 return DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV);
9312 return DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV);
9316 auto getNotOperand = [](
const SDValue &
Op) -> std::optional<const SDValue> {
9317 using namespace llvm::SDPatternMatch;
9322 return std::nullopt;
9328 auto NotOperand = (TrueV.
getOperand(0) == FalseV)
9330 : getNotOperand(TrueV.getOperand(0));
9333 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, *NotOperand, CondV);
9339 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV));
9346 auto NotOperand = (FalseV.
getOperand(0) == TrueV)
9348 : getNotOperand(FalseV.getOperand(0));
9351 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, *NotOperand, CondV);
9357 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV));
9374 int64_t TrueImm =
TrueVal.getSExtValue();
9375 int64_t FalseImm =
FalseVal.getSExtValue();
9394 if ((TrueVal - FalseVal).isPowerOf2() &&
FalseVal.isSignedIntN(12)) {
9399 if ((FalseVal - TrueVal).isPowerOf2() &&
TrueVal.isSignedIntN(12)) {
9406 auto getCost = [&](
const APInt &Delta,
const APInt &Addend) {
9408 Delta, Subtarget.getXLen(), Subtarget,
true);
9410 if (Addend.isSignedIntN(12))
9413 Addend, Subtarget.getXLen(), Subtarget,
true);
9414 return AddendCost + DeltaCost;
9416 bool IsCZERO_NEZ =
getCost(FalseVal - TrueVal, TrueVal) <=
9417 getCost(TrueVal - FalseVal, FalseVal);
9419 IsCZERO_NEZ ? FalseVal - TrueVal : TrueVal - FalseVal,
DL, VT);
9421 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9422 DL, VT, LHSVal, CondV);
9430 SDValue ConstVal = IsCZERO_NEZ ? TrueV : FalseV;
9431 SDValue RegV = IsCZERO_NEZ ? FalseV : TrueV;
9434 if (RawConstVal == -0x800) {
9437 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9438 DL, VT, XorOp, CondV);
9446 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9447 DL, VT, SubOp, CondV);
9454 if (!Subtarget.hasConditionalMoveFusion())
9457 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV),
9458 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV),
9462 if (
Op.hasOneUse()) {
9463 unsigned UseOpc =
Op->user_begin()->getOpcode();
9465 SDNode *BinOp = *
Op->user_begin();
9472 return lowerSELECT(NewSel, DAG);
9526 if (TrueVal - 1 == FalseVal)
9528 if (TrueVal + 1 == FalseVal)
9535 RHS == TrueV &&
LHS == FalseV) {
9566 MVT XLenVT = Subtarget.getXLenVT();
9577 return DAG.
getNode(RISCVISD::BR_CC,
DL,
Op.getValueType(),
Op.getOperand(0),
9578 LHS,
RHS, TargetCC,
Op.getOperand(2));
9581 return DAG.
getNode(RISCVISD::BR_CC,
DL,
Op.getValueType(),
Op.getOperand(0),
9588 RISCVMachineFunctionInfo *FuncInfo = MF.
getInfo<RISCVMachineFunctionInfo>();
9598 MachinePointerInfo(SV));
9603 const RISCVRegisterInfo &RI = *Subtarget.getRegisterInfo();
9608 int XLenInBytes = Subtarget.getXLen() / 8;
9610 EVT VT =
Op.getValueType();
9613 unsigned Depth =
Op.getConstantOperandVal(0);
9615 int Offset = -(XLenInBytes * 2);
9627 const RISCVRegisterInfo &RI = *Subtarget.getRegisterInfo();
9631 MVT XLenVT = Subtarget.getXLenVT();
9632 int XLenInBytes = Subtarget.getXLen() / 8;
9634 EVT VT =
Op.getValueType();
9636 unsigned Depth =
Op.getConstantOperandVal(0);
9638 int Off = -XLenInBytes;
9639 SDValue FrameAddr = lowerFRAMEADDR(
Op, DAG);
9643 MachinePointerInfo());
9658 EVT VT =
Lo.getValueType();
9697 EVT VT =
Lo.getValueType();
9748 MVT VT =
Op.getSimpleValueType();
9753 return DAG.
getNode(RISCVISD::VMSET_VL,
DL, VT, VL);
9757 return DAG.
getNode(RISCVISD::VMCLR_VL,
DL, VT, VL);
9774 MVT VecVT =
Op.getSimpleValueType();
9776 "Unexpected SPLAT_VECTOR_PARTS lowering");
9782 MVT ContainerVT = VecVT;
9802 int64_t ExtTrueVal)
const {
9804 MVT VecVT =
Op.getSimpleValueType();
9807 assert(Src.getValueType().isVector() &&
9808 Src.getValueType().getVectorElementType() == MVT::i1);
9828 MVT XLenVT = Subtarget.getXLenVT();
9834 if (
Xor.getOpcode() == RISCVISD::VMXOR_VL) {
9846 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9847 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
9848 SplatTrueVal = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9849 DAG.
getUNDEF(ContainerVT), SplatTrueVal, VL);
9851 DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, CC, SplatTrueVal,
9852 SplatZero, DAG.
getUNDEF(ContainerVT), VL);
9862 bool IsVPTrunc =
Op.getOpcode() == ISD::VP_TRUNCATE;
9864 EVT MaskVT =
Op.getValueType();
9867 "Unexpected type for vector mask lowering");
9869 MVT VecVT = Src.getSimpleValueType();
9873 VL =
Op.getOperand(2);
9876 MVT ContainerVT = VecVT;
9882 MVT MaskContainerVT =
9889 std::tie(Mask, VL) =
9896 SplatOne = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9897 DAG.
getUNDEF(ContainerVT), SplatOne, VL);
9898 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9899 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
9902 SDValue Trunc = DAG.
getNode(RISCVISD::AND_VL,
DL, ContainerVT, Src, SplatOne,
9903 DAG.
getUNDEF(ContainerVT), Mask, VL);
9904 Trunc = DAG.
getNode(RISCVISD::SETCC_VL,
DL, MaskContainerVT,
9914 unsigned Opc =
Op.getOpcode();
9915 bool IsVPTrunc =
Opc == ISD::VP_TRUNCATE;
9918 MVT VT =
Op.getSimpleValueType();
9920 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
9924 return lowerVectorMaskTruncLike(
Op, DAG);
9932 MVT SrcVT = Src.getSimpleValueType();
9937 "Unexpected vector truncate lowering");
9939 MVT ContainerVT = SrcVT;
9943 VL =
Op.getOperand(2);
9956 std::tie(Mask, VL) =
9962 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL_SSAT;
9964 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL_USAT;
9966 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL;
9972 }
while (SrcEltVT != DstEltVT);
9981RISCVTargetLowering::lowerStrictFPExtendOrRoundLike(
SDValue Op,
9986 MVT VT =
Op.getSimpleValueType();
9987 MVT SrcVT = Src.getSimpleValueType();
9988 MVT ContainerVT = VT;
10007 ? RISCVISD::STRICT_FP_EXTEND_VL
10008 : RISCVISD::STRICT_VFNCVT_ROD_VL;
10011 Chain, Src, Mask, VL);
10012 Chain = Src.getValue(1);
10016 ? RISCVISD::STRICT_FP_EXTEND_VL
10017 : RISCVISD::STRICT_FP_ROUND_VL;
10019 Chain, Src, Mask, VL);
10030RISCVTargetLowering::lowerVectorFPExtendOrRoundLike(
SDValue Op,
10033 Op.getOpcode() == ISD::VP_FP_ROUND ||
Op.getOpcode() == ISD::VP_FP_EXTEND;
10035 Op.getOpcode() == ISD::VP_FP_EXTEND ||
Op.getOpcode() == ISD::FP_EXTEND;
10040 MVT VT =
Op.getSimpleValueType();
10042 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
10045 MVT SrcVT = Src.getSimpleValueType();
10047 bool IsDirectExtend =
10055 bool IsDirectConv = IsDirectExtend || IsDirectTrunc;
10062 MVT ContainerVT = VT;
10065 Mask =
Op.getOperand(1);
10066 VL =
Op.getOperand(2);
10080 std::tie(Mask, VL) =
10083 unsigned ConvOpc = IsExtend ? RISCVISD::FP_EXTEND_VL : RISCVISD::FP_ROUND_VL;
10085 if (IsDirectConv) {
10086 Src = DAG.
getNode(ConvOpc,
DL, ContainerVT, Src, Mask, VL);
10092 unsigned InterConvOpc =
10093 IsExtend ? RISCVISD::FP_EXTEND_VL : RISCVISD::VFNCVT_ROD_VL;
10097 DAG.
getNode(InterConvOpc,
DL, InterVT, Src, Mask, VL);
10099 DAG.
getNode(ConvOpc,
DL, ContainerVT, IntermediateConv, Mask, VL);
10110static std::optional<MVT>
10116 const unsigned MinVLMAX = VectorBitsMin / EltSize;
10118 if (MaxIdx < MinVLMAX)
10120 else if (MaxIdx < MinVLMAX * 2)
10123 else if (MaxIdx < MinVLMAX * 4)
10128 return std::nullopt;
10136 return isUInt<5>(IdxC->getZExtValue());
10148 MVT VecVT =
Op.getSimpleValueType();
10149 MVT XLenVT = Subtarget.getXLenVT();
10164 if ((ValVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
10165 ValVT == MVT::bf16) {
10170 DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Val), Idx);
10174 MVT ContainerVT = VecVT;
10184 std::optional<unsigned> AlignedIdx;
10186 const unsigned OrigIdx = IdxC->getZExtValue();
10189 DL, DAG, Subtarget)) {
10190 ContainerVT = *ShrunkVT;
10198 if (
auto VLEN = Subtarget.getRealVLen(); VLEN && ContainerVT.
bitsGT(M1VT)) {
10201 unsigned RemIdx = OrigIdx % ElemsPerVReg;
10202 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
10205 ContainerVT = M1VT;
10212 bool IsLegalInsert = Subtarget.is64Bit() || Val.
getValueType() != MVT::i64;
10220 IsLegalInsert =
true;
10229 if (IsLegalInsert) {
10231 VecVT.
isFloatingPoint() ? RISCVISD::VFMV_S_F_VL : RISCVISD::VMV_S_X_VL;
10235 Vec = DAG.
getNode(
Opc,
DL, ContainerVT, Vec, Val, VL);
10245 if (Subtarget.hasVendorXRivosVisni() && VecVT.
isInteger() &&
10250 Vec = DAG.
getNode(RISCVISD::RI_VINSERT_VL,
DL, ContainerVT, Vec, Val, Idx,
10266 std::tie(ValLo, ValHi) = DAG.
SplitScalar(Val,
DL, MVT::i32, MVT::i32);
10267 MVT I32ContainerVT =
10277 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10278 Vec, Vec, ValLo, I32Mask, InsertI64VL);
10282 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10283 Tail, ValInVec, ValHi, I32Mask, InsertI64VL);
10285 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
10296 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10298 DAG.
getUNDEF(I32ContainerVT), ValLo,
10299 I32Mask, InsertI64VL);
10300 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10301 DAG.
getUNDEF(I32ContainerVT), ValInVec, ValHi,
10302 I32Mask, InsertI64VL);
10304 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
10317 Idx, Mask, InsertVL, Policy);
10335 EVT EltVT =
Op.getValueType();
10337 MVT XLenVT = Subtarget.getXLenVT();
10342 MVT ContainerVT = VecVT;
10349 DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Vec, Mask, VL);
10356 if (NumElts >= 8) {
10358 unsigned WidenVecLen;
10361 unsigned MaxEEW = Subtarget.getELen();
10366 "the number of elements should be power of 2");
10370 ExtractBitIdx = Idx;
10372 WideEltVT = LargestEltVT;
10375 ExtractElementIdx = DAG.
getNode(
10384 Vec = DAG.
getNode(ISD::BITCAST,
DL, WideVT, Vec);
10386 Vec, ExtractElementIdx);
10401 if ((EltVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
10402 EltVT == MVT::bf16) {
10408 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, EltVT, IntExtract);
10412 MVT ContainerVT = VecVT;
10422 const auto VLen = Subtarget.getRealVLen();
10424 IdxC && VLen && VecVT.
getSizeInBits().getKnownMinValue() > *VLen) {
10426 unsigned OrigIdx = IdxC->getZExtValue();
10429 unsigned RemIdx = OrigIdx % ElemsPerVReg;
10430 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
10431 unsigned ExtractIdx =
10435 ContainerVT = M1VT;
10440 std::optional<uint64_t> MaxIdx;
10444 MaxIdx = IdxC->getZExtValue();
10446 if (
auto SmallerVT =
10448 ContainerVT = *SmallerVT;
10455 if (Subtarget.hasVendorXRivosVisni() && EltVT.
isInteger() &&
10483 DAG.
getUNDEF(ContainerVT), Vec, Idx, Mask, VL);
10502 "Unexpected opcode");
10509 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
10514 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
10515 if (!
II || !
II->hasScalarOperand())
10518 unsigned SplatOp =
II->ScalarOperand + 1 + HasChain;
10519 assert(SplatOp <
Op.getNumOperands());
10531 if (OpVT.
bitsLT(XLenVT)) {
10538 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
10548 assert(
II->ScalarOperand > 0 &&
"Unexpected splat operand!");
10549 MVT VT =
Op.getOperand(SplatOp - 1).getSimpleValueType();
10552 assert(XLenVT == MVT::i32 && OpVT == MVT::i64 &&
10563 case Intrinsic::riscv_vslide1up:
10564 case Intrinsic::riscv_vslide1down:
10565 case Intrinsic::riscv_vslide1up_mask:
10566 case Intrinsic::riscv_vslide1down_mask: {
10568 unsigned NumOps =
Op.getNumOperands();
10569 bool IsMasked =
NumOps == 7;
10575 std::tie(ScalarLo, ScalarHi) =
10584 const auto [MinVLMAX, MaxVLMAX] =
10588 if (AVLInt <= MinVLMAX) {
10590 }
else if (AVLInt >= 2 * MaxVLMAX) {
10624 if (IntNo == Intrinsic::riscv_vslide1up ||
10625 IntNo == Intrinsic::riscv_vslide1up_mask) {
10626 Vec = DAG.
getNode(RISCVISD::VSLIDE1UP_VL,
DL, I32VT, Passthru, Vec,
10627 ScalarHi, I32Mask, I32VL);
10628 Vec = DAG.
getNode(RISCVISD::VSLIDE1UP_VL,
DL, I32VT, Passthru, Vec,
10629 ScalarLo, I32Mask, I32VL);
10631 Vec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32VT, Passthru, Vec,
10632 ScalarLo, I32Mask, I32VL);
10633 Vec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32VT, Passthru, Vec,
10634 ScalarHi, I32Mask, I32VL);
10652 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, Mask, Vec, MaskedOff,
10656 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, Mask, Vec, MaskedOff,
10683 const unsigned ElementWidth = 8;
10688 [[maybe_unused]]
unsigned MinVF =
10691 [[maybe_unused]]
unsigned VF =
N->getConstantOperandVal(2);
10695 bool Fractional = VF < LMul1VF;
10696 unsigned LMulVal = Fractional ? LMul1VF / VF : VF / LMul1VF;
10717 MVT ContainerVT = OpVT;
10725 SDValue Res = DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Op0, Mask, VL);
10733 return DAG.
getSelect(
DL, XLenVT, Setcc, VL, Res);
10744 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
10748 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
10749 if (!
II || !
II->hasScalarOperand())
10752 unsigned SplatOp =
II->ScalarOperand + 1;
10753 assert(SplatOp <
Op.getNumOperands());
10765 if (OpVT.
bitsLT(XLenVT)) {
10768 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
10779 EVT ValType = V.getValueType();
10780 if (ValType.isVector() && ValType.isFloatingPoint()) {
10783 ValType.getVectorElementCount());
10786 if (ValType.isFixedLengthVector()) {
10788 DAG, V.getSimpleValueType(), Subtarget);
10804 unsigned IntNo =
Op.getConstantOperandVal(0);
10806 MVT XLenVT = Subtarget.getXLenVT();
10811 case Intrinsic::riscv_tuple_insert: {
10816 return DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL,
Op.getValueType(), Vec,
10819 case Intrinsic::riscv_tuple_extract: {
10823 return DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL,
Op.getValueType(), Vec,
10826 case Intrinsic::thread_pointer: {
10830 case Intrinsic::riscv_orc_b:
10831 case Intrinsic::riscv_brev8:
10832 case Intrinsic::riscv_sha256sig0:
10833 case Intrinsic::riscv_sha256sig1:
10834 case Intrinsic::riscv_sha256sum0:
10835 case Intrinsic::riscv_sha256sum1:
10836 case Intrinsic::riscv_sm3p0:
10837 case Intrinsic::riscv_sm3p1: {
10840 case Intrinsic::riscv_orc_b:
Opc = RISCVISD::ORC_B;
break;
10841 case Intrinsic::riscv_brev8:
Opc = RISCVISD::BREV8;
break;
10842 case Intrinsic::riscv_sha256sig0:
Opc = RISCVISD::SHA256SIG0;
break;
10843 case Intrinsic::riscv_sha256sig1:
Opc = RISCVISD::SHA256SIG1;
break;
10844 case Intrinsic::riscv_sha256sum0:
Opc = RISCVISD::SHA256SUM0;
break;
10845 case Intrinsic::riscv_sha256sum1:
Opc = RISCVISD::SHA256SUM1;
break;
10846 case Intrinsic::riscv_sm3p0:
Opc = RISCVISD::SM3P0;
break;
10847 case Intrinsic::riscv_sm3p1:
Opc = RISCVISD::SM3P1;
break;
10852 case Intrinsic::riscv_sm4ks:
10853 case Intrinsic::riscv_sm4ed: {
10855 IntNo == Intrinsic::riscv_sm4ks ? RISCVISD::SM4KS : RISCVISD::SM4ED;
10860 case Intrinsic::riscv_zip:
10861 case Intrinsic::riscv_unzip: {
10863 IntNo == Intrinsic::riscv_zip ? RISCVISD::ZIP : RISCVISD::UNZIP;
10866 case Intrinsic::riscv_mopr:
10867 return DAG.
getNode(RISCVISD::MOP_R,
DL, XLenVT,
Op.getOperand(1),
10870 case Intrinsic::riscv_moprr: {
10871 return DAG.
getNode(RISCVISD::MOP_RR,
DL, XLenVT,
Op.getOperand(1),
10872 Op.getOperand(2),
Op.getOperand(3));
10874 case Intrinsic::riscv_clmul:
10875 return DAG.
getNode(RISCVISD::CLMUL,
DL, XLenVT,
Op.getOperand(1),
10877 case Intrinsic::riscv_clmulh:
10878 case Intrinsic::riscv_clmulr: {
10880 IntNo == Intrinsic::riscv_clmulh ? RISCVISD::CLMULH : RISCVISD::CLMULR;
10883 case Intrinsic::experimental_get_vector_length:
10885 case Intrinsic::experimental_cttz_elts:
10887 case Intrinsic::riscv_vmv_x_s: {
10891 case Intrinsic::riscv_vfmv_f_s:
10893 case Intrinsic::riscv_vmv_v_x:
10895 Op.getOperand(3),
Op.getSimpleValueType(),
DL, DAG,
10897 case Intrinsic::riscv_vfmv_v_f:
10898 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL,
Op.getValueType(),
10899 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
10900 case Intrinsic::riscv_vmv_s_x: {
10903 if (
Scalar.getValueType().bitsLE(XLenVT)) {
10905 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL,
Op.getValueType(),
10906 Op.getOperand(1), Scalar,
Op.getOperand(3));
10909 assert(
Scalar.getValueType() == MVT::i64 &&
"Unexpected scalar VT!");
10926 MVT VT =
Op.getSimpleValueType();
10931 if (
Op.getOperand(1).isUndef())
10932 return SplattedVal;
10941 DAG.
getNode(RISCVISD::SETCC_VL,
DL, MaskVT,
10944 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, SelectCond, SplattedVal,
10947 case Intrinsic::riscv_vfmv_s_f:
10948 return DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL,
Op.getSimpleValueType(),
10949 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
10951 case Intrinsic::riscv_vaesdf_vv:
10952 case Intrinsic::riscv_vaesdf_vs:
10953 case Intrinsic::riscv_vaesdm_vv:
10954 case Intrinsic::riscv_vaesdm_vs:
10955 case Intrinsic::riscv_vaesef_vv:
10956 case Intrinsic::riscv_vaesef_vs:
10957 case Intrinsic::riscv_vaesem_vv:
10958 case Intrinsic::riscv_vaesem_vs:
10959 case Intrinsic::riscv_vaeskf1:
10960 case Intrinsic::riscv_vaeskf2:
10961 case Intrinsic::riscv_vaesz_vs:
10962 case Intrinsic::riscv_vsm4k:
10963 case Intrinsic::riscv_vsm4r_vv:
10964 case Intrinsic::riscv_vsm4r_vs: {
10965 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
10966 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
10967 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
10972 case Intrinsic::riscv_vsm3c:
10973 case Intrinsic::riscv_vsm3me: {
10974 if (!
isValidEGW(8,
Op.getSimpleValueType(), Subtarget) ||
10975 !
isValidEGW(8,
Op->getOperand(1).getSimpleValueType(), Subtarget))
10980 case Intrinsic::riscv_vsha2ch:
10981 case Intrinsic::riscv_vsha2cl:
10982 case Intrinsic::riscv_vsha2ms: {
10983 if (
Op->getSimpleValueType(0).getScalarSizeInBits() == 64 &&
10984 !Subtarget.hasStdExtZvknhb())
10986 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
10987 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
10988 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
10992 case Intrinsic::riscv_sf_vc_v_x:
10993 case Intrinsic::riscv_sf_vc_v_i:
10994 case Intrinsic::riscv_sf_vc_v_xv:
10995 case Intrinsic::riscv_sf_vc_v_iv:
10996 case Intrinsic::riscv_sf_vc_v_vv:
10997 case Intrinsic::riscv_sf_vc_v_fv:
10998 case Intrinsic::riscv_sf_vc_v_xvv:
10999 case Intrinsic::riscv_sf_vc_v_ivv:
11000 case Intrinsic::riscv_sf_vc_v_vvv:
11001 case Intrinsic::riscv_sf_vc_v_fvv:
11002 case Intrinsic::riscv_sf_vc_v_xvw:
11003 case Intrinsic::riscv_sf_vc_v_ivw:
11004 case Intrinsic::riscv_sf_vc_v_vvw:
11005 case Intrinsic::riscv_sf_vc_v_fvw: {
11006 MVT VT =
Op.getSimpleValueType();
11043 MVT VT =
Op.getSimpleValueType();
11047 if (VT.isFloatingPoint()) {
11049 VT.getVectorElementCount());
11052 if (VT.isFixedLengthVector())
11062 if (VT.isFixedLengthVector())
11064 if (VT.isFloatingPoint())
11087 case Intrinsic::riscv_seg2_load_mask:
11088 case Intrinsic::riscv_seg3_load_mask:
11089 case Intrinsic::riscv_seg4_load_mask:
11090 case Intrinsic::riscv_seg5_load_mask:
11091 case Intrinsic::riscv_seg6_load_mask:
11092 case Intrinsic::riscv_seg7_load_mask:
11093 case Intrinsic::riscv_seg8_load_mask:
11096 case Intrinsic::riscv_sseg2_load_mask:
11097 case Intrinsic::riscv_sseg3_load_mask:
11098 case Intrinsic::riscv_sseg4_load_mask:
11099 case Intrinsic::riscv_sseg5_load_mask:
11100 case Intrinsic::riscv_sseg6_load_mask:
11101 case Intrinsic::riscv_sseg7_load_mask:
11102 case Intrinsic::riscv_sseg8_load_mask:
11110 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
11111 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
11112 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
11113 Intrinsic::riscv_vlseg8_mask};
11115 Intrinsic::riscv_vlsseg2_mask, Intrinsic::riscv_vlsseg3_mask,
11116 Intrinsic::riscv_vlsseg4_mask, Intrinsic::riscv_vlsseg5_mask,
11117 Intrinsic::riscv_vlsseg6_mask, Intrinsic::riscv_vlsseg7_mask,
11118 Intrinsic::riscv_vlsseg8_mask};
11121 unsigned NF =
Op->getNumValues() - 1;
11122 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
11124 MVT VT =
Op->getSimpleValueType(0);
11132 SDValue VL =
Op.getOperand(
Op.getNumOperands() - 1);
11133 SDValue Mask =
Op.getOperand(
Op.getNumOperands() - 2);
11134 MVT MaskVT = Mask.getSimpleValueType();
11135 MVT MaskContainerVT =
11140 IsStrided ? VlssegInts[NF - 2] : VlsegInts[NF - 2],
DL, XLenVT);
11156 Ops.insert(std::next(
Ops.begin(), 4),
Op.getOperand(3));
11160 Load->getMemoryVT(), Load->getMemOperand());
11162 for (
unsigned int RetIdx = 0; RetIdx < NF; RetIdx++) {
11164 Result.getValue(0),
11168 Results.push_back(Result.getValue(1));
11174 unsigned IntNo =
Op.getConstantOperandVal(1);
11178 case Intrinsic::riscv_seg2_load_mask:
11179 case Intrinsic::riscv_seg3_load_mask:
11180 case Intrinsic::riscv_seg4_load_mask:
11181 case Intrinsic::riscv_seg5_load_mask:
11182 case Intrinsic::riscv_seg6_load_mask:
11183 case Intrinsic::riscv_seg7_load_mask:
11184 case Intrinsic::riscv_seg8_load_mask:
11185 case Intrinsic::riscv_sseg2_load_mask:
11186 case Intrinsic::riscv_sseg3_load_mask:
11187 case Intrinsic::riscv_sseg4_load_mask:
11188 case Intrinsic::riscv_sseg5_load_mask:
11189 case Intrinsic::riscv_sseg6_load_mask:
11190 case Intrinsic::riscv_sseg7_load_mask:
11191 case Intrinsic::riscv_sseg8_load_mask:
11194 case Intrinsic::riscv_sf_vc_v_x_se:
11196 case Intrinsic::riscv_sf_vc_v_i_se:
11198 case Intrinsic::riscv_sf_vc_v_xv_se:
11200 case Intrinsic::riscv_sf_vc_v_iv_se:
11202 case Intrinsic::riscv_sf_vc_v_vv_se:
11204 case Intrinsic::riscv_sf_vc_v_fv_se:
11206 case Intrinsic::riscv_sf_vc_v_xvv_se:
11208 case Intrinsic::riscv_sf_vc_v_ivv_se:
11210 case Intrinsic::riscv_sf_vc_v_vvv_se:
11212 case Intrinsic::riscv_sf_vc_v_fvv_se:
11214 case Intrinsic::riscv_sf_vc_v_xvw_se:
11216 case Intrinsic::riscv_sf_vc_v_ivw_se:
11218 case Intrinsic::riscv_sf_vc_v_vvw_se:
11220 case Intrinsic::riscv_sf_vc_v_fvw_se:
11233 case Intrinsic::riscv_seg2_store_mask:
11234 case Intrinsic::riscv_seg3_store_mask:
11235 case Intrinsic::riscv_seg4_store_mask:
11236 case Intrinsic::riscv_seg5_store_mask:
11237 case Intrinsic::riscv_seg6_store_mask:
11238 case Intrinsic::riscv_seg7_store_mask:
11239 case Intrinsic::riscv_seg8_store_mask:
11242 case Intrinsic::riscv_sseg2_store_mask:
11243 case Intrinsic::riscv_sseg3_store_mask:
11244 case Intrinsic::riscv_sseg4_store_mask:
11245 case Intrinsic::riscv_sseg5_store_mask:
11246 case Intrinsic::riscv_sseg6_store_mask:
11247 case Intrinsic::riscv_sseg7_store_mask:
11248 case Intrinsic::riscv_sseg8_store_mask:
11257 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
11258 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
11259 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
11260 Intrinsic::riscv_vsseg8_mask};
11262 Intrinsic::riscv_vssseg2_mask, Intrinsic::riscv_vssseg3_mask,
11263 Intrinsic::riscv_vssseg4_mask, Intrinsic::riscv_vssseg5_mask,
11264 Intrinsic::riscv_vssseg6_mask, Intrinsic::riscv_vssseg7_mask,
11265 Intrinsic::riscv_vssseg8_mask};
11269 unsigned NF =
Op->getNumOperands() - (IsStrided ? 6 : 5);
11270 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
11272 MVT VT =
Op->getOperand(2).getSimpleValueType();
11278 SDValue VL =
Op.getOperand(
Op.getNumOperands() - 1);
11279 SDValue Mask =
Op.getOperand(
Op.getNumOperands() - 2);
11280 MVT MaskVT = Mask.getSimpleValueType();
11281 MVT MaskContainerVT =
11286 IsStrided ? VsssegInts[NF - 2] : VssegInts[NF - 2],
DL, XLenVT);
11292 for (
unsigned i = 0; i < NF; i++)
11294 RISCVISD::TUPLE_INSERT,
DL, VecTupTy, StoredVal,
11300 FixedIntrinsic->getChain(),
11309 Ops.insert(std::next(
Ops.begin(), 4),
11310 Op.getOperand(
Op.getNumOperands() - 3));
11314 FixedIntrinsic->getMemoryVT(), FixedIntrinsic->getMemOperand());
11319 unsigned IntNo =
Op.getConstantOperandVal(1);
11323 case Intrinsic::riscv_seg2_store_mask:
11324 case Intrinsic::riscv_seg3_store_mask:
11325 case Intrinsic::riscv_seg4_store_mask:
11326 case Intrinsic::riscv_seg5_store_mask:
11327 case Intrinsic::riscv_seg6_store_mask:
11328 case Intrinsic::riscv_seg7_store_mask:
11329 case Intrinsic::riscv_seg8_store_mask:
11330 case Intrinsic::riscv_sseg2_store_mask:
11331 case Intrinsic::riscv_sseg3_store_mask:
11332 case Intrinsic::riscv_sseg4_store_mask:
11333 case Intrinsic::riscv_sseg5_store_mask:
11334 case Intrinsic::riscv_sseg6_store_mask:
11335 case Intrinsic::riscv_sseg7_store_mask:
11336 case Intrinsic::riscv_sseg8_store_mask:
11339 case Intrinsic::riscv_sf_vc_xv_se:
11341 case Intrinsic::riscv_sf_vc_iv_se:
11343 case Intrinsic::riscv_sf_vc_vv_se:
11345 case Intrinsic::riscv_sf_vc_fv_se:
11347 case Intrinsic::riscv_sf_vc_xvv_se:
11349 case Intrinsic::riscv_sf_vc_ivv_se:
11351 case Intrinsic::riscv_sf_vc_vvv_se:
11353 case Intrinsic::riscv_sf_vc_fvv_se:
11355 case Intrinsic::riscv_sf_vc_xvw_se:
11357 case Intrinsic::riscv_sf_vc_ivw_se:
11359 case Intrinsic::riscv_sf_vc_vvw_se:
11361 case Intrinsic::riscv_sf_vc_fvw_se:
11369 switch (ISDOpcode) {
11372 case ISD::VP_REDUCE_ADD:
11373 case ISD::VECREDUCE_ADD:
11374 return RISCVISD::VECREDUCE_ADD_VL;
11375 case ISD::VP_REDUCE_UMAX:
11376 case ISD::VECREDUCE_UMAX:
11377 return RISCVISD::VECREDUCE_UMAX_VL;
11378 case ISD::VP_REDUCE_SMAX:
11379 case ISD::VECREDUCE_SMAX:
11380 return RISCVISD::VECREDUCE_SMAX_VL;
11381 case ISD::VP_REDUCE_UMIN:
11382 case ISD::VECREDUCE_UMIN:
11383 return RISCVISD::VECREDUCE_UMIN_VL;
11384 case ISD::VP_REDUCE_SMIN:
11385 case ISD::VECREDUCE_SMIN:
11386 return RISCVISD::VECREDUCE_SMIN_VL;
11387 case ISD::VP_REDUCE_AND:
11388 case ISD::VECREDUCE_AND:
11389 return RISCVISD::VECREDUCE_AND_VL;
11390 case ISD::VP_REDUCE_OR:
11391 case ISD::VECREDUCE_OR:
11392 return RISCVISD::VECREDUCE_OR_VL;
11393 case ISD::VP_REDUCE_XOR:
11394 case ISD::VECREDUCE_XOR:
11395 return RISCVISD::VECREDUCE_XOR_VL;
11396 case ISD::VP_REDUCE_FADD:
11397 return RISCVISD::VECREDUCE_FADD_VL;
11398 case ISD::VP_REDUCE_SEQ_FADD:
11399 return RISCVISD::VECREDUCE_SEQ_FADD_VL;
11400 case ISD::VP_REDUCE_FMAX:
11401 case ISD::VP_REDUCE_FMAXIMUM:
11402 return RISCVISD::VECREDUCE_FMAX_VL;
11403 case ISD::VP_REDUCE_FMIN:
11404 case ISD::VP_REDUCE_FMINIMUM:
11405 return RISCVISD::VECREDUCE_FMIN_VL;
11414 SDValue Vec =
Op.getOperand(IsVP ? 1 : 0);
11416 assert((
Op.getOpcode() == ISD::VECREDUCE_AND ||
11417 Op.getOpcode() == ISD::VECREDUCE_OR ||
11418 Op.getOpcode() == ISD::VECREDUCE_XOR ||
11419 Op.getOpcode() == ISD::VP_REDUCE_AND ||
11420 Op.getOpcode() == ISD::VP_REDUCE_OR ||
11421 Op.getOpcode() == ISD::VP_REDUCE_XOR) &&
11422 "Unexpected reduction lowering");
11424 MVT XLenVT = Subtarget.getXLenVT();
11426 MVT ContainerVT = VecVT;
11434 Mask =
Op.getOperand(2);
11435 VL =
Op.getOperand(3);
11437 std::tie(Mask, VL) =
11442 switch (
Op.getOpcode()) {
11445 case ISD::VECREDUCE_AND:
11446 case ISD::VP_REDUCE_AND: {
11450 Vec = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Vec, TrueMask, VL);
11453 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11457 case ISD::VECREDUCE_OR:
11458 case ISD::VP_REDUCE_OR:
11460 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11463 case ISD::VECREDUCE_XOR:
11464 case ISD::VP_REDUCE_XOR: {
11467 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11488 return DAG.
getNode(BaseOpc,
DL,
Op.getValueType(), SetCC,
Op.getOperand(0));
11494 return (RegisterAVL && RegisterAVL->getReg() == RISCV::X0) ||
11495 (ImmAVL && ImmAVL->getZExtValue() >= 1);
11511 auto InnerVT = VecVT.
bitsLE(M1VT) ? VecVT : M1VT;
11515 auto InnerVL = NonZeroAVL ? VL : DAG.
getConstant(1,
DL, XLenVT);
11518 if (M1VT != InnerVT)
11523 SDValue Ops[] = {PassThru, Vec, InitialValue, Mask, VL, Policy};
11541 VecEVT =
Lo.getValueType();
11554 MVT ContainerVT = VecVT;
11573 Mask, VL,
DL, DAG, Subtarget);
11579static std::tuple<unsigned, SDValue, SDValue>
11583 auto Flags =
Op->getFlags();
11584 unsigned Opcode =
Op.getOpcode();
11588 case ISD::VECREDUCE_FADD: {
11592 return std::make_tuple(RISCVISD::VECREDUCE_FADD_VL,
Op.getOperand(0), Zero);
11594 case ISD::VECREDUCE_SEQ_FADD:
11595 return std::make_tuple(RISCVISD::VECREDUCE_SEQ_FADD_VL,
Op.getOperand(1),
11597 case ISD::VECREDUCE_FMINIMUM:
11598 case ISD::VECREDUCE_FMAXIMUM:
11599 case ISD::VECREDUCE_FMIN:
11600 case ISD::VECREDUCE_FMAX: {
11603 (Opcode == ISD::VECREDUCE_FMIN || Opcode == ISD::VECREDUCE_FMINIMUM)
11604 ? RISCVISD::VECREDUCE_FMIN_VL
11605 : RISCVISD::VECREDUCE_FMAX_VL;
11606 return std::make_tuple(RVVOpc,
Op.getOperand(0), Front);
11614 MVT VecEltVT =
Op.getSimpleValueType();
11616 unsigned RVVOpcode;
11617 SDValue VectorVal, ScalarVal;
11618 std::tie(RVVOpcode, VectorVal, ScalarVal) =
11622 MVT ContainerVT = VecVT;
11628 MVT ResVT =
Op.getSimpleValueType();
11631 VL,
DL, DAG, Subtarget);
11632 if (
Op.getOpcode() != ISD::VECREDUCE_FMINIMUM &&
11633 Op.getOpcode() != ISD::VECREDUCE_FMAXIMUM)
11636 if (
Op->getFlags().hasNoNaNs())
11642 {VectorVal, VectorVal, DAG.getCondCode(ISD::SETNE),
11643 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
11644 MVT XLenVT = Subtarget.getXLenVT();
11645 SDValue CPop = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, IsNan, Mask, VL);
11649 DL, ResVT, NoNaNs, Res,
11656 unsigned Opc =
Op.getOpcode();
11660 MVT XLenVT = Subtarget.getXLenVT();
11679 Vec, Mask, VL,
DL, DAG, Subtarget);
11680 if ((
Opc != ISD::VP_REDUCE_FMINIMUM &&
Opc != ISD::VP_REDUCE_FMAXIMUM) ||
11681 Op->getFlags().hasNoNaNs())
11688 RISCVISD::SETCC_VL,
DL, PredVT,
11690 SDValue VCPop = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, IsNaN, Mask, VL);
11698 DL, ResVT, NoNaNs, Res,
11710 MVT XLenVT = Subtarget.getXLenVT();
11711 unsigned OrigIdx =
Op.getConstantOperandVal(2);
11712 const RISCVRegisterInfo *
TRI = Subtarget.getRegisterInfo();
11714 if (OrigIdx == 0 && Vec.
isUndef())
11725 assert(OrigIdx % 8 == 0 &&
"Invalid index");
11728 "Unexpected mask vector lowering");
11758 const auto VLen = Subtarget.getRealVLen();
11760 MVT ContainerVT = VecVT;
11782 if (OrigIdx == 0) {
11784 DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, ContainerVT, Vec, SubVec, VL);
11787 SubVec =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, Vec, SubVec,
11788 SlideupAmt, Mask, VL, Policy);
11796 MVT ContainerVecVT = VecVT;
11802 MVT ContainerSubVecVT = SubVecVT;
11808 unsigned SubRegIdx;
11809 ElementCount RemIdx;
11818 ContainerVecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
11819 SubRegIdx = Decompose.first;
11821 (OrigIdx % Vscale));
11825 ContainerVecVT, ContainerSubVecVT, OrigIdx,
TRI);
11826 SubRegIdx = Decompose.first;
11832 Subtarget.expandVScale(SubVecVT.
getSizeInBits()).getKnownMinValue()));
11833 bool ExactlyVecRegSized =
11835 .isKnownMultipleOf(Subtarget.expandVScale(VecRegSize));
11850 if (RemIdx.
isZero() && (ExactlyVecRegSized || Vec.
isUndef())) {
11854 if (SubRegIdx == RISCV::NoSubRegister) {
11876 MVT InterSubVT = ContainerVecVT;
11877 SDValue AlignedExtract = Vec;
11899 if (Subtarget.expandVScale(EndIndex) ==
11906 SubVec = DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, InterSubVT, AlignedExtract,
11914 SubVec =
getVSlideup(DAG, Subtarget,
DL, InterSubVT, AlignedExtract, SubVec,
11915 SlideupAmt, Mask, VL, Policy);
11920 if (ContainerVecVT.
bitsGT(InterSubVT))
11928 return DAG.
getBitcast(
Op.getSimpleValueType(), SubVec);
11934 MVT SubVecVT =
Op.getSimpleValueType();
11938 MVT XLenVT = Subtarget.getXLenVT();
11939 unsigned OrigIdx =
Op.getConstantOperandVal(1);
11940 const RISCVRegisterInfo *
TRI = Subtarget.getRegisterInfo();
11955 assert(OrigIdx % 8 == 0 &&
"Invalid index");
11958 "Unexpected mask vector lowering");
11984 const auto VLen = Subtarget.getRealVLen();
11992 MVT ContainerVT = VecVT;
12000 if (
auto ShrunkVT =
12002 ContainerVT = *ShrunkVT;
12014 DAG.
getUNDEF(ContainerVT), Vec, SlidedownAmt, Mask, VL);
12025 MVT ContainerSubVecVT = SubVecVT;
12029 unsigned SubRegIdx;
12030 ElementCount RemIdx;
12039 VecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
12040 SubRegIdx = Decompose.first;
12042 (OrigIdx % Vscale));
12046 VecVT, ContainerSubVecVT, OrigIdx,
TRI);
12047 SubRegIdx = Decompose.first;
12074 MVT InterSubVT = VecVT;
12079 assert(SubRegIdx != RISCV::NoSubRegister);
12098 Vec, SlidedownAmt, Mask, VL);
12106 return DAG.
getBitcast(
Op.getSimpleValueType(), Slidedown);
12113 MVT VT =
N.getSimpleValueType();
12117 assert(
Op.getSimpleValueType() == VT &&
12118 "Operands and result must be same type");
12122 unsigned NumVals =
N->getNumValues();
12125 NumVals,
N.getValueType().changeVectorElementType(MVT::i8)));
12128 for (
unsigned I = 0;
I < NumVals;
I++) {
12134 if (TruncVals.
size() > 1)
12136 return TruncVals.
front();
12142 MVT VecVT =
Op.getSimpleValueType();
12144 const unsigned Factor =
Op->getNumValues();
12155 for (
unsigned i = 0U; i < Factor; ++i)
12164 for (
unsigned i = 0U; i < Factor; ++i)
12174 for (
unsigned i = 0; i != Factor; ++i) {
12177 Ops[i * 2 + 1] = OpHi;
12188 for (
unsigned i = 0; i != Factor; ++i)
12195 if (Subtarget.hasVendorXRivosVizip() && Factor == 2) {
12196 MVT VT =
Op->getSimpleValueType(0);
12221 lowerVZIP(RISCVISD::RI_VUNZIP2A_VL, V1, V2,
DL, DAG, Subtarget);
12223 lowerVZIP(RISCVISD::RI_VUNZIP2B_VL, V1, V2,
DL, DAG, Subtarget);
12256 EvenSplat = DAG.
getBitcast(MVT::nxv64i1, EvenSplat);
12260 OddSplat = DAG.
getBitcast(MVT::nxv64i1, OddSplat);
12265 EvenMask, DAG.
getUNDEF(ConcatVT));
12277 MVT XLenVT = Subtarget.getXLenVT();
12299 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
12300 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
12301 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
12302 Intrinsic::riscv_vlseg8_mask};
12326 for (
unsigned i = 0U; i < Factor; ++i)
12327 Res[i] = DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL, VecVT, Load,
12336 MVT VecVT =
Op.getSimpleValueType();
12349 for (
unsigned i = 0U; i < Factor; ++i)
12357 for (
unsigned i = 0U; i < Factor; ++i)
12363 MVT XLenVT = Subtarget.getXLenVT();
12370 for (
unsigned i = 0; i != Factor; ++i) {
12373 Ops[i + Factor] = OpHi;
12384 for (
unsigned i = 0; i != Factor; ++i) {
12385 unsigned IdxLo = 2 * i;
12386 unsigned IdxHi = 2 * i + 1;
12388 Res[IdxLo / Factor].getValue(IdxLo % Factor),
12389 Res[IdxHi / Factor].getValue(IdxHi % Factor));
12407 EVT PtrVT =
StackPtr.getValueType();
12413 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
12414 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
12415 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
12416 Intrinsic::riscv_vsseg8_mask,
12424 for (
unsigned i = 0; i < Factor; i++)
12426 DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VecTupTy, StoredVal,
12449 for (
unsigned i = 0; i != Factor; ++i) {
12453 Loads[i] = DAG.
getLoad(VecVT,
DL, Chain, StackPtr, PtrInfo);
12461 if (Subtarget.hasVendorXRivosVizip() && !
Op.getOperand(0).isUndef() &&
12462 !
Op.getOperand(1).isUndef()) {
12482 Op.getOperand(0),
Op.getOperand(1));
12506 DAG.
getNode(RISCVISD::ADD_VL,
DL, IdxVT, Idx, VLMax, Idx, OddMask, VL);
12511 Interleaved = DAG.
getNode(RISCVISD::VRGATHEREI16_VV_VL,
DL, ConcatVT,
12528 MVT VT =
Op.getSimpleValueType();
12530 MVT XLenVT = Subtarget.getXLenVT();
12533 uint64_t StepValImm =
Op.getConstantOperandVal(0);
12534 if (StepValImm != 1) {
12543 VL, VT,
DL, DAG, Subtarget);
12558 MVT VecVT =
Op.getSimpleValueType();
12567 MVT ContainerVT = VecVT;
12574 MVT XLenVT = Subtarget.getXLenVT();
12620 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
12621 unsigned MaxVLMAX =
12626 unsigned GatherOpc = RISCVISD::VRGATHER_VV_VL;
12631 if (MaxVLMAX > 256 && EltSize == 8) {
12645 LoVT.getVectorMinNumElements());
12650 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
12658 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
12683 DAG.
getUNDEF(ContainerVT), Mask, VL);
12694 MVT XLenVT = Subtarget.getXLenVT();
12695 MVT VecVT =
Op.getSimpleValueType();
12700 SDValue DownOffset, UpOffset;
12701 if (ImmValue >= 0) {
12716 DAG, Subtarget,
DL, VecVT, DAG.
getUNDEF(VecVT), V1, DownOffset, TrueMask,
12717 Subtarget.hasVLDependentLatency() ? UpOffset
12719 return getVSlideup(DAG, Subtarget,
DL, VecVT, SlideDown, V2, UpOffset,
12725RISCVTargetLowering::lowerFixedLengthVectorLoadToRVV(
SDValue Op,
12731 Load->getMemoryVT(),
12732 *
Load->getMemOperand()) &&
12733 "Expecting a correctly-aligned load");
12735 MVT VT =
Op.getSimpleValueType();
12736 MVT XLenVT = Subtarget.getXLenVT();
12741 const auto [MinVLMAX, MaxVLMAX] =
12745 MachineMemOperand *MMO =
Load->getMemOperand();
12758 IsMaskOp ? Intrinsic::riscv_vlm : Intrinsic::riscv_vle,
DL, XLenVT);
12762 Ops.push_back(
Load->getBasePtr());
12764 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
12767 Load->getMemoryVT(),
Load->getMemOperand());
12774RISCVTargetLowering::lowerFixedLengthVectorStoreToRVV(
SDValue Op,
12780 Store->getMemoryVT(),
12781 *
Store->getMemOperand()) &&
12782 "Expecting a correctly-aligned store");
12786 MVT XLenVT = Subtarget.getXLenVT();
12802 const auto [MinVLMAX, MaxVLMAX] =
12806 MachineMemOperand *MMO =
Store->getMemOperand();
12816 IsMaskOp ? Intrinsic::riscv_vsm : Intrinsic::riscv_vse,
DL, XLenVT);
12819 {Store->getChain(), IntID, NewValue, Store->getBasePtr(), VL},
12820 Store->getMemoryVT(),
Store->getMemOperand());
12826 MVT VT =
Op.getSimpleValueType();
12829 EVT MemVT = MemSD->getMemoryVT();
12830 MachineMemOperand *MMO = MemSD->getMemOperand();
12831 SDValue Chain = MemSD->getChain();
12835 bool IsExpandingLoad =
false;
12837 Mask = VPLoad->getMask();
12839 VL = VPLoad->getVectorLength();
12842 Mask = MLoad->getMask();
12843 PassThru = MLoad->getPassThru();
12844 IsExpandingLoad = MLoad->isExpandingLoad();
12849 MVT XLenVT = Subtarget.getXLenVT();
12851 MVT ContainerVT = VT;
12865 if (!IsUnmasked && IsExpandingLoad) {
12868 DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Mask,
12872 unsigned IntID = IsUnmasked || IsExpandingLoad ? Intrinsic::riscv_vle
12873 : Intrinsic::riscv_vle_mask;
12875 if (IntID == Intrinsic::riscv_vle)
12878 Ops.push_back(PassThru);
12879 Ops.push_back(BasePtr);
12880 if (IntID == Intrinsic::riscv_vle_mask)
12881 Ops.push_back(Mask);
12883 if (IntID == Intrinsic::riscv_vle_mask)
12886 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
12890 Chain =
Result.getValue(1);
12892 MVT IndexVT = ContainerVT;
12897 bool UseVRGATHEREI16 =
false;
12905 UseVRGATHEREI16 =
true;
12911 DAG.
getUNDEF(IndexVT), Mask, ExpandingVL);
12913 DAG.
getNode(UseVRGATHEREI16 ? RISCVISD::VRGATHEREI16_VV_VL
12914 : RISCVISD::VRGATHER_VV_VL,
12915 DL, ContainerVT, Result, Iota, PassThru, Mask, ExpandingVL);
12926 MVT VT =
Op->getSimpleValueType(0);
12929 EVT MemVT = VPLoadFF->getMemoryVT();
12930 MachineMemOperand *MMO = VPLoadFF->getMemOperand();
12931 SDValue Chain = VPLoadFF->getChain();
12935 SDValue VL = VPLoadFF->getVectorLength();
12937 MVT XLenVT = Subtarget.getXLenVT();
12939 MVT ContainerVT = VT;
12946 unsigned IntID = Intrinsic::riscv_vleff_mask;
12956 SDVTList VTs = DAG.
getVTList({ContainerVT,
Op->getValueType(1), MVT::Other});
12961 Chain =
Result.getValue(2);
12974 EVT MemVT = MemSD->getMemoryVT();
12975 MachineMemOperand *MMO = MemSD->getMemOperand();
12976 SDValue Chain = MemSD->getChain();
12980 bool IsCompressingStore =
false;
12982 Val = VPStore->getValue();
12983 Mask = VPStore->getMask();
12984 VL = VPStore->getVectorLength();
12987 Val = MStore->getValue();
12988 Mask = MStore->getMask();
12989 IsCompressingStore = MStore->isCompressingStore();
12996 MVT XLenVT = Subtarget.getXLenVT();
12998 MVT ContainerVT = VT;
13003 if (!IsUnmasked || IsCompressingStore) {
13012 if (IsCompressingStore) {
13015 DAG.
getUNDEF(ContainerVT), Val, Mask, VL);
13017 DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Mask,
13022 IsUnmasked ? Intrinsic::riscv_vse : Intrinsic::riscv_vse_mask;
13024 Ops.push_back(Val);
13025 Ops.push_back(BasePtr);
13027 Ops.push_back(Mask);
13042 MVT XLenVT = Subtarget.getXLenVT();
13043 MVT ContainerVT = VT;
13056 Passthru, Val, Mask, VL);
13066 unsigned Opc =
Op.getOpcode();
13073 MVT VT =
Op.getSimpleValueType();
13081 SDVTList VTList =
Op->getVTList();
13106 MVT ContainerInVT = InVT;
13124 RISCVISD::STRICT_FSETCC_VL,
DL, DAG.
getVTList(MaskVT, MVT::Other),
13125 {Chain, Op1, Op1, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
13128 RISCVISD::STRICT_FSETCC_VL,
DL, DAG.
getVTList(MaskVT, MVT::Other),
13129 {Chain, Op2, Op2, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
13132 DAG.
getNode(RISCVISD::VMAND_VL,
DL, MaskVT, OrderMask1, OrderMask2, VL);
13135 Res = DAG.
getNode(RISCVISD::STRICT_FSETCCS_VL,
DL,
13137 {Chain, Op1, Op2, CC, Mask, Mask, VL});
13140 : RISCVISD::STRICT_FSETCCS_VL;
13142 {Chain, Op1, Op2, CC, DAG.getUNDEF(MaskVT), Mask, VL});
13155 MVT VT =
Op.getSimpleValueType();
13159 "Unexpected type for ISD::ABS");
13161 MVT ContainerVT = VT;
13168 if (
Op->getOpcode() == ISD::VP_ABS) {
13169 Mask =
Op->getOperand(1);
13173 VL =
Op->getOperand(2);
13178 RISCVISD::VMV_V_X_VL,
DL, ContainerVT, DAG.
getUNDEF(ContainerVT),
13181 DAG.
getUNDEF(ContainerVT), Mask, VL);
13183 DAG.
getUNDEF(ContainerVT), Mask, VL);
13192 const auto &TSInfo =
13196 bool HasPassthruOp = TSInfo.hasPassthruOp(NewOpc);
13197 bool HasMask = TSInfo.hasMaskOp(NewOpc);
13199 MVT VT =
Op.getSimpleValueType();
13204 for (
const SDValue &V :
Op->op_values()) {
13208 if (!
V.getValueType().isVector()) {
13214 assert(useRVVForFixedLengthVectorVT(
V.getSimpleValueType()) &&
13215 "Only fixed length vectors are supported!");
13217 V.getSimpleValueType().getVectorElementType());
13226 Ops.push_back(Mask);
13231 if (
Op->isStrictFPOpcode()) {
13250 const auto &TSInfo =
13254 bool HasPassthruOp = TSInfo.hasPassthruOp(RISCVISDOpc);
13257 MVT VT =
Op.getSimpleValueType();
13260 MVT ContainerVT = VT;
13269 if (HasPassthruOp) {
13272 if (*MaskIdx ==
OpIdx.index())
13276 if (
Op.getOpcode() == ISD::VP_MERGE) {
13278 Ops.push_back(
Ops.back());
13280 assert(
Op.getOpcode() == ISD::VP_SELECT);
13287 if (RISCVISDOpc == RISCVISD::VFCVT_RM_X_F_VL &&
13290 Subtarget.getXLenVT()));
13292 if (!
V.getValueType().isFixedLengthVector()) {
13297 MVT OpVT =
V.getSimpleValueType();
13299 assert(useRVVForFixedLengthVectorVT(OpVT) &&
13300 "Only fixed length vectors are supported!");
13315 MVT VT =
Op.getSimpleValueType();
13321 MVT ContainerVT = VT;
13328 MVT XLenVT = Subtarget.getXLenVT();
13331 DAG.
getUNDEF(ContainerVT), Zero, VL);
13334 Op.getOpcode() == ISD::VP_ZERO_EXTEND ? 1 : -1,
DL, XLenVT);
13336 DAG.
getUNDEF(ContainerVT), SplatValue, VL);
13339 ZeroSplat, DAG.
getUNDEF(ContainerVT), VL);
13348 MVT VT =
Op.getSimpleValueType();
13356 MVT ContainerVT = VT;
13364 SDValue AllOneMask = DAG.
getNode(RISCVISD::VMSET_VL,
DL, ContainerVT, VL);
13366 switch (Condition) {
13371 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, Op2, VL);
13376 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, Op2, VL);
13378 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, AllOneMask, VL);
13386 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, AllOneMask, VL);
13387 Result = DAG.
getNode(RISCVISD::VMAND_VL,
DL, ContainerVT, Temp, Op2, VL);
13395 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op2, AllOneMask, VL);
13396 Result = DAG.
getNode(RISCVISD::VMAND_VL,
DL, ContainerVT, Op1, Temp, VL);
13404 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, AllOneMask, VL);
13405 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, Op2, VL);
13413 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op2, AllOneMask, VL);
13414 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, Op1, VL);
13434 MVT DstVT =
Op.getSimpleValueType();
13435 MVT SrcVT = Src.getSimpleValueType();
13448 if (DstEltSize >= SrcEltSize) {
13452 unsigned RISCVISDExtOpc = RISCVISDOpc == RISCVISD::SINT_TO_FP_VL
13453 ? RISCVISD::VSEXT_VL
13454 : RISCVISD::VZEXT_VL;
13457 if (SrcEltSize == 1) {
13459 MVT XLenVT = Subtarget.getXLenVT();
13464 RISCVISDExtOpc == RISCVISD::VZEXT_VL ? 1 : -1,
DL, XLenVT);
13467 Src = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, IntVT, Src, OneSplat,
13468 ZeroSplat, DAG.
getUNDEF(IntVT), VL);
13469 }
else if (DstEltSize > (2 * SrcEltSize)) {
13473 Src = DAG.
getNode(RISCVISDExtOpc,
DL, IntVT, Src, Mask, VL);
13479 "Wrong input/output vector types");
13482 if (DstEltSize > (2 * SrcEltSize)) {
13487 DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, InterimFVT, Src, Mask, VL);
13498 MVT InterimFVT = DstVT;
13499 if (SrcEltSize > (2 * DstEltSize)) {
13500 assert(SrcEltSize == (4 * DstEltSize) &&
"Unexpected types!");
13507 if (InterimFVT != DstVT) {
13509 Result = DAG.
getNode(RISCVISD::FP_ROUND_VL,
DL, DstVT, Src, Mask, VL);
13513 "Wrong input/output vector types");
13517 if (DstEltSize == 1) {
13520 assert(SrcEltSize >= 16 &&
"Unexpected FP type!");
13527 MVT XLenVT = Subtarget.getXLenVT();
13529 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, InterimIVT,
13530 DAG.
getUNDEF(InterimIVT), SplatZero, VL);
13540 while (InterimIVT != DstVT) {
13552 MVT VT =
Op.getSimpleValueType();
13561 MVT VT =
Op.getSimpleValueType();
13562 MVT XLenVT = Subtarget.getXLenVT();
13575 MVT ContainerVT = VT;
13595 TrueVal = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, PromotedVT, TrueVal, SplatOne,
13596 SplatZero, DAG.
getUNDEF(PromotedVT), VL);
13599 SplatOne, SplatZero, DAG.
getUNDEF(PromotedVT), VLMax);
13603 TrueVal, FalseVal, FalseVal, VL);
13608 RISCVISD::SETCC_VL,
DL, ContainerVT,
13618RISCVTargetLowering::lowerVPSpliceExperimental(
SDValue Op,
13620 using namespace SDPatternMatch;
13631 const MVT XLenVT = Subtarget.getXLenVT();
13632 MVT VT =
Op.getSimpleValueType();
13633 MVT ContainerVT = VT;
13643 if (IsMaskVector) {
13653 Op1 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, Op1, SplatOneOp1,
13654 SplatZeroOp1, DAG.
getUNDEF(ContainerVT), EVL1);
13662 Op2 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, Op2, SplatOneOp2,
13663 SplatZeroOp2, DAG.
getUNDEF(ContainerVT), EVL2);
13666 auto getVectorFirstEle = [](
SDValue Vec) {
13679 if (
auto FirstEle = getVectorFirstEle(
Op->getOperand(0))) {
13682 if ((EltVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
13683 EltVT == MVT::bf16) {
13691 : RISCVISD::VSLIDE1UP_VL,
13692 DL, ContainerVT, DAG.
getUNDEF(ContainerVT), Op2,
13693 FirstEle, Mask, EVL2);
13703 SDValue DownOffset, UpOffset;
13704 if (ImmValue >= 0) {
13718 DAG.
getUNDEF(ContainerVT), Op1, DownOffset, Mask,
13719 Subtarget.hasVLDependentLatency() ? UpOffset : EVL2);
13723 if (IsMaskVector) {
13727 {Result, DAG.getConstant(0, DL, ContainerVT),
13728 DAG.getCondCode(ISD::SETNE), DAG.getUNDEF(getMaskTypeFor(ContainerVT)),
13743 MVT VT =
Op.getSimpleValueType();
13745 MVT ContainerVT = VT;
13756 DAG.
getNode(
C->isZero() ? RISCVISD::VMCLR_VL : RISCVISD::VMSET_VL,
DL,
13779RISCVTargetLowering::lowerVPReverseExperimental(
SDValue Op,
13782 MVT VT =
Op.getSimpleValueType();
13783 MVT XLenVT = Subtarget.getXLenVT();
13789 MVT ContainerVT = VT;
13797 MVT GatherVT = ContainerVT;
13801 if (IsMaskVector) {
13811 Op1 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, IndicesVT, Op1, SplatOne,
13812 SplatZero, DAG.
getUNDEF(IndicesVT), EVL);
13817 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
13818 unsigned MaxVLMAX =
13821 unsigned GatherOpc = RISCVISD::VRGATHER_VV_VL;
13827 if (MaxVLMAX > 256 && EltSize == 8) {
13855 DAG.
getUNDEF(GatherVT), Result, Diff, Mask, EVL);
13857 if (IsMaskVector) {
13860 DAG.
getNode(RISCVISD::SETCC_VL,
DL, ContainerVT,
13873 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
13880 DAG.
getUNDEF(IndicesVT), VecLen, EVL);
13881 SDValue VRSUB = DAG.
getNode(RISCVISD::SUB_VL,
DL, IndicesVT, VecLenSplat, VID,
13882 DAG.
getUNDEF(IndicesVT), Mask, EVL);
13884 DAG.
getUNDEF(GatherVT), Mask, EVL);
13886 if (IsMaskVector) {
13889 RISCVISD::SETCC_VL,
DL, ContainerVT,
13901 MVT VT =
Op.getSimpleValueType();
13903 return lowerVPOp(
Op, DAG);
13910 MVT ContainerVT = VT;
13928 MVT XLenVT = Subtarget.getXLenVT();
13929 MVT VT =
Op.getSimpleValueType();
13930 MVT ContainerVT = VT;
13934 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
13942 : Intrinsic::riscv_vlse_mask,
13945 DAG.
getUNDEF(ContainerVT), VPNode->getBasePtr(),
13946 VPNode->getStride()};
13952 Ops.push_back(Mask);
13954 Ops.push_back(VPNode->getVectorLength());
13958 Ops.push_back(Policy);
13963 VPNode->getMemoryVT(), VPNode->getMemOperand());
13975 MVT XLenVT = Subtarget.getXLenVT();
13978 SDValue StoreVal = VPNode->getValue();
13980 MVT ContainerVT = VT;
13991 : Intrinsic::riscv_vsse_mask,
13994 VPNode->getBasePtr(), VPNode->getStride()};
14000 Ops.push_back(Mask);
14002 Ops.push_back(VPNode->getVectorLength());
14005 Ops, VPNode->getMemoryVT(),
14006 VPNode->getMemOperand());
14018 MVT VT =
Op.getSimpleValueType();
14021 EVT MemVT = MemSD->getMemoryVT();
14022 MachineMemOperand *MMO = MemSD->getMemOperand();
14023 SDValue Chain = MemSD->getChain();
14030 Index = VPGN->getIndex();
14031 Mask = VPGN->getMask();
14033 VL = VPGN->getVectorLength();
14039 Index = MGN->getIndex();
14040 Mask = MGN->getMask();
14041 PassThru = MGN->getPassThru();
14045 MVT IndexVT =
Index.getSimpleValueType();
14046 MVT XLenVT = Subtarget.getXLenVT();
14049 "Unexpected VTs!");
14050 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
14053 "Unexpected extending MGATHER/VP_GATHER");
14059 MVT ContainerVT = VT;
14083 IsUnmasked ? Intrinsic::riscv_vluxei : Intrinsic::riscv_vluxei_mask;
14088 Ops.push_back(PassThru);
14089 Ops.push_back(BasePtr);
14090 Ops.push_back(Index);
14092 Ops.push_back(Mask);
14097 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
14100 Chain =
Result.getValue(1);
14118 EVT MemVT = MemSD->getMemoryVT();
14119 MachineMemOperand *MMO = MemSD->getMemOperand();
14120 SDValue Chain = MemSD->getChain();
14123 [[maybe_unused]]
bool IsTruncatingStore =
false;
14127 Index = VPSN->getIndex();
14128 Mask = VPSN->getMask();
14129 Val = VPSN->getValue();
14130 VL = VPSN->getVectorLength();
14132 IsTruncatingStore =
false;
14136 Index = MSN->getIndex();
14137 Mask = MSN->getMask();
14138 Val = MSN->getValue();
14139 IsTruncatingStore = MSN->isTruncatingStore();
14143 MVT IndexVT =
Index.getSimpleValueType();
14144 MVT XLenVT = Subtarget.getXLenVT();
14147 "Unexpected VTs!");
14148 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
14151 assert(!IsTruncatingStore &&
"Unexpected truncating MSCATTER/VP_SCATTER");
14157 MVT ContainerVT = VT;
14181 IsUnmasked ? Intrinsic::riscv_vsoxei : Intrinsic::riscv_vsoxei_mask;
14183 Ops.push_back(Val);
14184 Ops.push_back(BasePtr);
14185 Ops.push_back(Index);
14187 Ops.push_back(Mask);
14196 const MVT XLenVT = Subtarget.getXLenVT();
14200 SDVTList VTs = DAG.
getVTList(XLenVT, MVT::Other);
14207 static const int Table =
14226 const MVT XLenVT = Subtarget.getXLenVT();
14236 static const unsigned Table =
14251 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14257 const MVT XLenVT = Subtarget.getXLenVT();
14261 SDVTList VTs = DAG.
getVTList(XLenVT, MVT::Other);
14262 return DAG.
getNode(RISCVISD::READ_CSR,
DL, VTs, Chain, SysRegNo);
14267 const MVT XLenVT = Subtarget.getXLenVT();
14274 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14280 const MVT XLenVT = Subtarget.getXLenVT();
14286 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14300 SDValue Result = DAG.
getNode(RISCVISD::READ_CSR,
DL, VTs, Chain, SysRegNo);
14301 Chain = Result.getValue(1);
14307 const MVT XLenVT = Subtarget.getXLenVT();
14317 Chain = DAG.
getNode(RISCVISD::CLEAR_CSR,
DL, MVT::Other, Chain, SysRegNo,
14319 return DAG.
getNode(RISCVISD::SET_CSR,
DL, MVT::Other, Chain, SysRegNo,
14325 const MVT XLenVT = Subtarget.getXLenVT();
14332 return DAG.
getNode(RISCVISD::CLEAR_CSR,
DL, MVT::Other, Chain, SysRegNo,
14340 bool isRISCV64 = Subtarget.is64Bit();
14354 return RISCVISD::SLLW;
14356 return RISCVISD::SRAW;
14358 return RISCVISD::SRLW;
14360 return RISCVISD::DIVW;
14362 return RISCVISD::DIVUW;
14364 return RISCVISD::REMUW;
14366 return RISCVISD::ROLW;
14368 return RISCVISD::RORW;
14404 switch (
N->getOpcode()) {
14406 llvm_unreachable(
"Don't know how to custom type legalize this operation!");
14411 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14412 "Unexpected custom legalisation");
14413 bool IsStrict =
N->isStrictFPOpcode();
14416 SDValue Op0 = IsStrict ?
N->getOperand(1) :
N->getOperand(0);
14425 !Subtarget.hasStdExtZfhOrZhinx()) {
14430 unsigned Opc = IsSigned ? RISCVISD::STRICT_FCVT_W_RV64
14431 : RISCVISD::STRICT_FCVT_WU_RV64;
14434 Opc,
DL, VTs, Chain, Op0,
14443 !Subtarget.hasStdExtZfhOrZhinx()) ||
14445 Op0 = DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, Op0);
14447 unsigned Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
14468 std::tie(Result, Chain) =
14469 makeLibCall(DAG, LC,
N->getValueType(0), Op0, CallOptions,
DL, Chain);
14475 case ISD::LROUND: {
14484 if (Op0.
getValueType() == MVT::f16 && !Subtarget.hasStdExtZfhOrZhinx())
14485 Op0 = DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, Op0);
14488 DAG.
getNode(RISCVISD::FCVT_W_RV64,
DL, MVT::i64, Op0,
14496 RTLIB::Libcall LC =
14497 Op0.
getValueType() == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
14506 case ISD::READCYCLECOUNTER:
14507 case ISD::READSTEADYCOUNTER: {
14508 assert(!Subtarget.is64Bit() &&
"READCYCLECOUNTER/READSTEADYCOUNTER only "
14509 "has custom type legalization on riscv32");
14511 SDValue LoCounter, HiCounter;
14512 MVT XLenVT = Subtarget.getXLenVT();
14513 if (
N->getOpcode() == ISD::READCYCLECOUNTER) {
14522 N->getOperand(0), LoCounter, HiCounter);
14537 if (
N->getValueType(0) == MVT::i64) {
14538 assert(Subtarget.hasStdExtZilsd() && !Subtarget.is64Bit() &&
14539 "Unexpected custom legalisation");
14541 if (!Subtarget.enableUnalignedScalarMem() && Ld->
getAlign() < 8)
14546 RISCVISD::LD_RV32,
DL,
14547 DAG.
getVTList({MVT::i32, MVT::i32, MVT::Other}),
14548 {Ld->getChain(), Ld->getBasePtr()}, MVT::i64, Ld->
getMemOperand());
14552 Results.append({Pair, Result.getValue(2)});
14556 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14557 "Unexpected custom legalisation");
14568 unsigned Size =
N->getSimpleValueType(0).getSizeInBits();
14569 unsigned XLen = Subtarget.getXLen();
14572 assert(
Size == (XLen * 2) &&
"Unexpected custom legalisation");
14580 if (LHSIsU == RHSIsU)
14584 MVT XLenVT = Subtarget.getXLenVT();
14597 if (RHSIsU && LHSIsS && !RHSIsS)
14598 Results.push_back(MakeMULPair(LHS, RHS));
14599 else if (LHSIsU && RHSIsS && !LHSIsS)
14600 Results.push_back(MakeMULPair(RHS, LHS));
14608 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14609 "Unexpected custom legalisation");
14615 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14616 "Unexpected custom legalisation");
14619 if (
N->getOpcode() ==
ISD::SHL && Subtarget.hasStdExtZbs() &&
14644 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14645 "Unexpected custom legalisation");
14646 assert((Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb() ||
14647 Subtarget.hasVendorXTHeadBb()) &&
14648 "Unexpected custom legalization");
14650 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()))
14658 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14659 "Unexpected custom legalisation");
14665 unsigned Opc = IsCTZ ? RISCVISD::CTZW : RISCVISD::CLZW;
14673 MVT VT =
N->getSimpleValueType(0);
14674 assert((VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32) &&
14675 Subtarget.is64Bit() && Subtarget.hasStdExtM() &&
14676 "Unexpected custom legalisation");
14688 if (VT != MVT::i32)
14696 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14697 "Unexpected custom legalisation");
14718 EVT OType =
N->getValueType(1);
14730 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14731 "Unexpected custom legalisation");
14748 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1), Res,
14752 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1),
N->getOperand(0),
14759 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1), Res, LHS,
14769 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14770 !Subtarget.hasStdExtZbb() &&
"Unexpected custom legalisation");
14778 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14779 "Unexpected custom legalisation");
14784 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14785 "Unexpected custom legalisation");
14787 if (Subtarget.hasStdExtZbb()) {
14820 case ISD::BITCAST: {
14821 EVT VT =
N->getValueType(0);
14825 MVT XLenVT = Subtarget.getXLenVT();
14826 if (VT == MVT::i16 &&
14827 ((Op0VT == MVT::f16 && Subtarget.hasStdExtZfhminOrZhinxmin()) ||
14828 (Op0VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
14831 }
else if (VT == MVT::i32 && Op0VT == MVT::f32 && Subtarget.is64Bit() &&
14832 Subtarget.hasStdExtFOrZfinx()) {
14834 DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Op0);
14836 }
else if (VT == MVT::i64 && Op0VT == MVT::f64 && !Subtarget.is64Bit() &&
14837 Subtarget.hasStdExtDOrZdinx()) {
14839 DAG.
getVTList(MVT::i32, MVT::i32), Op0);
14858 assert(
N->getValueType(0) == MVT::i8 && Subtarget.hasStdExtZbkb() &&
14859 "Unexpected custom legalisation");
14860 MVT XLenVT = Subtarget.getXLenVT();
14868 case RISCVISD::BREV8:
14869 case RISCVISD::ORC_B: {
14870 MVT VT =
N->getSimpleValueType(0);
14871 MVT XLenVT = Subtarget.getXLenVT();
14872 assert((VT == MVT::i16 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
14873 "Unexpected custom legalisation");
14874 assert(((
N->getOpcode() == RISCVISD::BREV8 && Subtarget.hasStdExtZbkb()) ||
14875 (
N->getOpcode() == RISCVISD::ORC_B && Subtarget.hasStdExtZbb())) &&
14876 "Unexpected extension");
14902 assert(!Subtarget.is64Bit() &&
N->getValueType(0) == MVT::i64 &&
14904 "Unexpected EXTRACT_VECTOR_ELT legalization");
14907 MVT ContainerVT = VecVT;
14913 MVT XLenVT = Subtarget.getXLenVT();
14922 DAG.
getUNDEF(ContainerVT), Vec, Idx, Mask, VL);
14934 DAG.
getNode(RISCVISD::SRL_VL,
DL, ContainerVT, Vec, ThirtyTwoV,
14935 DAG.
getUNDEF(ContainerVT), Mask, VL);
14943 unsigned IntNo =
N->getConstantOperandVal(0);
14947 "Don't know how to custom type legalize this intrinsic!");
14948 case Intrinsic::experimental_get_vector_length: {
14953 case Intrinsic::experimental_cttz_elts: {
14959 case Intrinsic::riscv_orc_b:
14960 case Intrinsic::riscv_brev8:
14961 case Intrinsic::riscv_sha256sig0:
14962 case Intrinsic::riscv_sha256sig1:
14963 case Intrinsic::riscv_sha256sum0:
14964 case Intrinsic::riscv_sha256sum1:
14965 case Intrinsic::riscv_sm3p0:
14966 case Intrinsic::riscv_sm3p1: {
14967 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
14971 case Intrinsic::riscv_orc_b:
Opc = RISCVISD::ORC_B;
break;
14972 case Intrinsic::riscv_brev8:
Opc = RISCVISD::BREV8;
break;
14973 case Intrinsic::riscv_sha256sig0:
Opc = RISCVISD::SHA256SIG0;
break;
14974 case Intrinsic::riscv_sha256sig1:
Opc = RISCVISD::SHA256SIG1;
break;
14975 case Intrinsic::riscv_sha256sum0:
Opc = RISCVISD::SHA256SUM0;
break;
14976 case Intrinsic::riscv_sha256sum1:
Opc = RISCVISD::SHA256SUM1;
break;
14977 case Intrinsic::riscv_sm3p0:
Opc = RISCVISD::SM3P0;
break;
14978 case Intrinsic::riscv_sm3p1:
Opc = RISCVISD::SM3P1;
break;
14987 case Intrinsic::riscv_sm4ks:
14988 case Intrinsic::riscv_sm4ed: {
14990 IntNo == Intrinsic::riscv_sm4ks ? RISCVISD::SM4KS : RISCVISD::SM4ED;
14996 DAG.
getNode(
Opc,
DL, MVT::i64, NewOp0, NewOp1,
N->getOperand(3));
15000 case Intrinsic::riscv_mopr: {
15001 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15006 RISCVISD::MOP_R,
DL, MVT::i64, NewOp,
15011 case Intrinsic::riscv_moprr: {
15012 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15019 RISCVISD::MOP_RR,
DL, MVT::i64, NewOp0, NewOp1,
15024 case Intrinsic::riscv_clmul: {
15025 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15036 case Intrinsic::riscv_clmulh:
15037 case Intrinsic::riscv_clmulr: {
15038 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15058 unsigned Opc = IntNo == Intrinsic::riscv_clmulh ? RISCVISD::CLMULH
15059 : RISCVISD::CLMULR;
15066 case Intrinsic::riscv_vmv_x_s: {
15067 EVT VT =
N->getValueType(0);
15068 MVT XLenVT = Subtarget.getXLenVT();
15069 if (VT.
bitsLT(XLenVT)) {
15072 Subtarget.getXLenVT(),
N->getOperand(1));
15077 assert(VT == MVT::i64 && !Subtarget.is64Bit() &&
15078 "Unexpected custom legalization");
15094 SDValue LShr32 = DAG.
getNode(RISCVISD::SRL_VL,
DL, VecVT, Vec, ThirtyTwoV,
15105 case ISD::VECREDUCE_ADD:
15106 case ISD::VECREDUCE_AND:
15107 case ISD::VECREDUCE_OR:
15108 case ISD::VECREDUCE_XOR:
15109 case ISD::VECREDUCE_SMAX:
15110 case ISD::VECREDUCE_UMAX:
15111 case ISD::VECREDUCE_SMIN:
15112 case ISD::VECREDUCE_UMIN:
15116 case ISD::VP_REDUCE_ADD:
15117 case ISD::VP_REDUCE_AND:
15118 case ISD::VP_REDUCE_OR:
15119 case ISD::VP_REDUCE_XOR:
15120 case ISD::VP_REDUCE_SMAX:
15121 case ISD::VP_REDUCE_UMAX:
15122 case ISD::VP_REDUCE_SMIN:
15123 case ISD::VP_REDUCE_UMIN:
15144 return ISD::VECREDUCE_ADD;
15146 return ISD::VECREDUCE_UMAX;
15148 return ISD::VECREDUCE_SMAX;
15150 return ISD::VECREDUCE_UMIN;
15152 return ISD::VECREDUCE_SMIN;
15154 return ISD::VECREDUCE_AND;
15156 return ISD::VECREDUCE_OR;
15158 return ISD::VECREDUCE_XOR;
15161 return ISD::VECREDUCE_FADD;
15163 return ISD::VECREDUCE_FMAX;
15165 return ISD::VECREDUCE_FMIN;
15191 const EVT VT =
N->getValueType(0);
15192 const unsigned Opc =
N->getOpcode();
15202 if (!
N->getFlags().hasAllowReassociation())
15213 "Inconsistent mappings");
15217 if (!
LHS.hasOneUse() || !
RHS.hasOneUse())
15245 if (0 == std::min(LHSIdx, RHSIdx) && 1 == std::max(LHSIdx, RHSIdx)) {
15248 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
N->getFlags());
15255 if (
LHS.getOpcode() != ReduceOpc)
15269 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
15270 ReduceVec->
getFlags() &
N->getFlags());
15280 auto BinOpToRVVReduce = [](
unsigned Opc) {
15285 return RISCVISD::VECREDUCE_ADD_VL;
15287 return RISCVISD::VECREDUCE_UMAX_VL;
15289 return RISCVISD::VECREDUCE_SMAX_VL;
15291 return RISCVISD::VECREDUCE_UMIN_VL;
15293 return RISCVISD::VECREDUCE_SMIN_VL;
15295 return RISCVISD::VECREDUCE_AND_VL;
15297 return RISCVISD::VECREDUCE_OR_VL;
15299 return RISCVISD::VECREDUCE_XOR_VL;
15301 return RISCVISD::VECREDUCE_FADD_VL;
15303 return RISCVISD::VECREDUCE_FMAX_VL;
15305 return RISCVISD::VECREDUCE_FMIN_VL;
15309 auto IsReduction = [&BinOpToRVVReduce](
SDValue V,
unsigned Opc) {
15312 V.getOperand(0).getOpcode() == BinOpToRVVReduce(
Opc);
15315 unsigned Opc =
N->getOpcode();
15316 unsigned ReduceIdx;
15317 if (IsReduction(
N->getOperand(0),
Opc))
15319 else if (IsReduction(
N->getOperand(1),
Opc))
15325 if (
Opc ==
ISD::FADD && !
N->getFlags().hasAllowReassociation())
15328 SDValue Extract =
N->getOperand(ReduceIdx);
15341 if (ScalarV.
getOpcode() != RISCVISD::VFMV_S_F_VL &&
15342 ScalarV.
getOpcode() != RISCVISD::VMV_S_X_VL &&
15343 ScalarV.
getOpcode() != RISCVISD::VMV_V_X_VL)
15360 SDValue NewStart =
N->getOperand(1 - ReduceIdx);
15393 EVT VT =
N->getValueType(0);
15409 int64_t C0 = N0C->getSExtValue();
15410 int64_t C1 = N1C->getSExtValue();
15411 if (C0 <= 0 || C1 <= 0)
15414 int64_t Diff = std::abs(C0 - C1);
15420 int64_t Bits = std::min(C0, C1);
15452 if (VShift.
slt(1) || VShift.
sgt(3))
15456 EVT VT =
N->getValueType(0);
15476 EVT VT =
N->getValueType(0);
15504 EVT VT =
N->getValueType(0);
15525 Slct.
getOpcode() != RISCVISD::SELECT_CC) ||
15533 bool SwapSelectOps;
15534 unsigned OpOffset = Slct.
getOpcode() == RISCVISD::SELECT_CC ? 2 : 0;
15539 SwapSelectOps =
false;
15540 NonConstantVal = FalseVal;
15542 SwapSelectOps =
true;
15543 NonConstantVal = TrueVal;
15549 FalseVal = DAG.
getNode(
N->getOpcode(),
SDLoc(
N), VT, OtherOp, NonConstantVal);
15554 if (Slct.
getOpcode() == RISCVISD::SELECT_CC)
15597 EVT VT =
N->getValueType(0);
15612 if (!N0C->hasOneUse())
15614 int64_t C0 = N0C->getSExtValue();
15615 int64_t C1 = N1C->getSExtValue();
15617 if (C0 == -1 || C0 == 0 || C0 == 1 ||
isInt<12>(C1))
15624 }
else if ((C1 / C0 + 1) != 0 &&
isInt<12>(C1 / C0 + 1) &&
15628 }
else if ((C1 / C0 - 1) != 0 &&
isInt<12>(C1 / C0 - 1) &&
15656 EVT VT =
N->getValueType(0);
15687 unsigned OuterExtend =
15691 OuterExtend,
SDLoc(
N), VT,
15699 EVT VT =
N->getValueType(0);
15750 EVT VT =
N->getValueType(0);
15760 APInt ImmValMinus1 = N0C->getAPIntValue() - 1;
15770 if (!isIntEqualitySetCC(CCVal) || !SetCCOpVT.
isInteger())
15793 if (!Subtarget.hasStdExtZbb())
15796 EVT VT =
N->getValueType(0);
15798 if (VT != Subtarget.
getXLenVT() && VT != MVT::i32 && VT != MVT::i16)
15810 unsigned ShiftedAmount = 8 - ShAmtCLeft->getZExtValue();
15812 if (ShiftedAmount >= 8)
15816 SDValue RightShiftOperand = N1;
15818 if (ShiftedAmount != 0) {
15822 if (!ShAmtCRight || ShAmtCRight->getZExtValue() != ShiftedAmount)
15831 if (LeftShiftOperand != RightShiftOperand)
15835 Mask <<= ShiftedAmount;
15841 return DAG.
getNode(RISCVISD::ORC_B,
SDLoc(
N), VT, LeftShiftOperand);
15849 EVT VT =
N->getValueType(0);
15881 bool IsAnd =
N->getOpcode() ==
ISD::AND;
15905 EVT VT =
N->getValueType(0);
15929 EVT VT =
N->getValueType(0);
15956 if (CondLHS != True)
15963 if (!CondRHSC || CondRHSC->
getAPIntValue() != (1ULL << ScalarBits))
15975 if (!FalseRHSC || !FalseRHSC->
isZero())
15995 EVT VT =
N->getValueType(0);
16002 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() && VT == MVT::i1 &&
16045 EVT VT =
N->getValueType(0);
16064 EVT WideVT =
X.getValueType();
16086 if (N0.
getOpcode() != ISD::ATOMIC_LOAD)
16101 if (Mask != ExpectedMask)
16127 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
16165 if (N0.
getOpcode() != RISCVISD::CZERO_EQZ ||
16166 N1.
getOpcode() != RISCVISD::CZERO_NEZ ||
16184 EVT VT =
N->getValueType(0);
16202 if (!Subtarget.hasVendorXqcibm())
16215 if (
N->getValueType(0) != MVT::i32)
16218 unsigned Width, ShAmt;
16235 return DAG.
getNode(RISCVISD::QC_INSB,
DL, MVT::i32,
Ops);
16273 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
16288 if (N0.
getOpcode() == RISCVISD::SLLW &&
16292 return DAG.
getNode(RISCVISD::ROLW,
DL, MVT::i64,
16303 const APInt &Imm = ConstN00->getAPIntValue();
16304 if ((Imm + 1).isSignedIntN(12))
16328 EVT VT =
N->getValueType(0);
16337 bool IsAdd = (
E & 3) == 1;
16338 E -= IsAdd ? 1 : -1;
16342 Result = DAG.
getNode(AddSubOp,
DL, VT, Result, ShiftVal);
16352 uint64_t MulAmtLowBit = MulAmt & (-MulAmt);
16357 ShiftAmt1 = MulAmt + MulAmtLowBit;
16360 ShiftAmt1 = MulAmt - MulAmtLowBit;
16364 EVT VT =
N->getValueType(0);
16378 EVT VT =
N->getValueType(0);
16387 bool ShouldExpandMul =
16389 !Subtarget.hasStdExtZmmul();
16390 if (!ShouldExpandMul)
16409 for (
uint64_t Divisor : {3, 5, 9}) {
16410 if (MulAmt % Divisor != 0)
16412 uint64_t MulAmt2 = MulAmt / Divisor;
16420 X.getConstantOperandVal(1) == UINT64_C(0xffffffff)) {
16423 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, Shl,
16437 if (MulAmt2 == 3 || MulAmt2 == 5 || MulAmt2 == 9) {
16442 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, Mul359,
16453 if (ScaleShift >= 1 && ScaleShift < 4) {
16454 unsigned ShiftAmt =
Log2_64((MulAmt & (MulAmt - 1)));
16458 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT,
X,
16468 for (
uint64_t Divisor : {3, 5, 9}) {
16473 if ((
C >> TZ) == Divisor && (TZ == 1 || TZ == 2 || TZ == 3)) {
16478 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, Mul359,
16484 if (MulAmt > 2 &&
isPowerOf2_64((MulAmt - 1) & (MulAmt - 2))) {
16486 if (ScaleShift >= 1 && ScaleShift < 4) {
16487 unsigned ShiftAmt =
Log2_64(((MulAmt - 1) & (MulAmt - 2)));
16513 for (
uint64_t Divisor : {3, 5, 9}) {
16514 if (MulAmt % Divisor != 0)
16516 uint64_t MulAmt2 = MulAmt / Divisor;
16519 for (
uint64_t Divisor2 : {3, 5, 9}) {
16520 if (MulAmt2 % Divisor2 != 0)
16522 uint64_t MulAmt3 = MulAmt2 / Divisor2;
16529 RISCVISD::SHL_ADD,
DL, VT, Mul359A,
16541 if (!Subtarget.hasStdExtZmmul())
16551 EVT VT =
N->getValueType(0);
16558 if (
N->getOperand(0).getOpcode() !=
ISD::AND ||
16559 N->getOperand(0).getOperand(0).getOpcode() !=
ISD::SRL)
16572 if (!V1.
isMask(HalfSize) || V2 != (1ULL | 1ULL << HalfSize) ||
16573 V3 != (HalfSize - 1))
16583 return DAG.
getNode(ISD::BITCAST,
DL, VT, Sra);
16589 EVT VT =
N->getValueType(0);
16597 unsigned AddSubOpc;
16603 auto IsAddSubWith1 = [&](
SDValue V) ->
bool {
16604 AddSubOpc = V->getOpcode();
16616 if (IsAddSubWith1(N0)) {
16618 return DAG.
getNode(AddSubOpc,
DL, VT, N1, MulVal);
16621 if (IsAddSubWith1(N1)) {
16623 return DAG.
getNode(AddSubOpc,
DL, VT, N0, MulVal);
16638 if (isIndexTypeSigned(IndexType))
16641 if (!
N->hasOneUse())
16644 EVT VT =
N.getValueType();
16683 EVT SrcVT = Src.getValueType();
16687 NewElen = std::max(NewElen, 8U);
16714 EVT OpVT =
X.getValueType();
16722 if (OpSize <= Subtarget.
getXLen() ||
16728 auto IsVectorBitCastCheap = [](
SDValue X) {
16731 X.getOpcode() == ISD::LOAD;
16733 if (!IsVectorBitCastCheap(
X) || !IsVectorBitCastCheap(
Y))
16737 Attribute::NoImplicitFloat))
16744 unsigned VecSize = OpSize / 8;
16756 DAG.
getNode(ISD::VP_REDUCE_OR,
DL, XLenVT,
16769 EVT VT =
N->getValueType(0);
16774 if (!isIntEqualitySetCC(
Cond))
16799 if (OpVT == MVT::i64 && AndRHSInt <= 0xffffffff &&
16803 if (NewC >= -2048 && NewC <= 2048) {
16809 return DAG.
getSetCC(dl, VT, Shift,
16819 if (OpVT != MVT::i64 || !Subtarget.
is64Bit())
16839 const APInt &C1 = N1C->getAPIntValue();
16857 EVT VT =
N->getValueType(0);
16859 unsigned Opc = Src.getOpcode();
16864 if (
Opc == RISCVISD::FMV_X_ANYEXTH && SrcVT.
bitsGE(MVT::i16) &&
16865 Subtarget.hasStdExtZfhmin())
16866 return DAG.
getNode(RISCVISD::FMV_X_SIGNEXTH,
DL, VT, Src.getOperand(0));
16872 return DAG.
getNode(RISCVISD::SLLW,
DL, VT, Src.getOperand(0),
16873 Src.getOperand(1));
16892struct CombineResult;
16894enum ExtKind : uint8_t {
16926struct NodeExtensionHelper {
16935 bool SupportsFPExt;
16937 bool SupportsBF16Ext;
16940 bool EnforceOneUse;
16950 case RISCVISD::VSEXT_VL:
16951 case RISCVISD::VZEXT_VL:
16952 case RISCVISD::FP_EXTEND_VL:
16955 return OrigOperand;
16961 return OrigOperand.
getOpcode() == RISCVISD::VMV_V_X_VL ||
16966 unsigned getExtOpc(ExtKind SupportsExt)
const {
16967 switch (SupportsExt) {
16968 case ExtKind::SExt:
16969 return RISCVISD::VSEXT_VL;
16970 case ExtKind::ZExt:
16971 return RISCVISD::VZEXT_VL;
16972 case ExtKind::FPExt:
16973 case ExtKind::BF16Ext:
16974 return RISCVISD::FP_EXTEND_VL;
16982 SDValue getOrCreateExtendedOp(SDNode *Root, SelectionDAG &DAG,
16983 const RISCVSubtarget &Subtarget,
16984 std::optional<ExtKind> SupportsExt)
const {
16985 if (!SupportsExt.has_value())
16986 return OrigOperand;
16988 MVT NarrowVT = getNarrowType(Root, *SupportsExt);
16992 if (
Source.getValueType() == NarrowVT)
16995 unsigned ExtOpc = getExtOpc(*SupportsExt);
16998 SDLoc
DL(OrigOperand);
16999 auto [
Mask, VL] = getMaskAndVL(Root, DAG, Subtarget);
17003 case RISCVISD::VSEXT_VL:
17004 case RISCVISD::VZEXT_VL:
17005 case RISCVISD::FP_EXTEND_VL:
17006 return DAG.
getNode(ExtOpc,
DL, NarrowVT, Source, Mask, VL);
17009 case RISCVISD::VMV_V_X_VL:
17010 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, NarrowVT,
17012 case RISCVISD::VFMV_V_F_VL:
17014 assert(
Source.getOpcode() == ISD::FP_EXTEND &&
"Unexpected source");
17017 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL, NarrowVT,
17018 DAG.
getUNDEF(NarrowVT), Source, VL);
17031 static MVT getNarrowType(
const SDNode *Root, ExtKind SupportsExt) {
17037 MVT EltVT = SupportsExt == ExtKind::BF16Ext ? MVT::bf16
17038 : SupportsExt == ExtKind::FPExt
17040 : MVT::getIntegerVT(NarrowSize);
17042 assert((
int)NarrowSize >= (SupportsExt == ExtKind::FPExt ? 16 : 8) &&
17043 "Trying to extend something we can't represent");
17050 static unsigned getSExtOpcode(
unsigned Opcode) {
17053 case RISCVISD::ADD_VL:
17054 case RISCVISD::VWADD_W_VL:
17055 case RISCVISD::VWADDU_W_VL:
17057 case RISCVISD::OR_VL:
17058 return RISCVISD::VWADD_VL;
17060 case RISCVISD::SUB_VL:
17061 case RISCVISD::VWSUB_W_VL:
17062 case RISCVISD::VWSUBU_W_VL:
17063 return RISCVISD::VWSUB_VL;
17065 case RISCVISD::MUL_VL:
17066 return RISCVISD::VWMUL_VL;
17074 static unsigned getZExtOpcode(
unsigned Opcode) {
17077 case RISCVISD::ADD_VL:
17078 case RISCVISD::VWADD_W_VL:
17079 case RISCVISD::VWADDU_W_VL:
17081 case RISCVISD::OR_VL:
17082 return RISCVISD::VWADDU_VL;
17084 case RISCVISD::SUB_VL:
17085 case RISCVISD::VWSUB_W_VL:
17086 case RISCVISD::VWSUBU_W_VL:
17087 return RISCVISD::VWSUBU_VL;
17089 case RISCVISD::MUL_VL:
17090 return RISCVISD::VWMULU_VL;
17092 case RISCVISD::SHL_VL:
17093 return RISCVISD::VWSLL_VL;
17101 static unsigned getFPExtOpcode(
unsigned Opcode) {
17103 case RISCVISD::FADD_VL:
17104 case RISCVISD::VFWADD_W_VL:
17105 return RISCVISD::VFWADD_VL;
17106 case RISCVISD::FSUB_VL:
17107 case RISCVISD::VFWSUB_W_VL:
17108 return RISCVISD::VFWSUB_VL;
17109 case RISCVISD::FMUL_VL:
17110 return RISCVISD::VFWMUL_VL;
17111 case RISCVISD::VFMADD_VL:
17112 return RISCVISD::VFWMADD_VL;
17113 case RISCVISD::VFMSUB_VL:
17114 return RISCVISD::VFWMSUB_VL;
17115 case RISCVISD::VFNMADD_VL:
17116 return RISCVISD::VFWNMADD_VL;
17117 case RISCVISD::VFNMSUB_VL:
17118 return RISCVISD::VFWNMSUB_VL;
17126 static unsigned getSUOpcode(
unsigned Opcode) {
17128 "SU is only supported for MUL");
17129 return RISCVISD::VWMULSU_VL;
17134 static unsigned getWOpcode(
unsigned Opcode, ExtKind SupportsExt) {
17137 case RISCVISD::ADD_VL:
17139 case RISCVISD::OR_VL:
17140 return SupportsExt == ExtKind::SExt ? RISCVISD::VWADD_W_VL
17141 : RISCVISD::VWADDU_W_VL;
17143 case RISCVISD::SUB_VL:
17144 return SupportsExt == ExtKind::SExt ? RISCVISD::VWSUB_W_VL
17145 : RISCVISD::VWSUBU_W_VL;
17146 case RISCVISD::FADD_VL:
17147 return RISCVISD::VFWADD_W_VL;
17148 case RISCVISD::FSUB_VL:
17149 return RISCVISD::VFWSUB_W_VL;
17155 using CombineToTry = std::function<std::optional<CombineResult>(
17156 SDNode * ,
const NodeExtensionHelper & ,
17157 const NodeExtensionHelper & , SelectionDAG &,
17158 const RISCVSubtarget &)>;
17161 bool needToPromoteOtherUsers()
const {
return EnforceOneUse; }
17163 void fillUpExtensionSupportForSplat(SDNode *Root, SelectionDAG &DAG,
17164 const RISCVSubtarget &Subtarget) {
17169 "Unexpected Opcode");
17182 unsigned ScalarBits =
Op.getValueSizeInBits();
17184 if (ScalarBits < EltBits) {
17186 assert(
Opc == RISCVISD::VMV_V_X_VL && EltBits == 64 && ScalarBits == 32 &&
17187 !Subtarget.
is64Bit() &&
"Unexpected splat");
17189 SupportsSExt =
true;
17193 SupportsZExt =
true;
17195 EnforceOneUse =
false;
17199 unsigned NarrowSize = EltBits / 2;
17202 if (NarrowSize < 8)
17206 SupportsSExt =
true;
17210 SupportsZExt =
true;
17212 EnforceOneUse =
false;
17215 bool isSupportedFPExtend(MVT NarrowEltVT,
const RISCVSubtarget &Subtarget) {
17216 return (NarrowEltVT == MVT::f32 ||
17220 bool isSupportedBF16Extend(MVT NarrowEltVT,
const RISCVSubtarget &Subtarget) {
17221 return NarrowEltVT == MVT::bf16 && Subtarget.hasStdExtZvfbfwma();
17226 void fillUpExtensionSupport(SDNode *Root, SelectionDAG &DAG,
17227 const RISCVSubtarget &Subtarget) {
17228 SupportsZExt =
false;
17229 SupportsSExt =
false;
17230 SupportsFPExt =
false;
17231 SupportsBF16Ext =
false;
17232 EnforceOneUse =
true;
17254 case RISCVISD::VZEXT_VL:
17255 SupportsZExt =
true;
17257 case RISCVISD::VSEXT_VL:
17258 SupportsSExt =
true;
17260 case RISCVISD::FP_EXTEND_VL: {
17263 if (isSupportedFPExtend(NarrowEltVT, Subtarget))
17264 SupportsFPExt =
true;
17265 if (isSupportedBF16Extend(NarrowEltVT, Subtarget))
17266 SupportsBF16Ext =
true;
17271 case RISCVISD::VMV_V_X_VL:
17272 fillUpExtensionSupportForSplat(Root, DAG, Subtarget);
17274 case RISCVISD::VFMV_V_F_VL: {
17281 if (
Op.getOpcode() != ISD::FP_EXTEND)
17285 unsigned ScalarBits =
Op.getOperand(0).getValueSizeInBits();
17286 if (NarrowSize != ScalarBits)
17289 if (isSupportedFPExtend(
Op.getOperand(0).getSimpleValueType(), Subtarget))
17290 SupportsFPExt =
true;
17291 if (isSupportedBF16Extend(
Op.getOperand(0).getSimpleValueType(),
17293 SupportsBF16Ext =
true;
17302 static bool isSupportedRoot(
const SDNode *Root,
17303 const RISCVSubtarget &Subtarget) {
17315 case RISCVISD::ADD_VL:
17316 case RISCVISD::MUL_VL:
17317 case RISCVISD::VWADD_W_VL:
17318 case RISCVISD::VWADDU_W_VL:
17319 case RISCVISD::SUB_VL:
17320 case RISCVISD::VWSUB_W_VL:
17321 case RISCVISD::VWSUBU_W_VL:
17323 case RISCVISD::FADD_VL:
17324 case RISCVISD::FSUB_VL:
17325 case RISCVISD::FMUL_VL:
17326 case RISCVISD::VFWADD_W_VL:
17327 case RISCVISD::VFWSUB_W_VL:
17329 case RISCVISD::OR_VL:
17333 Subtarget.hasStdExtZvbb();
17334 case RISCVISD::SHL_VL:
17335 return Subtarget.hasStdExtZvbb();
17336 case RISCVISD::VFMADD_VL:
17337 case RISCVISD::VFNMSUB_VL:
17338 case RISCVISD::VFNMADD_VL:
17339 case RISCVISD::VFMSUB_VL:
17347 NodeExtensionHelper(SDNode *Root,
unsigned OperandIdx, SelectionDAG &DAG,
17348 const RISCVSubtarget &Subtarget) {
17349 assert(isSupportedRoot(Root, Subtarget) &&
17350 "Trying to build an helper with an "
17351 "unsupported root");
17352 assert(OperandIdx < 2 &&
"Requesting something else than LHS or RHS");
17362 case RISCVISD::VWADD_W_VL:
17363 case RISCVISD::VWADDU_W_VL:
17364 case RISCVISD::VWSUB_W_VL:
17365 case RISCVISD::VWSUBU_W_VL:
17366 case RISCVISD::VFWADD_W_VL:
17367 case RISCVISD::VFWSUB_W_VL:
17369 if (OperandIdx == 1)
17373 fillUpExtensionSupport(Root, DAG, Subtarget);
17379 static std::pair<SDValue, SDValue>
17380 getMaskAndVL(
const SDNode *Root, SelectionDAG &DAG,
17381 const RISCVSubtarget &Subtarget) {
17382 assert(isSupportedRoot(Root, Subtarget) &&
"Unexpected root");
17401 switch (
N->getOpcode()) {
17405 case RISCVISD::ADD_VL:
17406 case RISCVISD::MUL_VL:
17407 case RISCVISD::OR_VL:
17408 case RISCVISD::FADD_VL:
17409 case RISCVISD::FMUL_VL:
17410 case RISCVISD::VFMADD_VL:
17411 case RISCVISD::VFNMSUB_VL:
17412 case RISCVISD::VFNMADD_VL:
17413 case RISCVISD::VFMSUB_VL:
17415 case RISCVISD::VWADD_W_VL:
17416 case RISCVISD::VWADDU_W_VL:
17418 case RISCVISD::SUB_VL:
17419 case RISCVISD::VWSUB_W_VL:
17420 case RISCVISD::VWSUBU_W_VL:
17421 case RISCVISD::VFWADD_W_VL:
17422 case RISCVISD::FSUB_VL:
17423 case RISCVISD::VFWSUB_W_VL:
17425 case RISCVISD::SHL_VL:
17444struct CombineResult {
17446 unsigned TargetOpcode;
17448 std::optional<ExtKind> LHSExt;
17449 std::optional<ExtKind> RHSExt;
17453 NodeExtensionHelper
LHS;
17455 NodeExtensionHelper
RHS;
17457 CombineResult(
unsigned TargetOpcode, SDNode *Root,
17458 const NodeExtensionHelper &
LHS, std::optional<ExtKind> LHSExt,
17459 const NodeExtensionHelper &
RHS, std::optional<ExtKind> RHSExt)
17460 : TargetOpcode(TargetOpcode), LHSExt(LHSExt), RHSExt(RHSExt), Root(Root),
17466 SDValue materialize(SelectionDAG &DAG,
17467 const RISCVSubtarget &Subtarget)
const {
17469 std::tie(Mask, VL) =
17470 NodeExtensionHelper::getMaskAndVL(Root, DAG, Subtarget);
17484 LHS.getOrCreateExtendedOp(Root, DAG, Subtarget, LHSExt),
17485 RHS.getOrCreateExtendedOp(Root, DAG, Subtarget, RHSExt),
17486 Passthru, Mask, VL);
17500static std::optional<CombineResult>
17501canFoldToVWWithSameExtensionImpl(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17502 const NodeExtensionHelper &
RHS,
17505 if ((AllowExtMask & ExtKind::ZExt) &&
LHS.SupportsZExt &&
RHS.SupportsZExt)
17506 return CombineResult(NodeExtensionHelper::getZExtOpcode(Root->
getOpcode()),
17507 Root,
LHS, {ExtKind::ZExt},
RHS,
17509 if ((AllowExtMask & ExtKind::SExt) &&
LHS.SupportsSExt &&
RHS.SupportsSExt)
17510 return CombineResult(NodeExtensionHelper::getSExtOpcode(Root->
getOpcode()),
17511 Root,
LHS, {ExtKind::SExt},
RHS,
17513 if ((AllowExtMask & ExtKind::FPExt) &&
LHS.SupportsFPExt &&
RHS.SupportsFPExt)
17514 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
17515 Root,
LHS, {ExtKind::FPExt},
RHS,
17517 if ((AllowExtMask & ExtKind::BF16Ext) &&
LHS.SupportsBF16Ext &&
17518 RHS.SupportsBF16Ext)
17519 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
17520 Root,
LHS, {ExtKind::BF16Ext},
RHS,
17521 {ExtKind::BF16Ext});
17522 return std::nullopt;
17531static std::optional<CombineResult>
17532canFoldToVWWithSameExtension(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17535 return canFoldToVWWithSameExtensionImpl(
17536 Root,
LHS,
RHS, ExtKind::ZExt | ExtKind::SExt | ExtKind::FPExt, DAG,
17544static std::optional<CombineResult>
17545canFoldToVWWithSameExtZEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17548 return canFoldToVWWithSameExtensionImpl(Root,
LHS,
RHS, ExtKind::ZExt, DAG,
17556static std::optional<CombineResult>
17557canFoldToVWWithSameExtBF16(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17560 return canFoldToVWWithSameExtensionImpl(Root,
LHS,
RHS, ExtKind::BF16Ext, DAG,
17568static std::optional<CombineResult>
17569canFoldToVW_W(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17572 if (
RHS.SupportsFPExt)
17573 return CombineResult(
17574 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::FPExt),
17575 Root,
LHS, std::nullopt,
RHS, {ExtKind::FPExt});
17582 return CombineResult(
17583 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::ZExt), Root,
17584 LHS, std::nullopt,
RHS, {ExtKind::ZExt});
17586 return CombineResult(
17587 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::SExt), Root,
17588 LHS, std::nullopt,
RHS, {ExtKind::SExt});
17589 return std::nullopt;
17596static std::optional<CombineResult>
17597canFoldToVWWithSEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17600 if (
LHS.SupportsSExt)
17601 return CombineResult(NodeExtensionHelper::getSExtOpcode(Root->
getOpcode()),
17602 Root,
LHS, {ExtKind::SExt},
RHS,
17604 return std::nullopt;
17611static std::optional<CombineResult>
17612canFoldToVWWithZEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17615 if (
LHS.SupportsZExt)
17616 return CombineResult(NodeExtensionHelper::getZExtOpcode(Root->
getOpcode()),
17617 Root,
LHS, {ExtKind::ZExt},
RHS,
17619 return std::nullopt;
17626static std::optional<CombineResult>
17627canFoldToVWWithFPEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17630 if (
LHS.SupportsFPExt)
17631 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
17632 Root,
LHS, {ExtKind::FPExt},
RHS,
17634 return std::nullopt;
17641static std::optional<CombineResult>
17642canFoldToVW_SU(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17646 if (!
LHS.SupportsSExt || !
RHS.SupportsZExt)
17647 return std::nullopt;
17648 return CombineResult(NodeExtensionHelper::getSUOpcode(Root->
getOpcode()),
17649 Root,
LHS, {ExtKind::SExt},
RHS,
17654NodeExtensionHelper::getSupportedFoldings(
const SDNode *Root) {
17660 case RISCVISD::ADD_VL:
17661 case RISCVISD::SUB_VL:
17662 case RISCVISD::OR_VL:
17663 case RISCVISD::FADD_VL:
17664 case RISCVISD::FSUB_VL:
17666 Strategies.
push_back(canFoldToVWWithSameExtension);
17670 case RISCVISD::FMUL_VL:
17671 case RISCVISD::VFMADD_VL:
17672 case RISCVISD::VFMSUB_VL:
17673 case RISCVISD::VFNMADD_VL:
17674 case RISCVISD::VFNMSUB_VL:
17675 Strategies.
push_back(canFoldToVWWithSameExtension);
17676 if (Root->
getOpcode() == RISCVISD::VFMADD_VL)
17677 Strategies.
push_back(canFoldToVWWithSameExtBF16);
17680 case RISCVISD::MUL_VL:
17682 Strategies.
push_back(canFoldToVWWithSameExtension);
17687 case RISCVISD::SHL_VL:
17689 Strategies.
push_back(canFoldToVWWithSameExtZEXT);
17691 case RISCVISD::VWADD_W_VL:
17692 case RISCVISD::VWSUB_W_VL:
17694 Strategies.
push_back(canFoldToVWWithSEXT);
17696 case RISCVISD::VWADDU_W_VL:
17697 case RISCVISD::VWSUBU_W_VL:
17699 Strategies.
push_back(canFoldToVWWithZEXT);
17701 case RISCVISD::VFWADD_W_VL:
17702 case RISCVISD::VFWSUB_W_VL:
17704 Strategies.
push_back(canFoldToVWWithFPEXT);
17715 assert(
N->getOpcode() == RISCVISD::ADD_VL);
17718 SDValue Passthru =
N->getOperand(2);
17752 if (!NodeExtensionHelper::isSupportedRoot(
N, Subtarget))
17758 Inserted.insert(
N);
17761 while (!Worklist.
empty()) {
17764 NodeExtensionHelper
LHS(Root, 0, DAG, Subtarget);
17765 NodeExtensionHelper
RHS(Root, 1, DAG, Subtarget);
17766 auto AppendUsersIfNeeded = [&Worklist, &Subtarget,
17767 &Inserted](
const NodeExtensionHelper &
Op) {
17768 if (
Op.needToPromoteOtherUsers()) {
17771 if (!NodeExtensionHelper::isSupportedRoot(TheUser, Subtarget))
17776 if (Inserted.insert(TheUser).second)
17789 NodeExtensionHelper::getSupportedFoldings(Root);
17791 assert(!FoldingStrategies.
empty() &&
"Nothing to be folded");
17792 bool Matched =
false;
17793 for (
int Attempt = 0;
17794 (Attempt != 1 + NodeExtensionHelper::isCommutative(Root)) && !Matched;
17797 for (NodeExtensionHelper::CombineToTry FoldingStrategy :
17798 FoldingStrategies) {
17799 std::optional<CombineResult> Res =
17800 FoldingStrategy(Root,
LHS,
RHS, DAG, Subtarget);
17807 if (Res->LHSExt.has_value())
17808 if (!AppendUsersIfNeeded(
LHS))
17810 if (Res->RHSExt.has_value())
17811 if (!AppendUsersIfNeeded(
RHS))
17823 SDValue InputRootReplacement;
17830 for (CombineResult Res : CombinesToApply) {
17831 SDValue NewValue = Res.materialize(DAG, Subtarget);
17832 if (!InputRootReplacement) {
17834 "First element is expected to be the current node");
17835 InputRootReplacement = NewValue;
17840 for (std::pair<SDValue, SDValue> OldNewValues : ValuesToReplace) {
17844 return InputRootReplacement;
17851 unsigned Opc =
N->getOpcode();
17852 assert(
Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWADDU_W_VL ||
17853 Opc == RISCVISD::VWSUB_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL);
17856 SDValue MergeOp =
N->getOperand(1);
17857 unsigned MergeOpc = MergeOp.
getOpcode();
17859 if (MergeOpc != RISCVISD::VMERGE_VL && MergeOpc !=
ISD::VSELECT)
17868 SDValue Passthru =
N->getOperand(2);
17874 if (Mask.getOpcode() != RISCVISD::VMSET_VL)
17882 Z = Z.getOperand(1);
17888 {Y, X, Y, MergeOp->getOperand(0), N->getOperand(4)},
17895 [[maybe_unused]]
unsigned Opc =
N->getOpcode();
17896 assert(
Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWADDU_W_VL ||
17897 Opc == RISCVISD::VWSUB_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL);
17924 EVT NewMemVT = (MemVT == MVT::i32) ? MVT::i64 : MVT::i128;
17929 if (LSNode1->
getOpcode() == ISD::LOAD) {
17932 if (MemVT == MVT::i32)
17933 Opcode = (Ext ==
ISD::ZEXTLOAD) ? RISCVISD::TH_LWUD : RISCVISD::TH_LWD;
17935 Opcode = RISCVISD::TH_LDD;
17938 Opcode,
SDLoc(LSNode1), DAG.
getVTList({XLenVT, XLenVT, MVT::Other}),
17939 {LSNode1->getChain(), BasePtr,
17940 DAG.getConstant(Imm, SDLoc(LSNode1), XLenVT)},
17951 unsigned Opcode = (MemVT == MVT::i32) ? RISCVISD::TH_SWD : RISCVISD::TH_SDD;
17955 {LSNode1->getChain(), LSNode1->getOperand(1), LSNode2->getOperand(1),
17956 BasePtr, DAG.getConstant(Imm, SDLoc(LSNode1), XLenVT)},
17973 if (!Subtarget.hasVendorXTHeadMemPair())
17978 unsigned OpNum = LSNode1->
getOpcode() == ISD::LOAD ? 1 : 2;
17985 auto ExtractBaseAndOffset = [](
SDValue Ptr) -> std::pair<SDValue, uint64_t> {
17988 return {
Ptr->getOperand(0), C1->getZExtValue()};
17992 auto [Base1, Offset1] = ExtractBaseAndOffset(LSNode1->
getOperand(OpNum));
18013 auto [Base2, Offset2] = ExtractBaseAndOffset(LSNode2->
getOperand(OpNum));
18016 if (Base1 != Base2)
18020 bool Valid =
false;
18021 if (MemVT == MVT::i32) {
18025 }
else if (MemVT == MVT::i64) {
18061 if (Src->isStrictFPOpcode())
18069 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
18079 EVT VT =
N->getValueType(0);
18082 MVT SrcVT = Src.getSimpleValueType();
18083 MVT SrcContainerVT = SrcVT;
18111 IsSigned ? RISCVISD::VFCVT_RTZ_X_F_VL : RISCVISD::VFCVT_RTZ_XU_F_VL;
18112 FpToInt = DAG.
getNode(
Opc,
DL, ContainerVT, XVal, Mask, VL);
18115 IsSigned ? RISCVISD::VFCVT_RM_X_F_VL : RISCVISD::VFCVT_RM_XU_F_VL;
18116 FpToInt = DAG.
getNode(
Opc,
DL, ContainerVT, XVal, Mask,
18129 if (VT != MVT::i32 && VT != XLenVT)
18134 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
18136 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
18159 EVT DstVT =
N->getValueType(0);
18160 if (DstVT != XLenVT)
18166 if (Src->isStrictFPOpcode())
18174 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
18186 if (SatVT == DstVT)
18187 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
18188 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
18189 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
18194 Src = Src.getOperand(0);
18202 if (
Opc == RISCVISD::FCVT_WU_RV64)
18215 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected extension");
18221 EVT VT =
N->getValueType(0);
18227 return DAG.
getNode(RISCVISD::BREV8,
DL, VT, Src.getOperand(0));
18240 EVT LoadVT = VPLoad->getValueType(0);
18244 N->getOperand(2) != VPLoad->getVectorLength() ||
18245 !
N->getOperand(0).hasOneUse())
18252 SDValue LoadMask = VPLoad->getMask();
18257 if (LoadMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
18259 LoadMask.
getOperand(2) != VPLoad->getVectorLength())
18267 SDValue NumElem = VPLoad->getVectorLength();
18268 uint64_t ElemWidthByte = VPLoad->getValueType(0).getScalarSizeInBits() / 8;
18280 PtrInfo, VPLoad->getMemOperand()->getFlags(),
18284 LoadVT,
DL, VPLoad->getChain(),
Base, Stride, LoadMask,
18285 VPLoad->getVectorLength(), MMO, VPLoad->isExpandingLoad());
18299 if (VPStore->getValue().getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE)
18302 SDValue VPReverse = VPStore->getValue();
18308 VPStore->getVectorLength() != VPReverse.
getOperand(2) ||
18312 SDValue StoreMask = VPStore->getMask();
18317 if (StoreMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
18319 StoreMask.
getOperand(2) != VPStore->getVectorLength())
18327 SDValue NumElem = VPStore->getVectorLength();
18341 PtrInfo, VPStore->getMemOperand()->getFlags(),
18346 VPStore->getOffset(), Stride, StoreMask, VPStore->getVectorLength(),
18347 VPStore->getMemoryVT(), MMO, VPStore->getAddressingMode(),
18348 VPStore->isTruncatingStore(), VPStore->isCompressingStore());
18360 EVT VT =
N->getValueType(0);
18372 if (In.getOpcode() != ISD::VP_SRL || In.getOperand(2) != Mask ||
18373 In.getOperand(3) != VL)
18382 if (
LHS.getOpcode() != ISD::VP_ADD ||
LHS.getOperand(2) != Mask ||
18383 LHS.getOperand(3) != VL)
18390 if (V.getOpcode() != ISD::VP_ADD || V.getOperand(2) != Mask ||
18391 V.getOperand(3) != VL)
18403 if (!FindAdd(LHS0, LHS1) && !FindAdd(LHS1, LHS0))
18417 if (
Op.getOpcode() != ISD::VP_ZERO_EXTEND ||
Op.getOperand(1) != Mask ||
18418 Op.getOperand(2) != VL)
18428 Operands[0].getOperand(0), Mask, VL);
18430 Operands[1].getOperand(0), Mask, VL);
18434 return DAG.
getNode(RISCVISD::AVGCEILU_VL,
DL, VT,
18435 {NewOp0, NewOp1, DAG.
getUNDEF(VT), Mask, VL});
18447 case RISCVISD::VFMADD_VL: Opcode = RISCVISD::VFNMSUB_VL;
break;
18448 case RISCVISD::VFNMSUB_VL: Opcode = RISCVISD::VFMADD_VL;
break;
18449 case RISCVISD::VFNMADD_VL: Opcode = RISCVISD::VFMSUB_VL;
break;
18450 case RISCVISD::VFMSUB_VL: Opcode = RISCVISD::VFNMADD_VL;
break;
18451 case RISCVISD::STRICT_VFMADD_VL: Opcode = RISCVISD::STRICT_VFNMSUB_VL;
break;
18452 case RISCVISD::STRICT_VFNMSUB_VL: Opcode = RISCVISD::STRICT_VFMADD_VL;
break;
18453 case RISCVISD::STRICT_VFNMADD_VL: Opcode = RISCVISD::STRICT_VFMSUB_VL;
break;
18454 case RISCVISD::STRICT_VFMSUB_VL: Opcode = RISCVISD::STRICT_VFNMADD_VL;
break;
18464 case RISCVISD::VFMADD_VL: Opcode = RISCVISD::VFMSUB_VL;
break;
18465 case RISCVISD::VFMSUB_VL: Opcode = RISCVISD::VFMADD_VL;
break;
18466 case RISCVISD::VFNMADD_VL: Opcode = RISCVISD::VFNMSUB_VL;
break;
18467 case RISCVISD::VFNMSUB_VL: Opcode = RISCVISD::VFNMADD_VL;
break;
18468 case RISCVISD::STRICT_VFMADD_VL: Opcode = RISCVISD::STRICT_VFMSUB_VL;
break;
18469 case RISCVISD::STRICT_VFMSUB_VL: Opcode = RISCVISD::STRICT_VFMADD_VL;
break;
18470 case RISCVISD::STRICT_VFNMADD_VL: Opcode = RISCVISD::STRICT_VFNMSUB_VL;
break;
18471 case RISCVISD::STRICT_VFNMSUB_VL: Opcode = RISCVISD::STRICT_VFNMADD_VL;
break;
18484 unsigned Offset = IsStrict ? 1 : 0;
18491 auto invertIfNegative = [&Mask, &VL](
SDValue &V) {
18492 if (V.getOpcode() == RISCVISD::FNEG_VL && V.getOperand(1) == Mask &&
18493 V.getOperand(2) == VL) {
18495 V = V.getOperand(0);
18502 bool NegA = invertIfNegative(
A);
18503 bool NegB = invertIfNegative(
B);
18504 bool NegC = invertIfNegative(
C);
18507 if (!NegA && !NegB && !NegC)
18513 {N->getOperand(0), A, B, C, Mask, VL});
18537 EVT VT =
N->getValueType(0);
18544 uint64_t ShAmt =
N->getConstantOperandVal(1);
18557 if (LShAmt < ExtSize) {
18570 if (ShAmt > 32 || VT != MVT::i64)
18600 U->getConstantOperandVal(1) > 32)
18655 if (!
Cond.hasOneUse())
18674 EVT VT =
Cond.getValueType();
18719 LHS =
LHS.getOperand(0);
18729 LHS.getOperand(0).getValueType() == Subtarget.
getXLenVT()) {
18737 RHS =
LHS.getOperand(1);
18738 LHS =
LHS.getOperand(0);
18747 auto isXorImmediate = [](
const SDValue &
Op) ->
bool {
18749 return isInt<12>(XorCnst->getSExtValue());
18753 auto singleBitOp = [&DAG](
const SDValue &VarOp,
18754 const SDValue &ConstOp) ->
bool {
18757 return (XorCnst->getSExtValue() == 1) &&
18762 auto onlyUsedBySelectOrBR = [](
const SDValue &
Op) ->
bool {
18763 for (
const SDNode *UserNode :
Op->users()) {
18764 const unsigned Opcode = UserNode->getOpcode();
18765 if (Opcode != RISCVISD::SELECT_CC && Opcode != RISCVISD::BR_CC)
18770 auto isFoldableXorEq = [isXorImmediate, singleBitOp, onlyUsedBySelectOrBR](
18773 (!isXorImmediate(
LHS.getOperand(1)) ||
18774 singleBitOp(
LHS.getOperand(0),
LHS.getOperand(1)) ||
18775 onlyUsedBySelectOrBR(
LHS));
18778 if (isFoldableXorEq(
LHS,
RHS)) {
18779 RHS =
LHS.getOperand(1);
18780 LHS =
LHS.getOperand(0);
18806 if (Subtarget.hasVendorXAndesPerf()) {
18816 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
18859 bool Commutative =
true;
18860 unsigned Opc = TrueVal.getOpcode();
18870 Commutative =
false;
18880 if (!TrueVal.hasOneUse())
18884 if (FalseVal == TrueVal.getOperand(0))
18886 else if (Commutative && FalseVal == TrueVal.getOperand(1))
18891 EVT VT =
N->getValueType(0);
18893 SDValue OtherOp = TrueVal.getOperand(1 - OpToFold);
18899 assert(IdentityOperand &&
"No identity operand!");
18904 DAG.
getSelect(
DL, OtherOpVT,
N->getOperand(0), OtherOp, IdentityOperand);
18905 return DAG.
getNode(TrueVal.getOpcode(),
DL, VT, FalseVal, NewSel);
18926 CountZeroes =
N->getOperand(2);
18927 ValOnZero =
N->getOperand(1);
18929 CountZeroes =
N->getOperand(1);
18930 ValOnZero =
N->getOperand(2);
18949 if (
Cond->getOperand(0) != CountZeroesArgument)
18968 CountZeroes, BitWidthMinusOne);
18978 EVT VT =
N->getValueType(0);
18979 EVT CondVT =
Cond.getValueType();
18987 (Subtarget.
hasCZEROLike() || Subtarget.hasVendorXTHeadCondMov())) {
18993 const APInt &MaskVal =
LHS.getConstantOperandAPInt(1);
19004 if (!TrueVal.hasOneUse() || !FalseVal.hasOneUse())
19008 if (TrueVal.getOpcode() ==
ISD::SUB && FalseVal.getOpcode() ==
ISD::ADD) {
19016 SDValue A = FalseVal.getOperand(0);
19017 SDValue B = FalseVal.getOperand(1);
19019 return ((TrueVal.getOperand(0) ==
A && TrueVal.getOperand(1) ==
B) ||
19020 (TrueVal.getOperand(1) ==
A && TrueVal.getOperand(0) ==
B));
19028 EVT VT =
N->getValueType(0);
19030 SDValue TrueVal =
N->getOperand(1);
19031 SDValue FalseVal =
N->getOperand(2);
19061 SDValue TrueVal =
N->getOperand(1);
19062 SDValue FalseVal =
N->getOperand(2);
19077 EVT VT =
N->getValueType(0);
19084 const unsigned Opcode =
N->op_begin()->getNode()->getOpcode();
19099 if (
Op.isUndef()) {
19112 if (
Op.getOpcode() != Opcode || !
Op.hasOneUse())
19121 if (
Op.getOperand(0).getValueType() !=
Op.getOperand(1).getValueType())
19145 EVT AVT =
A.getValueType();
19146 EVT BVT =
B.getValueType();
19176 if (AOpt || BOpt) {
19194 EVT OpVT =
A.getValueType();
19202 IsSigned ? ISD::PARTIAL_REDUCE_SMLA : ISD::PARTIAL_REDUCE_UMLA;
19216 EVT OpVT =
A.getOperand(0).getValueType();
19218 OpVT !=
B.getOperand(0).getValueType() ||
19224 Opc = ISD::PARTIAL_REDUCE_SMLA;
19227 Opc = ISD::PARTIAL_REDUCE_UMLA;
19230 Opc = ISD::PARTIAL_REDUCE_SUMLA;
19233 Opc = ISD::PARTIAL_REDUCE_SUMLA;
19247 if (!Subtarget.hasStdExtZvqdotq())
19251 EVT VT =
N->getValueType(0);
19254 return DAG.
getNode(ISD::VECREDUCE_ADD,
DL, VT, V);
19276 const unsigned InVecOpcode = InVec->
getOpcode();
19293 InVecLHS, InValLHS, EltNo);
19295 InVecRHS, InValRHS, EltNo);
19307 unsigned Elt = IndexC->getZExtValue();
19313 unsigned NewIdx = Elt % ConcatNumElts;
19315 unsigned ConcatOpIdx = Elt / ConcatNumElts;
19320 ConcatOps[ConcatOpIdx] = ConcatOp;
19332 EVT VT =
N->getValueType(0);
19344 !
SDValue(BaseLd, 0).hasOneUse())
19347 EVT BaseLdVT = BaseLd->getValueType(0);
19355 if (!Ld || !Ld->isSimple() || !
Op.hasOneUse() ||
19357 Ld->getValueType(0) != BaseLdVT)
19366 using PtrDiff = std::pair<std::variant<int64_t, SDValue>,
bool>;
19368 LoadSDNode *Ld2) -> std::optional<PtrDiff> {
19373 if (BIO1.equalBaseIndex(BIO2, DAG))
19378 SDValue P2 = Ld2->getBasePtr();
19381 if (P1.getOpcode() ==
ISD::ADD && P1.getOperand(0) == P2)
19382 return {{P1.getOperand(1),
true}};
19384 return std::nullopt;
19388 auto BaseDiff = GetPtrDiff(Lds[0], Lds[1]);
19393 for (
auto *It = Lds.
begin() + 1; It != Lds.
end() - 1; It++)
19394 if (GetPtrDiff(*It, *std::next(It)) != BaseDiff)
19402 unsigned WideScalarBitWidth =
19415 auto [StrideVariant, MustNegateStride] = *BaseDiff;
19417 std::holds_alternative<SDValue>(StrideVariant)
19418 ? std::get<SDValue>(StrideVariant)
19421 if (MustNegateStride)
19430 ConstStride && ConstStride->getSExtValue() >= 0)
19434 ConstStride->getSExtValue() * (
N->getNumOperands() - 1);
19440 BaseLd->getPointerInfo(), BaseLd->getMemOperand()->getFlags(), MemSize,
19444 WideVecVT,
DL, BaseLd->getChain(), BaseLd->getBasePtr(), Stride,
19458 EVT VT =
N->getValueType(0);
19475 for (
int MaskIndex : Mask) {
19476 bool SelectMaskVal = (MaskIndex < (int)NumElts);
19479 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
19516 if (
N->getValueType(0).isFixedLengthVector())
19519 SDValue Addend =
N->getOperand(0);
19522 if (
N->getOpcode() == RISCVISD::ADD_VL) {
19523 SDValue AddPassthruOp =
N->getOperand(2);
19524 if (!AddPassthruOp.
isUndef())
19528 auto IsVWMulOpc = [](
unsigned Opc) {
19530 case RISCVISD::VWMUL_VL:
19531 case RISCVISD::VWMULU_VL:
19532 case RISCVISD::VWMULSU_VL:
19547 if (!MulPassthruOp.
isUndef())
19557 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
19558 }(
N, DAG, Subtarget);
19563 if (AddMask != MulMask || AddVL != MulVL)
19566 const auto &TSInfo =
19568 unsigned Opc = TSInfo.getMAccOpcode(MulOp.
getOpcode());
19571 EVT VT =
N->getValueType(0);
19582 if (!
N->getValueType(0).isVector())
19585 SDValue Addend =
N->getOperand(0);
19588 if (
N->getOpcode() == RISCVISD::ADD_VL) {
19589 SDValue AddPassthruOp =
N->getOperand(2);
19590 if (!AddPassthruOp.
isUndef())
19594 auto IsVqdotqOpc = [](
unsigned Opc) {
19596 case RISCVISD::VQDOT_VL:
19597 case RISCVISD::VQDOTU_VL:
19598 case RISCVISD::VQDOTSU_VL:
19618 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
19619 }(
N, DAG, Subtarget);
19622 if (AddVL != MulVL)
19625 if (AddMask.getOpcode() != RISCVISD::VMSET_VL ||
19626 AddMask.getOperand(0) != MulVL)
19631 EVT VT =
N->getValueType(0);
19632 Addend = DAG.
getNode(RISCVISD::ADD_VL,
DL, VT, Addend, AccumOp,
19633 DAG.
getUNDEF(VT), AddMask, AddVL);
19651 const EVT IndexVT = Index.getValueType();
19655 if (!isIndexTypeSigned(IndexType))
19685 assert(ShuffleMask.empty());
19687 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
19690 if (Index->getOperand(i)->isUndef())
19692 uint64_t C = Index->getConstantOperandVal(i);
19693 if (
C % ElementSize != 0)
19695 C =
C / ElementSize;
19698 ShuffleMask.push_back(
C);
19699 ActiveLanes.
set(
C);
19701 return ActiveLanes.
all();
19719 if (NumElems % 2 != 0)
19723 const unsigned WiderElementSize = ElementSize * 2;
19724 if (WiderElementSize > ST.getELen()/8)
19727 if (!ST.enableUnalignedVectorMem() && BaseAlign < WiderElementSize)
19730 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
19733 if (Index->getOperand(i)->isUndef())
19737 uint64_t C = Index->getConstantOperandVal(i);
19739 if (
C % WiderElementSize != 0)
19744 if (
C !=
Last + ElementSize)
19763 if (!IsVLMAX || Mask.getOpcode() != RISCVISD::VMSET_VL ||
19764 Mask.getOperand(0) != VL)
19767 auto IsTruncNode = [&](
SDValue V) {
19768 return V.getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL &&
19769 V.getOperand(1) == Mask && V.getOperand(2) == VL;
19776 while (IsTruncNode(
Op)) {
19777 if (!
Op.hasOneUse())
19779 Op =
Op.getOperand(0);
19812 assert(
N->getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL);
19814 MVT VT =
N->getSimpleValueType(0);
19819 auto MatchMinMax = [&VL, &Mask](
SDValue V,
unsigned Opc,
unsigned OpcVL,
19821 if (V.getOpcode() !=
Opc &&
19822 !(V.getOpcode() == OpcVL && V.getOperand(2).isUndef() &&
19823 V.getOperand(3) == Mask && V.getOperand(4) == VL))
19831 Op.getOperand(1).getValueType().isFixedLengthVector() &&
19833 Op.getOperand(1).getOperand(0).getValueType() ==
Op.getValueType() &&
19835 Op =
Op.getOperand(1).getOperand(0);
19838 return V.getOperand(0);
19840 if (
Op.getOpcode() == RISCVISD::VMV_V_X_VL &&
Op.getOperand(0).isUndef() &&
19841 Op.getOperand(2) == VL) {
19844 Op1->getAPIntValue().sextOrTrunc(
Op.getScalarValueSizeInBits());
19854 auto DetectUSatPattern = [&](
SDValue V) {
19866 MatchMinMax(SMinOp,
ISD::SMAX, RISCVISD::SMAX_VL, LoC))
19875 MatchMinMax(SMaxOp,
ISD::SMIN, RISCVISD::SMIN_VL, HiC))
19878 return DAG.
getNode(RISCVISD::SMAX_VL,
DL, V.getValueType(), SMinOp,
19879 V.getOperand(1), DAG.
getUNDEF(V.getValueType()),
19885 auto DetectSSatPattern = [&](
SDValue V) {
19887 unsigned NumSrcBits = V.getScalarValueSizeInBits();
19894 MatchMinMax(SMinOp,
ISD::SMAX, RISCVISD::SMAX_VL, LoC))
19895 if (HiC == SignedMax && LoC == SignedMin)
19900 MatchMinMax(SMaxOp,
ISD::SMIN, RISCVISD::SMIN_VL, HiC))
19901 if (HiC == SignedMax && LoC == SignedMin)
19910 while (Src.getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL &&
19911 Src.getOperand(1) == Mask && Src.getOperand(2) == VL &&
19913 Src = Src.getOperand(0);
19917 if ((Val = DetectUSatPattern(Src)))
19918 ClipOpc = RISCVISD::TRUNCATE_VECTOR_VL_USAT;
19919 else if ((Val = DetectSSatPattern(Src)))
19920 ClipOpc = RISCVISD::TRUNCATE_VECTOR_VL_SSAT;
19929 Val = DAG.
getNode(ClipOpc,
DL, ValVT, Val, Mask, VL);
19930 }
while (ValVT != VT);
19948 unsigned Opc =
N->getOpcode();
19950 "Unexpected opcode");
19951 EVT VT =
N->getValueType(0);
19960 Src = Src.getOperand(0);
19962 if (Src.getOpcode() != ISD::BITCAST)
19964 Src = Src.getOperand(0);
19965 }
else if (
Opc == ISD::VECREDUCE_ADD) {
19968 Src = Src.getOperand(0);
19971 EVT SrcEVT = Src.getValueType();
19986 if (
Opc == ISD::VECREDUCE_ADD) {
19993 VectorBitsMax, EltSize, MinSize);
19998 MVT ContainerVT = SrcMVT;
20026 if (!
LHS.hasOneUse())
20029 switch (
LHS.getOpcode()) {
20031 case RISCVISD::VSEXT_VL:
20032 Opcode = RISCVISD::VWMULSU_VL;
20035 case RISCVISD::VZEXT_VL:
20036 Opcode = RISCVISD::VWMULU_VL;
20047 else if (
RHS.getOpcode() == RISCVISD::VMV_V_X_VL &&
20049 ShAmtInt =
RHS.getConstantOperandVal(1);
20062 if (ShAmtInt >= NarrowBits)
20064 MVT VT =
N->getSimpleValueType(0);
20071 switch (
N->getOpcode()) {
20076 case RISCVISD::SHL_VL:
20077 Passthru =
N->getOperand(2);
20078 Mask =
N->getOperand(3);
20079 VL =
N->getOperand(4);
20084 return DAG.
getNode(Opcode,
DL, VT, NarrowOp,
20086 Passthru, Mask, VL);
20092 const MVT XLenVT = Subtarget.getXLenVT();
20098 auto SimplifyDemandedLowBitsHelper = [&](
unsigned OpNo,
unsigned LowBits) {
20109 switch (
N->getOpcode()) {
20112 case RISCVISD::SplitF64: {
20116 if (Op0->
getOpcode() == RISCVISD::BuildPairF64)
20129 APInt V =
C->getValueAPF().bitcastToAPInt();
20158 case RISCVISD::SLLW:
20159 case RISCVISD::SRAW:
20160 case RISCVISD::SRLW:
20161 case RISCVISD::RORW:
20162 case RISCVISD::ROLW: {
20164 if (SimplifyDemandedLowBitsHelper(0, 32) ||
20165 SimplifyDemandedLowBitsHelper(1, 5))
20170 case RISCVISD::CLZW:
20171 case RISCVISD::CTZW: {
20173 if (SimplifyDemandedLowBitsHelper(0, 32))
20177 case RISCVISD::FMV_W_X_RV64: {
20182 if (Op0.
getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64)
20186 case RISCVISD::FMV_X_ANYEXTH:
20187 case RISCVISD::FMV_X_ANYEXTW_RV64: {
20190 MVT VT =
N->getSimpleValueType(0);
20201 if ((
N->getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64 &&
20202 Op0->
getOpcode() == RISCVISD::FMV_W_X_RV64) ||
20203 (
N->getOpcode() == RISCVISD::FMV_X_ANYEXTH &&
20204 Op0->
getOpcode() == RISCVISD::FMV_H_X)) {
20206 "Unexpected value type!");
20216 LN0->getBasePtr(), IVT, LN0->getMemOperand());
20229 unsigned FPBits =
N->getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64 ? 32 : 16;
20240 EVT VT =
N->getValueType(0);
20289 EVT VT =
N->getValueType(0);
20306 if (!
C || !
C->getValueAPF().isExactlyValue(+1.0))
20321 case ISD::FMINNUM: {
20336 if (
N->getValueType(0) == MVT::i64 && Subtarget.is64Bit()) {
20341 Src.getOperand(0));
20346 Src.getOperand(0), Src.getOperand(1));
20354 case RISCVISD::TRUNCATE_VECTOR_VL:
20358 case ISD::VP_TRUNCATE:
20366 case RISCVISD::CZERO_EQZ:
20367 case RISCVISD::CZERO_NEZ: {
20371 unsigned Opc =
N->getOpcode();
20374 if (
Opc == RISCVISD::CZERO_EQZ && Val ==
Cond)
20378 Opc == RISCVISD::CZERO_EQZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ;
20386 return DAG.
getNode(InvOpc,
SDLoc(
N),
N->getValueType(0), Val, NewCond);
20396 N->getValueType(0), Val,
Cond.getOperand(0));
20400 case RISCVISD::SELECT_CC: {
20407 SDValue FalseV =
N->getOperand(4);
20409 EVT VT =
N->getValueType(0);
20412 if (TrueV == FalseV)
20443 return DAG.
getNode(RISCVISD::SELECT_CC,
DL,
N->getValueType(0),
20444 {LHS, RHS, CC, TrueV, FalseV});
20446 if (!Subtarget.hasConditionalMoveFusion()) {
20503 case RISCVISD::BR_CC: {
20510 return DAG.
getNode(RISCVISD::BR_CC,
DL,
N->getValueType(0),
20511 N->getOperand(0), LHS, RHS, CC,
N->getOperand(4));
20524 EVT VT =
N->getValueType(0);
20536 if (In2.
getOpcode() != ISD::FP_EXTEND &&
20545 DAG.
getNode(ISD::FNEG,
DL, VT, NewFPExtRound));
20547 case ISD::MGATHER: {
20549 const EVT VT =
N->getValueType(0);
20550 SDValue Index = MGN->getIndex();
20551 SDValue ScaleOp = MGN->getScale();
20553 assert(!MGN->isIndexScaled() &&
20554 "Scaled gather/scatter should not be formed");
20559 N->getVTList(), MGN->getMemoryVT(),
DL,
20560 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
20561 MGN->getBasePtr(), Index, ScaleOp},
20562 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
20566 N->getVTList(), MGN->getMemoryVT(),
DL,
20567 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
20568 MGN->getBasePtr(), Index, ScaleOp},
20569 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
20575 if (std::optional<VIDSequence> SimpleVID =
20577 SimpleVID && SimpleVID->StepDenominator == 1) {
20578 const int64_t StepNumerator = SimpleVID->StepNumerator;
20579 const int64_t Addend = SimpleVID->Addend;
20586 assert(MGN->getBasePtr()->getValueType(0) == PtrVT);
20594 VT,
DL, MGN->getChain(), BasePtr,
20596 EVL, MGN->getMemOperand());
20598 MGN->getPassThru());
20608 MGN->getBasePtr(), DAG.
getUNDEF(XLenVT),
20610 MGN->getMemoryVT(), MGN->getMemOperand(),
20619 MGN->getMemOperand()->getBaseAlign(), Subtarget)) {
20621 for (
unsigned i = 0; i < Index->getNumOperands(); i += 2)
20622 NewIndices.
push_back(Index.getOperand(i));
20623 EVT IndexVT = Index.getValueType()
20630 assert(EltCnt.isKnownEven() &&
"Splitting vector, but not in half!");
20632 EltCnt.divideCoefficientBy(2));
20635 EltCnt.divideCoefficientBy(2));
20640 {MGN->getChain(), Passthru, Mask, MGN->getBasePtr(),
20648 case ISD::MSCATTER:{
20650 SDValue Index = MSN->getIndex();
20651 SDValue ScaleOp = MSN->getScale();
20653 assert(!MSN->isIndexScaled() &&
20654 "Scaled gather/scatter should not be formed");
20659 N->getVTList(), MSN->getMemoryVT(),
DL,
20660 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
20662 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
20666 N->getVTList(), MSN->getMemoryVT(),
DL,
20667 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
20669 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
20671 EVT VT = MSN->getValue()->getValueType(0);
20673 if (!MSN->isTruncatingStore() &&
20677 return DAG.
getMaskedStore(MSN->getChain(),
DL, Shuffle, MSN->getBasePtr(),
20678 DAG.
getUNDEF(XLenVT), MSN->getMask(),
20679 MSN->getMemoryVT(), MSN->getMemOperand(),
20684 case ISD::VP_GATHER: {
20686 SDValue Index = VPGN->getIndex();
20687 SDValue ScaleOp = VPGN->getScale();
20689 assert(!VPGN->isIndexScaled() &&
20690 "Scaled gather/scatter should not be formed");
20695 {VPGN->getChain(), VPGN->getBasePtr(), Index,
20696 ScaleOp, VPGN->getMask(),
20697 VPGN->getVectorLength()},
20698 VPGN->getMemOperand(), IndexType);
20702 {VPGN->getChain(), VPGN->getBasePtr(), Index,
20703 ScaleOp, VPGN->getMask(),
20704 VPGN->getVectorLength()},
20705 VPGN->getMemOperand(), IndexType);
20709 case ISD::VP_SCATTER: {
20711 SDValue Index = VPSN->getIndex();
20712 SDValue ScaleOp = VPSN->getScale();
20714 assert(!VPSN->isIndexScaled() &&
20715 "Scaled gather/scatter should not be formed");
20720 {VPSN->getChain(), VPSN->getValue(),
20721 VPSN->getBasePtr(), Index, ScaleOp,
20722 VPSN->getMask(), VPSN->getVectorLength()},
20723 VPSN->getMemOperand(), IndexType);
20727 {VPSN->getChain(), VPSN->getValue(),
20728 VPSN->getBasePtr(), Index, ScaleOp,
20729 VPSN->getMask(), VPSN->getVectorLength()},
20730 VPSN->getMemOperand(), IndexType);
20733 case RISCVISD::SHL_VL:
20737 case RISCVISD::SRA_VL:
20738 case RISCVISD::SRL_VL: {
20740 if (ShAmt.
getOpcode() == RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL) {
20744 EVT VT =
N->getValueType(0);
20747 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt,
20748 N->getOperand(2),
N->getOperand(3),
N->getOperand(4));
20763 if (ShAmt.
getOpcode() == RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL) {
20766 EVT VT =
N->getValueType(0);
20769 DAG.
getRegister(RISCV::X0, Subtarget.getXLenVT()));
20770 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt);
20774 case RISCVISD::ADD_VL:
20782 case RISCVISD::VWADD_W_VL:
20783 case RISCVISD::VWADDU_W_VL:
20784 case RISCVISD::VWSUB_W_VL:
20785 case RISCVISD::VWSUBU_W_VL:
20787 case RISCVISD::OR_VL:
20788 case RISCVISD::SUB_VL:
20789 case RISCVISD::MUL_VL:
20791 case RISCVISD::VFMADD_VL:
20792 case RISCVISD::VFNMADD_VL:
20793 case RISCVISD::VFMSUB_VL:
20794 case RISCVISD::VFNMSUB_VL:
20795 case RISCVISD::STRICT_VFMADD_VL:
20796 case RISCVISD::STRICT_VFNMADD_VL:
20797 case RISCVISD::STRICT_VFMSUB_VL:
20798 case RISCVISD::STRICT_VFNMSUB_VL:
20800 case RISCVISD::FADD_VL:
20801 case RISCVISD::FSUB_VL:
20802 case RISCVISD::FMUL_VL:
20803 case RISCVISD::VFWADD_W_VL:
20804 case RISCVISD::VFWSUB_W_VL:
20812 if (
N->getOpcode() != ISD::STORE)
20816 SDValue Chain = Store->getChain();
20817 EVT MemVT = Store->getMemoryVT();
20818 SDValue Val = Store->getValue();
20821 bool IsScalarizable =
20823 Store->isSimple() &&
20853 NewVT, *Store->getMemOperand())) {
20855 return DAG.
getStore(Chain,
DL, NewV, Store->getBasePtr(),
20856 Store->getPointerInfo(), Store->getBaseAlign(),
20857 Store->getMemOperand()->getFlags());
20867 L->hasNUsesOfValue(1, 0) && L->hasNUsesOfValue(1, 1) &&
20869 L->getMemoryVT() == MemVT) {
20872 NewVT, *Store->getMemOperand()) &&
20874 NewVT, *L->getMemOperand())) {
20876 L->getPointerInfo(), L->getBaseAlign(),
20877 L->getMemOperand()->getFlags());
20878 return DAG.
getStore(Chain,
DL, NewL, Store->getBasePtr(),
20879 Store->getPointerInfo(), Store->getBaseAlign(),
20880 Store->getMemOperand()->getFlags());
20887 if ((Val.
getOpcode() == RISCVISD::VMV_X_S ||
20893 MVT VecVT = Src.getSimpleValueType();
20900 Store->getChain(),
DL, Src, Store->getBasePtr(), Store->getOffset(),
20903 Store->getMemOperand(), Store->getAddressingMode(),
20904 Store->isTruncatingStore(),
false);
20911 EVT VT =
N->getValueType(0);
20936 case RISCVISD::VFMV_V_F_VL: {
20937 const MVT VT =
N->getSimpleValueType(0);
20938 SDValue Passthru =
N->getOperand(0);
20939 SDValue Scalar =
N->getOperand(1);
20944 return DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL, VT, Passthru, Scalar, VL);
20947 case RISCVISD::VMV_V_X_VL: {
20948 const MVT VT =
N->getSimpleValueType(0);
20949 SDValue Passthru =
N->getOperand(0);
20950 SDValue Scalar =
N->getOperand(1);
20955 unsigned ScalarSize = Scalar.getValueSizeInBits();
20957 if (ScalarSize > EltWidth && Passthru.
isUndef())
20958 if (SimplifyDemandedLowBitsHelper(1, EltWidth))
20965 (!Const || Const->isZero() ||
20966 !Const->getAPIntValue().sextOrTrunc(EltWidth).isSignedIntN(5)))
20967 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, VT, Passthru, Scalar, VL);
20971 case RISCVISD::VFMV_S_F_VL: {
20976 if (
N->getOperand(0).isUndef() &&
20979 Src.getOperand(0).getValueType().isScalableVector()) {
20980 EVT VT =
N->getValueType(0);
21000 case RISCVISD::VMV_S_X_VL: {
21001 const MVT VT =
N->getSimpleValueType(0);
21002 SDValue Passthru =
N->getOperand(0);
21003 SDValue Scalar =
N->getOperand(1);
21009 unsigned ScalarSize = Scalar.getValueSizeInBits();
21011 if (ScalarSize > EltWidth && SimplifyDemandedLowBitsHelper(1, EltWidth))
21014 if (Scalar.getOpcode() == RISCVISD::VMV_X_S && Passthru.
isUndef() &&
21015 Scalar.getOperand(0).getValueType() ==
N->getValueType(0))
21016 return Scalar.getOperand(0);
21023 DAG.
getNode(
N->getOpcode(),
DL, M1VT, M1Passthru, Scalar, VL);
21032 Const && !Const->isZero() &&
isInt<5>(Const->getSExtValue()) &&
21034 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru, Scalar, VL);
21038 case RISCVISD::VMV_X_S: {
21040 MVT VecVT =
N->getOperand(0).getSimpleValueType();
21042 if (M1VT.
bitsLT(VecVT)) {
21044 return DAG.
getNode(RISCVISD::VMV_X_S,
DL,
N->getSimpleValueType(0), Vec);
21052 unsigned IntNo =
N->getConstantOperandVal(IntOpNo);
21057 case Intrinsic::riscv_vcpop:
21058 case Intrinsic::riscv_vcpop_mask:
21059 case Intrinsic::riscv_vfirst:
21060 case Intrinsic::riscv_vfirst_mask: {
21062 if (IntNo == Intrinsic::riscv_vcpop_mask ||
21063 IntNo == Intrinsic::riscv_vfirst_mask)
21064 VL =
N->getOperand(3);
21069 EVT VT =
N->getValueType(0);
21070 if (IntNo == Intrinsic::riscv_vfirst ||
21071 IntNo == Intrinsic::riscv_vfirst_mask)
21075 case Intrinsic::riscv_vsseg2_mask:
21076 case Intrinsic::riscv_vsseg3_mask:
21077 case Intrinsic::riscv_vsseg4_mask:
21078 case Intrinsic::riscv_vsseg5_mask:
21079 case Intrinsic::riscv_vsseg6_mask:
21080 case Intrinsic::riscv_vsseg7_mask:
21081 case Intrinsic::riscv_vsseg8_mask: {
21083 unsigned NF = Tuple.getValueType().getRISCVVectorTupleNumFields();
21085 if (Subtarget.hasOptimizedSegmentLoadStore(NF) || !Tuple.hasOneUse() ||
21086 Tuple.getOpcode() != RISCVISD::TUPLE_INSERT ||
21087 !Tuple.getOperand(0).isUndef())
21095 "Type mismatch without bitcast?");
21096 unsigned Stride = SEW / 8 * NF;
21097 unsigned Offset = SEW / 8 * Idx;
21124 case ISD::EXPERIMENTAL_VP_REVERSE:
21126 case ISD::VP_STORE:
21128 case ISD::BITCAST: {
21129 assert(Subtarget.useRVVForFixedLengthVectors());
21131 EVT VT =
N->getValueType(0);
21142 for (
unsigned i = 0; i < NF; ++i)
21143 Result = DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VT, Result,
Splat,
21149 if ((SrcVT == MVT::v1i1 || SrcVT == MVT::v2i1 || SrcVT == MVT::v4i1) &&
21162 case ISD::VECREDUCE_ADD:
21170 case RISCVISD::VRGATHER_VX_VL: {
21173 EVT VT =
N->getValueType(0);
21176 SDValue Passthru =
N->getOperand(2);
21183 Src = Src.getOperand(1);
21185 switch (Src.getOpcode()) {
21188 case RISCVISD::VMV_V_X_VL:
21189 case RISCVISD::VFMV_V_F_VL:
21197 case RISCVISD::VMV_S_X_VL:
21198 case RISCVISD::VFMV_S_F_VL:
21214 case RISCVISD::TUPLE_EXTRACT: {
21215 EVT VT =
N->getValueType(0);
21217 unsigned Idx =
N->getConstantOperandVal(1);
21222 switch (Tuple.getConstantOperandVal(1)) {
21225 case Intrinsic::riscv_vlseg2_mask:
21226 case Intrinsic::riscv_vlseg3_mask:
21227 case Intrinsic::riscv_vlseg4_mask:
21228 case Intrinsic::riscv_vlseg5_mask:
21229 case Intrinsic::riscv_vlseg6_mask:
21230 case Intrinsic::riscv_vlseg7_mask:
21231 case Intrinsic::riscv_vlseg8_mask:
21232 NF = Tuple.getValueType().getRISCVVectorTupleNumFields();
21236 if (!NF || Subtarget.hasOptimizedSegmentLoadStore(NF))
21241 "Type mismatch without bitcast?");
21242 unsigned Stride = SEW / 8 * NF;
21243 unsigned Offset = SEW / 8 * Idx;
21246 Tuple.getOperand(0),
21268 return Result.getValue(0);
21270 case RISCVISD::TUPLE_INSERT: {
21272 if (
N->getOperand(1).isUndef())
21273 return N->getOperand(0);
21276 case RISCVISD::VSLIDE1UP_VL:
21277 case RISCVISD::VFSLIDE1UP_VL: {
21281 MVT VT =
N->getSimpleValueType(0);
21285 if (!
N->getOperand(0).isUndef() ||
21304 return getVSlideup(DAG, Subtarget,
DL, VT, SrcVec,
N->getOperand(1),
21314 EVT XVT,
unsigned KeptBits)
const {
21319 if (XVT != MVT::i32 && XVT != MVT::i64)
21323 if (KeptBits == 32 || KeptBits == 64)
21327 return Subtarget.hasStdExtZbb() &&
21328 ((KeptBits == 8 && XVT == MVT::i64 && !Subtarget.is64Bit()) ||
21336 "Expected shift op");
21360 if (Ty.isScalarInteger() &&
21363 return isUsedByLdSt(N0.
getNode(),
N);
21369 if (C2 && Subtarget.hasShlAdd(C2->getZExtValue()) &&
N->hasOneUse() &&
21370 N->user_begin()->getOpcode() ==
ISD::ADD &&
21371 !isUsedByLdSt(*
N->user_begin(),
nullptr) &&
21376 const APInt &C1Int = C1->getAPIntValue();
21377 APInt ShiftedC1Int = C1Int << C2->getAPIntValue();
21398 ShiftedC1Int, Ty.getSizeInBits(), Subtarget,
21403 if (C1Cost < ShiftedC1Cost)
21426 EVT VT =
Op.getValueType();
21430 unsigned Opcode =
Op.getOpcode();
21438 const APInt &Mask =
C->getAPIntValue();
21447 auto IsLegalMask = [ShrunkMask, ExpandedMask](
const APInt &Mask) ->
bool {
21448 return ShrunkMask.
isSubsetOf(Mask) && Mask.isSubsetOf(ExpandedMask);
21450 auto UseMask = [Mask,
Op, &TLO](
const APInt &NewMask) ->
bool {
21451 if (NewMask == Mask)
21456 Op.getOperand(0), NewC);
21469 APInt NewMask =
APInt(Mask.getBitWidth(), 0xffff);
21470 if (IsLegalMask(NewMask))
21471 return UseMask(NewMask);
21474 if (VT == MVT::i64) {
21476 if (IsLegalMask(NewMask))
21477 return UseMask(NewMask);
21492 APInt NewMask = ShrunkMask;
21493 if (MinSignedBits <= 12)
21495 else if (!
C->isOpaque() && MinSignedBits <= 32 && !ShrunkMask.
isSignedIntN(32))
21501 assert(IsLegalMask(NewMask));
21502 return UseMask(NewMask);
21506 static const uint64_t GREVMasks[] = {
21507 0x5555555555555555ULL, 0x3333333333333333ULL, 0x0F0F0F0F0F0F0F0FULL,
21508 0x00FF00FF00FF00FFULL, 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL};
21510 for (
unsigned Stage = 0; Stage != 6; ++Stage) {
21511 unsigned Shift = 1 << Stage;
21512 if (ShAmt & Shift) {
21514 uint64_t Res = ((x & Mask) << Shift) | ((x >> Shift) & Mask);
21526 const APInt &DemandedElts,
21528 unsigned Depth)
const {
21530 unsigned Opc =
Op.getOpcode();
21535 "Should use MaskedValueIsZero if you don't know whether Op"
21536 " is a target node!");
21541 case RISCVISD::SELECT_CC: {
21552 case RISCVISD::VCPOP_VL: {
21557 case RISCVISD::CZERO_EQZ:
21558 case RISCVISD::CZERO_NEZ:
21564 case RISCVISD::REMUW: {
21574 case RISCVISD::DIVUW: {
21584 case RISCVISD::SLLW: {
21593 case RISCVISD::SRLW: {
21602 case RISCVISD::SRAW: {
21611 case RISCVISD::SHL_ADD: {
21614 unsigned ShAmt =
Op.getConstantOperandVal(1);
21621 case RISCVISD::CTZW: {
21628 case RISCVISD::CLZW: {
21635 case RISCVISD::BREV8:
21636 case RISCVISD::ORC_B: {
21640 bool IsGORC =
Op.getOpcode() == RISCVISD::ORC_B;
21648 case RISCVISD::READ_VLENB: {
21651 const unsigned MinVLenB = Subtarget.getRealMinVLen() / 8;
21652 const unsigned MaxVLenB = Subtarget.getRealMaxVLen() / 8;
21653 assert(MinVLenB > 0 &&
"READ_VLENB without vector extension enabled?");
21656 if (MaxVLenB == MinVLenB)
21660 case RISCVISD::FCLASS: {
21673 case Intrinsic::riscv_vsetvli:
21674 case Intrinsic::riscv_vsetvlimax: {
21675 bool HasAVL = IntNo == Intrinsic::riscv_vsetvli;
21676 unsigned VSEW =
Op.getConstantOperandVal(HasAVL + 1);
21681 uint64_t MaxVL = Subtarget.getRealMaxVLen() / SEW;
21682 MaxVL = (Fractional) ? MaxVL / LMul : MaxVL * LMul;
21686 MaxVL = std::min(MaxVL,
Op.getConstantOperandVal(1));
21688 unsigned KnownZeroFirstBit =
Log2_32(MaxVL) + 1;
21701 unsigned Depth)
const {
21702 switch (
Op.getOpcode()) {
21705 case RISCVISD::SELECT_CC: {
21708 if (Tmp == 1)
return 1;
21711 return std::min(Tmp, Tmp2);
21713 case RISCVISD::CZERO_EQZ:
21714 case RISCVISD::CZERO_NEZ:
21718 case RISCVISD::ABSW: {
21723 if (Tmp < 33)
return 1;
21726 case RISCVISD::SRAW: {
21733 return std::max(Tmp, 33U);
21735 case RISCVISD::SLLW:
21736 case RISCVISD::SRLW:
21737 case RISCVISD::DIVW:
21738 case RISCVISD::DIVUW:
21739 case RISCVISD::REMUW:
21740 case RISCVISD::ROLW:
21741 case RISCVISD::RORW:
21742 case RISCVISD::FCVT_W_RV64:
21743 case RISCVISD::FCVT_WU_RV64:
21744 case RISCVISD::STRICT_FCVT_W_RV64:
21745 case RISCVISD::STRICT_FCVT_WU_RV64:
21748 case RISCVISD::VMV_X_S: {
21754 unsigned XLen = Subtarget.getXLen();
21755 unsigned EltBits =
Op.getOperand(0).getScalarValueSizeInBits();
21756 if (EltBits <= XLen)
21757 return XLen - EltBits + 1;
21761 unsigned IntNo =
Op.getConstantOperandVal(1);
21765 case Intrinsic::riscv_masked_atomicrmw_xchg:
21766 case Intrinsic::riscv_masked_atomicrmw_add:
21767 case Intrinsic::riscv_masked_atomicrmw_sub:
21768 case Intrinsic::riscv_masked_atomicrmw_nand:
21769 case Intrinsic::riscv_masked_atomicrmw_max:
21770 case Intrinsic::riscv_masked_atomicrmw_min:
21771 case Intrinsic::riscv_masked_atomicrmw_umax:
21772 case Intrinsic::riscv_masked_atomicrmw_umin:
21773 case Intrinsic::riscv_masked_cmpxchg:
21780 assert(Subtarget.hasStdExtA());
21781 return Op.getValueSizeInBits() - 31;
21793 unsigned Depth)
const {
21796 switch (
Op.getOpcode()) {
21797 case RISCVISD::BREV8:
21798 case RISCVISD::ORC_B: {
21800 bool IsGORC =
Op.getOpcode() == RISCVISD::ORC_B;
21808 OriginalDemandedElts, Known2, TLO,
Depth + 1))
21820 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
21828 switch (
Op.getOpcode()) {
21829 case RISCVISD::SLLW:
21830 case RISCVISD::SRAW:
21831 case RISCVISD::SRLW:
21832 case RISCVISD::RORW:
21833 case RISCVISD::ROLW:
21837 case RISCVISD::SELECT_CC:
21839 assert(
Op.getOperand(0).getValueType().isInteger() &&
21840 "RISCVISD::SELECT_CC only compares integers");
21849 assert(Ld &&
"Unexpected null LoadSDNode");
21858 if (!CNode || CNode->isMachineConstantPoolEntry() ||
21859 CNode->getOffset() != 0)
21866 if (
Ptr.getOpcode() == RISCVISD::LLA) {
21867 auto *CNode = GetSupportedConstantPool(
Ptr.getOperand(0));
21868 if (!CNode || CNode->getTargetFlags() != 0)
21871 return CNode->getConstVal();
21875 if (
Ptr.getOpcode() != RISCVISD::ADD_LO ||
21876 Ptr.getOperand(0).getOpcode() != RISCVISD::HI)
21879 auto *CNodeLo = GetSupportedConstantPool(
Ptr.getOperand(1));
21880 auto *CNodeHi = GetSupportedConstantPool(
Ptr.getOperand(0).getOperand(0));
21886 if (CNodeLo->getConstVal() != CNodeHi->getConstVal())
21889 return CNodeLo->getConstVal();
21894 assert(
MI.getOpcode() == RISCV::ReadCounterWide &&
"Unexpected instruction");
21926 Register ReadAgainReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
21929 int64_t LoCounter =
MI.getOperand(2).getImm();
21930 int64_t HiCounter =
MI.getOperand(3).getImm();
21940 BuildMI(LoopMBB,
DL,
TII->get(RISCV::CSRRS), ReadAgainReg)
21952 MI.eraseFromParent();
21960 assert(
MI.getOpcode() == RISCV::SplitF64Pseudo &&
"Unexpected instruction");
21968 Register SrcReg =
MI.getOperand(2).getReg();
21973 TII.storeRegToStackSlot(*BB,
MI, SrcReg,
MI.getOperand(2).isKill(), FI, SrcRC,
21988 MI.eraseFromParent();
21995 assert(
MI.getOpcode() == RISCV::BuildPairF64Pseudo &&
21996 "Unexpected instruction");
22002 Register DstReg =
MI.getOperand(0).getReg();
22024 TII.loadRegFromStackSlot(*BB,
MI, DstReg, FI, DstRC, RI,
Register());
22025 MI.eraseFromParent();
22030 unsigned RelOpcode,
unsigned EqOpcode,
22033 Register DstReg =
MI.getOperand(0).getReg();
22034 Register Src1Reg =
MI.getOperand(1).getReg();
22035 Register Src2Reg =
MI.getOperand(2).getReg();
22037 Register SavedFFlags =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22061 MI.eraseFromParent();
22112 F->insert(It, FirstMBB);
22113 F->insert(It, SecondMBB);
22114 F->insert(It, SinkMBB);
22164 First.eraseFromParent();
22203 if (
MI.getOpcode() != RISCV::Select_GPR_Using_CC_GPR &&
22204 MI.getOperand(1).isReg() &&
MI.getOperand(2).isReg() &&
22205 Next != BB->
end() &&
Next->getOpcode() ==
MI.getOpcode() &&
22206 Next->getOperand(5).getReg() ==
MI.getOperand(0).getReg() &&
22207 Next->getOperand(5).isKill())
22212 if (
MI.getOperand(2).isReg())
22213 RHS =
MI.getOperand(2).getReg();
22218 SelectDests.
insert(
MI.getOperand(0).getReg());
22222 SequenceMBBI !=
E; ++SequenceMBBI) {
22223 if (SequenceMBBI->isDebugInstr())
22225 if (RISCVInstrInfo::isSelectPseudo(*SequenceMBBI)) {
22226 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
22227 !SequenceMBBI->getOperand(2).isReg() ||
22228 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
22229 SequenceMBBI->getOperand(3).getImm() != CC ||
22230 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
22231 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
22233 LastSelectPseudo = &*SequenceMBBI;
22235 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
22238 if (SequenceMBBI->hasUnmodeledSideEffects() ||
22239 SequenceMBBI->mayLoadOrStore() ||
22240 SequenceMBBI->usesCustomInsertionHook())
22243 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
22258 F->insert(
I, IfFalseMBB);
22259 F->insert(
I, TailMBB);
22262 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
22268 TailMBB->
push_back(DebugInstr->removeFromParent());
22272 TailMBB->
splice(TailMBB->
end(), HeadMBB,
22282 if (
MI.getOperand(2).isImm())
22285 .
addImm(
MI.getOperand(2).getImm())
22297 auto SelectMBBI =
MI.getIterator();
22298 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
22300 while (SelectMBBI != SelectEnd) {
22301 auto Next = std::next(SelectMBBI);
22302 if (RISCVInstrInfo::isSelectPseudo(*SelectMBBI)) {
22305 TII.get(RISCV::PHI), SelectMBBI->getOperand(0).getReg())
22306 .
addReg(SelectMBBI->getOperand(4).getReg())
22308 .
addReg(SelectMBBI->getOperand(5).getReg())
22315 F->getProperties().resetNoPHIs();
22323 RISCVVInversePseudosTable::getBaseInfo(MCOpcode, LMul, SEW);
22324 assert(
Inverse &&
"Unexpected LMUL and SEW pair for instruction");
22326 RISCV::lookupMaskedIntrinsicByUnmasked(
Inverse->Pseudo);
22327 assert(
Masked &&
"Could not find masked instruction for LMUL and SEW pair");
22333 unsigned CVTXOpc) {
22339 Register SavedFFLAGS =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22352 .
add(
MI.getOperand(1))
22353 .
add(
MI.getOperand(2))
22354 .
add(
MI.getOperand(3))
22356 .
add(
MI.getOperand(4))
22357 .
add(
MI.getOperand(5))
22358 .
add(
MI.getOperand(6))
22373 .
add(
MI.getOperand(0))
22374 .
add(
MI.getOperand(1))
22376 .
add(
MI.getOperand(3))
22378 .
add(
MI.getOperand(4))
22379 .
add(
MI.getOperand(5))
22380 .
add(
MI.getOperand(6))
22390 MI.eraseFromParent();
22396 unsigned CmpOpc, F2IOpc, I2FOpc, FSGNJOpc, FSGNJXOpc;
22398 switch (
MI.getOpcode()) {
22401 case RISCV::PseudoFROUND_H:
22402 CmpOpc = RISCV::FLT_H;
22403 F2IOpc = RISCV::FCVT_W_H;
22404 I2FOpc = RISCV::FCVT_H_W;
22405 FSGNJOpc = RISCV::FSGNJ_H;
22406 FSGNJXOpc = RISCV::FSGNJX_H;
22407 RC = &RISCV::FPR16RegClass;
22409 case RISCV::PseudoFROUND_H_INX:
22410 CmpOpc = RISCV::FLT_H_INX;
22411 F2IOpc = RISCV::FCVT_W_H_INX;
22412 I2FOpc = RISCV::FCVT_H_W_INX;
22413 FSGNJOpc = RISCV::FSGNJ_H_INX;
22414 FSGNJXOpc = RISCV::FSGNJX_H_INX;
22415 RC = &RISCV::GPRF16RegClass;
22417 case RISCV::PseudoFROUND_S:
22418 CmpOpc = RISCV::FLT_S;
22419 F2IOpc = RISCV::FCVT_W_S;
22420 I2FOpc = RISCV::FCVT_S_W;
22421 FSGNJOpc = RISCV::FSGNJ_S;
22422 FSGNJXOpc = RISCV::FSGNJX_S;
22423 RC = &RISCV::FPR32RegClass;
22425 case RISCV::PseudoFROUND_S_INX:
22426 CmpOpc = RISCV::FLT_S_INX;
22427 F2IOpc = RISCV::FCVT_W_S_INX;
22428 I2FOpc = RISCV::FCVT_S_W_INX;
22429 FSGNJOpc = RISCV::FSGNJ_S_INX;
22430 FSGNJXOpc = RISCV::FSGNJX_S_INX;
22431 RC = &RISCV::GPRF32RegClass;
22433 case RISCV::PseudoFROUND_D:
22435 CmpOpc = RISCV::FLT_D;
22436 F2IOpc = RISCV::FCVT_L_D;
22437 I2FOpc = RISCV::FCVT_D_L;
22438 FSGNJOpc = RISCV::FSGNJ_D;
22439 FSGNJXOpc = RISCV::FSGNJX_D;
22440 RC = &RISCV::FPR64RegClass;
22442 case RISCV::PseudoFROUND_D_INX:
22444 CmpOpc = RISCV::FLT_D_INX;
22445 F2IOpc = RISCV::FCVT_L_D_INX;
22446 I2FOpc = RISCV::FCVT_D_L_INX;
22447 FSGNJOpc = RISCV::FSGNJ_D_INX;
22448 FSGNJXOpc = RISCV::FSGNJX_D_INX;
22449 RC = &RISCV::GPRRegClass;
22461 F->insert(
I, CvtMBB);
22462 F->insert(
I, DoneMBB);
22470 MBB->addSuccessor(CvtMBB);
22471 MBB->addSuccessor(DoneMBB);
22473 Register DstReg =
MI.getOperand(0).getReg();
22474 Register SrcReg =
MI.getOperand(1).getReg();
22475 Register MaxReg =
MI.getOperand(2).getReg();
22476 int64_t FRM =
MI.getOperand(3).getImm();
22481 Register FabsReg =
MRI.createVirtualRegister(RC);
22485 Register CmpReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22500 Register F2IReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22522 MI.eraseFromParent();
22529 switch (
MI.getOpcode()) {
22532 case RISCV::ReadCounterWide:
22533 assert(!Subtarget.is64Bit() &&
22534 "ReadCounterWide is only to be used on riscv32");
22536 case RISCV::Select_GPR_Using_CC_GPR:
22537 case RISCV::Select_GPR_Using_CC_Imm5_Zibi:
22538 case RISCV::Select_GPR_Using_CC_SImm5_CV:
22539 case RISCV::Select_GPRNoX0_Using_CC_SImm5NonZero_QC:
22540 case RISCV::Select_GPRNoX0_Using_CC_UImm5NonZero_QC:
22541 case RISCV::Select_GPRNoX0_Using_CC_SImm16NonZero_QC:
22542 case RISCV::Select_GPRNoX0_Using_CC_UImm16NonZero_QC:
22543 case RISCV::Select_GPR_Using_CC_UImmLog2XLen_NDS:
22544 case RISCV::Select_GPR_Using_CC_UImm7_NDS:
22545 case RISCV::Select_FPR16_Using_CC_GPR:
22546 case RISCV::Select_FPR16INX_Using_CC_GPR:
22547 case RISCV::Select_FPR32_Using_CC_GPR:
22548 case RISCV::Select_FPR32INX_Using_CC_GPR:
22549 case RISCV::Select_FPR64_Using_CC_GPR:
22550 case RISCV::Select_FPR64INX_Using_CC_GPR:
22551 case RISCV::Select_FPR64IN32X_Using_CC_GPR:
22553 case RISCV::BuildPairF64Pseudo:
22555 case RISCV::SplitF64Pseudo:
22557 case RISCV::PseudoQuietFLE_H:
22559 case RISCV::PseudoQuietFLE_H_INX:
22560 return emitQuietFCMP(
MI, BB, RISCV::FLE_H_INX, RISCV::FEQ_H_INX, Subtarget);
22561 case RISCV::PseudoQuietFLT_H:
22563 case RISCV::PseudoQuietFLT_H_INX:
22564 return emitQuietFCMP(
MI, BB, RISCV::FLT_H_INX, RISCV::FEQ_H_INX, Subtarget);
22565 case RISCV::PseudoQuietFLE_S:
22567 case RISCV::PseudoQuietFLE_S_INX:
22568 return emitQuietFCMP(
MI, BB, RISCV::FLE_S_INX, RISCV::FEQ_S_INX, Subtarget);
22569 case RISCV::PseudoQuietFLT_S:
22571 case RISCV::PseudoQuietFLT_S_INX:
22572 return emitQuietFCMP(
MI, BB, RISCV::FLT_S_INX, RISCV::FEQ_S_INX, Subtarget);
22573 case RISCV::PseudoQuietFLE_D:
22575 case RISCV::PseudoQuietFLE_D_INX:
22576 return emitQuietFCMP(
MI, BB, RISCV::FLE_D_INX, RISCV::FEQ_D_INX, Subtarget);
22577 case RISCV::PseudoQuietFLE_D_IN32X:
22580 case RISCV::PseudoQuietFLT_D:
22582 case RISCV::PseudoQuietFLT_D_INX:
22583 return emitQuietFCMP(
MI, BB, RISCV::FLT_D_INX, RISCV::FEQ_D_INX, Subtarget);
22584 case RISCV::PseudoQuietFLT_D_IN32X:
22588 case RISCV::PseudoVFROUND_NOEXCEPT_V_M1_MASK:
22590 case RISCV::PseudoVFROUND_NOEXCEPT_V_M2_MASK:
22592 case RISCV::PseudoVFROUND_NOEXCEPT_V_M4_MASK:
22594 case RISCV::PseudoVFROUND_NOEXCEPT_V_M8_MASK:
22596 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF2_MASK:
22598 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF4_MASK:
22600 case RISCV::PseudoFROUND_H:
22601 case RISCV::PseudoFROUND_H_INX:
22602 case RISCV::PseudoFROUND_S:
22603 case RISCV::PseudoFROUND_S_INX:
22604 case RISCV::PseudoFROUND_D:
22605 case RISCV::PseudoFROUND_D_INX:
22606 case RISCV::PseudoFROUND_D_IN32X:
22608 case RISCV::PROBED_STACKALLOC_DYN:
22610 case TargetOpcode::STATEPOINT:
22616 MI.addOperand(*
MI.getMF(),
22622 case TargetOpcode::STACKMAP:
22623 case TargetOpcode::PATCHPOINT:
22624 if (!Subtarget.is64Bit())
22626 "supported on 64-bit targets");
22636 if (
auto *FRMDef =
MI.findRegisterDefOperand(RISCV::FRM,
nullptr)) {
22637 FRMDef->setIsDead(
false);
22641 int Idx = RISCV::getNamedOperandIdx(
MI.getOpcode(), RISCV::OpName::frm);
22651 if (
MI.readsRegister(RISCV::FRM,
nullptr))
22657void RISCVTargetLowering::analyzeInputArgs(
22661 for (
const auto &[Idx, In] :
enumerate(Ins)) {
22667 LLVM_DEBUG(
dbgs() <<
"InputArg #" << Idx <<
" has unhandled type "
22674void RISCVTargetLowering::analyzeOutputArgs(
22678 for (
const auto &[Idx, Out] :
enumerate(Outs)) {
22679 MVT ArgVT = Out.VT;
22680 ISD::ArgFlagsTy ArgFlags = Out.Flags;
22684 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << Idx <<
" has unhandled type "
22701 return DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, Val);
22735 if (In.isOrigArg()) {
22740 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
22741 (
BitWidth < 32 && In.Flags.isZExt())) {
22762 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, LocVT, Val);
22763 if (LocVT == MVT::i64 && VA.
getValVT() == MVT::f32)
22764 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Val);
22776 Val = DAG.
getNode(ISD::BITCAST,
DL, LocVT, Val);
22812 ExtType,
DL, LocVT, Chain, FIN,
22829 Register LoVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
22842 Register HiVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
22846 return DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64,
Lo,
Hi);
22857 switch (CallConv) {
22866#define CC_VLS_CASE(ABI_VLEN) case CallingConv::RISCV_VLSCall_##ABI_VLEN:
22882 if (Subtarget.hasStdExtE())
22884 if (!Subtarget.hasStdExtFOrZfinx() || !Subtarget.hasStdExtDOrZdinx())
22886 "(Zdinx/D) instruction set extensions");
22890 if (Func.hasFnAttribute(
"interrupt")) {
22891 if (!Func.arg_empty())
22893 "Functions with the interrupt attribute cannot have arguments!");
22904 "SiFive-CLIC-preemptible",
22905 "SiFive-CLIC-stack-swap",
22906 "SiFive-CLIC-preemptible-stack-swap",
22910 "Function interrupt attribute argument not supported!");
22912 if (Kind.starts_with(
"qci-") && !Subtarget.hasVendorXqciint())
22914 "'qci-*' interrupt kinds require Xqciint extension");
22916 if (Kind.starts_with(
"SiFive-CLIC-") && !Subtarget.hasVendorXSfmclic())
22918 "'SiFive-CLIC-*' interrupt kinds require XSfmclic extension");
22920 if (Kind ==
"rnmi" && !Subtarget.hasStdExtSmrnmi())
22923 if (Kind.starts_with(
"SiFive-CLIC-preemptible") && TFI->
hasFP(MF))
22925 "have a frame pointer");
22929 MVT XLenVT = Subtarget.getXLenVT();
22930 unsigned XLenInBytes = Subtarget.getXLen() / 8;
22932 std::vector<SDValue> OutChains;
22941 analyzeInputArgs(MF, CCInfo, Ins,
false,
22945 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
22966 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
22967 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
22969 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
22971 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
23000 int VarArgsSaveSize = XLenInBytes * (ArgRegs.
size() - Idx);
23005 if (VarArgsSaveSize == 0) {
23009 int VaArgOffset = -VarArgsSaveSize;
23017 XLenInBytes, VaArgOffset -
static_cast<int>(XLenInBytes),
true);
23018 VarArgsSaveSize += XLenInBytes;
23025 for (
unsigned I = Idx;
I < ArgRegs.
size(); ++
I) {
23026 const Register Reg = RegInfo.createVirtualRegister(RC);
23027 RegInfo.addLiveIn(ArgRegs[
I], Reg);
23030 Chain,
DL, ArgValue, FIN,
23032 OutChains.push_back(Store);
23046 if (!OutChains.empty()) {
23047 OutChains.push_back(Chain);
23057bool RISCVTargetLowering::isEligibleForTailCallOptimization(
23061 auto CalleeCC = CLI.CallConv;
23062 auto &Outs = CLI.Outs;
23064 auto CallerCC = Caller.getCallingConv();
23071 if (Caller.hasFnAttribute(
"interrupt"))
23086 for (
auto &VA : ArgLocs)
23092 auto IsCallerStructRet = Caller.hasStructRetAttr();
23093 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
23094 if (IsCallerStructRet || IsCalleeStructRet)
23099 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
23100 if (CalleeCC != CallerCC) {
23101 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
23102 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
23109 for (
auto &Arg : Outs)
23110 if (Arg.Flags.isByVal())
23136 MVT XLenVT = Subtarget.getXLenVT();
23151 if (Subtarget.hasStdExtE())
23155 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
23161 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
23167 "call site marked musttail");
23174 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
23176 if (!Flags.isByVal())
23180 unsigned Size = Flags.getByValSize();
23181 Align Alignment = Flags.getNonZeroByValAlign();
23188 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
23190 false,
nullptr, IsTailCall,
23202 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
23205 SDValue ArgValue = OutVals[OutIdx];
23213 RISCVISD::SplitF64,
DL, DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
23225 if (!StackPtr.getNode())
23237 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
23255 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
23256 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
23262 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
23263 SDValue PartValue = OutVals[OutIdx + 1];
23264 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
23278 DAG.
getStore(Chain,
DL, ArgValue, SpillSlot,
23280 for (
const auto &Part : Parts) {
23281 SDValue PartValue = Part.first;
23282 SDValue PartOffset = Part.second;
23289 ArgValue = SpillSlot;
23295 if (Flags.isByVal())
23296 ArgValue = ByValArgs[j++];
23303 if (
Options.EmitCallSiteInfo)
23307 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
23308 "for passing parameters");
23311 if (!StackPtr.getNode())
23325 if (!MemOpChains.
empty())
23331 for (
auto &Reg : RegsToPass) {
23332 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
23339 validateCCReservedRegs(RegsToPass, MF);
23343 "Return address register required, but has been reserved."});
23348 bool CalleeIsLargeExternalSymbol =
false;
23354 CalleeIsLargeExternalSymbol =
true;
23365 Ops.push_back(Chain);
23366 Ops.push_back(Callee);
23370 for (
auto &Reg : RegsToPass)
23371 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
23375 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
23376 assert(Mask &&
"Missing call preserved mask for calling convention");
23381 Ops.push_back(Glue);
23384 "Unexpected CFI type for a direct call");
23392 bool NeedSWGuarded =
false;
23394 Subtarget.hasStdExtZicfilp() &&
23396 NeedSWGuarded =
true;
23401 NeedSWGuarded ? RISCVISD::SW_GUARDED_TAIL : RISCVISD::TAIL;
23410 unsigned CallOpc = NeedSWGuarded ? RISCVISD::SW_GUARDED_CALL : RISCVISD::CALL;
23426 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_RISCV);
23429 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
23430 auto &VA = RVLocs[i];
23438 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
23439 assert(VA.needsCustom());
23444 RetValue = DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64, RetValue,
23458 const Type *RetTy)
const {
23460 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
23462 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
23463 MVT VT = Outs[i].VT;
23466 true, Outs[i].OrigTy))
23497 for (
unsigned i = 0, e = RVLocs.
size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
23498 SDValue Val = OutVals[OutIdx];
23507 DAG.
getVTList(MVT::i32, MVT::i32), Val);
23511 Register RegHi = RVLocs[++i].getLocReg();
23513 if (Subtarget.isRegisterReservedByUser(RegLo) ||
23514 Subtarget.isRegisterReservedByUser(RegHi))
23517 "Return value register required, but has been reserved."});
23530 if (Subtarget.isRegisterReservedByUser(VA.
getLocReg()))
23533 "Return value register required, but has been reserved."});
23552 unsigned RetOpc = RISCVISD::RET_GLUE;
23555 if (Func.hasFnAttribute(
"interrupt")) {
23556 if (!Func.getReturnType()->isVoidTy())
23558 "Functions with the interrupt attribute must have void return type!");
23564 if (Kind ==
"supervisor")
23565 RetOpc = RISCVISD::SRET_GLUE;
23566 else if (Kind ==
"rnmi") {
23567 assert(Subtarget.hasFeature(RISCV::FeatureStdExtSmrnmi) &&
23568 "Need Smrnmi extension for rnmi");
23569 RetOpc = RISCVISD::MNRET_GLUE;
23570 }
else if (Kind ==
"qci-nest" || Kind ==
"qci-nonest") {
23571 assert(Subtarget.hasFeature(RISCV::FeatureVendorXqciint) &&
23572 "Need Xqciint for qci-(no)nest");
23573 RetOpc = RISCVISD::QC_C_MILEAVERET_GLUE;
23575 RetOpc = RISCVISD::MRET_GLUE;
23578 return DAG.
getNode(RetOpc,
DL, MVT::Other, RetOps);
23581void RISCVTargetLowering::validateCCReservedRegs(
23582 const SmallVectorImpl<std::pair<llvm::Register, llvm::SDValue>> &Regs,
23590 F,
"Argument register required, but has been reserved."});
23596 if (
N->getNumValues() != 1)
23598 if (!
N->hasNUsesOfValue(1, 0))
23601 SDNode *Copy = *
N->user_begin();
23603 if (Copy->getOpcode() == ISD::BITCAST) {
23615 if (Copy->getOperand(Copy->getNumOperands() - 1).getValueType() == MVT::Glue)
23619 bool HasRet =
false;
23621 if (
Node->getOpcode() != RISCVISD::RET_GLUE)
23628 Chain = Copy->getOperand(0);
23640 if (Constraint.
size() == 1) {
23641 switch (Constraint[0]) {
23658 if (Constraint ==
"vr" || Constraint ==
"vd" || Constraint ==
"vm")
23660 if (Constraint ==
"cr" || Constraint ==
"cR" || Constraint ==
"cf")
23666std::pair<unsigned, const TargetRegisterClass *>
23672 if (Constraint.
size() == 1) {
23673 switch (Constraint[0]) {
23678 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
23679 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
23680 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
23681 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
23682 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23683 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23684 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
23686 if (VT == MVT::f16) {
23687 if (Subtarget.hasStdExtZfhmin())
23688 return std::make_pair(0U, &RISCV::FPR16RegClass);
23689 if (Subtarget.hasStdExtZhinxmin())
23690 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
23691 }
else if (VT == MVT::f32) {
23692 if (Subtarget.hasStdExtF())
23693 return std::make_pair(0U, &RISCV::FPR32RegClass);
23694 if (Subtarget.hasStdExtZfinx())
23695 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
23696 }
else if (VT == MVT::f64) {
23697 if (Subtarget.hasStdExtD())
23698 return std::make_pair(0U, &RISCV::FPR64RegClass);
23699 if (Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23700 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23701 if (Subtarget.hasStdExtZdinx() && Subtarget.is64Bit())
23702 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
23706 if (((VT == MVT::i64 || VT == MVT::f64) && !Subtarget.is64Bit()) ||
23707 (VT == MVT::i128 && Subtarget.is64Bit()))
23708 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23713 }
else if (Constraint ==
"vr") {
23714 for (
const auto *RC :
23715 {&RISCV::VRRegClass, &RISCV::VRM2RegClass, &RISCV::VRM4RegClass,
23716 &RISCV::VRM8RegClass, &RISCV::VRN2M1RegClass, &RISCV::VRN3M1RegClass,
23717 &RISCV::VRN4M1RegClass, &RISCV::VRN5M1RegClass,
23718 &RISCV::VRN6M1RegClass, &RISCV::VRN7M1RegClass,
23719 &RISCV::VRN8M1RegClass, &RISCV::VRN2M2RegClass,
23720 &RISCV::VRN3M2RegClass, &RISCV::VRN4M2RegClass,
23721 &RISCV::VRN2M4RegClass}) {
23723 return std::make_pair(0U, RC);
23727 if (
TRI->isTypeLegalForClass(*RC, ContainerVT))
23728 return std::make_pair(0U, RC);
23731 }
else if (Constraint ==
"vd") {
23732 for (
const auto *RC :
23733 {&RISCV::VRNoV0RegClass, &RISCV::VRM2NoV0RegClass,
23734 &RISCV::VRM4NoV0RegClass, &RISCV::VRM8NoV0RegClass,
23735 &RISCV::VRN2M1NoV0RegClass, &RISCV::VRN3M1NoV0RegClass,
23736 &RISCV::VRN4M1NoV0RegClass, &RISCV::VRN5M1NoV0RegClass,
23737 &RISCV::VRN6M1NoV0RegClass, &RISCV::VRN7M1NoV0RegClass,
23738 &RISCV::VRN8M1NoV0RegClass, &RISCV::VRN2M2NoV0RegClass,
23739 &RISCV::VRN3M2NoV0RegClass, &RISCV::VRN4M2NoV0RegClass,
23740 &RISCV::VRN2M4NoV0RegClass}) {
23742 return std::make_pair(0U, RC);
23746 if (
TRI->isTypeLegalForClass(*RC, ContainerVT))
23747 return std::make_pair(0U, RC);
23750 }
else if (Constraint ==
"vm") {
23751 if (
TRI->isTypeLegalForClass(RISCV::VMV0RegClass, VT.
SimpleTy))
23752 return std::make_pair(0U, &RISCV::VMV0RegClass);
23758 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, ContainerVT))
23759 return std::make_pair(0U, &RISCV::VMV0RegClass);
23761 }
else if (Constraint ==
"cr") {
23762 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
23763 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
23764 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
23765 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
23766 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23767 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23769 return std::make_pair(0U, &RISCV::GPRCRegClass);
23770 }
else if (Constraint ==
"cR") {
23771 if (((VT == MVT::i64 || VT == MVT::f64) && !Subtarget.is64Bit()) ||
23772 (VT == MVT::i128 && Subtarget.is64Bit()))
23773 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23774 }
else if (Constraint ==
"cf") {
23775 if (VT == MVT::f16) {
23776 if (Subtarget.hasStdExtZfhmin())
23777 return std::make_pair(0U, &RISCV::FPR16CRegClass);
23778 if (Subtarget.hasStdExtZhinxmin())
23779 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
23780 }
else if (VT == MVT::f32) {
23781 if (Subtarget.hasStdExtF())
23782 return std::make_pair(0U, &RISCV::FPR32CRegClass);
23783 if (Subtarget.hasStdExtZfinx())
23784 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
23785 }
else if (VT == MVT::f64) {
23786 if (Subtarget.hasStdExtD())
23787 return std::make_pair(0U, &RISCV::FPR64CRegClass);
23788 if (Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23789 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23790 if (Subtarget.hasStdExtZdinx() && Subtarget.is64Bit())
23791 return std::make_pair(0U, &RISCV::GPRCRegClass);
23800 .
Case(
"{zero}", RISCV::X0)
23801 .
Case(
"{ra}", RISCV::X1)
23802 .
Case(
"{sp}", RISCV::X2)
23803 .
Case(
"{gp}", RISCV::X3)
23804 .
Case(
"{tp}", RISCV::X4)
23805 .
Case(
"{t0}", RISCV::X5)
23806 .
Case(
"{t1}", RISCV::X6)
23807 .
Case(
"{t2}", RISCV::X7)
23808 .
Cases(
"{s0}",
"{fp}", RISCV::X8)
23809 .
Case(
"{s1}", RISCV::X9)
23810 .
Case(
"{a0}", RISCV::X10)
23811 .
Case(
"{a1}", RISCV::X11)
23812 .
Case(
"{a2}", RISCV::X12)
23813 .
Case(
"{a3}", RISCV::X13)
23814 .
Case(
"{a4}", RISCV::X14)
23815 .
Case(
"{a5}", RISCV::X15)
23816 .
Case(
"{a6}", RISCV::X16)
23817 .
Case(
"{a7}", RISCV::X17)
23818 .
Case(
"{s2}", RISCV::X18)
23819 .
Case(
"{s3}", RISCV::X19)
23820 .
Case(
"{s4}", RISCV::X20)
23821 .
Case(
"{s5}", RISCV::X21)
23822 .
Case(
"{s6}", RISCV::X22)
23823 .
Case(
"{s7}", RISCV::X23)
23824 .
Case(
"{s8}", RISCV::X24)
23825 .
Case(
"{s9}", RISCV::X25)
23826 .
Case(
"{s10}", RISCV::X26)
23827 .
Case(
"{s11}", RISCV::X27)
23828 .
Case(
"{t3}", RISCV::X28)
23829 .
Case(
"{t4}", RISCV::X29)
23830 .
Case(
"{t5}", RISCV::X30)
23831 .
Case(
"{t6}", RISCV::X31)
23833 if (XRegFromAlias != RISCV::NoRegister)
23834 return std::make_pair(XRegFromAlias, &RISCV::GPRRegClass);
23843 if (Subtarget.hasStdExtF()) {
23845 .
Cases(
"{f0}",
"{ft0}", RISCV::F0_F)
23846 .
Cases(
"{f1}",
"{ft1}", RISCV::F1_F)
23847 .
Cases(
"{f2}",
"{ft2}", RISCV::F2_F)
23848 .
Cases(
"{f3}",
"{ft3}", RISCV::F3_F)
23849 .
Cases(
"{f4}",
"{ft4}", RISCV::F4_F)
23850 .
Cases(
"{f5}",
"{ft5}", RISCV::F5_F)
23851 .
Cases(
"{f6}",
"{ft6}", RISCV::F6_F)
23852 .
Cases(
"{f7}",
"{ft7}", RISCV::F7_F)
23853 .
Cases(
"{f8}",
"{fs0}", RISCV::F8_F)
23854 .
Cases(
"{f9}",
"{fs1}", RISCV::F9_F)
23855 .
Cases(
"{f10}",
"{fa0}", RISCV::F10_F)
23856 .
Cases(
"{f11}",
"{fa1}", RISCV::F11_F)
23857 .
Cases(
"{f12}",
"{fa2}", RISCV::F12_F)
23858 .
Cases(
"{f13}",
"{fa3}", RISCV::F13_F)
23859 .
Cases(
"{f14}",
"{fa4}", RISCV::F14_F)
23860 .
Cases(
"{f15}",
"{fa5}", RISCV::F15_F)
23861 .
Cases(
"{f16}",
"{fa6}", RISCV::F16_F)
23862 .
Cases(
"{f17}",
"{fa7}", RISCV::F17_F)
23863 .
Cases(
"{f18}",
"{fs2}", RISCV::F18_F)
23864 .
Cases(
"{f19}",
"{fs3}", RISCV::F19_F)
23865 .
Cases(
"{f20}",
"{fs4}", RISCV::F20_F)
23866 .
Cases(
"{f21}",
"{fs5}", RISCV::F21_F)
23867 .
Cases(
"{f22}",
"{fs6}", RISCV::F22_F)
23868 .
Cases(
"{f23}",
"{fs7}", RISCV::F23_F)
23869 .
Cases(
"{f24}",
"{fs8}", RISCV::F24_F)
23870 .
Cases(
"{f25}",
"{fs9}", RISCV::F25_F)
23871 .
Cases(
"{f26}",
"{fs10}", RISCV::F26_F)
23872 .
Cases(
"{f27}",
"{fs11}", RISCV::F27_F)
23873 .
Cases(
"{f28}",
"{ft8}", RISCV::F28_F)
23874 .
Cases(
"{f29}",
"{ft9}", RISCV::F29_F)
23875 .
Cases(
"{f30}",
"{ft10}", RISCV::F30_F)
23876 .
Cases(
"{f31}",
"{ft11}", RISCV::F31_F)
23878 if (FReg != RISCV::NoRegister) {
23879 assert(RISCV::F0_F <= FReg && FReg <= RISCV::F31_F &&
"Unknown fp-reg");
23880 if (Subtarget.hasStdExtD() && (VT == MVT::f64 || VT == MVT::Other)) {
23881 unsigned RegNo = FReg - RISCV::F0_F;
23882 unsigned DReg = RISCV::F0_D + RegNo;
23883 return std::make_pair(DReg, &RISCV::FPR64RegClass);
23885 if (VT == MVT::f32 || VT == MVT::Other)
23886 return std::make_pair(FReg, &RISCV::FPR32RegClass);
23887 if (Subtarget.hasStdExtZfhmin() && VT == MVT::f16) {
23888 unsigned RegNo = FReg - RISCV::F0_F;
23889 unsigned HReg = RISCV::F0_H + RegNo;
23890 return std::make_pair(HReg, &RISCV::FPR16RegClass);
23895 if (Subtarget.hasVInstructions()) {
23897 .
Case(
"{v0}", RISCV::V0)
23898 .
Case(
"{v1}", RISCV::V1)
23899 .
Case(
"{v2}", RISCV::V2)
23900 .
Case(
"{v3}", RISCV::V3)
23901 .
Case(
"{v4}", RISCV::V4)
23902 .
Case(
"{v5}", RISCV::V5)
23903 .
Case(
"{v6}", RISCV::V6)
23904 .
Case(
"{v7}", RISCV::V7)
23905 .
Case(
"{v8}", RISCV::V8)
23906 .
Case(
"{v9}", RISCV::V9)
23907 .
Case(
"{v10}", RISCV::V10)
23908 .
Case(
"{v11}", RISCV::V11)
23909 .
Case(
"{v12}", RISCV::V12)
23910 .
Case(
"{v13}", RISCV::V13)
23911 .
Case(
"{v14}", RISCV::V14)
23912 .
Case(
"{v15}", RISCV::V15)
23913 .
Case(
"{v16}", RISCV::V16)
23914 .
Case(
"{v17}", RISCV::V17)
23915 .
Case(
"{v18}", RISCV::V18)
23916 .
Case(
"{v19}", RISCV::V19)
23917 .
Case(
"{v20}", RISCV::V20)
23918 .
Case(
"{v21}", RISCV::V21)
23919 .
Case(
"{v22}", RISCV::V22)
23920 .
Case(
"{v23}", RISCV::V23)
23921 .
Case(
"{v24}", RISCV::V24)
23922 .
Case(
"{v25}", RISCV::V25)
23923 .
Case(
"{v26}", RISCV::V26)
23924 .
Case(
"{v27}", RISCV::V27)
23925 .
Case(
"{v28}", RISCV::V28)
23926 .
Case(
"{v29}", RISCV::V29)
23927 .
Case(
"{v30}", RISCV::V30)
23928 .
Case(
"{v31}", RISCV::V31)
23930 if (VReg != RISCV::NoRegister) {
23931 if (
TRI->isTypeLegalForClass(RISCV::VMRegClass, VT.
SimpleTy))
23932 return std::make_pair(VReg, &RISCV::VMRegClass);
23933 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, VT.
SimpleTy))
23934 return std::make_pair(VReg, &RISCV::VRRegClass);
23935 for (
const auto *RC :
23936 {&RISCV::VRM2RegClass, &RISCV::VRM4RegClass, &RISCV::VRM8RegClass}) {
23937 if (
TRI->isTypeLegalForClass(*RC, VT.
SimpleTy)) {
23938 VReg =
TRI->getMatchingSuperReg(VReg, RISCV::sub_vrm1_0, RC);
23939 return std::make_pair(VReg, RC);
23945 std::pair<Register, const TargetRegisterClass *> Res =
23951 if (Res.second == &RISCV::GPRF16RegClass ||
23952 Res.second == &RISCV::GPRF32RegClass ||
23953 Res.second == &RISCV::GPRPairRegClass)
23954 return std::make_pair(Res.first, &RISCV::GPRRegClass);
23962 if (ConstraintCode.
size() == 1) {
23963 switch (ConstraintCode[0]) {
23978 if (Constraint.
size() == 1) {
23979 switch (Constraint[0]) {
23986 Subtarget.getXLenVT()));
24017 if (Subtarget.hasStdExtZtso()) {
24019 return Builder.CreateFence(Ord);
24024 return Builder.CreateFence(Ord);
24033 if (Subtarget.hasStdExtZtso()) {
24035 return Builder.CreateFence(Ord);
24041 if (Subtarget.enableTrailingSeqCstFence() &&
isa<StoreInst>(Inst) &&
24060 if (Subtarget.hasForcedAtomics())
24065 if (Subtarget.hasStdExtZacas() &&
24066 (
Size >= 32 || Subtarget.hasStdExtZabha()))
24072 if (
Size < 32 && !Subtarget.hasStdExtZabha())
24084 return Intrinsic::riscv_masked_atomicrmw_xchg;
24086 return Intrinsic::riscv_masked_atomicrmw_add;
24088 return Intrinsic::riscv_masked_atomicrmw_sub;
24090 return Intrinsic::riscv_masked_atomicrmw_nand;
24092 return Intrinsic::riscv_masked_atomicrmw_max;
24094 return Intrinsic::riscv_masked_atomicrmw_min;
24096 return Intrinsic::riscv_masked_atomicrmw_umax;
24098 return Intrinsic::riscv_masked_atomicrmw_umin;
24114 Builder.CreateNot(Mask,
"Inv_Mask"),
24121 unsigned XLen = Subtarget.getXLen();
24124 Type *Tys[] = {Builder.getIntNTy(XLen), AlignedAddr->
getType()};
24130 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
24131 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
24132 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
24145 unsigned ValWidth =
24148 Builder.CreateSub(Builder.getIntN(XLen, XLen - ValWidth), ShiftAmt);
24149 Result = Builder.CreateCall(LrwOpScwLoop,
24150 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
24153 Builder.CreateCall(LrwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
24157 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
24165 if (Subtarget.hasForcedAtomics())
24169 if (!(Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas()) &&
24178 unsigned XLen = Subtarget.getXLen();
24179 Value *Ordering = Builder.getIntN(XLen,
static_cast<uint64_t>(Ord));
24180 Intrinsic::ID CmpXchgIntrID = Intrinsic::riscv_masked_cmpxchg;
24182 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
24183 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
24184 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
24186 Type *Tys[] = {Builder.getIntNTy(XLen), AlignedAddr->
getType()};
24187 Value *Result = Builder.CreateIntrinsic(
24188 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, Ordering});
24190 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
24195 EVT DataVT)
const {
24211 return Subtarget.hasStdExtZfhmin();
24213 return Subtarget.hasStdExtF();
24215 return Subtarget.hasStdExtD();
24245 assert(Subtarget.getRealMinVLen() >= 64 &&
"zve32* unsupported");
24247 "RVVBitsPerBlock changed, audit needed");
24256 if (!Subtarget.hasVendorXTHeadMemIdx())
24262 Base =
Op->getOperand(0);
24264 int64_t RHSC = RHS->getSExtValue();
24270 bool isLegalIndexedOffset =
false;
24271 for (
unsigned i = 0; i < 4; i++)
24272 if (
isInt<5>(RHSC >> i) && ((RHSC % (1LL << i)) == 0)) {
24273 isLegalIndexedOffset =
true;
24277 if (!isLegalIndexedOffset)
24294 VT = LD->getMemoryVT();
24295 Ptr = LD->getBasePtr();
24297 VT = ST->getMemoryVT();
24298 Ptr = ST->getBasePtr();
24314 if (Subtarget.hasVendorXCVmem() && !Subtarget.is64Bit()) {
24319 Base = LS->getBasePtr();
24323 if (
Base ==
Op->getOperand(0))
24325 else if (
Base ==
Op->getOperand(1))
24337 VT = LD->getMemoryVT();
24338 Ptr = LD->getBasePtr();
24340 VT = ST->getMemoryVT();
24341 Ptr = ST->getBasePtr();
24365 return VT.
isVector() ? Subtarget.hasVInstructionsF16()
24366 : Subtarget.hasStdExtZfhOrZhinx();
24368 return Subtarget.hasStdExtFOrZfinx();
24370 return Subtarget.hasStdExtDOrZdinx();
24384 const Constant *PersonalityFn)
const {
24389 const Constant *PersonalityFn)
const {
24396 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
24397 Type.getSizeInBits() < Subtarget.getXLen()))
24404 bool IsSigned)
const {
24405 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
24419 const bool HasZmmul = Subtarget.hasStdExtZmmul();
24424 const APInt &Imm = ConstNode->getAPIntValue();
24427 if (Subtarget.hasVendorXqciac() && Imm.isSignedIntN(12))
24431 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
24432 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
24436 if (Subtarget.hasShlAdd(3) && !Imm.isSignedIntN(12) &&
24437 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
24438 (Imm - 8).isPowerOf2()))
24443 if (!Imm.isSignedIntN(12) && Imm.countr_zero() < 12 &&
24444 ConstNode->hasOneUse()) {
24445 APInt ImmS = Imm.ashr(Imm.countr_zero());
24446 if ((ImmS + 1).isPowerOf2() || (ImmS - 1).isPowerOf2() ||
24447 (1 - ImmS).isPowerOf2())
24470 if (C1.
isSignedIntN(12) && !(C1 * C2).isSignedIntN(12))
24479 unsigned *
Fast)
const {
24482 *
Fast = Subtarget.enableUnalignedScalarMem();
24483 return Subtarget.enableUnalignedScalarMem();
24499 *
Fast = Subtarget.enableUnalignedVectorMem();
24500 return Subtarget.enableUnalignedVectorMem();
24505 const AttributeList &FuncAttributes)
const {
24506 if (!Subtarget.hasVInstructions())
24509 if (FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat))
24521 const unsigned MinVLenInBytes =
24522 std::min(Subtarget.getRealMinVLen() / 8, 1024U);
24524 if (
Op.size() < MinVLenInBytes)
24539 MVT PreferredVT = (
Op.isMemset() && !
Op.isZeroMemset()) ? MVT::i8 : ELenVT;
24543 if (PreferredVT != MVT::i8 && !Subtarget.enableUnalignedVectorMem()) {
24545 if (
Op.isFixedDstAlign())
24546 RequiredAlign = std::min(RequiredAlign,
Op.getDstAlign());
24548 RequiredAlign = std::min(RequiredAlign,
Op.getSrcAlign());
24556 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
24557 bool IsABIRegCopy = CC.has_value();
24560 MVT PairVT = Subtarget.is64Bit() ? MVT::i128 : MVT::i64;
24561 if ((ValueVT == PairVT ||
24562 (!Subtarget.is64Bit() && Subtarget.hasStdExtZdinx() &&
24563 ValueVT == MVT::f64)) &&
24564 NumParts == 1 && PartVT == MVT::Untyped) {
24566 MVT XLenVT = Subtarget.getXLenVT();
24567 if (ValueVT == MVT::f64)
24572 Parts[0] = DAG.
getNode(RISCVISD::BuildGPRPair,
DL, PartVT,
Lo,
Hi);
24576 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
24577 PartVT == MVT::f32) {
24580 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::i16, Val);
24584 Val = DAG.
getNode(ISD::BITCAST,
DL, PartVT, Val);
24592 [[maybe_unused]]
unsigned ValLMUL =
24596 [[maybe_unused]]
unsigned PartLMUL =
24599 assert(ValNF == PartNF && ValLMUL == PartLMUL &&
24600 "RISC-V vector tuple type only accepts same register class type "
24621 if (PartVTBitSize % ValueVTBitSize == 0) {
24622 assert(PartVTBitSize >= ValueVTBitSize);
24629 if (ValueEltVT != PartEltVT) {
24630 if (PartVTBitSize > ValueVTBitSize) {
24632 assert(
Count != 0 &&
"The number of element should not be zero.");
24633 EVT SameEltTypeVT =
24637 Val = DAG.
getNode(ISD::BITCAST,
DL, PartVT, Val);
24651 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
24652 bool IsABIRegCopy = CC.has_value();
24654 MVT PairVT = Subtarget.is64Bit() ? MVT::i128 : MVT::i64;
24655 if ((ValueVT == PairVT ||
24656 (!Subtarget.is64Bit() && Subtarget.hasStdExtZdinx() &&
24657 ValueVT == MVT::f64)) &&
24658 NumParts == 1 && PartVT == MVT::Untyped) {
24660 MVT XLenVT = Subtarget.getXLenVT();
24669 if (ValueVT == MVT::f64)
24674 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
24675 PartVT == MVT::f32) {
24679 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::i32, Val);
24681 Val = DAG.
getNode(ISD::BITCAST,
DL, ValueVT, Val);
24697 if (PartVTBitSize % ValueVTBitSize == 0) {
24698 assert(PartVTBitSize >= ValueVTBitSize);
24699 EVT SameEltTypeVT = ValueVT;
24706 if (ValueEltVT != PartEltVT) {
24708 assert(
Count != 0 &&
"The number of element should not be zero.");
24711 Val = DAG.
getNode(ISD::BITCAST,
DL, SameEltTypeVT, Val);
24727 bool OptSize = Attr.hasFnAttr(Attribute::MinSize);
24734 unsigned Opc =
N->getOpcode();
24743 M, Intrinsic::thread_pointer, IRB.
getPtrTy());
24751 if (Subtarget.isTargetFuchsia())
24757 if (Subtarget.isTargetAndroid())
24762 if (M->getStackProtectorGuard() ==
"tls") {
24764 int Offset = M->getStackProtectorGuardOffset();
24772 Align Alignment)
const {
24773 if (!Subtarget.hasVInstructions())
24777 if (DataType.isFixedLengthVector() && !Subtarget.useRVVForFixedLengthVectors())
24784 if (!Subtarget.enableUnalignedVectorMem() &&
24796 "Invalid call instruction for a KCFI check");
24798 MBBI->getOpcode()));
24801 Target.setIsRenamable(
false);
24809#define GET_REGISTER_MATCHER
24810#include "RISCVGenAsmMatcher.inc"
24821 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
24822 if (!ReservedRegs.
test(Reg) && !Subtarget.isRegisterReservedByUser(Reg))
24830 const MDNode *NontemporalInfo =
I.getMetadata(LLVMContext::MD_nontemporal);
24832 if (NontemporalInfo ==
nullptr)
24840 int NontemporalLevel = 5;
24841 const MDNode *RISCVNontemporalInfo =
24842 I.getMetadata(
"riscv-nontemporal-domain");
24843 if (RISCVNontemporalInfo !=
nullptr)
24850 assert((1 <= NontemporalLevel && NontemporalLevel <= 5) &&
24851 "RISC-V target doesn't support this non-temporal domain.");
24853 NontemporalLevel -= 2;
24855 if (NontemporalLevel & 0b1)
24857 if (NontemporalLevel & 0b10)
24870 return TargetFlags;
24883 return Subtarget.hasStdExtZvbb();
24888 return Subtarget.hasCPOPLike() && (VT == MVT::i32 || VT == MVT::i64);
24898 if (Subtarget.hasStdExtZalasr()) {
24899 if (Subtarget.hasStdExtZtso()) {
24929 if (
Op == Instruction::Add ||
Op == Instruction::Sub ||
24930 Op == Instruction::And ||
Op == Instruction::Or ||
24931 Op == Instruction::Xor ||
Op == Instruction::InsertElement ||
24932 Op == Instruction::ShuffleVector ||
Op == Instruction::Load ||
24933 Op == Instruction::Freeze ||
Op == Instruction::Store)
24938 if (RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(
II->getIntrinsicID()))
24951 if (AI->getAllocatedType()->isScalableTy())
24959RISCVTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
24967 if (!Subtarget.hasShortForwardBranchOpt())
24969 EVT VT =
N->getValueType(0);
24970 if (!(VT == MVT::i32 || (VT == MVT::i64 && Subtarget.
is64Bit())))
24974 if (Divisor.
sgt(2048) || Divisor.
slt(-2048))
24979bool RISCVTargetLowering::shouldFoldSelectWithSingleBitTest(
24980 EVT VT,
const APInt &AndMask)
const {
24981 if (Subtarget.
hasCZEROLike() || Subtarget.hasVendorXTHeadCondMov())
24987 return Subtarget.getMinimumJumpTableEntries();
24994 if (Subtarget.hasStdExtZicfilp()) {
25001 return DAG.
getNode(RISCVISD::SW_GUARDED_BRIND, dl, MVT::Other, Chain, Addr);
25018std::pair<const TargetRegisterClass *, uint8_t>
25038#define GET_RISCVVIntrinsicsTable_IMPL
25039#include "RISCVGenSearchableTables.inc"
25054 Align StackAlign)
const {
25058 unsigned StackProbeSize =
25062 return StackProbeSize ? StackProbeSize : StackAlign.
value();
25079 EVT VT =
Op.getValueType();
25090 Chain = DAG.
getNode(RISCVISD::PROBED_ALLOCA, dl, MVT::Other, Chain, SP);
25100 Register TargetReg =
MI.getOperand(0).getReg();
25103 bool IsRV64 = Subtarget.is64Bit();
25104 Align StackAlign = Subtarget.getFrameLowering()->getStackAlign();
25111 MF.
insert(MBBInsertPoint, LoopTestMBB);
25113 MF.
insert(MBBInsertPoint, ExitMBB);
25129 TII->get(IsRV64 ? RISCV::SD : RISCV::SW))
25150 MBB->addSuccessor(LoopTestMBB);
25152 MI.eraseFromParent();
25154 return ExitMBB->
begin()->getParent();
25158 if (Subtarget.hasStdExtFOrZfinx()) {
25159 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 cl::opt< int > FPImmCost(DEBUG_TYPE "-fpimm-cost", cl::Hidden, cl::desc("Give the maximum number of instructions that we will " "use for creating a floating-point immediate value"), cl::init(2))
static SDValue lowerScalarSplat(SDValue Passthru, SDValue Scalar, SDValue VL, MVT VT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isAlternating(const std::array< std::pair< int, int >, 2 > &SrcInfo, ArrayRef< int > Mask, unsigned Factor, bool RequiredPolarity)
static const RISCV::RISCVMaskedPseudoInfo * lookupMaskedIntrinsic(uint16_t MCOpcode, RISCVVType::VLMUL LMul, unsigned SEW)
static SDValue expandMul(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue performVWADDSUBW_VLCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static bool matchIndexAsWiderOp(EVT VT, SDValue Index, SDValue Mask, Align BaseAlign, const RISCVSubtarget &ST)
Match the index of a gather or scatter operation as an operation with twice the element width and hal...
static SDValue combineOp_VLToVWOp_VL(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
Combine a binary or FMA operation to its equivalent VW or VW_W form.
static SDValue combineVFMADD_VLWithVFNEG_VL(SDNode *N, SelectionDAG &DAG)
static SDValue combineOrOfCZERO(SDNode *N, SDValue N0, SDValue N1, SelectionDAG &DAG)
static SDValue useInversedSetcc(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static cl::opt< bool > ReassocShlAddiAdd("reassoc-shl-addi-add", cl::Hidden, cl::desc("Swap add and addi in cases where the add may " "be combined with a shift"), cl::init(true))
static SDValue lowerDisjointIndicesShuffle(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Given a shuffle where the indices are disjoint between the two sources, e.g.:
static SDValue combineVWADDSUBWSelect(SDNode *N, SelectionDAG &DAG)
static MachineBasicBlock * EmitLoweredCascadedSelect(MachineInstr &First, MachineInstr &Second, MachineBasicBlock *ThisMBB, const RISCVSubtarget &Subtarget)
static SDValue performINSERT_VECTOR_ELTCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue lowerFABSorFNEG(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerFMAXIMUM_FMINIMUM(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue foldReduceOperandViaVQDOT(SDValue InVec, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue reverseZExtICmpCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue SplitStrictFPVectorOp(SDValue Op, SelectionDAG &DAG)
static 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 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 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 TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isTargetExtTy() const
Return true if this is a target extension type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
A Use represents the edge between a Value definition and its users.
User * getUser() const
Returns the User that contains this Use.
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
std::pair< iterator, bool > insert(const ValueT &V)
constexpr bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
constexpr ScalarTy getFixedValue() const
static constexpr bool isKnownLE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
constexpr LeafTy multiplyCoefficientBy(ScalarTy RHS) const
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
constexpr bool isZero() const
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ RISCV_VectorCall
Calling convention used for RISC-V V-extension.
@ PreserveMost
Used for runtime calls that preserves most registers.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ SPIR_KERNEL
Used for SPIR kernel functions.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
@ GRAAL
Used by GraalVM. Two additional registers are reserved.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI bool isConstantSplatVectorAllOnes(const SDNode *N, bool BuildVectorOnly=false)
Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where all of the elements are ~0 ...
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ ADD
Simple integer binary arithmetic operators.
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ FADD
Simple binary floating point operators.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ STRICT_FSQRT
Constrained versions of libm-equivalent floating point intrinsics.
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ SIGN_EXTEND
Conversion operators.
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ CTTZ_ZERO_UNDEF
Bit counting operators with an undefined result for zero inputs.
@ VECTOR_INTERLEAVE
VECTOR_INTERLEAVE(VEC1, VEC2, ...) - Returns N vectors from N input vectors, where N is the factor to...
@ STEP_VECTOR
STEP_VECTOR(IMM) - Returns a scalable vector whose lanes are comprised of a linear sequence of unsign...
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ UNDEF
UNDEF - An undefined node.
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
@ GET_ROUNDING
Returns current rounding mode: -1 Undefined 0 Round to 0 1 Round to nearest, ties to even 2 Round to ...
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ SSHLSAT
RESULT = [US]SHLSAT(LHS, RHS) - Perform saturation left shift.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ VECTOR_REVERSE
VECTOR_REVERSE(VECTOR) - Returns a vector, of the same type as VECTOR, whose elements are shuffled us...
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ STRICT_SINT_TO_FP
STRICT_[US]INT_TO_FP - Convert a signed or unsigned integer to a floating point value.
@ EH_DWARF_CFA
EH_DWARF_CFA - This node represents the pointer to the DWARF Canonical Frame Address (CFA),...
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
@ STRICT_FADD
Constrained versions of the binary floating point operators.
@ SPLAT_VECTOR_PARTS
SPLAT_VECTOR_PARTS(SCALAR1, SCALAR2, ...) - Returns a vector with the scalar values joined together a...
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ VECTOR_SPLICE
VECTOR_SPLICE(VEC1, VEC2, IMM) - Returns a subvector of the same type as VEC1/VEC2 from CONCAT_VECTOR...
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ VECTOR_COMPRESS
VECTOR_COMPRESS(Vec, Mask, Passthru) consecutively place vector elements based on mask e....
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ VECTOR_DEINTERLEAVE
VECTOR_DEINTERLEAVE(VEC1, VEC2, ...) - Returns N vectors from N input vectors, where N is the factor ...
@ TRUNCATE_SSAT_S
TRUNCATE_[SU]SAT_[SU] - Truncate for saturated operand [SU] located in middle, prefix for SAT means i...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
LLVM_ABI bool isBuildVectorOfConstantSDNodes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR node of all ConstantSDNode or undef.
bool isNormalStore(const SDNode *N)
Returns true if the specified node is a non-truncating and unindexed store.
bool isExtOpcode(unsigned Opcode)
LLVM_ABI bool isConstantSplatVectorAllZeros(const SDNode *N, bool BuildVectorOnly=false)
Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where all of the elements are 0 o...
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
LLVM_ABI std::optional< unsigned > getVPMaskIdx(unsigned Opcode)
The operand position of the vector mask.
LLVM_ABI std::optional< unsigned > getVPExplicitVectorLengthIdx(unsigned Opcode)
The operand position of the explicit vector length parameter.
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
MemIndexType
MemIndexType enum - This enum defines how to interpret MGATHER/SCATTER's index parameter when calcula...
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
LLVM_ABI bool isBuildVectorOfConstantFPSDNodes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR node of all ConstantFPSDNode or undef.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LLVM_ABI bool isBuildVectorAllOnes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are ~0 or undef.
LLVM_ABI NodeType getVecReduceBaseOpcode(unsigned VecReduceOpcode)
Get underlying scalar opcode for VECREDUCE opcode.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
LLVM_ABI bool isVPOpcode(unsigned Opcode)
Whether this is a vector-predicated Opcode.
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
bool isIntEqualitySetCC(CondCode Code)
Return true if this is a setcc instruction that performs an equality comparison when used with intege...
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
@ Bitcast
Perform the operation on a different, but equivalently sized type.
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
CastInst_match< OpTy, TruncInst > m_Trunc(const OpTy &Op)
Matches Trunc.
BinaryOp_match< LHS, RHS, Instruction::Xor > m_Xor(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::FMul > m_FMul(const LHS &L, const RHS &R)
TwoOps_match< Val_t, Idx_t, Instruction::ExtractElement > m_ExtractElt(const Val_t &Val, const Idx_t &Idx)
Matches ExtractElementInst.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
deferredval_ty< Value > m_Deferred(Value *const &V)
Like m_Specific(), but works if the specific value to match is determined as part of the same match()...
match_combine_or< BinaryOp_match< LHS, RHS, Instruction::Add >, DisjointOr_match< LHS, RHS > > m_AddLike(const LHS &L, const RHS &R)
Match either "add" or "or disjoint".
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
FNeg_match< OpTy > m_FNeg(const OpTy &X)
Match 'fneg X' as 'fsub -0.0, X'.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
ThreeOps_match< Val_t, Elt_t, Idx_t, Instruction::InsertElement > m_InsertElt(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx)
Matches InsertElementInst.
unsigned getBrCond(CondCode CC, unsigned SelectOpc=0)
static RISCVVType::VLMUL getLMul(uint64_t TSFlags)
static int getFRMOpNum(const MCInstrDesc &Desc)
static unsigned getSEWOpNum(const MCInstrDesc &Desc)
int getLoadFPImm(APFloat FPImm)
getLoadFPImm - Return a 5-bit binary encoding of the floating-point immediate value.
InstSeq generateInstSeq(int64_t Val, const MCSubtargetInfo &STI)
int getIntMatCost(const APInt &Val, unsigned Size, const MCSubtargetInfo &STI, bool CompressionCost, bool FreeZeroes)
InstSeq generateTwoRegInstSeq(int64_t Val, const MCSubtargetInfo &STI, unsigned &ShiftAmt, unsigned &AddOpc)
SmallVector< Inst, 8 > InstSeq
static VLMUL encodeLMUL(unsigned LMUL, bool Fractional)
static unsigned decodeVSEW(unsigned VSEW)
@ TAIL_UNDISTURBED_MASK_UNDISTURBED
LLVM_ABI std::pair< unsigned, bool > decodeVLMUL(VLMUL VLMul)
static unsigned encodeSEW(unsigned SEW)
static constexpr unsigned FPMASK_Negative_Zero
static constexpr unsigned FPMASK_Positive_Subnormal
static constexpr unsigned FPMASK_Positive_Normal
static constexpr unsigned FPMASK_Negative_Subnormal
static constexpr unsigned FPMASK_Negative_Normal
static constexpr unsigned FPMASK_Positive_Infinity
static constexpr unsigned FPMASK_Negative_Infinity
static constexpr unsigned FPMASK_Quiet_NaN
ArrayRef< MCPhysReg > getArgGPRs(const RISCVABI::ABI ABI)
static constexpr unsigned FPMASK_Signaling_NaN
static constexpr unsigned FPMASK_Positive_Zero
static constexpr unsigned RVVBitsPerBlock
static constexpr unsigned RVVBytesPerBlock
LLVM_ABI Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
@ Kill
The last use of a register.
BinaryOpc_match< LHS, RHS > m_Srl(const LHS &L, const RHS &R)
Or< Preds... > m_AnyOf(const Preds &...preds)
auto m_Node(unsigned Opcode, const OpndPreds &...preds)
bool sd_match(SDNode *N, const SelectionDAG *DAG, Pattern &&P)
ConstantInt_match m_ConstInt()
Match any integer constants or splat of an integer constant.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
@ System
Synchronized with respect to all concurrently executing threads.
initializer< Ty > init(const Ty &Val)
uint32_t read32le(const void *P)
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
FunctionAddr VTableAddr Value
bool CC_RISCV_FastCC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
bool CC_RISCV_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static const MachineMemOperand::Flags MONontemporalBit1
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
MCCodeEmitter * createRISCVMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
static const MachineMemOperand::Flags MONontemporalBit0
bool RISCVCCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
RISCVCCAssignFn - This target-specific function extends the default CCValAssign with additional infor...
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI bool widenShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Try to transform a shuffle mask by replacing elements with the scaled index for an equivalent mask of...
LLVM_ABI Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
LLVM_ABI bool isNullOrNullSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndefs=false)
Return true if the value is a constant 0 integer or a splatted vector of a constant 0 integer (with n...
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
bool isReleaseOrStronger(AtomicOrdering AO)
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere.
constexpr bool has_single_bit(T Value) noexcept
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
FunctionAddr VTableAddr Count
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
bool CC_RISCV(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI bool isOneOrOneSplat(SDValue V, bool AllowUndefs=false)
Return true if the value is a constant 1 integer or a splatted vector of a constant 1 integer (with n...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
auto drop_end(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the last N elements excluded.
AtomicOrdering
Atomic ordering for LLVM's memory model.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
LLVM_ABI void narrowShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Replace each shuffle mask index with the scaled sequential indices for an equivalent mask of narrowed...
LLVM_ABI bool isMaskedSlidePair(ArrayRef< int > Mask, int NumElts, std::array< std::pair< int, int >, 2 > &SrcInfo)
Does this shuffle mask represent either one slide shuffle or a pair of two slide shuffles,...
@ Xor
Bitwise or logical XOR of integers.
@ SMin
Signed integer min implemented in terms of select(cmp()).
@ Sub
Subtraction of integers.
unsigned getKillRegState(bool B)
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
FunctionAddr VTableAddr Next
DWARFExpression::Operation Op
RoundingMode
Rounding mode.
@ TowardZero
roundTowardZero.
@ NearestTiesToEven
roundTiesToEven.
@ TowardPositive
roundTowardPositive.
@ NearestTiesToAway
roundTiesToAway.
@ TowardNegative
roundTowardNegative.
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
bool isAcquireOrStronger(AtomicOrdering AO)
constexpr unsigned BitWidth
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
LLVM_ABI void processShuffleMasks(ArrayRef< int > Mask, unsigned NumOfSrcRegs, unsigned NumOfDestRegs, unsigned NumOfUsedRegs, function_ref< void()> NoInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned)> SingleInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned, bool)> ManyInputsAction)
Splits and processes shuffle mask depending on the number of input and output registers.
unsigned Log2(Align A)
Returns the log2 of the alignment.
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
LLVM_ABI bool isNeutralConstant(unsigned Opc, SDNodeFlags Flags, SDValue V, unsigned OperandNo)
Returns true if V is a neutral element of Opc with Flags.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
auto mask(ShuffFunc S, unsigned Length, OptArgs... args) -> MaskT
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
static constexpr roundingMode rmNearestTiesToEven
static LLVM_ABI unsigned int semanticsPrecision(const fltSemantics &)
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint64_t value() const
This is a hole in the type system and should not be abused.
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
uint64_t getScalarStoreSize() const
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
bool isByteSized() const
Return true if the bit size is a multiple of 8.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
unsigned getRISCVVectorTupleNumFields() const
Given a RISCV vector tuple type, return the num_fields.
uint64_t getScalarSizeInBits() const
EVT getHalfSizedIntegerVT(LLVMContext &Context) const
Finds the smallest simple value type that is greater than or equal to half the width of this EVT.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
bool isRISCVVectorTuple() const
Return true if this is a vector value type.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isFixedLengthVector() const
EVT getRoundIntegerType(LLVMContext &Context) const
Rounds the bit-width of the given integer EVT up to the nearest power of two (and at least to eight),...
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
bool bitsGE(EVT VT) const
Return true if this has no less bits than VT.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
EVT changeVectorElementType(EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
bool isInteger() const
Return true if this is an integer or a vector integer type.
static LLVM_ABI KnownBits ashr(const KnownBits &LHS, const KnownBits &RHS, bool ShAmtNonZero=false, bool Exact=false)
Compute known bits for ashr(LHS, RHS).
static LLVM_ABI KnownBits urem(const KnownBits &LHS, const KnownBits &RHS)
Compute known bits for urem(LHS, RHS).
bool isUnknown() const
Returns true if we don't know any bits.
unsigned countMaxTrailingZeros() const
Returns the maximum number of trailing zero bits possible.
KnownBits trunc(unsigned BitWidth) const
Return known bits for a truncation of the value we're tracking.
unsigned getBitWidth() const
Get the bit width of this value.
KnownBits zext(unsigned BitWidth) const
Return known bits for a zero extension of the value we're tracking.
void resetAll()
Resets the known state of all bits.
static LLVM_ABI KnownBits lshr(const KnownBits &LHS, const KnownBits &RHS, bool ShAmtNonZero=false, bool Exact=false)
Compute known bits for lshr(LHS, RHS).
unsigned countMaxActiveBits() const
Returns the maximum number of bits needed to represent all possible unsigned values with these known ...
KnownBits intersectWith(const KnownBits &RHS) const
Returns KnownBits information that is known to be true for both this and RHS.
KnownBits sext(unsigned BitWidth) const
Return known bits for a sign extension of the value we're tracking.
static 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)