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;
4571 if (EVecEltVT != ContainerEltVT)
4620 Vec = getVSlide(ContainerVT, DAG.
getUNDEF(ContainerVT), Vec,
Offset, Mask,
4627 Opcode = SlideUp ? RISCVISD::VFSLIDE1UP_VL : RISCVISD::VFSLIDE1DOWN_VL;
4629 Opcode = SlideUp ? RISCVISD::VSLIDE1UP_VL : RISCVISD::VSLIDE1DOWN_VL;
4638 Vec = getVSlide(ContainerVT, DAG.
getUNDEF(ContainerVT), Vec,
Offset, Mask,
4654 if ((LoC >> 31) == HiC)
4655 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4667 auto InterVec = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, InterVT,
4669 return DAG.
getNode(ISD::BITCAST,
DL, VT, InterVec);
4676 Hi.getConstantOperandVal(1) == 31)
4677 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4682 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4685 return DAG.
getNode(RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL,
DL, VT, Passthru,
Lo,
4695 assert(Scalar.getValueType() == MVT::i64 &&
"Unexpected VT!");
4707 bool HasPassthru = Passthru && !Passthru.
isUndef();
4708 if (!HasPassthru && !Passthru)
4715 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
4716 EltVT == MVT::bf16) {
4717 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4718 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
4719 Scalar = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Scalar);
4721 Scalar = DAG.
getNode(ISD::BITCAST,
DL, MVT::i16, Scalar);
4723 Passthru = DAG.
getNode(ISD::BITCAST,
DL, IVT, Passthru);
4728 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL, VT, Passthru, Scalar, VL);
4732 if (Scalar.getValueType().bitsLE(XLenVT)) {
4739 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4740 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru, Scalar, VL);
4743 assert(XLenVT == MVT::i32 && Scalar.getValueType() == MVT::i64 &&
4744 "Unexpected scalar for splat lowering!");
4747 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, VT, Passthru,
4773 MVT ExtractedContainerVT = ExtractedVT;
4776 DAG, ExtractedContainerVT, Subtarget);
4778 ExtractedVal, DAG, Subtarget);
4780 if (ExtractedContainerVT.
bitsLE(VT))
4792 if (!Scalar.getValueType().bitsLE(XLenVT))
4795 VT,
DL, DAG, Subtarget);
4803 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4844 Src && Src.
getValueType().getVectorNumElements() == (NumElts * 2))
4861 !Subtarget.hasVendorXRivosVizip())
4864 int Size = Mask.size();
4866 assert(
Size == (
int)NumElts &&
"Unexpected mask size");
4872 EvenSrc = StartIndexes[0];
4873 OddSrc = StartIndexes[1];
4876 if (EvenSrc != 0 && OddSrc != 0)
4886 int HalfNumElts = NumElts / 2;
4887 return ((EvenSrc % HalfNumElts) == 0) && ((OddSrc % HalfNumElts) == 0);
4892 std::array<std::pair<int, int>, 2> &SrcInfo) {
4897 if (SrcInfo[0].second == 0 && SrcInfo[1].second == 0)
4901 if ((SrcInfo[0].second > 0 && SrcInfo[1].second < 0) ||
4902 SrcInfo[1].second == 0)
4904 assert(SrcInfo[0].first != -1 &&
"Must find one slide");
4912 if (SrcInfo[1].first == -1)
4914 return SrcInfo[0].second < 0 && SrcInfo[1].second > 0 &&
4915 SrcInfo[1].second - SrcInfo[0].second == (int)NumElts;
4920 bool RequiredPolarity) {
4921 int NumElts = Mask.size();
4922 for (
const auto &[Idx, M] :
enumerate(Mask)) {
4925 int Src = M >= NumElts;
4926 int Diff = (int)Idx - (M % NumElts);
4927 bool C = Src == SrcInfo[1].first && Diff == SrcInfo[1].second;
4928 assert(
C != (Src == SrcInfo[0].first && Diff == SrcInfo[0].second) &&
4929 "Must match exactly one of the two slides");
4930 if (RequiredPolarity != (
C == (Idx / Factor) % 2))
4941static bool isZipEven(
const std::array<std::pair<int, int>, 2> &SrcInfo,
4943 Factor = SrcInfo[1].second;
4945 Mask.size() % Factor == 0 &&
4956static bool isZipOdd(
const std::array<std::pair<int, int>, 2> &SrcInfo,
4958 Factor = -SrcInfo[1].second;
4960 Mask.size() % Factor == 0 &&
4973 ElementCount SrcEC = Src.getValueType().getVectorElementCount();
4980 unsigned Shift = Index * EltBits;
5005 std::optional<int> SplatIdx;
5007 if (M == -1 ||
I == (
unsigned)M)
5009 if (SplatIdx && *SplatIdx != M)
5018 for (
int MaskIndex : Mask) {
5019 bool SelectMaskVal = MaskIndex == *SplatIdx;
5022 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
5047 auto findNonEXTRACT_SUBVECTORParent =
5048 [](
SDValue Parent) -> std::pair<SDValue, uint64_t> {
5053 Parent.getOperand(0).getSimpleValueType().isFixedLengthVector()) {
5054 Offset += Parent.getConstantOperandVal(1);
5055 Parent = Parent.getOperand(0);
5057 return std::make_pair(Parent,
Offset);
5060 auto [V1Src, V1IndexOffset] = findNonEXTRACT_SUBVECTORParent(V1);
5061 auto [V2Src, V2IndexOffset] = findNonEXTRACT_SUBVECTORParent(V2);
5070 for (
size_t i = 0; i != NewMask.
size(); ++i) {
5071 if (NewMask[i] == -1)
5074 if (
static_cast<size_t>(NewMask[i]) < NewMask.
size()) {
5075 NewMask[i] = NewMask[i] + V1IndexOffset;
5079 NewMask[i] = NewMask[i] - NewMask.
size() + V2IndexOffset;
5085 if (NewMask[0] <= 0)
5089 for (
unsigned i = 1; i != NewMask.
size(); ++i)
5090 if (NewMask[i - 1] + 1 != NewMask[i])
5094 MVT SrcVT = Src.getSimpleValueType();
5123 int NumSubElts, Index;
5128 bool OpsSwapped = Mask[Index] < (int)NumElts;
5129 SDValue InPlace = OpsSwapped ? V2 : V1;
5130 SDValue ToInsert = OpsSwapped ? V1 : V2;
5141 if (NumSubElts + Index >= (
int)NumElts)
5152 Res = DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, ContainerVT, InPlace, ToInsert,
5155 Res =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, InPlace, ToInsert,
5167 bool OpsSwapped =
false;
5182 const unsigned E = Mask.size() - ((
Offset > 0) ?
Offset : 0);
5183 for (
unsigned i = S; i !=
E; ++i)
5184 if (Mask[i] >= 0 && (
unsigned)Mask[i] !=
Base + i +
Offset)
5190 bool IsVSlidedown = isSlideMask(Mask, OpsSwapped ? 0 : NumElts, 1);
5191 if (!IsVSlidedown && !isSlideMask(Mask, OpsSwapped ? 0 : NumElts, -1))
5194 const int InsertIdx = Mask[IsVSlidedown ? (NumElts - 1) : 0];
5196 if (InsertIdx < 0 || InsertIdx / NumElts != (
unsigned)OpsSwapped)
5213 IsVSlidedown ? RISCVISD::VSLIDE1DOWN_VL : RISCVISD::VSLIDE1UP_VL,
DL,
5219 auto OpCode = IsVSlidedown ?
5220 (VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1DOWN_VL : RISCVISD::VSLIDE1DOWN_VL) :
5221 (VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1UP_VL : RISCVISD::VSLIDE1UP_VL);
5224 auto Vec = DAG.
getNode(OpCode,
DL, ContainerVT,
5227 Splat, TrueMask, VL);
5239 for (
unsigned i = 0; i < Mask.size(); i++)
5240 LaneIsUndef[i % Factor] &= (Mask[i] == -1);
5243 for (
unsigned i = 0; i < Factor; i++) {
5254 for (
unsigned i = 0; i < Mask.size() / Factor; i++) {
5255 unsigned j = i * Factor + Index;
5256 if (Mask[j] != -1 && (
unsigned)Mask[j] != i)
5265 assert(RISCVISD::RI_VZIPEVEN_VL ==
Opc || RISCVISD::RI_VZIPODD_VL ==
Opc ||
5266 RISCVISD::RI_VZIP2A_VL ==
Opc || RISCVISD::RI_VZIP2B_VL ==
Opc ||
5267 RISCVISD::RI_VUNZIP2A_VL ==
Opc || RISCVISD::RI_VUNZIP2B_VL ==
Opc);
5275 MVT ContainerVT = IntVT;
5282 MVT InnerVT = ContainerVT;
5286 (RISCVISD::RI_VUNZIP2A_VL ==
Opc || RISCVISD::RI_VUNZIP2B_VL ==
Opc)) {
5298 if (InnerVT.
bitsLT(ContainerVT))
5313 MVT VT = V.getSimpleValueType();
5328 EC.multiplyCoefficientBy(Factor));
5347 MVT VecContainerVT = VecVT;
5364 MVT WideContainerVT = WideVT;
5370 EvenV = DAG.
getBitcast(VecContainerVT, EvenV);
5377 if (Subtarget.hasStdExtZvbb()) {
5381 Interleaved = DAG.
getNode(RISCVISD::VWSLL_VL,
DL, WideContainerVT, OddV,
5382 OffsetVec, Passthru, Mask, VL);
5383 Interleaved = DAG.
getNode(RISCVISD::VWADDU_W_VL,
DL, WideContainerVT,
5384 Interleaved, EvenV, Passthru, Mask, VL);
5391 Interleaved = DAG.
getNode(RISCVISD::VWADDU_VL,
DL, WideContainerVT, EvenV,
5392 OddV, Passthru, Mask, VL);
5398 OddV, AllOnesVec, Passthru, Mask, VL);
5405 Interleaved = DAG.
getNode(RISCVISD::ADD_VL,
DL, WideContainerVT,
5406 Interleaved, OddsMul, Passthru, Mask, VL);
5413 Interleaved = DAG.
getBitcast(ResultContainerVT, Interleaved);
5459 if (ViaEltSize > NumElts)
5467 if (ViaEltSize > NumElts)
5473 if (ViaEltSize > NumElts)
5480 MVT &RotateVT,
unsigned &RotateAmt) {
5483 unsigned NumSubElts;
5485 NumElts, NumSubElts, RotateAmt))
5488 NumElts / NumSubElts);
5556 unsigned NumOfSrcRegs = NumElts / NumOpElts;
5557 unsigned NumOfDestRegs = NumElts / NumOpElts;
5566 Mask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs,
5567 [&]() {
Operands.emplace_back(); },
5568 [&](
ArrayRef<int> SrcSubMask,
unsigned SrcVecIdx,
unsigned DstVecIdx) {
5569 Operands.emplace_back().emplace_back(SrcVecIdx, UINT_MAX,
5572 [&](
ArrayRef<int> SrcSubMask,
unsigned Idx1,
unsigned Idx2,
bool NewReg) {
5577 assert(
Operands.size() == NumOfDestRegs &&
"Whole vector must be processed");
5582 unsigned NumShuffles = std::accumulate(
5589 for (const auto &P : Data) {
5590 unsigned Idx2 = std::get<1>(P);
5591 ArrayRef<int> Mask = std::get<2>(P);
5592 if (Idx2 != UINT_MAX)
5594 else if (ShuffleVectorInst::isIdentityMask(Mask, Mask.size()))
5599 if ((NumOfDestRegs > 2 && NumShuffles > NumOfDestRegs) ||
5600 (NumOfDestRegs <= 2 && NumShuffles >= 4))
5602 auto ExtractValue = [&, &DAG = DAG](
SDValue SrcVec,
unsigned ExtractIdx) {
5603 SDValue SubVec = DAG.getExtractSubvector(
DL, M1VT, SrcVec, ExtractIdx);
5607 auto PerformShuffle = [&, &DAG = DAG](
SDValue SubVec1,
SDValue SubVec2,
5609 SDValue SubVec = DAG.getVectorShuffle(OneRegVT,
DL, SubVec1, SubVec2, Mask);
5612 SDValue Vec = DAG.getUNDEF(ContainerVT);
5618 const auto &[Idx1, Idx2,
_] =
Data[
I];
5626 V = ExtractValue(Idx1 >= NumOfSrcRegs ? V2 : V1,
5627 (Idx1 % NumOfSrcRegs) * NumOpElts);
5628 if (Idx2 != UINT_MAX) {
5631 V = ExtractValue(Idx2 >= NumOfSrcRegs ? V2 : V1,
5632 (Idx2 % NumOfSrcRegs) * NumOpElts);
5636 for (
const auto &[Idx1, Idx2, Mask] :
Data) {
5638 SDValue V2 = Idx2 == UINT_MAX ? V1 : Values.
at(Idx2);
5639 V = PerformShuffle(V1, V2, Mask);
5643 unsigned InsertIdx =
I * NumOpElts;
5645 Vec = DAG.getInsertSubvector(
DL, Vec, V, InsertIdx);
5655 bool SawUndef =
false;
5656 for (
const auto &[Idx, M] :
enumerate(Mask)) {
5663 if (Idx > (
unsigned)M)
5696 for (
int Idx : Mask) {
5699 unsigned SrcIdx = Idx % Mask.size();
5700 int Src = (
uint32_t)Idx < Mask.size() ? 0 : 1;
5701 if (Srcs[SrcIdx] == -1)
5704 else if (Srcs[SrcIdx] != Src)
5710 for (
int Lane : Srcs) {
5723 for (
unsigned I = 0;
I < Mask.size();
I++) {
5727 NewMask[
I] = Mask[
I] % Mask.size();
5741 if ((M / Span) != (
int)(
I / Span))
5743 int SpanIdx =
I % Span;
5753 return all_of(Mask, [&](
const auto &Idx) {
return Idx == -1 || Idx < Span; });
5765 int SpanIdx =
I % Span;
5766 if (Mask[SpanIdx] != M)
5780 MVT VT =
Op.getSimpleValueType();
5788 if (ElementSize > 32)
5811 MVT VT =
Op.getSimpleValueType();
5839 auto [TrueMask, VL] = TrueMaskVL;
5854 V.getOperand(0).getSimpleValueType().getVectorNumElements();
5855 V = V.getOperand(
Offset / OpElements);
5885 MVT SplatVT = ContainerVT;
5888 if (SVT == MVT::bf16 ||
5889 (SVT == MVT::f16 && !Subtarget.hasStdExtZfh())) {
5898 V = DAG.
getLoad(SVT,
DL, Ld->getChain(), NewAddr,
5899 Ld->getPointerInfo().getWithOffset(
Offset),
5900 Ld->getBaseAlign(), Ld->getMemOperand()->
getFlags());
5903 Ld->getPointerInfo().getWithOffset(
Offset), SVT,
5905 Ld->getMemOperand()->getFlags());
5909 : RISCVISD::VMV_V_X_VL;
5917 assert(Lane < (
int)NumElts &&
"Unexpected lane!");
5920 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
5942 if (Subtarget.hasStdExtZvkb())
5958 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
5959 for (
unsigned Factor = 2; Factor <= MaxFactor; Factor <<= 1) {
5962 1 <
count_if(Mask, [](
int Idx) {
return Idx != -1; })) {
5966 [&Mask](
int Idx) {
return Idx < (int)Mask.size(); }) &&
5967 1 <
count_if(Mask, [&Mask](
int Idx) {
5968 return Idx >= (int)Mask.size();
5998 if (Subtarget.hasVendorXRivosVizip() &&
6000 1 <
count_if(Mask, [](
int Idx) {
return Idx != -1; })) {
6002 Index == 0 ? RISCVISD::RI_VUNZIP2A_VL : RISCVISD::RI_VUNZIP2B_VL;
6018 [&Mask](
int Idx) {
return Idx < (int)Mask.size(); }) &&
6020 [&Mask](
int Idx) {
return Idx >= (int)Mask.size(); })) {
6024 if (NumElts < MinVLMAX) {
6048 int EvenSrc, OddSrc;
6058 bool LaneIsUndef[2] = {
true,
true};
6059 for (
const auto &[Idx, M] :
enumerate(Mask))
6060 LaneIsUndef[Idx % 2] &= (M == -1);
6062 int Size = Mask.size();
6064 if (LaneIsUndef[0]) {
6067 assert(EvenSrc >= 0 &&
"Undef source?");
6068 EvenV = (EvenSrc /
Size) == 0 ? V1 : V2;
6072 if (LaneIsUndef[1]) {
6075 assert(OddSrc >= 0 &&
"Undef source?");
6076 OddV = (OddSrc /
Size) == 0 ? V1 : V2;
6082 if (Subtarget.hasVendorXRivosVizip()) {
6085 return lowerVZIP(RISCVISD::RI_VZIP2A_VL, EvenV, OddV,
DL, DAG, Subtarget);
6096 std::array<std::pair<int, int>, 2> SrcInfo;
6103 auto GetSourceFor = [&](
const std::pair<int, int> &
Info) {
6104 int SrcIdx =
Info.first;
6105 assert(SrcIdx == 0 || SrcIdx == 1);
6106 SDValue &Src = Sources[SrcIdx];
6108 SDValue SrcV = SrcIdx == 0 ? V1 : V2;
6113 auto GetSlide = [&](
const std::pair<int, int> &Src,
SDValue Mask,
6115 auto [TrueMask, VL] = TrueMaskVL;
6116 SDValue SrcV = GetSourceFor(Src);
6117 int SlideAmt = Src.second;
6118 if (SlideAmt == 0) {
6120 assert(Mask == TrueMask);
6127 return getVSlideup(DAG, Subtarget,
DL, ContainerVT, Passthru, SrcV,
6132 if (SrcInfo[1].first == -1) {
6134 Res = GetSlide(SrcInfo[0], TrueMask, Res);
6138 if (Subtarget.hasVendorXRivosVizip()) {
6139 bool TryWiden =
false;
6143 SDValue Src1 = SrcInfo[0].first == 0 ? V1 : V2;
6144 SDValue Src2 = SrcInfo[1].first == 0 ? V1 : V2;
6145 return lowerVZIP(RISCVISD::RI_VZIPEVEN_VL, Src1, Src2,
DL, DAG,
6150 if (
isZipOdd(SrcInfo, Mask, Factor)) {
6152 SDValue Src1 = SrcInfo[1].first == 0 ? V1 : V2;
6153 SDValue Src2 = SrcInfo[0].first == 0 ? V1 : V2;
6154 return lowerVZIP(RISCVISD::RI_VZIPODD_VL, Src1, Src2,
DL, DAG,
6172 for (
const auto &[Idx, M] :
enumerate(Mask)) {
6174 (SrcInfo[1].second > 0 && Idx < (
unsigned)SrcInfo[1].second)) {
6178 int Src = M >= (int)NumElts;
6179 int Diff = (int)Idx - (M % NumElts);
6180 bool C = Src == SrcInfo[1].first && Diff == SrcInfo[1].second;
6181 assert(
C ^ (Src == SrcInfo[0].first && Diff == SrcInfo[0].second) &&
6182 "Must match exactly one of the two slides");
6185 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
6192 Res = GetSlide(SrcInfo[0], TrueMask, Res);
6193 Res = GetSlide(SrcInfo[1], SelectMask, Res);
6198 assert(!V1.
isUndef() &&
"Unexpected shuffle canonicalization");
6213 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
6214 for (
unsigned Factor = 4; Factor <= MaxFactor; Factor <<= 1) {
6229 if (NumElts > MinVLMAX) {
6230 unsigned MaxIdx = 0;
6234 MaxIdx = std::max(std::max((
unsigned)
I, (
unsigned)M), MaxIdx);
6236 unsigned NewNumElts =
6238 if (NewNumElts != NumElts) {
6242 Mask.take_front(NewNumElts));
6259 for (
auto Idx : Mask) {
6262 assert(Idx >= 0 && (
unsigned)Idx < NumElts);
6272 any_of(Mask, [&](
const auto &Idx) {
return Idx > 255; })) {
6282 unsigned GatherVVOpc = RISCVISD::VRGATHER_VV_VL;
6288 GatherVVOpc = RISCVISD::VRGATHEREI16_VV_VL;
6297 GatherVVOpc = RISCVISD::VRGATHEREI16_VV_VL;
6301 MVT IndexContainerVT =
6306 for (
int MaskIndex : Mask) {
6307 bool IsLHSIndex = MaskIndex < (int)NumElts && MaskIndex >= 0;
6317 if (NumElts <= MinVLMAX) {
6319 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
6325 auto [InnerTrueMask, InnerVL] =
6337 for (
int i = 0; i <
N; i++) {
6341 DAG.
getNode(GatherVVOpc,
DL, M1VT, SubV1, SubIndex,
6342 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6359 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6361 for (
int i = 0; i <
N; i++)
6377 for (
int i = 0; i <
N; i++) {
6380 DAG.
getUNDEF(IndexContainerVT), LHSIndices,
6381 SlideAmt, TrueMask, VL);
6385 DAG.
getNode(GatherVVOpc,
DL, M1VT, SubV1, SubIndex,
6386 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6396 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
6406 for (
int MaskIndex : Mask) {
6407 bool IsLHSOrUndefIndex = MaskIndex < (int)NumElts;
6408 ShuffleMaskLHS.
push_back(IsLHSOrUndefIndex && MaskIndex >= 0
6410 ShuffleMaskRHS.
push_back(IsLHSOrUndefIndex ? -1 : (MaskIndex - NumElts));
6441 for (
int MaskIndex : Mask) {
6442 bool SelectMaskVal = (MaskIndex < (int)NumElts) ^ !SwapOps;
6446 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
6464 const unsigned NumElts = M.size();
6471 std::array<std::pair<int, int>, 2> SrcInfo;
6482RISCVTargetLowering::lowerCTLZ_CTTZ_ZERO_UNDEF(
SDValue Op,
6484 MVT VT =
Op.getSimpleValueType();
6488 MVT ContainerVT = VT;
6491 if (
Op->isVPOpcode()) {
6492 Mask =
Op.getOperand(1);
6496 VL =
Op.getOperand(2);
6502 MVT FloatEltVT = (EltSize >= 32) ? MVT::f64 :
MVT::f32;
6504 FloatEltVT = MVT::f32;
6511 "Expected legal float type!");
6518 }
else if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF) {
6521 Src = DAG.
getNode(ISD::VP_AND,
DL, VT, Src, Neg, Mask, VL);
6526 if (FloatVT.
bitsGT(VT)) {
6527 if (
Op->isVPOpcode())
6528 FloatVal = DAG.
getNode(ISD::VP_UINT_TO_FP,
DL, FloatVT, Src, Mask, VL);
6537 if (!
Op->isVPOpcode())
6541 MVT ContainerFloatVT =
6543 FloatVal = DAG.
getNode(RISCVISD::VFCVT_RM_F_XU_VL,
DL, ContainerFloatVT,
6544 Src, Mask, RTZRM, VL);
6551 unsigned ShiftAmt = FloatEltVT == MVT::f64 ? 52 : 23;
6555 if (
Op->isVPOpcode()) {
6564 else if (IntVT.
bitsGT(VT))
6569 unsigned ExponentBias = FloatEltVT == MVT::f64 ? 1023 : 127;
6574 if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF)
6575 return DAG.
getNode(ISD::VP_SUB,
DL, VT, Exp,
6580 unsigned Adjust = ExponentBias + (EltSize - 1);
6582 if (
Op->isVPOpcode())
6592 else if (
Op.getOpcode() == ISD::VP_CTLZ)
6593 Res = DAG.
getNode(ISD::VP_UMIN,
DL, VT, Res,
6601 MVT XLenVT = Subtarget.getXLenVT();
6603 MVT SrcVT =
Source.getSimpleValueType();
6612 SrcVT = ContainerVT;
6624 SDValue Res = DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Source, Mask, EVL);
6625 if (
Op->getOpcode() == ISD::VP_CTTZ_ELTS_ZERO_UNDEF)
6643 assert(Load &&
Load->getMemoryVT().isVector() &&
"Expected vector load");
6646 Load->getMemoryVT(),
6647 *
Load->getMemOperand()))
6651 MVT VT =
Op.getSimpleValueType();
6653 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
6654 "Unexpected unaligned RVV load type");
6658 "Expecting equally-sized RVV vector types to be legal");
6660 Load->getPointerInfo(),
Load->getBaseAlign(),
6661 Load->getMemOperand()->getFlags());
6672 assert(Store &&
Store->getValue().getValueType().isVector() &&
6673 "Expected vector store");
6676 Store->getMemoryVT(),
6677 *
Store->getMemOperand()))
6684 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
6685 "Unexpected unaligned RVV store type");
6689 "Expecting equally-sized RVV vector types to be legal");
6690 StoredVal = DAG.
getBitcast(NewVT, StoredVal);
6692 Store->getPointerInfo(),
Store->getBaseAlign(),
6693 Store->getMemOperand()->getFlags());
6698 assert(
Op.getValueType() == MVT::i64 &&
"Unexpected VT");
6727 unsigned ShiftAmt, AddOpc;
6738 MVT VT =
Op.getSimpleValueType();
6742 bool Negate =
false;
6746 if (Index < 0 &&
Imm.isNegative()) {
6763 return DAG.
getNode(ISD::FNEG,
DL, VT, Const);
6769 unsigned IsData =
Op.getConstantOperandVal(4);
6772 if (Subtarget.hasVendorXMIPSCBOP() && !IsData)
6773 return Op.getOperand(0);
6785 if (Subtarget.hasStdExtZtso()) {
6793 return DAG.
getNode(ISD::MEMBARRIER, dl, MVT::Other,
Op.getOperand(0));
6801 return DAG.
getNode(ISD::MEMBARRIER, dl, MVT::Other,
Op.getOperand(0));
6809 MVT VT =
Op.getSimpleValueType();
6810 MVT XLenVT = Subtarget.getXLenVT();
6811 unsigned Check =
Op.getConstantOperandVal(1);
6812 unsigned TDCMask = 0;
6840 MVT VT0 =
Op.getOperand(0).getSimpleValueType();
6845 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6847 VL =
Op.getOperand(3);
6850 VL,
Op->getFlags());
6865 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6867 MVT MaskContainerVT =
6870 VL =
Op.getOperand(3);
6874 SDValue FPCLASS = DAG.
getNode(RISCVISD::FCLASS_VL,
DL, ContainerDstVT, Op0,
6875 Mask, VL,
Op->getFlags());
6877 TDCMaskV = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerDstVT,
6878 DAG.
getUNDEF(ContainerDstVT), TDCMaskV, VL);
6881 DAG.
getNode(RISCVISD::SETCC_VL,
DL, ContainerVT,
6887 TDCMaskV, DAG.
getUNDEF(ContainerDstVT), Mask, VL);
6890 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerDstVT,
6891 DAG.
getUNDEF(ContainerDstVT), SplatZero, VL);
6911 MVT VT =
Op.getSimpleValueType();
6937 Op.getOpcode() == ISD::FMAXIMUM ? RISCVISD::FMAX : RISCVISD::FMIN;
6945 MVT ContainerVT = VT;
6953 if (
Op->isVPOpcode()) {
6954 Mask =
Op.getOperand(2);
6958 VL =
Op.getOperand(3);
6965 SDValue XIsNonNan = DAG.
getNode(RISCVISD::SETCC_VL,
DL, Mask.getValueType(),
6966 {X, X, DAG.getCondCode(ISD::SETOEQ),
6967 DAG.getUNDEF(ContainerVT), Mask, VL});
6968 NewY = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, XIsNonNan,
Y,
X,
6974 SDValue YIsNonNan = DAG.
getNode(RISCVISD::SETCC_VL,
DL, Mask.getValueType(),
6975 {Y, Y, DAG.getCondCode(ISD::SETOEQ),
6976 DAG.getUNDEF(ContainerVT), Mask, VL});
6977 NewX = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, YIsNonNan,
X,
Y,
6982 Op.getOpcode() == ISD::FMAXIMUM ||
Op->getOpcode() == ISD::VP_FMAXIMUM
6983 ? RISCVISD::VFMAX_VL
6984 : RISCVISD::VFMIN_VL;
6986 DAG.
getUNDEF(ContainerVT), Mask, VL);
6994 bool IsFABS =
Op.getOpcode() == ISD::FABS;
6995 assert((IsFABS ||
Op.getOpcode() == ISD::FNEG) &&
6996 "Wrong opcode for lowering FABS or FNEG.");
6999 MVT VT =
Op.getSimpleValueType();
7000 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
7004 DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT,
Op.getOperand(0));
7007 Mask = Mask.sext(Subtarget.
getXLen());
7012 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, Logic);
7020 MVT VT =
Op.getSimpleValueType();
7021 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
7031 if (SignSize == Subtarget.
getXLen())
7032 return DAG.
getNode(ISD::BITCAST,
DL, XLenVT, Sign);
7035 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Sign);
7037 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, XLenVT, Sign);
7039 assert(XLenVT == MVT::i32 &&
"Unexpected type");
7042 return DAG.
getNode(RISCVISD::SplitF64,
DL, {MVT::i32, MVT::i32}, Sign)
7072 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, CopiedSign);
7077#define OP_CASE(NODE) \
7079 return RISCVISD::NODE##_VL;
7080#define VP_CASE(NODE) \
7081 case ISD::VP_##NODE: \
7082 return RISCVISD::NODE##_VL;
7084 switch (
Op.getOpcode()) {
7163 case ISD::VP_CTLZ_ZERO_UNDEF:
7164 return RISCVISD::CTLZ_VL;
7166 case ISD::VP_CTTZ_ZERO_UNDEF:
7167 return RISCVISD::CTTZ_VL;
7170 return RISCVISD::VFMADD_VL;
7172 return RISCVISD::STRICT_VFMADD_VL;
7175 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7176 return RISCVISD::VMAND_VL;
7177 return RISCVISD::AND_VL;
7180 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7181 return RISCVISD::VMOR_VL;
7182 return RISCVISD::OR_VL;
7185 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7186 return RISCVISD::VMXOR_VL;
7187 return RISCVISD::XOR_VL;
7190 return RISCVISD::VZEXT_VL;
7192 return RISCVISD::VSEXT_VL;
7194 return RISCVISD::SETCC_VL;
7196 return RISCVISD::VMERGE_VL;
7197 case ISD::VP_SELECT:
7199 return RISCVISD::VMERGE_VL;
7201 return RISCVISD::SRA_VL;
7203 return RISCVISD::SRL_VL;
7205 return RISCVISD::FSQRT_VL;
7206 case ISD::VP_SIGN_EXTEND:
7207 return RISCVISD::VSEXT_VL;
7208 case ISD::VP_ZERO_EXTEND:
7209 return RISCVISD::VZEXT_VL;
7210 case ISD::VP_FP_TO_SINT:
7211 return RISCVISD::VFCVT_RTZ_X_F_VL;
7212 case ISD::VP_FP_TO_UINT:
7213 return RISCVISD::VFCVT_RTZ_XU_F_VL;
7215 case ISD::FMINIMUMNUM:
7216 case ISD::VP_FMINNUM:
7217 return RISCVISD::VFMIN_VL;
7219 case ISD::FMAXIMUMNUM:
7220 case ISD::VP_FMAXNUM:
7221 return RISCVISD::VFMAX_VL;
7225 case ISD::VP_LLRINT:
7226 return RISCVISD::VFCVT_RM_X_F_VL;
7235 return (
Op.getValueType() == MVT::nxv32f16 &&
7238 Op.getValueType() == MVT::nxv32bf16;
7248 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7249 if (!
Op.getOperand(j).getValueType().isVector()) {
7250 LoOperands[j] =
Op.getOperand(j);
7251 HiOperands[j] =
Op.getOperand(j);
7254 std::tie(LoOperands[j], HiOperands[j]) =
7259 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
7261 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
7274 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7276 std::tie(LoOperands[j], HiOperands[j]) =
7280 if (!
Op.getOperand(j).getValueType().isVector()) {
7281 LoOperands[j] =
Op.getOperand(j);
7282 HiOperands[j] =
Op.getOperand(j);
7285 std::tie(LoOperands[j], HiOperands[j]) =
7290 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
7292 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
7302 auto [EVLLo, EVLHi] =
7303 DAG.
SplitEVL(
Op.getOperand(3),
Op.getOperand(1).getValueType(),
DL);
7307 {Op.getOperand(0), Lo, MaskLo, EVLLo},
Op->getFlags());
7309 {ResLo, Hi, MaskHi, EVLHi},
Op->getFlags());
7326 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7327 if (!
Op.getOperand(j).getValueType().isVector()) {
7328 LoOperands[j] =
Op.getOperand(j);
7329 HiOperands[j] =
Op.getOperand(j);
7332 std::tie(LoOperands[j], HiOperands[j]) =
7337 DAG.
getNode(
Op.getOpcode(),
DL, LoVTs, LoOperands,
Op->getFlags());
7340 DAG.
getNode(
Op.getOpcode(),
DL, HiVTs, HiOperands,
Op->getFlags());
7348RISCVTargetLowering::lowerXAndesBfHCvtBFloat16Load(
SDValue Op,
7350 assert(Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh() &&
7351 "Unexpected bfloat16 load lowering");
7355 EVT MemVT =
LD->getMemoryVT();
7360 LD->getMemOperand());
7368 DAG.
getNode(RISCVISD::NDS_FMV_BF16_X,
DL, MVT::bf16, OrSixteenOne);
7373RISCVTargetLowering::lowerXAndesBfHCvtBFloat16Store(
SDValue Op,
7375 assert(Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh() &&
7376 "Unexpected bfloat16 store lowering");
7381 Subtarget.getXLenVT(),
ST->getValue());
7383 ST->getChain(),
DL, FMV,
ST->getBasePtr(),
7385 ST->getMemOperand());
7390 switch (
Op.getOpcode()) {
7393 "Unimplemented RISCVTargetLowering::LowerOperation Case");
7396 case ISD::ATOMIC_FENCE:
7399 return lowerGlobalAddress(
Op, DAG);
7401 return lowerBlockAddress(
Op, DAG);
7403 return lowerConstantPool(
Op, DAG);
7405 return lowerJumpTable(
Op, DAG);
7407 return lowerGlobalTLSAddress(
Op, DAG);
7411 return lowerConstantFP(
Op, DAG);
7413 return lowerSELECT(
Op, DAG);
7415 return lowerBRCOND(
Op, DAG);
7417 return lowerVASTART(
Op, DAG);
7419 return lowerFRAMEADDR(
Op, DAG);
7421 return lowerRETURNADDR(
Op, DAG);
7423 return lowerShiftLeftParts(
Op, DAG);
7425 return lowerShiftRightParts(
Op, DAG,
true);
7427 return lowerShiftRightParts(
Op, DAG,
false);
7430 if (
Op.getValueType().isFixedLengthVector()) {
7431 assert(Subtarget.hasStdExtZvkb());
7432 return lowerToScalableOp(
Op, DAG);
7434 assert(Subtarget.hasVendorXTHeadBb() &&
7435 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
7436 "Unexpected custom legalization");
7441 case ISD::BITCAST: {
7443 EVT VT =
Op.getValueType();
7446 MVT XLenVT = Subtarget.getXLenVT();
7447 if (Op0VT == MVT::i16 &&
7448 ((VT == MVT::f16 && Subtarget.hasStdExtZfhminOrZhinxmin()) ||
7449 (VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
7451 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, NewOp0);
7453 if (VT == MVT::f32 && Op0VT == MVT::i32 && Subtarget.is64Bit() &&
7454 Subtarget.hasStdExtFOrZfinx()) {
7456 return DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, NewOp0);
7458 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit() &&
7459 Subtarget.hasStdExtDOrZdinx()) {
7462 return DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64,
Lo,
Hi);
7474 "Unexpected types");
7506 return LowerINTRINSIC_WO_CHAIN(
Op, DAG);
7508 return LowerINTRINSIC_W_CHAIN(
Op, DAG);
7510 return LowerINTRINSIC_VOID(
Op, DAG);
7512 return LowerIS_FPCLASS(
Op, DAG);
7514 MVT VT =
Op.getSimpleValueType();
7516 assert(Subtarget.hasStdExtZvbb());
7517 return lowerToScalableOp(
Op, DAG);
7520 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected custom legalization");
7524 return DAG.
getNode(RISCVISD::BREV8,
DL, VT, BSwap);
7530 if (!
Op.getSimpleValueType().isVector())
7532 return lowerVectorTruncLike(
Op, DAG);
7535 if (
Op.getOperand(0).getValueType().isVector() &&
7536 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7537 return lowerVectorMaskExt(
Op, DAG, 1);
7538 if (
Op.getValueType().isScalableVector())
7540 return lowerToScalableOp(
Op, DAG);
7542 if (
Op.getOperand(0).getValueType().isVector() &&
7543 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7544 return lowerVectorMaskExt(
Op, DAG, -1);
7545 if (
Op.getValueType().isScalableVector())
7547 return lowerToScalableOp(
Op, DAG);
7549 return lowerSPLAT_VECTOR_PARTS(
Op, DAG);
7551 return lowerINSERT_VECTOR_ELT(
Op, DAG);
7553 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
7555 MVT VT =
Op.getSimpleValueType();
7563 MVT ContainerVT = VT;
7570 V = DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL, ContainerVT,
7571 DAG.
getUNDEF(ContainerVT), Scalar, VL);
7574 V = DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, ContainerVT,
7575 DAG.
getUNDEF(ContainerVT), Scalar, VL);
7582 MVT XLenVT = Subtarget.getXLenVT();
7583 MVT VT =
Op.getSimpleValueType();
7602 }
else if (
Log2 > 3) {
7606 }
else if ((Val % 8) == 0) {
7624 if (
Op.getValueType() == MVT::f16 && Subtarget.is64Bit() &&
7625 Op.getOperand(1).getValueType() == MVT::i32) {
7629 DAG.
getNode(ISD::FPOWI,
DL, MVT::f32, Op0,
Op.getOperand(1));
7640 case ISD::FP_EXTEND:
7642 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
7645 return lowerStrictFPExtendOrRoundLike(
Op, DAG);
7648 if (
Op.getValueType().isVector() &&
7649 ((
Op.getValueType().getScalarType() == MVT::f16 &&
7650 (Subtarget.hasVInstructionsF16Minimal() &&
7651 !Subtarget.hasVInstructionsF16())) ||
7652 Op.getValueType().getScalarType() == MVT::bf16)) {
7668 Op1.getValueType().isVector() &&
7669 ((Op1.getValueType().getScalarType() == MVT::f16 &&
7670 (Subtarget.hasVInstructionsF16Minimal() &&
7671 !Subtarget.hasVInstructionsF16())) ||
7672 Op1.getValueType().getScalarType() == MVT::bf16)) {
7678 Op1.getValueType().getVectorElementCount());
7681 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), WidenVec);
7691 MVT VT =
Op.getSimpleValueType();
7694 bool IsStrict =
Op->isStrictFPOpcode();
7695 SDValue Src =
Op.getOperand(0 + IsStrict);
7696 MVT SrcVT = Src.getSimpleValueType();
7707 "Unexpected vector element types");
7711 if (EltSize > (2 * SrcEltSize)) {
7723 Op.getOperand(0), Ext);
7727 assert(SrcEltVT == MVT::f16 &&
"Unexpected FP_TO_[US]INT lowering");
7732 auto [FExt, Chain] =
7734 return DAG.
getNode(
Op.getOpcode(),
DL,
Op->getVTList(), Chain, FExt);
7741 if (SrcEltSize > (2 * EltSize)) {
7744 assert(EltVT == MVT::f16 &&
"Unexpected [US]_TO_FP lowering");
7749 Op.getOperand(0), Src);
7764 Op.getOperand(0), Src);
7778 unsigned RVVOpc = 0;
7779 switch (
Op.getOpcode()) {
7783 RVVOpc = RISCVISD::VFCVT_RTZ_X_F_VL;
7786 RVVOpc = RISCVISD::VFCVT_RTZ_XU_F_VL;
7789 RVVOpc = RISCVISD::SINT_TO_FP_VL;
7792 RVVOpc = RISCVISD::UINT_TO_FP_VL;
7795 RVVOpc = RISCVISD::STRICT_VFCVT_RTZ_X_F_VL;
7798 RVVOpc = RISCVISD::STRICT_VFCVT_RTZ_XU_F_VL;
7801 RVVOpc = RISCVISD::STRICT_SINT_TO_FP_VL;
7804 RVVOpc = RISCVISD::STRICT_UINT_TO_FP_VL;
7811 "Expected same element count");
7818 Op.getOperand(0), Src, Mask, VL);
7822 Src = DAG.
getNode(RVVOpc,
DL, ContainerVT, Src, Mask, VL);
7828 case ISD::FP_TO_BF16: {
7831 assert(!Subtarget.isSoftFPABI() &&
"Unexpected custom legalization");
7837 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
7838 if (Subtarget.is64Bit())
7839 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Res);
7842 case ISD::BF16_TO_FP: {
7843 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalization");
7844 MVT VT =
Op.getSimpleValueType();
7849 SDValue Res = Subtarget.is64Bit()
7850 ? DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32,
Op)
7854 return DAG.
getNode(ISD::FP_EXTEND,
DL, VT, Res);
7857 case ISD::STRICT_FP_TO_FP16:
7858 case ISD::FP_TO_FP16: {
7861 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalisation");
7864 bool IsStrict =
Op->isStrictFPOpcode();
7865 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7869 std::tie(Res, Chain) =
7870 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
7871 if (Subtarget.is64Bit())
7872 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Res);
7878 case ISD::STRICT_FP16_TO_FP:
7879 case ISD::FP16_TO_FP: {
7882 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalisation");
7885 bool IsStrict =
Op->isStrictFPOpcode();
7886 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7888 SDValue Arg = Subtarget.is64Bit()
7889 ? DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, Op0)
7892 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
7893 CallOptions,
DL, Chain);
7901 case ISD::FNEARBYINT:
7904 case ISD::FROUNDEVEN:
7911 case ISD::LLROUND: {
7912 if (
Op.getValueType().isVector())
7914 assert(
Op.getOperand(0).getValueType() == MVT::f16 &&
7915 "Unexpected custom legalisation");
7918 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), Ext);
7924 assert(
Op.getOperand(1).getValueType() == MVT::f16 &&
7925 "Unexpected custom legalisation");
7928 {
Op.getOperand(0),
Op.getOperand(1)});
7929 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
7930 {Ext.getValue(1), Ext.getValue(0)});
7932 case ISD::VECREDUCE_ADD:
7933 case ISD::VECREDUCE_UMAX:
7934 case ISD::VECREDUCE_SMAX:
7935 case ISD::VECREDUCE_UMIN:
7936 case ISD::VECREDUCE_SMIN:
7937 return lowerVECREDUCE(
Op, DAG);
7938 case ISD::VECREDUCE_AND:
7939 case ISD::VECREDUCE_OR:
7940 case ISD::VECREDUCE_XOR:
7941 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7942 return lowerVectorMaskVecReduction(
Op, DAG,
false);
7943 return lowerVECREDUCE(
Op, DAG);
7944 case ISD::VECREDUCE_FADD:
7945 case ISD::VECREDUCE_SEQ_FADD:
7946 case ISD::VECREDUCE_FMIN:
7947 case ISD::VECREDUCE_FMAX:
7948 case ISD::VECREDUCE_FMAXIMUM:
7949 case ISD::VECREDUCE_FMINIMUM:
7950 return lowerFPVECREDUCE(
Op, DAG);
7951 case ISD::VP_REDUCE_ADD:
7952 case ISD::VP_REDUCE_UMAX:
7953 case ISD::VP_REDUCE_SMAX:
7954 case ISD::VP_REDUCE_UMIN:
7955 case ISD::VP_REDUCE_SMIN:
7956 case ISD::VP_REDUCE_FADD:
7957 case ISD::VP_REDUCE_SEQ_FADD:
7958 case ISD::VP_REDUCE_FMIN:
7959 case ISD::VP_REDUCE_FMAX:
7960 case ISD::VP_REDUCE_FMINIMUM:
7961 case ISD::VP_REDUCE_FMAXIMUM:
7964 return lowerVPREDUCE(
Op, DAG);
7965 case ISD::VP_REDUCE_AND:
7966 case ISD::VP_REDUCE_OR:
7967 case ISD::VP_REDUCE_XOR:
7968 if (
Op.getOperand(1).getValueType().getVectorElementType() == MVT::i1)
7969 return lowerVectorMaskVecReduction(
Op, DAG,
true);
7970 return lowerVPREDUCE(
Op, DAG);
7971 case ISD::VP_CTTZ_ELTS:
7972 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
7973 return lowerVPCttzElements(
Op, DAG);
7977 DAG.
getUNDEF(ContainerVT), DAG, Subtarget);
7980 return lowerINSERT_SUBVECTOR(
Op, DAG);
7982 return lowerEXTRACT_SUBVECTOR(
Op, DAG);
7984 return lowerVECTOR_DEINTERLEAVE(
Op, DAG);
7986 return lowerVECTOR_INTERLEAVE(
Op, DAG);
7988 return lowerSTEP_VECTOR(
Op, DAG);
7990 return lowerVECTOR_REVERSE(
Op, DAG);
7992 return lowerVECTOR_SPLICE(
Op, DAG);
7994 MVT VT =
Op.getSimpleValueType();
7996 if (!Subtarget.is64Bit() && EltVT == MVT::i64)
8001 MVT VT =
Op.getSimpleValueType();
8003 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
8004 EltVT == MVT::bf16) {
8007 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
8008 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
8009 Elt = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, Subtarget.getXLenVT(),
8012 Elt = DAG.
getNode(ISD::BITCAST,
DL, MVT::i16,
Op.getOperand(0));
8014 return DAG.
getNode(ISD::BITCAST,
DL, VT,
8018 if (EltVT == MVT::i1)
8019 return lowerVectorMaskSplat(
Op, DAG);
8028 MVT VT =
Op.getSimpleValueType();
8029 MVT ContainerVT = VT;
8041 if (
Op.getNumOperands() > 2 &&
8045 size_t HalfNumOps =
Op.getNumOperands() / 2;
8047 Op->ops().take_front(HalfNumOps));
8049 Op->ops().drop_front(HalfNumOps));
8053 unsigned NumOpElts =
8054 Op.getOperand(0).getSimpleValueType().getVectorMinNumElements();
8067 EVT VT = Load->getValueType(0);
8068 if (VT == MVT::f64) {
8069 assert(Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
8070 !Subtarget.is64Bit() &&
"Unexpected custom legalisation");
8074 SDValue BasePtr = Load->getBasePtr();
8075 SDValue Chain = Load->getChain();
8078 DAG.
getLoad(MVT::i32,
DL, Chain, BasePtr, Load->getPointerInfo(),
8079 Load->getBaseAlign(), Load->getMemOperand()->getFlags());
8082 MVT::i32,
DL, Chain, BasePtr, Load->getPointerInfo().getWithOffset(4),
8083 Load->getBaseAlign(), Load->getMemOperand()->getFlags());
8091 if (VT == MVT::bf16)
8092 return lowerXAndesBfHCvtBFloat16Load(
Op, DAG);
8097 MVT XLenVT = Subtarget.getXLenVT();
8100 unsigned NumElts = Sz / (NF * 8);
8101 int Log2LMUL =
Log2_64(NumElts) - 3;
8104 Flag.setNoUnsignedWrap(
true);
8106 SDValue BasePtr = Load->getBasePtr();
8114 for (
unsigned i = 0; i < NF; ++i) {
8119 Ret = DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VT, Ret, LoadVal,
8127 if (
auto V = expandUnalignedRVVLoad(
Op, DAG))
8129 if (
Op.getValueType().isFixedLengthVector())
8130 return lowerFixedLengthVectorLoadToRVV(
Op, DAG);
8135 SDValue StoredVal = Store->getValue();
8137 if (VT == MVT::f64) {
8138 assert(Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
8139 !Subtarget.is64Bit() &&
"Unexpected custom legalisation");
8143 SDValue BasePtr = Store->getBasePtr();
8144 SDValue Chain = Store->getChain();
8146 DAG.
getVTList(MVT::i32, MVT::i32), StoredVal);
8149 Store->getPointerInfo(), Store->getBaseAlign(),
8150 Store->getMemOperand()->getFlags());
8153 Store->getPointerInfo().getWithOffset(4),
8154 Store->getBaseAlign(),
8155 Store->getMemOperand()->getFlags());
8158 if (VT == MVT::i64) {
8159 assert(Subtarget.hasStdExtZilsd() && !Subtarget.is64Bit() &&
8160 "Unexpected custom legalisation");
8161 if (Store->isTruncatingStore())
8164 if (!Subtarget.enableUnalignedScalarMem() && Store->getAlign() < 8)
8175 {Store->getChain(), Lo, Hi, Store->getBasePtr()}, MVT::i64,
8176 Store->getMemOperand());
8179 if (VT == MVT::bf16)
8180 return lowerXAndesBfHCvtBFloat16Store(
Op, DAG);
8185 MVT XLenVT = Subtarget.getXLenVT();
8188 unsigned NumElts = Sz / (NF * 8);
8189 int Log2LMUL =
Log2_64(NumElts) - 3;
8192 Flag.setNoUnsignedWrap(
true);
8194 SDValue Chain = Store->getChain();
8195 SDValue BasePtr = Store->getBasePtr();
8202 for (
unsigned i = 0; i < NF; ++i) {
8204 DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL,
8207 Ret = DAG.
getStore(Chain,
DL, Extract, BasePtr,
8209 Store->getBaseAlign(),
8210 Store->getMemOperand()->getFlags());
8211 Chain = Ret.getValue(0);
8217 if (
auto V = expandUnalignedRVVStore(
Op, DAG))
8219 if (
Op.getOperand(1).getValueType().isFixedLengthVector())
8220 return lowerFixedLengthVectorStoreToRVV(
Op, DAG);
8225 return lowerMaskedLoad(
Op, DAG);
8226 case ISD::VP_LOAD_FF:
8227 return lowerLoadFF(
Op, DAG);
8230 return lowerMaskedStore(
Op, DAG);
8232 return lowerVectorCompress(
Op, DAG);
8241 EVT VT =
Op.getValueType();
8252 MVT OpVT =
Op.getOperand(0).getSimpleValueType();
8254 MVT VT =
Op.getSimpleValueType();
8259 "Unexpected CondCode");
8292 return DAG.
getSetCC(
DL, VT, RHS, LHS, CCVal);
8298 return lowerToScalableOp(
Op, DAG);
8315 return lowerToScalableOp(
Op, DAG);
8319 if (
Op.getSimpleValueType().isFixedLengthVector())
8320 return lowerToScalableOp(
Op, DAG);
8322 assert(
Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.is64Bit() &&
8323 "Unexpected custom legalisation");
8327 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
8338 case ISD::FMINIMUMNUM:
8339 case ISD::FMAXIMUMNUM:
8355 return lowerToScalableOp(
Op, DAG);
8359 EVT VT =
Op->getValueType(0);
8374 return lowerABS(
Op, DAG);
8379 if (Subtarget.hasStdExtZvbb())
8380 return lowerToScalableOp(
Op, DAG);
8382 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8384 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
8388 return lowerToScalableOp(
Op, DAG);
8397 return lowerToScalableOp(
Op, DAG);
8400 return lowerVectorStrictFSetcc(
Op, DAG);
8410 case ISD::VP_GATHER:
8411 return lowerMaskedGather(
Op, DAG);
8413 case ISD::VP_SCATTER:
8414 return lowerMaskedScatter(
Op, DAG);
8416 return lowerGET_ROUNDING(
Op, DAG);
8417 case ISD::SET_ROUNDING:
8418 return lowerSET_ROUNDING(
Op, DAG);
8419 case ISD::GET_FPENV:
8420 return lowerGET_FPENV(
Op, DAG);
8421 case ISD::SET_FPENV:
8422 return lowerSET_FPENV(
Op, DAG);
8423 case ISD::RESET_FPENV:
8424 return lowerRESET_FPENV(
Op, DAG);
8425 case ISD::GET_FPMODE:
8426 return lowerGET_FPMODE(
Op, DAG);
8427 case ISD::SET_FPMODE:
8428 return lowerSET_FPMODE(
Op, DAG);
8429 case ISD::RESET_FPMODE:
8430 return lowerRESET_FPMODE(
Op, DAG);
8432 return lowerEH_DWARF_CFA(
Op, DAG);
8434 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
8435 return lowerVPMergeMask(
Op, DAG);
8437 case ISD::VP_SELECT:
8445 case ISD::VP_UADDSAT:
8446 case ISD::VP_USUBSAT:
8447 case ISD::VP_SADDSAT:
8448 case ISD::VP_SSUBSAT:
8450 case ISD::VP_LLRINT:
8451 return lowerVPOp(
Op, DAG);
8455 return lowerLogicVPOp(
Op, DAG);
8464 case ISD::VP_FMINNUM:
8465 case ISD::VP_FMAXNUM:
8466 case ISD::VP_FCOPYSIGN:
8473 return lowerVPOp(
Op, DAG);
8474 case ISD::VP_IS_FPCLASS:
8475 return LowerIS_FPCLASS(
Op, DAG);
8476 case ISD::VP_SIGN_EXTEND:
8477 case ISD::VP_ZERO_EXTEND:
8478 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
8479 return lowerVPExtMaskOp(
Op, DAG);
8480 return lowerVPOp(
Op, DAG);
8481 case ISD::VP_TRUNCATE:
8482 return lowerVectorTruncLike(
Op, DAG);
8483 case ISD::VP_FP_EXTEND:
8484 case ISD::VP_FP_ROUND:
8485 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
8486 case ISD::VP_SINT_TO_FP:
8487 case ISD::VP_UINT_TO_FP:
8488 if (
Op.getValueType().isVector() &&
8489 ((
Op.getValueType().getScalarType() == MVT::f16 &&
8490 (Subtarget.hasVInstructionsF16Minimal() &&
8491 !Subtarget.hasVInstructionsF16())) ||
8492 Op.getValueType().getScalarType() == MVT::bf16)) {
8505 case ISD::VP_FP_TO_SINT:
8506 case ISD::VP_FP_TO_UINT:
8508 Op1.getValueType().isVector() &&
8509 ((Op1.getValueType().getScalarType() == MVT::f16 &&
8510 (Subtarget.hasVInstructionsF16Minimal() &&
8511 !Subtarget.hasVInstructionsF16())) ||
8512 Op1.getValueType().getScalarType() == MVT::bf16)) {
8518 Op1.getValueType().getVectorElementCount());
8522 {WidenVec, Op.getOperand(1), Op.getOperand(2)});
8524 return lowerVPFPIntConvOp(
Op, DAG);
8528 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
8529 return lowerVPSetCCMaskOp(
Op, DAG);
8535 case ISD::VP_BITREVERSE:
8537 return lowerVPOp(
Op, DAG);
8539 case ISD::VP_CTLZ_ZERO_UNDEF:
8540 if (Subtarget.hasStdExtZvbb())
8541 return lowerVPOp(
Op, DAG);
8542 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8544 case ISD::VP_CTTZ_ZERO_UNDEF:
8545 if (Subtarget.hasStdExtZvbb())
8546 return lowerVPOp(
Op, DAG);
8547 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8549 return lowerVPOp(
Op, DAG);
8550 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
8551 return lowerVPStridedLoad(
Op, DAG);
8552 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
8553 return lowerVPStridedStore(
Op, DAG);
8555 case ISD::VP_FFLOOR:
8557 case ISD::VP_FNEARBYINT:
8558 case ISD::VP_FROUND:
8559 case ISD::VP_FROUNDEVEN:
8560 case ISD::VP_FROUNDTOZERO:
8564 case ISD::VP_FMAXIMUM:
8565 case ISD::VP_FMINIMUM:
8569 case ISD::EXPERIMENTAL_VP_SPLICE:
8570 return lowerVPSpliceExperimental(
Op, DAG);
8571 case ISD::EXPERIMENTAL_VP_REVERSE:
8572 return lowerVPReverseExperimental(
Op, DAG);
8573 case ISD::EXPERIMENTAL_VP_SPLAT:
8574 return lowerVPSplatExperimental(
Op, DAG);
8577 "llvm.clear_cache only needs custom lower on Linux targets");
8580 return emitFlushICache(DAG,
Op.getOperand(0),
Op.getOperand(1),
8581 Op.getOperand(2), Flags,
DL);
8583 case ISD::DYNAMIC_STACKALLOC:
8584 return lowerDYNAMIC_STACKALLOC(
Op, DAG);
8585 case ISD::INIT_TRAMPOLINE:
8586 return lowerINIT_TRAMPOLINE(
Op, DAG);
8587 case ISD::ADJUST_TRAMPOLINE:
8588 return lowerADJUST_TRAMPOLINE(
Op, DAG);
8589 case ISD::PARTIAL_REDUCE_UMLA:
8590 case ISD::PARTIAL_REDUCE_SMLA:
8591 case ISD::PARTIAL_REDUCE_SUMLA:
8592 return lowerPARTIAL_REDUCE_MLA(
Op, DAG);
8599 MakeLibCallOptions CallOptions;
8600 std::pair<SDValue, SDValue> CallResult =
8601 makeLibCall(DAG, RTLIB::RISCV_FLUSH_ICACHE, MVT::isVoid,
8602 {Start, End, Flags}, CallOptions,
DL, InChain);
8605 return CallResult.second;
8610 if (!Subtarget.is64Bit())
8618 std::unique_ptr<MCCodeEmitter> CodeEmitter(
8646 const bool HasCFBranch =
8647 Subtarget.hasStdExtZicfilp() &&
8649 "cf-protection-branch");
8650 const unsigned StaticChainIdx = HasCFBranch ? 5 : 4;
8651 const unsigned StaticChainOffset = StaticChainIdx * 4;
8652 const unsigned FunctionAddressOffset = StaticChainOffset + 8;
8656 auto GetEncoding = [&](
const MCInst &MC) {
8659 CodeEmitter->encodeInstruction(MC, CB, Fixups, *STI);
8666 SmallVector<uint32_t> Encodings;
8671 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X7).addImm(0)),
8675 GetEncoding(MCInstBuilder(RISCV::LD)
8678 .addImm(FunctionAddressOffset)),
8681 GetEncoding(MCInstBuilder(RISCV::LD)
8684 .addImm(StaticChainOffset)),
8687 GetEncoding(MCInstBuilder(RISCV::JALR)
8695 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X0).addImm(0)),
8698 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X28).addImm(0)),
8702 GetEncoding(MCInstBuilder(RISCV::LD)
8705 .addImm(FunctionAddressOffset - 4)),
8708 GetEncoding(MCInstBuilder(RISCV::LD)
8711 .addImm(StaticChainOffset - 4)),
8714 GetEncoding(MCInstBuilder(RISCV::JALR)
8726 Root, dl, DAG.
getConstant(Encoding, dl, MVT::i64), Addr,
8727 MachinePointerInfo(TrmpAddr, Idx * 4), MVT::i32));
8731 SDValue FunctionAddress =
Op.getOperand(2);
8735 struct OffsetValuePair {
8739 } OffsetValues[] = {
8740 {StaticChainOffset, StaticChain},
8741 {FunctionAddressOffset, FunctionAddress},
8743 for (
auto &OffsetValue : OffsetValues) {
8746 DAG.
getConstant(OffsetValue.Offset, dl, MVT::i64));
8747 OffsetValue.Addr = Addr;
8749 DAG.
getStore(Root, dl, OffsetValue.Value, Addr,
8750 MachinePointerInfo(TrmpAddr, OffsetValue.Offset)));
8753 assert(OutChains.
size() == StaticChainIdx + 2 &&
8754 "Size of OutChains mismatch");
8759 SDValue EndOfTrmp = OffsetValues[0].Addr;
8770 if (!Subtarget.is64Bit())
8773 return Op.getOperand(0);
8782 MVT VT =
Op.getSimpleValueType();
8788 MVT ArgVT =
A.getSimpleValueType();
8789 assert(ArgVT ==
B.getSimpleValueType() &&
8799 MVT ContainerVT = VT;
8808 switch (
Op.getOpcode()) {
8809 case ISD::PARTIAL_REDUCE_SMLA:
8810 Opc = RISCVISD::VQDOT_VL;
8812 case ISD::PARTIAL_REDUCE_UMLA:
8813 Opc = RISCVISD::VQDOTU_VL;
8815 case ISD::PARTIAL_REDUCE_SUMLA:
8816 Opc = RISCVISD::VQDOTSU_VL;
8842 N->getOffset(), Flags);
8871template <
class NodeTy>
8873 bool IsLocal,
bool IsExternWeak)
const {
8883 if (IsLocal && !Subtarget.allowTaggedGlobals())
8887 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
8910 if (Subtarget.hasVendorXqcili()) {
8914 return DAG.
getNode(RISCVISD::QC_E_LI,
DL, Ty, Addr);
8921 return DAG.
getNode(RISCVISD::ADD_LO,
DL, Ty, MNHi, AddrLo);
8945 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
8953 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
8961 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
8962 const GlobalValue *GV =
N->getGlobal();
8970 return getAddr(
N, DAG);
8977 return getAddr(
N, DAG);
8984 return getAddr(
N, DAG);
8989 bool UseGOT)
const {
8992 const GlobalValue *GV =
N->getGlobal();
8993 MVT XLenVT = Subtarget.getXLenVT();
9030 DAG.
getNode(RISCVISD::ADD_TPREL,
DL, Ty, MNHi, TPReg, AddrAdd);
9031 return DAG.
getNode(RISCVISD::ADD_LO,
DL, Ty, MNAdd, AddrLo);
9039 const GlobalValue *GV =
N->getGlobal();
9050 Args.emplace_back(Load, CallTy);
9053 TargetLowering::CallLoweringInfo CLI(DAG);
9067 const GlobalValue *GV =
N->getGlobal();
9083 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
9097 Addr = getStaticTLSAddr(
N, DAG,
false);
9100 Addr = getStaticTLSAddr(
N, DAG,
true);
9105 : getDynamicTLSAddr(
N, DAG);
9122 if (
LHS == LHS2 &&
RHS == RHS2) {
9127 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
9135 return std::nullopt;
9147 MVT VT =
N->getSimpleValueType(0);
9174 uint64_t TrueM1 = TrueC->getZExtValue() - 1;
9176 unsigned ShAmount =
Log2_64(TrueM1);
9178 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, CondV,
9194 if (~TrueVal == FalseVal) {
9234 if (Subtarget.hasShortForwardBranchOpt())
9237 unsigned SelOpNo = 0;
9247 unsigned ConstSelOpNo = 1;
9248 unsigned OtherSelOpNo = 2;
9255 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
9260 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
9266 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
9268 std::swap(NewConstOps[0], NewConstOps[1]);
9280 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
9282 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
9285 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
9286 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
9295 MVT VT =
Op.getSimpleValueType();
9296 MVT XLenVT = Subtarget.getXLenVT();
9317 return DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV);
9320 return DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV);
9324 auto getNotOperand = [](
const SDValue &
Op) -> std::optional<const SDValue> {
9325 using namespace llvm::SDPatternMatch;
9330 return std::nullopt;
9336 auto NotOperand = (TrueV.
getOperand(0) == FalseV)
9338 : getNotOperand(TrueV.getOperand(0));
9341 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, *NotOperand, CondV);
9347 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV));
9354 auto NotOperand = (FalseV.
getOperand(0) == TrueV)
9356 : getNotOperand(FalseV.getOperand(0));
9359 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, *NotOperand, CondV);
9365 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV));
9382 int64_t TrueImm =
TrueVal.getSExtValue();
9383 int64_t FalseImm =
FalseVal.getSExtValue();
9402 if ((TrueVal - FalseVal).isPowerOf2() &&
FalseVal.isSignedIntN(12)) {
9407 if ((FalseVal - TrueVal).isPowerOf2() &&
TrueVal.isSignedIntN(12)) {
9414 auto getCost = [&](
const APInt &Delta,
const APInt &Addend) {
9416 Delta, Subtarget.getXLen(), Subtarget,
true);
9418 if (Addend.isSignedIntN(12))
9421 Addend, Subtarget.getXLen(), Subtarget,
true);
9422 return AddendCost + DeltaCost;
9424 bool IsCZERO_NEZ =
getCost(FalseVal - TrueVal, TrueVal) <=
9425 getCost(TrueVal - FalseVal, FalseVal);
9427 IsCZERO_NEZ ? FalseVal - TrueVal : TrueVal - FalseVal,
DL, VT);
9429 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9430 DL, VT, LHSVal, CondV);
9438 SDValue ConstVal = IsCZERO_NEZ ? TrueV : FalseV;
9439 SDValue RegV = IsCZERO_NEZ ? FalseV : TrueV;
9442 if (RawConstVal == -0x800) {
9445 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9446 DL, VT, XorOp, CondV);
9454 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9455 DL, VT, SubOp, CondV);
9462 if (!Subtarget.hasConditionalMoveFusion())
9465 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV),
9466 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV),
9470 if (
Op.hasOneUse()) {
9471 unsigned UseOpc =
Op->user_begin()->getOpcode();
9473 SDNode *BinOp = *
Op->user_begin();
9480 return lowerSELECT(NewSel, DAG);
9534 if (TrueVal - 1 == FalseVal)
9536 if (TrueVal + 1 == FalseVal)
9543 RHS == TrueV &&
LHS == FalseV) {
9574 MVT XLenVT = Subtarget.getXLenVT();
9585 return DAG.
getNode(RISCVISD::BR_CC,
DL,
Op.getValueType(),
Op.getOperand(0),
9586 LHS,
RHS, TargetCC,
Op.getOperand(2));
9589 return DAG.
getNode(RISCVISD::BR_CC,
DL,
Op.getValueType(),
Op.getOperand(0),
9596 RISCVMachineFunctionInfo *FuncInfo = MF.
getInfo<RISCVMachineFunctionInfo>();
9606 MachinePointerInfo(SV));
9611 const RISCVRegisterInfo &RI = *Subtarget.getRegisterInfo();
9616 int XLenInBytes = Subtarget.getXLen() / 8;
9618 EVT VT =
Op.getValueType();
9621 unsigned Depth =
Op.getConstantOperandVal(0);
9623 int Offset = -(XLenInBytes * 2);
9635 const RISCVRegisterInfo &RI = *Subtarget.getRegisterInfo();
9639 MVT XLenVT = Subtarget.getXLenVT();
9640 int XLenInBytes = Subtarget.getXLen() / 8;
9642 EVT VT =
Op.getValueType();
9644 unsigned Depth =
Op.getConstantOperandVal(0);
9646 int Off = -XLenInBytes;
9647 SDValue FrameAddr = lowerFRAMEADDR(
Op, DAG);
9651 MachinePointerInfo());
9666 EVT VT =
Lo.getValueType();
9705 EVT VT =
Lo.getValueType();
9756 MVT VT =
Op.getSimpleValueType();
9761 return DAG.
getNode(RISCVISD::VMSET_VL,
DL, VT, VL);
9765 return DAG.
getNode(RISCVISD::VMCLR_VL,
DL, VT, VL);
9782 MVT VecVT =
Op.getSimpleValueType();
9784 "Unexpected SPLAT_VECTOR_PARTS lowering");
9790 MVT ContainerVT = VecVT;
9810 int64_t ExtTrueVal)
const {
9812 MVT VecVT =
Op.getSimpleValueType();
9815 assert(Src.getValueType().isVector() &&
9816 Src.getValueType().getVectorElementType() == MVT::i1);
9836 MVT XLenVT = Subtarget.getXLenVT();
9842 if (
Xor.getOpcode() == RISCVISD::VMXOR_VL) {
9854 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9855 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
9856 SplatTrueVal = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9857 DAG.
getUNDEF(ContainerVT), SplatTrueVal, VL);
9859 DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, CC, SplatTrueVal,
9860 SplatZero, DAG.
getUNDEF(ContainerVT), VL);
9870 bool IsVPTrunc =
Op.getOpcode() == ISD::VP_TRUNCATE;
9872 EVT MaskVT =
Op.getValueType();
9875 "Unexpected type for vector mask lowering");
9877 MVT VecVT = Src.getSimpleValueType();
9881 VL =
Op.getOperand(2);
9884 MVT ContainerVT = VecVT;
9890 MVT MaskContainerVT =
9897 std::tie(Mask, VL) =
9904 SplatOne = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9905 DAG.
getUNDEF(ContainerVT), SplatOne, VL);
9906 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9907 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
9910 SDValue Trunc = DAG.
getNode(RISCVISD::AND_VL,
DL, ContainerVT, Src, SplatOne,
9911 DAG.
getUNDEF(ContainerVT), Mask, VL);
9912 Trunc = DAG.
getNode(RISCVISD::SETCC_VL,
DL, MaskContainerVT,
9922 unsigned Opc =
Op.getOpcode();
9923 bool IsVPTrunc =
Opc == ISD::VP_TRUNCATE;
9926 MVT VT =
Op.getSimpleValueType();
9928 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
9932 return lowerVectorMaskTruncLike(
Op, DAG);
9940 MVT SrcVT = Src.getSimpleValueType();
9945 "Unexpected vector truncate lowering");
9947 MVT ContainerVT = SrcVT;
9951 VL =
Op.getOperand(2);
9964 std::tie(Mask, VL) =
9970 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL_SSAT;
9972 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL_USAT;
9974 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL;
9980 }
while (SrcEltVT != DstEltVT);
9989RISCVTargetLowering::lowerStrictFPExtendOrRoundLike(
SDValue Op,
9994 MVT VT =
Op.getSimpleValueType();
9995 MVT SrcVT = Src.getSimpleValueType();
9996 MVT ContainerVT = VT;
10015 ? RISCVISD::STRICT_FP_EXTEND_VL
10016 : RISCVISD::STRICT_VFNCVT_ROD_VL;
10019 Chain, Src, Mask, VL);
10020 Chain = Src.getValue(1);
10024 ? RISCVISD::STRICT_FP_EXTEND_VL
10025 : RISCVISD::STRICT_FP_ROUND_VL;
10027 Chain, Src, Mask, VL);
10038RISCVTargetLowering::lowerVectorFPExtendOrRoundLike(
SDValue Op,
10041 Op.getOpcode() == ISD::VP_FP_ROUND ||
Op.getOpcode() == ISD::VP_FP_EXTEND;
10043 Op.getOpcode() == ISD::VP_FP_EXTEND ||
Op.getOpcode() == ISD::FP_EXTEND;
10048 MVT VT =
Op.getSimpleValueType();
10050 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
10053 MVT SrcVT = Src.getSimpleValueType();
10055 bool IsDirectExtend =
10063 bool IsDirectConv = IsDirectExtend || IsDirectTrunc;
10070 MVT ContainerVT = VT;
10073 Mask =
Op.getOperand(1);
10074 VL =
Op.getOperand(2);
10088 std::tie(Mask, VL) =
10091 unsigned ConvOpc = IsExtend ? RISCVISD::FP_EXTEND_VL : RISCVISD::FP_ROUND_VL;
10093 if (IsDirectConv) {
10094 Src = DAG.
getNode(ConvOpc,
DL, ContainerVT, Src, Mask, VL);
10100 unsigned InterConvOpc =
10101 IsExtend ? RISCVISD::FP_EXTEND_VL : RISCVISD::VFNCVT_ROD_VL;
10105 DAG.
getNode(InterConvOpc,
DL, InterVT, Src, Mask, VL);
10107 DAG.
getNode(ConvOpc,
DL, ContainerVT, IntermediateConv, Mask, VL);
10118static std::optional<MVT>
10124 const unsigned MinVLMAX = VectorBitsMin / EltSize;
10126 if (MaxIdx < MinVLMAX)
10128 else if (MaxIdx < MinVLMAX * 2)
10131 else if (MaxIdx < MinVLMAX * 4)
10136 return std::nullopt;
10144 return isUInt<5>(IdxC->getZExtValue());
10156 MVT VecVT =
Op.getSimpleValueType();
10157 MVT XLenVT = Subtarget.getXLenVT();
10172 if ((ValVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
10173 ValVT == MVT::bf16) {
10178 DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Val), Idx);
10182 MVT ContainerVT = VecVT;
10192 std::optional<unsigned> AlignedIdx;
10194 const unsigned OrigIdx = IdxC->getZExtValue();
10197 DL, DAG, Subtarget)) {
10198 ContainerVT = *ShrunkVT;
10206 if (
auto VLEN = Subtarget.getRealVLen(); VLEN && ContainerVT.
bitsGT(M1VT)) {
10209 unsigned RemIdx = OrigIdx % ElemsPerVReg;
10210 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
10213 ContainerVT = M1VT;
10220 bool IsLegalInsert = Subtarget.is64Bit() || Val.
getValueType() != MVT::i64;
10228 IsLegalInsert =
true;
10237 if (IsLegalInsert) {
10239 VecVT.
isFloatingPoint() ? RISCVISD::VFMV_S_F_VL : RISCVISD::VMV_S_X_VL;
10243 Vec = DAG.
getNode(
Opc,
DL, ContainerVT, Vec, Val, VL);
10253 if (Subtarget.hasVendorXRivosVisni() && VecVT.
isInteger() &&
10258 Vec = DAG.
getNode(RISCVISD::RI_VINSERT_VL,
DL, ContainerVT, Vec, Val, Idx,
10274 std::tie(ValLo, ValHi) = DAG.
SplitScalar(Val,
DL, MVT::i32, MVT::i32);
10275 MVT I32ContainerVT =
10285 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10286 Vec, Vec, ValLo, I32Mask, InsertI64VL);
10290 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10291 Tail, ValInVec, ValHi, I32Mask, InsertI64VL);
10293 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
10304 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10306 DAG.
getUNDEF(I32ContainerVT), ValLo,
10307 I32Mask, InsertI64VL);
10308 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10309 DAG.
getUNDEF(I32ContainerVT), ValInVec, ValHi,
10310 I32Mask, InsertI64VL);
10312 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
10325 Idx, Mask, InsertVL, Policy);
10343 EVT EltVT =
Op.getValueType();
10345 MVT XLenVT = Subtarget.getXLenVT();
10350 MVT ContainerVT = VecVT;
10357 DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Vec, Mask, VL);
10364 if (NumElts >= 8) {
10366 unsigned WidenVecLen;
10369 unsigned MaxEEW = Subtarget.getELen();
10374 "the number of elements should be power of 2");
10378 ExtractBitIdx = Idx;
10380 WideEltVT = LargestEltVT;
10383 ExtractElementIdx = DAG.
getNode(
10392 Vec = DAG.
getNode(ISD::BITCAST,
DL, WideVT, Vec);
10394 Vec, ExtractElementIdx);
10409 if ((EltVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
10410 EltVT == MVT::bf16) {
10416 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, EltVT, IntExtract);
10420 MVT ContainerVT = VecVT;
10430 const auto VLen = Subtarget.getRealVLen();
10432 IdxC && VLen && VecVT.
getSizeInBits().getKnownMinValue() > *VLen) {
10434 unsigned OrigIdx = IdxC->getZExtValue();
10437 unsigned RemIdx = OrigIdx % ElemsPerVReg;
10438 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
10439 unsigned ExtractIdx =
10443 ContainerVT = M1VT;
10448 std::optional<uint64_t> MaxIdx;
10452 MaxIdx = IdxC->getZExtValue();
10454 if (
auto SmallerVT =
10456 ContainerVT = *SmallerVT;
10463 if (Subtarget.hasVendorXRivosVisni() && EltVT.
isInteger() &&
10491 DAG.
getUNDEF(ContainerVT), Vec, Idx, Mask, VL);
10510 "Unexpected opcode");
10517 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
10522 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
10523 if (!
II || !
II->hasScalarOperand())
10526 unsigned SplatOp =
II->ScalarOperand + 1 + HasChain;
10527 assert(SplatOp <
Op.getNumOperands());
10539 if (OpVT.
bitsLT(XLenVT)) {
10546 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
10556 assert(
II->ScalarOperand > 0 &&
"Unexpected splat operand!");
10557 MVT VT =
Op.getOperand(SplatOp - 1).getSimpleValueType();
10560 assert(XLenVT == MVT::i32 && OpVT == MVT::i64 &&
10571 case Intrinsic::riscv_vslide1up:
10572 case Intrinsic::riscv_vslide1down:
10573 case Intrinsic::riscv_vslide1up_mask:
10574 case Intrinsic::riscv_vslide1down_mask: {
10576 unsigned NumOps =
Op.getNumOperands();
10577 bool IsMasked =
NumOps == 7;
10583 std::tie(ScalarLo, ScalarHi) =
10592 const auto [MinVLMAX, MaxVLMAX] =
10596 if (AVLInt <= MinVLMAX) {
10598 }
else if (AVLInt >= 2 * MaxVLMAX) {
10632 if (IntNo == Intrinsic::riscv_vslide1up ||
10633 IntNo == Intrinsic::riscv_vslide1up_mask) {
10634 Vec = DAG.
getNode(RISCVISD::VSLIDE1UP_VL,
DL, I32VT, Passthru, Vec,
10635 ScalarHi, I32Mask, I32VL);
10636 Vec = DAG.
getNode(RISCVISD::VSLIDE1UP_VL,
DL, I32VT, Passthru, Vec,
10637 ScalarLo, I32Mask, I32VL);
10639 Vec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32VT, Passthru, Vec,
10640 ScalarLo, I32Mask, I32VL);
10641 Vec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32VT, Passthru, Vec,
10642 ScalarHi, I32Mask, I32VL);
10660 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, Mask, Vec, MaskedOff,
10664 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, Mask, Vec, MaskedOff,
10691 const unsigned ElementWidth = 8;
10696 [[maybe_unused]]
unsigned MinVF =
10699 [[maybe_unused]]
unsigned VF =
N->getConstantOperandVal(2);
10703 bool Fractional = VF < LMul1VF;
10704 unsigned LMulVal = Fractional ? LMul1VF / VF : VF / LMul1VF;
10725 MVT ContainerVT = OpVT;
10733 SDValue Res = DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Op0, Mask, VL);
10741 return DAG.
getSelect(
DL, XLenVT, Setcc, VL, Res);
10752 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
10756 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
10757 if (!
II || !
II->hasScalarOperand())
10760 unsigned SplatOp =
II->ScalarOperand + 1;
10761 assert(SplatOp <
Op.getNumOperands());
10773 if (OpVT.
bitsLT(XLenVT)) {
10776 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
10787 EVT ValType = V.getValueType();
10788 if (ValType.isVector() && ValType.isFloatingPoint()) {
10791 ValType.getVectorElementCount());
10794 if (ValType.isFixedLengthVector()) {
10796 DAG, V.getSimpleValueType(), Subtarget);
10812 unsigned IntNo =
Op.getConstantOperandVal(0);
10814 MVT XLenVT = Subtarget.getXLenVT();
10819 case Intrinsic::riscv_tuple_insert: {
10824 return DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL,
Op.getValueType(), Vec,
10827 case Intrinsic::riscv_tuple_extract: {
10831 return DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL,
Op.getValueType(), Vec,
10834 case Intrinsic::thread_pointer: {
10838 case Intrinsic::riscv_orc_b:
10839 case Intrinsic::riscv_brev8:
10840 case Intrinsic::riscv_sha256sig0:
10841 case Intrinsic::riscv_sha256sig1:
10842 case Intrinsic::riscv_sha256sum0:
10843 case Intrinsic::riscv_sha256sum1:
10844 case Intrinsic::riscv_sm3p0:
10845 case Intrinsic::riscv_sm3p1: {
10848 case Intrinsic::riscv_orc_b:
Opc = RISCVISD::ORC_B;
break;
10849 case Intrinsic::riscv_brev8:
Opc = RISCVISD::BREV8;
break;
10850 case Intrinsic::riscv_sha256sig0:
Opc = RISCVISD::SHA256SIG0;
break;
10851 case Intrinsic::riscv_sha256sig1:
Opc = RISCVISD::SHA256SIG1;
break;
10852 case Intrinsic::riscv_sha256sum0:
Opc = RISCVISD::SHA256SUM0;
break;
10853 case Intrinsic::riscv_sha256sum1:
Opc = RISCVISD::SHA256SUM1;
break;
10854 case Intrinsic::riscv_sm3p0:
Opc = RISCVISD::SM3P0;
break;
10855 case Intrinsic::riscv_sm3p1:
Opc = RISCVISD::SM3P1;
break;
10860 case Intrinsic::riscv_sm4ks:
10861 case Intrinsic::riscv_sm4ed: {
10863 IntNo == Intrinsic::riscv_sm4ks ? RISCVISD::SM4KS : RISCVISD::SM4ED;
10868 case Intrinsic::riscv_zip:
10869 case Intrinsic::riscv_unzip: {
10871 IntNo == Intrinsic::riscv_zip ? RISCVISD::ZIP : RISCVISD::UNZIP;
10874 case Intrinsic::riscv_mopr:
10875 return DAG.
getNode(RISCVISD::MOP_R,
DL, XLenVT,
Op.getOperand(1),
10878 case Intrinsic::riscv_moprr: {
10879 return DAG.
getNode(RISCVISD::MOP_RR,
DL, XLenVT,
Op.getOperand(1),
10880 Op.getOperand(2),
Op.getOperand(3));
10882 case Intrinsic::riscv_clmul:
10883 return DAG.
getNode(RISCVISD::CLMUL,
DL, XLenVT,
Op.getOperand(1),
10885 case Intrinsic::riscv_clmulh:
10886 case Intrinsic::riscv_clmulr: {
10888 IntNo == Intrinsic::riscv_clmulh ? RISCVISD::CLMULH : RISCVISD::CLMULR;
10891 case Intrinsic::experimental_get_vector_length:
10893 case Intrinsic::experimental_cttz_elts:
10895 case Intrinsic::riscv_vmv_x_s: {
10899 case Intrinsic::riscv_vfmv_f_s:
10901 case Intrinsic::riscv_vmv_v_x:
10903 Op.getOperand(3),
Op.getSimpleValueType(),
DL, DAG,
10905 case Intrinsic::riscv_vfmv_v_f:
10906 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL,
Op.getValueType(),
10907 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
10908 case Intrinsic::riscv_vmv_s_x: {
10911 if (
Scalar.getValueType().bitsLE(XLenVT)) {
10913 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL,
Op.getValueType(),
10914 Op.getOperand(1), Scalar,
Op.getOperand(3));
10917 assert(
Scalar.getValueType() == MVT::i64 &&
"Unexpected scalar VT!");
10934 MVT VT =
Op.getSimpleValueType();
10939 if (
Op.getOperand(1).isUndef())
10940 return SplattedVal;
10949 DAG.
getNode(RISCVISD::SETCC_VL,
DL, MaskVT,
10952 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, SelectCond, SplattedVal,
10955 case Intrinsic::riscv_vfmv_s_f:
10956 return DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL,
Op.getSimpleValueType(),
10957 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
10959 case Intrinsic::riscv_vaesdf_vv:
10960 case Intrinsic::riscv_vaesdf_vs:
10961 case Intrinsic::riscv_vaesdm_vv:
10962 case Intrinsic::riscv_vaesdm_vs:
10963 case Intrinsic::riscv_vaesef_vv:
10964 case Intrinsic::riscv_vaesef_vs:
10965 case Intrinsic::riscv_vaesem_vv:
10966 case Intrinsic::riscv_vaesem_vs:
10967 case Intrinsic::riscv_vaeskf1:
10968 case Intrinsic::riscv_vaeskf2:
10969 case Intrinsic::riscv_vaesz_vs:
10970 case Intrinsic::riscv_vsm4k:
10971 case Intrinsic::riscv_vsm4r_vv:
10972 case Intrinsic::riscv_vsm4r_vs: {
10973 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
10974 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
10975 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
10980 case Intrinsic::riscv_vsm3c:
10981 case Intrinsic::riscv_vsm3me: {
10982 if (!
isValidEGW(8,
Op.getSimpleValueType(), Subtarget) ||
10983 !
isValidEGW(8,
Op->getOperand(1).getSimpleValueType(), Subtarget))
10988 case Intrinsic::riscv_vsha2ch:
10989 case Intrinsic::riscv_vsha2cl:
10990 case Intrinsic::riscv_vsha2ms: {
10991 if (
Op->getSimpleValueType(0).getScalarSizeInBits() == 64 &&
10992 !Subtarget.hasStdExtZvknhb())
10994 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
10995 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
10996 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
11000 case Intrinsic::riscv_sf_vc_v_x:
11001 case Intrinsic::riscv_sf_vc_v_i:
11002 case Intrinsic::riscv_sf_vc_v_xv:
11003 case Intrinsic::riscv_sf_vc_v_iv:
11004 case Intrinsic::riscv_sf_vc_v_vv:
11005 case Intrinsic::riscv_sf_vc_v_fv:
11006 case Intrinsic::riscv_sf_vc_v_xvv:
11007 case Intrinsic::riscv_sf_vc_v_ivv:
11008 case Intrinsic::riscv_sf_vc_v_vvv:
11009 case Intrinsic::riscv_sf_vc_v_fvv:
11010 case Intrinsic::riscv_sf_vc_v_xvw:
11011 case Intrinsic::riscv_sf_vc_v_ivw:
11012 case Intrinsic::riscv_sf_vc_v_vvw:
11013 case Intrinsic::riscv_sf_vc_v_fvw: {
11014 MVT VT =
Op.getSimpleValueType();
11051 MVT VT =
Op.getSimpleValueType();
11055 if (VT.isFloatingPoint()) {
11057 VT.getVectorElementCount());
11060 if (VT.isFixedLengthVector())
11070 if (VT.isFixedLengthVector())
11072 if (VT.isFloatingPoint())
11095 case Intrinsic::riscv_seg2_load_mask:
11096 case Intrinsic::riscv_seg3_load_mask:
11097 case Intrinsic::riscv_seg4_load_mask:
11098 case Intrinsic::riscv_seg5_load_mask:
11099 case Intrinsic::riscv_seg6_load_mask:
11100 case Intrinsic::riscv_seg7_load_mask:
11101 case Intrinsic::riscv_seg8_load_mask:
11104 case Intrinsic::riscv_sseg2_load_mask:
11105 case Intrinsic::riscv_sseg3_load_mask:
11106 case Intrinsic::riscv_sseg4_load_mask:
11107 case Intrinsic::riscv_sseg5_load_mask:
11108 case Intrinsic::riscv_sseg6_load_mask:
11109 case Intrinsic::riscv_sseg7_load_mask:
11110 case Intrinsic::riscv_sseg8_load_mask:
11118 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
11119 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
11120 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
11121 Intrinsic::riscv_vlseg8_mask};
11123 Intrinsic::riscv_vlsseg2_mask, Intrinsic::riscv_vlsseg3_mask,
11124 Intrinsic::riscv_vlsseg4_mask, Intrinsic::riscv_vlsseg5_mask,
11125 Intrinsic::riscv_vlsseg6_mask, Intrinsic::riscv_vlsseg7_mask,
11126 Intrinsic::riscv_vlsseg8_mask};
11129 unsigned NF =
Op->getNumValues() - 1;
11130 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
11132 MVT VT =
Op->getSimpleValueType(0);
11140 SDValue VL =
Op.getOperand(
Op.getNumOperands() - 1);
11141 SDValue Mask =
Op.getOperand(
Op.getNumOperands() - 2);
11142 MVT MaskVT = Mask.getSimpleValueType();
11143 MVT MaskContainerVT =
11148 IsStrided ? VlssegInts[NF - 2] : VlsegInts[NF - 2],
DL, XLenVT);
11164 Ops.insert(std::next(
Ops.begin(), 4),
Op.getOperand(3));
11168 Load->getMemoryVT(), Load->getMemOperand());
11170 for (
unsigned int RetIdx = 0; RetIdx < NF; RetIdx++) {
11172 Result.getValue(0),
11176 Results.push_back(Result.getValue(1));
11182 unsigned IntNo =
Op.getConstantOperandVal(1);
11186 case Intrinsic::riscv_seg2_load_mask:
11187 case Intrinsic::riscv_seg3_load_mask:
11188 case Intrinsic::riscv_seg4_load_mask:
11189 case Intrinsic::riscv_seg5_load_mask:
11190 case Intrinsic::riscv_seg6_load_mask:
11191 case Intrinsic::riscv_seg7_load_mask:
11192 case Intrinsic::riscv_seg8_load_mask:
11193 case Intrinsic::riscv_sseg2_load_mask:
11194 case Intrinsic::riscv_sseg3_load_mask:
11195 case Intrinsic::riscv_sseg4_load_mask:
11196 case Intrinsic::riscv_sseg5_load_mask:
11197 case Intrinsic::riscv_sseg6_load_mask:
11198 case Intrinsic::riscv_sseg7_load_mask:
11199 case Intrinsic::riscv_sseg8_load_mask:
11202 case Intrinsic::riscv_sf_vc_v_x_se:
11204 case Intrinsic::riscv_sf_vc_v_i_se:
11206 case Intrinsic::riscv_sf_vc_v_xv_se:
11208 case Intrinsic::riscv_sf_vc_v_iv_se:
11210 case Intrinsic::riscv_sf_vc_v_vv_se:
11212 case Intrinsic::riscv_sf_vc_v_fv_se:
11214 case Intrinsic::riscv_sf_vc_v_xvv_se:
11216 case Intrinsic::riscv_sf_vc_v_ivv_se:
11218 case Intrinsic::riscv_sf_vc_v_vvv_se:
11220 case Intrinsic::riscv_sf_vc_v_fvv_se:
11222 case Intrinsic::riscv_sf_vc_v_xvw_se:
11224 case Intrinsic::riscv_sf_vc_v_ivw_se:
11226 case Intrinsic::riscv_sf_vc_v_vvw_se:
11228 case Intrinsic::riscv_sf_vc_v_fvw_se:
11241 case Intrinsic::riscv_seg2_store_mask:
11242 case Intrinsic::riscv_seg3_store_mask:
11243 case Intrinsic::riscv_seg4_store_mask:
11244 case Intrinsic::riscv_seg5_store_mask:
11245 case Intrinsic::riscv_seg6_store_mask:
11246 case Intrinsic::riscv_seg7_store_mask:
11247 case Intrinsic::riscv_seg8_store_mask:
11250 case Intrinsic::riscv_sseg2_store_mask:
11251 case Intrinsic::riscv_sseg3_store_mask:
11252 case Intrinsic::riscv_sseg4_store_mask:
11253 case Intrinsic::riscv_sseg5_store_mask:
11254 case Intrinsic::riscv_sseg6_store_mask:
11255 case Intrinsic::riscv_sseg7_store_mask:
11256 case Intrinsic::riscv_sseg8_store_mask:
11265 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
11266 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
11267 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
11268 Intrinsic::riscv_vsseg8_mask};
11270 Intrinsic::riscv_vssseg2_mask, Intrinsic::riscv_vssseg3_mask,
11271 Intrinsic::riscv_vssseg4_mask, Intrinsic::riscv_vssseg5_mask,
11272 Intrinsic::riscv_vssseg6_mask, Intrinsic::riscv_vssseg7_mask,
11273 Intrinsic::riscv_vssseg8_mask};
11277 unsigned NF =
Op->getNumOperands() - (IsStrided ? 6 : 5);
11278 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
11280 MVT VT =
Op->getOperand(2).getSimpleValueType();
11286 SDValue VL =
Op.getOperand(
Op.getNumOperands() - 1);
11287 SDValue Mask =
Op.getOperand(
Op.getNumOperands() - 2);
11288 MVT MaskVT = Mask.getSimpleValueType();
11289 MVT MaskContainerVT =
11294 IsStrided ? VsssegInts[NF - 2] : VssegInts[NF - 2],
DL, XLenVT);
11300 for (
unsigned i = 0; i < NF; i++)
11302 RISCVISD::TUPLE_INSERT,
DL, VecTupTy, StoredVal,
11308 FixedIntrinsic->getChain(),
11317 Ops.insert(std::next(
Ops.begin(), 4),
11318 Op.getOperand(
Op.getNumOperands() - 3));
11322 FixedIntrinsic->getMemoryVT(), FixedIntrinsic->getMemOperand());
11327 unsigned IntNo =
Op.getConstantOperandVal(1);
11331 case Intrinsic::riscv_seg2_store_mask:
11332 case Intrinsic::riscv_seg3_store_mask:
11333 case Intrinsic::riscv_seg4_store_mask:
11334 case Intrinsic::riscv_seg5_store_mask:
11335 case Intrinsic::riscv_seg6_store_mask:
11336 case Intrinsic::riscv_seg7_store_mask:
11337 case Intrinsic::riscv_seg8_store_mask:
11338 case Intrinsic::riscv_sseg2_store_mask:
11339 case Intrinsic::riscv_sseg3_store_mask:
11340 case Intrinsic::riscv_sseg4_store_mask:
11341 case Intrinsic::riscv_sseg5_store_mask:
11342 case Intrinsic::riscv_sseg6_store_mask:
11343 case Intrinsic::riscv_sseg7_store_mask:
11344 case Intrinsic::riscv_sseg8_store_mask:
11347 case Intrinsic::riscv_sf_vc_xv_se:
11349 case Intrinsic::riscv_sf_vc_iv_se:
11351 case Intrinsic::riscv_sf_vc_vv_se:
11353 case Intrinsic::riscv_sf_vc_fv_se:
11355 case Intrinsic::riscv_sf_vc_xvv_se:
11357 case Intrinsic::riscv_sf_vc_ivv_se:
11359 case Intrinsic::riscv_sf_vc_vvv_se:
11361 case Intrinsic::riscv_sf_vc_fvv_se:
11363 case Intrinsic::riscv_sf_vc_xvw_se:
11365 case Intrinsic::riscv_sf_vc_ivw_se:
11367 case Intrinsic::riscv_sf_vc_vvw_se:
11369 case Intrinsic::riscv_sf_vc_fvw_se:
11377 switch (ISDOpcode) {
11380 case ISD::VP_REDUCE_ADD:
11381 case ISD::VECREDUCE_ADD:
11382 return RISCVISD::VECREDUCE_ADD_VL;
11383 case ISD::VP_REDUCE_UMAX:
11384 case ISD::VECREDUCE_UMAX:
11385 return RISCVISD::VECREDUCE_UMAX_VL;
11386 case ISD::VP_REDUCE_SMAX:
11387 case ISD::VECREDUCE_SMAX:
11388 return RISCVISD::VECREDUCE_SMAX_VL;
11389 case ISD::VP_REDUCE_UMIN:
11390 case ISD::VECREDUCE_UMIN:
11391 return RISCVISD::VECREDUCE_UMIN_VL;
11392 case ISD::VP_REDUCE_SMIN:
11393 case ISD::VECREDUCE_SMIN:
11394 return RISCVISD::VECREDUCE_SMIN_VL;
11395 case ISD::VP_REDUCE_AND:
11396 case ISD::VECREDUCE_AND:
11397 return RISCVISD::VECREDUCE_AND_VL;
11398 case ISD::VP_REDUCE_OR:
11399 case ISD::VECREDUCE_OR:
11400 return RISCVISD::VECREDUCE_OR_VL;
11401 case ISD::VP_REDUCE_XOR:
11402 case ISD::VECREDUCE_XOR:
11403 return RISCVISD::VECREDUCE_XOR_VL;
11404 case ISD::VP_REDUCE_FADD:
11405 return RISCVISD::VECREDUCE_FADD_VL;
11406 case ISD::VP_REDUCE_SEQ_FADD:
11407 return RISCVISD::VECREDUCE_SEQ_FADD_VL;
11408 case ISD::VP_REDUCE_FMAX:
11409 case ISD::VP_REDUCE_FMAXIMUM:
11410 return RISCVISD::VECREDUCE_FMAX_VL;
11411 case ISD::VP_REDUCE_FMIN:
11412 case ISD::VP_REDUCE_FMINIMUM:
11413 return RISCVISD::VECREDUCE_FMIN_VL;
11422 SDValue Vec =
Op.getOperand(IsVP ? 1 : 0);
11424 assert((
Op.getOpcode() == ISD::VECREDUCE_AND ||
11425 Op.getOpcode() == ISD::VECREDUCE_OR ||
11426 Op.getOpcode() == ISD::VECREDUCE_XOR ||
11427 Op.getOpcode() == ISD::VP_REDUCE_AND ||
11428 Op.getOpcode() == ISD::VP_REDUCE_OR ||
11429 Op.getOpcode() == ISD::VP_REDUCE_XOR) &&
11430 "Unexpected reduction lowering");
11432 MVT XLenVT = Subtarget.getXLenVT();
11434 MVT ContainerVT = VecVT;
11442 Mask =
Op.getOperand(2);
11443 VL =
Op.getOperand(3);
11445 std::tie(Mask, VL) =
11450 switch (
Op.getOpcode()) {
11453 case ISD::VECREDUCE_AND:
11454 case ISD::VP_REDUCE_AND: {
11458 Vec = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Vec, TrueMask, VL);
11461 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11465 case ISD::VECREDUCE_OR:
11466 case ISD::VP_REDUCE_OR:
11468 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11471 case ISD::VECREDUCE_XOR:
11472 case ISD::VP_REDUCE_XOR: {
11475 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11496 return DAG.
getNode(BaseOpc,
DL,
Op.getValueType(), SetCC,
Op.getOperand(0));
11502 return (RegisterAVL && RegisterAVL->getReg() == RISCV::X0) ||
11503 (ImmAVL && ImmAVL->getZExtValue() >= 1);
11519 auto InnerVT = VecVT.
bitsLE(M1VT) ? VecVT : M1VT;
11523 auto InnerVL = NonZeroAVL ? VL : DAG.
getConstant(1,
DL, XLenVT);
11526 if (M1VT != InnerVT)
11531 SDValue Ops[] = {PassThru, Vec, InitialValue, Mask, VL, Policy};
11549 VecEVT =
Lo.getValueType();
11562 MVT ContainerVT = VecVT;
11581 Mask, VL,
DL, DAG, Subtarget);
11587static std::tuple<unsigned, SDValue, SDValue>
11591 auto Flags =
Op->getFlags();
11592 unsigned Opcode =
Op.getOpcode();
11596 case ISD::VECREDUCE_FADD: {
11600 return std::make_tuple(RISCVISD::VECREDUCE_FADD_VL,
Op.getOperand(0), Zero);
11602 case ISD::VECREDUCE_SEQ_FADD:
11603 return std::make_tuple(RISCVISD::VECREDUCE_SEQ_FADD_VL,
Op.getOperand(1),
11605 case ISD::VECREDUCE_FMINIMUM:
11606 case ISD::VECREDUCE_FMAXIMUM:
11607 case ISD::VECREDUCE_FMIN:
11608 case ISD::VECREDUCE_FMAX: {
11611 (Opcode == ISD::VECREDUCE_FMIN || Opcode == ISD::VECREDUCE_FMINIMUM)
11612 ? RISCVISD::VECREDUCE_FMIN_VL
11613 : RISCVISD::VECREDUCE_FMAX_VL;
11614 return std::make_tuple(RVVOpc,
Op.getOperand(0), Front);
11622 MVT VecEltVT =
Op.getSimpleValueType();
11624 unsigned RVVOpcode;
11625 SDValue VectorVal, ScalarVal;
11626 std::tie(RVVOpcode, VectorVal, ScalarVal) =
11630 MVT ContainerVT = VecVT;
11636 MVT ResVT =
Op.getSimpleValueType();
11639 VL,
DL, DAG, Subtarget);
11640 if (
Op.getOpcode() != ISD::VECREDUCE_FMINIMUM &&
11641 Op.getOpcode() != ISD::VECREDUCE_FMAXIMUM)
11644 if (
Op->getFlags().hasNoNaNs())
11650 {VectorVal, VectorVal, DAG.getCondCode(ISD::SETNE),
11651 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
11652 MVT XLenVT = Subtarget.getXLenVT();
11653 SDValue CPop = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, IsNan, Mask, VL);
11657 DL, ResVT, NoNaNs, Res,
11664 unsigned Opc =
Op.getOpcode();
11668 MVT XLenVT = Subtarget.getXLenVT();
11687 Vec, Mask, VL,
DL, DAG, Subtarget);
11688 if ((
Opc != ISD::VP_REDUCE_FMINIMUM &&
Opc != ISD::VP_REDUCE_FMAXIMUM) ||
11689 Op->getFlags().hasNoNaNs())
11696 RISCVISD::SETCC_VL,
DL, PredVT,
11698 SDValue VCPop = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, IsNaN, Mask, VL);
11706 DL, ResVT, NoNaNs, Res,
11718 MVT XLenVT = Subtarget.getXLenVT();
11719 unsigned OrigIdx =
Op.getConstantOperandVal(2);
11720 const RISCVRegisterInfo *
TRI = Subtarget.getRegisterInfo();
11722 if (OrigIdx == 0 && Vec.
isUndef())
11733 assert(OrigIdx % 8 == 0 &&
"Invalid index");
11736 "Unexpected mask vector lowering");
11766 const auto VLen = Subtarget.getRealVLen();
11768 MVT ContainerVT = VecVT;
11790 if (OrigIdx == 0) {
11792 DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, ContainerVT, Vec, SubVec, VL);
11795 SubVec =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, Vec, SubVec,
11796 SlideupAmt, Mask, VL, Policy);
11804 MVT ContainerVecVT = VecVT;
11810 MVT ContainerSubVecVT = SubVecVT;
11816 unsigned SubRegIdx;
11817 ElementCount RemIdx;
11826 ContainerVecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
11827 SubRegIdx = Decompose.first;
11829 (OrigIdx % Vscale));
11833 ContainerVecVT, ContainerSubVecVT, OrigIdx,
TRI);
11834 SubRegIdx = Decompose.first;
11840 Subtarget.expandVScale(SubVecVT.
getSizeInBits()).getKnownMinValue()));
11841 bool ExactlyVecRegSized =
11843 .isKnownMultipleOf(Subtarget.expandVScale(VecRegSize));
11858 if (RemIdx.
isZero() && (ExactlyVecRegSized || Vec.
isUndef())) {
11862 if (SubRegIdx == RISCV::NoSubRegister) {
11884 MVT InterSubVT = ContainerVecVT;
11885 SDValue AlignedExtract = Vec;
11907 if (Subtarget.expandVScale(EndIndex) ==
11914 SubVec = DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, InterSubVT, AlignedExtract,
11922 SubVec =
getVSlideup(DAG, Subtarget,
DL, InterSubVT, AlignedExtract, SubVec,
11923 SlideupAmt, Mask, VL, Policy);
11928 if (ContainerVecVT.
bitsGT(InterSubVT))
11936 return DAG.
getBitcast(
Op.getSimpleValueType(), SubVec);
11942 MVT SubVecVT =
Op.getSimpleValueType();
11946 MVT XLenVT = Subtarget.getXLenVT();
11947 unsigned OrigIdx =
Op.getConstantOperandVal(1);
11948 const RISCVRegisterInfo *
TRI = Subtarget.getRegisterInfo();
11963 assert(OrigIdx % 8 == 0 &&
"Invalid index");
11966 "Unexpected mask vector lowering");
11992 const auto VLen = Subtarget.getRealVLen();
12000 MVT ContainerVT = VecVT;
12008 if (
auto ShrunkVT =
12010 ContainerVT = *ShrunkVT;
12022 DAG.
getUNDEF(ContainerVT), Vec, SlidedownAmt, Mask, VL);
12033 MVT ContainerSubVecVT = SubVecVT;
12037 unsigned SubRegIdx;
12038 ElementCount RemIdx;
12047 VecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
12048 SubRegIdx = Decompose.first;
12050 (OrigIdx % Vscale));
12054 VecVT, ContainerSubVecVT, OrigIdx,
TRI);
12055 SubRegIdx = Decompose.first;
12082 MVT InterSubVT = VecVT;
12087 assert(SubRegIdx != RISCV::NoSubRegister);
12106 Vec, SlidedownAmt, Mask, VL);
12114 return DAG.
getBitcast(
Op.getSimpleValueType(), Slidedown);
12121 MVT VT =
N.getSimpleValueType();
12125 assert(
Op.getSimpleValueType() == VT &&
12126 "Operands and result must be same type");
12130 unsigned NumVals =
N->getNumValues();
12133 NumVals,
N.getValueType().changeVectorElementType(MVT::i8)));
12136 for (
unsigned I = 0;
I < NumVals;
I++) {
12142 if (TruncVals.
size() > 1)
12144 return TruncVals.
front();
12150 MVT VecVT =
Op.getSimpleValueType();
12152 const unsigned Factor =
Op->getNumValues();
12163 for (
unsigned i = 0U; i < Factor; ++i)
12172 for (
unsigned i = 0U; i < Factor; ++i)
12182 for (
unsigned i = 0; i != Factor; ++i) {
12185 Ops[i * 2 + 1] = OpHi;
12196 for (
unsigned i = 0; i != Factor; ++i)
12203 if (Subtarget.hasVendorXRivosVizip() && Factor == 2) {
12204 MVT VT =
Op->getSimpleValueType(0);
12229 lowerVZIP(RISCVISD::RI_VUNZIP2A_VL, V1, V2,
DL, DAG, Subtarget);
12231 lowerVZIP(RISCVISD::RI_VUNZIP2B_VL, V1, V2,
DL, DAG, Subtarget);
12264 EvenSplat = DAG.
getBitcast(MVT::nxv64i1, EvenSplat);
12268 OddSplat = DAG.
getBitcast(MVT::nxv64i1, OddSplat);
12273 EvenMask, DAG.
getUNDEF(ConcatVT));
12285 MVT XLenVT = Subtarget.getXLenVT();
12307 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
12308 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
12309 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
12310 Intrinsic::riscv_vlseg8_mask};
12334 for (
unsigned i = 0U; i < Factor; ++i)
12335 Res[i] = DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL, VecVT, Load,
12344 MVT VecVT =
Op.getSimpleValueType();
12357 for (
unsigned i = 0U; i < Factor; ++i)
12365 for (
unsigned i = 0U; i < Factor; ++i)
12371 MVT XLenVT = Subtarget.getXLenVT();
12378 for (
unsigned i = 0; i != Factor; ++i) {
12381 Ops[i + Factor] = OpHi;
12392 for (
unsigned i = 0; i != Factor; ++i) {
12393 unsigned IdxLo = 2 * i;
12394 unsigned IdxHi = 2 * i + 1;
12396 Res[IdxLo / Factor].getValue(IdxLo % Factor),
12397 Res[IdxHi / Factor].getValue(IdxHi % Factor));
12415 EVT PtrVT =
StackPtr.getValueType();
12421 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
12422 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
12423 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
12424 Intrinsic::riscv_vsseg8_mask,
12432 for (
unsigned i = 0; i < Factor; i++)
12434 DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VecTupTy, StoredVal,
12457 for (
unsigned i = 0; i != Factor; ++i) {
12461 Loads[i] = DAG.
getLoad(VecVT,
DL, Chain, StackPtr, PtrInfo);
12469 if (Subtarget.hasVendorXRivosVizip() && !
Op.getOperand(0).isUndef() &&
12470 !
Op.getOperand(1).isUndef()) {
12490 Op.getOperand(0),
Op.getOperand(1));
12514 DAG.
getNode(RISCVISD::ADD_VL,
DL, IdxVT, Idx, VLMax, Idx, OddMask, VL);
12519 Interleaved = DAG.
getNode(RISCVISD::VRGATHEREI16_VV_VL,
DL, ConcatVT,
12536 MVT VT =
Op.getSimpleValueType();
12538 MVT XLenVT = Subtarget.getXLenVT();
12541 uint64_t StepValImm =
Op.getConstantOperandVal(0);
12542 if (StepValImm != 1) {
12551 VL, VT,
DL, DAG, Subtarget);
12566 MVT VecVT =
Op.getSimpleValueType();
12575 MVT ContainerVT = VecVT;
12582 MVT XLenVT = Subtarget.getXLenVT();
12628 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
12629 unsigned MaxVLMAX =
12634 unsigned GatherOpc = RISCVISD::VRGATHER_VV_VL;
12639 if (MaxVLMAX > 256 && EltSize == 8) {
12653 LoVT.getVectorMinNumElements());
12658 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
12666 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
12691 DAG.
getUNDEF(ContainerVT), Mask, VL);
12702 MVT XLenVT = Subtarget.getXLenVT();
12703 MVT VecVT =
Op.getSimpleValueType();
12708 SDValue DownOffset, UpOffset;
12709 if (ImmValue >= 0) {
12724 DAG, Subtarget,
DL, VecVT, DAG.
getUNDEF(VecVT), V1, DownOffset, TrueMask,
12725 Subtarget.hasVLDependentLatency() ? UpOffset
12727 return getVSlideup(DAG, Subtarget,
DL, VecVT, SlideDown, V2, UpOffset,
12733RISCVTargetLowering::lowerFixedLengthVectorLoadToRVV(
SDValue Op,
12739 Load->getMemoryVT(),
12740 *
Load->getMemOperand()) &&
12741 "Expecting a correctly-aligned load");
12743 MVT VT =
Op.getSimpleValueType();
12744 MVT XLenVT = Subtarget.getXLenVT();
12749 const auto [MinVLMAX, MaxVLMAX] =
12753 MachineMemOperand *MMO =
Load->getMemOperand();
12766 IsMaskOp ? Intrinsic::riscv_vlm : Intrinsic::riscv_vle,
DL, XLenVT);
12770 Ops.push_back(
Load->getBasePtr());
12772 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
12775 Load->getMemoryVT(),
Load->getMemOperand());
12782RISCVTargetLowering::lowerFixedLengthVectorStoreToRVV(
SDValue Op,
12788 Store->getMemoryVT(),
12789 *
Store->getMemOperand()) &&
12790 "Expecting a correctly-aligned store");
12794 MVT XLenVT = Subtarget.getXLenVT();
12810 const auto [MinVLMAX, MaxVLMAX] =
12814 MachineMemOperand *MMO =
Store->getMemOperand();
12824 IsMaskOp ? Intrinsic::riscv_vsm : Intrinsic::riscv_vse,
DL, XLenVT);
12827 {Store->getChain(), IntID, NewValue, Store->getBasePtr(), VL},
12828 Store->getMemoryVT(),
Store->getMemOperand());
12834 MVT VT =
Op.getSimpleValueType();
12837 EVT MemVT = MemSD->getMemoryVT();
12838 MachineMemOperand *MMO = MemSD->getMemOperand();
12839 SDValue Chain = MemSD->getChain();
12843 bool IsExpandingLoad =
false;
12845 Mask = VPLoad->getMask();
12847 VL = VPLoad->getVectorLength();
12850 Mask = MLoad->getMask();
12851 PassThru = MLoad->getPassThru();
12852 IsExpandingLoad = MLoad->isExpandingLoad();
12857 MVT XLenVT = Subtarget.getXLenVT();
12859 MVT ContainerVT = VT;
12873 if (!IsUnmasked && IsExpandingLoad) {
12876 DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Mask,
12880 unsigned IntID = IsUnmasked || IsExpandingLoad ? Intrinsic::riscv_vle
12881 : Intrinsic::riscv_vle_mask;
12883 if (IntID == Intrinsic::riscv_vle)
12886 Ops.push_back(PassThru);
12887 Ops.push_back(BasePtr);
12888 if (IntID == Intrinsic::riscv_vle_mask)
12889 Ops.push_back(Mask);
12891 if (IntID == Intrinsic::riscv_vle_mask)
12894 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
12898 Chain =
Result.getValue(1);
12900 MVT IndexVT = ContainerVT;
12905 bool UseVRGATHEREI16 =
false;
12913 UseVRGATHEREI16 =
true;
12919 DAG.
getUNDEF(IndexVT), Mask, ExpandingVL);
12921 DAG.
getNode(UseVRGATHEREI16 ? RISCVISD::VRGATHEREI16_VV_VL
12922 : RISCVISD::VRGATHER_VV_VL,
12923 DL, ContainerVT, Result, Iota, PassThru, Mask, ExpandingVL);
12934 MVT VT =
Op->getSimpleValueType(0);
12937 EVT MemVT = VPLoadFF->getMemoryVT();
12938 MachineMemOperand *MMO = VPLoadFF->getMemOperand();
12939 SDValue Chain = VPLoadFF->getChain();
12943 SDValue VL = VPLoadFF->getVectorLength();
12945 MVT XLenVT = Subtarget.getXLenVT();
12947 MVT ContainerVT = VT;
12954 unsigned IntID = Intrinsic::riscv_vleff_mask;
12964 SDVTList VTs = DAG.
getVTList({ContainerVT,
Op->getValueType(1), MVT::Other});
12969 Chain =
Result.getValue(2);
12982 EVT MemVT = MemSD->getMemoryVT();
12983 MachineMemOperand *MMO = MemSD->getMemOperand();
12984 SDValue Chain = MemSD->getChain();
12988 bool IsCompressingStore =
false;
12990 Val = VPStore->getValue();
12991 Mask = VPStore->getMask();
12992 VL = VPStore->getVectorLength();
12995 Val = MStore->getValue();
12996 Mask = MStore->getMask();
12997 IsCompressingStore = MStore->isCompressingStore();
13004 MVT XLenVT = Subtarget.getXLenVT();
13006 MVT ContainerVT = VT;
13011 if (!IsUnmasked || IsCompressingStore) {
13020 if (IsCompressingStore) {
13023 DAG.
getUNDEF(ContainerVT), Val, Mask, VL);
13025 DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Mask,
13030 IsUnmasked ? Intrinsic::riscv_vse : Intrinsic::riscv_vse_mask;
13032 Ops.push_back(Val);
13033 Ops.push_back(BasePtr);
13035 Ops.push_back(Mask);
13050 MVT XLenVT = Subtarget.getXLenVT();
13051 MVT ContainerVT = VT;
13064 Passthru, Val, Mask, VL);
13074 unsigned Opc =
Op.getOpcode();
13081 MVT VT =
Op.getSimpleValueType();
13089 SDVTList VTList =
Op->getVTList();
13114 MVT ContainerInVT = InVT;
13132 RISCVISD::STRICT_FSETCC_VL,
DL, DAG.
getVTList(MaskVT, MVT::Other),
13133 {Chain, Op1, Op1, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
13136 RISCVISD::STRICT_FSETCC_VL,
DL, DAG.
getVTList(MaskVT, MVT::Other),
13137 {Chain, Op2, Op2, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
13140 DAG.
getNode(RISCVISD::VMAND_VL,
DL, MaskVT, OrderMask1, OrderMask2, VL);
13143 Res = DAG.
getNode(RISCVISD::STRICT_FSETCCS_VL,
DL,
13145 {Chain, Op1, Op2, CC, Mask, Mask, VL});
13148 : RISCVISD::STRICT_FSETCCS_VL;
13150 {Chain, Op1, Op2, CC, DAG.getUNDEF(MaskVT), Mask, VL});
13163 MVT VT =
Op.getSimpleValueType();
13167 "Unexpected type for ISD::ABS");
13169 MVT ContainerVT = VT;
13176 if (
Op->getOpcode() == ISD::VP_ABS) {
13177 Mask =
Op->getOperand(1);
13181 VL =
Op->getOperand(2);
13186 RISCVISD::VMV_V_X_VL,
DL, ContainerVT, DAG.
getUNDEF(ContainerVT),
13189 DAG.
getUNDEF(ContainerVT), Mask, VL);
13191 DAG.
getUNDEF(ContainerVT), Mask, VL);
13200 const auto &TSInfo =
13204 bool HasPassthruOp = TSInfo.hasPassthruOp(NewOpc);
13205 bool HasMask = TSInfo.hasMaskOp(NewOpc);
13207 MVT VT =
Op.getSimpleValueType();
13212 for (
const SDValue &V :
Op->op_values()) {
13216 if (!
V.getValueType().isVector()) {
13222 assert(useRVVForFixedLengthVectorVT(
V.getSimpleValueType()) &&
13223 "Only fixed length vectors are supported!");
13225 V.getSimpleValueType().getVectorElementType());
13234 Ops.push_back(Mask);
13239 if (
Op->isStrictFPOpcode()) {
13258 const auto &TSInfo =
13262 bool HasPassthruOp = TSInfo.hasPassthruOp(RISCVISDOpc);
13265 MVT VT =
Op.getSimpleValueType();
13268 MVT ContainerVT = VT;
13277 if (HasPassthruOp) {
13280 if (*MaskIdx ==
OpIdx.index())
13284 if (
Op.getOpcode() == ISD::VP_MERGE) {
13286 Ops.push_back(
Ops.back());
13288 assert(
Op.getOpcode() == ISD::VP_SELECT);
13295 if (RISCVISDOpc == RISCVISD::VFCVT_RM_X_F_VL &&
13298 Subtarget.getXLenVT()));
13300 if (!
V.getValueType().isFixedLengthVector()) {
13305 MVT OpVT =
V.getSimpleValueType();
13307 assert(useRVVForFixedLengthVectorVT(OpVT) &&
13308 "Only fixed length vectors are supported!");
13323 MVT VT =
Op.getSimpleValueType();
13329 MVT ContainerVT = VT;
13336 MVT XLenVT = Subtarget.getXLenVT();
13339 DAG.
getUNDEF(ContainerVT), Zero, VL);
13342 Op.getOpcode() == ISD::VP_ZERO_EXTEND ? 1 : -1,
DL, XLenVT);
13344 DAG.
getUNDEF(ContainerVT), SplatValue, VL);
13347 ZeroSplat, DAG.
getUNDEF(ContainerVT), VL);
13356 MVT VT =
Op.getSimpleValueType();
13364 MVT ContainerVT = VT;
13372 SDValue AllOneMask = DAG.
getNode(RISCVISD::VMSET_VL,
DL, ContainerVT, VL);
13374 switch (Condition) {
13379 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, Op2, VL);
13384 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, Op2, VL);
13386 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, AllOneMask, VL);
13394 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, AllOneMask, VL);
13395 Result = DAG.
getNode(RISCVISD::VMAND_VL,
DL, ContainerVT, Temp, Op2, VL);
13403 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op2, AllOneMask, VL);
13404 Result = DAG.
getNode(RISCVISD::VMAND_VL,
DL, ContainerVT, Op1, Temp, VL);
13412 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, AllOneMask, VL);
13413 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, Op2, VL);
13421 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op2, AllOneMask, VL);
13422 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, Op1, VL);
13442 MVT DstVT =
Op.getSimpleValueType();
13443 MVT SrcVT = Src.getSimpleValueType();
13456 if (DstEltSize >= SrcEltSize) {
13460 unsigned RISCVISDExtOpc = RISCVISDOpc == RISCVISD::SINT_TO_FP_VL
13461 ? RISCVISD::VSEXT_VL
13462 : RISCVISD::VZEXT_VL;
13465 if (SrcEltSize == 1) {
13467 MVT XLenVT = Subtarget.getXLenVT();
13472 RISCVISDExtOpc == RISCVISD::VZEXT_VL ? 1 : -1,
DL, XLenVT);
13475 Src = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, IntVT, Src, OneSplat,
13476 ZeroSplat, DAG.
getUNDEF(IntVT), VL);
13477 }
else if (DstEltSize > (2 * SrcEltSize)) {
13481 Src = DAG.
getNode(RISCVISDExtOpc,
DL, IntVT, Src, Mask, VL);
13487 "Wrong input/output vector types");
13490 if (DstEltSize > (2 * SrcEltSize)) {
13495 DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, InterimFVT, Src, Mask, VL);
13506 MVT InterimFVT = DstVT;
13507 if (SrcEltSize > (2 * DstEltSize)) {
13508 assert(SrcEltSize == (4 * DstEltSize) &&
"Unexpected types!");
13515 if (InterimFVT != DstVT) {
13517 Result = DAG.
getNode(RISCVISD::FP_ROUND_VL,
DL, DstVT, Src, Mask, VL);
13521 "Wrong input/output vector types");
13525 if (DstEltSize == 1) {
13528 assert(SrcEltSize >= 16 &&
"Unexpected FP type!");
13535 MVT XLenVT = Subtarget.getXLenVT();
13537 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, InterimIVT,
13538 DAG.
getUNDEF(InterimIVT), SplatZero, VL);
13548 while (InterimIVT != DstVT) {
13560 MVT VT =
Op.getSimpleValueType();
13569 MVT VT =
Op.getSimpleValueType();
13570 MVT XLenVT = Subtarget.getXLenVT();
13583 MVT ContainerVT = VT;
13603 TrueVal = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, PromotedVT, TrueVal, SplatOne,
13604 SplatZero, DAG.
getUNDEF(PromotedVT), VL);
13607 SplatOne, SplatZero, DAG.
getUNDEF(PromotedVT), VLMax);
13611 TrueVal, FalseVal, FalseVal, VL);
13616 RISCVISD::SETCC_VL,
DL, ContainerVT,
13626RISCVTargetLowering::lowerVPSpliceExperimental(
SDValue Op,
13628 using namespace SDPatternMatch;
13639 const MVT XLenVT = Subtarget.getXLenVT();
13640 MVT VT =
Op.getSimpleValueType();
13641 MVT ContainerVT = VT;
13651 if (IsMaskVector) {
13661 Op1 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, Op1, SplatOneOp1,
13662 SplatZeroOp1, DAG.
getUNDEF(ContainerVT), EVL1);
13670 Op2 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, Op2, SplatOneOp2,
13671 SplatZeroOp2, DAG.
getUNDEF(ContainerVT), EVL2);
13674 auto getVectorFirstEle = [](
SDValue Vec) {
13687 if (
auto FirstEle = getVectorFirstEle(
Op->getOperand(0))) {
13690 if ((EltVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
13691 EltVT == MVT::bf16) {
13699 : RISCVISD::VSLIDE1UP_VL,
13700 DL, ContainerVT, DAG.
getUNDEF(ContainerVT), Op2,
13701 FirstEle, Mask, EVL2);
13711 SDValue DownOffset, UpOffset;
13712 if (ImmValue >= 0) {
13726 DAG.
getUNDEF(ContainerVT), Op1, DownOffset, Mask,
13727 Subtarget.hasVLDependentLatency() ? UpOffset : EVL2);
13731 if (IsMaskVector) {
13735 {Result, DAG.getConstant(0, DL, ContainerVT),
13736 DAG.getCondCode(ISD::SETNE), DAG.getUNDEF(getMaskTypeFor(ContainerVT)),
13751 MVT VT =
Op.getSimpleValueType();
13753 MVT ContainerVT = VT;
13764 DAG.
getNode(
C->isZero() ? RISCVISD::VMCLR_VL : RISCVISD::VMSET_VL,
DL,
13787RISCVTargetLowering::lowerVPReverseExperimental(
SDValue Op,
13790 MVT VT =
Op.getSimpleValueType();
13791 MVT XLenVT = Subtarget.getXLenVT();
13797 MVT ContainerVT = VT;
13805 MVT GatherVT = ContainerVT;
13809 if (IsMaskVector) {
13819 Op1 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, IndicesVT, Op1, SplatOne,
13820 SplatZero, DAG.
getUNDEF(IndicesVT), EVL);
13825 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
13826 unsigned MaxVLMAX =
13829 unsigned GatherOpc = RISCVISD::VRGATHER_VV_VL;
13835 if (MaxVLMAX > 256 && EltSize == 8) {
13863 DAG.
getUNDEF(GatherVT), Result, Diff, Mask, EVL);
13865 if (IsMaskVector) {
13868 DAG.
getNode(RISCVISD::SETCC_VL,
DL, ContainerVT,
13881 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
13888 DAG.
getUNDEF(IndicesVT), VecLen, EVL);
13889 SDValue VRSUB = DAG.
getNode(RISCVISD::SUB_VL,
DL, IndicesVT, VecLenSplat, VID,
13890 DAG.
getUNDEF(IndicesVT), Mask, EVL);
13892 DAG.
getUNDEF(GatherVT), Mask, EVL);
13894 if (IsMaskVector) {
13897 RISCVISD::SETCC_VL,
DL, ContainerVT,
13909 MVT VT =
Op.getSimpleValueType();
13911 return lowerVPOp(
Op, DAG);
13918 MVT ContainerVT = VT;
13936 MVT XLenVT = Subtarget.getXLenVT();
13937 MVT VT =
Op.getSimpleValueType();
13938 MVT ContainerVT = VT;
13942 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
13950 : Intrinsic::riscv_vlse_mask,
13953 DAG.
getUNDEF(ContainerVT), VPNode->getBasePtr(),
13954 VPNode->getStride()};
13960 Ops.push_back(Mask);
13962 Ops.push_back(VPNode->getVectorLength());
13966 Ops.push_back(Policy);
13971 VPNode->getMemoryVT(), VPNode->getMemOperand());
13983 MVT XLenVT = Subtarget.getXLenVT();
13986 SDValue StoreVal = VPNode->getValue();
13988 MVT ContainerVT = VT;
13999 : Intrinsic::riscv_vsse_mask,
14002 VPNode->getBasePtr(), VPNode->getStride()};
14008 Ops.push_back(Mask);
14010 Ops.push_back(VPNode->getVectorLength());
14013 Ops, VPNode->getMemoryVT(),
14014 VPNode->getMemOperand());
14026 MVT VT =
Op.getSimpleValueType();
14029 EVT MemVT = MemSD->getMemoryVT();
14030 MachineMemOperand *MMO = MemSD->getMemOperand();
14031 SDValue Chain = MemSD->getChain();
14038 Index = VPGN->getIndex();
14039 Mask = VPGN->getMask();
14041 VL = VPGN->getVectorLength();
14047 Index = MGN->getIndex();
14048 Mask = MGN->getMask();
14049 PassThru = MGN->getPassThru();
14053 MVT IndexVT =
Index.getSimpleValueType();
14054 MVT XLenVT = Subtarget.getXLenVT();
14057 "Unexpected VTs!");
14058 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
14061 "Unexpected extending MGATHER/VP_GATHER");
14067 MVT ContainerVT = VT;
14091 IsUnmasked ? Intrinsic::riscv_vluxei : Intrinsic::riscv_vluxei_mask;
14096 Ops.push_back(PassThru);
14097 Ops.push_back(BasePtr);
14098 Ops.push_back(Index);
14100 Ops.push_back(Mask);
14105 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
14108 Chain =
Result.getValue(1);
14126 EVT MemVT = MemSD->getMemoryVT();
14127 MachineMemOperand *MMO = MemSD->getMemOperand();
14128 SDValue Chain = MemSD->getChain();
14131 [[maybe_unused]]
bool IsTruncatingStore =
false;
14135 Index = VPSN->getIndex();
14136 Mask = VPSN->getMask();
14137 Val = VPSN->getValue();
14138 VL = VPSN->getVectorLength();
14140 IsTruncatingStore =
false;
14144 Index = MSN->getIndex();
14145 Mask = MSN->getMask();
14146 Val = MSN->getValue();
14147 IsTruncatingStore = MSN->isTruncatingStore();
14151 MVT IndexVT =
Index.getSimpleValueType();
14152 MVT XLenVT = Subtarget.getXLenVT();
14155 "Unexpected VTs!");
14156 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
14159 assert(!IsTruncatingStore &&
"Unexpected truncating MSCATTER/VP_SCATTER");
14165 MVT ContainerVT = VT;
14189 IsUnmasked ? Intrinsic::riscv_vsoxei : Intrinsic::riscv_vsoxei_mask;
14191 Ops.push_back(Val);
14192 Ops.push_back(BasePtr);
14193 Ops.push_back(Index);
14195 Ops.push_back(Mask);
14204 const MVT XLenVT = Subtarget.getXLenVT();
14208 SDVTList VTs = DAG.
getVTList(XLenVT, MVT::Other);
14215 static const int Table =
14234 const MVT XLenVT = Subtarget.getXLenVT();
14244 static const unsigned Table =
14259 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14265 const MVT XLenVT = Subtarget.getXLenVT();
14269 SDVTList VTs = DAG.
getVTList(XLenVT, MVT::Other);
14270 return DAG.
getNode(RISCVISD::READ_CSR,
DL, VTs, Chain, SysRegNo);
14275 const MVT XLenVT = Subtarget.getXLenVT();
14282 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14288 const MVT XLenVT = Subtarget.getXLenVT();
14294 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14308 SDValue Result = DAG.
getNode(RISCVISD::READ_CSR,
DL, VTs, Chain, SysRegNo);
14309 Chain = Result.getValue(1);
14315 const MVT XLenVT = Subtarget.getXLenVT();
14325 Chain = DAG.
getNode(RISCVISD::CLEAR_CSR,
DL, MVT::Other, Chain, SysRegNo,
14327 return DAG.
getNode(RISCVISD::SET_CSR,
DL, MVT::Other, Chain, SysRegNo,
14333 const MVT XLenVT = Subtarget.getXLenVT();
14340 return DAG.
getNode(RISCVISD::CLEAR_CSR,
DL, MVT::Other, Chain, SysRegNo,
14348 bool isRISCV64 = Subtarget.is64Bit();
14362 return RISCVISD::SLLW;
14364 return RISCVISD::SRAW;
14366 return RISCVISD::SRLW;
14368 return RISCVISD::DIVW;
14370 return RISCVISD::DIVUW;
14372 return RISCVISD::REMUW;
14374 return RISCVISD::ROLW;
14376 return RISCVISD::RORW;
14412 switch (
N->getOpcode()) {
14414 llvm_unreachable(
"Don't know how to custom type legalize this operation!");
14419 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14420 "Unexpected custom legalisation");
14421 bool IsStrict =
N->isStrictFPOpcode();
14424 SDValue Op0 = IsStrict ?
N->getOperand(1) :
N->getOperand(0);
14433 !Subtarget.hasStdExtZfhOrZhinx()) {
14438 unsigned Opc = IsSigned ? RISCVISD::STRICT_FCVT_W_RV64
14439 : RISCVISD::STRICT_FCVT_WU_RV64;
14442 Opc,
DL, VTs, Chain, Op0,
14451 !Subtarget.hasStdExtZfhOrZhinx()) ||
14453 Op0 = DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, Op0);
14455 unsigned Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
14476 std::tie(Result, Chain) =
14477 makeLibCall(DAG, LC,
N->getValueType(0), Op0, CallOptions,
DL, Chain);
14483 case ISD::LROUND: {
14492 if (Op0.
getValueType() == MVT::f16 && !Subtarget.hasStdExtZfhOrZhinx())
14493 Op0 = DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, Op0);
14496 DAG.
getNode(RISCVISD::FCVT_W_RV64,
DL, MVT::i64, Op0,
14504 RTLIB::Libcall LC =
14505 Op0.
getValueType() == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
14514 case ISD::READCYCLECOUNTER:
14515 case ISD::READSTEADYCOUNTER: {
14516 assert(!Subtarget.is64Bit() &&
"READCYCLECOUNTER/READSTEADYCOUNTER only "
14517 "has custom type legalization on riscv32");
14519 SDValue LoCounter, HiCounter;
14520 MVT XLenVT = Subtarget.getXLenVT();
14521 if (
N->getOpcode() == ISD::READCYCLECOUNTER) {
14530 N->getOperand(0), LoCounter, HiCounter);
14545 if (
N->getValueType(0) == MVT::i64) {
14546 assert(Subtarget.hasStdExtZilsd() && !Subtarget.is64Bit() &&
14547 "Unexpected custom legalisation");
14549 if (!Subtarget.enableUnalignedScalarMem() && Ld->
getAlign() < 8)
14554 RISCVISD::LD_RV32,
DL,
14555 DAG.
getVTList({MVT::i32, MVT::i32, MVT::Other}),
14556 {Ld->getChain(), Ld->getBasePtr()}, MVT::i64, Ld->
getMemOperand());
14560 Results.append({Pair, Result.getValue(2)});
14564 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14565 "Unexpected custom legalisation");
14576 unsigned Size =
N->getSimpleValueType(0).getSizeInBits();
14577 unsigned XLen = Subtarget.getXLen();
14580 assert(
Size == (XLen * 2) &&
"Unexpected custom legalisation");
14588 if (LHSIsU == RHSIsU)
14592 MVT XLenVT = Subtarget.getXLenVT();
14605 if (RHSIsU && LHSIsS && !RHSIsS)
14606 Results.push_back(MakeMULPair(LHS, RHS));
14607 else if (LHSIsU && RHSIsS && !LHSIsS)
14608 Results.push_back(MakeMULPair(RHS, LHS));
14616 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14617 "Unexpected custom legalisation");
14623 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14624 "Unexpected custom legalisation");
14627 if (
N->getOpcode() ==
ISD::SHL && Subtarget.hasStdExtZbs() &&
14652 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14653 "Unexpected custom legalisation");
14654 assert((Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb() ||
14655 Subtarget.hasVendorXTHeadBb()) &&
14656 "Unexpected custom legalization");
14658 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()))
14666 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14667 "Unexpected custom legalisation");
14673 unsigned Opc = IsCTZ ? RISCVISD::CTZW : RISCVISD::CLZW;
14681 MVT VT =
N->getSimpleValueType(0);
14682 assert((VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32) &&
14683 Subtarget.is64Bit() && Subtarget.hasStdExtM() &&
14684 "Unexpected custom legalisation");
14696 if (VT != MVT::i32)
14704 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14705 "Unexpected custom legalisation");
14726 EVT OType =
N->getValueType(1);
14738 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14739 "Unexpected custom legalisation");
14756 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1), Res,
14760 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1),
N->getOperand(0),
14767 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1), Res, LHS,
14777 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14778 !Subtarget.hasStdExtZbb() &&
"Unexpected custom legalisation");
14786 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14787 "Unexpected custom legalisation");
14792 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14793 "Unexpected custom legalisation");
14795 if (Subtarget.hasStdExtZbb()) {
14828 case ISD::BITCAST: {
14829 EVT VT =
N->getValueType(0);
14833 MVT XLenVT = Subtarget.getXLenVT();
14834 if (VT == MVT::i16 &&
14835 ((Op0VT == MVT::f16 && Subtarget.hasStdExtZfhminOrZhinxmin()) ||
14836 (Op0VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
14839 }
else if (VT == MVT::i32 && Op0VT == MVT::f32 && Subtarget.is64Bit() &&
14840 Subtarget.hasStdExtFOrZfinx()) {
14842 DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Op0);
14844 }
else if (VT == MVT::i64 && Op0VT == MVT::f64 && !Subtarget.is64Bit() &&
14845 Subtarget.hasStdExtDOrZdinx()) {
14847 DAG.
getVTList(MVT::i32, MVT::i32), Op0);
14866 assert(
N->getValueType(0) == MVT::i8 && Subtarget.hasStdExtZbkb() &&
14867 "Unexpected custom legalisation");
14868 MVT XLenVT = Subtarget.getXLenVT();
14876 case RISCVISD::BREV8:
14877 case RISCVISD::ORC_B: {
14878 MVT VT =
N->getSimpleValueType(0);
14879 MVT XLenVT = Subtarget.getXLenVT();
14880 assert((VT == MVT::i16 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
14881 "Unexpected custom legalisation");
14882 assert(((
N->getOpcode() == RISCVISD::BREV8 && Subtarget.hasStdExtZbkb()) ||
14883 (
N->getOpcode() == RISCVISD::ORC_B && Subtarget.hasStdExtZbb())) &&
14884 "Unexpected extension");
14910 assert(!Subtarget.is64Bit() &&
N->getValueType(0) == MVT::i64 &&
14912 "Unexpected EXTRACT_VECTOR_ELT legalization");
14915 MVT ContainerVT = VecVT;
14921 MVT XLenVT = Subtarget.getXLenVT();
14930 DAG.
getUNDEF(ContainerVT), Vec, Idx, Mask, VL);
14942 DAG.
getNode(RISCVISD::SRL_VL,
DL, ContainerVT, Vec, ThirtyTwoV,
14943 DAG.
getUNDEF(ContainerVT), Mask, VL);
14951 unsigned IntNo =
N->getConstantOperandVal(0);
14955 "Don't know how to custom type legalize this intrinsic!");
14956 case Intrinsic::experimental_get_vector_length: {
14961 case Intrinsic::experimental_cttz_elts: {
14967 case Intrinsic::riscv_orc_b:
14968 case Intrinsic::riscv_brev8:
14969 case Intrinsic::riscv_sha256sig0:
14970 case Intrinsic::riscv_sha256sig1:
14971 case Intrinsic::riscv_sha256sum0:
14972 case Intrinsic::riscv_sha256sum1:
14973 case Intrinsic::riscv_sm3p0:
14974 case Intrinsic::riscv_sm3p1: {
14975 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
14979 case Intrinsic::riscv_orc_b:
Opc = RISCVISD::ORC_B;
break;
14980 case Intrinsic::riscv_brev8:
Opc = RISCVISD::BREV8;
break;
14981 case Intrinsic::riscv_sha256sig0:
Opc = RISCVISD::SHA256SIG0;
break;
14982 case Intrinsic::riscv_sha256sig1:
Opc = RISCVISD::SHA256SIG1;
break;
14983 case Intrinsic::riscv_sha256sum0:
Opc = RISCVISD::SHA256SUM0;
break;
14984 case Intrinsic::riscv_sha256sum1:
Opc = RISCVISD::SHA256SUM1;
break;
14985 case Intrinsic::riscv_sm3p0:
Opc = RISCVISD::SM3P0;
break;
14986 case Intrinsic::riscv_sm3p1:
Opc = RISCVISD::SM3P1;
break;
14995 case Intrinsic::riscv_sm4ks:
14996 case Intrinsic::riscv_sm4ed: {
14998 IntNo == Intrinsic::riscv_sm4ks ? RISCVISD::SM4KS : RISCVISD::SM4ED;
15004 DAG.
getNode(
Opc,
DL, MVT::i64, NewOp0, NewOp1,
N->getOperand(3));
15008 case Intrinsic::riscv_mopr: {
15009 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15014 RISCVISD::MOP_R,
DL, MVT::i64, NewOp,
15019 case Intrinsic::riscv_moprr: {
15020 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15027 RISCVISD::MOP_RR,
DL, MVT::i64, NewOp0, NewOp1,
15032 case Intrinsic::riscv_clmul: {
15033 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15044 case Intrinsic::riscv_clmulh:
15045 case Intrinsic::riscv_clmulr: {
15046 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15066 unsigned Opc = IntNo == Intrinsic::riscv_clmulh ? RISCVISD::CLMULH
15067 : RISCVISD::CLMULR;
15074 case Intrinsic::riscv_vmv_x_s: {
15075 EVT VT =
N->getValueType(0);
15076 MVT XLenVT = Subtarget.getXLenVT();
15077 if (VT.
bitsLT(XLenVT)) {
15080 Subtarget.getXLenVT(),
N->getOperand(1));
15085 assert(VT == MVT::i64 && !Subtarget.is64Bit() &&
15086 "Unexpected custom legalization");
15102 SDValue LShr32 = DAG.
getNode(RISCVISD::SRL_VL,
DL, VecVT, Vec, ThirtyTwoV,
15113 case ISD::VECREDUCE_ADD:
15114 case ISD::VECREDUCE_AND:
15115 case ISD::VECREDUCE_OR:
15116 case ISD::VECREDUCE_XOR:
15117 case ISD::VECREDUCE_SMAX:
15118 case ISD::VECREDUCE_UMAX:
15119 case ISD::VECREDUCE_SMIN:
15120 case ISD::VECREDUCE_UMIN:
15124 case ISD::VP_REDUCE_ADD:
15125 case ISD::VP_REDUCE_AND:
15126 case ISD::VP_REDUCE_OR:
15127 case ISD::VP_REDUCE_XOR:
15128 case ISD::VP_REDUCE_SMAX:
15129 case ISD::VP_REDUCE_UMAX:
15130 case ISD::VP_REDUCE_SMIN:
15131 case ISD::VP_REDUCE_UMIN:
15152 return ISD::VECREDUCE_ADD;
15154 return ISD::VECREDUCE_UMAX;
15156 return ISD::VECREDUCE_SMAX;
15158 return ISD::VECREDUCE_UMIN;
15160 return ISD::VECREDUCE_SMIN;
15162 return ISD::VECREDUCE_AND;
15164 return ISD::VECREDUCE_OR;
15166 return ISD::VECREDUCE_XOR;
15169 return ISD::VECREDUCE_FADD;
15171 return ISD::VECREDUCE_FMAX;
15173 return ISD::VECREDUCE_FMIN;
15199 const EVT VT =
N->getValueType(0);
15200 const unsigned Opc =
N->getOpcode();
15210 if (!
N->getFlags().hasAllowReassociation())
15221 "Inconsistent mappings");
15225 if (!
LHS.hasOneUse() || !
RHS.hasOneUse())
15253 if (0 == std::min(LHSIdx, RHSIdx) && 1 == std::max(LHSIdx, RHSIdx)) {
15256 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
N->getFlags());
15263 if (
LHS.getOpcode() != ReduceOpc)
15277 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
15278 ReduceVec->
getFlags() &
N->getFlags());
15288 auto BinOpToRVVReduce = [](
unsigned Opc) {
15293 return RISCVISD::VECREDUCE_ADD_VL;
15295 return RISCVISD::VECREDUCE_UMAX_VL;
15297 return RISCVISD::VECREDUCE_SMAX_VL;
15299 return RISCVISD::VECREDUCE_UMIN_VL;
15301 return RISCVISD::VECREDUCE_SMIN_VL;
15303 return RISCVISD::VECREDUCE_AND_VL;
15305 return RISCVISD::VECREDUCE_OR_VL;
15307 return RISCVISD::VECREDUCE_XOR_VL;
15309 return RISCVISD::VECREDUCE_FADD_VL;
15311 return RISCVISD::VECREDUCE_FMAX_VL;
15313 return RISCVISD::VECREDUCE_FMIN_VL;
15317 auto IsReduction = [&BinOpToRVVReduce](
SDValue V,
unsigned Opc) {
15320 V.getOperand(0).getOpcode() == BinOpToRVVReduce(
Opc);
15323 unsigned Opc =
N->getOpcode();
15324 unsigned ReduceIdx;
15325 if (IsReduction(
N->getOperand(0),
Opc))
15327 else if (IsReduction(
N->getOperand(1),
Opc))
15333 if (
Opc ==
ISD::FADD && !
N->getFlags().hasAllowReassociation())
15336 SDValue Extract =
N->getOperand(ReduceIdx);
15349 if (ScalarV.
getOpcode() != RISCVISD::VFMV_S_F_VL &&
15350 ScalarV.
getOpcode() != RISCVISD::VMV_S_X_VL &&
15351 ScalarV.
getOpcode() != RISCVISD::VMV_V_X_VL)
15368 SDValue NewStart =
N->getOperand(1 - ReduceIdx);
15401 EVT VT =
N->getValueType(0);
15417 int64_t C0 = N0C->getSExtValue();
15418 int64_t C1 = N1C->getSExtValue();
15419 if (C0 <= 0 || C1 <= 0)
15422 int64_t Diff = std::abs(C0 - C1);
15428 int64_t Bits = std::min(C0, C1);
15460 if (VShift.
slt(1) || VShift.
sgt(3))
15464 EVT VT =
N->getValueType(0);
15484 EVT VT =
N->getValueType(0);
15512 EVT VT =
N->getValueType(0);
15533 Slct.
getOpcode() != RISCVISD::SELECT_CC) ||
15541 bool SwapSelectOps;
15542 unsigned OpOffset = Slct.
getOpcode() == RISCVISD::SELECT_CC ? 2 : 0;
15547 SwapSelectOps =
false;
15548 NonConstantVal = FalseVal;
15550 SwapSelectOps =
true;
15551 NonConstantVal = TrueVal;
15557 FalseVal = DAG.
getNode(
N->getOpcode(),
SDLoc(
N), VT, OtherOp, NonConstantVal);
15562 if (Slct.
getOpcode() == RISCVISD::SELECT_CC)
15605 EVT VT =
N->getValueType(0);
15620 if (!N0C->hasOneUse())
15622 int64_t C0 = N0C->getSExtValue();
15623 int64_t C1 = N1C->getSExtValue();
15625 if (C0 == -1 || C0 == 0 || C0 == 1 ||
isInt<12>(C1))
15632 }
else if ((C1 / C0 + 1) != 0 &&
isInt<12>(C1 / C0 + 1) &&
15636 }
else if ((C1 / C0 - 1) != 0 &&
isInt<12>(C1 / C0 - 1) &&
15664 EVT VT =
N->getValueType(0);
15695 unsigned OuterExtend =
15699 OuterExtend,
SDLoc(
N), VT,
15707 EVT VT =
N->getValueType(0);
15758 EVT VT =
N->getValueType(0);
15768 APInt ImmValMinus1 = N0C->getAPIntValue() - 1;
15778 if (!isIntEqualitySetCC(CCVal) || !SetCCOpVT.
isInteger())
15801 if (!Subtarget.hasStdExtZbb())
15804 EVT VT =
N->getValueType(0);
15806 if (VT != Subtarget.
getXLenVT() && VT != MVT::i32 && VT != MVT::i16)
15818 unsigned ShiftedAmount = 8 - ShAmtCLeft->getZExtValue();
15820 if (ShiftedAmount >= 8)
15824 SDValue RightShiftOperand = N1;
15826 if (ShiftedAmount != 0) {
15830 if (!ShAmtCRight || ShAmtCRight->getZExtValue() != ShiftedAmount)
15839 if (LeftShiftOperand != RightShiftOperand)
15843 Mask <<= ShiftedAmount;
15849 return DAG.
getNode(RISCVISD::ORC_B,
SDLoc(
N), VT, LeftShiftOperand);
15857 EVT VT =
N->getValueType(0);
15889 bool IsAnd =
N->getOpcode() ==
ISD::AND;
15913 EVT VT =
N->getValueType(0);
15937 EVT VT =
N->getValueType(0);
15964 if (CondLHS != True)
15971 if (!CondRHSC || CondRHSC->
getAPIntValue() != (1ULL << ScalarBits))
15983 if (!FalseRHSC || !FalseRHSC->
isZero())
16003 EVT VT =
N->getValueType(0);
16010 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() && VT == MVT::i1 &&
16053 EVT VT =
N->getValueType(0);
16072 EVT WideVT =
X.getValueType();
16094 if (N0.
getOpcode() != ISD::ATOMIC_LOAD)
16109 if (Mask != ExpectedMask)
16135 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
16173 if (N0.
getOpcode() != RISCVISD::CZERO_EQZ ||
16174 N1.
getOpcode() != RISCVISD::CZERO_NEZ ||
16192 EVT VT =
N->getValueType(0);
16210 if (!Subtarget.hasVendorXqcibm())
16222 if (
N->getValueType(0) != MVT::i32)
16224 unsigned Width, ShAmt;
16241 return DAG.
getNode(RISCVISD::QC_INSB,
DL, MVT::i32,
Ops);
16246 if (!Subtarget.hasVendorXqcibm())
16256 unsigned ShAmt, Width;
16260 if (
N->getValueType(0) != MVT::i32)
16265 if (Width == 1 && Subtarget.hasStdExtZbs())
16277 return DAG.
getNode(RISCVISD::QC_INSB,
DL, MVT::i32,
Ops);
16285 if (!Subtarget.hasVendorXqcibm())
16291 APInt MaskImm, OrImm;
16310 unsigned ShAmt, Width;
16323 return DAG.
getNode(RISCVISD::QC_INSB,
DL, MVT::i32,
Ops);
16365 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
16380 if (N0.
getOpcode() == RISCVISD::SLLW &&
16384 return DAG.
getNode(RISCVISD::ROLW,
DL, MVT::i64,
16395 const APInt &Imm = ConstN00->getAPIntValue();
16396 if ((Imm + 1).isSignedIntN(12))
16420 EVT VT =
N->getValueType(0);
16429 bool IsAdd = (
E & 3) == 1;
16430 E -= IsAdd ? 1 : -1;
16434 Result = DAG.
getNode(AddSubOp,
DL, VT, Result, ShiftVal);
16444 uint64_t MulAmtLowBit = MulAmt & (-MulAmt);
16449 ShiftAmt1 = MulAmt + MulAmtLowBit;
16452 ShiftAmt1 = MulAmt - MulAmtLowBit;
16456 EVT VT =
N->getValueType(0);
16470 EVT VT =
N->getValueType(0);
16479 bool ShouldExpandMul =
16481 !Subtarget.hasStdExtZmmul();
16482 if (!ShouldExpandMul)
16501 for (
uint64_t Divisor : {3, 5, 9}) {
16502 if (MulAmt % Divisor != 0)
16504 uint64_t MulAmt2 = MulAmt / Divisor;
16512 X.getConstantOperandVal(1) == UINT64_C(0xffffffff)) {
16515 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, Shl,
16529 if (MulAmt2 == 3 || MulAmt2 == 5 || MulAmt2 == 9) {
16534 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, Mul359,
16545 if (ScaleShift >= 1 && ScaleShift < 4) {
16546 unsigned ShiftAmt =
Log2_64((MulAmt & (MulAmt - 1)));
16550 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT,
X,
16560 for (
uint64_t Divisor : {3, 5, 9}) {
16565 if ((
C >> TZ) == Divisor && (TZ == 1 || TZ == 2 || TZ == 3)) {
16570 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, Mul359,
16576 if (MulAmt > 2 &&
isPowerOf2_64((MulAmt - 1) & (MulAmt - 2))) {
16578 if (ScaleShift >= 1 && ScaleShift < 4) {
16579 unsigned ShiftAmt =
Log2_64(((MulAmt - 1) & (MulAmt - 2)));
16605 for (
uint64_t Divisor : {3, 5, 9}) {
16606 if (MulAmt % Divisor != 0)
16608 uint64_t MulAmt2 = MulAmt / Divisor;
16611 for (
uint64_t Divisor2 : {3, 5, 9}) {
16612 if (MulAmt2 % Divisor2 != 0)
16614 uint64_t MulAmt3 = MulAmt2 / Divisor2;
16621 RISCVISD::SHL_ADD,
DL, VT, Mul359A,
16633 if (!Subtarget.hasStdExtZmmul())
16643 EVT VT =
N->getValueType(0);
16650 if (
N->getOperand(0).getOpcode() !=
ISD::AND ||
16651 N->getOperand(0).getOperand(0).getOpcode() !=
ISD::SRL)
16664 if (!V1.
isMask(HalfSize) || V2 != (1ULL | 1ULL << HalfSize) ||
16665 V3 != (HalfSize - 1))
16675 return DAG.
getNode(ISD::BITCAST,
DL, VT, Sra);
16681 EVT VT =
N->getValueType(0);
16689 unsigned AddSubOpc;
16695 auto IsAddSubWith1 = [&](
SDValue V) ->
bool {
16696 AddSubOpc = V->getOpcode();
16708 if (IsAddSubWith1(N0)) {
16710 return DAG.
getNode(AddSubOpc,
DL, VT, N1, MulVal);
16713 if (IsAddSubWith1(N1)) {
16715 return DAG.
getNode(AddSubOpc,
DL, VT, N0, MulVal);
16730 if (isIndexTypeSigned(IndexType))
16733 if (!
N->hasOneUse())
16736 EVT VT =
N.getValueType();
16775 EVT SrcVT = Src.getValueType();
16779 NewElen = std::max(NewElen, 8U);
16806 EVT OpVT =
X.getValueType();
16814 if (OpSize <= Subtarget.
getXLen() ||
16820 auto IsVectorBitCastCheap = [](
SDValue X) {
16823 X.getOpcode() == ISD::LOAD;
16825 if (!IsVectorBitCastCheap(
X) || !IsVectorBitCastCheap(
Y))
16829 Attribute::NoImplicitFloat))
16836 unsigned VecSize = OpSize / 8;
16848 DAG.
getNode(ISD::VP_REDUCE_OR,
DL, XLenVT,
16861 EVT VT =
N->getValueType(0);
16866 if (!isIntEqualitySetCC(
Cond))
16891 if (OpVT == MVT::i64 &&
isUInt<32>(AndRHSInt) &&
16895 if (NewC >= -2048 && NewC <= 2048) {
16901 return DAG.
getSetCC(dl, VT, Shift,
16911 if (OpVT != MVT::i64 || !Subtarget.
is64Bit())
16931 const APInt &C1 = N1C->getAPIntValue();
16949 EVT VT =
N->getValueType(0);
16951 unsigned Opc = Src.getOpcode();
16956 if (
Opc == RISCVISD::FMV_X_ANYEXTH && SrcVT.
bitsGE(MVT::i16) &&
16957 Subtarget.hasStdExtZfhmin())
16958 return DAG.
getNode(RISCVISD::FMV_X_SIGNEXTH,
DL, VT, Src.getOperand(0));
16964 return DAG.
getNode(RISCVISD::SLLW,
DL, VT, Src.getOperand(0),
16965 Src.getOperand(1));
16984struct CombineResult;
16986enum ExtKind : uint8_t {
17018struct NodeExtensionHelper {
17027 bool SupportsFPExt;
17029 bool SupportsBF16Ext;
17032 bool EnforceOneUse;
17042 case RISCVISD::VSEXT_VL:
17043 case RISCVISD::VZEXT_VL:
17044 case RISCVISD::FP_EXTEND_VL:
17047 return OrigOperand;
17053 return OrigOperand.
getOpcode() == RISCVISD::VMV_V_X_VL ||
17058 unsigned getExtOpc(ExtKind SupportsExt)
const {
17059 switch (SupportsExt) {
17060 case ExtKind::SExt:
17061 return RISCVISD::VSEXT_VL;
17062 case ExtKind::ZExt:
17063 return RISCVISD::VZEXT_VL;
17064 case ExtKind::FPExt:
17065 case ExtKind::BF16Ext:
17066 return RISCVISD::FP_EXTEND_VL;
17074 SDValue getOrCreateExtendedOp(SDNode *Root, SelectionDAG &DAG,
17075 const RISCVSubtarget &Subtarget,
17076 std::optional<ExtKind> SupportsExt)
const {
17077 if (!SupportsExt.has_value())
17078 return OrigOperand;
17080 MVT NarrowVT = getNarrowType(Root, *SupportsExt);
17084 if (
Source.getValueType() == NarrowVT)
17087 unsigned ExtOpc = getExtOpc(*SupportsExt);
17090 SDLoc
DL(OrigOperand);
17091 auto [
Mask, VL] = getMaskAndVL(Root, DAG, Subtarget);
17095 case RISCVISD::VSEXT_VL:
17096 case RISCVISD::VZEXT_VL:
17097 case RISCVISD::FP_EXTEND_VL:
17098 return DAG.
getNode(ExtOpc,
DL, NarrowVT, Source, Mask, VL);
17101 case RISCVISD::VMV_V_X_VL:
17102 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, NarrowVT,
17104 case RISCVISD::VFMV_V_F_VL:
17106 assert(
Source.getOpcode() == ISD::FP_EXTEND &&
"Unexpected source");
17109 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL, NarrowVT,
17110 DAG.
getUNDEF(NarrowVT), Source, VL);
17123 static MVT getNarrowType(
const SDNode *Root, ExtKind SupportsExt) {
17129 MVT EltVT = SupportsExt == ExtKind::BF16Ext ? MVT::bf16
17130 : SupportsExt == ExtKind::FPExt
17132 : MVT::getIntegerVT(NarrowSize);
17134 assert((
int)NarrowSize >= (SupportsExt == ExtKind::FPExt ? 16 : 8) &&
17135 "Trying to extend something we can't represent");
17142 static unsigned getSExtOpcode(
unsigned Opcode) {
17145 case RISCVISD::ADD_VL:
17146 case RISCVISD::VWADD_W_VL:
17147 case RISCVISD::VWADDU_W_VL:
17149 case RISCVISD::OR_VL:
17150 return RISCVISD::VWADD_VL;
17152 case RISCVISD::SUB_VL:
17153 case RISCVISD::VWSUB_W_VL:
17154 case RISCVISD::VWSUBU_W_VL:
17155 return RISCVISD::VWSUB_VL;
17157 case RISCVISD::MUL_VL:
17158 return RISCVISD::VWMUL_VL;
17166 static unsigned getZExtOpcode(
unsigned Opcode) {
17169 case RISCVISD::ADD_VL:
17170 case RISCVISD::VWADD_W_VL:
17171 case RISCVISD::VWADDU_W_VL:
17173 case RISCVISD::OR_VL:
17174 return RISCVISD::VWADDU_VL;
17176 case RISCVISD::SUB_VL:
17177 case RISCVISD::VWSUB_W_VL:
17178 case RISCVISD::VWSUBU_W_VL:
17179 return RISCVISD::VWSUBU_VL;
17181 case RISCVISD::MUL_VL:
17182 return RISCVISD::VWMULU_VL;
17184 case RISCVISD::SHL_VL:
17185 return RISCVISD::VWSLL_VL;
17193 static unsigned getFPExtOpcode(
unsigned Opcode) {
17195 case RISCVISD::FADD_VL:
17196 case RISCVISD::VFWADD_W_VL:
17197 return RISCVISD::VFWADD_VL;
17198 case RISCVISD::FSUB_VL:
17199 case RISCVISD::VFWSUB_W_VL:
17200 return RISCVISD::VFWSUB_VL;
17201 case RISCVISD::FMUL_VL:
17202 return RISCVISD::VFWMUL_VL;
17203 case RISCVISD::VFMADD_VL:
17204 return RISCVISD::VFWMADD_VL;
17205 case RISCVISD::VFMSUB_VL:
17206 return RISCVISD::VFWMSUB_VL;
17207 case RISCVISD::VFNMADD_VL:
17208 return RISCVISD::VFWNMADD_VL;
17209 case RISCVISD::VFNMSUB_VL:
17210 return RISCVISD::VFWNMSUB_VL;
17218 static unsigned getSUOpcode(
unsigned Opcode) {
17220 "SU is only supported for MUL");
17221 return RISCVISD::VWMULSU_VL;
17226 static unsigned getWOpcode(
unsigned Opcode, ExtKind SupportsExt) {
17229 case RISCVISD::ADD_VL:
17231 case RISCVISD::OR_VL:
17232 return SupportsExt == ExtKind::SExt ? RISCVISD::VWADD_W_VL
17233 : RISCVISD::VWADDU_W_VL;
17235 case RISCVISD::SUB_VL:
17236 return SupportsExt == ExtKind::SExt ? RISCVISD::VWSUB_W_VL
17237 : RISCVISD::VWSUBU_W_VL;
17238 case RISCVISD::FADD_VL:
17239 return RISCVISD::VFWADD_W_VL;
17240 case RISCVISD::FSUB_VL:
17241 return RISCVISD::VFWSUB_W_VL;
17247 using CombineToTry = std::function<std::optional<CombineResult>(
17248 SDNode * ,
const NodeExtensionHelper & ,
17249 const NodeExtensionHelper & , SelectionDAG &,
17250 const RISCVSubtarget &)>;
17253 bool needToPromoteOtherUsers()
const {
return EnforceOneUse; }
17255 void fillUpExtensionSupportForSplat(SDNode *Root, SelectionDAG &DAG,
17256 const RISCVSubtarget &Subtarget) {
17261 "Unexpected Opcode");
17274 unsigned ScalarBits =
Op.getValueSizeInBits();
17276 if (ScalarBits < EltBits) {
17278 assert(
Opc == RISCVISD::VMV_V_X_VL && EltBits == 64 && ScalarBits == 32 &&
17279 !Subtarget.
is64Bit() &&
"Unexpected splat");
17281 SupportsSExt =
true;
17285 SupportsZExt =
true;
17287 EnforceOneUse =
false;
17291 unsigned NarrowSize = EltBits / 2;
17294 if (NarrowSize < 8)
17298 SupportsSExt =
true;
17302 SupportsZExt =
true;
17304 EnforceOneUse =
false;
17307 bool isSupportedFPExtend(MVT NarrowEltVT,
const RISCVSubtarget &Subtarget) {
17308 return (NarrowEltVT == MVT::f32 ||
17312 bool isSupportedBF16Extend(MVT NarrowEltVT,
const RISCVSubtarget &Subtarget) {
17313 return NarrowEltVT == MVT::bf16 && Subtarget.hasStdExtZvfbfwma();
17318 void fillUpExtensionSupport(SDNode *Root, SelectionDAG &DAG,
17319 const RISCVSubtarget &Subtarget) {
17320 SupportsZExt =
false;
17321 SupportsSExt =
false;
17322 SupportsFPExt =
false;
17323 SupportsBF16Ext =
false;
17324 EnforceOneUse =
true;
17346 case RISCVISD::VZEXT_VL:
17347 SupportsZExt =
true;
17349 case RISCVISD::VSEXT_VL:
17350 SupportsSExt =
true;
17352 case RISCVISD::FP_EXTEND_VL: {
17355 if (isSupportedFPExtend(NarrowEltVT, Subtarget))
17356 SupportsFPExt =
true;
17357 if (isSupportedBF16Extend(NarrowEltVT, Subtarget))
17358 SupportsBF16Ext =
true;
17363 case RISCVISD::VMV_V_X_VL:
17364 fillUpExtensionSupportForSplat(Root, DAG, Subtarget);
17366 case RISCVISD::VFMV_V_F_VL: {
17373 if (
Op.getOpcode() != ISD::FP_EXTEND)
17377 unsigned ScalarBits =
Op.getOperand(0).getValueSizeInBits();
17378 if (NarrowSize != ScalarBits)
17381 if (isSupportedFPExtend(
Op.getOperand(0).getSimpleValueType(), Subtarget))
17382 SupportsFPExt =
true;
17383 if (isSupportedBF16Extend(
Op.getOperand(0).getSimpleValueType(),
17385 SupportsBF16Ext =
true;
17394 static bool isSupportedRoot(
const SDNode *Root,
17395 const RISCVSubtarget &Subtarget) {
17407 case RISCVISD::ADD_VL:
17408 case RISCVISD::MUL_VL:
17409 case RISCVISD::VWADD_W_VL:
17410 case RISCVISD::VWADDU_W_VL:
17411 case RISCVISD::SUB_VL:
17412 case RISCVISD::VWSUB_W_VL:
17413 case RISCVISD::VWSUBU_W_VL:
17415 case RISCVISD::FADD_VL:
17416 case RISCVISD::FSUB_VL:
17417 case RISCVISD::FMUL_VL:
17418 case RISCVISD::VFWADD_W_VL:
17419 case RISCVISD::VFWSUB_W_VL:
17421 case RISCVISD::OR_VL:
17425 Subtarget.hasStdExtZvbb();
17426 case RISCVISD::SHL_VL:
17427 return Subtarget.hasStdExtZvbb();
17428 case RISCVISD::VFMADD_VL:
17429 case RISCVISD::VFNMSUB_VL:
17430 case RISCVISD::VFNMADD_VL:
17431 case RISCVISD::VFMSUB_VL:
17439 NodeExtensionHelper(SDNode *Root,
unsigned OperandIdx, SelectionDAG &DAG,
17440 const RISCVSubtarget &Subtarget) {
17441 assert(isSupportedRoot(Root, Subtarget) &&
17442 "Trying to build an helper with an "
17443 "unsupported root");
17444 assert(OperandIdx < 2 &&
"Requesting something else than LHS or RHS");
17454 case RISCVISD::VWADD_W_VL:
17455 case RISCVISD::VWADDU_W_VL:
17456 case RISCVISD::VWSUB_W_VL:
17457 case RISCVISD::VWSUBU_W_VL:
17458 case RISCVISD::VFWADD_W_VL:
17459 case RISCVISD::VFWSUB_W_VL:
17461 if (OperandIdx == 1)
17465 fillUpExtensionSupport(Root, DAG, Subtarget);
17471 static std::pair<SDValue, SDValue>
17472 getMaskAndVL(
const SDNode *Root, SelectionDAG &DAG,
17473 const RISCVSubtarget &Subtarget) {
17474 assert(isSupportedRoot(Root, Subtarget) &&
"Unexpected root");
17493 switch (
N->getOpcode()) {
17497 case RISCVISD::ADD_VL:
17498 case RISCVISD::MUL_VL:
17499 case RISCVISD::OR_VL:
17500 case RISCVISD::FADD_VL:
17501 case RISCVISD::FMUL_VL:
17502 case RISCVISD::VFMADD_VL:
17503 case RISCVISD::VFNMSUB_VL:
17504 case RISCVISD::VFNMADD_VL:
17505 case RISCVISD::VFMSUB_VL:
17507 case RISCVISD::VWADD_W_VL:
17508 case RISCVISD::VWADDU_W_VL:
17510 case RISCVISD::SUB_VL:
17511 case RISCVISD::VWSUB_W_VL:
17512 case RISCVISD::VWSUBU_W_VL:
17513 case RISCVISD::VFWADD_W_VL:
17514 case RISCVISD::FSUB_VL:
17515 case RISCVISD::VFWSUB_W_VL:
17517 case RISCVISD::SHL_VL:
17536struct CombineResult {
17538 unsigned TargetOpcode;
17540 std::optional<ExtKind> LHSExt;
17541 std::optional<ExtKind> RHSExt;
17545 NodeExtensionHelper
LHS;
17547 NodeExtensionHelper
RHS;
17549 CombineResult(
unsigned TargetOpcode, SDNode *Root,
17550 const NodeExtensionHelper &
LHS, std::optional<ExtKind> LHSExt,
17551 const NodeExtensionHelper &
RHS, std::optional<ExtKind> RHSExt)
17552 : TargetOpcode(TargetOpcode), LHSExt(LHSExt), RHSExt(RHSExt), Root(Root),
17558 SDValue materialize(SelectionDAG &DAG,
17559 const RISCVSubtarget &Subtarget)
const {
17561 std::tie(Mask, VL) =
17562 NodeExtensionHelper::getMaskAndVL(Root, DAG, Subtarget);
17576 LHS.getOrCreateExtendedOp(Root, DAG, Subtarget, LHSExt),
17577 RHS.getOrCreateExtendedOp(Root, DAG, Subtarget, RHSExt),
17578 Passthru, Mask, VL);
17592static std::optional<CombineResult>
17593canFoldToVWWithSameExtensionImpl(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17594 const NodeExtensionHelper &
RHS,
17597 if ((AllowExtMask & ExtKind::ZExt) &&
LHS.SupportsZExt &&
RHS.SupportsZExt)
17598 return CombineResult(NodeExtensionHelper::getZExtOpcode(Root->
getOpcode()),
17599 Root,
LHS, {ExtKind::ZExt},
RHS,
17601 if ((AllowExtMask & ExtKind::SExt) &&
LHS.SupportsSExt &&
RHS.SupportsSExt)
17602 return CombineResult(NodeExtensionHelper::getSExtOpcode(Root->
getOpcode()),
17603 Root,
LHS, {ExtKind::SExt},
RHS,
17605 if ((AllowExtMask & ExtKind::FPExt) &&
LHS.SupportsFPExt &&
RHS.SupportsFPExt)
17606 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
17607 Root,
LHS, {ExtKind::FPExt},
RHS,
17609 if ((AllowExtMask & ExtKind::BF16Ext) &&
LHS.SupportsBF16Ext &&
17610 RHS.SupportsBF16Ext)
17611 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
17612 Root,
LHS, {ExtKind::BF16Ext},
RHS,
17613 {ExtKind::BF16Ext});
17614 return std::nullopt;
17623static std::optional<CombineResult>
17624canFoldToVWWithSameExtension(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17627 return canFoldToVWWithSameExtensionImpl(
17628 Root,
LHS,
RHS, ExtKind::ZExt | ExtKind::SExt | ExtKind::FPExt, DAG,
17636static std::optional<CombineResult>
17637canFoldToVWWithSameExtZEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17640 return canFoldToVWWithSameExtensionImpl(Root,
LHS,
RHS, ExtKind::ZExt, DAG,
17648static std::optional<CombineResult>
17649canFoldToVWWithSameExtBF16(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17652 return canFoldToVWWithSameExtensionImpl(Root,
LHS,
RHS, ExtKind::BF16Ext, DAG,
17660static std::optional<CombineResult>
17661canFoldToVW_W(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17664 if (
RHS.SupportsFPExt)
17665 return CombineResult(
17666 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::FPExt),
17667 Root,
LHS, std::nullopt,
RHS, {ExtKind::FPExt});
17674 return CombineResult(
17675 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::ZExt), Root,
17676 LHS, std::nullopt,
RHS, {ExtKind::ZExt});
17678 return CombineResult(
17679 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::SExt), Root,
17680 LHS, std::nullopt,
RHS, {ExtKind::SExt});
17681 return std::nullopt;
17688static std::optional<CombineResult>
17689canFoldToVWWithSEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17692 if (
LHS.SupportsSExt)
17693 return CombineResult(NodeExtensionHelper::getSExtOpcode(Root->
getOpcode()),
17694 Root,
LHS, {ExtKind::SExt},
RHS,
17696 return std::nullopt;
17703static std::optional<CombineResult>
17704canFoldToVWWithZEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17707 if (
LHS.SupportsZExt)
17708 return CombineResult(NodeExtensionHelper::getZExtOpcode(Root->
getOpcode()),
17709 Root,
LHS, {ExtKind::ZExt},
RHS,
17711 return std::nullopt;
17718static std::optional<CombineResult>
17719canFoldToVWWithFPEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17722 if (
LHS.SupportsFPExt)
17723 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
17724 Root,
LHS, {ExtKind::FPExt},
RHS,
17726 return std::nullopt;
17733static std::optional<CombineResult>
17734canFoldToVW_SU(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17738 if (!
LHS.SupportsSExt || !
RHS.SupportsZExt)
17739 return std::nullopt;
17740 return CombineResult(NodeExtensionHelper::getSUOpcode(Root->
getOpcode()),
17741 Root,
LHS, {ExtKind::SExt},
RHS,
17746NodeExtensionHelper::getSupportedFoldings(
const SDNode *Root) {
17752 case RISCVISD::ADD_VL:
17753 case RISCVISD::SUB_VL:
17754 case RISCVISD::OR_VL:
17755 case RISCVISD::FADD_VL:
17756 case RISCVISD::FSUB_VL:
17758 Strategies.
push_back(canFoldToVWWithSameExtension);
17762 case RISCVISD::FMUL_VL:
17763 case RISCVISD::VFMADD_VL:
17764 case RISCVISD::VFMSUB_VL:
17765 case RISCVISD::VFNMADD_VL:
17766 case RISCVISD::VFNMSUB_VL:
17767 Strategies.
push_back(canFoldToVWWithSameExtension);
17768 if (Root->
getOpcode() == RISCVISD::VFMADD_VL)
17769 Strategies.
push_back(canFoldToVWWithSameExtBF16);
17772 case RISCVISD::MUL_VL:
17774 Strategies.
push_back(canFoldToVWWithSameExtension);
17779 case RISCVISD::SHL_VL:
17781 Strategies.
push_back(canFoldToVWWithSameExtZEXT);
17783 case RISCVISD::VWADD_W_VL:
17784 case RISCVISD::VWSUB_W_VL:
17786 Strategies.
push_back(canFoldToVWWithSEXT);
17788 case RISCVISD::VWADDU_W_VL:
17789 case RISCVISD::VWSUBU_W_VL:
17791 Strategies.
push_back(canFoldToVWWithZEXT);
17793 case RISCVISD::VFWADD_W_VL:
17794 case RISCVISD::VFWSUB_W_VL:
17796 Strategies.
push_back(canFoldToVWWithFPEXT);
17807 assert(
N->getOpcode() == RISCVISD::ADD_VL);
17810 SDValue Passthru =
N->getOperand(2);
17844 if (!NodeExtensionHelper::isSupportedRoot(
N, Subtarget))
17850 Inserted.insert(
N);
17853 while (!Worklist.
empty()) {
17856 NodeExtensionHelper
LHS(Root, 0, DAG, Subtarget);
17857 NodeExtensionHelper
RHS(Root, 1, DAG, Subtarget);
17858 auto AppendUsersIfNeeded = [&Worklist, &Subtarget,
17859 &Inserted](
const NodeExtensionHelper &
Op) {
17860 if (
Op.needToPromoteOtherUsers()) {
17863 if (!NodeExtensionHelper::isSupportedRoot(TheUser, Subtarget))
17868 if (Inserted.insert(TheUser).second)
17881 NodeExtensionHelper::getSupportedFoldings(Root);
17883 assert(!FoldingStrategies.
empty() &&
"Nothing to be folded");
17884 bool Matched =
false;
17885 for (
int Attempt = 0;
17886 (Attempt != 1 + NodeExtensionHelper::isCommutative(Root)) && !Matched;
17889 for (NodeExtensionHelper::CombineToTry FoldingStrategy :
17890 FoldingStrategies) {
17891 std::optional<CombineResult> Res =
17892 FoldingStrategy(Root,
LHS,
RHS, DAG, Subtarget);
17899 if (Res->LHSExt.has_value())
17900 if (!AppendUsersIfNeeded(
LHS))
17902 if (Res->RHSExt.has_value())
17903 if (!AppendUsersIfNeeded(
RHS))
17915 SDValue InputRootReplacement;
17922 for (CombineResult Res : CombinesToApply) {
17923 SDValue NewValue = Res.materialize(DAG, Subtarget);
17924 if (!InputRootReplacement) {
17926 "First element is expected to be the current node");
17927 InputRootReplacement = NewValue;
17932 for (std::pair<SDValue, SDValue> OldNewValues : ValuesToReplace) {
17936 return InputRootReplacement;
17943 unsigned Opc =
N->getOpcode();
17944 assert(
Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWADDU_W_VL ||
17945 Opc == RISCVISD::VWSUB_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL);
17948 SDValue MergeOp =
N->getOperand(1);
17949 unsigned MergeOpc = MergeOp.
getOpcode();
17951 if (MergeOpc != RISCVISD::VMERGE_VL && MergeOpc !=
ISD::VSELECT)
17960 SDValue Passthru =
N->getOperand(2);
17966 if (Mask.getOpcode() != RISCVISD::VMSET_VL)
17974 Z = Z.getOperand(1);
17980 {Y, X, Y, MergeOp->getOperand(0), N->getOperand(4)},
17987 [[maybe_unused]]
unsigned Opc =
N->getOpcode();
17988 assert(
Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWADDU_W_VL ||
17989 Opc == RISCVISD::VWSUB_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL);
18016 EVT NewMemVT = (MemVT == MVT::i32) ? MVT::i64 : MVT::i128;
18021 if (LSNode1->
getOpcode() == ISD::LOAD) {
18024 if (MemVT == MVT::i32)
18025 Opcode = (Ext ==
ISD::ZEXTLOAD) ? RISCVISD::TH_LWUD : RISCVISD::TH_LWD;
18027 Opcode = RISCVISD::TH_LDD;
18030 Opcode,
SDLoc(LSNode1), DAG.
getVTList({XLenVT, XLenVT, MVT::Other}),
18031 {LSNode1->getChain(), BasePtr,
18032 DAG.getConstant(Imm, SDLoc(LSNode1), XLenVT)},
18043 unsigned Opcode = (MemVT == MVT::i32) ? RISCVISD::TH_SWD : RISCVISD::TH_SDD;
18047 {LSNode1->getChain(), LSNode1->getOperand(1), LSNode2->getOperand(1),
18048 BasePtr, DAG.getConstant(Imm, SDLoc(LSNode1), XLenVT)},
18065 if (!Subtarget.hasVendorXTHeadMemPair())
18070 unsigned OpNum = LSNode1->
getOpcode() == ISD::LOAD ? 1 : 2;
18077 auto ExtractBaseAndOffset = [](
SDValue Ptr) -> std::pair<SDValue, uint64_t> {
18080 return {
Ptr->getOperand(0), C1->getZExtValue()};
18084 auto [Base1, Offset1] = ExtractBaseAndOffset(LSNode1->
getOperand(OpNum));
18105 auto [Base2, Offset2] = ExtractBaseAndOffset(LSNode2->
getOperand(OpNum));
18108 if (Base1 != Base2)
18112 bool Valid =
false;
18113 if (MemVT == MVT::i32) {
18117 }
else if (MemVT == MVT::i64) {
18153 if (Src->isStrictFPOpcode())
18161 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
18171 EVT VT =
N->getValueType(0);
18174 MVT SrcVT = Src.getSimpleValueType();
18175 MVT SrcContainerVT = SrcVT;
18203 IsSigned ? RISCVISD::VFCVT_RTZ_X_F_VL : RISCVISD::VFCVT_RTZ_XU_F_VL;
18204 FpToInt = DAG.
getNode(
Opc,
DL, ContainerVT, XVal, Mask, VL);
18207 IsSigned ? RISCVISD::VFCVT_RM_X_F_VL : RISCVISD::VFCVT_RM_XU_F_VL;
18208 FpToInt = DAG.
getNode(
Opc,
DL, ContainerVT, XVal, Mask,
18221 if (VT != MVT::i32 && VT != XLenVT)
18226 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
18228 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
18251 EVT DstVT =
N->getValueType(0);
18252 if (DstVT != XLenVT)
18258 if (Src->isStrictFPOpcode())
18266 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
18278 if (SatVT == DstVT)
18279 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
18280 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
18281 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
18286 Src = Src.getOperand(0);
18294 if (
Opc == RISCVISD::FCVT_WU_RV64)
18307 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected extension");
18313 EVT VT =
N->getValueType(0);
18319 return DAG.
getNode(RISCVISD::BREV8,
DL, VT, Src.getOperand(0));
18332 EVT LoadVT = VPLoad->getValueType(0);
18336 N->getOperand(2) != VPLoad->getVectorLength() ||
18337 !
N->getOperand(0).hasOneUse())
18344 SDValue LoadMask = VPLoad->getMask();
18349 if (LoadMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
18351 LoadMask.
getOperand(2) != VPLoad->getVectorLength())
18359 SDValue NumElem = VPLoad->getVectorLength();
18360 uint64_t ElemWidthByte = VPLoad->getValueType(0).getScalarSizeInBits() / 8;
18372 PtrInfo, VPLoad->getMemOperand()->getFlags(),
18376 LoadVT,
DL, VPLoad->getChain(),
Base, Stride, LoadMask,
18377 VPLoad->getVectorLength(), MMO, VPLoad->isExpandingLoad());
18391 if (VPStore->getValue().getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE)
18394 SDValue VPReverse = VPStore->getValue();
18400 VPStore->getVectorLength() != VPReverse.
getOperand(2) ||
18404 SDValue StoreMask = VPStore->getMask();
18409 if (StoreMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
18411 StoreMask.
getOperand(2) != VPStore->getVectorLength())
18419 SDValue NumElem = VPStore->getVectorLength();
18433 PtrInfo, VPStore->getMemOperand()->getFlags(),
18438 VPStore->getOffset(), Stride, StoreMask, VPStore->getVectorLength(),
18439 VPStore->getMemoryVT(), MMO, VPStore->getAddressingMode(),
18440 VPStore->isTruncatingStore(), VPStore->isCompressingStore());
18452 EVT VT =
N->getValueType(0);
18464 if (In.getOpcode() != ISD::VP_SRL || In.getOperand(2) != Mask ||
18465 In.getOperand(3) != VL)
18474 if (
LHS.getOpcode() != ISD::VP_ADD ||
LHS.getOperand(2) != Mask ||
18475 LHS.getOperand(3) != VL)
18482 if (V.getOpcode() != ISD::VP_ADD || V.getOperand(2) != Mask ||
18483 V.getOperand(3) != VL)
18495 if (!FindAdd(LHS0, LHS1) && !FindAdd(LHS1, LHS0))
18509 if (
Op.getOpcode() != ISD::VP_ZERO_EXTEND ||
Op.getOperand(1) != Mask ||
18510 Op.getOperand(2) != VL)
18520 Operands[0].getOperand(0), Mask, VL);
18522 Operands[1].getOperand(0), Mask, VL);
18526 return DAG.
getNode(RISCVISD::AVGCEILU_VL,
DL, VT,
18527 {NewOp0, NewOp1, DAG.
getUNDEF(VT), Mask, VL});
18539 case RISCVISD::VFMADD_VL: Opcode = RISCVISD::VFNMSUB_VL;
break;
18540 case RISCVISD::VFNMSUB_VL: Opcode = RISCVISD::VFMADD_VL;
break;
18541 case RISCVISD::VFNMADD_VL: Opcode = RISCVISD::VFMSUB_VL;
break;
18542 case RISCVISD::VFMSUB_VL: Opcode = RISCVISD::VFNMADD_VL;
break;
18543 case RISCVISD::STRICT_VFMADD_VL: Opcode = RISCVISD::STRICT_VFNMSUB_VL;
break;
18544 case RISCVISD::STRICT_VFNMSUB_VL: Opcode = RISCVISD::STRICT_VFMADD_VL;
break;
18545 case RISCVISD::STRICT_VFNMADD_VL: Opcode = RISCVISD::STRICT_VFMSUB_VL;
break;
18546 case RISCVISD::STRICT_VFMSUB_VL: Opcode = RISCVISD::STRICT_VFNMADD_VL;
break;
18556 case RISCVISD::VFMADD_VL: Opcode = RISCVISD::VFMSUB_VL;
break;
18557 case RISCVISD::VFMSUB_VL: Opcode = RISCVISD::VFMADD_VL;
break;
18558 case RISCVISD::VFNMADD_VL: Opcode = RISCVISD::VFNMSUB_VL;
break;
18559 case RISCVISD::VFNMSUB_VL: Opcode = RISCVISD::VFNMADD_VL;
break;
18560 case RISCVISD::STRICT_VFMADD_VL: Opcode = RISCVISD::STRICT_VFMSUB_VL;
break;
18561 case RISCVISD::STRICT_VFMSUB_VL: Opcode = RISCVISD::STRICT_VFMADD_VL;
break;
18562 case RISCVISD::STRICT_VFNMADD_VL: Opcode = RISCVISD::STRICT_VFNMSUB_VL;
break;
18563 case RISCVISD::STRICT_VFNMSUB_VL: Opcode = RISCVISD::STRICT_VFNMADD_VL;
break;
18576 unsigned Offset = IsStrict ? 1 : 0;
18583 auto invertIfNegative = [&Mask, &VL](
SDValue &V) {
18584 if (V.getOpcode() == RISCVISD::FNEG_VL && V.getOperand(1) == Mask &&
18585 V.getOperand(2) == VL) {
18587 V = V.getOperand(0);
18594 bool NegA = invertIfNegative(
A);
18595 bool NegB = invertIfNegative(
B);
18596 bool NegC = invertIfNegative(
C);
18599 if (!NegA && !NegB && !NegC)
18605 {N->getOperand(0), A, B, C, Mask, VL});
18629 EVT VT =
N->getValueType(0);
18636 uint64_t ShAmt =
N->getConstantOperandVal(1);
18649 if (LShAmt < ExtSize) {
18662 if (ShAmt > 32 || VT != MVT::i64)
18692 U->getConstantOperandVal(1) > 32)
18747 if (!
Cond.hasOneUse())
18766 EVT VT =
Cond.getValueType();
18811 LHS =
LHS.getOperand(0);
18821 LHS.getOperand(0).getValueType() == Subtarget.
getXLenVT()) {
18829 RHS =
LHS.getOperand(1);
18830 LHS =
LHS.getOperand(0);
18839 auto isXorImmediate = [](
const SDValue &
Op) ->
bool {
18841 return isInt<12>(XorCnst->getSExtValue());
18845 auto singleBitOp = [&DAG](
const SDValue &VarOp,
18846 const SDValue &ConstOp) ->
bool {
18849 return (XorCnst->getSExtValue() == 1) &&
18854 auto onlyUsedBySelectOrBR = [](
const SDValue &
Op) ->
bool {
18855 for (
const SDNode *UserNode :
Op->users()) {
18856 const unsigned Opcode = UserNode->getOpcode();
18857 if (Opcode != RISCVISD::SELECT_CC && Opcode != RISCVISD::BR_CC)
18862 auto isFoldableXorEq = [isXorImmediate, singleBitOp, onlyUsedBySelectOrBR](
18865 (!isXorImmediate(
LHS.getOperand(1)) ||
18866 singleBitOp(
LHS.getOperand(0),
LHS.getOperand(1)) ||
18867 onlyUsedBySelectOrBR(
LHS));
18870 if (isFoldableXorEq(
LHS,
RHS)) {
18871 RHS =
LHS.getOperand(1);
18872 LHS =
LHS.getOperand(0);
18898 if (Subtarget.hasVendorXAndesPerf()) {
18908 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
18951 bool Commutative =
true;
18952 unsigned Opc = TrueVal.getOpcode();
18962 Commutative =
false;
18972 if (!TrueVal.hasOneUse())
18976 if (FalseVal == TrueVal.getOperand(0))
18978 else if (Commutative && FalseVal == TrueVal.getOperand(1))
18983 EVT VT =
N->getValueType(0);
18985 SDValue OtherOp = TrueVal.getOperand(1 - OpToFold);
18991 assert(IdentityOperand &&
"No identity operand!");
18996 DAG.
getSelect(
DL, OtherOpVT,
N->getOperand(0), OtherOp, IdentityOperand);
18997 return DAG.
getNode(TrueVal.getOpcode(),
DL, VT, FalseVal, NewSel);
19018 CountZeroes =
N->getOperand(2);
19019 ValOnZero =
N->getOperand(1);
19021 CountZeroes =
N->getOperand(1);
19022 ValOnZero =
N->getOperand(2);
19041 if (
Cond->getOperand(0) != CountZeroesArgument)
19060 CountZeroes, BitWidthMinusOne);
19070 EVT VT =
N->getValueType(0);
19071 EVT CondVT =
Cond.getValueType();
19079 (Subtarget.
hasCZEROLike() || Subtarget.hasVendorXTHeadCondMov())) {
19085 const APInt &MaskVal =
LHS.getConstantOperandAPInt(1);
19096 if (!TrueVal.hasOneUse() || !FalseVal.hasOneUse())
19100 if (TrueVal.getOpcode() ==
ISD::SUB && FalseVal.getOpcode() ==
ISD::ADD) {
19108 SDValue A = FalseVal.getOperand(0);
19109 SDValue B = FalseVal.getOperand(1);
19111 return ((TrueVal.getOperand(0) ==
A && TrueVal.getOperand(1) ==
B) ||
19112 (TrueVal.getOperand(1) ==
A && TrueVal.getOperand(0) ==
B));
19120 EVT VT =
N->getValueType(0);
19122 SDValue TrueVal =
N->getOperand(1);
19123 SDValue FalseVal =
N->getOperand(2);
19153 SDValue TrueVal =
N->getOperand(1);
19154 SDValue FalseVal =
N->getOperand(2);
19169 EVT VT =
N->getValueType(0);
19176 const unsigned Opcode =
N->op_begin()->getNode()->getOpcode();
19191 if (
Op.isUndef()) {
19204 if (
Op.getOpcode() != Opcode || !
Op.hasOneUse())
19213 if (
Op.getOperand(0).getValueType() !=
Op.getOperand(1).getValueType())
19237 EVT AVT =
A.getValueType();
19238 EVT BVT =
B.getValueType();
19268 if (AOpt || BOpt) {
19286 EVT OpVT =
A.getValueType();
19294 IsSigned ? ISD::PARTIAL_REDUCE_SMLA : ISD::PARTIAL_REDUCE_UMLA;
19308 EVT OpVT =
A.getOperand(0).getValueType();
19310 OpVT !=
B.getOperand(0).getValueType() ||
19316 Opc = ISD::PARTIAL_REDUCE_SMLA;
19319 Opc = ISD::PARTIAL_REDUCE_UMLA;
19322 Opc = ISD::PARTIAL_REDUCE_SUMLA;
19325 Opc = ISD::PARTIAL_REDUCE_SUMLA;
19339 if (!Subtarget.hasStdExtZvqdotq())
19343 EVT VT =
N->getValueType(0);
19346 return DAG.
getNode(ISD::VECREDUCE_ADD,
DL, VT, V);
19368 const unsigned InVecOpcode = InVec->
getOpcode();
19385 InVecLHS, InValLHS, EltNo);
19387 InVecRHS, InValRHS, EltNo);
19399 unsigned Elt = IndexC->getZExtValue();
19405 unsigned NewIdx = Elt % ConcatNumElts;
19407 unsigned ConcatOpIdx = Elt / ConcatNumElts;
19412 ConcatOps[ConcatOpIdx] = ConcatOp;
19424 EVT VT =
N->getValueType(0);
19436 !
SDValue(BaseLd, 0).hasOneUse())
19439 EVT BaseLdVT = BaseLd->getValueType(0);
19447 if (!Ld || !Ld->isSimple() || !
Op.hasOneUse() ||
19449 Ld->getValueType(0) != BaseLdVT)
19458 using PtrDiff = std::pair<std::variant<int64_t, SDValue>,
bool>;
19460 LoadSDNode *Ld2) -> std::optional<PtrDiff> {
19465 if (BIO1.equalBaseIndex(BIO2, DAG))
19470 SDValue P2 = Ld2->getBasePtr();
19473 if (P1.getOpcode() ==
ISD::ADD && P1.getOperand(0) == P2)
19474 return {{P1.getOperand(1),
true}};
19476 return std::nullopt;
19480 auto BaseDiff = GetPtrDiff(Lds[0], Lds[1]);
19485 for (
auto *It = Lds.
begin() + 1; It != Lds.
end() - 1; It++)
19486 if (GetPtrDiff(*It, *std::next(It)) != BaseDiff)
19494 unsigned WideScalarBitWidth =
19507 auto [StrideVariant, MustNegateStride] = *BaseDiff;
19509 std::holds_alternative<SDValue>(StrideVariant)
19510 ? std::get<SDValue>(StrideVariant)
19513 if (MustNegateStride)
19522 ConstStride && ConstStride->getSExtValue() >= 0)
19526 ConstStride->getSExtValue() * (
N->getNumOperands() - 1);
19532 BaseLd->getPointerInfo(), BaseLd->getMemOperand()->getFlags(), MemSize,
19536 WideVecVT,
DL, BaseLd->getChain(), BaseLd->getBasePtr(), Stride,
19550 EVT VT =
N->getValueType(0);
19567 for (
int MaskIndex : Mask) {
19568 bool SelectMaskVal = (MaskIndex < (int)NumElts);
19571 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
19608 if (
N->getValueType(0).isFixedLengthVector())
19611 SDValue Addend =
N->getOperand(0);
19614 if (
N->getOpcode() == RISCVISD::ADD_VL) {
19615 SDValue AddPassthruOp =
N->getOperand(2);
19616 if (!AddPassthruOp.
isUndef())
19620 auto IsVWMulOpc = [](
unsigned Opc) {
19622 case RISCVISD::VWMUL_VL:
19623 case RISCVISD::VWMULU_VL:
19624 case RISCVISD::VWMULSU_VL:
19639 if (!MulPassthruOp.
isUndef())
19649 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
19650 }(
N, DAG, Subtarget);
19655 if (AddMask != MulMask || AddVL != MulVL)
19658 const auto &TSInfo =
19660 unsigned Opc = TSInfo.getMAccOpcode(MulOp.
getOpcode());
19663 EVT VT =
N->getValueType(0);
19674 if (!
N->getValueType(0).isVector())
19677 SDValue Addend =
N->getOperand(0);
19680 if (
N->getOpcode() == RISCVISD::ADD_VL) {
19681 SDValue AddPassthruOp =
N->getOperand(2);
19682 if (!AddPassthruOp.
isUndef())
19686 auto IsVqdotqOpc = [](
unsigned Opc) {
19688 case RISCVISD::VQDOT_VL:
19689 case RISCVISD::VQDOTU_VL:
19690 case RISCVISD::VQDOTSU_VL:
19710 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
19711 }(
N, DAG, Subtarget);
19714 if (AddVL != MulVL)
19717 if (AddMask.getOpcode() != RISCVISD::VMSET_VL ||
19718 AddMask.getOperand(0) != MulVL)
19723 EVT VT =
N->getValueType(0);
19724 Addend = DAG.
getNode(RISCVISD::ADD_VL,
DL, VT, Addend, AccumOp,
19725 DAG.
getUNDEF(VT), AddMask, AddVL);
19743 const EVT IndexVT = Index.getValueType();
19747 if (!isIndexTypeSigned(IndexType))
19777 assert(ShuffleMask.empty());
19779 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
19782 if (Index->getOperand(i)->isUndef())
19784 uint64_t C = Index->getConstantOperandVal(i);
19785 if (
C % ElementSize != 0)
19787 C =
C / ElementSize;
19790 ShuffleMask.push_back(
C);
19791 ActiveLanes.
set(
C);
19793 return ActiveLanes.
all();
19811 if (NumElems % 2 != 0)
19815 const unsigned WiderElementSize = ElementSize * 2;
19816 if (WiderElementSize > ST.getELen()/8)
19819 if (!ST.enableUnalignedVectorMem() && BaseAlign < WiderElementSize)
19822 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
19825 if (Index->getOperand(i)->isUndef())
19829 uint64_t C = Index->getConstantOperandVal(i);
19831 if (
C % WiderElementSize != 0)
19836 if (
C !=
Last + ElementSize)
19855 if (!IsVLMAX || Mask.getOpcode() != RISCVISD::VMSET_VL ||
19856 Mask.getOperand(0) != VL)
19859 auto IsTruncNode = [&](
SDValue V) {
19860 return V.getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL &&
19861 V.getOperand(1) == Mask && V.getOperand(2) == VL;
19868 while (IsTruncNode(
Op)) {
19869 if (!
Op.hasOneUse())
19871 Op =
Op.getOperand(0);
19904 assert(
N->getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL);
19906 MVT VT =
N->getSimpleValueType(0);
19911 auto MatchMinMax = [&VL, &Mask](
SDValue V,
unsigned Opc,
unsigned OpcVL,
19913 if (V.getOpcode() !=
Opc &&
19914 !(V.getOpcode() == OpcVL && V.getOperand(2).isUndef() &&
19915 V.getOperand(3) == Mask && V.getOperand(4) == VL))
19923 Op.getOperand(1).getValueType().isFixedLengthVector() &&
19925 Op.getOperand(1).getOperand(0).getValueType() ==
Op.getValueType() &&
19927 Op =
Op.getOperand(1).getOperand(0);
19930 return V.getOperand(0);
19932 if (
Op.getOpcode() == RISCVISD::VMV_V_X_VL &&
Op.getOperand(0).isUndef() &&
19933 Op.getOperand(2) == VL) {
19936 Op1->getAPIntValue().sextOrTrunc(
Op.getScalarValueSizeInBits());
19946 auto DetectUSatPattern = [&](
SDValue V) {
19958 MatchMinMax(SMinOp,
ISD::SMAX, RISCVISD::SMAX_VL, LoC))
19967 MatchMinMax(SMaxOp,
ISD::SMIN, RISCVISD::SMIN_VL, HiC))
19970 return DAG.
getNode(RISCVISD::SMAX_VL,
DL, V.getValueType(), SMinOp,
19971 V.getOperand(1), DAG.
getUNDEF(V.getValueType()),
19977 auto DetectSSatPattern = [&](
SDValue V) {
19979 unsigned NumSrcBits = V.getScalarValueSizeInBits();
19986 MatchMinMax(SMinOp,
ISD::SMAX, RISCVISD::SMAX_VL, LoC))
19987 if (HiC == SignedMax && LoC == SignedMin)
19992 MatchMinMax(SMaxOp,
ISD::SMIN, RISCVISD::SMIN_VL, HiC))
19993 if (HiC == SignedMax && LoC == SignedMin)
20002 while (Src.getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL &&
20003 Src.getOperand(1) == Mask && Src.getOperand(2) == VL &&
20005 Src = Src.getOperand(0);
20009 if ((Val = DetectUSatPattern(Src)))
20010 ClipOpc = RISCVISD::TRUNCATE_VECTOR_VL_USAT;
20011 else if ((Val = DetectSSatPattern(Src)))
20012 ClipOpc = RISCVISD::TRUNCATE_VECTOR_VL_SSAT;
20021 Val = DAG.
getNode(ClipOpc,
DL, ValVT, Val, Mask, VL);
20022 }
while (ValVT != VT);
20040 unsigned Opc =
N->getOpcode();
20042 "Unexpected opcode");
20043 EVT VT =
N->getValueType(0);
20052 Src = Src.getOperand(0);
20054 if (Src.getOpcode() != ISD::BITCAST)
20056 Src = Src.getOperand(0);
20057 }
else if (
Opc == ISD::VECREDUCE_ADD) {
20060 Src = Src.getOperand(0);
20063 EVT SrcEVT = Src.getValueType();
20078 if (
Opc == ISD::VECREDUCE_ADD) {
20085 VectorBitsMax, EltSize, MinSize);
20090 MVT ContainerVT = SrcMVT;
20118 if (!
LHS.hasOneUse())
20121 switch (
LHS.getOpcode()) {
20123 case RISCVISD::VSEXT_VL:
20124 Opcode = RISCVISD::VWMULSU_VL;
20127 case RISCVISD::VZEXT_VL:
20128 Opcode = RISCVISD::VWMULU_VL;
20139 else if (
RHS.getOpcode() == RISCVISD::VMV_V_X_VL &&
20141 ShAmtInt =
RHS.getConstantOperandVal(1);
20154 if (ShAmtInt >= NarrowBits)
20156 MVT VT =
N->getSimpleValueType(0);
20163 switch (
N->getOpcode()) {
20168 case RISCVISD::SHL_VL:
20169 Passthru =
N->getOperand(2);
20170 Mask =
N->getOperand(3);
20171 VL =
N->getOperand(4);
20176 return DAG.
getNode(Opcode,
DL, VT, NarrowOp,
20178 Passthru, Mask, VL);
20184 const MVT XLenVT = Subtarget.getXLenVT();
20190 auto SimplifyDemandedLowBitsHelper = [&](
unsigned OpNo,
unsigned LowBits) {
20201 switch (
N->getOpcode()) {
20204 case RISCVISD::SplitF64: {
20208 if (Op0->
getOpcode() == RISCVISD::BuildPairF64)
20221 APInt V =
C->getValueAPF().bitcastToAPInt();
20250 case RISCVISD::SLLW:
20251 case RISCVISD::SRAW:
20252 case RISCVISD::SRLW:
20253 case RISCVISD::RORW:
20254 case RISCVISD::ROLW: {
20256 if (SimplifyDemandedLowBitsHelper(0, 32) ||
20257 SimplifyDemandedLowBitsHelper(1, 5))
20262 case RISCVISD::CLZW:
20263 case RISCVISD::CTZW: {
20265 if (SimplifyDemandedLowBitsHelper(0, 32))
20269 case RISCVISD::FMV_W_X_RV64: {
20274 if (Op0.
getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64)
20278 case RISCVISD::FMV_X_ANYEXTH:
20279 case RISCVISD::FMV_X_ANYEXTW_RV64: {
20282 MVT VT =
N->getSimpleValueType(0);
20293 if ((
N->getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64 &&
20294 Op0->
getOpcode() == RISCVISD::FMV_W_X_RV64) ||
20295 (
N->getOpcode() == RISCVISD::FMV_X_ANYEXTH &&
20296 Op0->
getOpcode() == RISCVISD::FMV_H_X)) {
20298 "Unexpected value type!");
20308 LN0->getBasePtr(), IVT, LN0->getMemOperand());
20321 unsigned FPBits =
N->getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64 ? 32 : 16;
20332 EVT VT =
N->getValueType(0);
20381 EVT VT =
N->getValueType(0);
20398 if (!
C || !
C->getValueAPF().isExactlyValue(+1.0))
20413 case ISD::FMINNUM: {
20428 if (
N->getValueType(0) == MVT::i64 && Subtarget.is64Bit()) {
20433 Src.getOperand(0));
20438 Src.getOperand(0), Src.getOperand(1));
20446 case RISCVISD::TRUNCATE_VECTOR_VL:
20450 case ISD::VP_TRUNCATE:
20458 case RISCVISD::CZERO_EQZ:
20459 case RISCVISD::CZERO_NEZ: {
20463 unsigned Opc =
N->getOpcode();
20466 if (
Opc == RISCVISD::CZERO_EQZ && Val ==
Cond)
20470 Opc == RISCVISD::CZERO_EQZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ;
20478 return DAG.
getNode(InvOpc,
SDLoc(
N),
N->getValueType(0), Val, NewCond);
20488 N->getValueType(0), Val,
Cond.getOperand(0));
20492 case RISCVISD::SELECT_CC: {
20499 SDValue FalseV =
N->getOperand(4);
20501 EVT VT =
N->getValueType(0);
20504 if (TrueV == FalseV)
20535 return DAG.
getNode(RISCVISD::SELECT_CC,
DL,
N->getValueType(0),
20536 {LHS, RHS, CC, TrueV, FalseV});
20538 if (!Subtarget.hasConditionalMoveFusion()) {
20595 case RISCVISD::BR_CC: {
20602 return DAG.
getNode(RISCVISD::BR_CC,
DL,
N->getValueType(0),
20603 N->getOperand(0), LHS, RHS, CC,
N->getOperand(4));
20616 EVT VT =
N->getValueType(0);
20628 if (In2.
getOpcode() != ISD::FP_EXTEND &&
20637 DAG.
getNode(ISD::FNEG,
DL, VT, NewFPExtRound));
20639 case ISD::MGATHER: {
20641 const EVT VT =
N->getValueType(0);
20642 SDValue Index = MGN->getIndex();
20643 SDValue ScaleOp = MGN->getScale();
20645 assert(!MGN->isIndexScaled() &&
20646 "Scaled gather/scatter should not be formed");
20651 N->getVTList(), MGN->getMemoryVT(),
DL,
20652 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
20653 MGN->getBasePtr(), Index, ScaleOp},
20654 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
20658 N->getVTList(), MGN->getMemoryVT(),
DL,
20659 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
20660 MGN->getBasePtr(), Index, ScaleOp},
20661 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
20667 if (std::optional<VIDSequence> SimpleVID =
20669 SimpleVID && SimpleVID->StepDenominator == 1) {
20670 const int64_t StepNumerator = SimpleVID->StepNumerator;
20671 const int64_t Addend = SimpleVID->Addend;
20678 assert(MGN->getBasePtr()->getValueType(0) == PtrVT);
20686 VT,
DL, MGN->getChain(), BasePtr,
20688 EVL, MGN->getMemOperand());
20690 MGN->getPassThru());
20700 MGN->getBasePtr(), DAG.
getUNDEF(XLenVT),
20702 MGN->getMemoryVT(), MGN->getMemOperand(),
20711 MGN->getMemOperand()->getBaseAlign(), Subtarget)) {
20713 for (
unsigned i = 0; i < Index->getNumOperands(); i += 2)
20714 NewIndices.
push_back(Index.getOperand(i));
20715 EVT IndexVT = Index.getValueType()
20722 assert(EltCnt.isKnownEven() &&
"Splitting vector, but not in half!");
20724 EltCnt.divideCoefficientBy(2));
20727 EltCnt.divideCoefficientBy(2));
20732 {MGN->getChain(), Passthru, Mask, MGN->getBasePtr(),
20740 case ISD::MSCATTER:{
20742 SDValue Index = MSN->getIndex();
20743 SDValue ScaleOp = MSN->getScale();
20745 assert(!MSN->isIndexScaled() &&
20746 "Scaled gather/scatter should not be formed");
20751 N->getVTList(), MSN->getMemoryVT(),
DL,
20752 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
20754 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
20758 N->getVTList(), MSN->getMemoryVT(),
DL,
20759 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
20761 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
20763 EVT VT = MSN->getValue()->getValueType(0);
20765 if (!MSN->isTruncatingStore() &&
20769 return DAG.
getMaskedStore(MSN->getChain(),
DL, Shuffle, MSN->getBasePtr(),
20770 DAG.
getUNDEF(XLenVT), MSN->getMask(),
20771 MSN->getMemoryVT(), MSN->getMemOperand(),
20776 case ISD::VP_GATHER: {
20778 SDValue Index = VPGN->getIndex();
20779 SDValue ScaleOp = VPGN->getScale();
20781 assert(!VPGN->isIndexScaled() &&
20782 "Scaled gather/scatter should not be formed");
20787 {VPGN->getChain(), VPGN->getBasePtr(), Index,
20788 ScaleOp, VPGN->getMask(),
20789 VPGN->getVectorLength()},
20790 VPGN->getMemOperand(), IndexType);
20794 {VPGN->getChain(), VPGN->getBasePtr(), Index,
20795 ScaleOp, VPGN->getMask(),
20796 VPGN->getVectorLength()},
20797 VPGN->getMemOperand(), IndexType);
20801 case ISD::VP_SCATTER: {
20803 SDValue Index = VPSN->getIndex();
20804 SDValue ScaleOp = VPSN->getScale();
20806 assert(!VPSN->isIndexScaled() &&
20807 "Scaled gather/scatter should not be formed");
20812 {VPSN->getChain(), VPSN->getValue(),
20813 VPSN->getBasePtr(), Index, ScaleOp,
20814 VPSN->getMask(), VPSN->getVectorLength()},
20815 VPSN->getMemOperand(), IndexType);
20819 {VPSN->getChain(), VPSN->getValue(),
20820 VPSN->getBasePtr(), Index, ScaleOp,
20821 VPSN->getMask(), VPSN->getVectorLength()},
20822 VPSN->getMemOperand(), IndexType);
20825 case RISCVISD::SHL_VL:
20829 case RISCVISD::SRA_VL:
20830 case RISCVISD::SRL_VL: {
20832 if (ShAmt.
getOpcode() == RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL) {
20836 EVT VT =
N->getValueType(0);
20839 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt,
20840 N->getOperand(2),
N->getOperand(3),
N->getOperand(4));
20855 if (ShAmt.
getOpcode() == RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL) {
20858 EVT VT =
N->getValueType(0);
20861 DAG.
getRegister(RISCV::X0, Subtarget.getXLenVT()));
20862 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt);
20866 case RISCVISD::ADD_VL:
20874 case RISCVISD::VWADD_W_VL:
20875 case RISCVISD::VWADDU_W_VL:
20876 case RISCVISD::VWSUB_W_VL:
20877 case RISCVISD::VWSUBU_W_VL:
20879 case RISCVISD::OR_VL:
20880 case RISCVISD::SUB_VL:
20881 case RISCVISD::MUL_VL:
20883 case RISCVISD::VFMADD_VL:
20884 case RISCVISD::VFNMADD_VL:
20885 case RISCVISD::VFMSUB_VL:
20886 case RISCVISD::VFNMSUB_VL:
20887 case RISCVISD::STRICT_VFMADD_VL:
20888 case RISCVISD::STRICT_VFNMADD_VL:
20889 case RISCVISD::STRICT_VFMSUB_VL:
20890 case RISCVISD::STRICT_VFNMSUB_VL:
20892 case RISCVISD::FADD_VL:
20893 case RISCVISD::FSUB_VL:
20894 case RISCVISD::FMUL_VL:
20895 case RISCVISD::VFWADD_W_VL:
20896 case RISCVISD::VFWSUB_W_VL:
20904 if (
N->getOpcode() != ISD::STORE)
20908 SDValue Chain = Store->getChain();
20909 EVT MemVT = Store->getMemoryVT();
20910 SDValue Val = Store->getValue();
20913 bool IsScalarizable =
20915 Store->isSimple() &&
20945 NewVT, *Store->getMemOperand())) {
20947 return DAG.
getStore(Chain,
DL, NewV, Store->getBasePtr(),
20948 Store->getPointerInfo(), Store->getBaseAlign(),
20949 Store->getMemOperand()->getFlags());
20959 L->hasNUsesOfValue(1, 0) && L->hasNUsesOfValue(1, 1) &&
20961 L->getMemoryVT() == MemVT) {
20964 NewVT, *Store->getMemOperand()) &&
20966 NewVT, *L->getMemOperand())) {
20968 L->getPointerInfo(), L->getBaseAlign(),
20969 L->getMemOperand()->getFlags());
20970 return DAG.
getStore(Chain,
DL, NewL, Store->getBasePtr(),
20971 Store->getPointerInfo(), Store->getBaseAlign(),
20972 Store->getMemOperand()->getFlags());
20979 if ((Val.
getOpcode() == RISCVISD::VMV_X_S ||
20985 MVT VecVT = Src.getSimpleValueType();
20992 Store->getChain(),
DL, Src, Store->getBasePtr(), Store->getOffset(),
20995 Store->getMemOperand(), Store->getAddressingMode(),
20996 Store->isTruncatingStore(),
false);
21003 EVT VT =
N->getValueType(0);
21028 case RISCVISD::VFMV_V_F_VL: {
21029 const MVT VT =
N->getSimpleValueType(0);
21030 SDValue Passthru =
N->getOperand(0);
21031 SDValue Scalar =
N->getOperand(1);
21036 return DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL, VT, Passthru, Scalar, VL);
21039 case RISCVISD::VMV_V_X_VL: {
21040 const MVT VT =
N->getSimpleValueType(0);
21041 SDValue Passthru =
N->getOperand(0);
21042 SDValue Scalar =
N->getOperand(1);
21047 unsigned ScalarSize = Scalar.getValueSizeInBits();
21049 if (ScalarSize > EltWidth && Passthru.
isUndef())
21050 if (SimplifyDemandedLowBitsHelper(1, EltWidth))
21057 (!Const || Const->isZero() ||
21058 !Const->getAPIntValue().sextOrTrunc(EltWidth).isSignedIntN(5)))
21059 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, VT, Passthru, Scalar, VL);
21063 case RISCVISD::VFMV_S_F_VL: {
21068 if (
N->getOperand(0).isUndef() &&
21071 Src.getOperand(0).getValueType().isScalableVector()) {
21072 EVT VT =
N->getValueType(0);
21092 case RISCVISD::VMV_S_X_VL: {
21093 const MVT VT =
N->getSimpleValueType(0);
21094 SDValue Passthru =
N->getOperand(0);
21095 SDValue Scalar =
N->getOperand(1);
21101 unsigned ScalarSize = Scalar.getValueSizeInBits();
21103 if (ScalarSize > EltWidth && SimplifyDemandedLowBitsHelper(1, EltWidth))
21106 if (Scalar.getOpcode() == RISCVISD::VMV_X_S && Passthru.
isUndef() &&
21107 Scalar.getOperand(0).getValueType() ==
N->getValueType(0))
21108 return Scalar.getOperand(0);
21115 DAG.
getNode(
N->getOpcode(),
DL, M1VT, M1Passthru, Scalar, VL);
21124 Const && !Const->isZero() &&
isInt<5>(Const->getSExtValue()) &&
21126 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru, Scalar, VL);
21130 case RISCVISD::VMV_X_S: {
21132 MVT VecVT =
N->getOperand(0).getSimpleValueType();
21134 if (M1VT.
bitsLT(VecVT)) {
21136 return DAG.
getNode(RISCVISD::VMV_X_S,
DL,
N->getSimpleValueType(0), Vec);
21144 unsigned IntNo =
N->getConstantOperandVal(IntOpNo);
21149 case Intrinsic::riscv_vcpop:
21150 case Intrinsic::riscv_vcpop_mask:
21151 case Intrinsic::riscv_vfirst:
21152 case Intrinsic::riscv_vfirst_mask: {
21154 if (IntNo == Intrinsic::riscv_vcpop_mask ||
21155 IntNo == Intrinsic::riscv_vfirst_mask)
21156 VL =
N->getOperand(3);
21161 EVT VT =
N->getValueType(0);
21162 if (IntNo == Intrinsic::riscv_vfirst ||
21163 IntNo == Intrinsic::riscv_vfirst_mask)
21167 case Intrinsic::riscv_vsseg2_mask:
21168 case Intrinsic::riscv_vsseg3_mask:
21169 case Intrinsic::riscv_vsseg4_mask:
21170 case Intrinsic::riscv_vsseg5_mask:
21171 case Intrinsic::riscv_vsseg6_mask:
21172 case Intrinsic::riscv_vsseg7_mask:
21173 case Intrinsic::riscv_vsseg8_mask: {
21175 unsigned NF = Tuple.getValueType().getRISCVVectorTupleNumFields();
21177 if (Subtarget.hasOptimizedSegmentLoadStore(NF) || !Tuple.hasOneUse() ||
21178 Tuple.getOpcode() != RISCVISD::TUPLE_INSERT ||
21179 !Tuple.getOperand(0).isUndef())
21187 "Type mismatch without bitcast?");
21188 unsigned Stride = SEW / 8 * NF;
21189 unsigned Offset = SEW / 8 * Idx;
21216 case ISD::EXPERIMENTAL_VP_REVERSE:
21218 case ISD::VP_STORE:
21220 case ISD::BITCAST: {
21221 assert(Subtarget.useRVVForFixedLengthVectors());
21223 EVT VT =
N->getValueType(0);
21234 for (
unsigned i = 0; i < NF; ++i)
21235 Result = DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VT, Result,
Splat,
21241 if ((SrcVT == MVT::v1i1 || SrcVT == MVT::v2i1 || SrcVT == MVT::v4i1) &&
21254 case ISD::VECREDUCE_ADD:
21262 case RISCVISD::VRGATHER_VX_VL: {
21265 EVT VT =
N->getValueType(0);
21268 SDValue Passthru =
N->getOperand(2);
21275 Src = Src.getOperand(1);
21277 switch (Src.getOpcode()) {
21280 case RISCVISD::VMV_V_X_VL:
21281 case RISCVISD::VFMV_V_F_VL:
21289 case RISCVISD::VMV_S_X_VL:
21290 case RISCVISD::VFMV_S_F_VL:
21306 case RISCVISD::TUPLE_EXTRACT: {
21307 EVT VT =
N->getValueType(0);
21309 unsigned Idx =
N->getConstantOperandVal(1);
21314 switch (Tuple.getConstantOperandVal(1)) {
21317 case Intrinsic::riscv_vlseg2_mask:
21318 case Intrinsic::riscv_vlseg3_mask:
21319 case Intrinsic::riscv_vlseg4_mask:
21320 case Intrinsic::riscv_vlseg5_mask:
21321 case Intrinsic::riscv_vlseg6_mask:
21322 case Intrinsic::riscv_vlseg7_mask:
21323 case Intrinsic::riscv_vlseg8_mask:
21324 NF = Tuple.getValueType().getRISCVVectorTupleNumFields();
21328 if (!NF || Subtarget.hasOptimizedSegmentLoadStore(NF))
21333 "Type mismatch without bitcast?");
21334 unsigned Stride = SEW / 8 * NF;
21335 unsigned Offset = SEW / 8 * Idx;
21338 Tuple.getOperand(0),
21360 return Result.getValue(0);
21362 case RISCVISD::TUPLE_INSERT: {
21364 if (
N->getOperand(1).isUndef())
21365 return N->getOperand(0);
21368 case RISCVISD::VSLIDE1UP_VL:
21369 case RISCVISD::VFSLIDE1UP_VL: {
21373 MVT VT =
N->getSimpleValueType(0);
21377 if (!
N->getOperand(0).isUndef() ||
21396 return getVSlideup(DAG, Subtarget,
DL, VT, SrcVec,
N->getOperand(1),
21406 EVT XVT,
unsigned KeptBits)
const {
21411 if (XVT != MVT::i32 && XVT != MVT::i64)
21415 if (KeptBits == 32 || KeptBits == 64)
21419 return Subtarget.hasStdExtZbb() &&
21420 ((KeptBits == 8 && XVT == MVT::i64 && !Subtarget.is64Bit()) ||
21428 "Expected shift op");
21452 if (Ty.isScalarInteger() &&
21455 return isUsedByLdSt(N0.
getNode(),
N);
21461 if (C2 && Subtarget.hasShlAdd(C2->getZExtValue()) &&
N->hasOneUse() &&
21462 N->user_begin()->getOpcode() ==
ISD::ADD &&
21463 !isUsedByLdSt(*
N->user_begin(),
nullptr) &&
21468 const APInt &C1Int = C1->getAPIntValue();
21469 APInt ShiftedC1Int = C1Int << C2->getAPIntValue();
21490 ShiftedC1Int, Ty.getSizeInBits(), Subtarget,
21495 if (C1Cost < ShiftedC1Cost)
21518 EVT VT =
Op.getValueType();
21522 unsigned Opcode =
Op.getOpcode();
21530 const APInt &Mask =
C->getAPIntValue();
21539 auto IsLegalMask = [ShrunkMask, ExpandedMask](
const APInt &Mask) ->
bool {
21540 return ShrunkMask.
isSubsetOf(Mask) && Mask.isSubsetOf(ExpandedMask);
21542 auto UseMask = [Mask,
Op, &TLO](
const APInt &NewMask) ->
bool {
21543 if (NewMask == Mask)
21548 Op.getOperand(0), NewC);
21561 APInt NewMask =
APInt(Mask.getBitWidth(), 0xffff);
21562 if (IsLegalMask(NewMask))
21563 return UseMask(NewMask);
21566 if (VT == MVT::i64) {
21568 if (IsLegalMask(NewMask))
21569 return UseMask(NewMask);
21584 APInt NewMask = ShrunkMask;
21585 if (MinSignedBits <= 12)
21587 else if (!
C->isOpaque() && MinSignedBits <= 32 && !ShrunkMask.
isSignedIntN(32))
21593 assert(IsLegalMask(NewMask));
21594 return UseMask(NewMask);
21598 static const uint64_t GREVMasks[] = {
21599 0x5555555555555555ULL, 0x3333333333333333ULL, 0x0F0F0F0F0F0F0F0FULL,
21600 0x00FF00FF00FF00FFULL, 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL};
21602 for (
unsigned Stage = 0; Stage != 6; ++Stage) {
21603 unsigned Shift = 1 << Stage;
21604 if (ShAmt & Shift) {
21606 uint64_t Res = ((x & Mask) << Shift) | ((x >> Shift) & Mask);
21618 const APInt &DemandedElts,
21620 unsigned Depth)
const {
21622 unsigned Opc =
Op.getOpcode();
21627 "Should use MaskedValueIsZero if you don't know whether Op"
21628 " is a target node!");
21633 case RISCVISD::SELECT_CC: {
21644 case RISCVISD::VCPOP_VL: {
21649 case RISCVISD::CZERO_EQZ:
21650 case RISCVISD::CZERO_NEZ:
21656 case RISCVISD::REMUW: {
21666 case RISCVISD::DIVUW: {
21676 case RISCVISD::SLLW: {
21685 case RISCVISD::SRLW: {
21694 case RISCVISD::SRAW: {
21703 case RISCVISD::SHL_ADD: {
21706 unsigned ShAmt =
Op.getConstantOperandVal(1);
21713 case RISCVISD::CTZW: {
21720 case RISCVISD::CLZW: {
21727 case RISCVISD::BREV8:
21728 case RISCVISD::ORC_B: {
21732 bool IsGORC =
Op.getOpcode() == RISCVISD::ORC_B;
21740 case RISCVISD::READ_VLENB: {
21743 const unsigned MinVLenB = Subtarget.getRealMinVLen() / 8;
21744 const unsigned MaxVLenB = Subtarget.getRealMaxVLen() / 8;
21745 assert(MinVLenB > 0 &&
"READ_VLENB without vector extension enabled?");
21748 if (MaxVLenB == MinVLenB)
21752 case RISCVISD::FCLASS: {
21765 case Intrinsic::riscv_vsetvli:
21766 case Intrinsic::riscv_vsetvlimax: {
21767 bool HasAVL = IntNo == Intrinsic::riscv_vsetvli;
21768 unsigned VSEW =
Op.getConstantOperandVal(HasAVL + 1);
21773 uint64_t MaxVL = Subtarget.getRealMaxVLen() / SEW;
21774 MaxVL = (Fractional) ? MaxVL / LMul : MaxVL * LMul;
21778 MaxVL = std::min(MaxVL,
Op.getConstantOperandVal(1));
21780 unsigned KnownZeroFirstBit =
Log2_32(MaxVL) + 1;
21793 unsigned Depth)
const {
21794 switch (
Op.getOpcode()) {
21797 case RISCVISD::SELECT_CC: {
21800 if (Tmp == 1)
return 1;
21803 return std::min(Tmp, Tmp2);
21805 case RISCVISD::CZERO_EQZ:
21806 case RISCVISD::CZERO_NEZ:
21810 case RISCVISD::ABSW: {
21815 if (Tmp < 33)
return 1;
21818 case RISCVISD::SRAW: {
21825 return std::max(Tmp, 33U);
21827 case RISCVISD::SLLW:
21828 case RISCVISD::SRLW:
21829 case RISCVISD::DIVW:
21830 case RISCVISD::DIVUW:
21831 case RISCVISD::REMUW:
21832 case RISCVISD::ROLW:
21833 case RISCVISD::RORW:
21834 case RISCVISD::FCVT_W_RV64:
21835 case RISCVISD::FCVT_WU_RV64:
21836 case RISCVISD::STRICT_FCVT_W_RV64:
21837 case RISCVISD::STRICT_FCVT_WU_RV64:
21840 case RISCVISD::VMV_X_S: {
21846 unsigned XLen = Subtarget.getXLen();
21847 unsigned EltBits =
Op.getOperand(0).getScalarValueSizeInBits();
21848 if (EltBits <= XLen)
21849 return XLen - EltBits + 1;
21853 unsigned IntNo =
Op.getConstantOperandVal(1);
21857 case Intrinsic::riscv_masked_atomicrmw_xchg:
21858 case Intrinsic::riscv_masked_atomicrmw_add:
21859 case Intrinsic::riscv_masked_atomicrmw_sub:
21860 case Intrinsic::riscv_masked_atomicrmw_nand:
21861 case Intrinsic::riscv_masked_atomicrmw_max:
21862 case Intrinsic::riscv_masked_atomicrmw_min:
21863 case Intrinsic::riscv_masked_atomicrmw_umax:
21864 case Intrinsic::riscv_masked_atomicrmw_umin:
21865 case Intrinsic::riscv_masked_cmpxchg:
21872 assert(Subtarget.hasStdExtA());
21873 return Op.getValueSizeInBits() - 31;
21885 unsigned Depth)
const {
21888 switch (
Op.getOpcode()) {
21889 case RISCVISD::BREV8:
21890 case RISCVISD::ORC_B: {
21892 bool IsGORC =
Op.getOpcode() == RISCVISD::ORC_B;
21900 OriginalDemandedElts, Known2, TLO,
Depth + 1))
21912 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
21920 switch (
Op.getOpcode()) {
21921 case RISCVISD::SLLW:
21922 case RISCVISD::SRAW:
21923 case RISCVISD::SRLW:
21924 case RISCVISD::RORW:
21925 case RISCVISD::ROLW:
21929 case RISCVISD::SELECT_CC:
21931 assert(
Op.getOperand(0).getValueType().isInteger() &&
21932 "RISCVISD::SELECT_CC only compares integers");
21941 assert(Ld &&
"Unexpected null LoadSDNode");
21950 if (!CNode || CNode->isMachineConstantPoolEntry() ||
21951 CNode->getOffset() != 0)
21958 if (
Ptr.getOpcode() == RISCVISD::LLA) {
21959 auto *CNode = GetSupportedConstantPool(
Ptr.getOperand(0));
21960 if (!CNode || CNode->getTargetFlags() != 0)
21963 return CNode->getConstVal();
21967 if (
Ptr.getOpcode() != RISCVISD::ADD_LO ||
21968 Ptr.getOperand(0).getOpcode() != RISCVISD::HI)
21971 auto *CNodeLo = GetSupportedConstantPool(
Ptr.getOperand(1));
21972 auto *CNodeHi = GetSupportedConstantPool(
Ptr.getOperand(0).getOperand(0));
21978 if (CNodeLo->getConstVal() != CNodeHi->getConstVal())
21981 return CNodeLo->getConstVal();
21986 assert(
MI.getOpcode() == RISCV::ReadCounterWide &&
"Unexpected instruction");
22018 Register ReadAgainReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
22021 int64_t LoCounter =
MI.getOperand(2).getImm();
22022 int64_t HiCounter =
MI.getOperand(3).getImm();
22032 BuildMI(LoopMBB,
DL,
TII->get(RISCV::CSRRS), ReadAgainReg)
22044 MI.eraseFromParent();
22052 assert(
MI.getOpcode() == RISCV::SplitF64Pseudo &&
"Unexpected instruction");
22060 Register SrcReg =
MI.getOperand(2).getReg();
22065 TII.storeRegToStackSlot(*BB,
MI, SrcReg,
MI.getOperand(2).isKill(), FI, SrcRC,
22080 MI.eraseFromParent();
22087 assert(
MI.getOpcode() == RISCV::BuildPairF64Pseudo &&
22088 "Unexpected instruction");
22094 Register DstReg =
MI.getOperand(0).getReg();
22116 TII.loadRegFromStackSlot(*BB,
MI, DstReg, FI, DstRC, RI,
Register());
22117 MI.eraseFromParent();
22122 unsigned RelOpcode,
unsigned EqOpcode,
22125 Register DstReg =
MI.getOperand(0).getReg();
22126 Register Src1Reg =
MI.getOperand(1).getReg();
22127 Register Src2Reg =
MI.getOperand(2).getReg();
22129 Register SavedFFlags =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22153 MI.eraseFromParent();
22204 F->insert(It, FirstMBB);
22205 F->insert(It, SecondMBB);
22206 F->insert(It, SinkMBB);
22256 First.eraseFromParent();
22296 if (
MI.getOpcode() != RISCV::Select_GPR_Using_CC_GPR &&
22297 MI.getOperand(1).isReg() &&
MI.getOperand(2).isReg() &&
22298 Next != BB->
end() &&
Next->getOpcode() ==
MI.getOpcode() &&
22299 Next->getOperand(5).getReg() ==
MI.getOperand(0).getReg() &&
22300 Next->getOperand(5).isKill())
22305 if (
MI.getOperand(2).isReg())
22306 RHS =
MI.getOperand(2).getReg();
22311 SelectDests.
insert(
MI.getOperand(0).getReg());
22317 SequenceMBBI !=
E; ++SequenceMBBI) {
22318 if (SequenceMBBI->isDebugInstr())
22320 if (RISCVInstrInfo::isSelectPseudo(*SequenceMBBI)) {
22321 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
22322 !SequenceMBBI->getOperand(2).isReg() ||
22323 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
22324 SequenceMBBI->getOperand(3).getImm() != CC ||
22325 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
22326 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
22328 LastSelectPseudo = &*SequenceMBBI;
22330 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
22333 if (SequenceMBBI->hasUnmodeledSideEffects() ||
22334 SequenceMBBI->mayLoadOrStore() ||
22335 SequenceMBBI->usesCustomInsertionHook() ||
22336 TII.isFrameInstr(*SequenceMBBI) ||
22337 SequenceMBBI->isStackAligningInlineAsm())
22340 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
22354 F->insert(
I, IfFalseMBB);
22355 F->insert(
I, TailMBB);
22358 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
22364 TailMBB->
push_back(DebugInstr->removeFromParent());
22368 TailMBB->
splice(TailMBB->
end(), HeadMBB,
22378 if (
MI.getOperand(2).isImm())
22381 .
addImm(
MI.getOperand(2).getImm())
22393 auto SelectMBBI =
MI.getIterator();
22394 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
22396 while (SelectMBBI != SelectEnd) {
22397 auto Next = std::next(SelectMBBI);
22398 if (RISCVInstrInfo::isSelectPseudo(*SelectMBBI)) {
22401 TII.get(RISCV::PHI), SelectMBBI->getOperand(0).getReg())
22402 .
addReg(SelectMBBI->getOperand(4).getReg())
22404 .
addReg(SelectMBBI->getOperand(5).getReg())
22411 F->getProperties().resetNoPHIs();
22419 RISCVVInversePseudosTable::getBaseInfo(MCOpcode, LMul, SEW);
22420 assert(
Inverse &&
"Unexpected LMUL and SEW pair for instruction");
22422 RISCV::lookupMaskedIntrinsicByUnmasked(
Inverse->Pseudo);
22423 assert(
Masked &&
"Could not find masked instruction for LMUL and SEW pair");
22429 unsigned CVTXOpc) {
22435 Register SavedFFLAGS =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22448 .
add(
MI.getOperand(1))
22449 .
add(
MI.getOperand(2))
22450 .
add(
MI.getOperand(3))
22452 .
add(
MI.getOperand(4))
22453 .
add(
MI.getOperand(5))
22454 .
add(
MI.getOperand(6))
22469 .
add(
MI.getOperand(0))
22470 .
add(
MI.getOperand(1))
22472 .
add(
MI.getOperand(3))
22474 .
add(
MI.getOperand(4))
22475 .
add(
MI.getOperand(5))
22476 .
add(
MI.getOperand(6))
22486 MI.eraseFromParent();
22492 unsigned CmpOpc, F2IOpc, I2FOpc, FSGNJOpc, FSGNJXOpc;
22494 switch (
MI.getOpcode()) {
22497 case RISCV::PseudoFROUND_H:
22498 CmpOpc = RISCV::FLT_H;
22499 F2IOpc = RISCV::FCVT_W_H;
22500 I2FOpc = RISCV::FCVT_H_W;
22501 FSGNJOpc = RISCV::FSGNJ_H;
22502 FSGNJXOpc = RISCV::FSGNJX_H;
22503 RC = &RISCV::FPR16RegClass;
22505 case RISCV::PseudoFROUND_H_INX:
22506 CmpOpc = RISCV::FLT_H_INX;
22507 F2IOpc = RISCV::FCVT_W_H_INX;
22508 I2FOpc = RISCV::FCVT_H_W_INX;
22509 FSGNJOpc = RISCV::FSGNJ_H_INX;
22510 FSGNJXOpc = RISCV::FSGNJX_H_INX;
22511 RC = &RISCV::GPRF16RegClass;
22513 case RISCV::PseudoFROUND_S:
22514 CmpOpc = RISCV::FLT_S;
22515 F2IOpc = RISCV::FCVT_W_S;
22516 I2FOpc = RISCV::FCVT_S_W;
22517 FSGNJOpc = RISCV::FSGNJ_S;
22518 FSGNJXOpc = RISCV::FSGNJX_S;
22519 RC = &RISCV::FPR32RegClass;
22521 case RISCV::PseudoFROUND_S_INX:
22522 CmpOpc = RISCV::FLT_S_INX;
22523 F2IOpc = RISCV::FCVT_W_S_INX;
22524 I2FOpc = RISCV::FCVT_S_W_INX;
22525 FSGNJOpc = RISCV::FSGNJ_S_INX;
22526 FSGNJXOpc = RISCV::FSGNJX_S_INX;
22527 RC = &RISCV::GPRF32RegClass;
22529 case RISCV::PseudoFROUND_D:
22531 CmpOpc = RISCV::FLT_D;
22532 F2IOpc = RISCV::FCVT_L_D;
22533 I2FOpc = RISCV::FCVT_D_L;
22534 FSGNJOpc = RISCV::FSGNJ_D;
22535 FSGNJXOpc = RISCV::FSGNJX_D;
22536 RC = &RISCV::FPR64RegClass;
22538 case RISCV::PseudoFROUND_D_INX:
22540 CmpOpc = RISCV::FLT_D_INX;
22541 F2IOpc = RISCV::FCVT_L_D_INX;
22542 I2FOpc = RISCV::FCVT_D_L_INX;
22543 FSGNJOpc = RISCV::FSGNJ_D_INX;
22544 FSGNJXOpc = RISCV::FSGNJX_D_INX;
22545 RC = &RISCV::GPRRegClass;
22557 F->insert(
I, CvtMBB);
22558 F->insert(
I, DoneMBB);
22566 MBB->addSuccessor(CvtMBB);
22567 MBB->addSuccessor(DoneMBB);
22569 Register DstReg =
MI.getOperand(0).getReg();
22570 Register SrcReg =
MI.getOperand(1).getReg();
22571 Register MaxReg =
MI.getOperand(2).getReg();
22572 int64_t FRM =
MI.getOperand(3).getImm();
22577 Register FabsReg =
MRI.createVirtualRegister(RC);
22581 Register CmpReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22596 Register F2IReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22618 MI.eraseFromParent();
22625 switch (
MI.getOpcode()) {
22628 case RISCV::ReadCounterWide:
22629 assert(!Subtarget.is64Bit() &&
22630 "ReadCounterWide is only to be used on riscv32");
22632 case RISCV::Select_GPR_Using_CC_GPR:
22633 case RISCV::Select_GPR_Using_CC_Imm5_Zibi:
22634 case RISCV::Select_GPR_Using_CC_SImm5_CV:
22635 case RISCV::Select_GPRNoX0_Using_CC_SImm5NonZero_QC:
22636 case RISCV::Select_GPRNoX0_Using_CC_UImm5NonZero_QC:
22637 case RISCV::Select_GPRNoX0_Using_CC_SImm16NonZero_QC:
22638 case RISCV::Select_GPRNoX0_Using_CC_UImm16NonZero_QC:
22639 case RISCV::Select_GPR_Using_CC_UImmLog2XLen_NDS:
22640 case RISCV::Select_GPR_Using_CC_UImm7_NDS:
22641 case RISCV::Select_FPR16_Using_CC_GPR:
22642 case RISCV::Select_FPR16INX_Using_CC_GPR:
22643 case RISCV::Select_FPR32_Using_CC_GPR:
22644 case RISCV::Select_FPR32INX_Using_CC_GPR:
22645 case RISCV::Select_FPR64_Using_CC_GPR:
22646 case RISCV::Select_FPR64INX_Using_CC_GPR:
22647 case RISCV::Select_FPR64IN32X_Using_CC_GPR:
22649 case RISCV::BuildPairF64Pseudo:
22651 case RISCV::SplitF64Pseudo:
22653 case RISCV::PseudoQuietFLE_H:
22655 case RISCV::PseudoQuietFLE_H_INX:
22656 return emitQuietFCMP(
MI, BB, RISCV::FLE_H_INX, RISCV::FEQ_H_INX, Subtarget);
22657 case RISCV::PseudoQuietFLT_H:
22659 case RISCV::PseudoQuietFLT_H_INX:
22660 return emitQuietFCMP(
MI, BB, RISCV::FLT_H_INX, RISCV::FEQ_H_INX, Subtarget);
22661 case RISCV::PseudoQuietFLE_S:
22663 case RISCV::PseudoQuietFLE_S_INX:
22664 return emitQuietFCMP(
MI, BB, RISCV::FLE_S_INX, RISCV::FEQ_S_INX, Subtarget);
22665 case RISCV::PseudoQuietFLT_S:
22667 case RISCV::PseudoQuietFLT_S_INX:
22668 return emitQuietFCMP(
MI, BB, RISCV::FLT_S_INX, RISCV::FEQ_S_INX, Subtarget);
22669 case RISCV::PseudoQuietFLE_D:
22671 case RISCV::PseudoQuietFLE_D_INX:
22672 return emitQuietFCMP(
MI, BB, RISCV::FLE_D_INX, RISCV::FEQ_D_INX, Subtarget);
22673 case RISCV::PseudoQuietFLE_D_IN32X:
22676 case RISCV::PseudoQuietFLT_D:
22678 case RISCV::PseudoQuietFLT_D_INX:
22679 return emitQuietFCMP(
MI, BB, RISCV::FLT_D_INX, RISCV::FEQ_D_INX, Subtarget);
22680 case RISCV::PseudoQuietFLT_D_IN32X:
22684 case RISCV::PseudoVFROUND_NOEXCEPT_V_M1_MASK:
22686 case RISCV::PseudoVFROUND_NOEXCEPT_V_M2_MASK:
22688 case RISCV::PseudoVFROUND_NOEXCEPT_V_M4_MASK:
22690 case RISCV::PseudoVFROUND_NOEXCEPT_V_M8_MASK:
22692 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF2_MASK:
22694 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF4_MASK:
22696 case RISCV::PseudoFROUND_H:
22697 case RISCV::PseudoFROUND_H_INX:
22698 case RISCV::PseudoFROUND_S:
22699 case RISCV::PseudoFROUND_S_INX:
22700 case RISCV::PseudoFROUND_D:
22701 case RISCV::PseudoFROUND_D_INX:
22702 case RISCV::PseudoFROUND_D_IN32X:
22704 case RISCV::PROBED_STACKALLOC_DYN:
22706 case TargetOpcode::STATEPOINT:
22712 MI.addOperand(*
MI.getMF(),
22718 case TargetOpcode::STACKMAP:
22719 case TargetOpcode::PATCHPOINT:
22720 if (!Subtarget.is64Bit())
22722 "supported on 64-bit targets");
22732 if (
auto *FRMDef =
MI.findRegisterDefOperand(RISCV::FRM,
nullptr)) {
22733 FRMDef->setIsDead(
false);
22737 int Idx = RISCV::getNamedOperandIdx(
MI.getOpcode(), RISCV::OpName::frm);
22747 if (
MI.readsRegister(RISCV::FRM,
nullptr))
22753void RISCVTargetLowering::analyzeInputArgs(
22757 for (
const auto &[Idx, In] :
enumerate(Ins)) {
22763 LLVM_DEBUG(
dbgs() <<
"InputArg #" << Idx <<
" has unhandled type "
22770void RISCVTargetLowering::analyzeOutputArgs(
22774 for (
const auto &[Idx, Out] :
enumerate(Outs)) {
22775 MVT ArgVT = Out.VT;
22776 ISD::ArgFlagsTy ArgFlags = Out.Flags;
22780 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << Idx <<
" has unhandled type "
22797 return DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, Val);
22831 if (In.isOrigArg()) {
22836 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
22837 (
BitWidth < 32 && In.Flags.isZExt())) {
22858 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, LocVT, Val);
22859 if (LocVT == MVT::i64 && VA.
getValVT() == MVT::f32)
22860 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Val);
22872 Val = DAG.
getNode(ISD::BITCAST,
DL, LocVT, Val);
22908 ExtType,
DL, LocVT, Chain, FIN,
22925 Register LoVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
22938 Register HiVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
22942 return DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64,
Lo,
Hi);
22953 switch (CallConv) {
22962#define CC_VLS_CASE(ABI_VLEN) case CallingConv::RISCV_VLSCall_##ABI_VLEN:
22978 if (Subtarget.hasStdExtE())
22980 if (!Subtarget.hasStdExtFOrZfinx() || !Subtarget.hasStdExtDOrZdinx())
22982 "(Zdinx/D) instruction set extensions");
22986 if (Func.hasFnAttribute(
"interrupt")) {
22987 if (!Func.arg_empty())
22989 "Functions with the interrupt attribute cannot have arguments!");
23000 "SiFive-CLIC-preemptible",
23001 "SiFive-CLIC-stack-swap",
23002 "SiFive-CLIC-preemptible-stack-swap",
23006 "Function interrupt attribute argument not supported!");
23008 if (Kind.starts_with(
"qci-") && !Subtarget.hasVendorXqciint())
23010 "'qci-*' interrupt kinds require Xqciint extension");
23012 if (Kind.starts_with(
"SiFive-CLIC-") && !Subtarget.hasVendorXSfmclic())
23014 "'SiFive-CLIC-*' interrupt kinds require XSfmclic extension");
23016 if (Kind ==
"rnmi" && !Subtarget.hasStdExtSmrnmi())
23019 if (Kind.starts_with(
"SiFive-CLIC-preemptible") && TFI->
hasFP(MF))
23021 "have a frame pointer");
23025 MVT XLenVT = Subtarget.getXLenVT();
23026 unsigned XLenInBytes = Subtarget.getXLen() / 8;
23028 std::vector<SDValue> OutChains;
23037 analyzeInputArgs(MF, CCInfo, Ins,
false,
23041 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
23062 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
23063 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
23065 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
23067 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
23096 int VarArgsSaveSize = XLenInBytes * (ArgRegs.
size() - Idx);
23101 if (VarArgsSaveSize == 0) {
23105 int VaArgOffset = -VarArgsSaveSize;
23113 XLenInBytes, VaArgOffset -
static_cast<int>(XLenInBytes),
true);
23114 VarArgsSaveSize += XLenInBytes;
23121 for (
unsigned I = Idx;
I < ArgRegs.
size(); ++
I) {
23122 const Register Reg = RegInfo.createVirtualRegister(RC);
23123 RegInfo.addLiveIn(ArgRegs[
I], Reg);
23126 Chain,
DL, ArgValue, FIN,
23128 OutChains.push_back(Store);
23142 if (!OutChains.empty()) {
23143 OutChains.push_back(Chain);
23153bool RISCVTargetLowering::isEligibleForTailCallOptimization(
23157 auto CalleeCC = CLI.CallConv;
23158 auto &Outs = CLI.Outs;
23160 auto CallerCC = Caller.getCallingConv();
23167 if (Caller.hasFnAttribute(
"interrupt"))
23182 for (
auto &VA : ArgLocs)
23188 auto IsCallerStructRet = Caller.hasStructRetAttr();
23189 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
23190 if (IsCallerStructRet || IsCalleeStructRet)
23195 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
23196 if (CalleeCC != CallerCC) {
23197 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
23198 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
23205 for (
auto &Arg : Outs)
23206 if (Arg.Flags.isByVal())
23232 MVT XLenVT = Subtarget.getXLenVT();
23247 if (Subtarget.hasStdExtE())
23251 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
23257 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
23263 "call site marked musttail");
23270 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
23272 if (!Flags.isByVal())
23276 unsigned Size = Flags.getByValSize();
23277 Align Alignment = Flags.getNonZeroByValAlign();
23284 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
23286 false,
nullptr, IsTailCall,
23298 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
23301 SDValue ArgValue = OutVals[OutIdx];
23309 RISCVISD::SplitF64,
DL, DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
23321 if (!StackPtr.getNode())
23333 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
23351 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
23352 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
23358 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
23359 SDValue PartValue = OutVals[OutIdx + 1];
23360 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
23374 DAG.
getStore(Chain,
DL, ArgValue, SpillSlot,
23376 for (
const auto &Part : Parts) {
23377 SDValue PartValue = Part.first;
23378 SDValue PartOffset = Part.second;
23385 ArgValue = SpillSlot;
23391 if (Flags.isByVal())
23392 ArgValue = ByValArgs[j++];
23399 if (
Options.EmitCallSiteInfo)
23403 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
23404 "for passing parameters");
23407 if (!StackPtr.getNode())
23421 if (!MemOpChains.
empty())
23427 for (
auto &Reg : RegsToPass) {
23428 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
23435 validateCCReservedRegs(RegsToPass, MF);
23439 "Return address register required, but has been reserved."});
23444 bool CalleeIsLargeExternalSymbol =
false;
23450 CalleeIsLargeExternalSymbol =
true;
23461 Ops.push_back(Chain);
23462 Ops.push_back(Callee);
23466 for (
auto &Reg : RegsToPass)
23467 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
23471 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
23472 assert(Mask &&
"Missing call preserved mask for calling convention");
23477 Ops.push_back(Glue);
23480 "Unexpected CFI type for a direct call");
23488 bool NeedSWGuarded =
false;
23490 Subtarget.hasStdExtZicfilp() &&
23492 NeedSWGuarded =
true;
23497 NeedSWGuarded ? RISCVISD::SW_GUARDED_TAIL : RISCVISD::TAIL;
23506 unsigned CallOpc = NeedSWGuarded ? RISCVISD::SW_GUARDED_CALL : RISCVISD::CALL;
23522 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_RISCV);
23525 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
23526 auto &VA = RVLocs[i];
23534 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
23535 assert(VA.needsCustom());
23540 RetValue = DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64, RetValue,
23554 const Type *RetTy)
const {
23556 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
23558 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
23559 MVT VT = Outs[i].VT;
23562 true, Outs[i].OrigTy))
23593 for (
unsigned i = 0, e = RVLocs.
size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
23594 SDValue Val = OutVals[OutIdx];
23603 DAG.
getVTList(MVT::i32, MVT::i32), Val);
23607 Register RegHi = RVLocs[++i].getLocReg();
23609 if (Subtarget.isRegisterReservedByUser(RegLo) ||
23610 Subtarget.isRegisterReservedByUser(RegHi))
23613 "Return value register required, but has been reserved."});
23626 if (Subtarget.isRegisterReservedByUser(VA.
getLocReg()))
23629 "Return value register required, but has been reserved."});
23648 unsigned RetOpc = RISCVISD::RET_GLUE;
23651 if (Func.hasFnAttribute(
"interrupt")) {
23652 if (!Func.getReturnType()->isVoidTy())
23654 "Functions with the interrupt attribute must have void return type!");
23660 if (Kind ==
"supervisor")
23661 RetOpc = RISCVISD::SRET_GLUE;
23662 else if (Kind ==
"rnmi") {
23663 assert(Subtarget.hasFeature(RISCV::FeatureStdExtSmrnmi) &&
23664 "Need Smrnmi extension for rnmi");
23665 RetOpc = RISCVISD::MNRET_GLUE;
23666 }
else if (Kind ==
"qci-nest" || Kind ==
"qci-nonest") {
23667 assert(Subtarget.hasFeature(RISCV::FeatureVendorXqciint) &&
23668 "Need Xqciint for qci-(no)nest");
23669 RetOpc = RISCVISD::QC_C_MILEAVERET_GLUE;
23671 RetOpc = RISCVISD::MRET_GLUE;
23674 return DAG.
getNode(RetOpc,
DL, MVT::Other, RetOps);
23677void RISCVTargetLowering::validateCCReservedRegs(
23678 const SmallVectorImpl<std::pair<llvm::Register, llvm::SDValue>> &Regs,
23686 F,
"Argument register required, but has been reserved."});
23692 if (
N->getNumValues() != 1)
23694 if (!
N->hasNUsesOfValue(1, 0))
23697 SDNode *Copy = *
N->user_begin();
23699 if (Copy->getOpcode() == ISD::BITCAST) {
23711 if (Copy->getOperand(Copy->getNumOperands() - 1).getValueType() == MVT::Glue)
23715 bool HasRet =
false;
23717 if (
Node->getOpcode() != RISCVISD::RET_GLUE)
23724 Chain = Copy->getOperand(0);
23736 if (Constraint.
size() == 1) {
23737 switch (Constraint[0]) {
23754 if (Constraint ==
"vr" || Constraint ==
"vd" || Constraint ==
"vm")
23756 if (Constraint ==
"cr" || Constraint ==
"cR" || Constraint ==
"cf")
23762std::pair<unsigned, const TargetRegisterClass *>
23768 if (Constraint.
size() == 1) {
23769 switch (Constraint[0]) {
23774 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
23775 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
23776 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
23777 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
23778 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23779 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23780 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
23782 if (VT == MVT::f16) {
23783 if (Subtarget.hasStdExtZfhmin())
23784 return std::make_pair(0U, &RISCV::FPR16RegClass);
23785 if (Subtarget.hasStdExtZhinxmin())
23786 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
23787 }
else if (VT == MVT::f32) {
23788 if (Subtarget.hasStdExtF())
23789 return std::make_pair(0U, &RISCV::FPR32RegClass);
23790 if (Subtarget.hasStdExtZfinx())
23791 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
23792 }
else if (VT == MVT::f64) {
23793 if (Subtarget.hasStdExtD())
23794 return std::make_pair(0U, &RISCV::FPR64RegClass);
23795 if (Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23796 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23797 if (Subtarget.hasStdExtZdinx() && Subtarget.is64Bit())
23798 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
23802 if (((VT == MVT::i64 || VT == MVT::f64) && !Subtarget.is64Bit()) ||
23803 (VT == MVT::i128 && Subtarget.is64Bit()))
23804 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23809 }
else if (Constraint ==
"vr") {
23810 for (
const auto *RC :
23811 {&RISCV::VRRegClass, &RISCV::VRM2RegClass, &RISCV::VRM4RegClass,
23812 &RISCV::VRM8RegClass, &RISCV::VRN2M1RegClass, &RISCV::VRN3M1RegClass,
23813 &RISCV::VRN4M1RegClass, &RISCV::VRN5M1RegClass,
23814 &RISCV::VRN6M1RegClass, &RISCV::VRN7M1RegClass,
23815 &RISCV::VRN8M1RegClass, &RISCV::VRN2M2RegClass,
23816 &RISCV::VRN3M2RegClass, &RISCV::VRN4M2RegClass,
23817 &RISCV::VRN2M4RegClass}) {
23819 return std::make_pair(0U, RC);
23823 if (
TRI->isTypeLegalForClass(*RC, ContainerVT))
23824 return std::make_pair(0U, RC);
23827 }
else if (Constraint ==
"vd") {
23828 for (
const auto *RC :
23829 {&RISCV::VRNoV0RegClass, &RISCV::VRM2NoV0RegClass,
23830 &RISCV::VRM4NoV0RegClass, &RISCV::VRM8NoV0RegClass,
23831 &RISCV::VRN2M1NoV0RegClass, &RISCV::VRN3M1NoV0RegClass,
23832 &RISCV::VRN4M1NoV0RegClass, &RISCV::VRN5M1NoV0RegClass,
23833 &RISCV::VRN6M1NoV0RegClass, &RISCV::VRN7M1NoV0RegClass,
23834 &RISCV::VRN8M1NoV0RegClass, &RISCV::VRN2M2NoV0RegClass,
23835 &RISCV::VRN3M2NoV0RegClass, &RISCV::VRN4M2NoV0RegClass,
23836 &RISCV::VRN2M4NoV0RegClass}) {
23838 return std::make_pair(0U, RC);
23842 if (
TRI->isTypeLegalForClass(*RC, ContainerVT))
23843 return std::make_pair(0U, RC);
23846 }
else if (Constraint ==
"vm") {
23847 if (
TRI->isTypeLegalForClass(RISCV::VMV0RegClass, VT.
SimpleTy))
23848 return std::make_pair(0U, &RISCV::VMV0RegClass);
23854 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, ContainerVT))
23855 return std::make_pair(0U, &RISCV::VMV0RegClass);
23857 }
else if (Constraint ==
"cr") {
23858 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
23859 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
23860 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
23861 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
23862 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23863 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23865 return std::make_pair(0U, &RISCV::GPRCRegClass);
23866 }
else if (Constraint ==
"cR") {
23867 if (((VT == MVT::i64 || VT == MVT::f64) && !Subtarget.is64Bit()) ||
23868 (VT == MVT::i128 && Subtarget.is64Bit()))
23869 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23870 }
else if (Constraint ==
"cf") {
23871 if (VT == MVT::f16) {
23872 if (Subtarget.hasStdExtZfhmin())
23873 return std::make_pair(0U, &RISCV::FPR16CRegClass);
23874 if (Subtarget.hasStdExtZhinxmin())
23875 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
23876 }
else if (VT == MVT::f32) {
23877 if (Subtarget.hasStdExtF())
23878 return std::make_pair(0U, &RISCV::FPR32CRegClass);
23879 if (Subtarget.hasStdExtZfinx())
23880 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
23881 }
else if (VT == MVT::f64) {
23882 if (Subtarget.hasStdExtD())
23883 return std::make_pair(0U, &RISCV::FPR64CRegClass);
23884 if (Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23885 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23886 if (Subtarget.hasStdExtZdinx() && Subtarget.is64Bit())
23887 return std::make_pair(0U, &RISCV::GPRCRegClass);
23896 .
Case(
"{zero}", RISCV::X0)
23897 .
Case(
"{ra}", RISCV::X1)
23898 .
Case(
"{sp}", RISCV::X2)
23899 .
Case(
"{gp}", RISCV::X3)
23900 .
Case(
"{tp}", RISCV::X4)
23901 .
Case(
"{t0}", RISCV::X5)
23902 .
Case(
"{t1}", RISCV::X6)
23903 .
Case(
"{t2}", RISCV::X7)
23904 .
Cases(
"{s0}",
"{fp}", RISCV::X8)
23905 .
Case(
"{s1}", RISCV::X9)
23906 .
Case(
"{a0}", RISCV::X10)
23907 .
Case(
"{a1}", RISCV::X11)
23908 .
Case(
"{a2}", RISCV::X12)
23909 .
Case(
"{a3}", RISCV::X13)
23910 .
Case(
"{a4}", RISCV::X14)
23911 .
Case(
"{a5}", RISCV::X15)
23912 .
Case(
"{a6}", RISCV::X16)
23913 .
Case(
"{a7}", RISCV::X17)
23914 .
Case(
"{s2}", RISCV::X18)
23915 .
Case(
"{s3}", RISCV::X19)
23916 .
Case(
"{s4}", RISCV::X20)
23917 .
Case(
"{s5}", RISCV::X21)
23918 .
Case(
"{s6}", RISCV::X22)
23919 .
Case(
"{s7}", RISCV::X23)
23920 .
Case(
"{s8}", RISCV::X24)
23921 .
Case(
"{s9}", RISCV::X25)
23922 .
Case(
"{s10}", RISCV::X26)
23923 .
Case(
"{s11}", RISCV::X27)
23924 .
Case(
"{t3}", RISCV::X28)
23925 .
Case(
"{t4}", RISCV::X29)
23926 .
Case(
"{t5}", RISCV::X30)
23927 .
Case(
"{t6}", RISCV::X31)
23929 if (XRegFromAlias != RISCV::NoRegister)
23930 return std::make_pair(XRegFromAlias, &RISCV::GPRRegClass);
23939 if (Subtarget.hasStdExtF()) {
23941 .
Cases(
"{f0}",
"{ft0}", RISCV::F0_F)
23942 .
Cases(
"{f1}",
"{ft1}", RISCV::F1_F)
23943 .
Cases(
"{f2}",
"{ft2}", RISCV::F2_F)
23944 .
Cases(
"{f3}",
"{ft3}", RISCV::F3_F)
23945 .
Cases(
"{f4}",
"{ft4}", RISCV::F4_F)
23946 .
Cases(
"{f5}",
"{ft5}", RISCV::F5_F)
23947 .
Cases(
"{f6}",
"{ft6}", RISCV::F6_F)
23948 .
Cases(
"{f7}",
"{ft7}", RISCV::F7_F)
23949 .
Cases(
"{f8}",
"{fs0}", RISCV::F8_F)
23950 .
Cases(
"{f9}",
"{fs1}", RISCV::F9_F)
23951 .
Cases(
"{f10}",
"{fa0}", RISCV::F10_F)
23952 .
Cases(
"{f11}",
"{fa1}", RISCV::F11_F)
23953 .
Cases(
"{f12}",
"{fa2}", RISCV::F12_F)
23954 .
Cases(
"{f13}",
"{fa3}", RISCV::F13_F)
23955 .
Cases(
"{f14}",
"{fa4}", RISCV::F14_F)
23956 .
Cases(
"{f15}",
"{fa5}", RISCV::F15_F)
23957 .
Cases(
"{f16}",
"{fa6}", RISCV::F16_F)
23958 .
Cases(
"{f17}",
"{fa7}", RISCV::F17_F)
23959 .
Cases(
"{f18}",
"{fs2}", RISCV::F18_F)
23960 .
Cases(
"{f19}",
"{fs3}", RISCV::F19_F)
23961 .
Cases(
"{f20}",
"{fs4}", RISCV::F20_F)
23962 .
Cases(
"{f21}",
"{fs5}", RISCV::F21_F)
23963 .
Cases(
"{f22}",
"{fs6}", RISCV::F22_F)
23964 .
Cases(
"{f23}",
"{fs7}", RISCV::F23_F)
23965 .
Cases(
"{f24}",
"{fs8}", RISCV::F24_F)
23966 .
Cases(
"{f25}",
"{fs9}", RISCV::F25_F)
23967 .
Cases(
"{f26}",
"{fs10}", RISCV::F26_F)
23968 .
Cases(
"{f27}",
"{fs11}", RISCV::F27_F)
23969 .
Cases(
"{f28}",
"{ft8}", RISCV::F28_F)
23970 .
Cases(
"{f29}",
"{ft9}", RISCV::F29_F)
23971 .
Cases(
"{f30}",
"{ft10}", RISCV::F30_F)
23972 .
Cases(
"{f31}",
"{ft11}", RISCV::F31_F)
23974 if (FReg != RISCV::NoRegister) {
23975 assert(RISCV::F0_F <= FReg && FReg <= RISCV::F31_F &&
"Unknown fp-reg");
23976 if (Subtarget.hasStdExtD() && (VT == MVT::f64 || VT == MVT::Other)) {
23977 unsigned RegNo = FReg - RISCV::F0_F;
23978 unsigned DReg = RISCV::F0_D + RegNo;
23979 return std::make_pair(DReg, &RISCV::FPR64RegClass);
23981 if (VT == MVT::f32 || VT == MVT::Other)
23982 return std::make_pair(FReg, &RISCV::FPR32RegClass);
23983 if (Subtarget.hasStdExtZfhmin() && VT == MVT::f16) {
23984 unsigned RegNo = FReg - RISCV::F0_F;
23985 unsigned HReg = RISCV::F0_H + RegNo;
23986 return std::make_pair(HReg, &RISCV::FPR16RegClass);
23991 if (Subtarget.hasVInstructions()) {
23993 .
Case(
"{v0}", RISCV::V0)
23994 .
Case(
"{v1}", RISCV::V1)
23995 .
Case(
"{v2}", RISCV::V2)
23996 .
Case(
"{v3}", RISCV::V3)
23997 .
Case(
"{v4}", RISCV::V4)
23998 .
Case(
"{v5}", RISCV::V5)
23999 .
Case(
"{v6}", RISCV::V6)
24000 .
Case(
"{v7}", RISCV::V7)
24001 .
Case(
"{v8}", RISCV::V8)
24002 .
Case(
"{v9}", RISCV::V9)
24003 .
Case(
"{v10}", RISCV::V10)
24004 .
Case(
"{v11}", RISCV::V11)
24005 .
Case(
"{v12}", RISCV::V12)
24006 .
Case(
"{v13}", RISCV::V13)
24007 .
Case(
"{v14}", RISCV::V14)
24008 .
Case(
"{v15}", RISCV::V15)
24009 .
Case(
"{v16}", RISCV::V16)
24010 .
Case(
"{v17}", RISCV::V17)
24011 .
Case(
"{v18}", RISCV::V18)
24012 .
Case(
"{v19}", RISCV::V19)
24013 .
Case(
"{v20}", RISCV::V20)
24014 .
Case(
"{v21}", RISCV::V21)
24015 .
Case(
"{v22}", RISCV::V22)
24016 .
Case(
"{v23}", RISCV::V23)
24017 .
Case(
"{v24}", RISCV::V24)
24018 .
Case(
"{v25}", RISCV::V25)
24019 .
Case(
"{v26}", RISCV::V26)
24020 .
Case(
"{v27}", RISCV::V27)
24021 .
Case(
"{v28}", RISCV::V28)
24022 .
Case(
"{v29}", RISCV::V29)
24023 .
Case(
"{v30}", RISCV::V30)
24024 .
Case(
"{v31}", RISCV::V31)
24026 if (VReg != RISCV::NoRegister) {
24027 if (
TRI->isTypeLegalForClass(RISCV::VMRegClass, VT.
SimpleTy))
24028 return std::make_pair(VReg, &RISCV::VMRegClass);
24029 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, VT.
SimpleTy))
24030 return std::make_pair(VReg, &RISCV::VRRegClass);
24031 for (
const auto *RC :
24032 {&RISCV::VRM2RegClass, &RISCV::VRM4RegClass, &RISCV::VRM8RegClass}) {
24033 if (
TRI->isTypeLegalForClass(*RC, VT.
SimpleTy)) {
24034 VReg =
TRI->getMatchingSuperReg(VReg, RISCV::sub_vrm1_0, RC);
24035 return std::make_pair(VReg, RC);
24041 std::pair<Register, const TargetRegisterClass *> Res =
24047 if (Res.second == &RISCV::GPRF16RegClass ||
24048 Res.second == &RISCV::GPRF32RegClass ||
24049 Res.second == &RISCV::GPRPairRegClass)
24050 return std::make_pair(Res.first, &RISCV::GPRRegClass);
24058 if (ConstraintCode.
size() == 1) {
24059 switch (ConstraintCode[0]) {
24074 if (Constraint.
size() == 1) {
24075 switch (Constraint[0]) {
24082 Subtarget.getXLenVT()));
24113 if (Subtarget.hasStdExtZtso()) {
24115 return Builder.CreateFence(Ord);
24120 return Builder.CreateFence(Ord);
24129 if (Subtarget.hasStdExtZtso()) {
24131 return Builder.CreateFence(Ord);
24137 if (Subtarget.enableTrailingSeqCstFence() &&
isa<StoreInst>(Inst) &&
24156 if (Subtarget.hasForcedAtomics())
24161 if (Subtarget.hasStdExtZacas() &&
24162 (
Size >= 32 || Subtarget.hasStdExtZabha()))
24168 if (
Size < 32 && !Subtarget.hasStdExtZabha())
24180 return Intrinsic::riscv_masked_atomicrmw_xchg;
24182 return Intrinsic::riscv_masked_atomicrmw_add;
24184 return Intrinsic::riscv_masked_atomicrmw_sub;
24186 return Intrinsic::riscv_masked_atomicrmw_nand;
24188 return Intrinsic::riscv_masked_atomicrmw_max;
24190 return Intrinsic::riscv_masked_atomicrmw_min;
24192 return Intrinsic::riscv_masked_atomicrmw_umax;
24194 return Intrinsic::riscv_masked_atomicrmw_umin;
24210 Builder.CreateNot(Mask,
"Inv_Mask"),
24217 unsigned XLen = Subtarget.getXLen();
24220 Type *Tys[] = {Builder.getIntNTy(XLen), AlignedAddr->
getType()};
24226 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
24227 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
24228 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
24241 unsigned ValWidth =
24244 Builder.CreateSub(Builder.getIntN(XLen, XLen - ValWidth), ShiftAmt);
24245 Result = Builder.CreateCall(LrwOpScwLoop,
24246 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
24249 Builder.CreateCall(LrwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
24253 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
24261 if (Subtarget.hasForcedAtomics())
24265 if (!(Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas()) &&
24274 unsigned XLen = Subtarget.getXLen();
24275 Value *Ordering = Builder.getIntN(XLen,
static_cast<uint64_t>(Ord));
24276 Intrinsic::ID CmpXchgIntrID = Intrinsic::riscv_masked_cmpxchg;
24278 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
24279 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
24280 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
24282 Type *Tys[] = {Builder.getIntNTy(XLen), AlignedAddr->
getType()};
24283 Value *Result = Builder.CreateIntrinsic(
24284 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, Ordering});
24286 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
24291 EVT DataVT)
const {
24307 return Subtarget.hasStdExtZfhmin();
24309 return Subtarget.hasStdExtF();
24311 return Subtarget.hasStdExtD();
24341 assert(Subtarget.getRealMinVLen() >= 64 &&
"zve32* unsupported");
24343 "RVVBitsPerBlock changed, audit needed");
24352 if (!Subtarget.hasVendorXTHeadMemIdx())
24358 Base =
Op->getOperand(0);
24360 int64_t RHSC = RHS->getSExtValue();
24366 bool isLegalIndexedOffset =
false;
24367 for (
unsigned i = 0; i < 4; i++)
24368 if (
isInt<5>(RHSC >> i) && ((RHSC % (1LL << i)) == 0)) {
24369 isLegalIndexedOffset =
true;
24373 if (!isLegalIndexedOffset)
24390 VT = LD->getMemoryVT();
24391 Ptr = LD->getBasePtr();
24393 VT = ST->getMemoryVT();
24394 Ptr = ST->getBasePtr();
24410 if (Subtarget.hasVendorXCVmem() && !Subtarget.is64Bit()) {
24415 Base = LS->getBasePtr();
24419 if (
Base ==
Op->getOperand(0))
24421 else if (
Base ==
Op->getOperand(1))
24433 VT = LD->getMemoryVT();
24434 Ptr = LD->getBasePtr();
24436 VT = ST->getMemoryVT();
24437 Ptr = ST->getBasePtr();
24461 return VT.
isVector() ? Subtarget.hasVInstructionsF16()
24462 : Subtarget.hasStdExtZfhOrZhinx();
24464 return Subtarget.hasStdExtFOrZfinx();
24466 return Subtarget.hasStdExtDOrZdinx();
24480 const Constant *PersonalityFn)
const {
24485 const Constant *PersonalityFn)
const {
24492 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
24493 Type.getSizeInBits() < Subtarget.getXLen()))
24500 bool IsSigned)
const {
24501 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
24515 const bool HasZmmul = Subtarget.hasStdExtZmmul();
24520 const APInt &Imm = ConstNode->getAPIntValue();
24523 if (Subtarget.hasVendorXqciac() && Imm.isSignedIntN(12))
24527 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
24528 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
24532 if (Subtarget.hasShlAdd(3) && !Imm.isSignedIntN(12) &&
24533 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
24534 (Imm - 8).isPowerOf2()))
24539 if (!Imm.isSignedIntN(12) && Imm.countr_zero() < 12 &&
24540 ConstNode->hasOneUse()) {
24541 APInt ImmS = Imm.ashr(Imm.countr_zero());
24542 if ((ImmS + 1).isPowerOf2() || (ImmS - 1).isPowerOf2() ||
24543 (1 - ImmS).isPowerOf2())
24566 if (C1.
isSignedIntN(12) && !(C1 * C2).isSignedIntN(12))
24575 unsigned *
Fast)
const {
24578 *
Fast = Subtarget.enableUnalignedScalarMem();
24579 return Subtarget.enableUnalignedScalarMem();
24595 *
Fast = Subtarget.enableUnalignedVectorMem();
24596 return Subtarget.enableUnalignedVectorMem();
24601 const AttributeList &FuncAttributes)
const {
24602 if (!Subtarget.hasVInstructions())
24605 if (FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat))
24617 const unsigned MinVLenInBytes =
24618 std::min(Subtarget.getRealMinVLen() / 8, 1024U);
24620 if (
Op.size() < MinVLenInBytes)
24635 MVT PreferredVT = (
Op.isMemset() && !
Op.isZeroMemset()) ? MVT::i8 : ELenVT;
24639 if (PreferredVT != MVT::i8 && !Subtarget.enableUnalignedVectorMem()) {
24641 if (
Op.isFixedDstAlign())
24642 RequiredAlign = std::min(RequiredAlign,
Op.getDstAlign());
24644 RequiredAlign = std::min(RequiredAlign,
Op.getSrcAlign());
24652 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
24653 bool IsABIRegCopy = CC.has_value();
24656 MVT PairVT = Subtarget.is64Bit() ? MVT::i128 : MVT::i64;
24657 if ((ValueVT == PairVT ||
24658 (!Subtarget.is64Bit() && Subtarget.hasStdExtZdinx() &&
24659 ValueVT == MVT::f64)) &&
24660 NumParts == 1 && PartVT == MVT::Untyped) {
24662 MVT XLenVT = Subtarget.getXLenVT();
24663 if (ValueVT == MVT::f64)
24668 Parts[0] = DAG.
getNode(RISCVISD::BuildGPRPair,
DL, PartVT,
Lo,
Hi);
24672 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
24673 PartVT == MVT::f32) {
24676 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::i16, Val);
24680 Val = DAG.
getNode(ISD::BITCAST,
DL, PartVT, Val);
24688 [[maybe_unused]]
unsigned ValLMUL =
24692 [[maybe_unused]]
unsigned PartLMUL =
24695 assert(ValNF == PartNF && ValLMUL == PartLMUL &&
24696 "RISC-V vector tuple type only accepts same register class type "
24717 if (PartVTBitSize % ValueVTBitSize == 0) {
24718 assert(PartVTBitSize >= ValueVTBitSize);
24725 if (ValueEltVT != PartEltVT) {
24726 if (PartVTBitSize > ValueVTBitSize) {
24728 assert(
Count != 0 &&
"The number of element should not be zero.");
24729 EVT SameEltTypeVT =
24733 Val = DAG.
getNode(ISD::BITCAST,
DL, PartVT, Val);
24747 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
24748 bool IsABIRegCopy = CC.has_value();
24750 MVT PairVT = Subtarget.is64Bit() ? MVT::i128 : MVT::i64;
24751 if ((ValueVT == PairVT ||
24752 (!Subtarget.is64Bit() && Subtarget.hasStdExtZdinx() &&
24753 ValueVT == MVT::f64)) &&
24754 NumParts == 1 && PartVT == MVT::Untyped) {
24756 MVT XLenVT = Subtarget.getXLenVT();
24765 if (ValueVT == MVT::f64)
24770 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
24771 PartVT == MVT::f32) {
24775 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::i32, Val);
24777 Val = DAG.
getNode(ISD::BITCAST,
DL, ValueVT, Val);
24793 if (PartVTBitSize % ValueVTBitSize == 0) {
24794 assert(PartVTBitSize >= ValueVTBitSize);
24795 EVT SameEltTypeVT = ValueVT;
24802 if (ValueEltVT != PartEltVT) {
24804 assert(
Count != 0 &&
"The number of element should not be zero.");
24807 Val = DAG.
getNode(ISD::BITCAST,
DL, SameEltTypeVT, Val);
24823 bool OptSize = Attr.hasFnAttr(Attribute::MinSize);
24830 unsigned Opc =
N->getOpcode();
24839 M, Intrinsic::thread_pointer, IRB.
getPtrTy());
24847 if (Subtarget.isTargetFuchsia())
24853 if (Subtarget.isTargetAndroid())
24858 if (M->getStackProtectorGuard() ==
"tls") {
24860 int Offset = M->getStackProtectorGuardOffset();
24868 Align Alignment)
const {
24869 if (!Subtarget.hasVInstructions())
24873 if (DataType.isFixedLengthVector() && !Subtarget.useRVVForFixedLengthVectors())
24880 if (!Subtarget.enableUnalignedVectorMem() &&
24892 "Invalid call instruction for a KCFI check");
24894 MBBI->getOpcode()));
24897 Target.setIsRenamable(
false);
24905#define GET_REGISTER_MATCHER
24906#include "RISCVGenAsmMatcher.inc"
24917 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
24918 if (!ReservedRegs.
test(Reg) && !Subtarget.isRegisterReservedByUser(Reg))
24926 const MDNode *NontemporalInfo =
I.getMetadata(LLVMContext::MD_nontemporal);
24928 if (NontemporalInfo ==
nullptr)
24936 int NontemporalLevel = 5;
24937 const MDNode *RISCVNontemporalInfo =
24938 I.getMetadata(
"riscv-nontemporal-domain");
24939 if (RISCVNontemporalInfo !=
nullptr)
24946 assert((1 <= NontemporalLevel && NontemporalLevel <= 5) &&
24947 "RISC-V target doesn't support this non-temporal domain.");
24949 NontemporalLevel -= 2;
24951 if (NontemporalLevel & 0b1)
24953 if (NontemporalLevel & 0b10)
24966 return TargetFlags;
24979 return Subtarget.hasStdExtZvbb();
24984 return Subtarget.hasCPOPLike() && (VT == MVT::i32 || VT == MVT::i64);
24994 if (Subtarget.hasStdExtZalasr()) {
24995 if (Subtarget.hasStdExtZtso()) {
25025 if (
Op == Instruction::Add ||
Op == Instruction::Sub ||
25026 Op == Instruction::And ||
Op == Instruction::Or ||
25027 Op == Instruction::Xor ||
Op == Instruction::InsertElement ||
25028 Op == Instruction::ShuffleVector ||
Op == Instruction::Load ||
25029 Op == Instruction::Freeze ||
Op == Instruction::Store)
25034 if (RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(
II->getIntrinsicID()))
25047 if (AI->getAllocatedType()->isScalableTy())
25055RISCVTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
25063 if (!Subtarget.hasShortForwardBranchOpt())
25065 EVT VT =
N->getValueType(0);
25066 if (!(VT == MVT::i32 || (VT == MVT::i64 && Subtarget.
is64Bit())))
25070 if (Divisor.
sgt(2048) || Divisor.
slt(-2048))
25075bool RISCVTargetLowering::shouldFoldSelectWithSingleBitTest(
25076 EVT VT,
const APInt &AndMask)
const {
25077 if (Subtarget.
hasCZEROLike() || Subtarget.hasVendorXTHeadCondMov())
25083 return Subtarget.getMinimumJumpTableEntries();
25090 if (Subtarget.hasStdExtZicfilp()) {
25097 return DAG.
getNode(RISCVISD::SW_GUARDED_BRIND, dl, MVT::Other, Chain, Addr);
25114std::pair<const TargetRegisterClass *, uint8_t>
25134#define GET_RISCVVIntrinsicsTable_IMPL
25135#include "RISCVGenSearchableTables.inc"
25150 Align StackAlign)
const {
25154 unsigned StackProbeSize =
25158 return StackProbeSize ? StackProbeSize : StackAlign.
value();
25175 EVT VT =
Op.getValueType();
25186 Chain = DAG.
getNode(RISCVISD::PROBED_ALLOCA, dl, MVT::Other, Chain, SP);
25196 Register TargetReg =
MI.getOperand(0).getReg();
25199 bool IsRV64 = Subtarget.is64Bit();
25200 Align StackAlign = Subtarget.getFrameLowering()->getStackAlign();
25207 MF.
insert(MBBInsertPoint, LoopTestMBB);
25209 MF.
insert(MBBInsertPoint, ExitMBB);
25225 TII->get(IsRV64 ? RISCV::SD : RISCV::SW))
25246 MBB->addSuccessor(LoopTestMBB);
25248 MI.eraseFromParent();
25250 return ExitMBB->
begin()->getParent();
25254 if (Subtarget.hasStdExtFOrZfinx()) {
25255 static const MCPhysReg RCRegs[] = {RISCV::FRM, RISCV::FFLAGS};
unsigned const MachineRegisterInfo * MRI
static MCRegister MatchRegisterName(StringRef Name)
static EVT getContainerForFixedLengthVector(SelectionDAG &DAG, EVT VT)
static SDValue performSHLCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
If the operand is a bitwise AND with a constant RHS, and the shift has a constant RHS and is the only...
static SDValue performORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const AArch64Subtarget *Subtarget, const AArch64TargetLowering &TLI)
static SDValue performANDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG)
static SDValue tryWidenMaskForShuffle(SDValue Op, SelectionDAG &DAG)
static SDValue performSETCCCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
static SDValue convertToScalableVector(SelectionDAG &DAG, EVT VT, SDValue V)
static SDValue convertFromScalableVector(SelectionDAG &DAG, EVT VT, SDValue V)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isConstant(const MachineInstr &MI)
AMDGPU Register Bank Select
static bool isZeroOrAllOnes(SDValue N, bool AllOnes)
static SDValue combineSelectAndUseCommutative(SDNode *N, bool AllOnes, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp, TargetLowering::DAGCombinerInfo &DCI, bool AllOnes=false)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static MCRegister MatchRegisterAltName(StringRef Name)
Maps from the set of all alternative registernames to a register number.
Function Alias Analysis Results
static SDValue getTargetNode(ConstantPoolSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, unsigned Flags)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static MachineBasicBlock * emitSelectPseudo(MachineInstr &MI, MachineBasicBlock *BB, unsigned Opcode)
static SDValue unpackFromRegLoc(const CSKYSubtarget &Subtarget, SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
static InstructionCost getCost(Instruction &Inst, TTI::TargetCostKind CostKind, TargetTransformInfo &TTI, TargetLibraryInfo &TLI)
const HexagonInstrInfo * TII
This file defines an InstructionCost class that is used when calculating the cost of an instruction,...
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define CC_VLS_CASE(ABIVlen)
static Align getPrefTypeAlign(EVT VT, SelectionDAG &DAG)
static std::optional< bool > matchSetCC(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue Val)
static SDValue customLegalizeToWOpWithSExt(SDNode *N, SelectionDAG &DAG)
static SDValue foldBinOpIntoSelectIfProfitable(SDNode *BO, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue customLegalizeToWOp(SDNode *N, SelectionDAG &DAG, int NumOp, unsigned ExtOpc=ISD::ANY_EXTEND)
static bool combine_CC(SDValue &LHS, SDValue &RHS, SDValue &CC, const SDLoc &DL, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static MachineBasicBlock * emitBuildPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static Intrinsic::ID getIntrinsicForMaskedAtomicRMWBinOp(unsigned GRLen, AtomicRMWInst::BinOp BinOp)
static void translateSetCCForBranch(const SDLoc &DL, SDValue &LHS, SDValue &RHS, ISD::CondCode &CC, SelectionDAG &DAG)
static bool isSplat(Value *V)
Return true if V is a splat of a value (which is used when multiplying a matrix with a scalar).
mir Rename Register Operands
Register const TargetRegisterInfo * TRI
Promote Memory to Register
This file provides utility analysis objects describing memory locations.
static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const MipsSubtarget &Subtarget)
static SDValue performSUBCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const MipsSubtarget &Subtarget)
static SDValue performSELECTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const MipsSubtarget &Subtarget)
static SDValue performMULCombine(SDNode *N, SelectionDAG &DAG, const TargetLowering::DAGCombinerInfo &DCI, const MipsSETargetLowering *TL, const MipsSubtarget &Subtarget)
static SDValue performXORCombine(SDNode *N, SelectionDAG &DAG, const MipsSubtarget &Subtarget)
static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG)
static SDValue performSRACombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const MipsSubtarget &Subtarget)
MachineInstr unsigned OpIdx
uint64_t IntrinsicInst * II
static CodeModel::Model getCodeModel(const PPCSubtarget &S, const TargetMachine &TM, const MachineOperand &MO)
static StringRef getName(Value *V)
static constexpr MCPhysReg SPReg
static StringRef getExtensionType(StringRef Ext)
static SDValue performCONCAT_VECTORSCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue SplitVectorReductionOp(SDValue Op, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static MachineBasicBlock * emitQuietFCMP(MachineInstr &MI, MachineBasicBlock *BB, unsigned RelOpcode, unsigned EqOpcode, const RISCVSubtarget &Subtarget)
static void processVCIXOperands(SDValue OrigOp, MutableArrayRef< SDValue > Operands, SelectionDAG &DAG)
static bool isLowSourceShuffle(ArrayRef< int > Mask, int Span)
Is this mask only using elements from the first span of the input?
static bool isZipOdd(const std::array< std::pair< int, int >, 2 > &SrcInfo, ArrayRef< int > Mask, unsigned &Factor)
Given a shuffle which can be represented as a pair of two slides, see if it is a zipodd idiom.
static SDValue lowerVZIP(unsigned Opc, SDValue Op0, SDValue Op1, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerBuildVectorOfConstants(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue performVECREDUCECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue lowerVECTOR_SHUFFLEAsVSlide1(const SDLoc &DL, MVT VT, SDValue V1, SDValue V2, ArrayRef< int > Mask, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
Match v(f)slide1up/down idioms.
static SDValue combineTruncToVnclip(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::optional< APInt > getExactInteger(const APFloat &APF, uint32_t BitWidth)
static SDValue performVP_TRUNCATECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isInterleaveShuffle(ArrayRef< int > Mask, MVT VT, int &EvenSrc, int &OddSrc, const RISCVSubtarget &Subtarget)
Is this shuffle interleaving contiguous elements from one vector into the even elements and contiguou...
static bool narrowIndex(SDValue &N, ISD::MemIndexType IndexType, SelectionDAG &DAG)
According to the property that indexed load/store instructions zero-extend their indices,...
static SDValue getSingleShuffleSrc(MVT VT, SDValue V1, SDValue V2)
static unsigned getPACKOpcode(unsigned DestBW, const RISCVSubtarget &Subtarget)
static SDValue splatSplitI64WithVL(const SDLoc &DL, MVT VT, SDValue Passthru, SDValue Scalar, SDValue VL, SelectionDAG &DAG)
static bool isLegalBitRotate(ArrayRef< int > Mask, EVT VT, const RISCVSubtarget &Subtarget, MVT &RotateVT, unsigned &RotateAmt)
static SDValue splatPartsI64WithVL(const SDLoc &DL, MVT VT, SDValue Passthru, SDValue Lo, SDValue Hi, SDValue VL, SelectionDAG &DAG)
static SDValue getWideningInterleave(SDValue EvenV, SDValue OddV, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue getAllOnesMask(MVT VecVT, SDValue VL, const SDLoc &DL, SelectionDAG &DAG)
Creates an all ones mask suitable for masking a vector of type VecTy with vector length VL.
static SDValue simplifyOp_VL(SDNode *N)
static SDValue lowerScalarSplat(SDValue Passthru, SDValue Scalar, SDValue VL, MVT VT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isAlternating(const std::array< std::pair< int, int >, 2 > &SrcInfo, ArrayRef< int > Mask, unsigned Factor, bool RequiredPolarity)
static cl::opt< int > FPImmCost(DEBUG_TYPE "-fpimm-cost", cl::Hidden, cl::desc("Give the maximum number of instructions that we will " "use for creating a floating-point immediate value"), cl::init(3))
static const RISCV::RISCVMaskedPseudoInfo * lookupMaskedIntrinsic(uint16_t MCOpcode, RISCVVType::VLMUL LMul, unsigned SEW)
static SDValue expandMul(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue performVWADDSUBW_VLCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static bool matchIndexAsWiderOp(EVT VT, SDValue Index, SDValue Mask, Align BaseAlign, const RISCVSubtarget &ST)
Match the index of a gather or scatter operation as an operation with twice the element width and hal...
static SDValue combineOp_VLToVWOp_VL(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
Combine a binary or FMA operation to its equivalent VW or VW_W form.
static SDValue combineVFMADD_VLWithVFNEG_VL(SDNode *N, SelectionDAG &DAG)
static SDValue combineOrOfCZERO(SDNode *N, SDValue N0, SDValue N1, SelectionDAG &DAG)
static SDValue useInversedSetcc(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static cl::opt< bool > ReassocShlAddiAdd("reassoc-shl-addi-add", cl::Hidden, cl::desc("Swap add and addi in cases where the add may " "be combined with a shift"), cl::init(true))
static SDValue lowerDisjointIndicesShuffle(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Given a shuffle where the indices are disjoint between the two sources, e.g.:
static SDValue combineVWADDSUBWSelect(SDNode *N, SelectionDAG &DAG)
static MachineBasicBlock * EmitLoweredCascadedSelect(MachineInstr &First, MachineInstr &Second, MachineBasicBlock *ThisMBB, const RISCVSubtarget &Subtarget)
static SDValue performINSERT_VECTOR_ELTCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue lowerFABSorFNEG(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerFMAXIMUM_FMINIMUM(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue foldReduceOperandViaVQDOT(SDValue InVec, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue reverseZExtICmpCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue SplitStrictFPVectorOp(SDValue Op, SelectionDAG &DAG)
static void promoteVCIXScalar(SDValue Op, MutableArrayRef< SDValue > Operands, SelectionDAG &DAG)
static SDValue tryDemorganOfBooleanCondition(SDValue Cond, SelectionDAG &DAG)
static SDValue performMemPairCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue combineDeMorganOfBoolean(SDNode *N, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLEAsVSlidedown(const SDLoc &DL, MVT VT, SDValue V1, SDValue V2, ArrayRef< int > Mask, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
static SDValue reduceANDOfAtomicLoad(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static unsigned getRVVReductionOp(unsigned ISDOpcode)
static SDValue combineSubShiftToOrcB(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerShuffleViaVRegSplitting(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static cl::opt< unsigned > NumRepeatedDivisors(DEBUG_TYPE "-fp-repeated-divisors", cl::Hidden, cl::desc("Set the minimum number of repetitions of a divisor to allow " "transformation to multiplications by the reciprocal"), cl::init(2))
static SDValue foldSelectOfCTTZOrCTLZ(SDNode *N, SelectionDAG &DAG)
static SDValue lowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerFixedVectorSegLoadIntrinsics(unsigned IntNo, SDValue Op, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
static SDValue combineVectorMulToSraBitcast(SDNode *N, SelectionDAG &DAG)
static bool isLocalRepeatingShuffle(ArrayRef< int > Mask, int Span)
Is this mask local (i.e.
static bool legalizeScatterGatherIndexType(SDLoc DL, SDValue &Index, ISD::MemIndexType &IndexType, RISCVTargetLowering::DAGCombinerInfo &DCI)
static bool isSpanSplatShuffle(ArrayRef< int > Mask, int Span)
Return true for a mask which performs an arbitrary shuffle within the first span, and then repeats th...
static SDValue getVSlidedown(SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const SDLoc &DL, EVT VT, SDValue Passthru, SDValue Op, SDValue Offset, SDValue Mask, SDValue VL, unsigned Policy=RISCVVType::TAIL_UNDISTURBED_MASK_UNDISTURBED)
static SDValue combineOrToBitfieldInsert(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue getVCIXISDNodeVOID(SDValue Op, SelectionDAG &DAG, unsigned Type)
static unsigned getRISCVVLOp(SDValue Op)
Get a RISC-V target specified VL op for a given SDNode.
static unsigned getVecReduceOpcode(unsigned Opc)
Given a binary operator, return the associative generic ISD::VECREDUCE_OP which corresponds to it.
static std::pair< SDValue, SDValue > getDefaultVLOps(uint64_t NumElts, MVT ContainerVT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isPromotedOpNeedingSplit(SDValue Op, const RISCVSubtarget &Subtarget)
static SDValue performFP_TO_INT_SATCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue lowerReductionSeq(unsigned RVVOpcode, MVT ResVT, SDValue StartValue, SDValue Vec, SDValue Mask, SDValue VL, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Helper to lower a reduction sequence of the form: scalar = reduce_op vec, scalar_start.
static SDValue expandMulToAddOrSubOfShl(SDNode *N, SelectionDAG &DAG, uint64_t MulAmt)
static SDValue performVP_REVERSECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerGetVectorLength(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::pair< SDValue, SDValue > getDefaultScalableVLOps(MVT VecVT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue getVLOperand(SDValue Op)
static SDValue performVECTOR_SHUFFLECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue performVP_STORECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static MachineBasicBlock * emitFROUND(MachineInstr &MI, MachineBasicBlock *MBB, const RISCVSubtarget &Subtarget)
static SDValue getLargeExternalSymbol(ExternalSymbolSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG)
static SDValue lowerCttzElts(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
const uint64_t ModeMask64
static SDValue lowerVectorIntrinsicScalars(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static cl::opt< unsigned > ExtensionMaxWebSize(DEBUG_TYPE "-ext-max-web-size", cl::Hidden, cl::desc("Give the maximum size (in number of nodes) of the web of " "instructions that we will consider for VW expansion"), cl::init(18))
static SDValue combineShlAddIAddImpl(SDNode *N, SDValue AddI, SDValue Other, SelectionDAG &DAG)
static SDValue getDeinterleaveShiftAndTrunc(const SDLoc &DL, MVT VT, SDValue Src, unsigned Factor, unsigned Index, SelectionDAG &DAG)
static SDValue combineBinOpOfZExt(SDNode *N, SelectionDAG &DAG)
static bool matchSelectAddSub(SDValue TrueVal, SDValue FalseVal, bool &SwapCC)
static SDValue performSIGN_EXTEND_INREGCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue combineXorToBitfieldInsert(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::optional< MVT > getSmallestVTForIndex(MVT VecVT, unsigned MaxIdx, SDLoc DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool useRVVForFixedLengthVectorVT(MVT VT, const RISCVSubtarget &Subtarget)
static bool isValidVisniInsertExtractIndex(SDValue Idx)
static Value * useTpOffset(IRBuilderBase &IRB, unsigned Offset)
static SDValue combineAddOfBooleanXor(SDNode *N, SelectionDAG &DAG)
static SDValue getZeroPaddedAdd(const SDLoc &DL, SDValue A, SDValue B, SelectionDAG &DAG)
Given fixed length vectors A and B with equal element types, but possibly different number of element...
const uint32_t ModeMask32
static SDValue combineTruncOfSraSext(SDNode *N, SelectionDAG &DAG)
static SDValue getVSlideup(SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const SDLoc &DL, EVT VT, SDValue Passthru, SDValue Op, SDValue Offset, SDValue Mask, SDValue VL, unsigned Policy=RISCVVType::TAIL_UNDISTURBED_MASK_UNDISTURBED)
static MachineBasicBlock * emitSplitF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const RISCVSubtarget &Subtarget)
static SDValue combineVqdotAccum(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static MachineBasicBlock * emitVFROUND_NOEXCEPT_MASK(MachineInstr &MI, MachineBasicBlock *BB, unsigned CVTXOpc)
static SDValue SplitVectorOp(SDValue Op, SelectionDAG &DAG)
static SDValue combineToVCPOP(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static unsigned negateFMAOpcode(unsigned Opcode, bool NegMul, bool NegAcc)
static SDValue lowerScalarInsert(SDValue Scalar, SDValue VL, MVT VT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerBuildVectorViaVID(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue transformAddShlImm(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue tryFoldSelectIntoOp(SDNode *N, SelectionDAG &DAG, SDValue TrueVal, SDValue FalseVal, bool Swapped)
static SDValue lowerBitreverseShuffle(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerConstant(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool matchIndexAsShuffle(EVT VT, SDValue Index, SDValue Mask, SmallVector< int > &ShuffleMask)
Match the index vector of a scatter or gather node as the shuffle mask which performs the rearrangeme...
static SDValue performVFMADD_VLCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue lowerFixedVectorSegStoreIntrinsics(unsigned IntNo, SDValue Op, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
static SDValue combineBinOpToReduce(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue SplitVPOp(SDValue Op, SelectionDAG &DAG)
static SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue widenVectorOpsToi8(SDValue N, const SDLoc &DL, SelectionDAG &DAG)
static SDValue lowerINT_TO_FP(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerVectorFTRUNC_FCEIL_FFLOOR_FROUND(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerFTRUNC_FCEIL_FFLOOR_FROUND(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::optional< VIDSequence > isSimpleVIDSequence(SDValue Op, unsigned EltSizeInBits)
static SDValue getVCIXISDNodeWCHAIN(SDValue Op, SelectionDAG &DAG, unsigned Type)
static SDValue lowerVectorXRINT_XROUND(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static uint64_t computeGREVOrGORC(uint64_t x, unsigned ShAmt, bool IsGORC)
static SDValue lowerVECTOR_SHUFFLEAsRotate(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isSimm12Constant(SDValue V)
static RISCVFPRndMode::RoundingMode matchRoundingOp(unsigned Opc)
static SDValue lowerVectorStrictFTRUNC_FCEIL_FFLOOR_FROUND(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue combineTruncSelectToSMaxUSat(SDNode *N, SelectionDAG &DAG)
static bool isElementRotate(const std::array< std::pair< int, int >, 2 > &SrcInfo, unsigned NumElts)
static SDValue performBITREVERSECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue transformAddImmMulImm(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue combineSubOfBoolean(SDNode *N, SelectionDAG &DAG)
static SDValue matchSplatAsGather(SDValue SplatVal, MVT VT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isValidEGW(int EGS, EVT VT, const RISCVSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLEAsVRGatherVX(ShuffleVectorSDNode *SVN, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
Match a single source shuffle which is an identity except that some particular element is repeated.
static bool isNonZeroAVL(SDValue AVL)
static SDValue lowerFP_TO_INT(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static MVT getQDOTXResultType(MVT OpVT)
static SDValue lowerVECTOR_SHUFFLEAsVSlideup(const SDLoc &DL, MVT VT, SDValue V1, SDValue V2, ArrayRef< int > Mask, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
static SDValue getLargeGlobalAddress(GlobalAddressSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG)
static MachineBasicBlock * emitReadCounterWidePseudo(MachineInstr &MI, MachineBasicBlock *BB)
static SDValue getWideningSpread(SDValue V, unsigned Factor, unsigned Index, const SDLoc &DL, SelectionDAG &DAG)
static cl::opt< bool > AllowSplatInVW_W(DEBUG_TYPE "-form-vw-w-with-splat", cl::Hidden, cl::desc("Allow the formation of VW_W operations (e.g., " "VWADD_W) with splat constants"), cl::init(false))
static SDValue unpackF64OnRV32DSoftABI(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const CCValAssign &HiVA, const SDLoc &DL)
static SDValue foldConcatVector(SDValue V1, SDValue V2)
If concat_vector(V1,V2) could be folded away to some existing vector source, return it.
static SDValue tryMemPairCombine(SelectionDAG &DAG, LSBaseSDNode *LSNode1, LSBaseSDNode *LSNode2, SDValue BasePtr, uint64_t Imm)
static std::tuple< unsigned, SDValue, SDValue > getRVVFPReductionOpAndOperands(SDValue Op, SelectionDAG &DAG, EVT EltVT, const RISCVSubtarget &Subtarget)
static SDValue performFP_TO_INTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue combineBinOpOfExtractToReduceTree(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Perform two related transforms whose purpose is to incrementally recognize an explode_vector followed...
static SDValue lowerBuildVectorViaPacking(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Double the element size of the build vector to reduce the number of vslide1down in the build vector c...
static SDValue performTRUNCATECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerSelectToBinOp(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue combineShlAddIAdd(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerBuildVectorViaDominantValues(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Try and optimize BUILD_VECTORs with "dominant values" - these are values which constitute a large pro...
static bool isCompressMask(ArrayRef< int > Mask)
static SDValue expandMulToNAFSequence(SDNode *N, SelectionDAG &DAG, uint64_t MulAmt)
static SDValue combineToVWMACC(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isZipEven(const std::array< std::pair< int, int >, 2 > &SrcInfo, ArrayRef< int > Mask, unsigned &Factor)
Given a shuffle which can be represented as a pair of two slides, see if it is a zipeven idiom.
static SDValue combineVectorSizedSetCCEquality(EVT VT, SDValue X, SDValue Y, ISD::CondCode CC, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Try to map an integer comparison with size > XLEN to vector instructions before type legalization spl...
static SDValue performBUILD_VECTORCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
If we have a build_vector where each lane is binop X, C, where C is a constant (but not necessarily t...
static SDValue combineOrAndToBitfieldInsert(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static LLT getMaskTypeFor(LLT VecTy)
Return the type of the mask type suitable for masking the provided vector type.
static unsigned getRISCVWOpcode(unsigned Opcode)
const SmallVectorImpl< MachineOperand > & Cond
Contains matchers for matching SelectionDAG nodes and values.
static bool isCommutative(Instruction *I, Value *ValWithUses)
static Type * getValueType(Value *V)
Returns the type of the given value/instruction V.
This file defines the SmallSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static constexpr int Concat[]
opStatus convertFromAPInt(const APInt &Input, bool IsSigned, roundingMode RM)
opStatus convertToInteger(MutableArrayRef< integerPart > Input, unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const
static APFloat getNaN(const fltSemantics &Sem, bool Negative=false, uint64_t payload=0)
Factory for NaN values.
Class for arbitrary precision integers.
bool isNegatedPowerOf2() const
Check if this APInt's negated value is a power of two greater than zero.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
uint64_t getZExtValue() const
Get zero extended value.
void setBitsFrom(unsigned loBit)
Set the top bits starting from loBit.
unsigned getActiveBits() const
Compute the number of active bits in the value.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
bool sgt(const APInt &RHS) const
Signed greater than comparison.
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
bool ugt(const APInt &RHS) const
Unsigned greater than comparison.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
unsigned getBitWidth() const
Return the number of bits in the APInt.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
bool isNegative() const
Determine sign of this APInt.
LLVM_ABI APInt sdiv(const APInt &RHS) const
Signed division function for APInt.
void clearAllBits()
Set every bit to 0.
unsigned countr_zero() const
Count the number of trailing zero bits.
bool isSignedIntN(unsigned N) const
Check if this APInt has an N-bits signed integer value.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
unsigned getSignificantBits() const
Get the minimum bit size for this signed APInt.
LLVM_ABI void insertBits(const APInt &SubBits, unsigned bitPosition)
Insert the bits from a smaller APInt starting at bitPosition.
bool isShiftedMask() const
Return true if this APInt value contains a non-empty sequence of ones with the remainder zero.
LLVM_ABI APInt srem(const APInt &RHS) const
Function for signed remainder operation.
bool isMask(unsigned numBits) const
bool isNonNegative() const
Determine if this APInt Value is non-negative (>= 0)
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
bool slt(const APInt &RHS) const
Signed less than comparison.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
void setLowBits(unsigned loBits)
Set the bottom loBits bits.
LLVM_ABI APInt extractBits(unsigned numBits, unsigned bitPosition) const
Return an APInt with the extracted bits [bitPosition,bitPosition+numBits).
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)
Constructs an APInt value that has a contiguous range of bits set.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
int64_t getSExtValue() const
Get sign extended value.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
An arbitrary precision integer that knows its signedness.
an instruction to allocate memory on the stack
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
An instruction that atomically checks whether a specified value is in a memory location,...
Value * getCompareOperand()
an instruction that atomically reads a memory location, combines it with another value,...
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ USubCond
Subtract only if no unsigned overflow.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ UMax
*p = old >unsigned v ? old : v
@ UDecWrap
Decrement one until a minimum value or zero.
bool isFloatingPointOperation() const
BinOp getOperation() const
AtomicOrdering getOrdering() const
Returns the ordering constraint of this rmw instruction.
This is an SDNode representing atomic operations.
const SDValue & getBasePtr() const
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
static LLVM_ABI BaseIndexOffset match(const SDNode *N, const SelectionDAG &DAG)
Parses tree in N for base, index, offset addresses.
LLVM Basic Block Representation.
LLVM_ABI const Module * getModule() const
Return the module owning the function this basic block belongs to, or nullptr if the function does no...
bool test(unsigned Idx) const
bool all() const
all - Returns true if all bits are set.
CCState - This class holds information needed while lowering arguments and return values.
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
LLVM_ABI void AnalyzeCallOperands(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeCallOperands - Analyze the outgoing arguments to a call, incorporating info about the passed v...
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
LLVM_ABI bool isIndirectCall() const
Return true if the callsite is an indirect call.
This class represents a function call, abstracting a target machine's calling convention.
bool isExactlyValue(double V) const
We don't rely on operator== working on double values, as it returns true for things that are clearly ...
This is the shared class of boolean and integer constants.
bool isMinusOne() const
This function will return true iff every bit in this constant is set to true.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
int64_t getSExtValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
unsigned getPointerSizeInBits(unsigned AS=0) const
The size in bits of the pointer representation in a given address space.
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
const ValueT & at(const_arg_type_t< KeyT > Val) const
at - Return the entry for the specified key, or abort if no such entry exists.
Implements a dense probed hash-table based set.
Diagnostic information for unsupported feature in backend.
static constexpr ElementCount getScalable(ScalarTy MinVal)
static constexpr ElementCount getFixed(ScalarTy MinVal)
Tagged union holding either a T or a Error.
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
uint64_t getFnAttributeAsParsedInteger(StringRef Kind, uint64_t Default=0) const
For a string attribute Kind, parse attribute as an integer.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
AttributeList getAttributes() const
Return the attribute list for this Function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Argument * getArg(unsigned i) const
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Helper struct to store a base, index and offset that forms an address.
int64_t getOffset() const
bool hasExternalWeakLinkage() const
Module * getParent()
Get the module that this global value is contained inside of...
Common base class shared among various IRBuilders.
Value * CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
BasicBlock * GetInsertBlock() const
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
static InstructionCost getInvalid(CostType Val=0)
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
Base class for LoadSDNode and StoreSDNode.
bool isIndexed() const
Return true if this is a pre/post inc/dec load/store.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
static constexpr LocationSize beforeOrAfterPointer()
Any location before or after the base pointer (but still within the underlying object).
Context object for machine code objects.
Base class for the full range of assembler expressions which are needed for parsing.
MCContext & getContext() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
const MDOperand & getOperand(unsigned I) const
static MVT getFloatingPointVT(unsigned BitWidth)
static auto integer_fixedlen_vector_valuetypes()
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
bool isRISCVVectorTuple() const
Return true if this is a RISCV vector tuple type where the runtime length is machine dependent.
uint64_t getScalarSizeInBits() const
MVT changeVectorElementType(MVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
bool bitsLE(MVT VT) const
Return true if this has no more bits than VT.
unsigned getVectorNumElements() const
static MVT getRISCVVectorTupleVT(unsigned Sz, unsigned NFields)
bool isVector() const
Return true if this is a vector value type.
bool isInteger() const
Return true if this is an integer or a vector integer type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
static MVT getScalableVectorVT(MVT VT, unsigned NumElements)
unsigned getRISCVVectorTupleNumFields() const
Given a RISC-V vector tuple type, return the num_fields.
MVT changeTypeToInteger()
Return the type converted to an equivalently sized integer or vector with integer element type.
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
bool bitsLT(MVT VT) const
Return true if this has less bits than VT.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
LLVM_ABI const fltSemantics & getFltSemantics() const
Returns an APFloat semantics tag appropriate for the value type.
bool bitsGT(MVT VT) const
Return true if this has more bits than VT.
bool isFixedLengthVector() const
ElementCount getVectorElementCount() const
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool bitsGE(MVT VT) const
Return true if this has no less bits than VT.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
bool isValid() const
Return true if this is a valid simple valuetype.
static MVT getIntegerVT(unsigned BitWidth)
MVT getDoubleNumVectorElementsVT() const
MVT getHalfNumVectorElementsVT() const
Return a VT for a vector type with the same element type but half the number of elements.
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
static auto integer_scalable_vector_valuetypes()
MVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
static auto fp_fixedlen_vector_valuetypes()
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
void push_back(MachineInstr *MI)
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
Instructions::iterator instr_iterator
instr_iterator instr_end()
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
LLVM_ABI void collectDebugValues(SmallVectorImpl< MachineInstr * > &DbgValues)
Scan instructions immediately following MI and collect any matching DBG_VALUEs.
void setFlag(MIFlag Flag)
Set a MI flag.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
@ EK_Custom32
EK_Custom32 - Each entry is a 32-bit value that is custom lowered by the TargetLowering::LowerCustomJ...
A description of a memory reference used in the backend.
const MDNode * getRanges() const
Return the range tag for the memory reference.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MONonTemporal
The memory access is non-temporal.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
const MachinePointerInfo & getPointerInfo() const
Flags getFlags() const
Return the raw flags of the source value,.
AAMDNodes getAAInfo() const
Return the AA tags for the memory reference.
Align getBaseAlign() const
Return the minimum known alignment in bytes of the base address, without the offset.
MachineOperand class - Representation of each machine instruction operand.
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
This is an abstract virtual class for memory operations.
bool isSimple() const
Returns true if the memory operation is neither atomic or volatile.
AtomicOrdering getSuccessOrdering() const
Return the atomic ordering requirements for this memory operation.
MachineMemOperand * getMemOperand() const
Return a MachineMemOperand object describing the memory reference performed by operation.
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
A Module instance is used to store all the information related to an LLVM module.
Metadata * getModuleFlag(StringRef Key) const
Return the corresponding value if Key appears in module flags, otherwise return null.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
A RISCV-specific constant pool value.
static RISCVConstantPoolValue * Create(const GlobalValue *GV)
RISCVMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private RISCV-...
void setVarArgsFrameIndex(int Index)
int getVarArgsFrameIndex() const
void setVarArgsSaveSize(int Size)
void addSExt32Register(Register Reg)
unsigned getMaxLMULForFixedLengthVectors() const
bool hasVInstructionsI64() const
bool hasVInstructionsF64() const
bool hasStdExtZfhOrZhinx() const
bool hasShlAdd(int64_t ShAmt) const
unsigned getRealMinVLen() const
bool useRVVForFixedLengthVectors() const
bool hasVInstructionsBF16Minimal() const
bool hasVInstructionsF16Minimal() const
bool hasConditionalMoveFusion() const
bool hasVInstructionsF16() const
unsigned getMaxBuildIntsCost() const
bool hasVInstructions() const
bool isRegisterReservedByUser(Register i) const override
std::optional< unsigned > getRealVLen() const
bool useConstantPoolForLargeInts() const
unsigned getRealMaxVLen() const
const RISCVRegisterInfo * getRegisterInfo() const override
const RISCVInstrInfo * getInstrInfo() const override
bool hasBEXTILike() const
const RISCVTargetLowering * getTargetLowering() const override
bool hasVInstructionsF32() const
bool hasCZEROLike() const
static std::pair< unsigned, unsigned > computeVLMAXBounds(MVT ContainerVT, const RISCVSubtarget &Subtarget)
static std::pair< unsigned, unsigned > decomposeSubvectorInsertExtractToSubRegs(MVT VecVT, MVT SubVecVT, unsigned InsertExtractIdx, const RISCVRegisterInfo *TRI)
ArrayRef< MCPhysReg > getRoundingControlRegisters() const override
Returns a 0 terminated array of rounding control registers that can be attached into strict FP call.
static MVT getM1VT(MVT VT)
Given a vector (either fixed or scalable), return the scalable vector corresponding to a vector regis...
InstructionCost getVRGatherVVCost(MVT VT) const
Return the cost of a vrgather.vv instruction for the type VT.
bool getIndexedAddressParts(SDNode *Op, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const
static unsigned getSubregIndexByMVT(MVT VT, unsigned Index)
Value * getIRStackGuard(IRBuilderBase &IRB) const override
If the target has a standard location for the stack protector cookie, returns the address of that loc...
bool shouldConvertFpToSat(unsigned Op, EVT FPVT, EVT VT) const override
Should we generate fp_to_si_sat and fp_to_ui_sat from type FPVT to type VT from min(max(fptoi)) satur...
InlineAsm::ConstraintCode getInlineAsmMemConstraint(StringRef ConstraintCode) const override
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
bool mayBeEmittedAsTailCall(const CallInst *CI) const override
Return true if the target may be able emit the call instruction as a tail call.
RISCVTargetLowering(const TargetMachine &TM, const RISCVSubtarget &STI)
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
Instruction * emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
Inserts in the IR a target-specific intrinsic specifying a fence.
bool isTruncateFree(Type *SrcTy, Type *DstTy) const override
Return true if it's free to truncate a value of type FromTy to type ToTy.
bool shouldRemoveExtendFromGSIndex(SDValue Extend, EVT DataVT) const override
Value * emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI, Value *AlignedAddr, Value *Incr, Value *Mask, Value *ShiftAmt, AtomicOrdering Ord) const override
Perform a masked atomicrmw using a target-specific intrinsic.
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const override
Returns true if the target allows unaligned memory accesses of the specified type.
const Constant * getTargetConstantFromLoad(LoadSDNode *LD) const override
This method returns the constant pool value that will be loaded by LD.
const RISCVSubtarget & getSubtarget() const
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
bool preferScalarizeSplat(SDNode *N) const override
bool shouldExtendTypeInLibCall(EVT Type) const override
Returns true if arguments should be extended in lib calls.
bool isLegalAddImmediate(int64_t Imm) const override
Return true if the specified immediate is legal add immediate, that is the target has add instruction...
bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const override
Returns true if arguments should be sign-extended in lib calls.
const MCExpr * LowerCustomJumpTableEntry(const MachineJumpTableInfo *MJTI, const MachineBasicBlock *MBB, unsigned uid, MCContext &Ctx) const override
InstructionCost getVRGatherVICost(MVT VT) const
Return the cost of a vrgather.vi (or vx) instruction for the type VT.
bool shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const override
Return true if it is beneficial to convert a load of a constant to just the constant itself.
bool targetShrinkDemandedConstant(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, TargetLoweringOpt &TLO) const override
bool shouldExpandBuildVectorWithShuffles(EVT VT, unsigned DefinedValues) const override
MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Return the register type for a given MVT, ensuring vectors are treated as a series of gpr sized integ...
bool decomposeMulByConstant(LLVMContext &Context, EVT VT, SDValue C) const override
Return true if it is profitable to transform an integer multiplication-by-constant into simpler opera...
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, LLVMContext &Context, const Type *RetTy) const override
This hook should be implemented to check whether the return values described by the Outs array can fi...
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
bool hasAndNotCompare(SDValue Y) const override
Return true if the target should transform: (X & Y) == Y ---> (~X & Y) == 0 (X & Y) !...
bool shouldScalarizeBinop(SDValue VecOp) const override
Try to convert an extract element of a vector binary operation into an extract element followed by a ...
bool isDesirableToCommuteWithShift(const SDNode *N, CombineLevel Level) const override
Return true if it is profitable to move this shift by a constant amount through its operand,...
bool areTwoSDNodeTargetMMOFlagsMergeable(const MemSDNode &NodeX, const MemSDNode &NodeY) const override
Return true if it is valid to merge the TargetMMOFlags in two SDNodes.
bool hasBitTest(SDValue X, SDValue Y) const override
Return true if the target has a bit-test instruction: (X & (1 << Y)) ==/!= 0 This knowledge can be us...
static unsigned computeVLMAX(unsigned VectorBits, unsigned EltSize, unsigned MinSize)
bool shouldExpandCttzElements(EVT VT) const override
Return true if the @llvm.experimental.cttz.elts intrinsic should be expanded using generic code in Se...
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
Value * emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, AtomicCmpXchgInst *CI, Value *AlignedAddr, Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const override
Perform a masked cmpxchg using a target-specific intrinsic.
bool isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize) const override
Returns true if the target can instruction select the specified FP immediate natively.
InstructionCost getLMULCost(MVT VT) const
Return the cost of LMUL for linear operations.
unsigned getJumpTableEncoding() const override
Return the entry encoding for a jump table in the current function.
bool isMulAddWithConstProfitable(SDValue AddNode, SDValue ConstNode) const override
Return true if it may be profitable to transform (mul (add x, c1), c2) -> (add (mul x,...
InstructionCost getVSlideVICost(MVT VT) const
Return the cost of a vslidedown.vi or vslideup.vi instruction for the type VT.
bool fallBackToDAGISel(const Instruction &Inst) const override
EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
bool isCtpopFast(EVT VT) const override
Return true if ctpop instruction is fast.
unsigned ComputeNumSignBitsForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
This method can be implemented by targets that want to expose additional information about sign bits ...
MVT getContainerForFixedLengthVector(MVT VT) const
static unsigned getRegClassIDForVecVT(MVT VT)
Register getExceptionPointerRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
TargetLowering::AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return true if EXTRACT_SUBVECTOR is cheap for extracting this result type from this source type with ...
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
MachineBasicBlock * emitDynamicProbedAlloc(MachineInstr &MI, MachineBasicBlock *MBB) const
MachineMemOperand::Flags getTargetMMOFlags(const Instruction &I) const override
This callback is used to inspect load/store instructions and add target-specific MachineMemOperand fl...
SDValue computeVLMax(MVT VecVT, const SDLoc &DL, SelectionDAG &DAG) const
bool signExtendConstant(const ConstantInt *CI) const override
Return true if this constant should be sign extended when promoting to a larger type.
bool shouldTransformSignedTruncationCheck(EVT XVT, unsigned KeptBits) const override
Should we tranform the IR-optimal check for whether given truncation down into KeptBits would be trun...
bool shouldProduceAndByConstByHoistingConstFromShiftsLHSOfAnd(SDValue X, ConstantSDNode *XC, ConstantSDNode *CC, SDValue Y, unsigned OldShiftOpcode, unsigned NewShiftOpcode, SelectionDAG &DAG) const override
Given the pattern (X & (C l>>/<< Y)) ==/!= 0 return true if it should be transformed into: ((X <</l>>...
bool hasInlineStackProbe(const MachineFunction &MF) const override
True if stack clash protection is enabled for this functions.
bool hasAndNot(SDValue Y) const override
Return true if the target has a bitwise and-not operation: X = ~A & B This can be used to simplify se...
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Returns the register with the specified architectural or ABI name.
InstructionCost getVSlideVXCost(MVT VT) const
Return the cost of a vslidedown.vx or vslideup.vx instruction for the type VT.
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override
Return true if result of the specified node is used by a return node only.
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const override
Return true if an FMA operation is faster than a pair of fmul and fadd instructions.
TargetLowering::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *CI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
Register getExceptionSelectorRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
unsigned getCustomCtpopCost(EVT VT, ISD::CondCode Cond) const override
Return the maximum number of "x & (x - 1)" operations that can be done instead of deferring to a cust...
void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override
This method should be implemented by targets that mark instructions with the 'hasPostISelHook' flag.
bool isShuffleMaskLegal(ArrayRef< int > M, EVT VT) const override
Return true if the given shuffle mask can be codegen'd directly, or if it should be stack expanded.
bool isCheapToSpeculateCttz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic cttz.
bool isLegalICmpImmediate(int64_t Imm) const override
Return true if the specified immediate is legal icmp immediate, that is the target has icmp instructi...
ISD::NodeType getExtendForAtomicCmpSwapArg() const override
Returns how the platform's atomic compare and swap expects its comparison value to be extended (ZERO_...
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower the incoming (formal) arguments, described by the Ins array,...
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I, MachineFunction &MF, unsigned Intrinsic) const override
Given an intrinsic, checks if on the target the intrinsic will need to map to a MemIntrinsicNode (tou...
unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const override
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
bool isLegalElementTypeForRVV(EVT ScalarTy) const
bool isVScaleKnownToBeAPowerOfTwo() const override
Return true only if vscale must be a power of two.
int getLegalZfaFPImm(const APFloat &Imm, EVT VT) const
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
Lower the specified operand into the Ops vector.
bool splitValueIntoRegisterParts(SelectionDAG &DAG, const SDLoc &DL, SDValue Val, SDValue *Parts, unsigned NumParts, MVT PartVT, std::optional< CallingConv::ID > CC) const override
Target-specific splitting of values into parts that fit a register storing a legal type.
Instruction * emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Return the number of registers for a given MVT, ensuring vectors are treated as a series of gpr sized...
ConstraintType getConstraintType(StringRef Constraint) const override
getConstraintType - Given a constraint letter, return the type of constraint it is for this target.
MachineInstr * EmitKCFICheck(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator &MBBI, const TargetInstrInfo *TII) const override
bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool PoisonOnly, bool ConsiderFlags, unsigned Depth) const override
Return true if Op can create undef or poison from non-undef & non-poison operands.
bool isIntDivCheap(EVT VT, AttributeList Attr) const override
Return true if integer divide is usually cheaper than a sequence of several shifts,...
SDValue expandIndirectJTBranch(const SDLoc &dl, SDValue Value, SDValue Addr, int JTI, SelectionDAG &DAG) const override
Expands target specific indirect branch for the case of JumpTable expansion.
static unsigned getRegClassIDForLMUL(RISCVVType::VLMUL LMul)
unsigned getNumRegisters(LLVMContext &Context, EVT VT, std::optional< MVT > RegisterVT=std::nullopt) const override
Return the number of registers for a given MVT, for inline assembly.
bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
Returns true by value, base pointer and offset pointer and addressing mode by reference if this node ...
bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
Returns true by value, base pointer and offset pointer and addressing mode by reference if the node's...
SDValue joinRegisterPartsIntoValue(SelectionDAG &DAG, const SDLoc &DL, const SDValue *Parts, unsigned NumParts, MVT PartVT, EVT ValueVT, std::optional< CallingConv::ID > CC) const override
Target-specific combining of register parts into its original value.
bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const override
Return if the target supports combining a chain like:
bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override
Return true if sign-extension from FromTy to ToTy is cheaper than zero-extension.
bool isLegalStridedLoadStore(EVT DataType, Align Alignment) const
Return true if a stride load store of the given result type and alignment is legal.
static bool isSpreadMask(ArrayRef< int > Mask, unsigned Factor, unsigned &Index)
Match a mask which "spreads" the leading elements of a vector evenly across the result.
static RISCVVType::VLMUL getLMUL(MVT VT)
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth) const override
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
bool shouldFoldSelectWithIdentityConstant(unsigned BinOpcode, EVT VT, unsigned SelectOpcode, SDValue X, SDValue Y) const override
Return true if pulling a binary operation into a select with an identity constant is profitable.
unsigned getStackProbeSize(const MachineFunction &MF, Align StackAlign) const
bool shouldInsertFencesForAtomic(const Instruction *I) const override
Whether AtomicExpandPass should automatically insert fences and reduce ordering for this atomic.
Wrapper class representing virtual and physical registers.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
ArrayRef< SDUse > ops() const
const APInt & getAsAPIntVal() const
Helper method returns the APInt value of a ConstantSDNode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
iterator_range< use_iterator > uses()
SDNodeFlags getFlags() const
size_t use_size() const
Return the number of uses of this node.
MVT getSimpleValueType(unsigned ResNo) const
Return the type of a specified result as a simple type.
static bool hasPredecessorHelper(const SDNode *N, SmallPtrSetImpl< const SDNode * > &Visited, SmallVectorImpl< const SDNode * > &Worklist, unsigned int MaxSteps=0, bool TopologicalPrune=false)
Returns true if N is a predecessor of any node in Worklist.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
const SDValue & getOperand(unsigned Num) const
std::optional< APInt > bitcastToAPInt() const
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
void setCFIType(uint32_t Type)
bool isUndef() const
Returns true if the node type is UNDEF or POISON.
iterator_range< user_iterator > users()
Represents a use of a SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
const APInt & getConstantOperandAPInt(unsigned i) const
uint64_t getScalarValueSizeInBits() const
uint64_t getConstantOperandVal(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getOpcode() const
unsigned getNumOperands() const
virtual bool isTargetStrictFPOpcode(unsigned Opcode) const
Returns true if a node with the given target-specific opcode has strict floating-point semantics.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI Align getReducedAlign(EVT VT, bool UseABI)
In most cases this function returns the ABI alignment for a given type, except for illegal vector typ...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
SDValue getExtractVectorElt(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Extract element at Idx from Vec.
LLVM_ABI unsigned ComputeMaxSignificantBits(SDValue Op, unsigned Depth=0) const
Get the upper bound on bit size for this Value Op as a signed integer.
LLVM_ABI SDValue getMaskedGather(SDVTList VTs, EVT MemVT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType, ISD::LoadExtType ExtTy)
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL)
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDValue getNeutralElement(unsigned Opcode, const SDLoc &DL, EVT VT, SDNodeFlags Flags)
Get the (commutative) neutral element for the given opcode, if it exists.
LLVM_ABI SDValue getAtomicLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT MemVT, EVT VT, SDValue Chain, SDValue Ptr, MachineMemOperand *MMO)
LLVM_ABI SDValue getVScale(const SDLoc &DL, EVT VT, APInt MulImm, bool ConstantFold=true)
Return a node that represents the runtime scaling 'MulImm * RuntimeVL'.
LLVM_ABI SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
LLVM_ABI SDValue getStridedLoadVP(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, const SDLoc &DL, SDValue Chain, SDValue Ptr, SDValue Offset, SDValue Stride, SDValue Mask, SDValue EVL, EVT MemVT, MachineMemOperand *MMO, bool IsExpanding=false)
LLVM_ABI SDValue makeEquivalentMemoryOrdering(SDValue OldChain, SDValue NewMemOpChain)
If an existing load has uses of its chain, create a token factor node with that chain and the new mem...
LLVM_ABI SDValue getJumpTableDebugInfo(int JTI, SDValue Chain, const SDLoc &DL)
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false)
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
bool isSafeToSpeculativelyExecute(unsigned Opcode) const
Some opcodes may create immediate undefined behavior when used with some values (integer division-by-...
LLVM_ABI SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
SDValue getExtractSubvector(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Return the VT typed sub-vector of Vec at Idx.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getElementCount(const SDLoc &DL, EVT VT, ElementCount EC, bool ConstantFold=true)
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
SDValue getInsertSubvector(const SDLoc &DL, SDValue Vec, SDValue SubVec, unsigned Idx)
Insert SubVec at the Idx element of Vec.
LLVM_ABI SDValue getStepVector(const SDLoc &DL, EVT ResVT, const APInt &StepVal)
Returns a vector of type ResVT whose elements contain the linear sequence <0, Step,...
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
LLVM_ABI bool shouldOptForSize() const
std::pair< SDValue, SDValue > SplitVectorOperand(const SDNode *N, unsigned OpNo)
Split the node's operand with EXTRACT_SUBVECTOR and return the low/high part.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
LLVM_ABI SDValue getVPZExtOrTrunc(const SDLoc &DL, EVT VT, SDValue Op, SDValue Mask, SDValue EVL)
Convert a vector-predicated Op, which must be an integer vector, to the vector-type VT,...
const TargetLowering & getTargetLoweringInfo() const
LLVM_ABI SDValue getStridedStoreVP(SDValue Chain, const SDLoc &DL, SDValue Val, SDValue Ptr, SDValue Offset, SDValue Stride, SDValue Mask, SDValue EVL, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
bool NewNodesMustHaveLegalTypes
When true, additional steps are taken to ensure that getConstant() and similar functions return DAG n...
LLVM_ABI std::pair< EVT, EVT > GetSplitDestVTs(const EVT &VT) const
Compute the VTs needed for the low/hi parts of a type which is split (or expanded) into two not neces...
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
LLVM_ABI SDValue getGatherVP(SDVTList VTs, EVT VT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType)
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI bool isSplatValue(SDValue V, const APInt &DemandedElts, APInt &UndefElts, unsigned Depth=0) const
Test whether V has a splatted value for all the demanded elements.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
const SelectionDAGTargetInfo & getSelectionDAGInfo() const
LLVM_ABI SDValue getStoreVP(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, SDValue Offset, SDValue Mask, SDValue EVL, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags=SDNodeFlags())
Returns sum of the base pointer and offset.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue getSplatVector(EVT VT, const SDLoc &DL, SDValue Op)
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI bool SignBitIsZero(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero.
SDValue getInsertVectorElt(const SDLoc &DL, SDValue Vec, SDValue Elt, unsigned Idx)
Insert Elt into Vec at offset Idx.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDValue > Ops, SDNodeFlags Flags=SDNodeFlags())
LLVM_ABI SDValue getMaskedStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Base, SDValue Offset, SDValue Mask, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
LLVM_ABI std::pair< SDValue, SDValue > getStrictFPExtendOrRound(SDValue Op, SDValue Chain, const SDLoc &DL, EVT VT)
Convert Op, which must be a STRICT operation of float type, to the float type VT, by either extending...
LLVM_ABI std::pair< SDValue, SDValue > SplitEVL(SDValue N, EVT VecVT, const SDLoc &DL)
Split the explicit vector length parameter of a VP operation.
LLVM_ABI SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either any-extending or truncat...
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getScatterVP(SDVTList VTs, EVT VT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
LLVM_ABI SDValue getFPExtendOrRound(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of float type, to the float type VT, by either extending or rounding (by tr...
LLVM_ABI bool isKnownNeverNaN(SDValue Op, const APInt &DemandedElts, bool SNaN=false, unsigned Depth=0) const
Test whether the given SDValue (or all elements of it, if it is a vector) is known to never be NaN in...
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI SDValue getBoolConstant(bool V, const SDLoc &DL, EVT VT, EVT OpVT)
Create a true or false constant of type VT using the target's BooleanContent for type OpVT.
SDValue getTargetBlockAddress(const BlockAddress *BA, EVT VT, int64_t Offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
void addCallSiteInfo(const SDNode *Node, CallSiteInfo &&CallInfo)
Set CallSiteInfo to be associated with Node.
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Base, SDValue Offset, SDValue Mask, SDValue Src0, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, ISD::LoadExtType, bool IsExpanding=false)
SDValue getSplat(EVT VT, const SDLoc &DL, SDValue Op)
Returns a node representing a splat of one value into all lanes of the provided vector type.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
LLVM_ABI SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a logical NOT operation as (XOR Val, BooleanOne).
LLVM_ABI SDValue getMaskedScatter(SDVTList VTs, EVT MemVT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType, bool IsTruncating=false)
static LLVM_ABI bool isSelectMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from its source vectors without lane crossings.
static LLVM_ABI bool isBitRotateMask(ArrayRef< int > Mask, unsigned EltSizeInBits, unsigned MinSubElts, unsigned MaxSubElts, unsigned &NumSubElts, unsigned &RotateAmt)
Checks if the shuffle is a bit rotation of the first operand across multiple subelements,...
static LLVM_ABI bool isSingleSourceMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector.
static LLVM_ABI bool isDeInterleaveMaskOfFactor(ArrayRef< int > Mask, unsigned Factor, unsigned &Index)
Check if the mask is a DE-interleave mask of the given factor Factor like: <Index,...
static LLVM_ABI bool isIdentityMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector without lane crossin...
static LLVM_ABI bool isReverseMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask swaps the order of elements from exactly one source vector.
static LLVM_ABI bool isInsertSubvectorMask(ArrayRef< int > Mask, int NumSrcElts, int &NumSubElts, int &Index)
Return true if this shuffle mask is an insert subvector mask.
static LLVM_ABI bool isInterleaveMask(ArrayRef< int > Mask, unsigned Factor, unsigned NumInputElts, SmallVectorImpl< unsigned > &StartIndexes)
Return true if the mask interleaves one or more input vectors together.
This SDNode is used to implement the code generator support for the llvm IR shufflevector instruction...
int getSplatIndex() const
ArrayRef< int > getMask() const
static LLVM_ABI bool isSplatMask(ArrayRef< int > Mask)
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
pointer data()
Return a pointer to the vector's buffer, even if empty().
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
StringRef - Represent a constant reference to a string, i.e.
constexpr size_t size() const
size - Get the string size.
LLVM_ABI std::string lower() const
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, T Value)
Information about stack frame layout on the target.
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
TargetInstrInfo - Interface to description of machine instruction set.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
bool PredictableSelectIsExpensive
Tells the code generator that select is more expensive than a branch if the branch is usually predict...
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
unsigned MaxStoresPerMemcpyOptSize
Likewise for functions with the OptSize attribute.
MachineBasicBlock * emitPatchPoint(MachineInstr &MI, MachineBasicBlock *MBB) const
Replace/modify any TargetFrameIndex operands with a targte-dependent sequence of memory operands that...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
virtual unsigned getMinimumJumpTableEntries() const
Return lower limit for number of blocks in a jump table.
const TargetMachine & getTargetMachine() const
unsigned MaxLoadsPerMemcmp
Specify maximum number of load instructions per memcmp call.
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
unsigned MaxGluedStoresPerMemcpy
Specify max number of store instructions to glue in inlined memcpy.
virtual bool isZExtFree(Type *FromTy, Type *ToTy) const
Return true if any actual instruction that defines a value of type FromTy implicitly zero-extends the...
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
void setOperationPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
Convenience method to set an operation to Promote and specify the type in a single call.
unsigned getMinCmpXchgSizeInBits() const
Returns the size of the smallest cmpxchg or ll/sc instruction the backend supports.
virtual unsigned getNumRegisters(LLVMContext &Context, EVT VT, std::optional< MVT > RegisterVT=std::nullopt) const
Return the number of registers that this ValueType will eventually require.
void setIndexedLoadAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed load does or does not work with the specified type and indicate w...
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
virtual unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
bool isOperationCustom(unsigned Op, EVT VT) const
Return true if the operation uses custom lowering, regardless of whether the type is legal or not.
unsigned MaxStoresPerMemsetOptSize
Likewise for functions with the OptSize attribute.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
unsigned MaxStoresPerMemmove
Specify maximum number of store instructions per memmove call.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
virtual bool isTruncateFree(Type *FromTy, Type *ToTy) const
Return true if it's free to truncate a value of type FromTy to type ToTy.
unsigned MaxStoresPerMemmoveOptSize
Likewise for functions with the OptSize attribute.
virtual bool shouldFoldSelectWithSingleBitTest(EVT VT, const APInt &AndMask) const
virtual Value * getIRStackGuard(IRBuilderBase &IRB) const
If the target has a standard location for the stack protector guard, returns the address of that loca...
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
bool EnableExtLdPromotion
void setIndexedStoreAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed store does or does not work with the specified type and indicate ...
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
bool isOperationLegal(unsigned Op, EVT VT) const
Return true if the specified operation is legal on this target.
unsigned MaxStoresPerMemset
Specify maximum number of store instructions per memset call.
void setPartialReduceMLAAction(unsigned Opc, MVT AccVT, MVT InputVT, LegalizeAction Action)
Indicate how a PARTIAL_REDUCE_U/SMLA node with Acc type AccVT and Input type InputVT should be treate...
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
unsigned MaxLoadsPerMemcmpOptSize
Likewise for functions with the OptSize attribute.
virtual bool isBinOp(unsigned Opcode) const
Return true if the node is a math/logic binary operator.
void setMinCmpXchgSizeInBits(unsigned SizeInBits)
Sets the minimum cmpxchg or ll/sc size supported by the backend.
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
void setCondCodeAction(ArrayRef< ISD::CondCode > CCs, MVT VT, LegalizeAction Action)
Indicate that the specified condition code is or isn't supported on the target and indicate what to d...
virtual std::pair< const TargetRegisterClass *, uint8_t > findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const
Return the largest legal super-reg register class of the register class for the specified type and it...
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
std::vector< ArgListEntry > ArgListTy
bool allowsMemoryAccessForAlignment(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
This function returns true if the memory access is aligned or if the target allows this specific unal...
unsigned MaxStoresPerMemcpy
Specify maximum number of store instructions per memcpy call.
bool isOperationLegalOrCustomOrPromote(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual MVT getVPExplicitVectorLengthTy() const
Returns the type to be used for the EVL/AVL operand of VP nodes: ISD::VP_ADD, ISD::VP_SUB,...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
SDValue expandAddSubSat(SDNode *Node, SelectionDAG &DAG) const
Method for building the DAG expansion of ISD::[US][ADD|SUB]SAT.
SDValue buildSDIVPow2WithCMov(SDNode *N, const APInt &Divisor, SelectionDAG &DAG, SmallVectorImpl< SDNode * > &Created) const
Build sdiv by power-of-2 with conditional move instructions Ref: "Hacker's Delight" by Henry Warren 1...
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
virtual SDValue expandIndirectJTBranch(const SDLoc &dl, SDValue Value, SDValue Addr, int JTI, SelectionDAG &DAG) const
Expands target specific indirect branch for the case of JumpTable expansion.
virtual InlineAsm::ConstraintCode getInlineAsmMemConstraint(StringRef ConstraintCode) const
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
virtual SDValue LowerToTLSEmulatedModel(const GlobalAddressSDNode *GA, SelectionDAG &DAG) const
Lower TLS global address SDNode for target independent emulated TLS model.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
bool isPositionIndependent() const
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
virtual bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0) const
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
TargetLowering(const TargetLowering &)=delete
virtual unsigned combineRepeatedFPDivisors() const
Indicate whether this target prefers to combine FDIVs with the same divisor.
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
virtual unsigned getJumpTableEncoding() const
Return the entry encoding for a jump table in the current function.
virtual bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool PoisonOnly, bool ConsiderFlags, unsigned Depth) const
Return true if Op can create undef or poison from non-undef & non-poison operands.
Primary interface to the complete machine description for the target machine.
TLSModel::Model getTLSModel(const GlobalValue *GV) const
Returns the TLS model which should be used for the given global variable.
const Triple & getTargetTriple() const
bool useTLSDESC() const
Returns true if this target uses TLS Descriptors.
const MCSubtargetInfo * getMCSubtargetInfo() const
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
virtual TargetLoweringObjectFile * getObjFileLowering() const
unsigned EmitCallGraphSection
Emit section containing call graph metadata.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual bool isRegisterReservedByUser(Register R) const
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
Target - Wrapper for Target specific information.
bool isOSBinFormatCOFF() const
Tests whether the OS uses the COFF binary format.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
LLVM_ABI Type * getStructElementType(unsigned N) const
LLVM_ABI bool isScalableTy(SmallPtrSetImpl< const Type * > &Visited) const
Return true if this is a type whose size is a known multiple of vscale.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
bool isStructTy() const
True if this is an instance of StructType.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isTargetExtTy() const
Return true if this is a target extension type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
A Use represents the edge between a Value definition and its users.
User * getUser() const
Returns the User that contains this Use.
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
std::pair< iterator, bool > insert(const ValueT &V)
constexpr bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
constexpr ScalarTy getFixedValue() const
static constexpr bool isKnownLE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
constexpr LeafTy multiplyCoefficientBy(ScalarTy RHS) const
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
constexpr bool isZero() const
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ RISCV_VectorCall
Calling convention used for RISC-V V-extension.
@ PreserveMost
Used for runtime calls that preserves most registers.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ SPIR_KERNEL
Used for SPIR kernel functions.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
@ GRAAL
Used by GraalVM. Two additional registers are reserved.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI bool isConstantSplatVectorAllOnes(const SDNode *N, bool BuildVectorOnly=false)
Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where all of the elements are ~0 ...
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ ADD
Simple integer binary arithmetic operators.
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ FADD
Simple binary floating point operators.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ STRICT_FSQRT
Constrained versions of libm-equivalent floating point intrinsics.
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ SIGN_EXTEND
Conversion operators.
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ CTTZ_ZERO_UNDEF
Bit counting operators with an undefined result for zero inputs.
@ VECTOR_INTERLEAVE
VECTOR_INTERLEAVE(VEC1, VEC2, ...) - Returns N vectors from N input vectors, where N is the factor to...
@ STEP_VECTOR
STEP_VECTOR(IMM) - Returns a scalable vector whose lanes are comprised of a linear sequence of unsign...
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ UNDEF
UNDEF - An undefined node.
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
@ GET_ROUNDING
Returns current rounding mode: -1 Undefined 0 Round to 0 1 Round to nearest, ties to even 2 Round to ...
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ SSHLSAT
RESULT = [US]SHLSAT(LHS, RHS) - Perform saturation left shift.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ VECTOR_REVERSE
VECTOR_REVERSE(VECTOR) - Returns a vector, of the same type as VECTOR, whose elements are shuffled us...
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ STRICT_SINT_TO_FP
STRICT_[US]INT_TO_FP - Convert a signed or unsigned integer to a floating point value.
@ EH_DWARF_CFA
EH_DWARF_CFA - This node represents the pointer to the DWARF Canonical Frame Address (CFA),...
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
@ STRICT_FADD
Constrained versions of the binary floating point operators.
@ SPLAT_VECTOR_PARTS
SPLAT_VECTOR_PARTS(SCALAR1, SCALAR2, ...) - Returns a vector with the scalar values joined together a...
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ VECTOR_SPLICE
VECTOR_SPLICE(VEC1, VEC2, IMM) - Returns a subvector of the same type as VEC1/VEC2 from CONCAT_VECTOR...
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ VECTOR_COMPRESS
VECTOR_COMPRESS(Vec, Mask, Passthru) consecutively place vector elements based on mask e....
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ VECTOR_DEINTERLEAVE
VECTOR_DEINTERLEAVE(VEC1, VEC2, ...) - Returns N vectors from N input vectors, where N is the factor ...
@ TRUNCATE_SSAT_S
TRUNCATE_[SU]SAT_[SU] - Truncate for saturated operand [SU] located in middle, prefix for SAT means i...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
LLVM_ABI bool isBuildVectorOfConstantSDNodes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR node of all ConstantSDNode or undef.
bool isNormalStore(const SDNode *N)
Returns true if the specified node is a non-truncating and unindexed store.
bool isExtOpcode(unsigned Opcode)
LLVM_ABI bool isConstantSplatVectorAllZeros(const SDNode *N, bool BuildVectorOnly=false)
Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where all of the elements are 0 o...
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
LLVM_ABI std::optional< unsigned > getVPMaskIdx(unsigned Opcode)
The operand position of the vector mask.
LLVM_ABI std::optional< unsigned > getVPExplicitVectorLengthIdx(unsigned Opcode)
The operand position of the explicit vector length parameter.
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
MemIndexType
MemIndexType enum - This enum defines how to interpret MGATHER/SCATTER's index parameter when calcula...
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
LLVM_ABI bool isBuildVectorOfConstantFPSDNodes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR node of all ConstantFPSDNode or undef.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LLVM_ABI bool isBuildVectorAllOnes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are ~0 or undef.
LLVM_ABI NodeType getVecReduceBaseOpcode(unsigned VecReduceOpcode)
Get underlying scalar opcode for VECREDUCE opcode.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
LLVM_ABI bool isVPOpcode(unsigned Opcode)
Whether this is a vector-predicated Opcode.
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
bool isIntEqualitySetCC(CondCode Code)
Return true if this is a setcc instruction that performs an equality comparison when used with intege...
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
@ Bitcast
Perform the operation on a different, but equivalently sized type.
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
CastInst_match< OpTy, TruncInst > m_Trunc(const OpTy &Op)
Matches Trunc.
BinaryOp_match< LHS, RHS, Instruction::Xor > m_Xor(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::FMul > m_FMul(const LHS &L, const RHS &R)
TwoOps_match< Val_t, Idx_t, Instruction::ExtractElement > m_ExtractElt(const Val_t &Val, const Idx_t &Idx)
Matches ExtractElementInst.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
deferredval_ty< Value > m_Deferred(Value *const &V)
Like m_Specific(), but works if the specific value to match is determined as part of the same match()...
match_combine_or< BinaryOp_match< LHS, RHS, Instruction::Add >, DisjointOr_match< LHS, RHS > > m_AddLike(const LHS &L, const RHS &R)
Match either "add" or "or disjoint".
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
FNeg_match< OpTy > m_FNeg(const OpTy &X)
Match 'fneg X' as 'fsub -0.0, X'.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::Or > m_Or(const LHS &L, const RHS &R)
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
ThreeOps_match< Val_t, Elt_t, Idx_t, Instruction::InsertElement > m_InsertElt(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx)
Matches InsertElementInst.
unsigned getBrCond(CondCode CC, unsigned SelectOpc=0)
static RISCVVType::VLMUL getLMul(uint64_t TSFlags)
static int getFRMOpNum(const MCInstrDesc &Desc)
static unsigned getSEWOpNum(const MCInstrDesc &Desc)
int getLoadFPImm(APFloat FPImm)
getLoadFPImm - Return a 5-bit binary encoding of the floating-point immediate value.
InstSeq generateInstSeq(int64_t Val, const MCSubtargetInfo &STI)
int getIntMatCost(const APInt &Val, unsigned Size, const MCSubtargetInfo &STI, bool CompressionCost, bool FreeZeroes)
InstSeq generateTwoRegInstSeq(int64_t Val, const MCSubtargetInfo &STI, unsigned &ShiftAmt, unsigned &AddOpc)
SmallVector< Inst, 8 > InstSeq
static VLMUL encodeLMUL(unsigned LMUL, bool Fractional)
static unsigned decodeVSEW(unsigned VSEW)
@ TAIL_UNDISTURBED_MASK_UNDISTURBED
LLVM_ABI std::pair< unsigned, bool > decodeVLMUL(VLMUL VLMul)
static unsigned encodeSEW(unsigned SEW)
static constexpr unsigned FPMASK_Negative_Zero
static constexpr unsigned FPMASK_Positive_Subnormal
static constexpr unsigned FPMASK_Positive_Normal
static constexpr unsigned FPMASK_Negative_Subnormal
static constexpr unsigned FPMASK_Negative_Normal
static constexpr unsigned FPMASK_Positive_Infinity
static constexpr unsigned FPMASK_Negative_Infinity
static constexpr unsigned FPMASK_Quiet_NaN
ArrayRef< MCPhysReg > getArgGPRs(const RISCVABI::ABI ABI)
static constexpr unsigned FPMASK_Signaling_NaN
static constexpr unsigned FPMASK_Positive_Zero
static constexpr unsigned RVVBitsPerBlock
static constexpr unsigned RVVBytesPerBlock
LLVM_ABI Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
@ Kill
The last use of a register.
BinaryOpc_match< LHS, RHS > m_Srl(const LHS &L, const RHS &R)
auto m_SpecificVT(EVT RefVT, const Pattern &P)
Match a specific ValueType.
Or< Preds... > m_AnyOf(const Preds &...preds)
auto m_Node(unsigned Opcode, const OpndPreds &...preds)
bool sd_match(SDNode *N, const SelectionDAG *DAG, Pattern &&P)
ConstantInt_match m_ConstInt()
Match any integer constants or splat of an integer constant.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
@ System
Synchronized with respect to all concurrently executing threads.
initializer< Ty > init(const Ty &Val)
uint32_t read32le(const void *P)
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
FunctionAddr VTableAddr Value
bool CC_RISCV_FastCC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
bool CC_RISCV_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static const MachineMemOperand::Flags MONontemporalBit1
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
MCCodeEmitter * createRISCVMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
static const MachineMemOperand::Flags MONontemporalBit0
bool RISCVCCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
RISCVCCAssignFn - This target-specific function extends the default CCValAssign with additional infor...
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI bool widenShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Try to transform a shuffle mask by replacing elements with the scaled index for an equivalent mask of...
LLVM_ABI Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
LLVM_ABI bool isNullOrNullSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndefs=false)
Return true if the value is a constant 0 integer or a splatted vector of a constant 0 integer (with n...
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
bool isReleaseOrStronger(AtomicOrdering AO)
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere.
constexpr bool has_single_bit(T Value) noexcept
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
FunctionAddr VTableAddr Count
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
bool CC_RISCV(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
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)