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() &&
438 !Subtarget.hasVendorXqcicm() && !Subtarget.hasVendorXqcics())
441 if (Subtarget.hasVendorXqcia() && !Subtarget.is64Bit()) {
450 static const unsigned FPLegalNodeTypes[] = {
451 ISD::FMINNUM, ISD::FMAXNUM, ISD::FMINIMUMNUM,
452 ISD::FMAXIMUMNUM, ISD::LRINT, ISD::LLRINT,
464 static const unsigned FPOpToExpand[] = {
465 ISD::FSIN, ISD::FCOS, ISD::FSINCOS, ISD::FPOW,
468 static const unsigned FPRndMode[] = {
469 ISD::FCEIL, ISD::FFLOOR, ISD::FTRUNC, ISD::FRINT, ISD::FROUND,
472 static const unsigned ZfhminZfbfminPromoteOps[] = {
473 ISD::FMINNUM, ISD::FMAXNUM, ISD::FMAXIMUMNUM,
480 ISD::FTRUNC, ISD::FRINT, ISD::FROUND,
483 if (Subtarget.hasStdExtZfbfmin()) {
498 if (Subtarget.hasStdExtZfhminOrZhinxmin()) {
499 if (Subtarget.hasStdExtZfhOrZhinx()) {
506 if (Subtarget.hasStdExtZfa())
511 for (
auto Op : {ISD::LROUND, ISD::LLROUND, ISD::LRINT, ISD::LLRINT,
532 ISD::FNEARBYINT, MVT::f16,
533 Subtarget.hasStdExtZfh() && Subtarget.hasStdExtZfa() ?
Legal :
Promote);
535 ISD::FCOS, ISD::FSIN, ISD::FSINCOS, ISD::FEXP,
536 ISD::FEXP2, ISD::FEXP10, ISD::FLOG, ISD::FLOG2,
537 ISD::FLOG10, ISD::FLDEXP, ISD::FFREXP},
549 if (Subtarget.is64Bit())
553 if (Subtarget.hasStdExtFOrZfinx()) {
575 if (Subtarget.hasStdExtZfa()) {
584 if (Subtarget.hasStdExtFOrZfinx() && Subtarget.is64Bit())
587 if (Subtarget.hasStdExtDOrZdinx()) {
590 if (!Subtarget.is64Bit())
593 if (Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
594 !Subtarget.is64Bit()) {
599 if (Subtarget.hasStdExtZfa()) {
605 if (Subtarget.is64Bit())
634 if (Subtarget.is64Bit()) {
641 if (Subtarget.hasStdExtFOrZfinx()) {
667 if (Subtarget.is64Bit())
677 if (Subtarget.is64Bit()) {
684 if (Subtarget.is64Bit())
687 if (Subtarget.hasVendorXMIPSCBOP())
689 else if (Subtarget.hasStdExtZicbop())
692 if (Subtarget.hasStdExtA()) {
694 if (Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas())
698 }
else if (Subtarget.hasForcedAtomics()) {
713 if (Subtarget.hasVInstructions()) {
722 {MVT::i8, MVT::i16},
Custom);
723 if (Subtarget.is64Bit())
733 static const unsigned IntegerVPOps[] = {
734 ISD::VP_ADD, ISD::VP_SUB, ISD::VP_MUL,
735 ISD::VP_SDIV, ISD::VP_UDIV, ISD::VP_SREM,
736 ISD::VP_UREM, ISD::VP_AND, ISD::VP_OR,
737 ISD::VP_XOR, ISD::VP_SRA, ISD::VP_SRL,
738 ISD::VP_SHL, ISD::VP_REDUCE_ADD, ISD::VP_REDUCE_AND,
739 ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR, ISD::VP_REDUCE_SMAX,
740 ISD::VP_REDUCE_SMIN, ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN,
741 ISD::VP_MERGE, ISD::VP_SELECT, ISD::VP_FP_TO_SINT,
742 ISD::VP_FP_TO_UINT, ISD::VP_SETCC, ISD::VP_SIGN_EXTEND,
743 ISD::VP_ZERO_EXTEND, ISD::VP_TRUNCATE, ISD::VP_SMIN,
744 ISD::VP_SMAX, ISD::VP_UMIN, ISD::VP_UMAX,
745 ISD::VP_ABS, ISD::EXPERIMENTAL_VP_REVERSE, ISD::EXPERIMENTAL_VP_SPLICE,
746 ISD::VP_SADDSAT, ISD::VP_UADDSAT, ISD::VP_SSUBSAT,
747 ISD::VP_USUBSAT, ISD::VP_CTTZ_ELTS, ISD::VP_CTTZ_ELTS_ZERO_UNDEF,
748 ISD::EXPERIMENTAL_VP_SPLAT};
750 static const unsigned FloatingPointVPOps[] = {
751 ISD::VP_FADD, ISD::VP_FSUB, ISD::VP_FMUL,
752 ISD::VP_FDIV, ISD::VP_FNEG, ISD::VP_FABS,
753 ISD::VP_FMA, ISD::VP_REDUCE_FADD, ISD::VP_REDUCE_SEQ_FADD,
754 ISD::VP_REDUCE_FMIN, ISD::VP_REDUCE_FMAX, ISD::VP_MERGE,
755 ISD::VP_SELECT, ISD::VP_SINT_TO_FP, ISD::VP_UINT_TO_FP,
756 ISD::VP_SETCC, ISD::VP_FP_ROUND, ISD::VP_FP_EXTEND,
757 ISD::VP_SQRT, ISD::VP_FMINNUM, ISD::VP_FMAXNUM,
758 ISD::VP_FCEIL, ISD::VP_FFLOOR, ISD::VP_FROUND,
759 ISD::VP_FROUNDEVEN, ISD::VP_FCOPYSIGN, ISD::VP_FROUNDTOZERO,
760 ISD::VP_FRINT, ISD::VP_FNEARBYINT, ISD::VP_IS_FPCLASS,
761 ISD::VP_FMINIMUM, ISD::VP_FMAXIMUM, ISD::VP_LRINT,
762 ISD::VP_LLRINT, ISD::VP_REDUCE_FMINIMUM,
763 ISD::VP_REDUCE_FMAXIMUM, ISD::EXPERIMENTAL_VP_SPLAT};
765 static const unsigned IntegerVecReduceOps[] = {
766 ISD::VECREDUCE_ADD, ISD::VECREDUCE_AND, ISD::VECREDUCE_OR,
767 ISD::VECREDUCE_XOR, ISD::VECREDUCE_SMAX, ISD::VECREDUCE_SMIN,
768 ISD::VECREDUCE_UMAX, ISD::VECREDUCE_UMIN};
770 static const unsigned FloatingPointVecReduceOps[] = {
771 ISD::VECREDUCE_FADD, ISD::VECREDUCE_SEQ_FADD, ISD::VECREDUCE_FMIN,
772 ISD::VECREDUCE_FMAX, ISD::VECREDUCE_FMINIMUM, ISD::VECREDUCE_FMAXIMUM};
774 static const unsigned FloatingPointLibCallOps[] = {
775 ISD::FREM, ISD::FPOW, ISD::FCOS, ISD::FSIN, ISD::FSINCOS, ISD::FEXP,
776 ISD::FEXP2, ISD::FEXP10, ISD::FLOG, ISD::FLOG2, ISD::FLOG10};
778 if (!Subtarget.is64Bit()) {
787 ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR,
788 ISD::VP_REDUCE_SMAX, ISD::VP_REDUCE_SMIN,
789 ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN},
793 for (
MVT VT : BoolVecVTs) {
819 {ISD::VECREDUCE_AND, ISD::VECREDUCE_OR, ISD::VECREDUCE_XOR}, VT,
823 {ISD::VP_REDUCE_AND, ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR}, VT,
847 ISD::VP_TRUNCATE, ISD::VP_SETCC},
864 for (
MVT VT : IntVecVTs) {
875 if (VT.getVectorElementType() == MVT::i64 && !Subtarget.hasStdExtV())
925 {ISD::VP_LOAD, ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
926 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER, ISD::VP_SCATTER},
951 if (Subtarget.hasStdExtZvkb()) {
959 if (Subtarget.hasStdExtZvbb()) {
963 ISD::VP_CTTZ_ZERO_UNDEF, ISD::VP_CTPOP},
969 ISD::VP_CTTZ_ZERO_UNDEF, ISD::VP_CTPOP},
978 ISD::VP_CTLZ_ZERO_UNDEF, ISD::VP_CTTZ_ZERO_UNDEF},
986 for (
MVT VT : VecTupleVTs) {
1007 static const unsigned ZvfhminZvfbfminPromoteOps[] = {
1035 ISD::VECREDUCE_FMIN,
1036 ISD::VECREDUCE_FMAX,
1037 ISD::VECREDUCE_FMINIMUM,
1038 ISD::VECREDUCE_FMAXIMUM};
1041 static const unsigned ZvfhminZvfbfminPromoteVPOps[] = {
1047 ISD::VP_REDUCE_FMIN,
1048 ISD::VP_REDUCE_FMAX,
1056 ISD::VP_FROUNDTOZERO,
1062 ISD::VP_REDUCE_FMINIMUM,
1063 ISD::VP_REDUCE_FMAXIMUM};
1066 const auto SetCommonVFPActions = [&](
MVT VT) {
1082 {ISD::FMINNUM, ISD::FMAXNUM, ISD::FMAXIMUMNUM, ISD::FMINIMUMNUM}, VT,
1087 ISD::FROUNDEVEN, ISD::FRINT, ISD::FNEARBYINT,
1104 {ISD::VP_LOAD, ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1105 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER, ISD::VP_SCATTER},
1141 const auto SetCommonVFPExtLoadTruncStoreActions =
1143 for (
auto SmallVT : SmallerVTs) {
1151 const auto SetCommonPromoteToF32Actions = [&](
MVT VT) {
1179 ISD::MGATHER, ISD::MSCATTER, ISD::VP_LOAD,
1180 ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1181 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1204 if (Subtarget.hasVInstructionsF16()) {
1205 for (
MVT VT : F16VecVTs) {
1208 SetCommonVFPActions(VT);
1210 }
else if (Subtarget.hasVInstructionsF16Minimal()) {
1211 for (
MVT VT : F16VecVTs) {
1214 SetCommonPromoteToF32Actions(VT);
1218 if (Subtarget.hasVInstructionsBF16Minimal()) {
1219 for (
MVT VT : BF16VecVTs) {
1222 SetCommonPromoteToF32Actions(VT);
1226 if (Subtarget.hasVInstructionsF32()) {
1227 for (
MVT VT : F32VecVTs) {
1230 SetCommonVFPActions(VT);
1231 SetCommonVFPExtLoadTruncStoreActions(VT, F16VecVTs);
1232 SetCommonVFPExtLoadTruncStoreActions(VT, BF16VecVTs);
1236 if (Subtarget.hasVInstructionsF64()) {
1237 for (
MVT VT : F64VecVTs) {
1240 SetCommonVFPActions(VT);
1241 SetCommonVFPExtLoadTruncStoreActions(VT, F16VecVTs);
1242 SetCommonVFPExtLoadTruncStoreActions(VT, BF16VecVTs);
1243 SetCommonVFPExtLoadTruncStoreActions(VT, F32VecVTs);
1247 if (Subtarget.useRVVForFixedLengthVectors()) {
1249 if (!useRVVForFixedLengthVectorVT(VT))
1294 {ISD::VECREDUCE_AND, ISD::VECREDUCE_OR, ISD::VECREDUCE_XOR}, VT,
1298 {ISD::VP_REDUCE_AND, ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR}, VT,
1325 ISD::VP_SETCC, ISD::VP_TRUNCATE},
1349 {ISD::MLOAD, ISD::MSTORE, ISD::MGATHER, ISD::MSCATTER}, VT,
Custom);
1352 ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1353 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1385 ISD::VECREDUCE_SMIN, ISD::VECREDUCE_UMAX,
1386 ISD::VECREDUCE_UMIN},
1391 if (Subtarget.hasStdExtZvkb())
1394 if (Subtarget.hasStdExtZvbb()) {
1418 if (!useRVVForFixedLengthVectorVT(VT))
1441 ISD::MGATHER, ISD::MSCATTER},
1444 ISD::VP_SCATTER, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1445 ISD::EXPERIMENTAL_VP_STRIDED_STORE},
1454 !Subtarget.hasVInstructionsF16()) {
1464 if (Subtarget.hasStdExtZfhmin()) {
1490 if (Subtarget.hasStdExtZfbfmin()) {
1516 ISD::FMA, ISD::FMINNUM, ISD::FMAXNUM,
1518 ISD::FMAXIMUM, ISD::FMINIMUM},
1522 ISD::FROUNDEVEN, ISD::FRINT, ISD::LRINT,
1523 ISD::LLRINT, ISD::LROUND, ISD::LLROUND,
1549 if (Subtarget.is64Bit())
1551 if (Subtarget.hasStdExtZfhminOrZhinxmin())
1553 if (Subtarget.hasStdExtZfbfmin())
1555 if (Subtarget.hasStdExtFOrZfinx())
1557 if (Subtarget.hasStdExtDOrZdinx())
1562 if (Subtarget.hasStdExtA())
1565 if (Subtarget.hasForcedAtomics()) {
1568 {ISD::ATOMIC_CMP_SWAP, ISD::ATOMIC_SWAP, ISD::ATOMIC_LOAD_ADD,
1569 ISD::ATOMIC_LOAD_SUB, ISD::ATOMIC_LOAD_AND, ISD::ATOMIC_LOAD_OR,
1570 ISD::ATOMIC_LOAD_XOR, ISD::ATOMIC_LOAD_NAND, ISD::ATOMIC_LOAD_MIN,
1571 ISD::ATOMIC_LOAD_MAX, ISD::ATOMIC_LOAD_UMIN, ISD::ATOMIC_LOAD_UMAX},
1575 if (Subtarget.hasVendorXTHeadMemIdx()) {
1584 if (Subtarget.is64Bit()) {
1591 if (Subtarget.hasVendorXCVmem() && !Subtarget.is64Bit()) {
1602 if (Subtarget.hasStdExtZvqdotq() && Subtarget.getELen() >= 64) {
1603 static const unsigned MLAOps[] = {ISD::PARTIAL_REDUCE_SMLA,
1604 ISD::PARTIAL_REDUCE_UMLA,
1605 ISD::PARTIAL_REDUCE_SUMLA};
1612 if (Subtarget.useRVVForFixedLengthVectors()) {
1614 if (VT.getVectorElementType() != MVT::i32 ||
1615 !useRVVForFixedLengthVectorVT(VT))
1625 if (Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh()) {
1631 const Align FunctionAlignment(Subtarget.hasStdExtZca() ? 2 : 4);
1643 if (Subtarget.hasStdExtFOrZfinx())
1646 if (Subtarget.hasStdExtZbb())
1649 if ((Subtarget.hasStdExtZbs() && Subtarget.is64Bit()) ||
1650 Subtarget.hasVInstructions())
1653 if (Subtarget.hasStdExtZbkb())
1656 if (Subtarget.hasStdExtFOrZfinx())
1659 if (Subtarget.hasVInstructions())
1662 ISD::VP_GATHER, ISD::VP_SCATTER,
ISD::SRA,
1665 ISD::VP_STORE, ISD::VP_TRUNCATE, ISD::EXPERIMENTAL_VP_REVERSE,
1671 if (Subtarget.hasVendorXTHeadMemPair())
1673 if (Subtarget.useRVVForFixedLengthVectors())
1693 Subtarget.getMaxStoresPerMemmove(
true);
1705 if (Subtarget.hasVInstructions() &&
1716bool RISCVTargetLowering::shouldExpandGetVectorLength(
EVT TripCountVT,
1718 bool IsScalable)
const {
1725 if (TripCountVT != MVT::i32 && TripCountVT != Subtarget.
getXLenVT())
1743 return !Subtarget.hasVInstructions() ||
1751 auto &
DL =
I.getDataLayout();
1753 auto SetRVVLoadStoreInfo = [&](
unsigned PtrOp,
bool IsStore,
1754 bool IsUnitStrided,
bool UsePtrVal =
false) {
1759 Info.ptrVal =
I.getArgOperand(PtrOp);
1761 Info.fallbackAddressSpace =
1762 I.getArgOperand(PtrOp)->getType()->getPointerAddressSpace();
1766 MemTy =
I.getArgOperand(0)->getType();
1769 MemTy =
I.getType();
1784 Info.align =
DL.getABITypeAlign(MemTy);
1794 if (
I.hasMetadata(LLVMContext::MD_nontemporal))
1801 case Intrinsic::riscv_masked_atomicrmw_xchg:
1802 case Intrinsic::riscv_masked_atomicrmw_add:
1803 case Intrinsic::riscv_masked_atomicrmw_sub:
1804 case Intrinsic::riscv_masked_atomicrmw_nand:
1805 case Intrinsic::riscv_masked_atomicrmw_max:
1806 case Intrinsic::riscv_masked_atomicrmw_min:
1807 case Intrinsic::riscv_masked_atomicrmw_umax:
1808 case Intrinsic::riscv_masked_atomicrmw_umin:
1809 case Intrinsic::riscv_masked_cmpxchg:
1816 Info.memVT = MVT::i32;
1817 Info.ptrVal =
I.getArgOperand(0);
1819 Info.align =
Align(4);
1823 case Intrinsic::riscv_seg2_load_mask:
1824 case Intrinsic::riscv_seg3_load_mask:
1825 case Intrinsic::riscv_seg4_load_mask:
1826 case Intrinsic::riscv_seg5_load_mask:
1827 case Intrinsic::riscv_seg6_load_mask:
1828 case Intrinsic::riscv_seg7_load_mask:
1829 case Intrinsic::riscv_seg8_load_mask:
1830 case Intrinsic::riscv_sseg2_load_mask:
1831 case Intrinsic::riscv_sseg3_load_mask:
1832 case Intrinsic::riscv_sseg4_load_mask:
1833 case Intrinsic::riscv_sseg5_load_mask:
1834 case Intrinsic::riscv_sseg6_load_mask:
1835 case Intrinsic::riscv_sseg7_load_mask:
1836 case Intrinsic::riscv_sseg8_load_mask:
1837 return SetRVVLoadStoreInfo( 0,
false,
1839 case Intrinsic::riscv_seg2_store_mask:
1840 case Intrinsic::riscv_seg3_store_mask:
1841 case Intrinsic::riscv_seg4_store_mask:
1842 case Intrinsic::riscv_seg5_store_mask:
1843 case Intrinsic::riscv_seg6_store_mask:
1844 case Intrinsic::riscv_seg7_store_mask:
1845 case Intrinsic::riscv_seg8_store_mask:
1847 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1850 case Intrinsic::riscv_sseg2_store_mask:
1851 case Intrinsic::riscv_sseg3_store_mask:
1852 case Intrinsic::riscv_sseg4_store_mask:
1853 case Intrinsic::riscv_sseg5_store_mask:
1854 case Intrinsic::riscv_sseg6_store_mask:
1855 case Intrinsic::riscv_sseg7_store_mask:
1856 case Intrinsic::riscv_sseg8_store_mask:
1858 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
1861 case Intrinsic::riscv_vlm:
1862 return SetRVVLoadStoreInfo( 0,
1866 case Intrinsic::riscv_vle:
1867 case Intrinsic::riscv_vle_mask:
1868 case Intrinsic::riscv_vleff:
1869 case Intrinsic::riscv_vleff_mask:
1870 return SetRVVLoadStoreInfo( 1,
1874 case Intrinsic::riscv_vsm:
1875 case Intrinsic::riscv_vse:
1876 case Intrinsic::riscv_vse_mask:
1877 return SetRVVLoadStoreInfo( 1,
1881 case Intrinsic::riscv_vlse:
1882 case Intrinsic::riscv_vlse_mask:
1883 case Intrinsic::riscv_vloxei:
1884 case Intrinsic::riscv_vloxei_mask:
1885 case Intrinsic::riscv_vluxei:
1886 case Intrinsic::riscv_vluxei_mask:
1887 return SetRVVLoadStoreInfo( 1,
1890 case Intrinsic::riscv_vsse:
1891 case Intrinsic::riscv_vsse_mask:
1892 case Intrinsic::riscv_vsoxei:
1893 case Intrinsic::riscv_vsoxei_mask:
1894 case Intrinsic::riscv_vsuxei:
1895 case Intrinsic::riscv_vsuxei_mask:
1896 return SetRVVLoadStoreInfo( 1,
1899 case Intrinsic::riscv_vlseg2:
1900 case Intrinsic::riscv_vlseg3:
1901 case Intrinsic::riscv_vlseg4:
1902 case Intrinsic::riscv_vlseg5:
1903 case Intrinsic::riscv_vlseg6:
1904 case Intrinsic::riscv_vlseg7:
1905 case Intrinsic::riscv_vlseg8:
1906 case Intrinsic::riscv_vlseg2ff:
1907 case Intrinsic::riscv_vlseg3ff:
1908 case Intrinsic::riscv_vlseg4ff:
1909 case Intrinsic::riscv_vlseg5ff:
1910 case Intrinsic::riscv_vlseg6ff:
1911 case Intrinsic::riscv_vlseg7ff:
1912 case Intrinsic::riscv_vlseg8ff:
1913 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1916 case Intrinsic::riscv_vlseg2_mask:
1917 case Intrinsic::riscv_vlseg3_mask:
1918 case Intrinsic::riscv_vlseg4_mask:
1919 case Intrinsic::riscv_vlseg5_mask:
1920 case Intrinsic::riscv_vlseg6_mask:
1921 case Intrinsic::riscv_vlseg7_mask:
1922 case Intrinsic::riscv_vlseg8_mask:
1923 case Intrinsic::riscv_vlseg2ff_mask:
1924 case Intrinsic::riscv_vlseg3ff_mask:
1925 case Intrinsic::riscv_vlseg4ff_mask:
1926 case Intrinsic::riscv_vlseg5ff_mask:
1927 case Intrinsic::riscv_vlseg6ff_mask:
1928 case Intrinsic::riscv_vlseg7ff_mask:
1929 case Intrinsic::riscv_vlseg8ff_mask:
1930 return SetRVVLoadStoreInfo(
I.arg_size() - 5,
1933 case Intrinsic::riscv_vlsseg2:
1934 case Intrinsic::riscv_vlsseg3:
1935 case Intrinsic::riscv_vlsseg4:
1936 case Intrinsic::riscv_vlsseg5:
1937 case Intrinsic::riscv_vlsseg6:
1938 case Intrinsic::riscv_vlsseg7:
1939 case Intrinsic::riscv_vlsseg8:
1940 case Intrinsic::riscv_vloxseg2:
1941 case Intrinsic::riscv_vloxseg3:
1942 case Intrinsic::riscv_vloxseg4:
1943 case Intrinsic::riscv_vloxseg5:
1944 case Intrinsic::riscv_vloxseg6:
1945 case Intrinsic::riscv_vloxseg7:
1946 case Intrinsic::riscv_vloxseg8:
1947 case Intrinsic::riscv_vluxseg2:
1948 case Intrinsic::riscv_vluxseg3:
1949 case Intrinsic::riscv_vluxseg4:
1950 case Intrinsic::riscv_vluxseg5:
1951 case Intrinsic::riscv_vluxseg6:
1952 case Intrinsic::riscv_vluxseg7:
1953 case Intrinsic::riscv_vluxseg8:
1954 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
1957 case Intrinsic::riscv_vlsseg2_mask:
1958 case Intrinsic::riscv_vlsseg3_mask:
1959 case Intrinsic::riscv_vlsseg4_mask:
1960 case Intrinsic::riscv_vlsseg5_mask:
1961 case Intrinsic::riscv_vlsseg6_mask:
1962 case Intrinsic::riscv_vlsseg7_mask:
1963 case Intrinsic::riscv_vlsseg8_mask:
1964 case Intrinsic::riscv_vloxseg2_mask:
1965 case Intrinsic::riscv_vloxseg3_mask:
1966 case Intrinsic::riscv_vloxseg4_mask:
1967 case Intrinsic::riscv_vloxseg5_mask:
1968 case Intrinsic::riscv_vloxseg6_mask:
1969 case Intrinsic::riscv_vloxseg7_mask:
1970 case Intrinsic::riscv_vloxseg8_mask:
1971 case Intrinsic::riscv_vluxseg2_mask:
1972 case Intrinsic::riscv_vluxseg3_mask:
1973 case Intrinsic::riscv_vluxseg4_mask:
1974 case Intrinsic::riscv_vluxseg5_mask:
1975 case Intrinsic::riscv_vluxseg6_mask:
1976 case Intrinsic::riscv_vluxseg7_mask:
1977 case Intrinsic::riscv_vluxseg8_mask:
1978 return SetRVVLoadStoreInfo(
I.arg_size() - 6,
1981 case Intrinsic::riscv_vsseg2:
1982 case Intrinsic::riscv_vsseg3:
1983 case Intrinsic::riscv_vsseg4:
1984 case Intrinsic::riscv_vsseg5:
1985 case Intrinsic::riscv_vsseg6:
1986 case Intrinsic::riscv_vsseg7:
1987 case Intrinsic::riscv_vsseg8:
1988 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1991 case Intrinsic::riscv_vsseg2_mask:
1992 case Intrinsic::riscv_vsseg3_mask:
1993 case Intrinsic::riscv_vsseg4_mask:
1994 case Intrinsic::riscv_vsseg5_mask:
1995 case Intrinsic::riscv_vsseg6_mask:
1996 case Intrinsic::riscv_vsseg7_mask:
1997 case Intrinsic::riscv_vsseg8_mask:
1998 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
2001 case Intrinsic::riscv_vssseg2:
2002 case Intrinsic::riscv_vssseg3:
2003 case Intrinsic::riscv_vssseg4:
2004 case Intrinsic::riscv_vssseg5:
2005 case Intrinsic::riscv_vssseg6:
2006 case Intrinsic::riscv_vssseg7:
2007 case Intrinsic::riscv_vssseg8:
2008 case Intrinsic::riscv_vsoxseg2:
2009 case Intrinsic::riscv_vsoxseg3:
2010 case Intrinsic::riscv_vsoxseg4:
2011 case Intrinsic::riscv_vsoxseg5:
2012 case Intrinsic::riscv_vsoxseg6:
2013 case Intrinsic::riscv_vsoxseg7:
2014 case Intrinsic::riscv_vsoxseg8:
2015 case Intrinsic::riscv_vsuxseg2:
2016 case Intrinsic::riscv_vsuxseg3:
2017 case Intrinsic::riscv_vsuxseg4:
2018 case Intrinsic::riscv_vsuxseg5:
2019 case Intrinsic::riscv_vsuxseg6:
2020 case Intrinsic::riscv_vsuxseg7:
2021 case Intrinsic::riscv_vsuxseg8:
2022 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
2025 case Intrinsic::riscv_vssseg2_mask:
2026 case Intrinsic::riscv_vssseg3_mask:
2027 case Intrinsic::riscv_vssseg4_mask:
2028 case Intrinsic::riscv_vssseg5_mask:
2029 case Intrinsic::riscv_vssseg6_mask:
2030 case Intrinsic::riscv_vssseg7_mask:
2031 case Intrinsic::riscv_vssseg8_mask:
2032 case Intrinsic::riscv_vsoxseg2_mask:
2033 case Intrinsic::riscv_vsoxseg3_mask:
2034 case Intrinsic::riscv_vsoxseg4_mask:
2035 case Intrinsic::riscv_vsoxseg5_mask:
2036 case Intrinsic::riscv_vsoxseg6_mask:
2037 case Intrinsic::riscv_vsoxseg7_mask:
2038 case Intrinsic::riscv_vsoxseg8_mask:
2039 case Intrinsic::riscv_vsuxseg2_mask:
2040 case Intrinsic::riscv_vsuxseg3_mask:
2041 case Intrinsic::riscv_vsuxseg4_mask:
2042 case Intrinsic::riscv_vsuxseg5_mask:
2043 case Intrinsic::riscv_vsuxseg6_mask:
2044 case Intrinsic::riscv_vsuxseg7_mask:
2045 case Intrinsic::riscv_vsuxseg8_mask:
2046 return SetRVVLoadStoreInfo(
I.arg_size() - 5,
2100 if (Subtarget.is64Bit() || !SrcTy->isIntegerTy() || !DstTy->
isIntegerTy())
2102 unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
2104 return (SrcBits == 64 && DestBits == 32);
2115 return (SrcBits == 64 && DestBits == 32);
2121 if (Subtarget.hasVInstructions() &&
2126 if (SrcBits == DestBits * 2) {
2138 EVT MemVT = LD->getMemoryVT();
2139 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
2149 return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
2157 return Subtarget.hasCTZLike();
2161 return Subtarget.hasCLZLike();
2172 if (!Subtarget.hasBEXTILike())
2177 return !Mask->getValue().isSignedIntN(12) && Mask->getValue().isPowerOf2();
2181 EVT VT =
Y.getValueType();
2186 return (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
2191 EVT VT =
Y.getValueType();
2196 return Subtarget.hasStdExtZvkb();
2201 if (Subtarget.hasStdExtZbs())
2202 return X.getValueType().isScalarInteger();
2205 if (Subtarget.hasVendorXTHeadBs())
2206 return C !=
nullptr;
2208 return C &&
C->getAPIntValue().ule(10);
2212 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
2218 if (!VT.
isVector() || !Subtarget.hasVInstructions())
2229 assert(Ty->isIntegerTy());
2231 unsigned BitSize = Ty->getIntegerBitWidth();
2232 if (BitSize > Subtarget.getXLen())
2236 int64_t Val = Imm.getSExtValue();
2244 if (!Subtarget.enableUnalignedScalarMem())
2254 return Seq.
size() <= Subtarget.getMaxBuildIntsCost();
2260 unsigned OldShiftOpcode,
unsigned NewShiftOpcode,
2267 if (XC && OldShiftOpcode ==
ISD::SRL && XC->isOne())
2315 if (!Subtarget.hasStdExtZfa())
2318 bool IsSupportedVT =
false;
2319 if (VT == MVT::f16) {
2320 IsSupportedVT = Subtarget.hasStdExtZfh() || Subtarget.hasStdExtZvfh();
2321 }
else if (VT == MVT::f32) {
2322 IsSupportedVT =
true;
2323 }
else if (VT == MVT::f64) {
2324 assert(Subtarget.hasStdExtD() &&
"Expect D extension");
2325 IsSupportedVT =
true;
2335 bool ForCodeSize)
const {
2336 bool IsLegalVT =
false;
2338 IsLegalVT = Subtarget.hasStdExtZfhminOrZhinxmin();
2339 else if (VT == MVT::f32)
2340 IsLegalVT = Subtarget.hasStdExtFOrZfinx();
2341 else if (VT == MVT::f64)
2342 IsLegalVT = Subtarget.hasStdExtDOrZdinx();
2343 else if (VT == MVT::bf16)
2344 IsLegalVT = Subtarget.hasStdExtZfbfmin();
2360 return Imm.isZero();
2364 if (Imm.isNegZero())
2369 const int FmvCost = Subtarget.hasStdExtZfinx() ? 0 : 1;
2372 Subtarget.getXLen(), Subtarget);
2378 unsigned Index)
const {
2395 if (EltVT == MVT::i1)
2401 unsigned MinVLen = Subtarget.getRealMinVLen();
2408 if (Index + ResElts <= MinVLMAX && Index < 31)
2417 return (ResElts * 2) == SrcElts && (Index == 0 || Index == ResElts);
2425 if (VT == MVT::f16 && Subtarget.hasStdExtFOrZfinx() &&
2426 !Subtarget.hasStdExtZfhminOrZhinxmin())
2436 std::optional<MVT> RegisterVT)
const {
2438 if (VT == (Subtarget.is64Bit() ? MVT::i128 : MVT::i64) && RegisterVT &&
2439 *RegisterVT == MVT::Untyped)
2450 if (VT == MVT::f16 && Subtarget.hasStdExtFOrZfinx() &&
2451 !Subtarget.hasStdExtZfhminOrZhinxmin())
2459 unsigned &NumIntermediates,
MVT &RegisterVT)
const {
2461 Context, CC, VT, IntermediateVT, NumIntermediates, RegisterVT);
2479 !Subtarget.hasVendorXAndesPerf()) {
2485 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
2499 int64_t
C = RHSC->getSExtValue();
2554 if (VT.
SimpleTy >= MVT::riscv_nxv1i8x2 &&
2555 VT.
SimpleTy <= MVT::riscv_nxv1i8x8)
2557 if (VT.
SimpleTy >= MVT::riscv_nxv2i8x2 &&
2558 VT.
SimpleTy <= MVT::riscv_nxv2i8x8)
2560 if (VT.
SimpleTy >= MVT::riscv_nxv4i8x2 &&
2561 VT.
SimpleTy <= MVT::riscv_nxv4i8x8)
2563 if (VT.
SimpleTy >= MVT::riscv_nxv8i8x2 &&
2564 VT.
SimpleTy <= MVT::riscv_nxv8i8x8)
2566 if (VT.
SimpleTy >= MVT::riscv_nxv16i8x2 &&
2567 VT.
SimpleTy <= MVT::riscv_nxv16i8x4)
2569 if (VT.
SimpleTy == MVT::riscv_nxv32i8x2)
2579 switch (KnownSize) {
2607 return RISCV::VRRegClassID;
2609 return RISCV::VRM2RegClassID;
2611 return RISCV::VRM4RegClassID;
2613 return RISCV::VRM8RegClassID;
2621 static_assert(RISCV::sub_vrm1_7 == RISCV::sub_vrm1_0 + 7,
2622 "Unexpected subreg numbering");
2623 return RISCV::sub_vrm1_0 + Index;
2626 static_assert(RISCV::sub_vrm2_3 == RISCV::sub_vrm2_0 + 3,
2627 "Unexpected subreg numbering");
2628 return RISCV::sub_vrm2_0 + Index;
2631 static_assert(RISCV::sub_vrm4_1 == RISCV::sub_vrm4_0 + 1,
2632 "Unexpected subreg numbering");
2633 return RISCV::sub_vrm4_0 + Index;
2641 unsigned RegsPerField =
2644 switch (RegsPerField) {
2647 return RISCV::VRN2M1RegClassID;
2649 return RISCV::VRN3M1RegClassID;
2651 return RISCV::VRN4M1RegClassID;
2653 return RISCV::VRN5M1RegClassID;
2655 return RISCV::VRN6M1RegClassID;
2657 return RISCV::VRN7M1RegClassID;
2659 return RISCV::VRN8M1RegClassID;
2663 return RISCV::VRN2M2RegClassID;
2665 return RISCV::VRN3M2RegClassID;
2667 return RISCV::VRN4M2RegClassID;
2671 return RISCV::VRN2M4RegClassID;
2679 return RISCV::VRRegClassID;
2688std::pair<unsigned, unsigned>
2690 MVT VecVT,
MVT SubVecVT,
unsigned InsertExtractIdx,
2692 static_assert((RISCV::VRM8RegClassID > RISCV::VRM4RegClassID &&
2693 RISCV::VRM4RegClassID > RISCV::VRM2RegClassID &&
2694 RISCV::VRM2RegClassID > RISCV::VRRegClassID),
2695 "Register classes not ordered");
2702 if (VecRegClassID == SubRegClassID)
2703 return {RISCV::NoSubRegister, 0};
2706 "Only allow scalable vector subvector.");
2708 "Invalid vector tuple insert/extract for vector and subvector with "
2719 unsigned SubRegIdx = RISCV::NoSubRegister;
2720 for (
const unsigned RCID :
2721 {RISCV::VRM4RegClassID, RISCV::VRM2RegClassID, RISCV::VRRegClassID})
2722 if (VecRegClassID > RCID && SubRegClassID <= RCID) {
2726 SubRegIdx =
TRI->composeSubRegIndices(SubRegIdx,
2731 return {SubRegIdx, InsertExtractIdx};
2736bool RISCVTargetLowering::mergeStoresAfterLegalization(
EVT VT)
const {
2746 return Subtarget.is64Bit() ? Subtarget.hasVInstructionsI64() :
true;
2750 return Subtarget.hasVInstructions();
2752 return Subtarget.hasVInstructionsI64();
2754 return Subtarget.hasVInstructionsF16Minimal();
2756 return Subtarget.hasVInstructionsBF16Minimal();
2758 return Subtarget.hasVInstructionsF32();
2760 return Subtarget.hasVInstructionsF64();
2774 "Unexpected opcode");
2776 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
2778 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
2781 return Op.getOperand(
II->VLOperand + 1 + HasChain);
2855bool RISCVTargetLowering::useRVVForFixedLengthVectorVT(
MVT VT)
const {
2856 return ::useRVVForFixedLengthVectorVT(VT, Subtarget);
2865 "Expected legal fixed length vector!");
2868 unsigned MaxELen = Subtarget.
getELen();
2902 return ::getContainerForFixedLengthVector(*
this, VT,
getSubtarget());
2909 "Expected to convert into a scalable vector!");
2910 assert(V.getValueType().isFixedLengthVector() &&
2911 "Expected a fixed length vector operand!");
2920 "Expected to convert into a fixed length vector!");
2921 assert(V.getValueType().isScalableVector() &&
2922 "Expected a scalable vector operand!");
2941 return DAG.
getNode(RISCVISD::VMSET_VL,
DL, MaskVT, VL);
2944static std::pair<SDValue, SDValue>
2953static std::pair<SDValue, SDValue>
2966static std::pair<SDValue, SDValue>
2983std::pair<unsigned, unsigned>
2991 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
2995 unsigned VectorBitsMin = Subtarget.getRealMinVLen();
2999 return std::make_pair(MinVLMAX, MaxVLMAX);
3011 EVT VT,
unsigned DefinedValues)
const {
3020 unsigned DLenFactor = Subtarget.getDLenFactor();
3025 std::tie(LMul, Fractional) =
3028 Cost = LMul <= DLenFactor ? (DLenFactor / LMul) : 1;
3030 Cost = (LMul * DLenFactor);
3044 bool Log2CostModel =
3046 if (Log2CostModel && LMULCost.isValid()) {
3047 unsigned Log =
Log2_64(LMULCost.getValue());
3049 return LMULCost * Log;
3051 return LMULCost * LMULCost;
3082 Op.getValueType() == MVT::bf16) {
3083 bool IsStrict =
Op->isStrictFPOpcode();
3088 {Op.getOperand(0), Op.getOperand(1)});
3090 {
Op.getValueType(), MVT::Other},
3096 DAG.
getNode(
Op.getOpcode(),
DL, MVT::f32,
Op.getOperand(0)),
3111 MVT DstVT =
Op.getSimpleValueType();
3120 Src.getValueType() == MVT::bf16) {
3126 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
3127 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
3128 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
3135 Opc,
DL, DstVT, Src,
3138 if (
Opc == RISCVISD::FCVT_WU_RV64)
3149 MVT SrcVT = Src.getSimpleValueType();
3155 if (SatVT != DstEltVT)
3158 MVT DstContainerVT = DstVT;
3159 MVT SrcContainerVT = SrcVT;
3165 "Expected same element count");
3174 {Src, Src, DAG.getCondCode(ISD::SETNE),
3175 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
3179 if (DstEltSize > (2 * SrcEltSize)) {
3182 Src = DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, InterVT, Src, Mask, VL);
3185 MVT CvtContainerVT = DstContainerVT;
3186 MVT CvtEltVT = DstEltVT;
3187 if (SrcEltSize > (2 * DstEltSize)) {
3193 IsSigned ? RISCVISD::VFCVT_RTZ_X_F_VL : RISCVISD::VFCVT_RTZ_XU_F_VL;
3196 while (CvtContainerVT != DstContainerVT) {
3200 unsigned ClipOpc = IsSigned ? RISCVISD::TRUNCATE_VECTOR_VL_SSAT
3201 : RISCVISD::TRUNCATE_VECTOR_VL_USAT;
3202 Res = DAG.
getNode(ClipOpc,
DL, CvtContainerVT, Res, Mask, VL);
3206 RISCVISD::VMV_V_X_VL,
DL, DstContainerVT, DAG.
getUNDEF(DstContainerVT),
3208 Res = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, DstContainerVT, IsNan, SplatZero,
3209 Res, DAG.
getUNDEF(DstContainerVT), VL);
3219 bool IsStrict =
Op->isStrictFPOpcode();
3220 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
3230 {
Op.getOperand(0), SrcVal});
3231 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
3232 {Ext.getValue(1), Ext.getValue(0)});
3235 DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, SrcVal));
3244 case ISD::FROUNDEVEN:
3246 case ISD::VP_FROUNDEVEN:
3250 case ISD::VP_FROUNDTOZERO:
3254 case ISD::VP_FFLOOR:
3266 case ISD::VP_FROUND:
3276 case ISD::VP_LLRINT:
3290 MVT VT =
Op.getSimpleValueType();
3300 MVT ContainerVT = VT;
3307 if (
Op->isVPOpcode()) {
3308 Mask =
Op.getOperand(1);
3312 VL =
Op.getOperand(2);
3318 SDValue Abs = DAG.
getNode(RISCVISD::FABS_VL,
DL, ContainerVT, Src, Mask, VL);
3331 DAG.
getUNDEF(ContainerVT), MaxValNode, VL);
3336 DAG.
getNode(RISCVISD::SETCC_VL,
DL, SetccVT,
3345 switch (
Op.getOpcode()) {
3353 case ISD::VP_FFLOOR:
3355 case ISD::FROUNDEVEN:
3356 case ISD::VP_FROUND:
3357 case ISD::VP_FROUNDEVEN:
3358 case ISD::VP_FROUNDTOZERO: {
3361 Truncated = DAG.
getNode(RISCVISD::VFCVT_RM_X_F_VL,
DL, IntVT, Src, Mask,
3366 Truncated = DAG.
getNode(RISCVISD::VFCVT_RTZ_X_F_VL,
DL, IntVT, Src,
3369 case ISD::FNEARBYINT:
3370 case ISD::VP_FNEARBYINT:
3371 Truncated = DAG.
getNode(RISCVISD::VFROUND_NOEXCEPT_VL,
DL, ContainerVT, Src,
3377 if (Truncated.
getOpcode() != RISCVISD::VFROUND_NOEXCEPT_VL)
3378 Truncated = DAG.
getNode(RISCVISD::SINT_TO_FP_VL,
DL, ContainerVT, Truncated,
3382 Truncated = DAG.
getNode(RISCVISD::FCOPYSIGN_VL,
DL, ContainerVT, Truncated,
3383 Src, Src, Mask, VL);
3398 MVT VT =
Op.getSimpleValueType();
3402 MVT ContainerVT = VT;
3414 MVT MaskVT = Mask.getSimpleValueType();
3417 {Chain, Src, Src, DAG.getCondCode(ISD::SETUNE),
3418 DAG.getUNDEF(MaskVT), Mask, VL});
3420 Src = DAG.
getNode(RISCVISD::STRICT_FADD_VL,
DL,
3422 {Chain, Src, Src, Src, Unorder, VL});
3426 SDValue Abs = DAG.
getNode(RISCVISD::FABS_VL,
DL, ContainerVT, Src, Mask, VL);
3439 DAG.
getUNDEF(ContainerVT), MaxValNode, VL);
3443 RISCVISD::SETCC_VL,
DL, MaskVT,
3451 switch (
Op.getOpcode()) {
3461 RISCVISD::STRICT_VFCVT_RM_X_F_VL,
DL, DAG.
getVTList(IntVT, MVT::Other),
3462 {Chain, Src, Mask, DAG.getTargetConstant(FRM, DL, XLenVT), VL});
3467 DAG.
getNode(RISCVISD::STRICT_VFCVT_RTZ_X_F_VL,
DL,
3468 DAG.
getVTList(IntVT, MVT::Other), Chain, Src, Mask, VL);
3471 Truncated = DAG.
getNode(RISCVISD::STRICT_VFROUND_NOEXCEPT_VL,
DL,
3472 DAG.
getVTList(ContainerVT, MVT::Other), Chain, Src,
3480 Truncated = DAG.
getNode(RISCVISD::STRICT_SINT_TO_FP_VL,
DL,
3481 DAG.
getVTList(ContainerVT, MVT::Other), Chain,
3482 Truncated, Mask, VL);
3487 Truncated = DAG.
getNode(RISCVISD::FCOPYSIGN_VL,
DL, ContainerVT, Truncated,
3488 Src, Src, Mask, VL);
3498 MVT VT =
Op.getSimpleValueType();
3519 return DAG.
getNode(RISCVISD::FROUND,
DL, VT, Src, MaxValNode,
3527 MVT DstVT =
Op.getSimpleValueType();
3529 MVT SrcVT = Src.getSimpleValueType();
3534 MVT DstContainerVT = DstVT;
3535 MVT SrcContainerVT = SrcVT;
3547 if (SrcElemType == MVT::f16 || SrcElemType == MVT::bf16) {
3549 Src = DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, F32VT, Src, Mask, VL);
3553 DAG.
getNode(RISCVISD::VFCVT_RM_X_F_VL,
DL, DstContainerVT, Src, Mask,
3573 return DAG.
getNode(RISCVISD::VSLIDEDOWN_VL,
DL, VT,
Ops);
3585 return DAG.
getNode(RISCVISD::VSLIDEUP_VL,
DL, VT,
Ops);
3610 return std::nullopt;
3628 unsigned EltSizeInBits) {
3631 return std::nullopt;
3632 bool IsInteger =
Op.getValueType().isInteger();
3634 std::optional<unsigned> SeqStepDenom;
3635 std::optional<APInt> SeqStepNum;
3636 std::optional<APInt> SeqAddend;
3637 std::optional<std::pair<APInt, unsigned>> PrevElt;
3638 assert(EltSizeInBits >=
Op.getValueType().getScalarSizeInBits());
3643 const unsigned OpSize =
Op.getScalarValueSizeInBits();
3644 for (
auto [Idx, Elt] :
enumerate(
Op->op_values())) {
3645 if (Elt.isUndef()) {
3646 Elts[Idx] = std::nullopt;
3650 Elts[Idx] = Elt->getAsAPIntVal().trunc(OpSize).zext(EltSizeInBits);
3655 return std::nullopt;
3656 Elts[Idx] = *ExactInteger;
3660 for (
auto [Idx, Elt] :
enumerate(Elts)) {
3669 unsigned IdxDiff = Idx - PrevElt->second;
3670 APInt ValDiff = *Elt - PrevElt->first;
3678 int64_t Remainder = ValDiff.
srem(IdxDiff);
3683 return std::nullopt;
3684 ValDiff = ValDiff.
sdiv(IdxDiff);
3689 SeqStepNum = ValDiff;
3690 else if (ValDiff != SeqStepNum)
3691 return std::nullopt;
3694 SeqStepDenom = IdxDiff;
3695 else if (IdxDiff != *SeqStepDenom)
3696 return std::nullopt;
3700 if (!PrevElt || PrevElt->first != *Elt)
3701 PrevElt = std::make_pair(*Elt, Idx);
3705 if (!SeqStepNum || !SeqStepDenom)
3706 return std::nullopt;
3710 for (
auto [Idx, Elt] :
enumerate(Elts)) {
3714 (
APInt(EltSizeInBits, Idx,
false,
true) *
3716 .sdiv(*SeqStepDenom);
3718 APInt Addend = *Elt - ExpectedVal;
3721 else if (Addend != SeqAddend)
3722 return std::nullopt;
3725 assert(SeqAddend &&
"Must have an addend if we have a step");
3727 return VIDSequence{SeqStepNum->getSExtValue(), *SeqStepDenom,
3728 SeqAddend->getSExtValue()};
3743 if (EltTy == MVT::i1 ||
3746 MVT SrcVT = Src.getSimpleValueType();
3762 MVT ContainerVT = VT;
3766 MVT SrcContainerVT = SrcVT;
3781 SDValue Gather = DAG.
getNode(RISCVISD::VRGATHER_VX_VL,
DL, ContainerVT, Src,
3782 Idx, DAG.
getUNDEF(ContainerVT), Mask, VL);
3790 MVT VT =
Op.getSimpleValueType();
3799 int64_t StepNumerator = SimpleVID->StepNumerator;
3800 unsigned StepDenominator = SimpleVID->StepDenominator;
3801 int64_t Addend = SimpleVID->Addend;
3803 assert(StepNumerator != 0 &&
"Invalid step");
3804 bool Negate =
false;
3805 int64_t SplatStepVal = StepNumerator;
3809 if (StepNumerator != 1 && StepNumerator !=
INT64_MIN &&
3811 Negate = StepNumerator < 0;
3813 SplatStepVal =
Log2_64(std::abs(StepNumerator));
3823 (SplatStepVal >= 0 || StepDenominator == 1) &&
isInt<32>(Addend)) {
3826 MVT VIDContainerVT =
3834 if ((StepOpcode ==
ISD::MUL && SplatStepVal != 1) ||
3835 (StepOpcode ==
ISD::SHL && SplatStepVal != 0)) {
3837 VID = DAG.
getNode(StepOpcode,
DL, VIDVT, VID, SplatStep);
3839 if (StepDenominator != 1) {
3844 if (Addend != 0 || Negate) {
3870 MVT VT =
Op.getSimpleValueType();
3879 unsigned NumElts =
Op.getNumOperands();
3882 unsigned MostCommonCount = 0;
3884 unsigned NumUndefElts =
3892 unsigned NumScalarLoads = 0;
3898 unsigned &
Count = ValueCounts[V];
3901 NumScalarLoads += !CFP->isExactlyValue(+0.0);
3906 if (++
Count >= MostCommonCount) {
3908 MostCommonCount =
Count;
3912 assert(DominantValue &&
"Not expecting an all-undef BUILD_VECTOR");
3913 unsigned NumDefElts = NumElts - NumUndefElts;
3914 unsigned DominantValueCountThreshold = NumDefElts <= 2 ? 0 : NumDefElts - 2;
3920 ((MostCommonCount > DominantValueCountThreshold) ||
3932 if (
SDValue LastOp =
Op->getOperand(
Op->getNumOperands() - 1);
3933 !LastOp.isUndef() && ValueCounts[LastOp] == 1 &&
3934 LastOp != DominantValue) {
3937 VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1DOWN_VL : RISCVISD::VSLIDE1DOWN_VL;
3943 Processed.
insert(LastOp);
3949 if (V.isUndef() || !Processed.
insert(V).second)
3951 if (ValueCounts[V] == 1) {
3959 return DAG.getConstant(V == V1, DL, XLenVT);
3975 MVT VT =
Op.getSimpleValueType();
3984 unsigned NumElts =
Op.getNumOperands();
4005 unsigned NumViaIntegerBits = std::clamp(NumElts, 8u, Subtarget.
getXLen());
4006 NumViaIntegerBits = std::min(NumViaIntegerBits, Subtarget.
getELen());
4014 unsigned IntegerViaVecElts =
divideCeil(NumElts, NumViaIntegerBits);
4015 MVT IntegerViaVecVT =
4020 unsigned BitPos = 0, IntegerEltIdx = 0;
4023 for (
unsigned I = 0;
I < NumElts;) {
4025 bool BitValue = !V.isUndef() && V->getAsZExtVal();
4026 Bits |= ((
uint64_t)BitValue << BitPos);
4032 if (
I % NumViaIntegerBits == 0 ||
I == NumElts) {
4033 if (NumViaIntegerBits <= 32)
4036 Elts[IntegerEltIdx] = Elt;
4045 if (NumElts < NumViaIntegerBits) {
4049 assert(IntegerViaVecVT == MVT::v1i8 &&
"Unexpected mask vector type");
4064 : RISCVISD::VMV_V_X_VL;
4084 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32) &&
4085 "Unexpected sequence type");
4089 unsigned ViaVecLen =
4097 const auto &SeqV =
OpIdx.value();
4098 if (!SeqV.isUndef())
4100 ((SeqV->getAsZExtVal() & EltMask) << (
OpIdx.index() * EltBitSize));
4106 if (ViaIntVT == MVT::i32)
4129 BV->getRepeatedSequence(Sequence) &&
4130 (Sequence.size() * EltBitSize) <= Subtarget.
getELen()) {
4131 unsigned SeqLen = Sequence.size();
4133 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32 ||
4134 ViaIntVT == MVT::i64) &&
4135 "Unexpected sequence type");
4140 const unsigned RequiredVL = NumElts / SeqLen;
4141 const unsigned ViaVecLen =
4143 NumElts : RequiredVL;
4146 unsigned EltIdx = 0;
4151 for (
const auto &SeqV : Sequence) {
4152 if (!SeqV.isUndef())
4154 ((SeqV->getAsZExtVal() & EltMask) << (EltIdx * EltBitSize));
4161 if (ViaIntVT == MVT::i32)
4168 (!Subtarget.
is64Bit() && ViaIntVT == MVT::i64)) &&
4169 "Unexpected bitcast sequence");
4173 MVT ViaContainerVT =
4176 DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ViaContainerVT,
4180 if (ViaVecLen != RequiredVL)
4199 Source, DAG, Subtarget);
4200 SDValue Res = DAG.
getNode(RISCVISD::VSEXT_VL,
DL, ContainerVT, Source, Mask, VL);
4219 return RISCV::PACKH;
4221 return Subtarget.
is64Bit() ? RISCV::PACKW : RISCV::PACK;
4236 MVT VT =
Op.getSimpleValueType();
4244 if (!Subtarget.hasStdExtZbb() || !Subtarget.hasStdExtZba())
4249 if (ElemSizeInBits >= std::min(Subtarget.
getELen(), Subtarget.
getXLen()) ||
4263 if (Subtarget.hasStdExtZbkb())
4268 ElemDL, XLenVT,
A,
B),
4280 NewOperands.
reserve(NumElts / 2);
4282 NewOperands.
push_back(pack(
Op.getOperand(i),
Op.getOperand(i + 1)));
4286 return DAG.
getNode(ISD::BITCAST,
DL, VT,
4292 MVT VT =
Op.getSimpleValueType();
4303 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) || EltVT == MVT::bf16) {
4308 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4309 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin())) {
4319 NewOps[
I] = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Elem);
4369 [](
const SDUse &U) { return U.get().isUndef(); })) {
4410 auto OneVRegOfOps =
ArrayRef(BuildVectorOps).slice(i, ElemsPerVReg);
4414 unsigned InsertIdx = (i / ElemsPerVReg) * NumOpElts;
4436 unsigned NumUndefElts =
4438 unsigned NumDefElts = NumElts - NumUndefElts;
4439 if (NumDefElts >= 8 && NumDefElts > NumElts / 2 &&
4446 for (
const auto &[Idx, U] :
enumerate(
Op->ops())) {
4448 if (Idx < NumElts / 2) {
4455 bool SelectMaskVal = (Idx < NumElts / 2);
4458 assert(SubVecAOps.
size() == NumElts && SubVecBOps.
size() == NumElts &&
4459 MaskVals.
size() == NumElts);
4494 unsigned UndefCount = 0;
4501 LinearBudget -= PerSlideCost;
4504 LinearBudget -= PerSlideCost;
4507 LinearBudget -= PerSlideCost;
4510 if (LinearBudget < 0)
4515 "Illegal type which will result in reserved encoding");
4531 bool SlideUp =
false;
4597 Vec = getVSlide(ContainerVT, DAG.
getUNDEF(ContainerVT), Vec,
Offset, Mask,
4604 Opcode = SlideUp ? RISCVISD::VFSLIDE1UP_VL : RISCVISD::VFSLIDE1DOWN_VL;
4606 Opcode = SlideUp ? RISCVISD::VSLIDE1UP_VL : RISCVISD::VSLIDE1DOWN_VL;
4615 Vec = getVSlide(ContainerVT, DAG.
getUNDEF(ContainerVT), Vec,
Offset, Mask,
4631 if ((LoC >> 31) == HiC)
4632 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4644 auto InterVec = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, InterVT,
4646 return DAG.
getNode(ISD::BITCAST,
DL, VT, InterVec);
4653 Hi.getConstantOperandVal(1) == 31)
4654 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4659 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4662 return DAG.
getNode(RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL,
DL, VT, Passthru,
Lo,
4672 assert(Scalar.getValueType() == MVT::i64 &&
"Unexpected VT!");
4684 bool HasPassthru = Passthru && !Passthru.
isUndef();
4685 if (!HasPassthru && !Passthru)
4692 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
4693 EltVT == MVT::bf16) {
4694 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4695 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
4696 Scalar = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Scalar);
4698 Scalar = DAG.
getNode(ISD::BITCAST,
DL, MVT::i16, Scalar);
4700 Passthru = DAG.
getNode(ISD::BITCAST,
DL, IVT, Passthru);
4705 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL, VT, Passthru, Scalar, VL);
4709 if (Scalar.getValueType().bitsLE(XLenVT)) {
4716 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4717 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru, Scalar, VL);
4720 assert(XLenVT == MVT::i32 && Scalar.getValueType() == MVT::i64 &&
4721 "Unexpected scalar for splat lowering!");
4724 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, VT, Passthru,
4750 MVT ExtractedContainerVT = ExtractedVT;
4753 DAG, ExtractedContainerVT, Subtarget);
4755 ExtractedVal, DAG, Subtarget);
4757 if (ExtractedContainerVT.
bitsLE(VT))
4769 if (!Scalar.getValueType().bitsLE(XLenVT))
4772 VT,
DL, DAG, Subtarget);
4780 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4821 Src && Src.
getValueType().getVectorNumElements() == (NumElts * 2))
4838 !Subtarget.hasVendorXRivosVizip())
4841 int Size = Mask.size();
4843 assert(
Size == (
int)NumElts &&
"Unexpected mask size");
4849 EvenSrc = StartIndexes[0];
4850 OddSrc = StartIndexes[1];
4853 if (EvenSrc != 0 && OddSrc != 0)
4863 int HalfNumElts = NumElts / 2;
4864 return ((EvenSrc % HalfNumElts) == 0) && ((OddSrc % HalfNumElts) == 0);
4869 std::array<std::pair<int, int>, 2> &SrcInfo) {
4874 if (SrcInfo[0].second == 0 && SrcInfo[1].second == 0)
4878 if ((SrcInfo[0].second > 0 && SrcInfo[1].second < 0) ||
4879 SrcInfo[1].second == 0)
4881 assert(SrcInfo[0].first != -1 &&
"Must find one slide");
4889 if (SrcInfo[1].first == -1)
4891 return SrcInfo[0].second < 0 && SrcInfo[1].second > 0 &&
4892 SrcInfo[1].second - SrcInfo[0].second == (int)NumElts;
4897 bool RequiredPolarity) {
4898 int NumElts = Mask.size();
4899 for (
const auto &[Idx, M] :
enumerate(Mask)) {
4902 int Src = M >= NumElts;
4903 int Diff = (int)Idx - (M % NumElts);
4904 bool C = Src == SrcInfo[1].first && Diff == SrcInfo[1].second;
4905 assert(
C != (Src == SrcInfo[0].first && Diff == SrcInfo[0].second) &&
4906 "Must match exactly one of the two slides");
4907 if (RequiredPolarity != (
C == (Idx / Factor) % 2))
4918static bool isZipEven(
const std::array<std::pair<int, int>, 2> &SrcInfo,
4920 Factor = SrcInfo[1].second;
4922 Mask.size() % Factor == 0 &&
4933static bool isZipOdd(
const std::array<std::pair<int, int>, 2> &SrcInfo,
4935 Factor = -SrcInfo[1].second;
4937 Mask.size() % Factor == 0 &&
4950 ElementCount SrcEC = Src.getValueType().getVectorElementCount();
4957 unsigned Shift = Index * EltBits;
4982 std::optional<int> SplatIdx;
4984 if (M == -1 ||
I == (
unsigned)M)
4986 if (SplatIdx && *SplatIdx != M)
4995 for (
int MaskIndex : Mask) {
4996 bool SelectMaskVal = MaskIndex == *SplatIdx;
4999 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
5024 auto findNonEXTRACT_SUBVECTORParent =
5025 [](
SDValue Parent) -> std::pair<SDValue, uint64_t> {
5030 Parent.getOperand(0).getSimpleValueType().isFixedLengthVector()) {
5031 Offset += Parent.getConstantOperandVal(1);
5032 Parent = Parent.getOperand(0);
5034 return std::make_pair(Parent,
Offset);
5037 auto [V1Src, V1IndexOffset] = findNonEXTRACT_SUBVECTORParent(V1);
5038 auto [V2Src, V2IndexOffset] = findNonEXTRACT_SUBVECTORParent(V2);
5047 for (
size_t i = 0; i != NewMask.
size(); ++i) {
5048 if (NewMask[i] == -1)
5051 if (
static_cast<size_t>(NewMask[i]) < NewMask.
size()) {
5052 NewMask[i] = NewMask[i] + V1IndexOffset;
5056 NewMask[i] = NewMask[i] - NewMask.
size() + V2IndexOffset;
5062 if (NewMask[0] <= 0)
5066 for (
unsigned i = 1; i != NewMask.
size(); ++i)
5067 if (NewMask[i - 1] + 1 != NewMask[i])
5071 MVT SrcVT = Src.getSimpleValueType();
5100 int NumSubElts, Index;
5105 bool OpsSwapped = Mask[Index] < (int)NumElts;
5106 SDValue InPlace = OpsSwapped ? V2 : V1;
5107 SDValue ToInsert = OpsSwapped ? V1 : V2;
5118 if (NumSubElts + Index >= (
int)NumElts)
5129 Res = DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, ContainerVT, InPlace, ToInsert,
5132 Res =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, InPlace, ToInsert,
5144 bool OpsSwapped =
false;
5159 const unsigned E = Mask.size() - ((
Offset > 0) ?
Offset : 0);
5160 for (
unsigned i = S; i !=
E; ++i)
5161 if (Mask[i] >= 0 && (
unsigned)Mask[i] !=
Base + i +
Offset)
5167 bool IsVSlidedown = isSlideMask(Mask, OpsSwapped ? 0 : NumElts, 1);
5168 if (!IsVSlidedown && !isSlideMask(Mask, OpsSwapped ? 0 : NumElts, -1))
5171 const int InsertIdx = Mask[IsVSlidedown ? (NumElts - 1) : 0];
5173 if (InsertIdx < 0 || InsertIdx / NumElts != (
unsigned)OpsSwapped)
5190 IsVSlidedown ? RISCVISD::VSLIDE1DOWN_VL : RISCVISD::VSLIDE1UP_VL,
DL,
5196 auto OpCode = IsVSlidedown ?
5197 (VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1DOWN_VL : RISCVISD::VSLIDE1DOWN_VL) :
5198 (VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1UP_VL : RISCVISD::VSLIDE1UP_VL);
5201 auto Vec = DAG.
getNode(OpCode,
DL, ContainerVT,
5204 Splat, TrueMask, VL);
5216 for (
unsigned i = 0; i < Mask.size(); i++)
5217 LaneIsUndef[i % Factor] &= (Mask[i] == -1);
5220 for (
unsigned i = 0; i < Factor; i++) {
5231 for (
unsigned i = 0; i < Mask.size() / Factor; i++) {
5232 unsigned j = i * Factor + Index;
5233 if (Mask[j] != -1 && (
unsigned)Mask[j] != i)
5242 assert(RISCVISD::RI_VZIPEVEN_VL ==
Opc || RISCVISD::RI_VZIPODD_VL ==
Opc ||
5243 RISCVISD::RI_VZIP2A_VL ==
Opc || RISCVISD::RI_VZIP2B_VL ==
Opc ||
5244 RISCVISD::RI_VUNZIP2A_VL ==
Opc || RISCVISD::RI_VUNZIP2B_VL ==
Opc);
5252 MVT ContainerVT = IntVT;
5259 MVT InnerVT = ContainerVT;
5263 (RISCVISD::RI_VUNZIP2A_VL ==
Opc || RISCVISD::RI_VUNZIP2B_VL ==
Opc)) {
5275 if (InnerVT.
bitsLT(ContainerVT))
5290 MVT VT = V.getSimpleValueType();
5305 EC.multiplyCoefficientBy(Factor));
5324 MVT VecContainerVT = VecVT;
5341 MVT WideContainerVT = WideVT;
5347 EvenV = DAG.
getBitcast(VecContainerVT, EvenV);
5354 if (Subtarget.hasStdExtZvbb()) {
5358 Interleaved = DAG.
getNode(RISCVISD::VWSLL_VL,
DL, WideContainerVT, OddV,
5359 OffsetVec, Passthru, Mask, VL);
5360 Interleaved = DAG.
getNode(RISCVISD::VWADDU_W_VL,
DL, WideContainerVT,
5361 Interleaved, EvenV, Passthru, Mask, VL);
5368 Interleaved = DAG.
getNode(RISCVISD::VWADDU_VL,
DL, WideContainerVT, EvenV,
5369 OddV, Passthru, Mask, VL);
5375 OddV, AllOnesVec, Passthru, Mask, VL);
5382 Interleaved = DAG.
getNode(RISCVISD::ADD_VL,
DL, WideContainerVT,
5383 Interleaved, OddsMul, Passthru, Mask, VL);
5390 Interleaved = DAG.
getBitcast(ResultContainerVT, Interleaved);
5436 if (ViaEltSize > NumElts)
5444 if (ViaEltSize > NumElts)
5450 if (ViaEltSize > NumElts)
5457 MVT &RotateVT,
unsigned &RotateAmt) {
5460 unsigned NumSubElts;
5462 NumElts, NumSubElts, RotateAmt))
5465 NumElts / NumSubElts);
5533 unsigned NumOfSrcRegs = NumElts / NumOpElts;
5534 unsigned NumOfDestRegs = NumElts / NumOpElts;
5543 Mask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs,
5544 [&]() {
Operands.emplace_back(); },
5545 [&](
ArrayRef<int> SrcSubMask,
unsigned SrcVecIdx,
unsigned DstVecIdx) {
5546 Operands.emplace_back().emplace_back(SrcVecIdx, UINT_MAX,
5549 [&](
ArrayRef<int> SrcSubMask,
unsigned Idx1,
unsigned Idx2,
bool NewReg) {
5554 assert(
Operands.size() == NumOfDestRegs &&
"Whole vector must be processed");
5559 unsigned NumShuffles = std::accumulate(
5566 for (const auto &P : Data) {
5567 unsigned Idx2 = std::get<1>(P);
5568 ArrayRef<int> Mask = std::get<2>(P);
5569 if (Idx2 != UINT_MAX)
5571 else if (ShuffleVectorInst::isIdentityMask(Mask, Mask.size()))
5576 if ((NumOfDestRegs > 2 && NumShuffles > NumOfDestRegs) ||
5577 (NumOfDestRegs <= 2 && NumShuffles >= 4))
5579 auto ExtractValue = [&, &DAG = DAG](
SDValue SrcVec,
unsigned ExtractIdx) {
5580 SDValue SubVec = DAG.getExtractSubvector(
DL, M1VT, SrcVec, ExtractIdx);
5584 auto PerformShuffle = [&, &DAG = DAG](
SDValue SubVec1,
SDValue SubVec2,
5586 SDValue SubVec = DAG.getVectorShuffle(OneRegVT,
DL, SubVec1, SubVec2, Mask);
5589 SDValue Vec = DAG.getUNDEF(ContainerVT);
5595 const auto &[Idx1, Idx2,
_] =
Data[
I];
5603 V = ExtractValue(Idx1 >= NumOfSrcRegs ? V2 : V1,
5604 (Idx1 % NumOfSrcRegs) * NumOpElts);
5605 if (Idx2 != UINT_MAX) {
5608 V = ExtractValue(Idx2 >= NumOfSrcRegs ? V2 : V1,
5609 (Idx2 % NumOfSrcRegs) * NumOpElts);
5613 for (
const auto &[Idx1, Idx2, Mask] :
Data) {
5615 SDValue V2 = Idx2 == UINT_MAX ? V1 : Values.
at(Idx2);
5616 V = PerformShuffle(V1, V2, Mask);
5620 unsigned InsertIdx =
I * NumOpElts;
5622 Vec = DAG.getInsertSubvector(
DL, Vec, V, InsertIdx);
5632 bool SawUndef =
false;
5633 for (
const auto &[Idx, M] :
enumerate(Mask)) {
5640 if (Idx > (
unsigned)M)
5673 for (
int Idx : Mask) {
5676 unsigned SrcIdx = Idx % Mask.size();
5677 int Src = (
uint32_t)Idx < Mask.size() ? 0 : 1;
5678 if (Srcs[SrcIdx] == -1)
5681 else if (Srcs[SrcIdx] != Src)
5687 for (
int Lane : Srcs) {
5700 for (
unsigned I = 0;
I < Mask.size();
I++) {
5704 NewMask[
I] = Mask[
I] % Mask.size();
5718 if ((M / Span) != (
int)(
I / Span))
5720 int SpanIdx =
I % Span;
5730 return all_of(Mask, [&](
const auto &Idx) {
return Idx == -1 || Idx < Span; });
5742 int SpanIdx =
I % Span;
5743 if (Mask[SpanIdx] != M)
5757 MVT VT =
Op.getSimpleValueType();
5765 if (ElementSize > 32)
5788 MVT VT =
Op.getSimpleValueType();
5816 auto [TrueMask, VL] = TrueMaskVL;
5831 V.getOperand(0).getSimpleValueType().getVectorNumElements();
5832 V = V.getOperand(
Offset / OpElements);
5862 MVT SplatVT = ContainerVT;
5865 if (SVT == MVT::bf16 ||
5866 (SVT == MVT::f16 && !Subtarget.hasStdExtZfh())) {
5875 V = DAG.
getLoad(SVT,
DL, Ld->getChain(), NewAddr,
5876 Ld->getPointerInfo().getWithOffset(
Offset),
5877 Ld->getBaseAlign(), Ld->getMemOperand()->
getFlags());
5880 Ld->getPointerInfo().getWithOffset(
Offset), SVT,
5882 Ld->getMemOperand()->getFlags());
5886 : RISCVISD::VMV_V_X_VL;
5894 assert(Lane < (
int)NumElts &&
"Unexpected lane!");
5897 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
5919 if (Subtarget.hasStdExtZvkb())
5935 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
5936 for (
unsigned Factor = 2; Factor <= MaxFactor; Factor <<= 1) {
5939 1 <
count_if(Mask, [](
int Idx) {
return Idx != -1; })) {
5943 [&Mask](
int Idx) {
return Idx < (int)Mask.size(); }) &&
5944 1 <
count_if(Mask, [&Mask](
int Idx) {
5945 return Idx >= (int)Mask.size();
5975 if (Subtarget.hasVendorXRivosVizip() &&
5977 1 <
count_if(Mask, [](
int Idx) {
return Idx != -1; })) {
5979 Index == 0 ? RISCVISD::RI_VUNZIP2A_VL : RISCVISD::RI_VUNZIP2B_VL;
5995 [&Mask](
int Idx) {
return Idx < (int)Mask.size(); }) &&
5997 [&Mask](
int Idx) {
return Idx >= (int)Mask.size(); })) {
6001 if (NumElts < MinVLMAX) {
6025 int EvenSrc, OddSrc;
6035 bool LaneIsUndef[2] = {
true,
true};
6036 for (
const auto &[Idx, M] :
enumerate(Mask))
6037 LaneIsUndef[Idx % 2] &= (M == -1);
6039 int Size = Mask.size();
6041 if (LaneIsUndef[0]) {
6044 assert(EvenSrc >= 0 &&
"Undef source?");
6045 EvenV = (EvenSrc /
Size) == 0 ? V1 : V2;
6049 if (LaneIsUndef[1]) {
6052 assert(OddSrc >= 0 &&
"Undef source?");
6053 OddV = (OddSrc /
Size) == 0 ? V1 : V2;
6059 if (Subtarget.hasVendorXRivosVizip()) {
6062 return lowerVZIP(RISCVISD::RI_VZIP2A_VL, EvenV, OddV,
DL, DAG, Subtarget);
6073 std::array<std::pair<int, int>, 2> SrcInfo;
6080 auto GetSourceFor = [&](
const std::pair<int, int> &
Info) {
6081 int SrcIdx =
Info.first;
6082 assert(SrcIdx == 0 || SrcIdx == 1);
6083 SDValue &Src = Sources[SrcIdx];
6085 SDValue SrcV = SrcIdx == 0 ? V1 : V2;
6090 auto GetSlide = [&](
const std::pair<int, int> &Src,
SDValue Mask,
6092 auto [TrueMask, VL] = TrueMaskVL;
6093 SDValue SrcV = GetSourceFor(Src);
6094 int SlideAmt = Src.second;
6095 if (SlideAmt == 0) {
6097 assert(Mask == TrueMask);
6104 return getVSlideup(DAG, Subtarget,
DL, ContainerVT, Passthru, SrcV,
6109 if (SrcInfo[1].first == -1) {
6111 Res = GetSlide(SrcInfo[0], TrueMask, Res);
6115 if (Subtarget.hasVendorXRivosVizip()) {
6116 bool TryWiden =
false;
6120 SDValue Src1 = SrcInfo[0].first == 0 ? V1 : V2;
6121 SDValue Src2 = SrcInfo[1].first == 0 ? V1 : V2;
6122 return lowerVZIP(RISCVISD::RI_VZIPEVEN_VL, Src1, Src2,
DL, DAG,
6127 if (
isZipOdd(SrcInfo, Mask, Factor)) {
6129 SDValue Src1 = SrcInfo[1].first == 0 ? V1 : V2;
6130 SDValue Src2 = SrcInfo[0].first == 0 ? V1 : V2;
6131 return lowerVZIP(RISCVISD::RI_VZIPODD_VL, Src1, Src2,
DL, DAG,
6149 for (
const auto &[Idx, M] :
enumerate(Mask)) {
6151 (SrcInfo[1].second > 0 && Idx < (
unsigned)SrcInfo[1].second)) {
6155 int Src = M >= (int)NumElts;
6156 int Diff = (int)Idx - (M % NumElts);
6157 bool C = Src == SrcInfo[1].first && Diff == SrcInfo[1].second;
6158 assert(
C ^ (Src == SrcInfo[0].first && Diff == SrcInfo[0].second) &&
6159 "Must match exactly one of the two slides");
6162 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
6169 Res = GetSlide(SrcInfo[0], TrueMask, Res);
6170 Res = GetSlide(SrcInfo[1], SelectMask, Res);
6175 assert(!V1.
isUndef() &&
"Unexpected shuffle canonicalization");
6190 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
6191 for (
unsigned Factor = 4; Factor <= MaxFactor; Factor <<= 1) {
6206 if (NumElts > MinVLMAX) {
6207 unsigned MaxIdx = 0;
6211 MaxIdx = std::max(std::max((
unsigned)
I, (
unsigned)M), MaxIdx);
6213 unsigned NewNumElts =
6215 if (NewNumElts != NumElts) {
6219 Mask.take_front(NewNumElts));
6236 for (
auto Idx : Mask) {
6239 assert(Idx >= 0 && (
unsigned)Idx < NumElts);
6249 any_of(Mask, [&](
const auto &Idx) {
return Idx > 255; })) {
6259 unsigned GatherVVOpc = RISCVISD::VRGATHER_VV_VL;
6265 GatherVVOpc = RISCVISD::VRGATHEREI16_VV_VL;
6274 GatherVVOpc = RISCVISD::VRGATHEREI16_VV_VL;
6278 MVT IndexContainerVT =
6283 for (
int MaskIndex : Mask) {
6284 bool IsLHSIndex = MaskIndex < (int)NumElts && MaskIndex >= 0;
6294 if (NumElts <= MinVLMAX) {
6296 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
6302 auto [InnerTrueMask, InnerVL] =
6314 for (
int i = 0; i <
N; i++) {
6318 DAG.
getNode(GatherVVOpc,
DL, M1VT, SubV1, SubIndex,
6319 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6336 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6338 for (
int i = 0; i <
N; i++)
6354 for (
int i = 0; i <
N; i++) {
6357 DAG.
getUNDEF(IndexContainerVT), LHSIndices,
6358 SlideAmt, TrueMask, VL);
6362 DAG.
getNode(GatherVVOpc,
DL, M1VT, SubV1, SubIndex,
6363 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6373 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
6383 for (
int MaskIndex : Mask) {
6384 bool IsLHSOrUndefIndex = MaskIndex < (int)NumElts;
6385 ShuffleMaskLHS.
push_back(IsLHSOrUndefIndex && MaskIndex >= 0
6387 ShuffleMaskRHS.
push_back(IsLHSOrUndefIndex ? -1 : (MaskIndex - NumElts));
6418 for (
int MaskIndex : Mask) {
6419 bool SelectMaskVal = (MaskIndex < (int)NumElts) ^ !SwapOps;
6423 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
6441 const unsigned NumElts = M.size();
6448 std::array<std::pair<int, int>, 2> SrcInfo;
6459RISCVTargetLowering::lowerCTLZ_CTTZ_ZERO_UNDEF(
SDValue Op,
6461 MVT VT =
Op.getSimpleValueType();
6465 MVT ContainerVT = VT;
6468 if (
Op->isVPOpcode()) {
6469 Mask =
Op.getOperand(1);
6473 VL =
Op.getOperand(2);
6479 MVT FloatEltVT = (EltSize >= 32) ? MVT::f64 :
MVT::f32;
6481 FloatEltVT = MVT::f32;
6488 "Expected legal float type!");
6495 }
else if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF) {
6498 Src = DAG.
getNode(ISD::VP_AND,
DL, VT, Src, Neg, Mask, VL);
6503 if (FloatVT.
bitsGT(VT)) {
6504 if (
Op->isVPOpcode())
6505 FloatVal = DAG.
getNode(ISD::VP_UINT_TO_FP,
DL, FloatVT, Src, Mask, VL);
6514 if (!
Op->isVPOpcode())
6518 MVT ContainerFloatVT =
6520 FloatVal = DAG.
getNode(RISCVISD::VFCVT_RM_F_XU_VL,
DL, ContainerFloatVT,
6521 Src, Mask, RTZRM, VL);
6528 unsigned ShiftAmt = FloatEltVT == MVT::f64 ? 52 : 23;
6532 if (
Op->isVPOpcode()) {
6541 else if (IntVT.
bitsGT(VT))
6546 unsigned ExponentBias = FloatEltVT == MVT::f64 ? 1023 : 127;
6551 if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF)
6552 return DAG.
getNode(ISD::VP_SUB,
DL, VT, Exp,
6557 unsigned Adjust = ExponentBias + (EltSize - 1);
6559 if (
Op->isVPOpcode())
6569 else if (
Op.getOpcode() == ISD::VP_CTLZ)
6570 Res = DAG.
getNode(ISD::VP_UMIN,
DL, VT, Res,
6578 MVT XLenVT = Subtarget.getXLenVT();
6580 MVT SrcVT =
Source.getSimpleValueType();
6589 SrcVT = ContainerVT;
6601 SDValue Res = DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Source, Mask, EVL);
6602 if (
Op->getOpcode() == ISD::VP_CTTZ_ELTS_ZERO_UNDEF)
6620 assert(Load &&
Load->getMemoryVT().isVector() &&
"Expected vector load");
6623 Load->getMemoryVT(),
6624 *
Load->getMemOperand()))
6628 MVT VT =
Op.getSimpleValueType();
6630 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
6631 "Unexpected unaligned RVV load type");
6635 "Expecting equally-sized RVV vector types to be legal");
6637 Load->getPointerInfo(),
Load->getBaseAlign(),
6638 Load->getMemOperand()->getFlags());
6649 assert(Store &&
Store->getValue().getValueType().isVector() &&
6650 "Expected vector store");
6653 Store->getMemoryVT(),
6654 *
Store->getMemOperand()))
6661 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
6662 "Unexpected unaligned RVV store type");
6666 "Expecting equally-sized RVV vector types to be legal");
6667 StoredVal = DAG.
getBitcast(NewVT, StoredVal);
6669 Store->getPointerInfo(),
Store->getBaseAlign(),
6670 Store->getMemOperand()->getFlags());
6675 assert(
Op.getValueType() == MVT::i64 &&
"Unexpected VT");
6704 unsigned ShiftAmt, AddOpc;
6715 MVT VT =
Op.getSimpleValueType();
6719 bool Negate =
false;
6723 if (Index < 0 &&
Imm.isNegative()) {
6740 return DAG.
getNode(ISD::FNEG,
DL, VT, Const);
6746 unsigned IsData =
Op.getConstantOperandVal(4);
6749 if (Subtarget.hasVendorXMIPSCBOP() && !IsData)
6750 return Op.getOperand(0);
6762 if (Subtarget.hasStdExtZtso()) {
6770 return DAG.
getNode(ISD::MEMBARRIER, dl, MVT::Other,
Op.getOperand(0));
6778 return DAG.
getNode(ISD::MEMBARRIER, dl, MVT::Other,
Op.getOperand(0));
6786 MVT VT =
Op.getSimpleValueType();
6787 MVT XLenVT = Subtarget.getXLenVT();
6788 unsigned Check =
Op.getConstantOperandVal(1);
6789 unsigned TDCMask = 0;
6817 MVT VT0 =
Op.getOperand(0).getSimpleValueType();
6822 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6824 VL =
Op.getOperand(3);
6827 VL,
Op->getFlags());
6842 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6844 MVT MaskContainerVT =
6847 VL =
Op.getOperand(3);
6851 SDValue FPCLASS = DAG.
getNode(RISCVISD::FCLASS_VL,
DL, ContainerDstVT, Op0,
6852 Mask, VL,
Op->getFlags());
6854 TDCMaskV = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerDstVT,
6855 DAG.
getUNDEF(ContainerDstVT), TDCMaskV, VL);
6858 DAG.
getNode(RISCVISD::SETCC_VL,
DL, ContainerVT,
6864 TDCMaskV, DAG.
getUNDEF(ContainerDstVT), Mask, VL);
6867 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerDstVT,
6868 DAG.
getUNDEF(ContainerDstVT), SplatZero, VL);
6888 MVT VT =
Op.getSimpleValueType();
6914 Op.getOpcode() == ISD::FMAXIMUM ? RISCVISD::FMAX : RISCVISD::FMIN;
6922 MVT ContainerVT = VT;
6930 if (
Op->isVPOpcode()) {
6931 Mask =
Op.getOperand(2);
6935 VL =
Op.getOperand(3);
6942 SDValue XIsNonNan = DAG.
getNode(RISCVISD::SETCC_VL,
DL, Mask.getValueType(),
6943 {X, X, DAG.getCondCode(ISD::SETOEQ),
6944 DAG.getUNDEF(ContainerVT), Mask, VL});
6945 NewY = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, XIsNonNan,
Y,
X,
6951 SDValue YIsNonNan = DAG.
getNode(RISCVISD::SETCC_VL,
DL, Mask.getValueType(),
6952 {Y, Y, DAG.getCondCode(ISD::SETOEQ),
6953 DAG.getUNDEF(ContainerVT), Mask, VL});
6954 NewX = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, YIsNonNan,
X,
Y,
6959 Op.getOpcode() == ISD::FMAXIMUM ||
Op->getOpcode() == ISD::VP_FMAXIMUM
6960 ? RISCVISD::VFMAX_VL
6961 : RISCVISD::VFMIN_VL;
6963 DAG.
getUNDEF(ContainerVT), Mask, VL);
6971 bool IsFABS =
Op.getOpcode() == ISD::FABS;
6972 assert((IsFABS ||
Op.getOpcode() == ISD::FNEG) &&
6973 "Wrong opcode for lowering FABS or FNEG.");
6976 MVT VT =
Op.getSimpleValueType();
6977 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
6981 DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT,
Op.getOperand(0));
6984 Mask = Mask.sext(Subtarget.
getXLen());
6989 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, Logic);
6997 MVT VT =
Op.getSimpleValueType();
6998 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
7008 if (SignSize == Subtarget.
getXLen())
7009 return DAG.
getNode(ISD::BITCAST,
DL, XLenVT, Sign);
7012 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Sign);
7014 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, XLenVT, Sign);
7016 assert(XLenVT == MVT::i32 &&
"Unexpected type");
7019 return DAG.
getNode(RISCVISD::SplitF64,
DL, {MVT::i32, MVT::i32}, Sign)
7049 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, CopiedSign);
7054#define OP_CASE(NODE) \
7056 return RISCVISD::NODE##_VL;
7057#define VP_CASE(NODE) \
7058 case ISD::VP_##NODE: \
7059 return RISCVISD::NODE##_VL;
7061 switch (
Op.getOpcode()) {
7140 case ISD::VP_CTLZ_ZERO_UNDEF:
7141 return RISCVISD::CTLZ_VL;
7143 case ISD::VP_CTTZ_ZERO_UNDEF:
7144 return RISCVISD::CTTZ_VL;
7147 return RISCVISD::VFMADD_VL;
7149 return RISCVISD::STRICT_VFMADD_VL;
7152 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7153 return RISCVISD::VMAND_VL;
7154 return RISCVISD::AND_VL;
7157 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7158 return RISCVISD::VMOR_VL;
7159 return RISCVISD::OR_VL;
7162 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7163 return RISCVISD::VMXOR_VL;
7164 return RISCVISD::XOR_VL;
7167 return RISCVISD::VZEXT_VL;
7169 return RISCVISD::VSEXT_VL;
7171 return RISCVISD::SETCC_VL;
7173 return RISCVISD::VMERGE_VL;
7174 case ISD::VP_SELECT:
7176 return RISCVISD::VMERGE_VL;
7178 return RISCVISD::SRA_VL;
7180 return RISCVISD::SRL_VL;
7182 return RISCVISD::FSQRT_VL;
7183 case ISD::VP_SIGN_EXTEND:
7184 return RISCVISD::VSEXT_VL;
7185 case ISD::VP_ZERO_EXTEND:
7186 return RISCVISD::VZEXT_VL;
7187 case ISD::VP_FP_TO_SINT:
7188 return RISCVISD::VFCVT_RTZ_X_F_VL;
7189 case ISD::VP_FP_TO_UINT:
7190 return RISCVISD::VFCVT_RTZ_XU_F_VL;
7192 case ISD::FMINIMUMNUM:
7193 case ISD::VP_FMINNUM:
7194 return RISCVISD::VFMIN_VL;
7196 case ISD::FMAXIMUMNUM:
7197 case ISD::VP_FMAXNUM:
7198 return RISCVISD::VFMAX_VL;
7202 case ISD::VP_LLRINT:
7203 return RISCVISD::VFCVT_RM_X_F_VL;
7212 return (
Op.getValueType() == MVT::nxv32f16 &&
7215 Op.getValueType() == MVT::nxv32bf16;
7225 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7226 if (!
Op.getOperand(j).getValueType().isVector()) {
7227 LoOperands[j] =
Op.getOperand(j);
7228 HiOperands[j] =
Op.getOperand(j);
7231 std::tie(LoOperands[j], HiOperands[j]) =
7236 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
7238 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
7251 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7253 std::tie(LoOperands[j], HiOperands[j]) =
7257 if (!
Op.getOperand(j).getValueType().isVector()) {
7258 LoOperands[j] =
Op.getOperand(j);
7259 HiOperands[j] =
Op.getOperand(j);
7262 std::tie(LoOperands[j], HiOperands[j]) =
7267 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
7269 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
7279 auto [EVLLo, EVLHi] =
7280 DAG.
SplitEVL(
Op.getOperand(3),
Op.getOperand(1).getValueType(),
DL);
7284 {Op.getOperand(0), Lo, MaskLo, EVLLo},
Op->getFlags());
7286 {ResLo, Hi, MaskHi, EVLHi},
Op->getFlags());
7303 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7304 if (!
Op.getOperand(j).getValueType().isVector()) {
7305 LoOperands[j] =
Op.getOperand(j);
7306 HiOperands[j] =
Op.getOperand(j);
7309 std::tie(LoOperands[j], HiOperands[j]) =
7314 DAG.
getNode(
Op.getOpcode(),
DL, LoVTs, LoOperands,
Op->getFlags());
7317 DAG.
getNode(
Op.getOpcode(),
DL, HiVTs, HiOperands,
Op->getFlags());
7325RISCVTargetLowering::lowerXAndesBfHCvtBFloat16Load(
SDValue Op,
7327 assert(Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh() &&
7328 "Unexpected bfloat16 load lowering");
7332 EVT MemVT =
LD->getMemoryVT();
7337 LD->getMemOperand());
7345 DAG.
getNode(RISCVISD::NDS_FMV_BF16_X,
DL, MVT::bf16, OrSixteenOne);
7350RISCVTargetLowering::lowerXAndesBfHCvtBFloat16Store(
SDValue Op,
7352 assert(Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh() &&
7353 "Unexpected bfloat16 store lowering");
7358 Subtarget.getXLenVT(),
ST->getValue());
7360 ST->getChain(),
DL, FMV,
ST->getBasePtr(),
7362 ST->getMemOperand());
7367 switch (
Op.getOpcode()) {
7370 "Unimplemented RISCVTargetLowering::LowerOperation Case");
7373 case ISD::ATOMIC_FENCE:
7376 return lowerGlobalAddress(
Op, DAG);
7378 return lowerBlockAddress(
Op, DAG);
7380 return lowerConstantPool(
Op, DAG);
7382 return lowerJumpTable(
Op, DAG);
7384 return lowerGlobalTLSAddress(
Op, DAG);
7388 return lowerConstantFP(
Op, DAG);
7390 return lowerSELECT(
Op, DAG);
7392 return lowerBRCOND(
Op, DAG);
7394 return lowerVASTART(
Op, DAG);
7396 return lowerFRAMEADDR(
Op, DAG);
7398 return lowerRETURNADDR(
Op, DAG);
7400 return lowerShiftLeftParts(
Op, DAG);
7402 return lowerShiftRightParts(
Op, DAG,
true);
7404 return lowerShiftRightParts(
Op, DAG,
false);
7407 if (
Op.getValueType().isFixedLengthVector()) {
7408 assert(Subtarget.hasStdExtZvkb());
7409 return lowerToScalableOp(
Op, DAG);
7411 assert(Subtarget.hasVendorXTHeadBb() &&
7412 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
7413 "Unexpected custom legalization");
7418 case ISD::BITCAST: {
7420 EVT VT =
Op.getValueType();
7423 MVT XLenVT = Subtarget.getXLenVT();
7424 if (Op0VT == MVT::i16 &&
7425 ((VT == MVT::f16 && Subtarget.hasStdExtZfhminOrZhinxmin()) ||
7426 (VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
7428 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, NewOp0);
7430 if (VT == MVT::f32 && Op0VT == MVT::i32 && Subtarget.is64Bit() &&
7431 Subtarget.hasStdExtFOrZfinx()) {
7433 return DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, NewOp0);
7435 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit() &&
7436 Subtarget.hasStdExtDOrZdinx()) {
7439 return DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64,
Lo,
Hi);
7451 "Unexpected types");
7483 return LowerINTRINSIC_WO_CHAIN(
Op, DAG);
7485 return LowerINTRINSIC_W_CHAIN(
Op, DAG);
7487 return LowerINTRINSIC_VOID(
Op, DAG);
7489 return LowerIS_FPCLASS(
Op, DAG);
7491 MVT VT =
Op.getSimpleValueType();
7493 assert(Subtarget.hasStdExtZvbb());
7494 return lowerToScalableOp(
Op, DAG);
7497 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected custom legalization");
7501 return DAG.
getNode(RISCVISD::BREV8,
DL, VT, BSwap);
7507 if (!
Op.getSimpleValueType().isVector())
7509 return lowerVectorTruncLike(
Op, DAG);
7512 if (
Op.getOperand(0).getValueType().isVector() &&
7513 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7514 return lowerVectorMaskExt(
Op, DAG, 1);
7515 if (
Op.getValueType().isScalableVector())
7517 return lowerToScalableOp(
Op, DAG);
7519 if (
Op.getOperand(0).getValueType().isVector() &&
7520 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7521 return lowerVectorMaskExt(
Op, DAG, -1);
7522 if (
Op.getValueType().isScalableVector())
7524 return lowerToScalableOp(
Op, DAG);
7526 return lowerSPLAT_VECTOR_PARTS(
Op, DAG);
7528 return lowerINSERT_VECTOR_ELT(
Op, DAG);
7530 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
7532 MVT VT =
Op.getSimpleValueType();
7540 MVT ContainerVT = VT;
7547 V = DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL, ContainerVT,
7548 DAG.
getUNDEF(ContainerVT), Scalar, VL);
7551 V = DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, ContainerVT,
7552 DAG.
getUNDEF(ContainerVT), Scalar, VL);
7559 MVT XLenVT = Subtarget.getXLenVT();
7560 MVT VT =
Op.getSimpleValueType();
7579 }
else if (
Log2 > 3) {
7583 }
else if ((Val % 8) == 0) {
7601 if (
Op.getValueType() == MVT::f16 && Subtarget.is64Bit() &&
7602 Op.getOperand(1).getValueType() == MVT::i32) {
7606 DAG.
getNode(ISD::FPOWI,
DL, MVT::f32, Op0,
Op.getOperand(1));
7617 case ISD::FP_EXTEND:
7619 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
7622 return lowerStrictFPExtendOrRoundLike(
Op, DAG);
7625 if (
Op.getValueType().isVector() &&
7626 ((
Op.getValueType().getScalarType() == MVT::f16 &&
7627 (Subtarget.hasVInstructionsF16Minimal() &&
7628 !Subtarget.hasVInstructionsF16())) ||
7629 Op.getValueType().getScalarType() == MVT::bf16)) {
7645 Op1.getValueType().isVector() &&
7646 ((Op1.getValueType().getScalarType() == MVT::f16 &&
7647 (Subtarget.hasVInstructionsF16Minimal() &&
7648 !Subtarget.hasVInstructionsF16())) ||
7649 Op1.getValueType().getScalarType() == MVT::bf16)) {
7655 Op1.getValueType().getVectorElementCount());
7658 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), WidenVec);
7668 MVT VT =
Op.getSimpleValueType();
7671 bool IsStrict =
Op->isStrictFPOpcode();
7672 SDValue Src =
Op.getOperand(0 + IsStrict);
7673 MVT SrcVT = Src.getSimpleValueType();
7684 "Unexpected vector element types");
7688 if (EltSize > (2 * SrcEltSize)) {
7700 Op.getOperand(0), Ext);
7704 assert(SrcEltVT == MVT::f16 &&
"Unexpected FP_TO_[US]INT lowering");
7709 auto [FExt, Chain] =
7711 return DAG.
getNode(
Op.getOpcode(),
DL,
Op->getVTList(), Chain, FExt);
7718 if (SrcEltSize > (2 * EltSize)) {
7721 assert(EltVT == MVT::f16 &&
"Unexpected [US]_TO_FP lowering");
7726 Op.getOperand(0), Src);
7741 Op.getOperand(0), Src);
7755 unsigned RVVOpc = 0;
7756 switch (
Op.getOpcode()) {
7760 RVVOpc = RISCVISD::VFCVT_RTZ_X_F_VL;
7763 RVVOpc = RISCVISD::VFCVT_RTZ_XU_F_VL;
7766 RVVOpc = RISCVISD::SINT_TO_FP_VL;
7769 RVVOpc = RISCVISD::UINT_TO_FP_VL;
7772 RVVOpc = RISCVISD::STRICT_VFCVT_RTZ_X_F_VL;
7775 RVVOpc = RISCVISD::STRICT_VFCVT_RTZ_XU_F_VL;
7778 RVVOpc = RISCVISD::STRICT_SINT_TO_FP_VL;
7781 RVVOpc = RISCVISD::STRICT_UINT_TO_FP_VL;
7788 "Expected same element count");
7795 Op.getOperand(0), Src, Mask, VL);
7799 Src = DAG.
getNode(RVVOpc,
DL, ContainerVT, Src, Mask, VL);
7805 case ISD::FP_TO_BF16: {
7808 assert(!Subtarget.isSoftFPABI() &&
"Unexpected custom legalization");
7814 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
7815 if (Subtarget.is64Bit())
7816 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Res);
7819 case ISD::BF16_TO_FP: {
7820 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalization");
7821 MVT VT =
Op.getSimpleValueType();
7826 SDValue Res = Subtarget.is64Bit()
7827 ? DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32,
Op)
7831 return DAG.
getNode(ISD::FP_EXTEND,
DL, VT, Res);
7834 case ISD::STRICT_FP_TO_FP16:
7835 case ISD::FP_TO_FP16: {
7838 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalisation");
7841 bool IsStrict =
Op->isStrictFPOpcode();
7842 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7846 std::tie(Res, Chain) =
7847 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
7848 if (Subtarget.is64Bit())
7849 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Res);
7855 case ISD::STRICT_FP16_TO_FP:
7856 case ISD::FP16_TO_FP: {
7859 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalisation");
7862 bool IsStrict =
Op->isStrictFPOpcode();
7863 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7865 SDValue Arg = Subtarget.is64Bit()
7866 ? DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, Op0)
7869 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
7870 CallOptions,
DL, Chain);
7878 case ISD::FNEARBYINT:
7881 case ISD::FROUNDEVEN:
7888 case ISD::LLROUND: {
7889 if (
Op.getValueType().isVector())
7891 assert(
Op.getOperand(0).getValueType() == MVT::f16 &&
7892 "Unexpected custom legalisation");
7895 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), Ext);
7901 assert(
Op.getOperand(1).getValueType() == MVT::f16 &&
7902 "Unexpected custom legalisation");
7905 {
Op.getOperand(0),
Op.getOperand(1)});
7906 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
7907 {Ext.getValue(1), Ext.getValue(0)});
7909 case ISD::VECREDUCE_ADD:
7910 case ISD::VECREDUCE_UMAX:
7911 case ISD::VECREDUCE_SMAX:
7912 case ISD::VECREDUCE_UMIN:
7913 case ISD::VECREDUCE_SMIN:
7914 return lowerVECREDUCE(
Op, DAG);
7915 case ISD::VECREDUCE_AND:
7916 case ISD::VECREDUCE_OR:
7917 case ISD::VECREDUCE_XOR:
7918 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7919 return lowerVectorMaskVecReduction(
Op, DAG,
false);
7920 return lowerVECREDUCE(
Op, DAG);
7921 case ISD::VECREDUCE_FADD:
7922 case ISD::VECREDUCE_SEQ_FADD:
7923 case ISD::VECREDUCE_FMIN:
7924 case ISD::VECREDUCE_FMAX:
7925 case ISD::VECREDUCE_FMAXIMUM:
7926 case ISD::VECREDUCE_FMINIMUM:
7927 return lowerFPVECREDUCE(
Op, DAG);
7928 case ISD::VP_REDUCE_ADD:
7929 case ISD::VP_REDUCE_UMAX:
7930 case ISD::VP_REDUCE_SMAX:
7931 case ISD::VP_REDUCE_UMIN:
7932 case ISD::VP_REDUCE_SMIN:
7933 case ISD::VP_REDUCE_FADD:
7934 case ISD::VP_REDUCE_SEQ_FADD:
7935 case ISD::VP_REDUCE_FMIN:
7936 case ISD::VP_REDUCE_FMAX:
7937 case ISD::VP_REDUCE_FMINIMUM:
7938 case ISD::VP_REDUCE_FMAXIMUM:
7941 return lowerVPREDUCE(
Op, DAG);
7942 case ISD::VP_REDUCE_AND:
7943 case ISD::VP_REDUCE_OR:
7944 case ISD::VP_REDUCE_XOR:
7945 if (
Op.getOperand(1).getValueType().getVectorElementType() == MVT::i1)
7946 return lowerVectorMaskVecReduction(
Op, DAG,
true);
7947 return lowerVPREDUCE(
Op, DAG);
7948 case ISD::VP_CTTZ_ELTS:
7949 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
7950 return lowerVPCttzElements(
Op, DAG);
7954 DAG.
getUNDEF(ContainerVT), DAG, Subtarget);
7957 return lowerINSERT_SUBVECTOR(
Op, DAG);
7959 return lowerEXTRACT_SUBVECTOR(
Op, DAG);
7961 return lowerVECTOR_DEINTERLEAVE(
Op, DAG);
7963 return lowerVECTOR_INTERLEAVE(
Op, DAG);
7965 return lowerSTEP_VECTOR(
Op, DAG);
7967 return lowerVECTOR_REVERSE(
Op, DAG);
7969 return lowerVECTOR_SPLICE(
Op, DAG);
7971 MVT VT =
Op.getSimpleValueType();
7973 if (!Subtarget.is64Bit() && EltVT == MVT::i64)
7978 MVT VT =
Op.getSimpleValueType();
7980 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
7981 EltVT == MVT::bf16) {
7984 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
7985 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
7986 Elt = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, Subtarget.getXLenVT(),
7989 Elt = DAG.
getNode(ISD::BITCAST,
DL, MVT::i16,
Op.getOperand(0));
7991 return DAG.
getNode(ISD::BITCAST,
DL, VT,
7995 if (EltVT == MVT::i1)
7996 return lowerVectorMaskSplat(
Op, DAG);
8005 MVT VT =
Op.getSimpleValueType();
8006 MVT ContainerVT = VT;
8018 if (
Op.getNumOperands() > 2 &&
8022 size_t HalfNumOps =
Op.getNumOperands() / 2;
8024 Op->ops().take_front(HalfNumOps));
8026 Op->ops().drop_front(HalfNumOps));
8030 unsigned NumOpElts =
8031 Op.getOperand(0).getSimpleValueType().getVectorMinNumElements();
8044 EVT VT = Load->getValueType(0);
8045 if (VT == MVT::f64) {
8046 assert(Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
8047 !Subtarget.is64Bit() &&
"Unexpected custom legalisation");
8051 SDValue BasePtr = Load->getBasePtr();
8052 SDValue Chain = Load->getChain();
8055 DAG.
getLoad(MVT::i32,
DL, Chain, BasePtr, Load->getPointerInfo(),
8056 Load->getBaseAlign(), Load->getMemOperand()->getFlags());
8059 MVT::i32,
DL, Chain, BasePtr, Load->getPointerInfo().getWithOffset(4),
8060 Load->getBaseAlign(), Load->getMemOperand()->getFlags());
8068 if (VT == MVT::bf16)
8069 return lowerXAndesBfHCvtBFloat16Load(
Op, DAG);
8074 MVT XLenVT = Subtarget.getXLenVT();
8077 unsigned NumElts = Sz / (NF * 8);
8078 int Log2LMUL =
Log2_64(NumElts) - 3;
8081 Flag.setNoUnsignedWrap(
true);
8083 SDValue BasePtr = Load->getBasePtr();
8091 for (
unsigned i = 0; i < NF; ++i) {
8096 Ret = DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VT, Ret, LoadVal,
8104 if (
auto V = expandUnalignedRVVLoad(
Op, DAG))
8106 if (
Op.getValueType().isFixedLengthVector())
8107 return lowerFixedLengthVectorLoadToRVV(
Op, DAG);
8112 SDValue StoredVal = Store->getValue();
8114 if (VT == MVT::f64) {
8115 assert(Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
8116 !Subtarget.is64Bit() &&
"Unexpected custom legalisation");
8120 SDValue BasePtr = Store->getBasePtr();
8121 SDValue Chain = Store->getChain();
8123 DAG.
getVTList(MVT::i32, MVT::i32), StoredVal);
8126 Store->getPointerInfo(), Store->getBaseAlign(),
8127 Store->getMemOperand()->getFlags());
8130 Store->getPointerInfo().getWithOffset(4),
8131 Store->getBaseAlign(),
8132 Store->getMemOperand()->getFlags());
8135 if (VT == MVT::i64) {
8136 assert(Subtarget.hasStdExtZilsd() && !Subtarget.is64Bit() &&
8137 "Unexpected custom legalisation");
8138 if (Store->isTruncatingStore())
8141 if (!Subtarget.enableUnalignedScalarMem() && Store->getAlign() < 8)
8152 {Store->getChain(), Lo, Hi, Store->getBasePtr()}, MVT::i64,
8153 Store->getMemOperand());
8156 if (VT == MVT::bf16)
8157 return lowerXAndesBfHCvtBFloat16Store(
Op, DAG);
8162 MVT XLenVT = Subtarget.getXLenVT();
8165 unsigned NumElts = Sz / (NF * 8);
8166 int Log2LMUL =
Log2_64(NumElts) - 3;
8169 Flag.setNoUnsignedWrap(
true);
8171 SDValue Chain = Store->getChain();
8172 SDValue BasePtr = Store->getBasePtr();
8179 for (
unsigned i = 0; i < NF; ++i) {
8181 DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL,
8184 Ret = DAG.
getStore(Chain,
DL, Extract, BasePtr,
8186 Store->getBaseAlign(),
8187 Store->getMemOperand()->getFlags());
8188 Chain = Ret.getValue(0);
8194 if (
auto V = expandUnalignedRVVStore(
Op, DAG))
8196 if (
Op.getOperand(1).getValueType().isFixedLengthVector())
8197 return lowerFixedLengthVectorStoreToRVV(
Op, DAG);
8202 return lowerMaskedLoad(
Op, DAG);
8203 case ISD::VP_LOAD_FF:
8204 return lowerLoadFF(
Op, DAG);
8207 return lowerMaskedStore(
Op, DAG);
8209 return lowerVectorCompress(
Op, DAG);
8218 EVT VT =
Op.getValueType();
8229 MVT OpVT =
Op.getOperand(0).getSimpleValueType();
8231 MVT VT =
Op.getSimpleValueType();
8236 "Unexpected CondCode");
8269 return DAG.
getSetCC(
DL, VT, RHS, LHS, CCVal);
8275 return lowerToScalableOp(
Op, DAG);
8292 return lowerToScalableOp(
Op, DAG);
8296 if (
Op.getSimpleValueType().isFixedLengthVector())
8297 return lowerToScalableOp(
Op, DAG);
8299 assert(
Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.is64Bit() &&
8300 "Unexpected custom legalisation");
8304 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
8315 case ISD::FMINIMUMNUM:
8316 case ISD::FMAXIMUMNUM:
8332 return lowerToScalableOp(
Op, DAG);
8336 EVT VT =
Op->getValueType(0);
8351 return lowerABS(
Op, DAG);
8356 if (Subtarget.hasStdExtZvbb())
8357 return lowerToScalableOp(
Op, DAG);
8359 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8361 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
8365 return lowerToScalableOp(
Op, DAG);
8374 return lowerToScalableOp(
Op, DAG);
8377 return lowerVectorStrictFSetcc(
Op, DAG);
8387 case ISD::VP_GATHER:
8388 return lowerMaskedGather(
Op, DAG);
8390 case ISD::VP_SCATTER:
8391 return lowerMaskedScatter(
Op, DAG);
8393 return lowerGET_ROUNDING(
Op, DAG);
8394 case ISD::SET_ROUNDING:
8395 return lowerSET_ROUNDING(
Op, DAG);
8396 case ISD::GET_FPENV:
8397 return lowerGET_FPENV(
Op, DAG);
8398 case ISD::SET_FPENV:
8399 return lowerSET_FPENV(
Op, DAG);
8400 case ISD::RESET_FPENV:
8401 return lowerRESET_FPENV(
Op, DAG);
8402 case ISD::GET_FPMODE:
8403 return lowerGET_FPMODE(
Op, DAG);
8404 case ISD::SET_FPMODE:
8405 return lowerSET_FPMODE(
Op, DAG);
8406 case ISD::RESET_FPMODE:
8407 return lowerRESET_FPMODE(
Op, DAG);
8409 return lowerEH_DWARF_CFA(
Op, DAG);
8411 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
8412 return lowerVPMergeMask(
Op, DAG);
8414 case ISD::VP_SELECT:
8422 case ISD::VP_UADDSAT:
8423 case ISD::VP_USUBSAT:
8424 case ISD::VP_SADDSAT:
8425 case ISD::VP_SSUBSAT:
8427 case ISD::VP_LLRINT:
8428 return lowerVPOp(
Op, DAG);
8432 return lowerLogicVPOp(
Op, DAG);
8441 case ISD::VP_FMINNUM:
8442 case ISD::VP_FMAXNUM:
8443 case ISD::VP_FCOPYSIGN:
8450 return lowerVPOp(
Op, DAG);
8451 case ISD::VP_IS_FPCLASS:
8452 return LowerIS_FPCLASS(
Op, DAG);
8453 case ISD::VP_SIGN_EXTEND:
8454 case ISD::VP_ZERO_EXTEND:
8455 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
8456 return lowerVPExtMaskOp(
Op, DAG);
8457 return lowerVPOp(
Op, DAG);
8458 case ISD::VP_TRUNCATE:
8459 return lowerVectorTruncLike(
Op, DAG);
8460 case ISD::VP_FP_EXTEND:
8461 case ISD::VP_FP_ROUND:
8462 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
8463 case ISD::VP_SINT_TO_FP:
8464 case ISD::VP_UINT_TO_FP:
8465 if (
Op.getValueType().isVector() &&
8466 ((
Op.getValueType().getScalarType() == MVT::f16 &&
8467 (Subtarget.hasVInstructionsF16Minimal() &&
8468 !Subtarget.hasVInstructionsF16())) ||
8469 Op.getValueType().getScalarType() == MVT::bf16)) {
8482 case ISD::VP_FP_TO_SINT:
8483 case ISD::VP_FP_TO_UINT:
8485 Op1.getValueType().isVector() &&
8486 ((Op1.getValueType().getScalarType() == MVT::f16 &&
8487 (Subtarget.hasVInstructionsF16Minimal() &&
8488 !Subtarget.hasVInstructionsF16())) ||
8489 Op1.getValueType().getScalarType() == MVT::bf16)) {
8495 Op1.getValueType().getVectorElementCount());
8499 {WidenVec, Op.getOperand(1), Op.getOperand(2)});
8501 return lowerVPFPIntConvOp(
Op, DAG);
8505 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
8506 return lowerVPSetCCMaskOp(
Op, DAG);
8512 case ISD::VP_BITREVERSE:
8514 return lowerVPOp(
Op, DAG);
8516 case ISD::VP_CTLZ_ZERO_UNDEF:
8517 if (Subtarget.hasStdExtZvbb())
8518 return lowerVPOp(
Op, DAG);
8519 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8521 case ISD::VP_CTTZ_ZERO_UNDEF:
8522 if (Subtarget.hasStdExtZvbb())
8523 return lowerVPOp(
Op, DAG);
8524 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8526 return lowerVPOp(
Op, DAG);
8527 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
8528 return lowerVPStridedLoad(
Op, DAG);
8529 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
8530 return lowerVPStridedStore(
Op, DAG);
8532 case ISD::VP_FFLOOR:
8534 case ISD::VP_FNEARBYINT:
8535 case ISD::VP_FROUND:
8536 case ISD::VP_FROUNDEVEN:
8537 case ISD::VP_FROUNDTOZERO:
8541 case ISD::VP_FMAXIMUM:
8542 case ISD::VP_FMINIMUM:
8546 case ISD::EXPERIMENTAL_VP_SPLICE:
8547 return lowerVPSpliceExperimental(
Op, DAG);
8548 case ISD::EXPERIMENTAL_VP_REVERSE:
8549 return lowerVPReverseExperimental(
Op, DAG);
8550 case ISD::EXPERIMENTAL_VP_SPLAT:
8551 return lowerVPSplatExperimental(
Op, DAG);
8554 "llvm.clear_cache only needs custom lower on Linux targets");
8557 return emitFlushICache(DAG,
Op.getOperand(0),
Op.getOperand(1),
8558 Op.getOperand(2), Flags,
DL);
8560 case ISD::DYNAMIC_STACKALLOC:
8561 return lowerDYNAMIC_STACKALLOC(
Op, DAG);
8562 case ISD::INIT_TRAMPOLINE:
8563 return lowerINIT_TRAMPOLINE(
Op, DAG);
8564 case ISD::ADJUST_TRAMPOLINE:
8565 return lowerADJUST_TRAMPOLINE(
Op, DAG);
8566 case ISD::PARTIAL_REDUCE_UMLA:
8567 case ISD::PARTIAL_REDUCE_SMLA:
8568 case ISD::PARTIAL_REDUCE_SUMLA:
8569 return lowerPARTIAL_REDUCE_MLA(
Op, DAG);
8576 MakeLibCallOptions CallOptions;
8577 std::pair<SDValue, SDValue> CallResult =
8578 makeLibCall(DAG, RTLIB::RISCV_FLUSH_ICACHE, MVT::isVoid,
8579 {Start, End, Flags}, CallOptions,
DL, InChain);
8582 return CallResult.second;
8587 if (!Subtarget.is64Bit())
8595 std::unique_ptr<MCCodeEmitter> CodeEmitter(
8623 const bool HasCFBranch =
8624 Subtarget.hasStdExtZicfilp() &&
8626 "cf-protection-branch");
8627 const unsigned StaticChainIdx = HasCFBranch ? 5 : 4;
8628 const unsigned StaticChainOffset = StaticChainIdx * 4;
8629 const unsigned FunctionAddressOffset = StaticChainOffset + 8;
8633 auto GetEncoding = [&](
const MCInst &MC) {
8636 CodeEmitter->encodeInstruction(MC, CB, Fixups, *STI);
8643 SmallVector<uint32_t> Encodings;
8648 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X7).addImm(0)),
8652 GetEncoding(MCInstBuilder(RISCV::LD)
8655 .addImm(FunctionAddressOffset)),
8658 GetEncoding(MCInstBuilder(RISCV::LD)
8661 .addImm(StaticChainOffset)),
8664 GetEncoding(MCInstBuilder(RISCV::JALR)
8672 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X0).addImm(0)),
8675 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X28).addImm(0)),
8679 GetEncoding(MCInstBuilder(RISCV::LD)
8682 .addImm(FunctionAddressOffset - 4)),
8685 GetEncoding(MCInstBuilder(RISCV::LD)
8688 .addImm(StaticChainOffset - 4)),
8691 GetEncoding(MCInstBuilder(RISCV::JALR)
8703 Root, dl, DAG.
getConstant(Encoding, dl, MVT::i64), Addr,
8704 MachinePointerInfo(TrmpAddr, Idx * 4), MVT::i32));
8708 SDValue FunctionAddress =
Op.getOperand(2);
8712 struct OffsetValuePair {
8716 } OffsetValues[] = {
8717 {StaticChainOffset, StaticChain},
8718 {FunctionAddressOffset, FunctionAddress},
8720 for (
auto &OffsetValue : OffsetValues) {
8723 DAG.
getConstant(OffsetValue.Offset, dl, MVT::i64));
8724 OffsetValue.Addr = Addr;
8726 DAG.
getStore(Root, dl, OffsetValue.Value, Addr,
8727 MachinePointerInfo(TrmpAddr, OffsetValue.Offset)));
8730 assert(OutChains.
size() == StaticChainIdx + 2 &&
8731 "Size of OutChains mismatch");
8736 SDValue EndOfTrmp = OffsetValues[0].Addr;
8747 if (!Subtarget.is64Bit())
8750 return Op.getOperand(0);
8759 MVT VT =
Op.getSimpleValueType();
8765 MVT ArgVT =
A.getSimpleValueType();
8766 assert(ArgVT ==
B.getSimpleValueType() &&
8776 MVT ContainerVT = VT;
8785 switch (
Op.getOpcode()) {
8786 case ISD::PARTIAL_REDUCE_SMLA:
8787 Opc = RISCVISD::VQDOT_VL;
8789 case ISD::PARTIAL_REDUCE_UMLA:
8790 Opc = RISCVISD::VQDOTU_VL;
8792 case ISD::PARTIAL_REDUCE_SUMLA:
8793 Opc = RISCVISD::VQDOTSU_VL;
8819 N->getOffset(), Flags);
8848template <
class NodeTy>
8850 bool IsLocal,
bool IsExternWeak)
const {
8860 if (IsLocal && !Subtarget.allowTaggedGlobals())
8864 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
8887 if (Subtarget.hasVendorXqcili()) {
8891 return DAG.
getNode(RISCVISD::QC_E_LI,
DL, Ty, Addr);
8898 return DAG.
getNode(RISCVISD::ADD_LO,
DL, Ty, MNHi, AddrLo);
8922 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
8930 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
8938 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
8939 const GlobalValue *GV =
N->getGlobal();
8947 return getAddr(
N, DAG);
8954 return getAddr(
N, DAG);
8961 return getAddr(
N, DAG);
8966 bool UseGOT)
const {
8969 const GlobalValue *GV =
N->getGlobal();
8970 MVT XLenVT = Subtarget.getXLenVT();
9007 DAG.
getNode(RISCVISD::ADD_TPREL,
DL, Ty, MNHi, TPReg, AddrAdd);
9008 return DAG.
getNode(RISCVISD::ADD_LO,
DL, Ty, MNAdd, AddrLo);
9016 const GlobalValue *GV =
N->getGlobal();
9027 Args.emplace_back(Load, CallTy);
9030 TargetLowering::CallLoweringInfo CLI(DAG);
9044 const GlobalValue *GV =
N->getGlobal();
9060 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
9074 Addr = getStaticTLSAddr(
N, DAG,
false);
9077 Addr = getStaticTLSAddr(
N, DAG,
true);
9082 : getDynamicTLSAddr(
N, DAG);
9099 if (
LHS == LHS2 &&
RHS == RHS2) {
9104 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
9112 return std::nullopt;
9124 MVT VT =
N->getSimpleValueType(0);
9151 uint64_t TrueM1 = TrueC->getZExtValue() - 1;
9153 unsigned ShAmount =
Log2_64(TrueM1);
9155 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, CondV,
9171 if (~TrueVal == FalseVal) {
9211 if (Subtarget.hasShortForwardBranchOpt())
9214 unsigned SelOpNo = 0;
9224 unsigned ConstSelOpNo = 1;
9225 unsigned OtherSelOpNo = 2;
9232 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
9237 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
9243 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
9245 std::swap(NewConstOps[0], NewConstOps[1]);
9257 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
9259 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
9262 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
9263 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
9272 MVT VT =
Op.getSimpleValueType();
9273 MVT XLenVT = Subtarget.getXLenVT();
9294 return DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV);
9297 return DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV);
9301 auto getNotOperand = [](
const SDValue &
Op) -> std::optional<const SDValue> {
9302 using namespace llvm::SDPatternMatch;
9307 return std::nullopt;
9313 auto NotOperand = (TrueV.
getOperand(0) == FalseV)
9315 : getNotOperand(TrueV.getOperand(0));
9318 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, *NotOperand, CondV);
9324 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV));
9331 auto NotOperand = (FalseV.
getOperand(0) == TrueV)
9333 : getNotOperand(FalseV.getOperand(0));
9336 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, *NotOperand, CondV);
9342 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV));
9359 int64_t TrueImm =
TrueVal.getSExtValue();
9360 int64_t FalseImm =
FalseVal.getSExtValue();
9379 if ((TrueVal - FalseVal).isPowerOf2() &&
FalseVal.isSignedIntN(12)) {
9384 if ((FalseVal - TrueVal).isPowerOf2() &&
TrueVal.isSignedIntN(12)) {
9391 auto getCost = [&](
const APInt &Delta,
const APInt &Addend) {
9393 Delta, Subtarget.getXLen(), Subtarget,
true);
9395 if (Addend.isSignedIntN(12))
9398 Addend, Subtarget.getXLen(), Subtarget,
true);
9399 return AddendCost + DeltaCost;
9401 bool IsCZERO_NEZ =
getCost(FalseVal - TrueVal, TrueVal) <=
9402 getCost(TrueVal - FalseVal, FalseVal);
9404 IsCZERO_NEZ ? FalseVal - TrueVal : TrueVal - FalseVal,
DL, VT);
9406 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9407 DL, VT, LHSVal, CondV);
9415 SDValue ConstVal = IsCZERO_NEZ ? TrueV : FalseV;
9416 SDValue RegV = IsCZERO_NEZ ? FalseV : TrueV;
9419 if (RawConstVal == -0x800) {
9422 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9423 DL, VT, XorOp, CondV);
9431 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9432 DL, VT, SubOp, CondV);
9439 if (!Subtarget.hasConditionalMoveFusion())
9442 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV),
9443 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV),
9447 if (
Op.hasOneUse()) {
9448 unsigned UseOpc =
Op->user_begin()->getOpcode();
9450 SDNode *BinOp = *
Op->user_begin();
9457 return lowerSELECT(NewSel, DAG);
9511 if (TrueVal - 1 == FalseVal)
9513 if (TrueVal + 1 == FalseVal)
9520 RHS == TrueV &&
LHS == FalseV) {
9551 MVT XLenVT = Subtarget.getXLenVT();
9562 return DAG.
getNode(RISCVISD::BR_CC,
DL,
Op.getValueType(),
Op.getOperand(0),
9563 LHS,
RHS, TargetCC,
Op.getOperand(2));
9566 return DAG.
getNode(RISCVISD::BR_CC,
DL,
Op.getValueType(),
Op.getOperand(0),
9573 RISCVMachineFunctionInfo *FuncInfo = MF.
getInfo<RISCVMachineFunctionInfo>();
9583 MachinePointerInfo(SV));
9588 const RISCVRegisterInfo &RI = *Subtarget.getRegisterInfo();
9593 int XLenInBytes = Subtarget.getXLen() / 8;
9595 EVT VT =
Op.getValueType();
9598 unsigned Depth =
Op.getConstantOperandVal(0);
9600 int Offset = -(XLenInBytes * 2);
9612 const RISCVRegisterInfo &RI = *Subtarget.getRegisterInfo();
9616 MVT XLenVT = Subtarget.getXLenVT();
9617 int XLenInBytes = Subtarget.getXLen() / 8;
9619 EVT VT =
Op.getValueType();
9621 unsigned Depth =
Op.getConstantOperandVal(0);
9623 int Off = -XLenInBytes;
9624 SDValue FrameAddr = lowerFRAMEADDR(
Op, DAG);
9628 MachinePointerInfo());
9643 EVT VT =
Lo.getValueType();
9682 EVT VT =
Lo.getValueType();
9733 MVT VT =
Op.getSimpleValueType();
9738 return DAG.
getNode(RISCVISD::VMSET_VL,
DL, VT, VL);
9742 return DAG.
getNode(RISCVISD::VMCLR_VL,
DL, VT, VL);
9759 MVT VecVT =
Op.getSimpleValueType();
9761 "Unexpected SPLAT_VECTOR_PARTS lowering");
9767 MVT ContainerVT = VecVT;
9787 int64_t ExtTrueVal)
const {
9789 MVT VecVT =
Op.getSimpleValueType();
9792 assert(Src.getValueType().isVector() &&
9793 Src.getValueType().getVectorElementType() == MVT::i1);
9813 MVT XLenVT = Subtarget.getXLenVT();
9819 if (
Xor.getOpcode() == RISCVISD::VMXOR_VL) {
9831 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9832 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
9833 SplatTrueVal = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9834 DAG.
getUNDEF(ContainerVT), SplatTrueVal, VL);
9836 DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, CC, SplatTrueVal,
9837 SplatZero, DAG.
getUNDEF(ContainerVT), VL);
9847 bool IsVPTrunc =
Op.getOpcode() == ISD::VP_TRUNCATE;
9849 EVT MaskVT =
Op.getValueType();
9852 "Unexpected type for vector mask lowering");
9854 MVT VecVT = Src.getSimpleValueType();
9858 VL =
Op.getOperand(2);
9861 MVT ContainerVT = VecVT;
9867 MVT MaskContainerVT =
9874 std::tie(Mask, VL) =
9881 SplatOne = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9882 DAG.
getUNDEF(ContainerVT), SplatOne, VL);
9883 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9884 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
9887 SDValue Trunc = DAG.
getNode(RISCVISD::AND_VL,
DL, ContainerVT, Src, SplatOne,
9888 DAG.
getUNDEF(ContainerVT), Mask, VL);
9889 Trunc = DAG.
getNode(RISCVISD::SETCC_VL,
DL, MaskContainerVT,
9899 unsigned Opc =
Op.getOpcode();
9900 bool IsVPTrunc =
Opc == ISD::VP_TRUNCATE;
9903 MVT VT =
Op.getSimpleValueType();
9905 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
9909 return lowerVectorMaskTruncLike(
Op, DAG);
9917 MVT SrcVT = Src.getSimpleValueType();
9922 "Unexpected vector truncate lowering");
9924 MVT ContainerVT = SrcVT;
9928 VL =
Op.getOperand(2);
9941 std::tie(Mask, VL) =
9947 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL_SSAT;
9949 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL_USAT;
9951 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL;
9957 }
while (SrcEltVT != DstEltVT);
9966RISCVTargetLowering::lowerStrictFPExtendOrRoundLike(
SDValue Op,
9971 MVT VT =
Op.getSimpleValueType();
9972 MVT SrcVT = Src.getSimpleValueType();
9973 MVT ContainerVT = VT;
9992 ? RISCVISD::STRICT_FP_EXTEND_VL
9993 : RISCVISD::STRICT_VFNCVT_ROD_VL;
9996 Chain, Src, Mask, VL);
9997 Chain = Src.getValue(1);
10001 ? RISCVISD::STRICT_FP_EXTEND_VL
10002 : RISCVISD::STRICT_FP_ROUND_VL;
10004 Chain, Src, Mask, VL);
10015RISCVTargetLowering::lowerVectorFPExtendOrRoundLike(
SDValue Op,
10018 Op.getOpcode() == ISD::VP_FP_ROUND ||
Op.getOpcode() == ISD::VP_FP_EXTEND;
10020 Op.getOpcode() == ISD::VP_FP_EXTEND ||
Op.getOpcode() == ISD::FP_EXTEND;
10025 MVT VT =
Op.getSimpleValueType();
10027 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
10030 MVT SrcVT = Src.getSimpleValueType();
10032 bool IsDirectExtend =
10040 bool IsDirectConv = IsDirectExtend || IsDirectTrunc;
10047 MVT ContainerVT = VT;
10050 Mask =
Op.getOperand(1);
10051 VL =
Op.getOperand(2);
10065 std::tie(Mask, VL) =
10068 unsigned ConvOpc = IsExtend ? RISCVISD::FP_EXTEND_VL : RISCVISD::FP_ROUND_VL;
10070 if (IsDirectConv) {
10071 Src = DAG.
getNode(ConvOpc,
DL, ContainerVT, Src, Mask, VL);
10077 unsigned InterConvOpc =
10078 IsExtend ? RISCVISD::FP_EXTEND_VL : RISCVISD::VFNCVT_ROD_VL;
10082 DAG.
getNode(InterConvOpc,
DL, InterVT, Src, Mask, VL);
10084 DAG.
getNode(ConvOpc,
DL, ContainerVT, IntermediateConv, Mask, VL);
10095static std::optional<MVT>
10101 const unsigned MinVLMAX = VectorBitsMin / EltSize;
10103 if (MaxIdx < MinVLMAX)
10105 else if (MaxIdx < MinVLMAX * 2)
10108 else if (MaxIdx < MinVLMAX * 4)
10113 return std::nullopt;
10121 return isUInt<5>(IdxC->getZExtValue());
10133 MVT VecVT =
Op.getSimpleValueType();
10134 MVT XLenVT = Subtarget.getXLenVT();
10149 if ((ValVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
10150 ValVT == MVT::bf16) {
10155 DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Val), Idx);
10159 MVT ContainerVT = VecVT;
10169 std::optional<unsigned> AlignedIdx;
10171 const unsigned OrigIdx = IdxC->getZExtValue();
10174 DL, DAG, Subtarget)) {
10175 ContainerVT = *ShrunkVT;
10183 if (
auto VLEN = Subtarget.getRealVLen(); VLEN && ContainerVT.
bitsGT(M1VT)) {
10186 unsigned RemIdx = OrigIdx % ElemsPerVReg;
10187 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
10190 ContainerVT = M1VT;
10197 bool IsLegalInsert = Subtarget.is64Bit() || Val.
getValueType() != MVT::i64;
10205 IsLegalInsert =
true;
10214 if (IsLegalInsert) {
10216 VecVT.
isFloatingPoint() ? RISCVISD::VFMV_S_F_VL : RISCVISD::VMV_S_X_VL;
10220 Vec = DAG.
getNode(
Opc,
DL, ContainerVT, Vec, Val, VL);
10230 if (Subtarget.hasVendorXRivosVisni() && VecVT.
isInteger() &&
10235 Vec = DAG.
getNode(RISCVISD::RI_VINSERT_VL,
DL, ContainerVT, Vec, Val, Idx,
10251 std::tie(ValLo, ValHi) = DAG.
SplitScalar(Val,
DL, MVT::i32, MVT::i32);
10252 MVT I32ContainerVT =
10262 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10263 Vec, Vec, ValLo, I32Mask, InsertI64VL);
10267 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10268 Tail, ValInVec, ValHi, I32Mask, InsertI64VL);
10270 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
10281 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10283 DAG.
getUNDEF(I32ContainerVT), ValLo,
10284 I32Mask, InsertI64VL);
10285 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10286 DAG.
getUNDEF(I32ContainerVT), ValInVec, ValHi,
10287 I32Mask, InsertI64VL);
10289 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
10302 Idx, Mask, InsertVL, Policy);
10320 EVT EltVT =
Op.getValueType();
10322 MVT XLenVT = Subtarget.getXLenVT();
10327 MVT ContainerVT = VecVT;
10334 DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Vec, Mask, VL);
10341 if (NumElts >= 8) {
10343 unsigned WidenVecLen;
10346 unsigned MaxEEW = Subtarget.getELen();
10351 "the number of elements should be power of 2");
10355 ExtractBitIdx = Idx;
10357 WideEltVT = LargestEltVT;
10360 ExtractElementIdx = DAG.
getNode(
10369 Vec = DAG.
getNode(ISD::BITCAST,
DL, WideVT, Vec);
10371 Vec, ExtractElementIdx);
10386 if ((EltVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
10387 EltVT == MVT::bf16) {
10393 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, EltVT, IntExtract);
10397 MVT ContainerVT = VecVT;
10407 const auto VLen = Subtarget.getRealVLen();
10409 IdxC && VLen && VecVT.
getSizeInBits().getKnownMinValue() > *VLen) {
10411 unsigned OrigIdx = IdxC->getZExtValue();
10414 unsigned RemIdx = OrigIdx % ElemsPerVReg;
10415 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
10416 unsigned ExtractIdx =
10420 ContainerVT = M1VT;
10425 std::optional<uint64_t> MaxIdx;
10429 MaxIdx = IdxC->getZExtValue();
10431 if (
auto SmallerVT =
10433 ContainerVT = *SmallerVT;
10440 if (Subtarget.hasVendorXRivosVisni() && EltVT.
isInteger() &&
10468 DAG.
getUNDEF(ContainerVT), Vec, Idx, Mask, VL);
10487 "Unexpected opcode");
10494 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
10499 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
10500 if (!
II || !
II->hasScalarOperand())
10503 unsigned SplatOp =
II->ScalarOperand + 1 + HasChain;
10504 assert(SplatOp <
Op.getNumOperands());
10516 if (OpVT.
bitsLT(XLenVT)) {
10523 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
10533 assert(
II->ScalarOperand > 0 &&
"Unexpected splat operand!");
10534 MVT VT =
Op.getOperand(SplatOp - 1).getSimpleValueType();
10537 assert(XLenVT == MVT::i32 && OpVT == MVT::i64 &&
10548 case Intrinsic::riscv_vslide1up:
10549 case Intrinsic::riscv_vslide1down:
10550 case Intrinsic::riscv_vslide1up_mask:
10551 case Intrinsic::riscv_vslide1down_mask: {
10553 unsigned NumOps =
Op.getNumOperands();
10554 bool IsMasked =
NumOps == 7;
10560 std::tie(ScalarLo, ScalarHi) =
10569 const auto [MinVLMAX, MaxVLMAX] =
10573 if (AVLInt <= MinVLMAX) {
10575 }
else if (AVLInt >= 2 * MaxVLMAX) {
10609 if (IntNo == Intrinsic::riscv_vslide1up ||
10610 IntNo == Intrinsic::riscv_vslide1up_mask) {
10611 Vec = DAG.
getNode(RISCVISD::VSLIDE1UP_VL,
DL, I32VT, Passthru, Vec,
10612 ScalarHi, I32Mask, I32VL);
10613 Vec = DAG.
getNode(RISCVISD::VSLIDE1UP_VL,
DL, I32VT, Passthru, Vec,
10614 ScalarLo, I32Mask, I32VL);
10616 Vec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32VT, Passthru, Vec,
10617 ScalarLo, I32Mask, I32VL);
10618 Vec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32VT, Passthru, Vec,
10619 ScalarHi, I32Mask, I32VL);
10637 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, Mask, Vec, MaskedOff,
10641 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, Mask, Vec, MaskedOff,
10668 const unsigned ElementWidth = 8;
10673 [[maybe_unused]]
unsigned MinVF =
10676 [[maybe_unused]]
unsigned VF =
N->getConstantOperandVal(2);
10680 bool Fractional = VF < LMul1VF;
10681 unsigned LMulVal = Fractional ? LMul1VF / VF : VF / LMul1VF;
10702 MVT ContainerVT = OpVT;
10710 SDValue Res = DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Op0, Mask, VL);
10718 return DAG.
getSelect(
DL, XLenVT, Setcc, VL, Res);
10729 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
10733 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
10734 if (!
II || !
II->hasScalarOperand())
10737 unsigned SplatOp =
II->ScalarOperand + 1;
10738 assert(SplatOp <
Op.getNumOperands());
10750 if (OpVT.
bitsLT(XLenVT)) {
10753 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
10764 EVT ValType = V.getValueType();
10765 if (ValType.isVector() && ValType.isFloatingPoint()) {
10768 ValType.getVectorElementCount());
10771 if (ValType.isFixedLengthVector()) {
10773 DAG, V.getSimpleValueType(), Subtarget);
10789 unsigned IntNo =
Op.getConstantOperandVal(0);
10791 MVT XLenVT = Subtarget.getXLenVT();
10796 case Intrinsic::riscv_tuple_insert: {
10801 return DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL,
Op.getValueType(), Vec,
10804 case Intrinsic::riscv_tuple_extract: {
10808 return DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL,
Op.getValueType(), Vec,
10811 case Intrinsic::thread_pointer: {
10815 case Intrinsic::riscv_orc_b:
10816 case Intrinsic::riscv_brev8:
10817 case Intrinsic::riscv_sha256sig0:
10818 case Intrinsic::riscv_sha256sig1:
10819 case Intrinsic::riscv_sha256sum0:
10820 case Intrinsic::riscv_sha256sum1:
10821 case Intrinsic::riscv_sm3p0:
10822 case Intrinsic::riscv_sm3p1: {
10825 case Intrinsic::riscv_orc_b:
Opc = RISCVISD::ORC_B;
break;
10826 case Intrinsic::riscv_brev8:
Opc = RISCVISD::BREV8;
break;
10827 case Intrinsic::riscv_sha256sig0:
Opc = RISCVISD::SHA256SIG0;
break;
10828 case Intrinsic::riscv_sha256sig1:
Opc = RISCVISD::SHA256SIG1;
break;
10829 case Intrinsic::riscv_sha256sum0:
Opc = RISCVISD::SHA256SUM0;
break;
10830 case Intrinsic::riscv_sha256sum1:
Opc = RISCVISD::SHA256SUM1;
break;
10831 case Intrinsic::riscv_sm3p0:
Opc = RISCVISD::SM3P0;
break;
10832 case Intrinsic::riscv_sm3p1:
Opc = RISCVISD::SM3P1;
break;
10837 case Intrinsic::riscv_sm4ks:
10838 case Intrinsic::riscv_sm4ed: {
10840 IntNo == Intrinsic::riscv_sm4ks ? RISCVISD::SM4KS : RISCVISD::SM4ED;
10845 case Intrinsic::riscv_zip:
10846 case Intrinsic::riscv_unzip: {
10848 IntNo == Intrinsic::riscv_zip ? RISCVISD::ZIP : RISCVISD::UNZIP;
10851 case Intrinsic::riscv_mopr:
10852 return DAG.
getNode(RISCVISD::MOP_R,
DL, XLenVT,
Op.getOperand(1),
10855 case Intrinsic::riscv_moprr: {
10856 return DAG.
getNode(RISCVISD::MOP_RR,
DL, XLenVT,
Op.getOperand(1),
10857 Op.getOperand(2),
Op.getOperand(3));
10859 case Intrinsic::riscv_clmul:
10860 return DAG.
getNode(RISCVISD::CLMUL,
DL, XLenVT,
Op.getOperand(1),
10862 case Intrinsic::riscv_clmulh:
10863 case Intrinsic::riscv_clmulr: {
10865 IntNo == Intrinsic::riscv_clmulh ? RISCVISD::CLMULH : RISCVISD::CLMULR;
10868 case Intrinsic::experimental_get_vector_length:
10870 case Intrinsic::experimental_cttz_elts:
10872 case Intrinsic::riscv_vmv_x_s: {
10876 case Intrinsic::riscv_vfmv_f_s:
10878 case Intrinsic::riscv_vmv_v_x:
10880 Op.getOperand(3),
Op.getSimpleValueType(),
DL, DAG,
10882 case Intrinsic::riscv_vfmv_v_f:
10883 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL,
Op.getValueType(),
10884 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
10885 case Intrinsic::riscv_vmv_s_x: {
10888 if (
Scalar.getValueType().bitsLE(XLenVT)) {
10890 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL,
Op.getValueType(),
10891 Op.getOperand(1), Scalar,
Op.getOperand(3));
10894 assert(
Scalar.getValueType() == MVT::i64 &&
"Unexpected scalar VT!");
10911 MVT VT =
Op.getSimpleValueType();
10916 if (
Op.getOperand(1).isUndef())
10917 return SplattedVal;
10926 DAG.
getNode(RISCVISD::SETCC_VL,
DL, MaskVT,
10929 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, SelectCond, SplattedVal,
10932 case Intrinsic::riscv_vfmv_s_f:
10933 return DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL,
Op.getSimpleValueType(),
10934 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
10936 case Intrinsic::riscv_vaesdf_vv:
10937 case Intrinsic::riscv_vaesdf_vs:
10938 case Intrinsic::riscv_vaesdm_vv:
10939 case Intrinsic::riscv_vaesdm_vs:
10940 case Intrinsic::riscv_vaesef_vv:
10941 case Intrinsic::riscv_vaesef_vs:
10942 case Intrinsic::riscv_vaesem_vv:
10943 case Intrinsic::riscv_vaesem_vs:
10944 case Intrinsic::riscv_vaeskf1:
10945 case Intrinsic::riscv_vaeskf2:
10946 case Intrinsic::riscv_vaesz_vs:
10947 case Intrinsic::riscv_vsm4k:
10948 case Intrinsic::riscv_vsm4r_vv:
10949 case Intrinsic::riscv_vsm4r_vs: {
10950 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
10951 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
10952 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
10957 case Intrinsic::riscv_vsm3c:
10958 case Intrinsic::riscv_vsm3me: {
10959 if (!
isValidEGW(8,
Op.getSimpleValueType(), Subtarget) ||
10960 !
isValidEGW(8,
Op->getOperand(1).getSimpleValueType(), Subtarget))
10965 case Intrinsic::riscv_vsha2ch:
10966 case Intrinsic::riscv_vsha2cl:
10967 case Intrinsic::riscv_vsha2ms: {
10968 if (
Op->getSimpleValueType(0).getScalarSizeInBits() == 64 &&
10969 !Subtarget.hasStdExtZvknhb())
10971 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
10972 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
10973 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
10977 case Intrinsic::riscv_sf_vc_v_x:
10978 case Intrinsic::riscv_sf_vc_v_i:
10979 case Intrinsic::riscv_sf_vc_v_xv:
10980 case Intrinsic::riscv_sf_vc_v_iv:
10981 case Intrinsic::riscv_sf_vc_v_vv:
10982 case Intrinsic::riscv_sf_vc_v_fv:
10983 case Intrinsic::riscv_sf_vc_v_xvv:
10984 case Intrinsic::riscv_sf_vc_v_ivv:
10985 case Intrinsic::riscv_sf_vc_v_vvv:
10986 case Intrinsic::riscv_sf_vc_v_fvv:
10987 case Intrinsic::riscv_sf_vc_v_xvw:
10988 case Intrinsic::riscv_sf_vc_v_ivw:
10989 case Intrinsic::riscv_sf_vc_v_vvw:
10990 case Intrinsic::riscv_sf_vc_v_fvw: {
10991 MVT VT =
Op.getSimpleValueType();
11028 MVT VT =
Op.getSimpleValueType();
11032 if (VT.isFloatingPoint()) {
11034 VT.getVectorElementCount());
11037 if (VT.isFixedLengthVector())
11047 if (VT.isFixedLengthVector())
11049 if (VT.isFloatingPoint())
11072 case Intrinsic::riscv_seg2_load_mask:
11073 case Intrinsic::riscv_seg3_load_mask:
11074 case Intrinsic::riscv_seg4_load_mask:
11075 case Intrinsic::riscv_seg5_load_mask:
11076 case Intrinsic::riscv_seg6_load_mask:
11077 case Intrinsic::riscv_seg7_load_mask:
11078 case Intrinsic::riscv_seg8_load_mask:
11081 case Intrinsic::riscv_sseg2_load_mask:
11082 case Intrinsic::riscv_sseg3_load_mask:
11083 case Intrinsic::riscv_sseg4_load_mask:
11084 case Intrinsic::riscv_sseg5_load_mask:
11085 case Intrinsic::riscv_sseg6_load_mask:
11086 case Intrinsic::riscv_sseg7_load_mask:
11087 case Intrinsic::riscv_sseg8_load_mask:
11095 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
11096 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
11097 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
11098 Intrinsic::riscv_vlseg8_mask};
11100 Intrinsic::riscv_vlsseg2_mask, Intrinsic::riscv_vlsseg3_mask,
11101 Intrinsic::riscv_vlsseg4_mask, Intrinsic::riscv_vlsseg5_mask,
11102 Intrinsic::riscv_vlsseg6_mask, Intrinsic::riscv_vlsseg7_mask,
11103 Intrinsic::riscv_vlsseg8_mask};
11106 unsigned NF =
Op->getNumValues() - 1;
11107 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
11109 MVT VT =
Op->getSimpleValueType(0);
11117 SDValue VL =
Op.getOperand(
Op.getNumOperands() - 1);
11118 SDValue Mask =
Op.getOperand(
Op.getNumOperands() - 2);
11119 MVT MaskVT = Mask.getSimpleValueType();
11120 MVT MaskContainerVT =
11125 IsStrided ? VlssegInts[NF - 2] : VlsegInts[NF - 2],
DL, XLenVT);
11141 Ops.insert(std::next(
Ops.begin(), 4),
Op.getOperand(3));
11145 Load->getMemoryVT(), Load->getMemOperand());
11147 for (
unsigned int RetIdx = 0; RetIdx < NF; RetIdx++) {
11149 Result.getValue(0),
11153 Results.push_back(Result.getValue(1));
11159 unsigned IntNo =
Op.getConstantOperandVal(1);
11163 case Intrinsic::riscv_seg2_load_mask:
11164 case Intrinsic::riscv_seg3_load_mask:
11165 case Intrinsic::riscv_seg4_load_mask:
11166 case Intrinsic::riscv_seg5_load_mask:
11167 case Intrinsic::riscv_seg6_load_mask:
11168 case Intrinsic::riscv_seg7_load_mask:
11169 case Intrinsic::riscv_seg8_load_mask:
11170 case Intrinsic::riscv_sseg2_load_mask:
11171 case Intrinsic::riscv_sseg3_load_mask:
11172 case Intrinsic::riscv_sseg4_load_mask:
11173 case Intrinsic::riscv_sseg5_load_mask:
11174 case Intrinsic::riscv_sseg6_load_mask:
11175 case Intrinsic::riscv_sseg7_load_mask:
11176 case Intrinsic::riscv_sseg8_load_mask:
11179 case Intrinsic::riscv_sf_vc_v_x_se:
11181 case Intrinsic::riscv_sf_vc_v_i_se:
11183 case Intrinsic::riscv_sf_vc_v_xv_se:
11185 case Intrinsic::riscv_sf_vc_v_iv_se:
11187 case Intrinsic::riscv_sf_vc_v_vv_se:
11189 case Intrinsic::riscv_sf_vc_v_fv_se:
11191 case Intrinsic::riscv_sf_vc_v_xvv_se:
11193 case Intrinsic::riscv_sf_vc_v_ivv_se:
11195 case Intrinsic::riscv_sf_vc_v_vvv_se:
11197 case Intrinsic::riscv_sf_vc_v_fvv_se:
11199 case Intrinsic::riscv_sf_vc_v_xvw_se:
11201 case Intrinsic::riscv_sf_vc_v_ivw_se:
11203 case Intrinsic::riscv_sf_vc_v_vvw_se:
11205 case Intrinsic::riscv_sf_vc_v_fvw_se:
11218 case Intrinsic::riscv_seg2_store_mask:
11219 case Intrinsic::riscv_seg3_store_mask:
11220 case Intrinsic::riscv_seg4_store_mask:
11221 case Intrinsic::riscv_seg5_store_mask:
11222 case Intrinsic::riscv_seg6_store_mask:
11223 case Intrinsic::riscv_seg7_store_mask:
11224 case Intrinsic::riscv_seg8_store_mask:
11227 case Intrinsic::riscv_sseg2_store_mask:
11228 case Intrinsic::riscv_sseg3_store_mask:
11229 case Intrinsic::riscv_sseg4_store_mask:
11230 case Intrinsic::riscv_sseg5_store_mask:
11231 case Intrinsic::riscv_sseg6_store_mask:
11232 case Intrinsic::riscv_sseg7_store_mask:
11233 case Intrinsic::riscv_sseg8_store_mask:
11242 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
11243 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
11244 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
11245 Intrinsic::riscv_vsseg8_mask};
11247 Intrinsic::riscv_vssseg2_mask, Intrinsic::riscv_vssseg3_mask,
11248 Intrinsic::riscv_vssseg4_mask, Intrinsic::riscv_vssseg5_mask,
11249 Intrinsic::riscv_vssseg6_mask, Intrinsic::riscv_vssseg7_mask,
11250 Intrinsic::riscv_vssseg8_mask};
11254 unsigned NF =
Op->getNumOperands() - (IsStrided ? 6 : 5);
11255 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
11257 MVT VT =
Op->getOperand(2).getSimpleValueType();
11263 SDValue VL =
Op.getOperand(
Op.getNumOperands() - 1);
11264 SDValue Mask =
Op.getOperand(
Op.getNumOperands() - 2);
11265 MVT MaskVT = Mask.getSimpleValueType();
11266 MVT MaskContainerVT =
11271 IsStrided ? VsssegInts[NF - 2] : VssegInts[NF - 2],
DL, XLenVT);
11277 for (
unsigned i = 0; i < NF; i++)
11279 RISCVISD::TUPLE_INSERT,
DL, VecTupTy, StoredVal,
11285 FixedIntrinsic->getChain(),
11294 Ops.insert(std::next(
Ops.begin(), 4),
11295 Op.getOperand(
Op.getNumOperands() - 3));
11299 FixedIntrinsic->getMemoryVT(), FixedIntrinsic->getMemOperand());
11304 unsigned IntNo =
Op.getConstantOperandVal(1);
11308 case Intrinsic::riscv_seg2_store_mask:
11309 case Intrinsic::riscv_seg3_store_mask:
11310 case Intrinsic::riscv_seg4_store_mask:
11311 case Intrinsic::riscv_seg5_store_mask:
11312 case Intrinsic::riscv_seg6_store_mask:
11313 case Intrinsic::riscv_seg7_store_mask:
11314 case Intrinsic::riscv_seg8_store_mask:
11315 case Intrinsic::riscv_sseg2_store_mask:
11316 case Intrinsic::riscv_sseg3_store_mask:
11317 case Intrinsic::riscv_sseg4_store_mask:
11318 case Intrinsic::riscv_sseg5_store_mask:
11319 case Intrinsic::riscv_sseg6_store_mask:
11320 case Intrinsic::riscv_sseg7_store_mask:
11321 case Intrinsic::riscv_sseg8_store_mask:
11324 case Intrinsic::riscv_sf_vc_xv_se:
11326 case Intrinsic::riscv_sf_vc_iv_se:
11328 case Intrinsic::riscv_sf_vc_vv_se:
11330 case Intrinsic::riscv_sf_vc_fv_se:
11332 case Intrinsic::riscv_sf_vc_xvv_se:
11334 case Intrinsic::riscv_sf_vc_ivv_se:
11336 case Intrinsic::riscv_sf_vc_vvv_se:
11338 case Intrinsic::riscv_sf_vc_fvv_se:
11340 case Intrinsic::riscv_sf_vc_xvw_se:
11342 case Intrinsic::riscv_sf_vc_ivw_se:
11344 case Intrinsic::riscv_sf_vc_vvw_se:
11346 case Intrinsic::riscv_sf_vc_fvw_se:
11354 switch (ISDOpcode) {
11357 case ISD::VP_REDUCE_ADD:
11358 case ISD::VECREDUCE_ADD:
11359 return RISCVISD::VECREDUCE_ADD_VL;
11360 case ISD::VP_REDUCE_UMAX:
11361 case ISD::VECREDUCE_UMAX:
11362 return RISCVISD::VECREDUCE_UMAX_VL;
11363 case ISD::VP_REDUCE_SMAX:
11364 case ISD::VECREDUCE_SMAX:
11365 return RISCVISD::VECREDUCE_SMAX_VL;
11366 case ISD::VP_REDUCE_UMIN:
11367 case ISD::VECREDUCE_UMIN:
11368 return RISCVISD::VECREDUCE_UMIN_VL;
11369 case ISD::VP_REDUCE_SMIN:
11370 case ISD::VECREDUCE_SMIN:
11371 return RISCVISD::VECREDUCE_SMIN_VL;
11372 case ISD::VP_REDUCE_AND:
11373 case ISD::VECREDUCE_AND:
11374 return RISCVISD::VECREDUCE_AND_VL;
11375 case ISD::VP_REDUCE_OR:
11376 case ISD::VECREDUCE_OR:
11377 return RISCVISD::VECREDUCE_OR_VL;
11378 case ISD::VP_REDUCE_XOR:
11379 case ISD::VECREDUCE_XOR:
11380 return RISCVISD::VECREDUCE_XOR_VL;
11381 case ISD::VP_REDUCE_FADD:
11382 return RISCVISD::VECREDUCE_FADD_VL;
11383 case ISD::VP_REDUCE_SEQ_FADD:
11384 return RISCVISD::VECREDUCE_SEQ_FADD_VL;
11385 case ISD::VP_REDUCE_FMAX:
11386 case ISD::VP_REDUCE_FMAXIMUM:
11387 return RISCVISD::VECREDUCE_FMAX_VL;
11388 case ISD::VP_REDUCE_FMIN:
11389 case ISD::VP_REDUCE_FMINIMUM:
11390 return RISCVISD::VECREDUCE_FMIN_VL;
11399 SDValue Vec =
Op.getOperand(IsVP ? 1 : 0);
11401 assert((
Op.getOpcode() == ISD::VECREDUCE_AND ||
11402 Op.getOpcode() == ISD::VECREDUCE_OR ||
11403 Op.getOpcode() == ISD::VECREDUCE_XOR ||
11404 Op.getOpcode() == ISD::VP_REDUCE_AND ||
11405 Op.getOpcode() == ISD::VP_REDUCE_OR ||
11406 Op.getOpcode() == ISD::VP_REDUCE_XOR) &&
11407 "Unexpected reduction lowering");
11409 MVT XLenVT = Subtarget.getXLenVT();
11411 MVT ContainerVT = VecVT;
11419 Mask =
Op.getOperand(2);
11420 VL =
Op.getOperand(3);
11422 std::tie(Mask, VL) =
11427 switch (
Op.getOpcode()) {
11430 case ISD::VECREDUCE_AND:
11431 case ISD::VP_REDUCE_AND: {
11435 Vec = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Vec, TrueMask, VL);
11438 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11442 case ISD::VECREDUCE_OR:
11443 case ISD::VP_REDUCE_OR:
11445 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11448 case ISD::VECREDUCE_XOR:
11449 case ISD::VP_REDUCE_XOR: {
11452 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11473 return DAG.
getNode(BaseOpc,
DL,
Op.getValueType(), SetCC,
Op.getOperand(0));
11479 return (RegisterAVL && RegisterAVL->getReg() == RISCV::X0) ||
11480 (ImmAVL && ImmAVL->getZExtValue() >= 1);
11496 auto InnerVT = VecVT.
bitsLE(M1VT) ? VecVT : M1VT;
11500 auto InnerVL = NonZeroAVL ? VL : DAG.
getConstant(1,
DL, XLenVT);
11503 if (M1VT != InnerVT)
11508 SDValue Ops[] = {PassThru, Vec, InitialValue, Mask, VL, Policy};
11526 VecEVT =
Lo.getValueType();
11539 MVT ContainerVT = VecVT;
11558 Mask, VL,
DL, DAG, Subtarget);
11564static std::tuple<unsigned, SDValue, SDValue>
11568 auto Flags =
Op->getFlags();
11569 unsigned Opcode =
Op.getOpcode();
11573 case ISD::VECREDUCE_FADD: {
11577 return std::make_tuple(RISCVISD::VECREDUCE_FADD_VL,
Op.getOperand(0), Zero);
11579 case ISD::VECREDUCE_SEQ_FADD:
11580 return std::make_tuple(RISCVISD::VECREDUCE_SEQ_FADD_VL,
Op.getOperand(1),
11582 case ISD::VECREDUCE_FMINIMUM:
11583 case ISD::VECREDUCE_FMAXIMUM:
11584 case ISD::VECREDUCE_FMIN:
11585 case ISD::VECREDUCE_FMAX: {
11588 (Opcode == ISD::VECREDUCE_FMIN || Opcode == ISD::VECREDUCE_FMINIMUM)
11589 ? RISCVISD::VECREDUCE_FMIN_VL
11590 : RISCVISD::VECREDUCE_FMAX_VL;
11591 return std::make_tuple(RVVOpc,
Op.getOperand(0), Front);
11599 MVT VecEltVT =
Op.getSimpleValueType();
11601 unsigned RVVOpcode;
11602 SDValue VectorVal, ScalarVal;
11603 std::tie(RVVOpcode, VectorVal, ScalarVal) =
11607 MVT ContainerVT = VecVT;
11613 MVT ResVT =
Op.getSimpleValueType();
11616 VL,
DL, DAG, Subtarget);
11617 if (
Op.getOpcode() != ISD::VECREDUCE_FMINIMUM &&
11618 Op.getOpcode() != ISD::VECREDUCE_FMAXIMUM)
11621 if (
Op->getFlags().hasNoNaNs())
11627 {VectorVal, VectorVal, DAG.getCondCode(ISD::SETNE),
11628 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
11629 MVT XLenVT = Subtarget.getXLenVT();
11630 SDValue CPop = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, IsNan, Mask, VL);
11634 DL, ResVT, NoNaNs, Res,
11641 unsigned Opc =
Op.getOpcode();
11645 MVT XLenVT = Subtarget.getXLenVT();
11664 Vec, Mask, VL,
DL, DAG, Subtarget);
11665 if ((
Opc != ISD::VP_REDUCE_FMINIMUM &&
Opc != ISD::VP_REDUCE_FMAXIMUM) ||
11666 Op->getFlags().hasNoNaNs())
11673 RISCVISD::SETCC_VL,
DL, PredVT,
11675 SDValue VCPop = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, IsNaN, Mask, VL);
11683 DL, ResVT, NoNaNs, Res,
11695 MVT XLenVT = Subtarget.getXLenVT();
11696 unsigned OrigIdx =
Op.getConstantOperandVal(2);
11697 const RISCVRegisterInfo *
TRI = Subtarget.getRegisterInfo();
11699 if (OrigIdx == 0 && Vec.
isUndef())
11710 assert(OrigIdx % 8 == 0 &&
"Invalid index");
11713 "Unexpected mask vector lowering");
11743 const auto VLen = Subtarget.getRealVLen();
11745 MVT ContainerVT = VecVT;
11767 if (OrigIdx == 0) {
11769 DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, ContainerVT, Vec, SubVec, VL);
11772 SubVec =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, Vec, SubVec,
11773 SlideupAmt, Mask, VL, Policy);
11781 MVT ContainerVecVT = VecVT;
11787 MVT ContainerSubVecVT = SubVecVT;
11793 unsigned SubRegIdx;
11794 ElementCount RemIdx;
11803 ContainerVecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
11804 SubRegIdx = Decompose.first;
11806 (OrigIdx % Vscale));
11810 ContainerVecVT, ContainerSubVecVT, OrigIdx,
TRI);
11811 SubRegIdx = Decompose.first;
11817 Subtarget.expandVScale(SubVecVT.
getSizeInBits()).getKnownMinValue()));
11818 bool ExactlyVecRegSized =
11820 .isKnownMultipleOf(Subtarget.expandVScale(VecRegSize));
11835 if (RemIdx.
isZero() && (ExactlyVecRegSized || Vec.
isUndef())) {
11839 if (SubRegIdx == RISCV::NoSubRegister) {
11861 MVT InterSubVT = ContainerVecVT;
11862 SDValue AlignedExtract = Vec;
11884 if (Subtarget.expandVScale(EndIndex) ==
11891 SubVec = DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, InterSubVT, AlignedExtract,
11899 SubVec =
getVSlideup(DAG, Subtarget,
DL, InterSubVT, AlignedExtract, SubVec,
11900 SlideupAmt, Mask, VL, Policy);
11905 if (ContainerVecVT.
bitsGT(InterSubVT))
11913 return DAG.
getBitcast(
Op.getSimpleValueType(), SubVec);
11919 MVT SubVecVT =
Op.getSimpleValueType();
11923 MVT XLenVT = Subtarget.getXLenVT();
11924 unsigned OrigIdx =
Op.getConstantOperandVal(1);
11925 const RISCVRegisterInfo *
TRI = Subtarget.getRegisterInfo();
11940 assert(OrigIdx % 8 == 0 &&
"Invalid index");
11943 "Unexpected mask vector lowering");
11969 const auto VLen = Subtarget.getRealVLen();
11977 MVT ContainerVT = VecVT;
11985 if (
auto ShrunkVT =
11987 ContainerVT = *ShrunkVT;
11999 DAG.
getUNDEF(ContainerVT), Vec, SlidedownAmt, Mask, VL);
12010 MVT ContainerSubVecVT = SubVecVT;
12014 unsigned SubRegIdx;
12015 ElementCount RemIdx;
12024 VecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
12025 SubRegIdx = Decompose.first;
12027 (OrigIdx % Vscale));
12031 VecVT, ContainerSubVecVT, OrigIdx,
TRI);
12032 SubRegIdx = Decompose.first;
12059 MVT InterSubVT = VecVT;
12064 assert(SubRegIdx != RISCV::NoSubRegister);
12083 Vec, SlidedownAmt, Mask, VL);
12091 return DAG.
getBitcast(
Op.getSimpleValueType(), Slidedown);
12098 MVT VT =
N.getSimpleValueType();
12102 assert(
Op.getSimpleValueType() == VT &&
12103 "Operands and result must be same type");
12107 unsigned NumVals =
N->getNumValues();
12110 NumVals,
N.getValueType().changeVectorElementType(MVT::i8)));
12113 for (
unsigned I = 0;
I < NumVals;
I++) {
12119 if (TruncVals.
size() > 1)
12121 return TruncVals.
front();
12127 MVT VecVT =
Op.getSimpleValueType();
12129 const unsigned Factor =
Op->getNumValues();
12140 for (
unsigned i = 0U; i < Factor; ++i)
12149 for (
unsigned i = 0U; i < Factor; ++i)
12159 for (
unsigned i = 0; i != Factor; ++i) {
12162 Ops[i * 2 + 1] = OpHi;
12173 for (
unsigned i = 0; i != Factor; ++i)
12180 if (Subtarget.hasVendorXRivosVizip() && Factor == 2) {
12181 MVT VT =
Op->getSimpleValueType(0);
12206 lowerVZIP(RISCVISD::RI_VUNZIP2A_VL, V1, V2,
DL, DAG, Subtarget);
12208 lowerVZIP(RISCVISD::RI_VUNZIP2B_VL, V1, V2,
DL, DAG, Subtarget);
12241 EvenSplat = DAG.
getBitcast(MVT::nxv64i1, EvenSplat);
12245 OddSplat = DAG.
getBitcast(MVT::nxv64i1, OddSplat);
12250 EvenMask, DAG.
getUNDEF(ConcatVT));
12262 MVT XLenVT = Subtarget.getXLenVT();
12284 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
12285 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
12286 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
12287 Intrinsic::riscv_vlseg8_mask};
12311 for (
unsigned i = 0U; i < Factor; ++i)
12312 Res[i] = DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL, VecVT, Load,
12321 MVT VecVT =
Op.getSimpleValueType();
12334 for (
unsigned i = 0U; i < Factor; ++i)
12342 for (
unsigned i = 0U; i < Factor; ++i)
12348 MVT XLenVT = Subtarget.getXLenVT();
12355 for (
unsigned i = 0; i != Factor; ++i) {
12358 Ops[i + Factor] = OpHi;
12369 for (
unsigned i = 0; i != Factor; ++i) {
12370 unsigned IdxLo = 2 * i;
12371 unsigned IdxHi = 2 * i + 1;
12373 Res[IdxLo / Factor].getValue(IdxLo % Factor),
12374 Res[IdxHi / Factor].getValue(IdxHi % Factor));
12392 EVT PtrVT =
StackPtr.getValueType();
12398 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
12399 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
12400 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
12401 Intrinsic::riscv_vsseg8_mask,
12409 for (
unsigned i = 0; i < Factor; i++)
12411 DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VecTupTy, StoredVal,
12434 for (
unsigned i = 0; i != Factor; ++i) {
12438 Loads[i] = DAG.
getLoad(VecVT,
DL, Chain, StackPtr, PtrInfo);
12446 if (Subtarget.hasVendorXRivosVizip() && !
Op.getOperand(0).isUndef() &&
12447 !
Op.getOperand(1).isUndef()) {
12467 Op.getOperand(0),
Op.getOperand(1));
12491 DAG.
getNode(RISCVISD::ADD_VL,
DL, IdxVT, Idx, VLMax, Idx, OddMask, VL);
12496 Interleaved = DAG.
getNode(RISCVISD::VRGATHEREI16_VV_VL,
DL, ConcatVT,
12513 MVT VT =
Op.getSimpleValueType();
12515 MVT XLenVT = Subtarget.getXLenVT();
12518 uint64_t StepValImm =
Op.getConstantOperandVal(0);
12519 if (StepValImm != 1) {
12528 VL, VT,
DL, DAG, Subtarget);
12543 MVT VecVT =
Op.getSimpleValueType();
12552 MVT ContainerVT = VecVT;
12559 MVT XLenVT = Subtarget.getXLenVT();
12605 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
12606 unsigned MaxVLMAX =
12611 unsigned GatherOpc = RISCVISD::VRGATHER_VV_VL;
12616 if (MaxVLMAX > 256 && EltSize == 8) {
12630 LoVT.getVectorMinNumElements());
12635 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
12643 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
12668 DAG.
getUNDEF(ContainerVT), Mask, VL);
12679 MVT XLenVT = Subtarget.getXLenVT();
12680 MVT VecVT =
Op.getSimpleValueType();
12685 SDValue DownOffset, UpOffset;
12686 if (ImmValue >= 0) {
12701 DAG, Subtarget,
DL, VecVT, DAG.
getUNDEF(VecVT), V1, DownOffset, TrueMask,
12702 Subtarget.hasVLDependentLatency() ? UpOffset
12704 return getVSlideup(DAG, Subtarget,
DL, VecVT, SlideDown, V2, UpOffset,
12710RISCVTargetLowering::lowerFixedLengthVectorLoadToRVV(
SDValue Op,
12716 Load->getMemoryVT(),
12717 *
Load->getMemOperand()) &&
12718 "Expecting a correctly-aligned load");
12720 MVT VT =
Op.getSimpleValueType();
12721 MVT XLenVT = Subtarget.getXLenVT();
12726 const auto [MinVLMAX, MaxVLMAX] =
12730 MachineMemOperand *MMO =
Load->getMemOperand();
12743 IsMaskOp ? Intrinsic::riscv_vlm : Intrinsic::riscv_vle,
DL, XLenVT);
12747 Ops.push_back(
Load->getBasePtr());
12749 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
12752 Load->getMemoryVT(),
Load->getMemOperand());
12759RISCVTargetLowering::lowerFixedLengthVectorStoreToRVV(
SDValue Op,
12765 Store->getMemoryVT(),
12766 *
Store->getMemOperand()) &&
12767 "Expecting a correctly-aligned store");
12771 MVT XLenVT = Subtarget.getXLenVT();
12787 const auto [MinVLMAX, MaxVLMAX] =
12791 MachineMemOperand *MMO =
Store->getMemOperand();
12801 IsMaskOp ? Intrinsic::riscv_vsm : Intrinsic::riscv_vse,
DL, XLenVT);
12804 {Store->getChain(), IntID, NewValue, Store->getBasePtr(), VL},
12805 Store->getMemoryVT(),
Store->getMemOperand());
12811 MVT VT =
Op.getSimpleValueType();
12814 EVT MemVT = MemSD->getMemoryVT();
12815 MachineMemOperand *MMO = MemSD->getMemOperand();
12816 SDValue Chain = MemSD->getChain();
12820 bool IsExpandingLoad =
false;
12822 Mask = VPLoad->getMask();
12824 VL = VPLoad->getVectorLength();
12827 Mask = MLoad->getMask();
12828 PassThru = MLoad->getPassThru();
12829 IsExpandingLoad = MLoad->isExpandingLoad();
12834 MVT XLenVT = Subtarget.getXLenVT();
12836 MVT ContainerVT = VT;
12850 if (!IsUnmasked && IsExpandingLoad) {
12853 DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Mask,
12857 unsigned IntID = IsUnmasked || IsExpandingLoad ? Intrinsic::riscv_vle
12858 : Intrinsic::riscv_vle_mask;
12860 if (IntID == Intrinsic::riscv_vle)
12863 Ops.push_back(PassThru);
12864 Ops.push_back(BasePtr);
12865 if (IntID == Intrinsic::riscv_vle_mask)
12866 Ops.push_back(Mask);
12868 if (IntID == Intrinsic::riscv_vle_mask)
12871 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
12875 Chain =
Result.getValue(1);
12877 MVT IndexVT = ContainerVT;
12882 bool UseVRGATHEREI16 =
false;
12890 UseVRGATHEREI16 =
true;
12896 DAG.
getUNDEF(IndexVT), Mask, ExpandingVL);
12898 DAG.
getNode(UseVRGATHEREI16 ? RISCVISD::VRGATHEREI16_VV_VL
12899 : RISCVISD::VRGATHER_VV_VL,
12900 DL, ContainerVT, Result, Iota, PassThru, Mask, ExpandingVL);
12911 MVT VT =
Op->getSimpleValueType(0);
12914 EVT MemVT = VPLoadFF->getMemoryVT();
12915 MachineMemOperand *MMO = VPLoadFF->getMemOperand();
12916 SDValue Chain = VPLoadFF->getChain();
12920 SDValue VL = VPLoadFF->getVectorLength();
12922 MVT XLenVT = Subtarget.getXLenVT();
12924 MVT ContainerVT = VT;
12931 unsigned IntID = Intrinsic::riscv_vleff_mask;
12941 SDVTList VTs = DAG.
getVTList({ContainerVT,
Op->getValueType(1), MVT::Other});
12946 Chain =
Result.getValue(2);
12959 EVT MemVT = MemSD->getMemoryVT();
12960 MachineMemOperand *MMO = MemSD->getMemOperand();
12961 SDValue Chain = MemSD->getChain();
12965 bool IsCompressingStore =
false;
12967 Val = VPStore->getValue();
12968 Mask = VPStore->getMask();
12969 VL = VPStore->getVectorLength();
12972 Val = MStore->getValue();
12973 Mask = MStore->getMask();
12974 IsCompressingStore = MStore->isCompressingStore();
12981 MVT XLenVT = Subtarget.getXLenVT();
12983 MVT ContainerVT = VT;
12988 if (!IsUnmasked || IsCompressingStore) {
12997 if (IsCompressingStore) {
13000 DAG.
getUNDEF(ContainerVT), Val, Mask, VL);
13002 DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Mask,
13007 IsUnmasked ? Intrinsic::riscv_vse : Intrinsic::riscv_vse_mask;
13009 Ops.push_back(Val);
13010 Ops.push_back(BasePtr);
13012 Ops.push_back(Mask);
13027 MVT XLenVT = Subtarget.getXLenVT();
13028 MVT ContainerVT = VT;
13041 Passthru, Val, Mask, VL);
13051 unsigned Opc =
Op.getOpcode();
13058 MVT VT =
Op.getSimpleValueType();
13066 SDVTList VTList =
Op->getVTList();
13091 MVT ContainerInVT = InVT;
13109 RISCVISD::STRICT_FSETCC_VL,
DL, DAG.
getVTList(MaskVT, MVT::Other),
13110 {Chain, Op1, Op1, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
13113 RISCVISD::STRICT_FSETCC_VL,
DL, DAG.
getVTList(MaskVT, MVT::Other),
13114 {Chain, Op2, Op2, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
13117 DAG.
getNode(RISCVISD::VMAND_VL,
DL, MaskVT, OrderMask1, OrderMask2, VL);
13120 Res = DAG.
getNode(RISCVISD::STRICT_FSETCCS_VL,
DL,
13122 {Chain, Op1, Op2, CC, Mask, Mask, VL});
13125 : RISCVISD::STRICT_FSETCCS_VL;
13127 {Chain, Op1, Op2, CC, DAG.getUNDEF(MaskVT), Mask, VL});
13140 MVT VT =
Op.getSimpleValueType();
13144 "Unexpected type for ISD::ABS");
13146 MVT ContainerVT = VT;
13153 if (
Op->getOpcode() == ISD::VP_ABS) {
13154 Mask =
Op->getOperand(1);
13158 VL =
Op->getOperand(2);
13163 RISCVISD::VMV_V_X_VL,
DL, ContainerVT, DAG.
getUNDEF(ContainerVT),
13166 DAG.
getUNDEF(ContainerVT), Mask, VL);
13168 DAG.
getUNDEF(ContainerVT), Mask, VL);
13177 const auto &TSInfo =
13181 bool HasPassthruOp = TSInfo.hasPassthruOp(NewOpc);
13182 bool HasMask = TSInfo.hasMaskOp(NewOpc);
13184 MVT VT =
Op.getSimpleValueType();
13189 for (
const SDValue &V :
Op->op_values()) {
13193 if (!
V.getValueType().isVector()) {
13199 assert(useRVVForFixedLengthVectorVT(
V.getSimpleValueType()) &&
13200 "Only fixed length vectors are supported!");
13202 V.getSimpleValueType().getVectorElementType());
13211 Ops.push_back(Mask);
13216 if (
Op->isStrictFPOpcode()) {
13235 const auto &TSInfo =
13239 bool HasPassthruOp = TSInfo.hasPassthruOp(RISCVISDOpc);
13242 MVT VT =
Op.getSimpleValueType();
13245 MVT ContainerVT = VT;
13254 if (HasPassthruOp) {
13257 if (*MaskIdx ==
OpIdx.index())
13261 if (
Op.getOpcode() == ISD::VP_MERGE) {
13263 Ops.push_back(
Ops.back());
13265 assert(
Op.getOpcode() == ISD::VP_SELECT);
13272 if (RISCVISDOpc == RISCVISD::VFCVT_RM_X_F_VL &&
13275 Subtarget.getXLenVT()));
13277 if (!
V.getValueType().isFixedLengthVector()) {
13282 MVT OpVT =
V.getSimpleValueType();
13284 assert(useRVVForFixedLengthVectorVT(OpVT) &&
13285 "Only fixed length vectors are supported!");
13300 MVT VT =
Op.getSimpleValueType();
13306 MVT ContainerVT = VT;
13313 MVT XLenVT = Subtarget.getXLenVT();
13316 DAG.
getUNDEF(ContainerVT), Zero, VL);
13319 Op.getOpcode() == ISD::VP_ZERO_EXTEND ? 1 : -1,
DL, XLenVT);
13321 DAG.
getUNDEF(ContainerVT), SplatValue, VL);
13324 ZeroSplat, DAG.
getUNDEF(ContainerVT), VL);
13333 MVT VT =
Op.getSimpleValueType();
13341 MVT ContainerVT = VT;
13349 SDValue AllOneMask = DAG.
getNode(RISCVISD::VMSET_VL,
DL, ContainerVT, VL);
13351 switch (Condition) {
13356 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, Op2, VL);
13361 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, Op2, VL);
13363 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, AllOneMask, VL);
13371 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, AllOneMask, VL);
13372 Result = DAG.
getNode(RISCVISD::VMAND_VL,
DL, ContainerVT, Temp, Op2, VL);
13380 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op2, AllOneMask, VL);
13381 Result = DAG.
getNode(RISCVISD::VMAND_VL,
DL, ContainerVT, Op1, Temp, VL);
13389 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, AllOneMask, VL);
13390 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, Op2, VL);
13398 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op2, AllOneMask, VL);
13399 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, Op1, VL);
13419 MVT DstVT =
Op.getSimpleValueType();
13420 MVT SrcVT = Src.getSimpleValueType();
13433 if (DstEltSize >= SrcEltSize) {
13437 unsigned RISCVISDExtOpc = RISCVISDOpc == RISCVISD::SINT_TO_FP_VL
13438 ? RISCVISD::VSEXT_VL
13439 : RISCVISD::VZEXT_VL;
13442 if (SrcEltSize == 1) {
13444 MVT XLenVT = Subtarget.getXLenVT();
13449 RISCVISDExtOpc == RISCVISD::VZEXT_VL ? 1 : -1,
DL, XLenVT);
13452 Src = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, IntVT, Src, OneSplat,
13453 ZeroSplat, DAG.
getUNDEF(IntVT), VL);
13454 }
else if (DstEltSize > (2 * SrcEltSize)) {
13458 Src = DAG.
getNode(RISCVISDExtOpc,
DL, IntVT, Src, Mask, VL);
13464 "Wrong input/output vector types");
13467 if (DstEltSize > (2 * SrcEltSize)) {
13472 DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, InterimFVT, Src, Mask, VL);
13483 MVT InterimFVT = DstVT;
13484 if (SrcEltSize > (2 * DstEltSize)) {
13485 assert(SrcEltSize == (4 * DstEltSize) &&
"Unexpected types!");
13492 if (InterimFVT != DstVT) {
13494 Result = DAG.
getNode(RISCVISD::FP_ROUND_VL,
DL, DstVT, Src, Mask, VL);
13498 "Wrong input/output vector types");
13502 if (DstEltSize == 1) {
13505 assert(SrcEltSize >= 16 &&
"Unexpected FP type!");
13512 MVT XLenVT = Subtarget.getXLenVT();
13514 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, InterimIVT,
13515 DAG.
getUNDEF(InterimIVT), SplatZero, VL);
13525 while (InterimIVT != DstVT) {
13537 MVT VT =
Op.getSimpleValueType();
13546 MVT VT =
Op.getSimpleValueType();
13547 MVT XLenVT = Subtarget.getXLenVT();
13560 MVT ContainerVT = VT;
13580 TrueVal = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, PromotedVT, TrueVal, SplatOne,
13581 SplatZero, DAG.
getUNDEF(PromotedVT), VL);
13584 SplatOne, SplatZero, DAG.
getUNDEF(PromotedVT), VLMax);
13588 TrueVal, FalseVal, FalseVal, VL);
13593 RISCVISD::SETCC_VL,
DL, ContainerVT,
13603RISCVTargetLowering::lowerVPSpliceExperimental(
SDValue Op,
13605 using namespace SDPatternMatch;
13616 const MVT XLenVT = Subtarget.getXLenVT();
13617 MVT VT =
Op.getSimpleValueType();
13618 MVT ContainerVT = VT;
13628 if (IsMaskVector) {
13638 Op1 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, Op1, SplatOneOp1,
13639 SplatZeroOp1, DAG.
getUNDEF(ContainerVT), EVL1);
13647 Op2 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, Op2, SplatOneOp2,
13648 SplatZeroOp2, DAG.
getUNDEF(ContainerVT), EVL2);
13651 auto getVectorFirstEle = [](
SDValue Vec) {
13664 if (
auto FirstEle = getVectorFirstEle(
Op->getOperand(0))) {
13667 if ((EltVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
13668 EltVT == MVT::bf16) {
13676 : RISCVISD::VSLIDE1UP_VL,
13677 DL, ContainerVT, DAG.
getUNDEF(ContainerVT), Op2,
13678 FirstEle, Mask, EVL2);
13688 SDValue DownOffset, UpOffset;
13689 if (ImmValue >= 0) {
13703 DAG.
getUNDEF(ContainerVT), Op1, DownOffset, Mask,
13704 Subtarget.hasVLDependentLatency() ? UpOffset : EVL2);
13708 if (IsMaskVector) {
13712 {Result, DAG.getConstant(0, DL, ContainerVT),
13713 DAG.getCondCode(ISD::SETNE), DAG.getUNDEF(getMaskTypeFor(ContainerVT)),
13728 MVT VT =
Op.getSimpleValueType();
13730 MVT ContainerVT = VT;
13741 DAG.
getNode(
C->isZero() ? RISCVISD::VMCLR_VL : RISCVISD::VMSET_VL,
DL,
13764RISCVTargetLowering::lowerVPReverseExperimental(
SDValue Op,
13767 MVT VT =
Op.getSimpleValueType();
13768 MVT XLenVT = Subtarget.getXLenVT();
13774 MVT ContainerVT = VT;
13782 MVT GatherVT = ContainerVT;
13786 if (IsMaskVector) {
13796 Op1 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, IndicesVT, Op1, SplatOne,
13797 SplatZero, DAG.
getUNDEF(IndicesVT), EVL);
13802 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
13803 unsigned MaxVLMAX =
13806 unsigned GatherOpc = RISCVISD::VRGATHER_VV_VL;
13812 if (MaxVLMAX > 256 && EltSize == 8) {
13840 DAG.
getUNDEF(GatherVT), Result, Diff, Mask, EVL);
13842 if (IsMaskVector) {
13845 DAG.
getNode(RISCVISD::SETCC_VL,
DL, ContainerVT,
13858 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
13865 DAG.
getUNDEF(IndicesVT), VecLen, EVL);
13866 SDValue VRSUB = DAG.
getNode(RISCVISD::SUB_VL,
DL, IndicesVT, VecLenSplat, VID,
13867 DAG.
getUNDEF(IndicesVT), Mask, EVL);
13869 DAG.
getUNDEF(GatherVT), Mask, EVL);
13871 if (IsMaskVector) {
13874 RISCVISD::SETCC_VL,
DL, ContainerVT,
13886 MVT VT =
Op.getSimpleValueType();
13888 return lowerVPOp(
Op, DAG);
13895 MVT ContainerVT = VT;
13913 MVT XLenVT = Subtarget.getXLenVT();
13914 MVT VT =
Op.getSimpleValueType();
13915 MVT ContainerVT = VT;
13919 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
13927 : Intrinsic::riscv_vlse_mask,
13930 DAG.
getUNDEF(ContainerVT), VPNode->getBasePtr(),
13931 VPNode->getStride()};
13937 Ops.push_back(Mask);
13939 Ops.push_back(VPNode->getVectorLength());
13943 Ops.push_back(Policy);
13948 VPNode->getMemoryVT(), VPNode->getMemOperand());
13960 MVT XLenVT = Subtarget.getXLenVT();
13963 SDValue StoreVal = VPNode->getValue();
13965 MVT ContainerVT = VT;
13976 : Intrinsic::riscv_vsse_mask,
13979 VPNode->getBasePtr(), VPNode->getStride()};
13985 Ops.push_back(Mask);
13987 Ops.push_back(VPNode->getVectorLength());
13990 Ops, VPNode->getMemoryVT(),
13991 VPNode->getMemOperand());
14003 MVT VT =
Op.getSimpleValueType();
14006 EVT MemVT = MemSD->getMemoryVT();
14007 MachineMemOperand *MMO = MemSD->getMemOperand();
14008 SDValue Chain = MemSD->getChain();
14015 Index = VPGN->getIndex();
14016 Mask = VPGN->getMask();
14018 VL = VPGN->getVectorLength();
14024 Index = MGN->getIndex();
14025 Mask = MGN->getMask();
14026 PassThru = MGN->getPassThru();
14030 MVT IndexVT =
Index.getSimpleValueType();
14031 MVT XLenVT = Subtarget.getXLenVT();
14034 "Unexpected VTs!");
14035 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
14038 "Unexpected extending MGATHER/VP_GATHER");
14044 MVT ContainerVT = VT;
14068 IsUnmasked ? Intrinsic::riscv_vluxei : Intrinsic::riscv_vluxei_mask;
14073 Ops.push_back(PassThru);
14074 Ops.push_back(BasePtr);
14075 Ops.push_back(Index);
14077 Ops.push_back(Mask);
14082 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
14085 Chain =
Result.getValue(1);
14103 EVT MemVT = MemSD->getMemoryVT();
14104 MachineMemOperand *MMO = MemSD->getMemOperand();
14105 SDValue Chain = MemSD->getChain();
14108 [[maybe_unused]]
bool IsTruncatingStore =
false;
14112 Index = VPSN->getIndex();
14113 Mask = VPSN->getMask();
14114 Val = VPSN->getValue();
14115 VL = VPSN->getVectorLength();
14117 IsTruncatingStore =
false;
14121 Index = MSN->getIndex();
14122 Mask = MSN->getMask();
14123 Val = MSN->getValue();
14124 IsTruncatingStore = MSN->isTruncatingStore();
14128 MVT IndexVT =
Index.getSimpleValueType();
14129 MVT XLenVT = Subtarget.getXLenVT();
14132 "Unexpected VTs!");
14133 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
14136 assert(!IsTruncatingStore &&
"Unexpected truncating MSCATTER/VP_SCATTER");
14142 MVT ContainerVT = VT;
14166 IsUnmasked ? Intrinsic::riscv_vsoxei : Intrinsic::riscv_vsoxei_mask;
14168 Ops.push_back(Val);
14169 Ops.push_back(BasePtr);
14170 Ops.push_back(Index);
14172 Ops.push_back(Mask);
14181 const MVT XLenVT = Subtarget.getXLenVT();
14185 SDVTList VTs = DAG.
getVTList(XLenVT, MVT::Other);
14192 static const int Table =
14211 const MVT XLenVT = Subtarget.getXLenVT();
14221 static const unsigned Table =
14236 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14242 const MVT XLenVT = Subtarget.getXLenVT();
14246 SDVTList VTs = DAG.
getVTList(XLenVT, MVT::Other);
14247 return DAG.
getNode(RISCVISD::READ_CSR,
DL, VTs, Chain, SysRegNo);
14252 const MVT XLenVT = Subtarget.getXLenVT();
14259 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14265 const MVT XLenVT = Subtarget.getXLenVT();
14271 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14285 SDValue Result = DAG.
getNode(RISCVISD::READ_CSR,
DL, VTs, Chain, SysRegNo);
14286 Chain = Result.getValue(1);
14292 const MVT XLenVT = Subtarget.getXLenVT();
14302 Chain = DAG.
getNode(RISCVISD::CLEAR_CSR,
DL, MVT::Other, Chain, SysRegNo,
14304 return DAG.
getNode(RISCVISD::SET_CSR,
DL, MVT::Other, Chain, SysRegNo,
14310 const MVT XLenVT = Subtarget.getXLenVT();
14317 return DAG.
getNode(RISCVISD::CLEAR_CSR,
DL, MVT::Other, Chain, SysRegNo,
14325 bool isRISCV64 = Subtarget.is64Bit();
14339 return RISCVISD::SLLW;
14341 return RISCVISD::SRAW;
14343 return RISCVISD::SRLW;
14345 return RISCVISD::DIVW;
14347 return RISCVISD::DIVUW;
14349 return RISCVISD::REMUW;
14351 return RISCVISD::ROLW;
14353 return RISCVISD::RORW;
14389 switch (
N->getOpcode()) {
14391 llvm_unreachable(
"Don't know how to custom type legalize this operation!");
14396 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14397 "Unexpected custom legalisation");
14398 bool IsStrict =
N->isStrictFPOpcode();
14401 SDValue Op0 = IsStrict ?
N->getOperand(1) :
N->getOperand(0);
14410 !Subtarget.hasStdExtZfhOrZhinx()) {
14415 unsigned Opc = IsSigned ? RISCVISD::STRICT_FCVT_W_RV64
14416 : RISCVISD::STRICT_FCVT_WU_RV64;
14419 Opc,
DL, VTs, Chain, Op0,
14428 !Subtarget.hasStdExtZfhOrZhinx()) ||
14430 Op0 = DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, Op0);
14432 unsigned Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
14453 std::tie(Result, Chain) =
14454 makeLibCall(DAG, LC,
N->getValueType(0), Op0, CallOptions,
DL, Chain);
14460 case ISD::LROUND: {
14469 if (Op0.
getValueType() == MVT::f16 && !Subtarget.hasStdExtZfhOrZhinx())
14470 Op0 = DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, Op0);
14473 DAG.
getNode(RISCVISD::FCVT_W_RV64,
DL, MVT::i64, Op0,
14481 RTLIB::Libcall LC =
14482 Op0.
getValueType() == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
14491 case ISD::READCYCLECOUNTER:
14492 case ISD::READSTEADYCOUNTER: {
14493 assert(!Subtarget.is64Bit() &&
"READCYCLECOUNTER/READSTEADYCOUNTER only "
14494 "has custom type legalization on riscv32");
14496 SDValue LoCounter, HiCounter;
14497 MVT XLenVT = Subtarget.getXLenVT();
14498 if (
N->getOpcode() == ISD::READCYCLECOUNTER) {
14507 N->getOperand(0), LoCounter, HiCounter);
14522 if (
N->getValueType(0) == MVT::i64) {
14523 assert(Subtarget.hasStdExtZilsd() && !Subtarget.is64Bit() &&
14524 "Unexpected custom legalisation");
14526 if (!Subtarget.enableUnalignedScalarMem() && Ld->
getAlign() < 8)
14531 RISCVISD::LD_RV32,
DL,
14532 DAG.
getVTList({MVT::i32, MVT::i32, MVT::Other}),
14533 {Ld->getChain(), Ld->getBasePtr()}, MVT::i64, Ld->
getMemOperand());
14537 Results.append({Pair, Result.getValue(2)});
14541 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14542 "Unexpected custom legalisation");
14553 unsigned Size =
N->getSimpleValueType(0).getSizeInBits();
14554 unsigned XLen = Subtarget.getXLen();
14557 assert(
Size == (XLen * 2) &&
"Unexpected custom legalisation");
14565 if (LHSIsU == RHSIsU)
14569 MVT XLenVT = Subtarget.getXLenVT();
14582 if (RHSIsU && LHSIsS && !RHSIsS)
14583 Results.push_back(MakeMULPair(LHS, RHS));
14584 else if (LHSIsU && RHSIsS && !LHSIsS)
14585 Results.push_back(MakeMULPair(RHS, LHS));
14593 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14594 "Unexpected custom legalisation");
14600 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14601 "Unexpected custom legalisation");
14604 if (
N->getOpcode() ==
ISD::SHL && Subtarget.hasStdExtZbs() &&
14629 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14630 "Unexpected custom legalisation");
14631 assert((Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb() ||
14632 Subtarget.hasVendorXTHeadBb()) &&
14633 "Unexpected custom legalization");
14635 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()))
14643 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14644 "Unexpected custom legalisation");
14650 unsigned Opc = IsCTZ ? RISCVISD::CTZW : RISCVISD::CLZW;
14658 MVT VT =
N->getSimpleValueType(0);
14659 assert((VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32) &&
14660 Subtarget.is64Bit() && Subtarget.hasStdExtM() &&
14661 "Unexpected custom legalisation");
14673 if (VT != MVT::i32)
14681 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14682 "Unexpected custom legalisation");
14703 EVT OType =
N->getValueType(1);
14715 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14716 "Unexpected custom legalisation");
14733 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1), Res,
14737 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1),
N->getOperand(0),
14744 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1), Res, LHS,
14754 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14755 !Subtarget.hasStdExtZbb() &&
"Unexpected custom legalisation");
14763 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14764 "Unexpected custom legalisation");
14769 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14770 "Unexpected custom legalisation");
14772 if (Subtarget.hasStdExtZbb()) {
14805 case ISD::BITCAST: {
14806 EVT VT =
N->getValueType(0);
14810 MVT XLenVT = Subtarget.getXLenVT();
14811 if (VT == MVT::i16 &&
14812 ((Op0VT == MVT::f16 && Subtarget.hasStdExtZfhminOrZhinxmin()) ||
14813 (Op0VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
14816 }
else if (VT == MVT::i32 && Op0VT == MVT::f32 && Subtarget.is64Bit() &&
14817 Subtarget.hasStdExtFOrZfinx()) {
14819 DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Op0);
14821 }
else if (VT == MVT::i64 && Op0VT == MVT::f64 && !Subtarget.is64Bit() &&
14822 Subtarget.hasStdExtDOrZdinx()) {
14824 DAG.
getVTList(MVT::i32, MVT::i32), Op0);
14843 assert(
N->getValueType(0) == MVT::i8 && Subtarget.hasStdExtZbkb() &&
14844 "Unexpected custom legalisation");
14845 MVT XLenVT = Subtarget.getXLenVT();
14853 case RISCVISD::BREV8:
14854 case RISCVISD::ORC_B: {
14855 MVT VT =
N->getSimpleValueType(0);
14856 MVT XLenVT = Subtarget.getXLenVT();
14857 assert((VT == MVT::i16 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
14858 "Unexpected custom legalisation");
14859 assert(((
N->getOpcode() == RISCVISD::BREV8 && Subtarget.hasStdExtZbkb()) ||
14860 (
N->getOpcode() == RISCVISD::ORC_B && Subtarget.hasStdExtZbb())) &&
14861 "Unexpected extension");
14887 assert(!Subtarget.is64Bit() &&
N->getValueType(0) == MVT::i64 &&
14889 "Unexpected EXTRACT_VECTOR_ELT legalization");
14892 MVT ContainerVT = VecVT;
14898 MVT XLenVT = Subtarget.getXLenVT();
14907 DAG.
getUNDEF(ContainerVT), Vec, Idx, Mask, VL);
14919 DAG.
getNode(RISCVISD::SRL_VL,
DL, ContainerVT, Vec, ThirtyTwoV,
14920 DAG.
getUNDEF(ContainerVT), Mask, VL);
14928 unsigned IntNo =
N->getConstantOperandVal(0);
14932 "Don't know how to custom type legalize this intrinsic!");
14933 case Intrinsic::experimental_get_vector_length: {
14938 case Intrinsic::experimental_cttz_elts: {
14944 case Intrinsic::riscv_orc_b:
14945 case Intrinsic::riscv_brev8:
14946 case Intrinsic::riscv_sha256sig0:
14947 case Intrinsic::riscv_sha256sig1:
14948 case Intrinsic::riscv_sha256sum0:
14949 case Intrinsic::riscv_sha256sum1:
14950 case Intrinsic::riscv_sm3p0:
14951 case Intrinsic::riscv_sm3p1: {
14952 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
14956 case Intrinsic::riscv_orc_b:
Opc = RISCVISD::ORC_B;
break;
14957 case Intrinsic::riscv_brev8:
Opc = RISCVISD::BREV8;
break;
14958 case Intrinsic::riscv_sha256sig0:
Opc = RISCVISD::SHA256SIG0;
break;
14959 case Intrinsic::riscv_sha256sig1:
Opc = RISCVISD::SHA256SIG1;
break;
14960 case Intrinsic::riscv_sha256sum0:
Opc = RISCVISD::SHA256SUM0;
break;
14961 case Intrinsic::riscv_sha256sum1:
Opc = RISCVISD::SHA256SUM1;
break;
14962 case Intrinsic::riscv_sm3p0:
Opc = RISCVISD::SM3P0;
break;
14963 case Intrinsic::riscv_sm3p1:
Opc = RISCVISD::SM3P1;
break;
14972 case Intrinsic::riscv_sm4ks:
14973 case Intrinsic::riscv_sm4ed: {
14975 IntNo == Intrinsic::riscv_sm4ks ? RISCVISD::SM4KS : RISCVISD::SM4ED;
14981 DAG.
getNode(
Opc,
DL, MVT::i64, NewOp0, NewOp1,
N->getOperand(3));
14985 case Intrinsic::riscv_mopr: {
14986 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
14991 RISCVISD::MOP_R,
DL, MVT::i64, NewOp,
14996 case Intrinsic::riscv_moprr: {
14997 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15004 RISCVISD::MOP_RR,
DL, MVT::i64, NewOp0, NewOp1,
15009 case Intrinsic::riscv_clmul: {
15010 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15021 case Intrinsic::riscv_clmulh:
15022 case Intrinsic::riscv_clmulr: {
15023 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15043 unsigned Opc = IntNo == Intrinsic::riscv_clmulh ? RISCVISD::CLMULH
15044 : RISCVISD::CLMULR;
15051 case Intrinsic::riscv_vmv_x_s: {
15052 EVT VT =
N->getValueType(0);
15053 MVT XLenVT = Subtarget.getXLenVT();
15054 if (VT.
bitsLT(XLenVT)) {
15057 Subtarget.getXLenVT(),
N->getOperand(1));
15062 assert(VT == MVT::i64 && !Subtarget.is64Bit() &&
15063 "Unexpected custom legalization");
15079 SDValue LShr32 = DAG.
getNode(RISCVISD::SRL_VL,
DL, VecVT, Vec, ThirtyTwoV,
15090 case ISD::VECREDUCE_ADD:
15091 case ISD::VECREDUCE_AND:
15092 case ISD::VECREDUCE_OR:
15093 case ISD::VECREDUCE_XOR:
15094 case ISD::VECREDUCE_SMAX:
15095 case ISD::VECREDUCE_UMAX:
15096 case ISD::VECREDUCE_SMIN:
15097 case ISD::VECREDUCE_UMIN:
15101 case ISD::VP_REDUCE_ADD:
15102 case ISD::VP_REDUCE_AND:
15103 case ISD::VP_REDUCE_OR:
15104 case ISD::VP_REDUCE_XOR:
15105 case ISD::VP_REDUCE_SMAX:
15106 case ISD::VP_REDUCE_UMAX:
15107 case ISD::VP_REDUCE_SMIN:
15108 case ISD::VP_REDUCE_UMIN:
15129 return ISD::VECREDUCE_ADD;
15131 return ISD::VECREDUCE_UMAX;
15133 return ISD::VECREDUCE_SMAX;
15135 return ISD::VECREDUCE_UMIN;
15137 return ISD::VECREDUCE_SMIN;
15139 return ISD::VECREDUCE_AND;
15141 return ISD::VECREDUCE_OR;
15143 return ISD::VECREDUCE_XOR;
15146 return ISD::VECREDUCE_FADD;
15148 return ISD::VECREDUCE_FMAX;
15150 return ISD::VECREDUCE_FMIN;
15176 const EVT VT =
N->getValueType(0);
15177 const unsigned Opc =
N->getOpcode();
15187 if (!
N->getFlags().hasAllowReassociation())
15198 "Inconsistent mappings");
15202 if (!
LHS.hasOneUse() || !
RHS.hasOneUse())
15230 if (0 == std::min(LHSIdx, RHSIdx) && 1 == std::max(LHSIdx, RHSIdx)) {
15233 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
N->getFlags());
15240 if (
LHS.getOpcode() != ReduceOpc)
15254 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
15255 ReduceVec->
getFlags() &
N->getFlags());
15265 auto BinOpToRVVReduce = [](
unsigned Opc) {
15270 return RISCVISD::VECREDUCE_ADD_VL;
15272 return RISCVISD::VECREDUCE_UMAX_VL;
15274 return RISCVISD::VECREDUCE_SMAX_VL;
15276 return RISCVISD::VECREDUCE_UMIN_VL;
15278 return RISCVISD::VECREDUCE_SMIN_VL;
15280 return RISCVISD::VECREDUCE_AND_VL;
15282 return RISCVISD::VECREDUCE_OR_VL;
15284 return RISCVISD::VECREDUCE_XOR_VL;
15286 return RISCVISD::VECREDUCE_FADD_VL;
15288 return RISCVISD::VECREDUCE_FMAX_VL;
15290 return RISCVISD::VECREDUCE_FMIN_VL;
15294 auto IsReduction = [&BinOpToRVVReduce](
SDValue V,
unsigned Opc) {
15297 V.getOperand(0).getOpcode() == BinOpToRVVReduce(
Opc);
15300 unsigned Opc =
N->getOpcode();
15301 unsigned ReduceIdx;
15302 if (IsReduction(
N->getOperand(0),
Opc))
15304 else if (IsReduction(
N->getOperand(1),
Opc))
15310 if (
Opc ==
ISD::FADD && !
N->getFlags().hasAllowReassociation())
15313 SDValue Extract =
N->getOperand(ReduceIdx);
15326 if (ScalarV.
getOpcode() != RISCVISD::VFMV_S_F_VL &&
15327 ScalarV.
getOpcode() != RISCVISD::VMV_S_X_VL &&
15328 ScalarV.
getOpcode() != RISCVISD::VMV_V_X_VL)
15345 SDValue NewStart =
N->getOperand(1 - ReduceIdx);
15378 EVT VT =
N->getValueType(0);
15394 int64_t C0 = N0C->getSExtValue();
15395 int64_t C1 = N1C->getSExtValue();
15396 if (C0 <= 0 || C1 <= 0)
15399 int64_t Diff = std::abs(C0 - C1);
15405 int64_t Bits = std::min(C0, C1);
15437 if (VShift.
slt(1) || VShift.
sgt(3))
15441 EVT VT =
N->getValueType(0);
15461 EVT VT =
N->getValueType(0);
15489 EVT VT =
N->getValueType(0);
15510 Slct.
getOpcode() != RISCVISD::SELECT_CC) ||
15518 bool SwapSelectOps;
15519 unsigned OpOffset = Slct.
getOpcode() == RISCVISD::SELECT_CC ? 2 : 0;
15524 SwapSelectOps =
false;
15525 NonConstantVal = FalseVal;
15527 SwapSelectOps =
true;
15528 NonConstantVal = TrueVal;
15534 FalseVal = DAG.
getNode(
N->getOpcode(),
SDLoc(
N), VT, OtherOp, NonConstantVal);
15539 if (Slct.
getOpcode() == RISCVISD::SELECT_CC)
15582 EVT VT =
N->getValueType(0);
15597 if (!N0C->hasOneUse())
15599 int64_t C0 = N0C->getSExtValue();
15600 int64_t C1 = N1C->getSExtValue();
15602 if (C0 == -1 || C0 == 0 || C0 == 1 ||
isInt<12>(C1))
15609 }
else if ((C1 / C0 + 1) != 0 &&
isInt<12>(C1 / C0 + 1) &&
15613 }
else if ((C1 / C0 - 1) != 0 &&
isInt<12>(C1 / C0 - 1) &&
15641 EVT VT =
N->getValueType(0);
15672 unsigned OuterExtend =
15676 OuterExtend,
SDLoc(
N), VT,
15684 EVT VT =
N->getValueType(0);
15735 EVT VT =
N->getValueType(0);
15745 APInt ImmValMinus1 = N0C->getAPIntValue() - 1;
15755 if (!isIntEqualitySetCC(CCVal) || !SetCCOpVT.
isInteger())
15778 if (!Subtarget.hasStdExtZbb())
15781 EVT VT =
N->getValueType(0);
15783 if (VT != Subtarget.
getXLenVT() && VT != MVT::i32 && VT != MVT::i16)
15795 unsigned ShiftedAmount = 8 - ShAmtCLeft->getZExtValue();
15797 if (ShiftedAmount >= 8)
15801 SDValue RightShiftOperand = N1;
15803 if (ShiftedAmount != 0) {
15807 if (!ShAmtCRight || ShAmtCRight->getZExtValue() != ShiftedAmount)
15816 if (LeftShiftOperand != RightShiftOperand)
15820 Mask <<= ShiftedAmount;
15826 return DAG.
getNode(RISCVISD::ORC_B,
SDLoc(
N), VT, LeftShiftOperand);
15834 EVT VT =
N->getValueType(0);
15866 bool IsAnd =
N->getOpcode() ==
ISD::AND;
15890 EVT VT =
N->getValueType(0);
15914 EVT VT =
N->getValueType(0);
15941 if (CondLHS != True)
15948 if (!CondRHSC || CondRHSC->
getAPIntValue() != (1ULL << ScalarBits))
15960 if (!FalseRHSC || !FalseRHSC->
isZero())
15980 EVT VT =
N->getValueType(0);
15987 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() && VT == MVT::i1 &&
16030 EVT VT =
N->getValueType(0);
16049 EVT WideVT =
X.getValueType();
16071 if (N0.
getOpcode() != ISD::ATOMIC_LOAD)
16086 if (Mask != ExpectedMask)
16112 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
16150 if (N0.
getOpcode() != RISCVISD::CZERO_EQZ ||
16151 N1.
getOpcode() != RISCVISD::CZERO_NEZ ||
16169 EVT VT =
N->getValueType(0);
16187 if (!Subtarget.hasVendorXqcibm())
16200 if (
N->getValueType(0) != MVT::i32)
16203 unsigned Width, ShAmt;
16220 return DAG.
getNode(RISCVISD::QC_INSB,
DL, MVT::i32,
Ops);
16258 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
16273 if (N0.
getOpcode() == RISCVISD::SLLW &&
16277 return DAG.
getNode(RISCVISD::ROLW,
DL, MVT::i64,
16288 const APInt &Imm = ConstN00->getAPIntValue();
16289 if ((Imm + 1).isSignedIntN(12))
16313 EVT VT =
N->getValueType(0);
16322 bool IsAdd = (
E & 3) == 1;
16323 E -= IsAdd ? 1 : -1;
16327 Result = DAG.
getNode(AddSubOp,
DL, VT, Result, ShiftVal);
16337 uint64_t MulAmtLowBit = MulAmt & (-MulAmt);
16342 ShiftAmt1 = MulAmt + MulAmtLowBit;
16345 ShiftAmt1 = MulAmt - MulAmtLowBit;
16349 EVT VT =
N->getValueType(0);
16363 EVT VT =
N->getValueType(0);
16372 bool ShouldExpandMul =
16374 !Subtarget.hasStdExtZmmul();
16375 if (!ShouldExpandMul)
16394 for (
uint64_t Divisor : {3, 5, 9}) {
16395 if (MulAmt % Divisor != 0)
16397 uint64_t MulAmt2 = MulAmt / Divisor;
16405 X.getConstantOperandVal(1) == UINT64_C(0xffffffff)) {
16408 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, Shl,
16422 if (MulAmt2 == 3 || MulAmt2 == 5 || MulAmt2 == 9) {
16427 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, Mul359,
16438 if (ScaleShift >= 1 && ScaleShift < 4) {
16439 unsigned ShiftAmt =
Log2_64((MulAmt & (MulAmt - 1)));
16443 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT,
X,
16453 for (
uint64_t Divisor : {3, 5, 9}) {
16458 if ((
C >> TZ) == Divisor && (TZ == 1 || TZ == 2 || TZ == 3)) {
16463 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, Mul359,
16469 if (MulAmt > 2 &&
isPowerOf2_64((MulAmt - 1) & (MulAmt - 2))) {
16471 if (ScaleShift >= 1 && ScaleShift < 4) {
16472 unsigned ShiftAmt =
Log2_64(((MulAmt - 1) & (MulAmt - 2)));
16498 for (
uint64_t Divisor : {3, 5, 9}) {
16499 if (MulAmt % Divisor != 0)
16501 uint64_t MulAmt2 = MulAmt / Divisor;
16504 for (
uint64_t Divisor2 : {3, 5, 9}) {
16505 if (MulAmt2 % Divisor2 != 0)
16507 uint64_t MulAmt3 = MulAmt2 / Divisor2;
16514 RISCVISD::SHL_ADD,
DL, VT, Mul359A,
16526 if (!Subtarget.hasStdExtZmmul())
16536 EVT VT =
N->getValueType(0);
16543 if (
N->getOperand(0).getOpcode() !=
ISD::AND ||
16544 N->getOperand(0).getOperand(0).getOpcode() !=
ISD::SRL)
16557 if (!V1.
isMask(HalfSize) || V2 != (1ULL | 1ULL << HalfSize) ||
16558 V3 != (HalfSize - 1))
16568 return DAG.
getNode(ISD::BITCAST,
DL, VT, Sra);
16574 EVT VT =
N->getValueType(0);
16582 unsigned AddSubOpc;
16588 auto IsAddSubWith1 = [&](
SDValue V) ->
bool {
16589 AddSubOpc = V->getOpcode();
16601 if (IsAddSubWith1(N0)) {
16603 return DAG.
getNode(AddSubOpc,
DL, VT, N1, MulVal);
16606 if (IsAddSubWith1(N1)) {
16608 return DAG.
getNode(AddSubOpc,
DL, VT, N0, MulVal);
16623 if (isIndexTypeSigned(IndexType))
16626 if (!
N->hasOneUse())
16629 EVT VT =
N.getValueType();
16668 EVT SrcVT = Src.getValueType();
16672 NewElen = std::max(NewElen, 8U);
16699 EVT OpVT =
X.getValueType();
16707 if (OpSize <= Subtarget.
getXLen() ||
16713 auto IsVectorBitCastCheap = [](
SDValue X) {
16716 X.getOpcode() == ISD::LOAD;
16718 if (!IsVectorBitCastCheap(
X) || !IsVectorBitCastCheap(
Y))
16722 Attribute::NoImplicitFloat))
16729 unsigned VecSize = OpSize / 8;
16741 DAG.
getNode(ISD::VP_REDUCE_OR,
DL, XLenVT,
16754 EVT VT =
N->getValueType(0);
16759 if (!isIntEqualitySetCC(
Cond))
16784 if (OpVT == MVT::i64 && AndRHSInt <= 0xffffffff &&
16788 if (NewC >= -2048 && NewC <= 2048) {
16794 return DAG.
getSetCC(dl, VT, Shift,
16804 if (OpVT != MVT::i64 || !Subtarget.
is64Bit())
16824 const APInt &C1 = N1C->getAPIntValue();
16842 EVT VT =
N->getValueType(0);
16844 unsigned Opc = Src.getOpcode();
16849 if (
Opc == RISCVISD::FMV_X_ANYEXTH && SrcVT.
bitsGE(MVT::i16) &&
16850 Subtarget.hasStdExtZfhmin())
16851 return DAG.
getNode(RISCVISD::FMV_X_SIGNEXTH,
DL, VT, Src.getOperand(0));
16857 return DAG.
getNode(RISCVISD::SLLW,
DL, VT, Src.getOperand(0),
16858 Src.getOperand(1));
16877struct CombineResult;
16879enum ExtKind : uint8_t {
16911struct NodeExtensionHelper {
16920 bool SupportsFPExt;
16922 bool SupportsBF16Ext;
16925 bool EnforceOneUse;
16935 case RISCVISD::VSEXT_VL:
16936 case RISCVISD::VZEXT_VL:
16937 case RISCVISD::FP_EXTEND_VL:
16940 return OrigOperand;
16946 return OrigOperand.
getOpcode() == RISCVISD::VMV_V_X_VL ||
16951 unsigned getExtOpc(ExtKind SupportsExt)
const {
16952 switch (SupportsExt) {
16953 case ExtKind::SExt:
16954 return RISCVISD::VSEXT_VL;
16955 case ExtKind::ZExt:
16956 return RISCVISD::VZEXT_VL;
16957 case ExtKind::FPExt:
16958 case ExtKind::BF16Ext:
16959 return RISCVISD::FP_EXTEND_VL;
16967 SDValue getOrCreateExtendedOp(SDNode *Root, SelectionDAG &DAG,
16968 const RISCVSubtarget &Subtarget,
16969 std::optional<ExtKind> SupportsExt)
const {
16970 if (!SupportsExt.has_value())
16971 return OrigOperand;
16973 MVT NarrowVT = getNarrowType(Root, *SupportsExt);
16977 if (
Source.getValueType() == NarrowVT)
16980 unsigned ExtOpc = getExtOpc(*SupportsExt);
16983 SDLoc
DL(OrigOperand);
16984 auto [
Mask, VL] = getMaskAndVL(Root, DAG, Subtarget);
16988 case RISCVISD::VSEXT_VL:
16989 case RISCVISD::VZEXT_VL:
16990 case RISCVISD::FP_EXTEND_VL:
16991 return DAG.
getNode(ExtOpc,
DL, NarrowVT, Source, Mask, VL);
16994 case RISCVISD::VMV_V_X_VL:
16995 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, NarrowVT,
16997 case RISCVISD::VFMV_V_F_VL:
16999 assert(
Source.getOpcode() == ISD::FP_EXTEND &&
"Unexpected source");
17002 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL, NarrowVT,
17003 DAG.
getUNDEF(NarrowVT), Source, VL);
17016 static MVT getNarrowType(
const SDNode *Root, ExtKind SupportsExt) {
17022 MVT EltVT = SupportsExt == ExtKind::BF16Ext ? MVT::bf16
17023 : SupportsExt == ExtKind::FPExt
17025 : MVT::getIntegerVT(NarrowSize);
17027 assert((
int)NarrowSize >= (SupportsExt == ExtKind::FPExt ? 16 : 8) &&
17028 "Trying to extend something we can't represent");
17035 static unsigned getSExtOpcode(
unsigned Opcode) {
17038 case RISCVISD::ADD_VL:
17039 case RISCVISD::VWADD_W_VL:
17040 case RISCVISD::VWADDU_W_VL:
17042 case RISCVISD::OR_VL:
17043 return RISCVISD::VWADD_VL;
17045 case RISCVISD::SUB_VL:
17046 case RISCVISD::VWSUB_W_VL:
17047 case RISCVISD::VWSUBU_W_VL:
17048 return RISCVISD::VWSUB_VL;
17050 case RISCVISD::MUL_VL:
17051 return RISCVISD::VWMUL_VL;
17059 static unsigned getZExtOpcode(
unsigned Opcode) {
17062 case RISCVISD::ADD_VL:
17063 case RISCVISD::VWADD_W_VL:
17064 case RISCVISD::VWADDU_W_VL:
17066 case RISCVISD::OR_VL:
17067 return RISCVISD::VWADDU_VL;
17069 case RISCVISD::SUB_VL:
17070 case RISCVISD::VWSUB_W_VL:
17071 case RISCVISD::VWSUBU_W_VL:
17072 return RISCVISD::VWSUBU_VL;
17074 case RISCVISD::MUL_VL:
17075 return RISCVISD::VWMULU_VL;
17077 case RISCVISD::SHL_VL:
17078 return RISCVISD::VWSLL_VL;
17086 static unsigned getFPExtOpcode(
unsigned Opcode) {
17088 case RISCVISD::FADD_VL:
17089 case RISCVISD::VFWADD_W_VL:
17090 return RISCVISD::VFWADD_VL;
17091 case RISCVISD::FSUB_VL:
17092 case RISCVISD::VFWSUB_W_VL:
17093 return RISCVISD::VFWSUB_VL;
17094 case RISCVISD::FMUL_VL:
17095 return RISCVISD::VFWMUL_VL;
17096 case RISCVISD::VFMADD_VL:
17097 return RISCVISD::VFWMADD_VL;
17098 case RISCVISD::VFMSUB_VL:
17099 return RISCVISD::VFWMSUB_VL;
17100 case RISCVISD::VFNMADD_VL:
17101 return RISCVISD::VFWNMADD_VL;
17102 case RISCVISD::VFNMSUB_VL:
17103 return RISCVISD::VFWNMSUB_VL;
17111 static unsigned getSUOpcode(
unsigned Opcode) {
17113 "SU is only supported for MUL");
17114 return RISCVISD::VWMULSU_VL;
17119 static unsigned getWOpcode(
unsigned Opcode, ExtKind SupportsExt) {
17122 case RISCVISD::ADD_VL:
17124 case RISCVISD::OR_VL:
17125 return SupportsExt == ExtKind::SExt ? RISCVISD::VWADD_W_VL
17126 : RISCVISD::VWADDU_W_VL;
17128 case RISCVISD::SUB_VL:
17129 return SupportsExt == ExtKind::SExt ? RISCVISD::VWSUB_W_VL
17130 : RISCVISD::VWSUBU_W_VL;
17131 case RISCVISD::FADD_VL:
17132 return RISCVISD::VFWADD_W_VL;
17133 case RISCVISD::FSUB_VL:
17134 return RISCVISD::VFWSUB_W_VL;
17140 using CombineToTry = std::function<std::optional<CombineResult>(
17141 SDNode * ,
const NodeExtensionHelper & ,
17142 const NodeExtensionHelper & , SelectionDAG &,
17143 const RISCVSubtarget &)>;
17146 bool needToPromoteOtherUsers()
const {
return EnforceOneUse; }
17148 void fillUpExtensionSupportForSplat(SDNode *Root, SelectionDAG &DAG,
17149 const RISCVSubtarget &Subtarget) {
17154 "Unexpected Opcode");
17167 unsigned ScalarBits =
Op.getValueSizeInBits();
17169 if (ScalarBits < EltBits) {
17171 assert(
Opc == RISCVISD::VMV_V_X_VL && EltBits == 64 && ScalarBits == 32 &&
17172 !Subtarget.
is64Bit() &&
"Unexpected splat");
17174 SupportsSExt =
true;
17178 SupportsZExt =
true;
17180 EnforceOneUse =
false;
17184 unsigned NarrowSize = EltBits / 2;
17187 if (NarrowSize < 8)
17191 SupportsSExt =
true;
17195 SupportsZExt =
true;
17197 EnforceOneUse =
false;
17200 bool isSupportedFPExtend(MVT NarrowEltVT,
const RISCVSubtarget &Subtarget) {
17201 return (NarrowEltVT == MVT::f32 ||
17205 bool isSupportedBF16Extend(MVT NarrowEltVT,
const RISCVSubtarget &Subtarget) {
17206 return NarrowEltVT == MVT::bf16 && Subtarget.hasStdExtZvfbfwma();
17211 void fillUpExtensionSupport(SDNode *Root, SelectionDAG &DAG,
17212 const RISCVSubtarget &Subtarget) {
17213 SupportsZExt =
false;
17214 SupportsSExt =
false;
17215 SupportsFPExt =
false;
17216 SupportsBF16Ext =
false;
17217 EnforceOneUse =
true;
17239 case RISCVISD::VZEXT_VL:
17240 SupportsZExt =
true;
17242 case RISCVISD::VSEXT_VL:
17243 SupportsSExt =
true;
17245 case RISCVISD::FP_EXTEND_VL: {
17248 if (isSupportedFPExtend(NarrowEltVT, Subtarget))
17249 SupportsFPExt =
true;
17250 if (isSupportedBF16Extend(NarrowEltVT, Subtarget))
17251 SupportsBF16Ext =
true;
17256 case RISCVISD::VMV_V_X_VL:
17257 fillUpExtensionSupportForSplat(Root, DAG, Subtarget);
17259 case RISCVISD::VFMV_V_F_VL: {
17266 if (
Op.getOpcode() != ISD::FP_EXTEND)
17270 unsigned ScalarBits =
Op.getOperand(0).getValueSizeInBits();
17271 if (NarrowSize != ScalarBits)
17274 if (isSupportedFPExtend(
Op.getOperand(0).getSimpleValueType(), Subtarget))
17275 SupportsFPExt =
true;
17276 if (isSupportedBF16Extend(
Op.getOperand(0).getSimpleValueType(),
17278 SupportsBF16Ext =
true;
17287 static bool isSupportedRoot(
const SDNode *Root,
17288 const RISCVSubtarget &Subtarget) {
17300 case RISCVISD::ADD_VL:
17301 case RISCVISD::MUL_VL:
17302 case RISCVISD::VWADD_W_VL:
17303 case RISCVISD::VWADDU_W_VL:
17304 case RISCVISD::SUB_VL:
17305 case RISCVISD::VWSUB_W_VL:
17306 case RISCVISD::VWSUBU_W_VL:
17308 case RISCVISD::FADD_VL:
17309 case RISCVISD::FSUB_VL:
17310 case RISCVISD::FMUL_VL:
17311 case RISCVISD::VFWADD_W_VL:
17312 case RISCVISD::VFWSUB_W_VL:
17314 case RISCVISD::OR_VL:
17318 Subtarget.hasStdExtZvbb();
17319 case RISCVISD::SHL_VL:
17320 return Subtarget.hasStdExtZvbb();
17321 case RISCVISD::VFMADD_VL:
17322 case RISCVISD::VFNMSUB_VL:
17323 case RISCVISD::VFNMADD_VL:
17324 case RISCVISD::VFMSUB_VL:
17332 NodeExtensionHelper(SDNode *Root,
unsigned OperandIdx, SelectionDAG &DAG,
17333 const RISCVSubtarget &Subtarget) {
17334 assert(isSupportedRoot(Root, Subtarget) &&
17335 "Trying to build an helper with an "
17336 "unsupported root");
17337 assert(OperandIdx < 2 &&
"Requesting something else than LHS or RHS");
17347 case RISCVISD::VWADD_W_VL:
17348 case RISCVISD::VWADDU_W_VL:
17349 case RISCVISD::VWSUB_W_VL:
17350 case RISCVISD::VWSUBU_W_VL:
17351 case RISCVISD::VFWADD_W_VL:
17352 case RISCVISD::VFWSUB_W_VL:
17353 if (OperandIdx == 1) {
17355 Opc == RISCVISD::VWADDU_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL;
17357 Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWSUB_W_VL;
17359 Opc == RISCVISD::VFWADD_W_VL ||
Opc == RISCVISD::VFWSUB_W_VL;
17362 EnforceOneUse =
false;
17367 fillUpExtensionSupport(Root, DAG, Subtarget);
17373 static std::pair<SDValue, SDValue>
17374 getMaskAndVL(
const SDNode *Root, SelectionDAG &DAG,
17375 const RISCVSubtarget &Subtarget) {
17376 assert(isSupportedRoot(Root, Subtarget) &&
"Unexpected root");
17395 switch (
N->getOpcode()) {
17399 case RISCVISD::ADD_VL:
17400 case RISCVISD::MUL_VL:
17401 case RISCVISD::OR_VL:
17402 case RISCVISD::VWADD_W_VL:
17403 case RISCVISD::VWADDU_W_VL:
17404 case RISCVISD::FADD_VL:
17405 case RISCVISD::FMUL_VL:
17406 case RISCVISD::VFWADD_W_VL:
17407 case RISCVISD::VFMADD_VL:
17408 case RISCVISD::VFNMSUB_VL:
17409 case RISCVISD::VFNMADD_VL:
17410 case RISCVISD::VFMSUB_VL:
17413 case RISCVISD::SUB_VL:
17414 case RISCVISD::VWSUB_W_VL:
17415 case RISCVISD::VWSUBU_W_VL:
17416 case RISCVISD::FSUB_VL:
17417 case RISCVISD::VFWSUB_W_VL:
17419 case RISCVISD::SHL_VL:
17438struct CombineResult {
17440 unsigned TargetOpcode;
17442 std::optional<ExtKind> LHSExt;
17443 std::optional<ExtKind> RHSExt;
17447 NodeExtensionHelper
LHS;
17449 NodeExtensionHelper
RHS;
17451 CombineResult(
unsigned TargetOpcode, SDNode *Root,
17452 const NodeExtensionHelper &
LHS, std::optional<ExtKind> LHSExt,
17453 const NodeExtensionHelper &
RHS, std::optional<ExtKind> RHSExt)
17454 : TargetOpcode(TargetOpcode), LHSExt(LHSExt), RHSExt(RHSExt), Root(Root),
17460 SDValue materialize(SelectionDAG &DAG,
17461 const RISCVSubtarget &Subtarget)
const {
17463 std::tie(Mask, VL) =
17464 NodeExtensionHelper::getMaskAndVL(Root, DAG, Subtarget);
17478 LHS.getOrCreateExtendedOp(Root, DAG, Subtarget, LHSExt),
17479 RHS.getOrCreateExtendedOp(Root, DAG, Subtarget, RHSExt),
17480 Passthru, Mask, VL);
17494static std::optional<CombineResult>
17495canFoldToVWWithSameExtensionImpl(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17496 const NodeExtensionHelper &
RHS,
17499 if ((AllowExtMask & ExtKind::ZExt) &&
LHS.SupportsZExt &&
RHS.SupportsZExt)
17500 return CombineResult(NodeExtensionHelper::getZExtOpcode(Root->
getOpcode()),
17501 Root,
LHS, {ExtKind::ZExt},
RHS,
17503 if ((AllowExtMask & ExtKind::SExt) &&
LHS.SupportsSExt &&
RHS.SupportsSExt)
17504 return CombineResult(NodeExtensionHelper::getSExtOpcode(Root->
getOpcode()),
17505 Root,
LHS, {ExtKind::SExt},
RHS,
17507 if ((AllowExtMask & ExtKind::FPExt) &&
LHS.SupportsFPExt &&
RHS.SupportsFPExt)
17508 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
17509 Root,
LHS, {ExtKind::FPExt},
RHS,
17511 if ((AllowExtMask & ExtKind::BF16Ext) &&
LHS.SupportsBF16Ext &&
17512 RHS.SupportsBF16Ext)
17513 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
17514 Root,
LHS, {ExtKind::BF16Ext},
RHS,
17515 {ExtKind::BF16Ext});
17516 return std::nullopt;
17525static std::optional<CombineResult>
17526canFoldToVWWithSameExtension(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17529 return canFoldToVWWithSameExtensionImpl(
17530 Root,
LHS,
RHS, ExtKind::ZExt | ExtKind::SExt | ExtKind::FPExt, DAG,
17538static std::optional<CombineResult>
17539canFoldToVW_W(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17542 if (
RHS.SupportsFPExt)
17543 return CombineResult(
17544 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::FPExt),
17545 Root,
LHS, std::nullopt,
RHS, {ExtKind::FPExt});
17552 return CombineResult(
17553 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::ZExt), Root,
17554 LHS, std::nullopt,
RHS, {ExtKind::ZExt});
17556 return CombineResult(
17557 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::SExt), Root,
17558 LHS, std::nullopt,
RHS, {ExtKind::SExt});
17559 return std::nullopt;
17566static std::optional<CombineResult>
17567canFoldToVWWithSEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17570 return canFoldToVWWithSameExtensionImpl(Root,
LHS,
RHS, ExtKind::SExt, DAG,
17578static std::optional<CombineResult>
17579canFoldToVWWithZEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17582 return canFoldToVWWithSameExtensionImpl(Root,
LHS,
RHS, ExtKind::ZExt, DAG,
17590static std::optional<CombineResult>
17591canFoldToVWWithFPEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17594 return canFoldToVWWithSameExtensionImpl(Root,
LHS,
RHS, ExtKind::FPExt, DAG,
17602static std::optional<CombineResult>
17603canFoldToVWWithBF16EXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17606 return canFoldToVWWithSameExtensionImpl(Root,
LHS,
RHS, ExtKind::BF16Ext, DAG,
17614static std::optional<CombineResult>
17615canFoldToVW_SU(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17619 if (!
LHS.SupportsSExt || !
RHS.SupportsZExt)
17620 return std::nullopt;
17621 return CombineResult(NodeExtensionHelper::getSUOpcode(Root->
getOpcode()),
17622 Root,
LHS, {ExtKind::SExt},
RHS,
17627NodeExtensionHelper::getSupportedFoldings(
const SDNode *Root) {
17633 case RISCVISD::ADD_VL:
17634 case RISCVISD::SUB_VL:
17635 case RISCVISD::OR_VL:
17636 case RISCVISD::FADD_VL:
17637 case RISCVISD::FSUB_VL:
17639 Strategies.
push_back(canFoldToVWWithSameExtension);
17643 case RISCVISD::FMUL_VL:
17644 case RISCVISD::VFMADD_VL:
17645 case RISCVISD::VFMSUB_VL:
17646 case RISCVISD::VFNMADD_VL:
17647 case RISCVISD::VFNMSUB_VL:
17648 Strategies.
push_back(canFoldToVWWithSameExtension);
17649 if (Root->
getOpcode() == RISCVISD::VFMADD_VL)
17650 Strategies.
push_back(canFoldToVWWithBF16EXT);
17653 case RISCVISD::MUL_VL:
17655 Strategies.
push_back(canFoldToVWWithSameExtension);
17660 case RISCVISD::SHL_VL:
17662 Strategies.
push_back(canFoldToVWWithZEXT);
17664 case RISCVISD::VWADD_W_VL:
17665 case RISCVISD::VWSUB_W_VL:
17667 Strategies.
push_back(canFoldToVWWithSEXT);
17669 case RISCVISD::VWADDU_W_VL:
17670 case RISCVISD::VWSUBU_W_VL:
17672 Strategies.
push_back(canFoldToVWWithZEXT);
17674 case RISCVISD::VFWADD_W_VL:
17675 case RISCVISD::VFWSUB_W_VL:
17677 Strategies.
push_back(canFoldToVWWithFPEXT);
17688 assert(
N->getOpcode() == RISCVISD::ADD_VL);
17691 SDValue Passthru =
N->getOperand(2);
17725 if (!NodeExtensionHelper::isSupportedRoot(
N, Subtarget))
17731 Inserted.insert(
N);
17734 while (!Worklist.
empty()) {
17737 NodeExtensionHelper
LHS(Root, 0, DAG, Subtarget);
17738 NodeExtensionHelper
RHS(Root, 1, DAG, Subtarget);
17739 auto AppendUsersIfNeeded = [&Worklist, &Subtarget,
17740 &Inserted](
const NodeExtensionHelper &
Op) {
17741 if (
Op.needToPromoteOtherUsers()) {
17744 if (!NodeExtensionHelper::isSupportedRoot(TheUser, Subtarget))
17749 if (Inserted.insert(TheUser).second)
17762 NodeExtensionHelper::getSupportedFoldings(Root);
17764 assert(!FoldingStrategies.
empty() &&
"Nothing to be folded");
17765 bool Matched =
false;
17766 for (
int Attempt = 0;
17767 (Attempt != 1 + NodeExtensionHelper::isCommutative(Root)) && !Matched;
17770 for (NodeExtensionHelper::CombineToTry FoldingStrategy :
17771 FoldingStrategies) {
17772 std::optional<CombineResult> Res =
17773 FoldingStrategy(Root,
LHS,
RHS, DAG, Subtarget);
17780 if (Res->LHSExt.has_value())
17781 if (!AppendUsersIfNeeded(
LHS))
17783 if (Res->RHSExt.has_value())
17784 if (!AppendUsersIfNeeded(
RHS))
17796 SDValue InputRootReplacement;
17803 for (CombineResult Res : CombinesToApply) {
17804 SDValue NewValue = Res.materialize(DAG, Subtarget);
17805 if (!InputRootReplacement) {
17807 "First element is expected to be the current node");
17808 InputRootReplacement = NewValue;
17813 for (std::pair<SDValue, SDValue> OldNewValues : ValuesToReplace) {
17817 return InputRootReplacement;
17824 unsigned Opc =
N->getOpcode();
17825 assert(
Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWADDU_W_VL ||
17826 Opc == RISCVISD::VWSUB_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL);
17829 SDValue MergeOp =
N->getOperand(1);
17830 unsigned MergeOpc = MergeOp.
getOpcode();
17832 if (MergeOpc != RISCVISD::VMERGE_VL && MergeOpc !=
ISD::VSELECT)
17841 SDValue Passthru =
N->getOperand(2);
17847 if (Mask.getOpcode() != RISCVISD::VMSET_VL)
17855 Z = Z.getOperand(1);
17861 {Y, X, Y, MergeOp->getOperand(0), N->getOperand(4)},
17868 [[maybe_unused]]
unsigned Opc =
N->getOpcode();
17869 assert(
Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWADDU_W_VL ||
17870 Opc == RISCVISD::VWSUB_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL);
17897 EVT NewMemVT = (MemVT == MVT::i32) ? MVT::i64 : MVT::i128;
17902 if (LSNode1->
getOpcode() == ISD::LOAD) {
17905 if (MemVT == MVT::i32)
17906 Opcode = (Ext ==
ISD::ZEXTLOAD) ? RISCVISD::TH_LWUD : RISCVISD::TH_LWD;
17908 Opcode = RISCVISD::TH_LDD;
17911 Opcode,
SDLoc(LSNode1), DAG.
getVTList({XLenVT, XLenVT, MVT::Other}),
17912 {LSNode1->getChain(), BasePtr,
17913 DAG.getConstant(Imm, SDLoc(LSNode1), XLenVT)},
17924 unsigned Opcode = (MemVT == MVT::i32) ? RISCVISD::TH_SWD : RISCVISD::TH_SDD;
17928 {LSNode1->getChain(), LSNode1->getOperand(1), LSNode2->getOperand(1),
17929 BasePtr, DAG.getConstant(Imm, SDLoc(LSNode1), XLenVT)},
17946 if (!Subtarget.hasVendorXTHeadMemPair())
17951 unsigned OpNum = LSNode1->
getOpcode() == ISD::LOAD ? 1 : 2;
17958 auto ExtractBaseAndOffset = [](
SDValue Ptr) -> std::pair<SDValue, uint64_t> {
17961 return {
Ptr->getOperand(0), C1->getZExtValue()};
17965 auto [Base1, Offset1] = ExtractBaseAndOffset(LSNode1->
getOperand(OpNum));
17986 auto [Base2, Offset2] = ExtractBaseAndOffset(LSNode2->
getOperand(OpNum));
17989 if (Base1 != Base2)
17993 bool Valid =
false;
17994 if (MemVT == MVT::i32) {
17998 }
else if (MemVT == MVT::i64) {
18034 if (Src->isStrictFPOpcode())
18042 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
18052 EVT VT =
N->getValueType(0);
18055 MVT SrcVT = Src.getSimpleValueType();
18056 MVT SrcContainerVT = SrcVT;
18084 IsSigned ? RISCVISD::VFCVT_RTZ_X_F_VL : RISCVISD::VFCVT_RTZ_XU_F_VL;
18085 FpToInt = DAG.
getNode(
Opc,
DL, ContainerVT, XVal, Mask, VL);
18088 IsSigned ? RISCVISD::VFCVT_RM_X_F_VL : RISCVISD::VFCVT_RM_XU_F_VL;
18089 FpToInt = DAG.
getNode(
Opc,
DL, ContainerVT, XVal, Mask,
18102 if (VT != MVT::i32 && VT != XLenVT)
18107 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
18109 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
18132 EVT DstVT =
N->getValueType(0);
18133 if (DstVT != XLenVT)
18139 if (Src->isStrictFPOpcode())
18147 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
18159 if (SatVT == DstVT)
18160 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
18161 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
18162 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
18167 Src = Src.getOperand(0);
18175 if (
Opc == RISCVISD::FCVT_WU_RV64)
18188 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected extension");
18194 EVT VT =
N->getValueType(0);
18200 return DAG.
getNode(RISCVISD::BREV8,
DL, VT, Src.getOperand(0));
18213 EVT LoadVT = VPLoad->getValueType(0);
18217 N->getOperand(2) != VPLoad->getVectorLength() ||
18218 !
N->getOperand(0).hasOneUse())
18225 SDValue LoadMask = VPLoad->getMask();
18230 if (LoadMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
18232 LoadMask.
getOperand(2) != VPLoad->getVectorLength())
18240 SDValue NumElem = VPLoad->getVectorLength();
18241 uint64_t ElemWidthByte = VPLoad->getValueType(0).getScalarSizeInBits() / 8;
18253 PtrInfo, VPLoad->getMemOperand()->getFlags(),
18257 LoadVT,
DL, VPLoad->getChain(),
Base, Stride, LoadMask,
18258 VPLoad->getVectorLength(), MMO, VPLoad->isExpandingLoad());
18272 if (VPStore->getValue().getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE)
18275 SDValue VPReverse = VPStore->getValue();
18281 VPStore->getVectorLength() != VPReverse.
getOperand(2) ||
18285 SDValue StoreMask = VPStore->getMask();
18290 if (StoreMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
18292 StoreMask.
getOperand(2) != VPStore->getVectorLength())
18300 SDValue NumElem = VPStore->getVectorLength();
18314 PtrInfo, VPStore->getMemOperand()->getFlags(),
18319 VPStore->getOffset(), Stride, StoreMask, VPStore->getVectorLength(),
18320 VPStore->getMemoryVT(), MMO, VPStore->getAddressingMode(),
18321 VPStore->isTruncatingStore(), VPStore->isCompressingStore());
18333 EVT VT =
N->getValueType(0);
18345 if (In.getOpcode() != ISD::VP_SRL || In.getOperand(2) != Mask ||
18346 In.getOperand(3) != VL)
18355 if (
LHS.getOpcode() != ISD::VP_ADD ||
LHS.getOperand(2) != Mask ||
18356 LHS.getOperand(3) != VL)
18363 if (V.getOpcode() != ISD::VP_ADD || V.getOperand(2) != Mask ||
18364 V.getOperand(3) != VL)
18376 if (!FindAdd(LHS0, LHS1) && !FindAdd(LHS1, LHS0))
18390 if (
Op.getOpcode() != ISD::VP_ZERO_EXTEND ||
Op.getOperand(1) != Mask ||
18391 Op.getOperand(2) != VL)
18401 Operands[0].getOperand(0), Mask, VL);
18403 Operands[1].getOperand(0), Mask, VL);
18407 return DAG.
getNode(RISCVISD::AVGCEILU_VL,
DL, VT,
18408 {NewOp0, NewOp1, DAG.
getUNDEF(VT), Mask, VL});
18420 case RISCVISD::VFMADD_VL: Opcode = RISCVISD::VFNMSUB_VL;
break;
18421 case RISCVISD::VFNMSUB_VL: Opcode = RISCVISD::VFMADD_VL;
break;
18422 case RISCVISD::VFNMADD_VL: Opcode = RISCVISD::VFMSUB_VL;
break;
18423 case RISCVISD::VFMSUB_VL: Opcode = RISCVISD::VFNMADD_VL;
break;
18424 case RISCVISD::STRICT_VFMADD_VL: Opcode = RISCVISD::STRICT_VFNMSUB_VL;
break;
18425 case RISCVISD::STRICT_VFNMSUB_VL: Opcode = RISCVISD::STRICT_VFMADD_VL;
break;
18426 case RISCVISD::STRICT_VFNMADD_VL: Opcode = RISCVISD::STRICT_VFMSUB_VL;
break;
18427 case RISCVISD::STRICT_VFMSUB_VL: Opcode = RISCVISD::STRICT_VFNMADD_VL;
break;
18437 case RISCVISD::VFMADD_VL: Opcode = RISCVISD::VFMSUB_VL;
break;
18438 case RISCVISD::VFMSUB_VL: Opcode = RISCVISD::VFMADD_VL;
break;
18439 case RISCVISD::VFNMADD_VL: Opcode = RISCVISD::VFNMSUB_VL;
break;
18440 case RISCVISD::VFNMSUB_VL: Opcode = RISCVISD::VFNMADD_VL;
break;
18441 case RISCVISD::STRICT_VFMADD_VL: Opcode = RISCVISD::STRICT_VFMSUB_VL;
break;
18442 case RISCVISD::STRICT_VFMSUB_VL: Opcode = RISCVISD::STRICT_VFMADD_VL;
break;
18443 case RISCVISD::STRICT_VFNMADD_VL: Opcode = RISCVISD::STRICT_VFNMSUB_VL;
break;
18444 case RISCVISD::STRICT_VFNMSUB_VL: Opcode = RISCVISD::STRICT_VFNMADD_VL;
break;
18457 unsigned Offset = IsStrict ? 1 : 0;
18464 auto invertIfNegative = [&Mask, &VL](
SDValue &V) {
18465 if (V.getOpcode() == RISCVISD::FNEG_VL && V.getOperand(1) == Mask &&
18466 V.getOperand(2) == VL) {
18468 V = V.getOperand(0);
18475 bool NegA = invertIfNegative(
A);
18476 bool NegB = invertIfNegative(
B);
18477 bool NegC = invertIfNegative(
C);
18480 if (!NegA && !NegB && !NegC)
18486 {N->getOperand(0), A, B, C, Mask, VL});
18510 EVT VT =
N->getValueType(0);
18517 uint64_t ShAmt =
N->getConstantOperandVal(1);
18530 if (LShAmt < ExtSize) {
18543 if (ShAmt > 32 || VT != MVT::i64)
18573 U->getConstantOperandVal(1) > 32)
18628 if (!
Cond.hasOneUse())
18647 EVT VT =
Cond.getValueType();
18692 LHS =
LHS.getOperand(0);
18702 LHS.getOperand(0).getValueType() == Subtarget.
getXLenVT()) {
18710 RHS =
LHS.getOperand(1);
18711 LHS =
LHS.getOperand(0);
18720 auto isXorImmediate = [](
const SDValue &
Op) ->
bool {
18722 return isInt<12>(XorCnst->getSExtValue());
18726 auto singleBitOp = [&DAG](
const SDValue &VarOp,
18727 const SDValue &ConstOp) ->
bool {
18730 return (XorCnst->getSExtValue() == 1) &&
18735 auto onlyUsedBySelectOrBR = [](
const SDValue &
Op) ->
bool {
18736 for (
const SDNode *UserNode :
Op->users()) {
18737 const unsigned Opcode = UserNode->getOpcode();
18738 if (Opcode != RISCVISD::SELECT_CC && Opcode != RISCVISD::BR_CC)
18743 auto isFoldableXorEq = [isXorImmediate, singleBitOp, onlyUsedBySelectOrBR](
18746 (!isXorImmediate(
LHS.getOperand(1)) ||
18747 singleBitOp(
LHS.getOperand(0),
LHS.getOperand(1)) ||
18748 onlyUsedBySelectOrBR(
LHS));
18751 if (isFoldableXorEq(
LHS,
RHS)) {
18752 RHS =
LHS.getOperand(1);
18753 LHS =
LHS.getOperand(0);
18779 if (Subtarget.hasVendorXAndesPerf()) {
18789 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
18832 bool Commutative =
true;
18833 unsigned Opc = TrueVal.getOpcode();
18843 Commutative =
false;
18853 if (!TrueVal.hasOneUse())
18857 if (FalseVal == TrueVal.getOperand(0))
18859 else if (Commutative && FalseVal == TrueVal.getOperand(1))
18864 EVT VT =
N->getValueType(0);
18866 SDValue OtherOp = TrueVal.getOperand(1 - OpToFold);
18872 assert(IdentityOperand &&
"No identity operand!");
18877 DAG.
getSelect(
DL, OtherOpVT,
N->getOperand(0), OtherOp, IdentityOperand);
18878 return DAG.
getNode(TrueVal.getOpcode(),
DL, VT, FalseVal, NewSel);
18899 CountZeroes =
N->getOperand(2);
18900 ValOnZero =
N->getOperand(1);
18902 CountZeroes =
N->getOperand(1);
18903 ValOnZero =
N->getOperand(2);
18922 if (
Cond->getOperand(0) != CountZeroesArgument)
18941 CountZeroes, BitWidthMinusOne);
18951 EVT VT =
N->getValueType(0);
18952 EVT CondVT =
Cond.getValueType();
18960 (Subtarget.
hasCZEROLike() || Subtarget.hasVendorXTHeadCondMov())) {
18966 const APInt &MaskVal =
LHS.getConstantOperandAPInt(1);
18977 if (!TrueVal.hasOneUse() || !FalseVal.hasOneUse())
18981 if (TrueVal.getOpcode() ==
ISD::SUB && FalseVal.getOpcode() ==
ISD::ADD) {
18989 SDValue A = FalseVal.getOperand(0);
18990 SDValue B = FalseVal.getOperand(1);
18992 return ((TrueVal.getOperand(0) ==
A && TrueVal.getOperand(1) ==
B) ||
18993 (TrueVal.getOperand(1) ==
A && TrueVal.getOperand(0) ==
B));
19001 EVT VT =
N->getValueType(0);
19003 SDValue TrueVal =
N->getOperand(1);
19004 SDValue FalseVal =
N->getOperand(2);
19034 SDValue TrueVal =
N->getOperand(1);
19035 SDValue FalseVal =
N->getOperand(2);
19050 EVT VT =
N->getValueType(0);
19057 const unsigned Opcode =
N->op_begin()->getNode()->getOpcode();
19072 if (
Op.isUndef()) {
19085 if (
Op.getOpcode() != Opcode || !
Op.hasOneUse())
19094 if (
Op.getOperand(0).getValueType() !=
Op.getOperand(1).getValueType())
19118 EVT AVT =
A.getValueType();
19119 EVT BVT =
B.getValueType();
19149 if (AOpt || BOpt) {
19167 EVT OpVT =
A.getValueType();
19175 IsSigned ? ISD::PARTIAL_REDUCE_SMLA : ISD::PARTIAL_REDUCE_UMLA;
19189 EVT OpVT =
A.getOperand(0).getValueType();
19191 OpVT !=
B.getOperand(0).getValueType() ||
19197 Opc = ISD::PARTIAL_REDUCE_SMLA;
19200 Opc = ISD::PARTIAL_REDUCE_UMLA;
19203 Opc = ISD::PARTIAL_REDUCE_SUMLA;
19206 Opc = ISD::PARTIAL_REDUCE_SUMLA;
19220 if (!Subtarget.hasStdExtZvqdotq())
19224 EVT VT =
N->getValueType(0);
19227 return DAG.
getNode(ISD::VECREDUCE_ADD,
DL, VT, V);
19249 const unsigned InVecOpcode = InVec->
getOpcode();
19266 InVecLHS, InValLHS, EltNo);
19268 InVecRHS, InValRHS, EltNo);
19280 unsigned Elt = IndexC->getZExtValue();
19286 unsigned NewIdx = Elt % ConcatNumElts;
19288 unsigned ConcatOpIdx = Elt / ConcatNumElts;
19293 ConcatOps[ConcatOpIdx] = ConcatOp;
19305 EVT VT =
N->getValueType(0);
19317 !
SDValue(BaseLd, 0).hasOneUse())
19320 EVT BaseLdVT = BaseLd->getValueType(0);
19328 if (!Ld || !Ld->isSimple() || !
Op.hasOneUse() ||
19330 Ld->getValueType(0) != BaseLdVT)
19339 using PtrDiff = std::pair<std::variant<int64_t, SDValue>,
bool>;
19341 LoadSDNode *Ld2) -> std::optional<PtrDiff> {
19346 if (BIO1.equalBaseIndex(BIO2, DAG))
19351 SDValue P2 = Ld2->getBasePtr();
19354 if (P1.getOpcode() ==
ISD::ADD && P1.getOperand(0) == P2)
19355 return {{P1.getOperand(1),
true}};
19357 return std::nullopt;
19361 auto BaseDiff = GetPtrDiff(Lds[0], Lds[1]);
19366 for (
auto *It = Lds.
begin() + 1; It != Lds.
end() - 1; It++)
19367 if (GetPtrDiff(*It, *std::next(It)) != BaseDiff)
19375 unsigned WideScalarBitWidth =
19388 auto [StrideVariant, MustNegateStride] = *BaseDiff;
19390 std::holds_alternative<SDValue>(StrideVariant)
19391 ? std::get<SDValue>(StrideVariant)
19394 if (MustNegateStride)
19403 ConstStride && ConstStride->getSExtValue() >= 0)
19407 ConstStride->getSExtValue() * (
N->getNumOperands() - 1);
19413 BaseLd->getPointerInfo(), BaseLd->getMemOperand()->getFlags(), MemSize,
19417 WideVecVT,
DL, BaseLd->getChain(), BaseLd->getBasePtr(), Stride,
19431 EVT VT =
N->getValueType(0);
19448 for (
int MaskIndex : Mask) {
19449 bool SelectMaskVal = (MaskIndex < (int)NumElts);
19452 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
19489 if (
N->getValueType(0).isFixedLengthVector())
19492 SDValue Addend =
N->getOperand(0);
19495 if (
N->getOpcode() == RISCVISD::ADD_VL) {
19496 SDValue AddPassthruOp =
N->getOperand(2);
19497 if (!AddPassthruOp.
isUndef())
19501 auto IsVWMulOpc = [](
unsigned Opc) {
19503 case RISCVISD::VWMUL_VL:
19504 case RISCVISD::VWMULU_VL:
19505 case RISCVISD::VWMULSU_VL:
19520 if (!MulPassthruOp.
isUndef())
19530 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
19531 }(
N, DAG, Subtarget);
19536 if (AddMask != MulMask || AddVL != MulVL)
19539 const auto &TSInfo =
19541 unsigned Opc = TSInfo.getMAccOpcode(MulOp.
getOpcode());
19544 EVT VT =
N->getValueType(0);
19555 if (!
N->getValueType(0).isVector())
19558 SDValue Addend =
N->getOperand(0);
19561 if (
N->getOpcode() == RISCVISD::ADD_VL) {
19562 SDValue AddPassthruOp =
N->getOperand(2);
19563 if (!AddPassthruOp.
isUndef())
19567 auto IsVqdotqOpc = [](
unsigned Opc) {
19569 case RISCVISD::VQDOT_VL:
19570 case RISCVISD::VQDOTU_VL:
19571 case RISCVISD::VQDOTSU_VL:
19591 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
19592 }(
N, DAG, Subtarget);
19595 if (AddVL != MulVL)
19598 if (AddMask.getOpcode() != RISCVISD::VMSET_VL ||
19599 AddMask.getOperand(0) != MulVL)
19604 EVT VT =
N->getValueType(0);
19605 Addend = DAG.
getNode(RISCVISD::ADD_VL,
DL, VT, Addend, AccumOp,
19606 DAG.
getUNDEF(VT), AddMask, AddVL);
19624 const EVT IndexVT = Index.getValueType();
19628 if (!isIndexTypeSigned(IndexType))
19658 assert(ShuffleMask.empty());
19660 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
19663 if (Index->getOperand(i)->isUndef())
19665 uint64_t C = Index->getConstantOperandVal(i);
19666 if (
C % ElementSize != 0)
19668 C =
C / ElementSize;
19671 ShuffleMask.push_back(
C);
19672 ActiveLanes.
set(
C);
19674 return ActiveLanes.
all();
19692 if (NumElems % 2 != 0)
19696 const unsigned WiderElementSize = ElementSize * 2;
19697 if (WiderElementSize > ST.getELen()/8)
19700 if (!ST.enableUnalignedVectorMem() && BaseAlign < WiderElementSize)
19703 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
19706 if (Index->getOperand(i)->isUndef())
19710 uint64_t C = Index->getConstantOperandVal(i);
19712 if (
C % WiderElementSize != 0)
19717 if (
C !=
Last + ElementSize)
19736 if (!IsVLMAX || Mask.getOpcode() != RISCVISD::VMSET_VL ||
19737 Mask.getOperand(0) != VL)
19740 auto IsTruncNode = [&](
SDValue V) {
19741 return V.getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL &&
19742 V.getOperand(1) == Mask && V.getOperand(2) == VL;
19749 while (IsTruncNode(
Op)) {
19750 if (!
Op.hasOneUse())
19752 Op =
Op.getOperand(0);
19785 assert(
N->getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL);
19787 MVT VT =
N->getSimpleValueType(0);
19792 auto MatchMinMax = [&VL, &Mask](
SDValue V,
unsigned Opc,
unsigned OpcVL,
19794 if (V.getOpcode() !=
Opc &&
19795 !(V.getOpcode() == OpcVL && V.getOperand(2).isUndef() &&
19796 V.getOperand(3) == Mask && V.getOperand(4) == VL))
19804 Op.getOperand(1).getValueType().isFixedLengthVector() &&
19806 Op.getOperand(1).getOperand(0).getValueType() ==
Op.getValueType() &&
19808 Op =
Op.getOperand(1).getOperand(0);
19811 return V.getOperand(0);
19813 if (
Op.getOpcode() == RISCVISD::VMV_V_X_VL &&
Op.getOperand(0).isUndef() &&
19814 Op.getOperand(2) == VL) {
19817 Op1->getAPIntValue().sextOrTrunc(
Op.getScalarValueSizeInBits());
19827 auto DetectUSatPattern = [&](
SDValue V) {
19839 MatchMinMax(SMinOp,
ISD::SMAX, RISCVISD::SMAX_VL, LoC))
19848 MatchMinMax(SMaxOp,
ISD::SMIN, RISCVISD::SMIN_VL, HiC))
19851 return DAG.
getNode(RISCVISD::SMAX_VL,
DL, V.getValueType(), SMinOp,
19852 V.getOperand(1), DAG.
getUNDEF(V.getValueType()),
19858 auto DetectSSatPattern = [&](
SDValue V) {
19860 unsigned NumSrcBits = V.getScalarValueSizeInBits();
19867 MatchMinMax(SMinOp,
ISD::SMAX, RISCVISD::SMAX_VL, LoC))
19868 if (HiC == SignedMax && LoC == SignedMin)
19873 MatchMinMax(SMaxOp,
ISD::SMIN, RISCVISD::SMIN_VL, HiC))
19874 if (HiC == SignedMax && LoC == SignedMin)
19883 while (Src.getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL &&
19884 Src.getOperand(1) == Mask && Src.getOperand(2) == VL &&
19886 Src = Src.getOperand(0);
19890 if ((Val = DetectUSatPattern(Src)))
19891 ClipOpc = RISCVISD::TRUNCATE_VECTOR_VL_USAT;
19892 else if ((Val = DetectSSatPattern(Src)))
19893 ClipOpc = RISCVISD::TRUNCATE_VECTOR_VL_SSAT;
19902 Val = DAG.
getNode(ClipOpc,
DL, ValVT, Val, Mask, VL);
19903 }
while (ValVT != VT);
19921 unsigned Opc =
N->getOpcode();
19923 "Unexpected opcode");
19924 EVT VT =
N->getValueType(0);
19933 Src = Src.getOperand(0);
19935 if (Src.getOpcode() != ISD::BITCAST)
19937 Src = Src.getOperand(0);
19938 }
else if (
Opc == ISD::VECREDUCE_ADD) {
19941 Src = Src.getOperand(0);
19944 EVT SrcEVT = Src.getValueType();
19959 if (
Opc == ISD::VECREDUCE_ADD) {
19966 VectorBitsMax, EltSize, MinSize);
19971 MVT ContainerVT = SrcMVT;
19999 if (!
LHS.hasOneUse())
20002 switch (
LHS.getOpcode()) {
20004 case RISCVISD::VSEXT_VL:
20005 Opcode = RISCVISD::VWMULSU_VL;
20008 case RISCVISD::VZEXT_VL:
20009 Opcode = RISCVISD::VWMULU_VL;
20020 else if (
RHS.getOpcode() == RISCVISD::VMV_V_X_VL &&
20022 ShAmtInt =
RHS.getConstantOperandVal(1);
20035 if (ShAmtInt >= NarrowBits)
20037 MVT VT =
N->getSimpleValueType(0);
20044 switch (
N->getOpcode()) {
20049 case RISCVISD::SHL_VL:
20050 Passthru =
N->getOperand(2);
20051 Mask =
N->getOperand(3);
20052 VL =
N->getOperand(4);
20057 return DAG.
getNode(Opcode,
DL, VT, NarrowOp,
20059 Passthru, Mask, VL);
20065 const MVT XLenVT = Subtarget.getXLenVT();
20071 auto SimplifyDemandedLowBitsHelper = [&](
unsigned OpNo,
unsigned LowBits) {
20082 switch (
N->getOpcode()) {
20085 case RISCVISD::SplitF64: {
20089 if (Op0->
getOpcode() == RISCVISD::BuildPairF64)
20102 APInt V =
C->getValueAPF().bitcastToAPInt();
20131 case RISCVISD::SLLW:
20132 case RISCVISD::SRAW:
20133 case RISCVISD::SRLW:
20134 case RISCVISD::RORW:
20135 case RISCVISD::ROLW: {
20137 if (SimplifyDemandedLowBitsHelper(0, 32) ||
20138 SimplifyDemandedLowBitsHelper(1, 5))
20143 case RISCVISD::CLZW:
20144 case RISCVISD::CTZW: {
20146 if (SimplifyDemandedLowBitsHelper(0, 32))
20150 case RISCVISD::FMV_W_X_RV64: {
20155 if (Op0.
getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64)
20159 case RISCVISD::FMV_X_ANYEXTH:
20160 case RISCVISD::FMV_X_ANYEXTW_RV64: {
20163 MVT VT =
N->getSimpleValueType(0);
20174 if ((
N->getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64 &&
20175 Op0->
getOpcode() == RISCVISD::FMV_W_X_RV64) ||
20176 (
N->getOpcode() == RISCVISD::FMV_X_ANYEXTH &&
20177 Op0->
getOpcode() == RISCVISD::FMV_H_X)) {
20179 "Unexpected value type!");
20189 LN0->getBasePtr(), IVT, LN0->getMemOperand());
20202 unsigned FPBits =
N->getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64 ? 32 : 16;
20213 EVT VT =
N->getValueType(0);
20262 EVT VT =
N->getValueType(0);
20279 if (!
C || !
C->getValueAPF().isExactlyValue(+1.0))
20294 case ISD::FMINNUM: {
20309 if (
N->getValueType(0) == MVT::i64 && Subtarget.is64Bit()) {
20314 Src.getOperand(0));
20319 Src.getOperand(0), Src.getOperand(1));
20327 case RISCVISD::TRUNCATE_VECTOR_VL:
20331 case ISD::VP_TRUNCATE:
20339 case RISCVISD::CZERO_EQZ:
20340 case RISCVISD::CZERO_NEZ: {
20344 unsigned Opc =
N->getOpcode();
20347 if (
Opc == RISCVISD::CZERO_EQZ && Val ==
Cond)
20351 Opc == RISCVISD::CZERO_EQZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ;
20359 return DAG.
getNode(InvOpc,
SDLoc(
N),
N->getValueType(0), Val, NewCond);
20369 N->getValueType(0), Val,
Cond.getOperand(0));
20373 case RISCVISD::SELECT_CC: {
20380 SDValue FalseV =
N->getOperand(4);
20382 EVT VT =
N->getValueType(0);
20385 if (TrueV == FalseV)
20416 return DAG.
getNode(RISCVISD::SELECT_CC,
DL,
N->getValueType(0),
20417 {LHS, RHS, CC, TrueV, FalseV});
20419 if (!Subtarget.hasConditionalMoveFusion()) {
20476 case RISCVISD::BR_CC: {
20483 return DAG.
getNode(RISCVISD::BR_CC,
DL,
N->getValueType(0),
20484 N->getOperand(0), LHS, RHS, CC,
N->getOperand(4));
20497 EVT VT =
N->getValueType(0);
20509 if (In2.
getOpcode() != ISD::FP_EXTEND &&
20518 DAG.
getNode(ISD::FNEG,
DL, VT, NewFPExtRound));
20520 case ISD::MGATHER: {
20522 const EVT VT =
N->getValueType(0);
20523 SDValue Index = MGN->getIndex();
20524 SDValue ScaleOp = MGN->getScale();
20526 assert(!MGN->isIndexScaled() &&
20527 "Scaled gather/scatter should not be formed");
20532 N->getVTList(), MGN->getMemoryVT(),
DL,
20533 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
20534 MGN->getBasePtr(), Index, ScaleOp},
20535 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
20539 N->getVTList(), MGN->getMemoryVT(),
DL,
20540 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
20541 MGN->getBasePtr(), Index, ScaleOp},
20542 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
20548 if (std::optional<VIDSequence> SimpleVID =
20550 SimpleVID && SimpleVID->StepDenominator == 1) {
20551 const int64_t StepNumerator = SimpleVID->StepNumerator;
20552 const int64_t Addend = SimpleVID->Addend;
20559 assert(MGN->getBasePtr()->getValueType(0) == PtrVT);
20567 VT,
DL, MGN->getChain(), BasePtr,
20569 EVL, MGN->getMemOperand());
20571 MGN->getPassThru());
20581 MGN->getBasePtr(), DAG.
getUNDEF(XLenVT),
20583 MGN->getMemoryVT(), MGN->getMemOperand(),
20592 MGN->getMemOperand()->getBaseAlign(), Subtarget)) {
20594 for (
unsigned i = 0; i < Index->getNumOperands(); i += 2)
20595 NewIndices.
push_back(Index.getOperand(i));
20596 EVT IndexVT = Index.getValueType()
20603 assert(EltCnt.isKnownEven() &&
"Splitting vector, but not in half!");
20605 EltCnt.divideCoefficientBy(2));
20608 EltCnt.divideCoefficientBy(2));
20613 {MGN->getChain(), Passthru, Mask, MGN->getBasePtr(),
20621 case ISD::MSCATTER:{
20623 SDValue Index = MSN->getIndex();
20624 SDValue ScaleOp = MSN->getScale();
20626 assert(!MSN->isIndexScaled() &&
20627 "Scaled gather/scatter should not be formed");
20632 N->getVTList(), MSN->getMemoryVT(),
DL,
20633 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
20635 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
20639 N->getVTList(), MSN->getMemoryVT(),
DL,
20640 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
20642 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
20644 EVT VT = MSN->getValue()->getValueType(0);
20646 if (!MSN->isTruncatingStore() &&
20650 return DAG.
getMaskedStore(MSN->getChain(),
DL, Shuffle, MSN->getBasePtr(),
20651 DAG.
getUNDEF(XLenVT), MSN->getMask(),
20652 MSN->getMemoryVT(), MSN->getMemOperand(),
20657 case ISD::VP_GATHER: {
20659 SDValue Index = VPGN->getIndex();
20660 SDValue ScaleOp = VPGN->getScale();
20662 assert(!VPGN->isIndexScaled() &&
20663 "Scaled gather/scatter should not be formed");
20668 {VPGN->getChain(), VPGN->getBasePtr(), Index,
20669 ScaleOp, VPGN->getMask(),
20670 VPGN->getVectorLength()},
20671 VPGN->getMemOperand(), IndexType);
20675 {VPGN->getChain(), VPGN->getBasePtr(), Index,
20676 ScaleOp, VPGN->getMask(),
20677 VPGN->getVectorLength()},
20678 VPGN->getMemOperand(), IndexType);
20682 case ISD::VP_SCATTER: {
20684 SDValue Index = VPSN->getIndex();
20685 SDValue ScaleOp = VPSN->getScale();
20687 assert(!VPSN->isIndexScaled() &&
20688 "Scaled gather/scatter should not be formed");
20693 {VPSN->getChain(), VPSN->getValue(),
20694 VPSN->getBasePtr(), Index, ScaleOp,
20695 VPSN->getMask(), VPSN->getVectorLength()},
20696 VPSN->getMemOperand(), IndexType);
20700 {VPSN->getChain(), VPSN->getValue(),
20701 VPSN->getBasePtr(), Index, ScaleOp,
20702 VPSN->getMask(), VPSN->getVectorLength()},
20703 VPSN->getMemOperand(), IndexType);
20706 case RISCVISD::SHL_VL:
20710 case RISCVISD::SRA_VL:
20711 case RISCVISD::SRL_VL: {
20713 if (ShAmt.
getOpcode() == RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL) {
20717 EVT VT =
N->getValueType(0);
20720 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt,
20721 N->getOperand(2),
N->getOperand(3),
N->getOperand(4));
20736 if (ShAmt.
getOpcode() == RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL) {
20739 EVT VT =
N->getValueType(0);
20742 DAG.
getRegister(RISCV::X0, Subtarget.getXLenVT()));
20743 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt);
20747 case RISCVISD::ADD_VL:
20755 case RISCVISD::VWADD_W_VL:
20756 case RISCVISD::VWADDU_W_VL:
20757 case RISCVISD::VWSUB_W_VL:
20758 case RISCVISD::VWSUBU_W_VL:
20760 case RISCVISD::OR_VL:
20761 case RISCVISD::SUB_VL:
20762 case RISCVISD::MUL_VL:
20764 case RISCVISD::VFMADD_VL:
20765 case RISCVISD::VFNMADD_VL:
20766 case RISCVISD::VFMSUB_VL:
20767 case RISCVISD::VFNMSUB_VL:
20768 case RISCVISD::STRICT_VFMADD_VL:
20769 case RISCVISD::STRICT_VFNMADD_VL:
20770 case RISCVISD::STRICT_VFMSUB_VL:
20771 case RISCVISD::STRICT_VFNMSUB_VL:
20773 case RISCVISD::FADD_VL:
20774 case RISCVISD::FSUB_VL:
20775 case RISCVISD::FMUL_VL:
20776 case RISCVISD::VFWADD_W_VL:
20777 case RISCVISD::VFWSUB_W_VL:
20785 if (
N->getOpcode() != ISD::STORE)
20789 SDValue Chain = Store->getChain();
20790 EVT MemVT = Store->getMemoryVT();
20791 SDValue Val = Store->getValue();
20794 bool IsScalarizable =
20796 Store->isSimple() &&
20826 NewVT, *Store->getMemOperand())) {
20828 return DAG.
getStore(Chain,
DL, NewV, Store->getBasePtr(),
20829 Store->getPointerInfo(), Store->getBaseAlign(),
20830 Store->getMemOperand()->getFlags());
20840 L->hasNUsesOfValue(1, 0) && L->hasNUsesOfValue(1, 1) &&
20842 L->getMemoryVT() == MemVT) {
20845 NewVT, *Store->getMemOperand()) &&
20847 NewVT, *L->getMemOperand())) {
20849 L->getPointerInfo(), L->getBaseAlign(),
20850 L->getMemOperand()->getFlags());
20851 return DAG.
getStore(Chain,
DL, NewL, Store->getBasePtr(),
20852 Store->getPointerInfo(), Store->getBaseAlign(),
20853 Store->getMemOperand()->getFlags());
20860 if ((Val.
getOpcode() == RISCVISD::VMV_X_S ||
20866 MVT VecVT = Src.getSimpleValueType();
20873 Store->getChain(),
DL, Src, Store->getBasePtr(), Store->getOffset(),
20876 Store->getMemOperand(), Store->getAddressingMode(),
20877 Store->isTruncatingStore(),
false);
20884 EVT VT =
N->getValueType(0);
20909 case RISCVISD::VFMV_V_F_VL: {
20910 const MVT VT =
N->getSimpleValueType(0);
20911 SDValue Passthru =
N->getOperand(0);
20912 SDValue Scalar =
N->getOperand(1);
20917 return DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL, VT, Passthru, Scalar, VL);
20920 case RISCVISD::VMV_V_X_VL: {
20921 const MVT VT =
N->getSimpleValueType(0);
20922 SDValue Passthru =
N->getOperand(0);
20923 SDValue Scalar =
N->getOperand(1);
20928 unsigned ScalarSize = Scalar.getValueSizeInBits();
20930 if (ScalarSize > EltWidth && Passthru.
isUndef())
20931 if (SimplifyDemandedLowBitsHelper(1, EltWidth))
20938 (!Const || Const->isZero() ||
20939 !Const->getAPIntValue().sextOrTrunc(EltWidth).isSignedIntN(5)))
20940 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, VT, Passthru, Scalar, VL);
20944 case RISCVISD::VFMV_S_F_VL: {
20949 if (
N->getOperand(0).isUndef() &&
20952 Src.getOperand(0).getValueType().isScalableVector()) {
20953 EVT VT =
N->getValueType(0);
20973 case RISCVISD::VMV_S_X_VL: {
20974 const MVT VT =
N->getSimpleValueType(0);
20975 SDValue Passthru =
N->getOperand(0);
20976 SDValue Scalar =
N->getOperand(1);
20982 unsigned ScalarSize = Scalar.getValueSizeInBits();
20984 if (ScalarSize > EltWidth && SimplifyDemandedLowBitsHelper(1, EltWidth))
20987 if (Scalar.getOpcode() == RISCVISD::VMV_X_S && Passthru.
isUndef() &&
20988 Scalar.getOperand(0).getValueType() ==
N->getValueType(0))
20989 return Scalar.getOperand(0);
20996 DAG.
getNode(
N->getOpcode(),
DL, M1VT, M1Passthru, Scalar, VL);
21005 Const && !Const->isZero() &&
isInt<5>(Const->getSExtValue()) &&
21007 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru, Scalar, VL);
21011 case RISCVISD::VMV_X_S: {
21013 MVT VecVT =
N->getOperand(0).getSimpleValueType();
21015 if (M1VT.
bitsLT(VecVT)) {
21017 return DAG.
getNode(RISCVISD::VMV_X_S,
DL,
N->getSimpleValueType(0), Vec);
21025 unsigned IntNo =
N->getConstantOperandVal(IntOpNo);
21030 case Intrinsic::riscv_vcpop:
21031 case Intrinsic::riscv_vcpop_mask:
21032 case Intrinsic::riscv_vfirst:
21033 case Intrinsic::riscv_vfirst_mask: {
21035 if (IntNo == Intrinsic::riscv_vcpop_mask ||
21036 IntNo == Intrinsic::riscv_vfirst_mask)
21037 VL =
N->getOperand(3);
21042 EVT VT =
N->getValueType(0);
21043 if (IntNo == Intrinsic::riscv_vfirst ||
21044 IntNo == Intrinsic::riscv_vfirst_mask)
21048 case Intrinsic::riscv_vsseg2_mask:
21049 case Intrinsic::riscv_vsseg3_mask:
21050 case Intrinsic::riscv_vsseg4_mask:
21051 case Intrinsic::riscv_vsseg5_mask:
21052 case Intrinsic::riscv_vsseg6_mask:
21053 case Intrinsic::riscv_vsseg7_mask:
21054 case Intrinsic::riscv_vsseg8_mask: {
21056 unsigned NF = Tuple.getValueType().getRISCVVectorTupleNumFields();
21058 if (Subtarget.hasOptimizedSegmentLoadStore(NF) || !Tuple.hasOneUse() ||
21059 Tuple.getOpcode() != RISCVISD::TUPLE_INSERT ||
21060 !Tuple.getOperand(0).isUndef())
21068 "Type mismatch without bitcast?");
21069 unsigned Stride = SEW / 8 * NF;
21070 unsigned Offset = SEW / 8 * Idx;
21097 case ISD::EXPERIMENTAL_VP_REVERSE:
21099 case ISD::VP_STORE:
21101 case ISD::BITCAST: {
21102 assert(Subtarget.useRVVForFixedLengthVectors());
21104 EVT VT =
N->getValueType(0);
21115 for (
unsigned i = 0; i < NF; ++i)
21116 Result = DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VT, Result,
Splat,
21122 if ((SrcVT == MVT::v1i1 || SrcVT == MVT::v2i1 || SrcVT == MVT::v4i1) &&
21135 case ISD::VECREDUCE_ADD:
21143 case RISCVISD::VRGATHER_VX_VL: {
21146 EVT VT =
N->getValueType(0);
21149 SDValue Passthru =
N->getOperand(2);
21156 Src = Src.getOperand(1);
21158 switch (Src.getOpcode()) {
21161 case RISCVISD::VMV_V_X_VL:
21162 case RISCVISD::VFMV_V_F_VL:
21170 case RISCVISD::VMV_S_X_VL:
21171 case RISCVISD::VFMV_S_F_VL:
21187 case RISCVISD::TUPLE_EXTRACT: {
21188 EVT VT =
N->getValueType(0);
21190 unsigned Idx =
N->getConstantOperandVal(1);
21195 switch (Tuple.getConstantOperandVal(1)) {
21198 case Intrinsic::riscv_vlseg2_mask:
21199 case Intrinsic::riscv_vlseg3_mask:
21200 case Intrinsic::riscv_vlseg4_mask:
21201 case Intrinsic::riscv_vlseg5_mask:
21202 case Intrinsic::riscv_vlseg6_mask:
21203 case Intrinsic::riscv_vlseg7_mask:
21204 case Intrinsic::riscv_vlseg8_mask:
21205 NF = Tuple.getValueType().getRISCVVectorTupleNumFields();
21209 if (!NF || Subtarget.hasOptimizedSegmentLoadStore(NF))
21214 "Type mismatch without bitcast?");
21215 unsigned Stride = SEW / 8 * NF;
21216 unsigned Offset = SEW / 8 * Idx;
21219 Tuple.getOperand(0),
21241 return Result.getValue(0);
21243 case RISCVISD::TUPLE_INSERT: {
21245 if (
N->getOperand(1).isUndef())
21246 return N->getOperand(0);
21249 case RISCVISD::VSLIDE1UP_VL:
21250 case RISCVISD::VFSLIDE1UP_VL: {
21254 MVT VT =
N->getSimpleValueType(0);
21258 if (!
N->getOperand(0).isUndef() ||
21277 return getVSlideup(DAG, Subtarget,
DL, VT, SrcVec,
N->getOperand(1),
21287 EVT XVT,
unsigned KeptBits)
const {
21292 if (XVT != MVT::i32 && XVT != MVT::i64)
21296 if (KeptBits == 32 || KeptBits == 64)
21300 return Subtarget.hasStdExtZbb() &&
21301 ((KeptBits == 8 && XVT == MVT::i64 && !Subtarget.is64Bit()) ||
21309 "Expected shift op");
21333 if (Ty.isScalarInteger() &&
21336 return isUsedByLdSt(N0.
getNode(),
N);
21342 if (C2 && Subtarget.hasShlAdd(C2->getZExtValue()) &&
N->hasOneUse() &&
21343 N->user_begin()->getOpcode() ==
ISD::ADD &&
21344 !isUsedByLdSt(*
N->user_begin(),
nullptr) &&
21349 const APInt &C1Int = C1->getAPIntValue();
21350 APInt ShiftedC1Int = C1Int << C2->getAPIntValue();
21371 ShiftedC1Int, Ty.getSizeInBits(), Subtarget,
21376 if (C1Cost < ShiftedC1Cost)
21399 EVT VT =
Op.getValueType();
21403 unsigned Opcode =
Op.getOpcode();
21411 const APInt &Mask =
C->getAPIntValue();
21420 auto IsLegalMask = [ShrunkMask, ExpandedMask](
const APInt &Mask) ->
bool {
21421 return ShrunkMask.
isSubsetOf(Mask) && Mask.isSubsetOf(ExpandedMask);
21423 auto UseMask = [Mask,
Op, &TLO](
const APInt &NewMask) ->
bool {
21424 if (NewMask == Mask)
21429 Op.getOperand(0), NewC);
21442 APInt NewMask =
APInt(Mask.getBitWidth(), 0xffff);
21443 if (IsLegalMask(NewMask))
21444 return UseMask(NewMask);
21447 if (VT == MVT::i64) {
21449 if (IsLegalMask(NewMask))
21450 return UseMask(NewMask);
21465 APInt NewMask = ShrunkMask;
21466 if (MinSignedBits <= 12)
21468 else if (!
C->isOpaque() && MinSignedBits <= 32 && !ShrunkMask.
isSignedIntN(32))
21474 assert(IsLegalMask(NewMask));
21475 return UseMask(NewMask);
21479 static const uint64_t GREVMasks[] = {
21480 0x5555555555555555ULL, 0x3333333333333333ULL, 0x0F0F0F0F0F0F0F0FULL,
21481 0x00FF00FF00FF00FFULL, 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL};
21483 for (
unsigned Stage = 0; Stage != 6; ++Stage) {
21484 unsigned Shift = 1 << Stage;
21485 if (ShAmt & Shift) {
21487 uint64_t Res = ((x & Mask) << Shift) | ((x >> Shift) & Mask);
21499 const APInt &DemandedElts,
21501 unsigned Depth)
const {
21503 unsigned Opc =
Op.getOpcode();
21508 "Should use MaskedValueIsZero if you don't know whether Op"
21509 " is a target node!");
21514 case RISCVISD::SELECT_CC: {
21525 case RISCVISD::VCPOP_VL: {
21530 case RISCVISD::CZERO_EQZ:
21531 case RISCVISD::CZERO_NEZ:
21537 case RISCVISD::REMUW: {
21547 case RISCVISD::DIVUW: {
21557 case RISCVISD::SLLW: {
21566 case RISCVISD::SRLW: {
21575 case RISCVISD::SRAW: {
21584 case RISCVISD::SHL_ADD: {
21587 unsigned ShAmt =
Op.getConstantOperandVal(1);
21594 case RISCVISD::CTZW: {
21601 case RISCVISD::CLZW: {
21608 case RISCVISD::BREV8:
21609 case RISCVISD::ORC_B: {
21613 bool IsGORC =
Op.getOpcode() == RISCVISD::ORC_B;
21621 case RISCVISD::READ_VLENB: {
21624 const unsigned MinVLenB = Subtarget.getRealMinVLen() / 8;
21625 const unsigned MaxVLenB = Subtarget.getRealMaxVLen() / 8;
21626 assert(MinVLenB > 0 &&
"READ_VLENB without vector extension enabled?");
21629 if (MaxVLenB == MinVLenB)
21633 case RISCVISD::FCLASS: {
21646 case Intrinsic::riscv_vsetvli:
21647 case Intrinsic::riscv_vsetvlimax: {
21648 bool HasAVL = IntNo == Intrinsic::riscv_vsetvli;
21649 unsigned VSEW =
Op.getConstantOperandVal(HasAVL + 1);
21654 uint64_t MaxVL = Subtarget.getRealMaxVLen() / SEW;
21655 MaxVL = (Fractional) ? MaxVL / LMul : MaxVL * LMul;
21659 MaxVL = std::min(MaxVL,
Op.getConstantOperandVal(1));
21661 unsigned KnownZeroFirstBit =
Log2_32(MaxVL) + 1;
21674 unsigned Depth)
const {
21675 switch (
Op.getOpcode()) {
21678 case RISCVISD::SELECT_CC: {
21681 if (Tmp == 1)
return 1;
21684 return std::min(Tmp, Tmp2);
21686 case RISCVISD::CZERO_EQZ:
21687 case RISCVISD::CZERO_NEZ:
21691 case RISCVISD::ABSW: {
21696 if (Tmp < 33)
return 1;
21699 case RISCVISD::SRAW: {
21706 return std::max(Tmp, 33U);
21708 case RISCVISD::SLLW:
21709 case RISCVISD::SRLW:
21710 case RISCVISD::DIVW:
21711 case RISCVISD::DIVUW:
21712 case RISCVISD::REMUW:
21713 case RISCVISD::ROLW:
21714 case RISCVISD::RORW:
21715 case RISCVISD::FCVT_W_RV64:
21716 case RISCVISD::FCVT_WU_RV64:
21717 case RISCVISD::STRICT_FCVT_W_RV64:
21718 case RISCVISD::STRICT_FCVT_WU_RV64:
21721 case RISCVISD::VMV_X_S: {
21727 unsigned XLen = Subtarget.getXLen();
21728 unsigned EltBits =
Op.getOperand(0).getScalarValueSizeInBits();
21729 if (EltBits <= XLen)
21730 return XLen - EltBits + 1;
21734 unsigned IntNo =
Op.getConstantOperandVal(1);
21738 case Intrinsic::riscv_masked_atomicrmw_xchg:
21739 case Intrinsic::riscv_masked_atomicrmw_add:
21740 case Intrinsic::riscv_masked_atomicrmw_sub:
21741 case Intrinsic::riscv_masked_atomicrmw_nand:
21742 case Intrinsic::riscv_masked_atomicrmw_max:
21743 case Intrinsic::riscv_masked_atomicrmw_min:
21744 case Intrinsic::riscv_masked_atomicrmw_umax:
21745 case Intrinsic::riscv_masked_atomicrmw_umin:
21746 case Intrinsic::riscv_masked_cmpxchg:
21753 assert(Subtarget.hasStdExtA());
21754 return Op.getValueSizeInBits() - 31;
21766 unsigned Depth)
const {
21769 switch (
Op.getOpcode()) {
21770 case RISCVISD::BREV8:
21771 case RISCVISD::ORC_B: {
21773 bool IsGORC =
Op.getOpcode() == RISCVISD::ORC_B;
21781 OriginalDemandedElts, Known2, TLO,
Depth + 1))
21793 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
21801 switch (
Op.getOpcode()) {
21802 case RISCVISD::SLLW:
21803 case RISCVISD::SRAW:
21804 case RISCVISD::SRLW:
21805 case RISCVISD::RORW:
21806 case RISCVISD::ROLW:
21810 case RISCVISD::SELECT_CC:
21812 assert(
Op.getOperand(0).getValueType().isInteger() &&
21813 "RISCVISD::SELECT_CC only compares integers");
21822 assert(Ld &&
"Unexpected null LoadSDNode");
21831 if (!CNode || CNode->isMachineConstantPoolEntry() ||
21832 CNode->getOffset() != 0)
21839 if (
Ptr.getOpcode() == RISCVISD::LLA) {
21840 auto *CNode = GetSupportedConstantPool(
Ptr.getOperand(0));
21841 if (!CNode || CNode->getTargetFlags() != 0)
21844 return CNode->getConstVal();
21848 if (
Ptr.getOpcode() != RISCVISD::ADD_LO ||
21849 Ptr.getOperand(0).getOpcode() != RISCVISD::HI)
21852 auto *CNodeLo = GetSupportedConstantPool(
Ptr.getOperand(1));
21853 auto *CNodeHi = GetSupportedConstantPool(
Ptr.getOperand(0).getOperand(0));
21859 if (CNodeLo->getConstVal() != CNodeHi->getConstVal())
21862 return CNodeLo->getConstVal();
21867 assert(
MI.getOpcode() == RISCV::ReadCounterWide &&
"Unexpected instruction");
21899 Register ReadAgainReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
21902 int64_t LoCounter =
MI.getOperand(2).getImm();
21903 int64_t HiCounter =
MI.getOperand(3).getImm();
21913 BuildMI(LoopMBB,
DL,
TII->get(RISCV::CSRRS), ReadAgainReg)
21925 MI.eraseFromParent();
21933 assert(
MI.getOpcode() == RISCV::SplitF64Pseudo &&
"Unexpected instruction");
21941 Register SrcReg =
MI.getOperand(2).getReg();
21946 TII.storeRegToStackSlot(*BB,
MI, SrcReg,
MI.getOperand(2).isKill(), FI, SrcRC,
21961 MI.eraseFromParent();
21968 assert(
MI.getOpcode() == RISCV::BuildPairF64Pseudo &&
21969 "Unexpected instruction");
21975 Register DstReg =
MI.getOperand(0).getReg();
21997 TII.loadRegFromStackSlot(*BB,
MI, DstReg, FI, DstRC, RI,
Register());
21998 MI.eraseFromParent();
22003 unsigned RelOpcode,
unsigned EqOpcode,
22006 Register DstReg =
MI.getOperand(0).getReg();
22007 Register Src1Reg =
MI.getOperand(1).getReg();
22008 Register Src2Reg =
MI.getOperand(2).getReg();
22010 Register SavedFFlags =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22034 MI.eraseFromParent();
22085 F->insert(It, FirstMBB);
22086 F->insert(It, SecondMBB);
22087 F->insert(It, SinkMBB);
22137 First.eraseFromParent();
22176 if (
MI.getOpcode() != RISCV::Select_GPR_Using_CC_GPR &&
22177 MI.getOperand(1).isReg() &&
MI.getOperand(2).isReg() &&
22178 Next != BB->
end() &&
Next->getOpcode() ==
MI.getOpcode() &&
22179 Next->getOperand(5).getReg() ==
MI.getOperand(0).getReg() &&
22180 Next->getOperand(5).isKill())
22185 if (
MI.getOperand(2).isReg())
22186 RHS =
MI.getOperand(2).getReg();
22191 SelectDests.
insert(
MI.getOperand(0).getReg());
22195 SequenceMBBI !=
E; ++SequenceMBBI) {
22196 if (SequenceMBBI->isDebugInstr())
22198 if (RISCVInstrInfo::isSelectPseudo(*SequenceMBBI)) {
22199 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
22200 !SequenceMBBI->getOperand(2).isReg() ||
22201 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
22202 SequenceMBBI->getOperand(3).getImm() != CC ||
22203 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
22204 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
22206 LastSelectPseudo = &*SequenceMBBI;
22208 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
22211 if (SequenceMBBI->hasUnmodeledSideEffects() ||
22212 SequenceMBBI->mayLoadOrStore() ||
22213 SequenceMBBI->usesCustomInsertionHook())
22216 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
22231 F->insert(
I, IfFalseMBB);
22232 F->insert(
I, TailMBB);
22235 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
22241 TailMBB->
push_back(DebugInstr->removeFromParent());
22245 TailMBB->
splice(TailMBB->
end(), HeadMBB,
22255 if (
MI.getOperand(2).isImm())
22258 .
addImm(
MI.getOperand(2).getImm())
22270 auto SelectMBBI =
MI.getIterator();
22271 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
22273 while (SelectMBBI != SelectEnd) {
22274 auto Next = std::next(SelectMBBI);
22275 if (RISCVInstrInfo::isSelectPseudo(*SelectMBBI)) {
22278 TII.get(RISCV::PHI), SelectMBBI->getOperand(0).getReg())
22279 .
addReg(SelectMBBI->getOperand(4).getReg())
22281 .
addReg(SelectMBBI->getOperand(5).getReg())
22288 F->getProperties().resetNoPHIs();
22296 RISCVVInversePseudosTable::getBaseInfo(MCOpcode, LMul, SEW);
22297 assert(
Inverse &&
"Unexpected LMUL and SEW pair for instruction");
22299 RISCV::lookupMaskedIntrinsicByUnmasked(
Inverse->Pseudo);
22300 assert(
Masked &&
"Could not find masked instruction for LMUL and SEW pair");
22306 unsigned CVTXOpc) {
22312 Register SavedFFLAGS =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22325 .
add(
MI.getOperand(1))
22326 .
add(
MI.getOperand(2))
22327 .
add(
MI.getOperand(3))
22329 .
add(
MI.getOperand(4))
22330 .
add(
MI.getOperand(5))
22331 .
add(
MI.getOperand(6))
22346 .
add(
MI.getOperand(0))
22347 .
add(
MI.getOperand(1))
22349 .
add(
MI.getOperand(3))
22351 .
add(
MI.getOperand(4))
22352 .
add(
MI.getOperand(5))
22353 .
add(
MI.getOperand(6))
22363 MI.eraseFromParent();
22369 unsigned CmpOpc, F2IOpc, I2FOpc, FSGNJOpc, FSGNJXOpc;
22371 switch (
MI.getOpcode()) {
22374 case RISCV::PseudoFROUND_H:
22375 CmpOpc = RISCV::FLT_H;
22376 F2IOpc = RISCV::FCVT_W_H;
22377 I2FOpc = RISCV::FCVT_H_W;
22378 FSGNJOpc = RISCV::FSGNJ_H;
22379 FSGNJXOpc = RISCV::FSGNJX_H;
22380 RC = &RISCV::FPR16RegClass;
22382 case RISCV::PseudoFROUND_H_INX:
22383 CmpOpc = RISCV::FLT_H_INX;
22384 F2IOpc = RISCV::FCVT_W_H_INX;
22385 I2FOpc = RISCV::FCVT_H_W_INX;
22386 FSGNJOpc = RISCV::FSGNJ_H_INX;
22387 FSGNJXOpc = RISCV::FSGNJX_H_INX;
22388 RC = &RISCV::GPRF16RegClass;
22390 case RISCV::PseudoFROUND_S:
22391 CmpOpc = RISCV::FLT_S;
22392 F2IOpc = RISCV::FCVT_W_S;
22393 I2FOpc = RISCV::FCVT_S_W;
22394 FSGNJOpc = RISCV::FSGNJ_S;
22395 FSGNJXOpc = RISCV::FSGNJX_S;
22396 RC = &RISCV::FPR32RegClass;
22398 case RISCV::PseudoFROUND_S_INX:
22399 CmpOpc = RISCV::FLT_S_INX;
22400 F2IOpc = RISCV::FCVT_W_S_INX;
22401 I2FOpc = RISCV::FCVT_S_W_INX;
22402 FSGNJOpc = RISCV::FSGNJ_S_INX;
22403 FSGNJXOpc = RISCV::FSGNJX_S_INX;
22404 RC = &RISCV::GPRF32RegClass;
22406 case RISCV::PseudoFROUND_D:
22408 CmpOpc = RISCV::FLT_D;
22409 F2IOpc = RISCV::FCVT_L_D;
22410 I2FOpc = RISCV::FCVT_D_L;
22411 FSGNJOpc = RISCV::FSGNJ_D;
22412 FSGNJXOpc = RISCV::FSGNJX_D;
22413 RC = &RISCV::FPR64RegClass;
22415 case RISCV::PseudoFROUND_D_INX:
22417 CmpOpc = RISCV::FLT_D_INX;
22418 F2IOpc = RISCV::FCVT_L_D_INX;
22419 I2FOpc = RISCV::FCVT_D_L_INX;
22420 FSGNJOpc = RISCV::FSGNJ_D_INX;
22421 FSGNJXOpc = RISCV::FSGNJX_D_INX;
22422 RC = &RISCV::GPRRegClass;
22434 F->insert(
I, CvtMBB);
22435 F->insert(
I, DoneMBB);
22443 MBB->addSuccessor(CvtMBB);
22444 MBB->addSuccessor(DoneMBB);
22446 Register DstReg =
MI.getOperand(0).getReg();
22447 Register SrcReg =
MI.getOperand(1).getReg();
22448 Register MaxReg =
MI.getOperand(2).getReg();
22449 int64_t FRM =
MI.getOperand(3).getImm();
22454 Register FabsReg =
MRI.createVirtualRegister(RC);
22458 Register CmpReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22473 Register F2IReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22495 MI.eraseFromParent();
22502 switch (
MI.getOpcode()) {
22505 case RISCV::ReadCounterWide:
22506 assert(!Subtarget.is64Bit() &&
22507 "ReadCounterWide is only to be used on riscv32");
22509 case RISCV::Select_GPR_Using_CC_GPR:
22510 case RISCV::Select_GPR_Using_CC_Imm5_Zibi:
22511 case RISCV::Select_GPR_Using_CC_SImm5_CV:
22512 case RISCV::Select_GPRNoX0_Using_CC_SImm5NonZero_QC:
22513 case RISCV::Select_GPRNoX0_Using_CC_UImm5NonZero_QC:
22514 case RISCV::Select_GPRNoX0_Using_CC_SImm16NonZero_QC:
22515 case RISCV::Select_GPRNoX0_Using_CC_UImm16NonZero_QC:
22516 case RISCV::Select_GPR_Using_CC_UImmLog2XLen_NDS:
22517 case RISCV::Select_GPR_Using_CC_UImm7_NDS:
22518 case RISCV::Select_FPR16_Using_CC_GPR:
22519 case RISCV::Select_FPR16INX_Using_CC_GPR:
22520 case RISCV::Select_FPR32_Using_CC_GPR:
22521 case RISCV::Select_FPR32INX_Using_CC_GPR:
22522 case RISCV::Select_FPR64_Using_CC_GPR:
22523 case RISCV::Select_FPR64INX_Using_CC_GPR:
22524 case RISCV::Select_FPR64IN32X_Using_CC_GPR:
22526 case RISCV::BuildPairF64Pseudo:
22528 case RISCV::SplitF64Pseudo:
22530 case RISCV::PseudoQuietFLE_H:
22532 case RISCV::PseudoQuietFLE_H_INX:
22533 return emitQuietFCMP(
MI, BB, RISCV::FLE_H_INX, RISCV::FEQ_H_INX, Subtarget);
22534 case RISCV::PseudoQuietFLT_H:
22536 case RISCV::PseudoQuietFLT_H_INX:
22537 return emitQuietFCMP(
MI, BB, RISCV::FLT_H_INX, RISCV::FEQ_H_INX, Subtarget);
22538 case RISCV::PseudoQuietFLE_S:
22540 case RISCV::PseudoQuietFLE_S_INX:
22541 return emitQuietFCMP(
MI, BB, RISCV::FLE_S_INX, RISCV::FEQ_S_INX, Subtarget);
22542 case RISCV::PseudoQuietFLT_S:
22544 case RISCV::PseudoQuietFLT_S_INX:
22545 return emitQuietFCMP(
MI, BB, RISCV::FLT_S_INX, RISCV::FEQ_S_INX, Subtarget);
22546 case RISCV::PseudoQuietFLE_D:
22548 case RISCV::PseudoQuietFLE_D_INX:
22549 return emitQuietFCMP(
MI, BB, RISCV::FLE_D_INX, RISCV::FEQ_D_INX, Subtarget);
22550 case RISCV::PseudoQuietFLE_D_IN32X:
22553 case RISCV::PseudoQuietFLT_D:
22555 case RISCV::PseudoQuietFLT_D_INX:
22556 return emitQuietFCMP(
MI, BB, RISCV::FLT_D_INX, RISCV::FEQ_D_INX, Subtarget);
22557 case RISCV::PseudoQuietFLT_D_IN32X:
22561 case RISCV::PseudoVFROUND_NOEXCEPT_V_M1_MASK:
22563 case RISCV::PseudoVFROUND_NOEXCEPT_V_M2_MASK:
22565 case RISCV::PseudoVFROUND_NOEXCEPT_V_M4_MASK:
22567 case RISCV::PseudoVFROUND_NOEXCEPT_V_M8_MASK:
22569 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF2_MASK:
22571 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF4_MASK:
22573 case RISCV::PseudoFROUND_H:
22574 case RISCV::PseudoFROUND_H_INX:
22575 case RISCV::PseudoFROUND_S:
22576 case RISCV::PseudoFROUND_S_INX:
22577 case RISCV::PseudoFROUND_D:
22578 case RISCV::PseudoFROUND_D_INX:
22579 case RISCV::PseudoFROUND_D_IN32X:
22581 case RISCV::PROBED_STACKALLOC_DYN:
22583 case TargetOpcode::STATEPOINT:
22589 MI.addOperand(*
MI.getMF(),
22595 case TargetOpcode::STACKMAP:
22596 case TargetOpcode::PATCHPOINT:
22597 if (!Subtarget.is64Bit())
22599 "supported on 64-bit targets");
22609 if (
auto *FRMDef =
MI.findRegisterDefOperand(RISCV::FRM,
nullptr)) {
22610 FRMDef->setIsDead(
false);
22614 int Idx = RISCV::getNamedOperandIdx(
MI.getOpcode(), RISCV::OpName::frm);
22624 if (
MI.readsRegister(RISCV::FRM,
nullptr))
22630void RISCVTargetLowering::analyzeInputArgs(
22634 for (
const auto &[Idx, In] :
enumerate(Ins)) {
22640 LLVM_DEBUG(
dbgs() <<
"InputArg #" << Idx <<
" has unhandled type "
22647void RISCVTargetLowering::analyzeOutputArgs(
22651 for (
const auto &[Idx, Out] :
enumerate(Outs)) {
22652 MVT ArgVT = Out.VT;
22653 ISD::ArgFlagsTy ArgFlags = Out.Flags;
22657 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << Idx <<
" has unhandled type "
22674 return DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, Val);
22708 if (In.isOrigArg()) {
22713 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
22714 (
BitWidth < 32 && In.Flags.isZExt())) {
22735 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, LocVT, Val);
22736 if (LocVT == MVT::i64 && VA.
getValVT() == MVT::f32)
22737 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Val);
22749 Val = DAG.
getNode(ISD::BITCAST,
DL, LocVT, Val);
22785 ExtType,
DL, LocVT, Chain, FIN,
22802 Register LoVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
22815 Register HiVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
22819 return DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64,
Lo,
Hi);
22830 switch (CallConv) {
22839#define CC_VLS_CASE(ABI_VLEN) case CallingConv::RISCV_VLSCall_##ABI_VLEN:
22855 if (Subtarget.hasStdExtE())
22857 if (!Subtarget.hasStdExtFOrZfinx() || !Subtarget.hasStdExtDOrZdinx())
22859 "(Zdinx/D) instruction set extensions");
22863 if (Func.hasFnAttribute(
"interrupt")) {
22864 if (!Func.arg_empty())
22866 "Functions with the interrupt attribute cannot have arguments!");
22877 "SiFive-CLIC-preemptible",
22878 "SiFive-CLIC-stack-swap",
22879 "SiFive-CLIC-preemptible-stack-swap",
22883 "Function interrupt attribute argument not supported!");
22885 if (Kind.starts_with(
"qci-") && !Subtarget.hasVendorXqciint())
22887 "'qci-*' interrupt kinds require Xqciint extension");
22889 if (Kind.starts_with(
"SiFive-CLIC-") && !Subtarget.hasVendorXSfmclic())
22891 "'SiFive-CLIC-*' interrupt kinds require XSfmclic extension");
22893 if (Kind ==
"rnmi" && !Subtarget.hasStdExtSmrnmi())
22896 if (Kind.starts_with(
"SiFive-CLIC-preemptible") && TFI->
hasFP(MF))
22898 "have a frame pointer");
22902 MVT XLenVT = Subtarget.getXLenVT();
22903 unsigned XLenInBytes = Subtarget.getXLen() / 8;
22905 std::vector<SDValue> OutChains;
22914 analyzeInputArgs(MF, CCInfo, Ins,
false,
22918 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
22939 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
22940 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
22942 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
22944 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
22973 int VarArgsSaveSize = XLenInBytes * (ArgRegs.
size() - Idx);
22978 if (VarArgsSaveSize == 0) {
22982 int VaArgOffset = -VarArgsSaveSize;
22990 XLenInBytes, VaArgOffset -
static_cast<int>(XLenInBytes),
true);
22991 VarArgsSaveSize += XLenInBytes;
22998 for (
unsigned I = Idx;
I < ArgRegs.
size(); ++
I) {
22999 const Register Reg = RegInfo.createVirtualRegister(RC);
23000 RegInfo.addLiveIn(ArgRegs[
I], Reg);
23003 Chain,
DL, ArgValue, FIN,
23005 OutChains.push_back(Store);
23019 if (!OutChains.empty()) {
23020 OutChains.push_back(Chain);
23030bool RISCVTargetLowering::isEligibleForTailCallOptimization(
23034 auto CalleeCC = CLI.CallConv;
23035 auto &Outs = CLI.Outs;
23037 auto CallerCC = Caller.getCallingConv();
23044 if (Caller.hasFnAttribute(
"interrupt"))
23059 for (
auto &VA : ArgLocs)
23065 auto IsCallerStructRet = Caller.hasStructRetAttr();
23066 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
23067 if (IsCallerStructRet || IsCalleeStructRet)
23072 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
23073 if (CalleeCC != CallerCC) {
23074 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
23075 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
23082 for (
auto &Arg : Outs)
23083 if (Arg.Flags.isByVal())
23109 MVT XLenVT = Subtarget.getXLenVT();
23124 if (Subtarget.hasStdExtE())
23128 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
23134 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
23140 "call site marked musttail");
23147 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
23149 if (!Flags.isByVal())
23153 unsigned Size = Flags.getByValSize();
23154 Align Alignment = Flags.getNonZeroByValAlign();
23161 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
23163 false,
nullptr, IsTailCall,
23175 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
23178 SDValue ArgValue = OutVals[OutIdx];
23186 RISCVISD::SplitF64,
DL, DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
23198 if (!StackPtr.getNode())
23210 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
23228 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
23229 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
23235 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
23236 SDValue PartValue = OutVals[OutIdx + 1];
23237 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
23251 DAG.
getStore(Chain,
DL, ArgValue, SpillSlot,
23253 for (
const auto &Part : Parts) {
23254 SDValue PartValue = Part.first;
23255 SDValue PartOffset = Part.second;
23262 ArgValue = SpillSlot;
23268 if (Flags.isByVal())
23269 ArgValue = ByValArgs[j++];
23276 if (
Options.EmitCallSiteInfo)
23280 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
23281 "for passing parameters");
23284 if (!StackPtr.getNode())
23298 if (!MemOpChains.
empty())
23304 for (
auto &Reg : RegsToPass) {
23305 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
23312 validateCCReservedRegs(RegsToPass, MF);
23316 "Return address register required, but has been reserved."});
23321 bool CalleeIsLargeExternalSymbol =
false;
23327 CalleeIsLargeExternalSymbol =
true;
23338 Ops.push_back(Chain);
23339 Ops.push_back(Callee);
23343 for (
auto &Reg : RegsToPass)
23344 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
23348 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
23349 assert(Mask &&
"Missing call preserved mask for calling convention");
23354 Ops.push_back(Glue);
23357 "Unexpected CFI type for a direct call");
23365 bool NeedSWGuarded =
false;
23367 Subtarget.hasStdExtZicfilp() &&
23369 NeedSWGuarded =
true;
23374 NeedSWGuarded ? RISCVISD::SW_GUARDED_TAIL : RISCVISD::TAIL;
23383 unsigned CallOpc = NeedSWGuarded ? RISCVISD::SW_GUARDED_CALL : RISCVISD::CALL;
23399 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_RISCV);
23402 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
23403 auto &VA = RVLocs[i];
23411 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
23412 assert(VA.needsCustom());
23417 RetValue = DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64, RetValue,
23431 const Type *RetTy)
const {
23433 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
23435 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
23436 MVT VT = Outs[i].VT;
23439 true, Outs[i].OrigTy))
23471 for (
unsigned i = 0, e = RVLocs.size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
23472 SDValue Val = OutVals[OutIdx];
23481 DAG.
getVTList(MVT::i32, MVT::i32), Val);
23485 Register RegHi = RVLocs[++i].getLocReg();
23491 "Return value register required, but has been reserved."});
23507 "Return value register required, but has been reserved."});
23526 unsigned RetOpc = RISCVISD::RET_GLUE;
23529 if (Func.hasFnAttribute(
"interrupt")) {
23530 if (!Func.getReturnType()->isVoidTy())
23532 "Functions with the interrupt attribute must have void return type!");
23538 if (Kind ==
"supervisor")
23539 RetOpc = RISCVISD::SRET_GLUE;
23540 else if (Kind ==
"rnmi") {
23541 assert(STI.hasFeature(RISCV::FeatureStdExtSmrnmi) &&
23542 "Need Smrnmi extension for rnmi");
23543 RetOpc = RISCVISD::MNRET_GLUE;
23544 }
else if (Kind ==
"qci-nest" || Kind ==
"qci-nonest") {
23545 assert(STI.hasFeature(RISCV::FeatureVendorXqciint) &&
23546 "Need Xqciint for qci-(no)nest");
23547 RetOpc = RISCVISD::QC_C_MILEAVERET_GLUE;
23549 RetOpc = RISCVISD::MRET_GLUE;
23552 return DAG.
getNode(RetOpc,
DL, MVT::Other, RetOps);
23555void RISCVTargetLowering::validateCCReservedRegs(
23556 const SmallVectorImpl<std::pair<llvm::Register, llvm::SDValue>> &Regs,
23565 F,
"Argument register required, but has been reserved."});
23571 if (
N->getNumValues() != 1)
23573 if (!
N->hasNUsesOfValue(1, 0))
23576 SDNode *Copy = *
N->user_begin();
23578 if (Copy->getOpcode() == ISD::BITCAST) {
23590 if (Copy->getOperand(Copy->getNumOperands() - 1).getValueType() == MVT::Glue)
23594 bool HasRet =
false;
23596 if (
Node->getOpcode() != RISCVISD::RET_GLUE)
23603 Chain = Copy->getOperand(0);
23615 if (Constraint.
size() == 1) {
23616 switch (Constraint[0]) {
23633 if (Constraint ==
"vr" || Constraint ==
"vd" || Constraint ==
"vm")
23635 if (Constraint ==
"cr" || Constraint ==
"cR" || Constraint ==
"cf")
23641std::pair<unsigned, const TargetRegisterClass *>
23647 if (Constraint.
size() == 1) {
23648 switch (Constraint[0]) {
23653 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
23654 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
23655 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
23656 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
23657 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23658 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23659 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
23661 if (VT == MVT::f16) {
23662 if (Subtarget.hasStdExtZfhmin())
23663 return std::make_pair(0U, &RISCV::FPR16RegClass);
23664 if (Subtarget.hasStdExtZhinxmin())
23665 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
23666 }
else if (VT == MVT::f32) {
23667 if (Subtarget.hasStdExtF())
23668 return std::make_pair(0U, &RISCV::FPR32RegClass);
23669 if (Subtarget.hasStdExtZfinx())
23670 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
23671 }
else if (VT == MVT::f64) {
23672 if (Subtarget.hasStdExtD())
23673 return std::make_pair(0U, &RISCV::FPR64RegClass);
23674 if (Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23675 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23676 if (Subtarget.hasStdExtZdinx() && Subtarget.is64Bit())
23677 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
23681 if (((VT == MVT::i64 || VT == MVT::f64) && !Subtarget.is64Bit()) ||
23682 (VT == MVT::i128 && Subtarget.is64Bit()))
23683 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23688 }
else if (Constraint ==
"vr") {
23689 for (
const auto *RC :
23690 {&RISCV::VRRegClass, &RISCV::VRM2RegClass, &RISCV::VRM4RegClass,
23691 &RISCV::VRM8RegClass, &RISCV::VRN2M1RegClass, &RISCV::VRN3M1RegClass,
23692 &RISCV::VRN4M1RegClass, &RISCV::VRN5M1RegClass,
23693 &RISCV::VRN6M1RegClass, &RISCV::VRN7M1RegClass,
23694 &RISCV::VRN8M1RegClass, &RISCV::VRN2M2RegClass,
23695 &RISCV::VRN3M2RegClass, &RISCV::VRN4M2RegClass,
23696 &RISCV::VRN2M4RegClass}) {
23698 return std::make_pair(0U, RC);
23702 if (
TRI->isTypeLegalForClass(*RC, ContainerVT))
23703 return std::make_pair(0U, RC);
23706 }
else if (Constraint ==
"vd") {
23707 for (
const auto *RC :
23708 {&RISCV::VRNoV0RegClass, &RISCV::VRM2NoV0RegClass,
23709 &RISCV::VRM4NoV0RegClass, &RISCV::VRM8NoV0RegClass,
23710 &RISCV::VRN2M1NoV0RegClass, &RISCV::VRN3M1NoV0RegClass,
23711 &RISCV::VRN4M1NoV0RegClass, &RISCV::VRN5M1NoV0RegClass,
23712 &RISCV::VRN6M1NoV0RegClass, &RISCV::VRN7M1NoV0RegClass,
23713 &RISCV::VRN8M1NoV0RegClass, &RISCV::VRN2M2NoV0RegClass,
23714 &RISCV::VRN3M2NoV0RegClass, &RISCV::VRN4M2NoV0RegClass,
23715 &RISCV::VRN2M4NoV0RegClass}) {
23717 return std::make_pair(0U, RC);
23721 if (
TRI->isTypeLegalForClass(*RC, ContainerVT))
23722 return std::make_pair(0U, RC);
23725 }
else if (Constraint ==
"vm") {
23726 if (
TRI->isTypeLegalForClass(RISCV::VMV0RegClass, VT.
SimpleTy))
23727 return std::make_pair(0U, &RISCV::VMV0RegClass);
23733 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, ContainerVT))
23734 return std::make_pair(0U, &RISCV::VMV0RegClass);
23736 }
else if (Constraint ==
"cr") {
23737 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
23738 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
23739 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
23740 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
23741 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23742 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23744 return std::make_pair(0U, &RISCV::GPRCRegClass);
23745 }
else if (Constraint ==
"cR") {
23746 if (((VT == MVT::i64 || VT == MVT::f64) && !Subtarget.is64Bit()) ||
23747 (VT == MVT::i128 && Subtarget.is64Bit()))
23748 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23749 }
else if (Constraint ==
"cf") {
23750 if (VT == MVT::f16) {
23751 if (Subtarget.hasStdExtZfhmin())
23752 return std::make_pair(0U, &RISCV::FPR16CRegClass);
23753 if (Subtarget.hasStdExtZhinxmin())
23754 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
23755 }
else if (VT == MVT::f32) {
23756 if (Subtarget.hasStdExtF())
23757 return std::make_pair(0U, &RISCV::FPR32CRegClass);
23758 if (Subtarget.hasStdExtZfinx())
23759 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
23760 }
else if (VT == MVT::f64) {
23761 if (Subtarget.hasStdExtD())
23762 return std::make_pair(0U, &RISCV::FPR64CRegClass);
23763 if (Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23764 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23765 if (Subtarget.hasStdExtZdinx() && Subtarget.is64Bit())
23766 return std::make_pair(0U, &RISCV::GPRCRegClass);
23775 .
Case(
"{zero}", RISCV::X0)
23776 .
Case(
"{ra}", RISCV::X1)
23777 .
Case(
"{sp}", RISCV::X2)
23778 .
Case(
"{gp}", RISCV::X3)
23779 .
Case(
"{tp}", RISCV::X4)
23780 .
Case(
"{t0}", RISCV::X5)
23781 .
Case(
"{t1}", RISCV::X6)
23782 .
Case(
"{t2}", RISCV::X7)
23783 .
Cases(
"{s0}",
"{fp}", RISCV::X8)
23784 .
Case(
"{s1}", RISCV::X9)
23785 .
Case(
"{a0}", RISCV::X10)
23786 .
Case(
"{a1}", RISCV::X11)
23787 .
Case(
"{a2}", RISCV::X12)
23788 .
Case(
"{a3}", RISCV::X13)
23789 .
Case(
"{a4}", RISCV::X14)
23790 .
Case(
"{a5}", RISCV::X15)
23791 .
Case(
"{a6}", RISCV::X16)
23792 .
Case(
"{a7}", RISCV::X17)
23793 .
Case(
"{s2}", RISCV::X18)
23794 .
Case(
"{s3}", RISCV::X19)
23795 .
Case(
"{s4}", RISCV::X20)
23796 .
Case(
"{s5}", RISCV::X21)
23797 .
Case(
"{s6}", RISCV::X22)
23798 .
Case(
"{s7}", RISCV::X23)
23799 .
Case(
"{s8}", RISCV::X24)
23800 .
Case(
"{s9}", RISCV::X25)
23801 .
Case(
"{s10}", RISCV::X26)
23802 .
Case(
"{s11}", RISCV::X27)
23803 .
Case(
"{t3}", RISCV::X28)
23804 .
Case(
"{t4}", RISCV::X29)
23805 .
Case(
"{t5}", RISCV::X30)
23806 .
Case(
"{t6}", RISCV::X31)
23808 if (XRegFromAlias != RISCV::NoRegister)
23809 return std::make_pair(XRegFromAlias, &RISCV::GPRRegClass);
23818 if (Subtarget.hasStdExtF()) {
23820 .
Cases(
"{f0}",
"{ft0}", RISCV::F0_F)
23821 .
Cases(
"{f1}",
"{ft1}", RISCV::F1_F)
23822 .
Cases(
"{f2}",
"{ft2}", RISCV::F2_F)
23823 .
Cases(
"{f3}",
"{ft3}", RISCV::F3_F)
23824 .
Cases(
"{f4}",
"{ft4}", RISCV::F4_F)
23825 .
Cases(
"{f5}",
"{ft5}", RISCV::F5_F)
23826 .
Cases(
"{f6}",
"{ft6}", RISCV::F6_F)
23827 .
Cases(
"{f7}",
"{ft7}", RISCV::F7_F)
23828 .
Cases(
"{f8}",
"{fs0}", RISCV::F8_F)
23829 .
Cases(
"{f9}",
"{fs1}", RISCV::F9_F)
23830 .
Cases(
"{f10}",
"{fa0}", RISCV::F10_F)
23831 .
Cases(
"{f11}",
"{fa1}", RISCV::F11_F)
23832 .
Cases(
"{f12}",
"{fa2}", RISCV::F12_F)
23833 .
Cases(
"{f13}",
"{fa3}", RISCV::F13_F)
23834 .
Cases(
"{f14}",
"{fa4}", RISCV::F14_F)
23835 .
Cases(
"{f15}",
"{fa5}", RISCV::F15_F)
23836 .
Cases(
"{f16}",
"{fa6}", RISCV::F16_F)
23837 .
Cases(
"{f17}",
"{fa7}", RISCV::F17_F)
23838 .
Cases(
"{f18}",
"{fs2}", RISCV::F18_F)
23839 .
Cases(
"{f19}",
"{fs3}", RISCV::F19_F)
23840 .
Cases(
"{f20}",
"{fs4}", RISCV::F20_F)
23841 .
Cases(
"{f21}",
"{fs5}", RISCV::F21_F)
23842 .
Cases(
"{f22}",
"{fs6}", RISCV::F22_F)
23843 .
Cases(
"{f23}",
"{fs7}", RISCV::F23_F)
23844 .
Cases(
"{f24}",
"{fs8}", RISCV::F24_F)
23845 .
Cases(
"{f25}",
"{fs9}", RISCV::F25_F)
23846 .
Cases(
"{f26}",
"{fs10}", RISCV::F26_F)
23847 .
Cases(
"{f27}",
"{fs11}", RISCV::F27_F)
23848 .
Cases(
"{f28}",
"{ft8}", RISCV::F28_F)
23849 .
Cases(
"{f29}",
"{ft9}", RISCV::F29_F)
23850 .
Cases(
"{f30}",
"{ft10}", RISCV::F30_F)
23851 .
Cases(
"{f31}",
"{ft11}", RISCV::F31_F)
23853 if (FReg != RISCV::NoRegister) {
23854 assert(RISCV::F0_F <= FReg && FReg <= RISCV::F31_F &&
"Unknown fp-reg");
23855 if (Subtarget.hasStdExtD() && (VT == MVT::f64 || VT == MVT::Other)) {
23856 unsigned RegNo = FReg - RISCV::F0_F;
23857 unsigned DReg = RISCV::F0_D + RegNo;
23858 return std::make_pair(DReg, &RISCV::FPR64RegClass);
23860 if (VT == MVT::f32 || VT == MVT::Other)
23861 return std::make_pair(FReg, &RISCV::FPR32RegClass);
23862 if (Subtarget.hasStdExtZfhmin() && VT == MVT::f16) {
23863 unsigned RegNo = FReg - RISCV::F0_F;
23864 unsigned HReg = RISCV::F0_H + RegNo;
23865 return std::make_pair(HReg, &RISCV::FPR16RegClass);
23870 if (Subtarget.hasVInstructions()) {
23872 .
Case(
"{v0}", RISCV::V0)
23873 .
Case(
"{v1}", RISCV::V1)
23874 .
Case(
"{v2}", RISCV::V2)
23875 .
Case(
"{v3}", RISCV::V3)
23876 .
Case(
"{v4}", RISCV::V4)
23877 .
Case(
"{v5}", RISCV::V5)
23878 .
Case(
"{v6}", RISCV::V6)
23879 .
Case(
"{v7}", RISCV::V7)
23880 .
Case(
"{v8}", RISCV::V8)
23881 .
Case(
"{v9}", RISCV::V9)
23882 .
Case(
"{v10}", RISCV::V10)
23883 .
Case(
"{v11}", RISCV::V11)
23884 .
Case(
"{v12}", RISCV::V12)
23885 .
Case(
"{v13}", RISCV::V13)
23886 .
Case(
"{v14}", RISCV::V14)
23887 .
Case(
"{v15}", RISCV::V15)
23888 .
Case(
"{v16}", RISCV::V16)
23889 .
Case(
"{v17}", RISCV::V17)
23890 .
Case(
"{v18}", RISCV::V18)
23891 .
Case(
"{v19}", RISCV::V19)
23892 .
Case(
"{v20}", RISCV::V20)
23893 .
Case(
"{v21}", RISCV::V21)
23894 .
Case(
"{v22}", RISCV::V22)
23895 .
Case(
"{v23}", RISCV::V23)
23896 .
Case(
"{v24}", RISCV::V24)
23897 .
Case(
"{v25}", RISCV::V25)
23898 .
Case(
"{v26}", RISCV::V26)
23899 .
Case(
"{v27}", RISCV::V27)
23900 .
Case(
"{v28}", RISCV::V28)
23901 .
Case(
"{v29}", RISCV::V29)
23902 .
Case(
"{v30}", RISCV::V30)
23903 .
Case(
"{v31}", RISCV::V31)
23905 if (VReg != RISCV::NoRegister) {
23906 if (
TRI->isTypeLegalForClass(RISCV::VMRegClass, VT.
SimpleTy))
23907 return std::make_pair(VReg, &RISCV::VMRegClass);
23908 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, VT.
SimpleTy))
23909 return std::make_pair(VReg, &RISCV::VRRegClass);
23910 for (
const auto *RC :
23911 {&RISCV::VRM2RegClass, &RISCV::VRM4RegClass, &RISCV::VRM8RegClass}) {
23912 if (
TRI->isTypeLegalForClass(*RC, VT.
SimpleTy)) {
23913 VReg =
TRI->getMatchingSuperReg(VReg, RISCV::sub_vrm1_0, RC);
23914 return std::make_pair(VReg, RC);
23920 std::pair<Register, const TargetRegisterClass *> Res =
23926 if (Res.second == &RISCV::GPRF16RegClass ||
23927 Res.second == &RISCV::GPRF32RegClass ||
23928 Res.second == &RISCV::GPRPairRegClass)
23929 return std::make_pair(Res.first, &RISCV::GPRRegClass);
23937 if (ConstraintCode.
size() == 1) {
23938 switch (ConstraintCode[0]) {
23953 if (Constraint.
size() == 1) {
23954 switch (Constraint[0]) {
23961 Subtarget.getXLenVT()));
23992 if (Subtarget.hasStdExtZtso()) {
23994 return Builder.CreateFence(Ord);
23999 return Builder.CreateFence(Ord);
24008 if (Subtarget.hasStdExtZtso()) {
24010 return Builder.CreateFence(Ord);
24016 if (Subtarget.enableTrailingSeqCstFence() &&
isa<StoreInst>(Inst) &&
24035 if (Subtarget.hasForcedAtomics())
24040 if (Subtarget.hasStdExtZacas() &&
24041 (
Size >= 32 || Subtarget.hasStdExtZabha()))
24047 if (
Size < 32 && !Subtarget.hasStdExtZabha())
24059 return Intrinsic::riscv_masked_atomicrmw_xchg;
24061 return Intrinsic::riscv_masked_atomicrmw_add;
24063 return Intrinsic::riscv_masked_atomicrmw_sub;
24065 return Intrinsic::riscv_masked_atomicrmw_nand;
24067 return Intrinsic::riscv_masked_atomicrmw_max;
24069 return Intrinsic::riscv_masked_atomicrmw_min;
24071 return Intrinsic::riscv_masked_atomicrmw_umax;
24073 return Intrinsic::riscv_masked_atomicrmw_umin;
24089 Builder.CreateNot(Mask,
"Inv_Mask"),
24096 unsigned XLen = Subtarget.getXLen();
24099 Type *Tys[] = {Builder.getIntNTy(XLen), AlignedAddr->
getType()};
24105 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
24106 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
24107 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
24120 unsigned ValWidth =
24123 Builder.CreateSub(Builder.getIntN(XLen, XLen - ValWidth), ShiftAmt);
24124 Result = Builder.CreateCall(LrwOpScwLoop,
24125 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
24128 Builder.CreateCall(LrwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
24132 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
24140 if (Subtarget.hasForcedAtomics())
24144 if (!(Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas()) &&
24153 unsigned XLen = Subtarget.getXLen();
24154 Value *Ordering = Builder.getIntN(XLen,
static_cast<uint64_t>(Ord));
24155 Intrinsic::ID CmpXchgIntrID = Intrinsic::riscv_masked_cmpxchg;
24157 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
24158 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
24159 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
24161 Type *Tys[] = {Builder.getIntNTy(XLen), AlignedAddr->
getType()};
24162 Value *Result = Builder.CreateIntrinsic(
24163 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, Ordering});
24165 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
24170 EVT DataVT)
const {
24186 return Subtarget.hasStdExtZfhmin();
24188 return Subtarget.hasStdExtF();
24190 return Subtarget.hasStdExtD();
24220 assert(Subtarget.getRealMinVLen() >= 64 &&
"zve32* unsupported");
24222 "RVVBitsPerBlock changed, audit needed");
24231 if (!Subtarget.hasVendorXTHeadMemIdx())
24237 Base =
Op->getOperand(0);
24239 int64_t RHSC = RHS->getSExtValue();
24245 bool isLegalIndexedOffset =
false;
24246 for (
unsigned i = 0; i < 4; i++)
24247 if (
isInt<5>(RHSC >> i) && ((RHSC % (1LL << i)) == 0)) {
24248 isLegalIndexedOffset =
true;
24252 if (!isLegalIndexedOffset)
24269 VT = LD->getMemoryVT();
24270 Ptr = LD->getBasePtr();
24272 VT = ST->getMemoryVT();
24273 Ptr = ST->getBasePtr();
24289 if (Subtarget.hasVendorXCVmem() && !Subtarget.is64Bit()) {
24294 Base = LS->getBasePtr();
24298 if (
Base ==
Op->getOperand(0))
24300 else if (
Base ==
Op->getOperand(1))
24312 VT = LD->getMemoryVT();
24313 Ptr = LD->getBasePtr();
24315 VT = ST->getMemoryVT();
24316 Ptr = ST->getBasePtr();
24340 return VT.
isVector() ? Subtarget.hasVInstructionsF16()
24341 : Subtarget.hasStdExtZfhOrZhinx();
24343 return Subtarget.hasStdExtFOrZfinx();
24345 return Subtarget.hasStdExtDOrZdinx();
24359 const Constant *PersonalityFn)
const {
24364 const Constant *PersonalityFn)
const {
24371 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
24372 Type.getSizeInBits() < Subtarget.getXLen()))
24379 bool IsSigned)
const {
24380 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
24394 const bool HasZmmul = Subtarget.hasStdExtZmmul();
24399 const APInt &Imm = ConstNode->getAPIntValue();
24402 if (Subtarget.hasVendorXqciac() && Imm.isSignedIntN(12))
24406 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
24407 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
24411 if (Subtarget.hasShlAdd(3) && !Imm.isSignedIntN(12) &&
24412 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
24413 (Imm - 8).isPowerOf2()))
24418 if (!Imm.isSignedIntN(12) && Imm.countr_zero() < 12 &&
24419 ConstNode->hasOneUse()) {
24420 APInt ImmS = Imm.ashr(Imm.countr_zero());
24421 if ((ImmS + 1).isPowerOf2() || (ImmS - 1).isPowerOf2() ||
24422 (1 - ImmS).isPowerOf2())
24445 if (C1.
isSignedIntN(12) && !(C1 * C2).isSignedIntN(12))
24454 unsigned *
Fast)
const {
24457 *
Fast = Subtarget.enableUnalignedScalarMem();
24458 return Subtarget.enableUnalignedScalarMem();
24474 *
Fast = Subtarget.enableUnalignedVectorMem();
24475 return Subtarget.enableUnalignedVectorMem();
24480 const AttributeList &FuncAttributes)
const {
24481 if (!Subtarget.hasVInstructions())
24484 if (FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat))
24496 const unsigned MinVLenInBytes =
24497 std::min(Subtarget.getRealMinVLen() / 8, 1024U);
24499 if (
Op.size() < MinVLenInBytes)
24514 MVT PreferredVT = (
Op.isMemset() && !
Op.isZeroMemset()) ? MVT::i8 : ELenVT;
24518 if (PreferredVT != MVT::i8 && !Subtarget.enableUnalignedVectorMem()) {
24520 if (
Op.isFixedDstAlign())
24521 RequiredAlign = std::min(RequiredAlign,
Op.getDstAlign());
24523 RequiredAlign = std::min(RequiredAlign,
Op.getSrcAlign());
24531 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
24532 bool IsABIRegCopy = CC.has_value();
24535 MVT PairVT = Subtarget.is64Bit() ? MVT::i128 : MVT::i64;
24536 if ((ValueVT == PairVT ||
24537 (!Subtarget.is64Bit() && Subtarget.hasStdExtZdinx() &&
24538 ValueVT == MVT::f64)) &&
24539 NumParts == 1 && PartVT == MVT::Untyped) {
24541 MVT XLenVT = Subtarget.getXLenVT();
24542 if (ValueVT == MVT::f64)
24547 Parts[0] = DAG.
getNode(RISCVISD::BuildGPRPair,
DL, PartVT,
Lo,
Hi);
24551 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
24552 PartVT == MVT::f32) {
24555 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::i16, Val);
24559 Val = DAG.
getNode(ISD::BITCAST,
DL, PartVT, Val);
24567 [[maybe_unused]]
unsigned ValLMUL =
24571 [[maybe_unused]]
unsigned PartLMUL =
24574 assert(ValNF == PartNF && ValLMUL == PartLMUL &&
24575 "RISC-V vector tuple type only accepts same register class type "
24596 if (PartVTBitSize % ValueVTBitSize == 0) {
24597 assert(PartVTBitSize >= ValueVTBitSize);
24604 if (ValueEltVT != PartEltVT) {
24605 if (PartVTBitSize > ValueVTBitSize) {
24607 assert(
Count != 0 &&
"The number of element should not be zero.");
24608 EVT SameEltTypeVT =
24612 Val = DAG.
getNode(ISD::BITCAST,
DL, PartVT, Val);
24626 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
24627 bool IsABIRegCopy = CC.has_value();
24629 MVT PairVT = Subtarget.is64Bit() ? MVT::i128 : MVT::i64;
24630 if ((ValueVT == PairVT ||
24631 (!Subtarget.is64Bit() && Subtarget.hasStdExtZdinx() &&
24632 ValueVT == MVT::f64)) &&
24633 NumParts == 1 && PartVT == MVT::Untyped) {
24635 MVT XLenVT = Subtarget.getXLenVT();
24644 if (ValueVT == MVT::f64)
24649 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
24650 PartVT == MVT::f32) {
24654 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::i32, Val);
24656 Val = DAG.
getNode(ISD::BITCAST,
DL, ValueVT, Val);
24672 if (PartVTBitSize % ValueVTBitSize == 0) {
24673 assert(PartVTBitSize >= ValueVTBitSize);
24674 EVT SameEltTypeVT = ValueVT;
24681 if (ValueEltVT != PartEltVT) {
24683 assert(
Count != 0 &&
"The number of element should not be zero.");
24686 Val = DAG.
getNode(ISD::BITCAST,
DL, SameEltTypeVT, Val);
24702 bool OptSize = Attr.hasFnAttr(Attribute::MinSize);
24709 unsigned Opc =
N->getOpcode();
24718 M, Intrinsic::thread_pointer, IRB.
getPtrTy());
24726 if (Subtarget.isTargetFuchsia())
24732 if (Subtarget.isTargetAndroid())
24737 if (M->getStackProtectorGuard() ==
"tls") {
24739 int Offset = M->getStackProtectorGuardOffset();
24747 Align Alignment)
const {
24748 if (!Subtarget.hasVInstructions())
24752 if (DataType.isFixedLengthVector() && !Subtarget.useRVVForFixedLengthVectors())
24759 if (!Subtarget.enableUnalignedVectorMem() &&
24771 "Invalid call instruction for a KCFI check");
24773 MBBI->getOpcode()));
24776 Target.setIsRenamable(
false);
24784#define GET_REGISTER_MATCHER
24785#include "RISCVGenAsmMatcher.inc"
24796 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
24797 if (!ReservedRegs.
test(Reg) && !Subtarget.isRegisterReservedByUser(Reg))
24805 const MDNode *NontemporalInfo =
I.getMetadata(LLVMContext::MD_nontemporal);
24807 if (NontemporalInfo ==
nullptr)
24815 int NontemporalLevel = 5;
24816 const MDNode *RISCVNontemporalInfo =
24817 I.getMetadata(
"riscv-nontemporal-domain");
24818 if (RISCVNontemporalInfo !=
nullptr)
24825 assert((1 <= NontemporalLevel && NontemporalLevel <= 5) &&
24826 "RISC-V target doesn't support this non-temporal domain.");
24828 NontemporalLevel -= 2;
24830 if (NontemporalLevel & 0b1)
24832 if (NontemporalLevel & 0b10)
24845 return TargetFlags;
24858 return Subtarget.hasStdExtZvbb();
24863 return Subtarget.hasCPOPLike() && (VT == MVT::i32 || VT == MVT::i64);
24873 if (Subtarget.hasStdExtZalasr()) {
24874 if (Subtarget.hasStdExtZtso()) {
24904 if (
Op == Instruction::Add ||
Op == Instruction::Sub ||
24905 Op == Instruction::And ||
Op == Instruction::Or ||
24906 Op == Instruction::Xor ||
Op == Instruction::InsertElement ||
24907 Op == Instruction::ShuffleVector ||
Op == Instruction::Load ||
24908 Op == Instruction::Freeze ||
Op == Instruction::Store)
24913 if (RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(
II->getIntrinsicID()))
24926 if (AI->getAllocatedType()->isScalableTy())
24934RISCVTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
24942 if (!Subtarget.hasShortForwardBranchOpt())
24944 EVT VT =
N->getValueType(0);
24945 if (!(VT == MVT::i32 || (VT == MVT::i64 && Subtarget.
is64Bit())))
24949 if (Divisor.
sgt(2048) || Divisor.
slt(-2048))
24954bool RISCVTargetLowering::shouldFoldSelectWithSingleBitTest(
24955 EVT VT,
const APInt &AndMask)
const {
24956 if (Subtarget.
hasCZEROLike() || Subtarget.hasVendorXTHeadCondMov())
24962 return Subtarget.getMinimumJumpTableEntries();
24969 if (Subtarget.hasStdExtZicfilp()) {
24976 return DAG.
getNode(RISCVISD::SW_GUARDED_BRIND, dl, MVT::Other, Chain, Addr);
24993std::pair<const TargetRegisterClass *, uint8_t>
25013#define GET_RISCVVIntrinsicsTable_IMPL
25014#include "RISCVGenSearchableTables.inc"
25029 Align StackAlign)
const {
25033 unsigned StackProbeSize =
25037 return StackProbeSize ? StackProbeSize : StackAlign.
value();
25054 EVT VT =
Op.getValueType();
25065 Chain = DAG.
getNode(RISCVISD::PROBED_ALLOCA, dl, MVT::Other, Chain, SP);
25075 Register TargetReg =
MI.getOperand(0).getReg();
25078 bool IsRV64 = Subtarget.is64Bit();
25079 Align StackAlign = Subtarget.getFrameLowering()->getStackAlign();
25086 MF.
insert(MBBInsertPoint, LoopTestMBB);
25088 MF.
insert(MBBInsertPoint, ExitMBB);
25104 TII->get(IsRV64 ? RISCV::SD : RISCV::SW))
25125 MBB->addSuccessor(LoopTestMBB);
25127 MI.eraseFromParent();
25129 return ExitMBB->
begin()->getParent();
25133 if (Subtarget.hasStdExtFOrZfinx()) {
25134 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 bool isLowSourceShuffle(ArrayRef< int > Mask, int Span)
Is this mask only using elements from the first span of the input?
static bool isZipOdd(const std::array< std::pair< int, int >, 2 > &SrcInfo, ArrayRef< int > Mask, unsigned &Factor)
Given a shuffle which can be represented as a pair of two slides, see if it is a zipodd idiom.
static SDValue lowerVZIP(unsigned Opc, SDValue Op0, SDValue Op1, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerBuildVectorOfConstants(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue performVECREDUCECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue lowerVECTOR_SHUFFLEAsVSlide1(const SDLoc &DL, MVT VT, SDValue V1, SDValue V2, ArrayRef< int > Mask, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
Match v(f)slide1up/down idioms.
static SDValue combineTruncToVnclip(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::optional< APInt > getExactInteger(const APFloat &APF, uint32_t BitWidth)
static SDValue performVP_TRUNCATECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isInterleaveShuffle(ArrayRef< int > Mask, MVT VT, int &EvenSrc, int &OddSrc, const RISCVSubtarget &Subtarget)
Is this shuffle interleaving contiguous elements from one vector into the even elements and contiguou...
static bool narrowIndex(SDValue &N, ISD::MemIndexType IndexType, SelectionDAG &DAG)
According to the property that indexed load/store instructions zero-extend their indices,...
static SDValue getSingleShuffleSrc(MVT VT, SDValue V1, SDValue V2)
static unsigned getPACKOpcode(unsigned DestBW, const RISCVSubtarget &Subtarget)
static void promoteVCIXScalar(const SDValue &Op, SmallVectorImpl< SDValue > &Operands, SelectionDAG &DAG)
static SDValue splatSplitI64WithVL(const SDLoc &DL, MVT VT, SDValue Passthru, SDValue Scalar, SDValue VL, SelectionDAG &DAG)
static bool isLegalBitRotate(ArrayRef< int > Mask, EVT VT, const RISCVSubtarget &Subtarget, MVT &RotateVT, unsigned &RotateAmt)
static SDValue splatPartsI64WithVL(const SDLoc &DL, MVT VT, SDValue Passthru, SDValue Lo, SDValue Hi, SDValue VL, SelectionDAG &DAG)
static SDValue getWideningInterleave(SDValue EvenV, SDValue OddV, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue getAllOnesMask(MVT VecVT, SDValue VL, const SDLoc &DL, SelectionDAG &DAG)
Creates an all ones mask suitable for masking a vector of type VecTy with vector length VL.
static SDValue simplifyOp_VL(SDNode *N)
static cl::opt< int > FPImmCost(DEBUG_TYPE "-fpimm-cost", cl::Hidden, cl::desc("Give the maximum number of instructions that we will " "use for creating a floating-point immediate value"), cl::init(2))
static SDValue lowerScalarSplat(SDValue Passthru, SDValue Scalar, SDValue VL, MVT VT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isAlternating(const std::array< std::pair< int, int >, 2 > &SrcInfo, ArrayRef< int > Mask, unsigned Factor, bool RequiredPolarity)
static const RISCV::RISCVMaskedPseudoInfo * lookupMaskedIntrinsic(uint16_t MCOpcode, RISCVVType::VLMUL LMul, unsigned SEW)
static SDValue expandMul(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue performVWADDSUBW_VLCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static bool matchIndexAsWiderOp(EVT VT, SDValue Index, SDValue Mask, Align BaseAlign, const RISCVSubtarget &ST)
Match the index of a gather or scatter operation as an operation with twice the element width and hal...
static SDValue combineOp_VLToVWOp_VL(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
Combine a binary or FMA operation to its equivalent VW or VW_W form.
static SDValue combineVFMADD_VLWithVFNEG_VL(SDNode *N, SelectionDAG &DAG)
static SDValue combineOrOfCZERO(SDNode *N, SDValue N0, SDValue N1, SelectionDAG &DAG)
static SDValue useInversedSetcc(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static cl::opt< bool > ReassocShlAddiAdd("reassoc-shl-addi-add", cl::Hidden, cl::desc("Swap add and addi in cases where the add may " "be combined with a shift"), cl::init(true))
static SDValue lowerDisjointIndicesShuffle(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Given a shuffle where the indices are disjoint between the two sources, e.g.:
static SDValue combineVWADDSUBWSelect(SDNode *N, SelectionDAG &DAG)
static MachineBasicBlock * EmitLoweredCascadedSelect(MachineInstr &First, MachineInstr &Second, MachineBasicBlock *ThisMBB, const RISCVSubtarget &Subtarget)
static SDValue performINSERT_VECTOR_ELTCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue lowerFABSorFNEG(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerFMAXIMUM_FMINIMUM(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue foldReduceOperandViaVQDOT(SDValue InVec, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue reverseZExtICmpCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue SplitStrictFPVectorOp(SDValue Op, SelectionDAG &DAG)
static SDValue tryDemorganOfBooleanCondition(SDValue Cond, SelectionDAG &DAG)
static SDValue performMemPairCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue combineDeMorganOfBoolean(SDNode *N, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLEAsVSlidedown(const SDLoc &DL, MVT VT, SDValue V1, SDValue V2, ArrayRef< int > Mask, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
static SDValue reduceANDOfAtomicLoad(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static unsigned getRVVReductionOp(unsigned ISDOpcode)
static SDValue combineSubShiftToOrcB(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerShuffleViaVRegSplitting(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue getVCIXISDNodeVOID(SDValue &Op, SelectionDAG &DAG, unsigned Type)
static SDValue lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static cl::opt< unsigned > NumRepeatedDivisors(DEBUG_TYPE "-fp-repeated-divisors", cl::Hidden, cl::desc("Set the minimum number of repetitions of a divisor to allow " "transformation to multiplications by the reciprocal"), cl::init(2))
static SDValue foldSelectOfCTTZOrCTLZ(SDNode *N, SelectionDAG &DAG)
static SDValue lowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerFixedVectorSegLoadIntrinsics(unsigned IntNo, SDValue Op, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
static SDValue combineVectorMulToSraBitcast(SDNode *N, SelectionDAG &DAG)
static bool isLocalRepeatingShuffle(ArrayRef< int > Mask, int Span)
Is this mask local (i.e.
static bool legalizeScatterGatherIndexType(SDLoc DL, SDValue &Index, ISD::MemIndexType &IndexType, RISCVTargetLowering::DAGCombinerInfo &DCI)
static bool isSpanSplatShuffle(ArrayRef< int > Mask, int Span)
Return true for a mask which performs an arbitrary shuffle within the first span, and then repeats th...
static SDValue getVSlidedown(SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const SDLoc &DL, EVT VT, SDValue Passthru, SDValue Op, SDValue Offset, SDValue Mask, SDValue VL, unsigned Policy=RISCVVType::TAIL_UNDISTURBED_MASK_UNDISTURBED)
static unsigned getRISCVVLOp(SDValue Op)
Get a RISC-V target specified VL op for a given SDNode.
static unsigned getVecReduceOpcode(unsigned Opc)
Given a binary operator, return the associative generic ISD::VECREDUCE_OP which corresponds to it.
static std::pair< SDValue, SDValue > getDefaultVLOps(uint64_t NumElts, MVT ContainerVT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isPromotedOpNeedingSplit(SDValue Op, const RISCVSubtarget &Subtarget)
static SDValue performFP_TO_INT_SATCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue lowerReductionSeq(unsigned RVVOpcode, MVT ResVT, SDValue StartValue, SDValue Vec, SDValue Mask, SDValue VL, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Helper to lower a reduction sequence of the form: scalar = reduce_op vec, scalar_start.
static SDValue expandMulToAddOrSubOfShl(SDNode *N, SelectionDAG &DAG, uint64_t MulAmt)
static SDValue performVP_REVERSECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerGetVectorLength(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::pair< SDValue, SDValue > getDefaultScalableVLOps(MVT VecVT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue getVLOperand(SDValue Op)
static SDValue performVECTOR_SHUFFLECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue performVP_STORECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static MachineBasicBlock * emitFROUND(MachineInstr &MI, MachineBasicBlock *MBB, const RISCVSubtarget &Subtarget)
static SDValue getLargeExternalSymbol(ExternalSymbolSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG)
static SDValue lowerCttzElts(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
const uint64_t ModeMask64
static SDValue lowerVectorIntrinsicScalars(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static cl::opt< unsigned > ExtensionMaxWebSize(DEBUG_TYPE "-ext-max-web-size", cl::Hidden, cl::desc("Give the maximum size (in number of nodes) of the web of " "instructions that we will consider for VW expansion"), cl::init(18))
static SDValue combineShlAddIAddImpl(SDNode *N, SDValue AddI, SDValue Other, SelectionDAG &DAG)
static SDValue getDeinterleaveShiftAndTrunc(const SDLoc &DL, MVT VT, SDValue Src, unsigned Factor, unsigned Index, SelectionDAG &DAG)
static SDValue combineBinOpOfZExt(SDNode *N, SelectionDAG &DAG)
static bool matchSelectAddSub(SDValue TrueVal, SDValue FalseVal, bool &SwapCC)
static SDValue performSIGN_EXTEND_INREGCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue combineXorToBitfieldInsert(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::optional< MVT > getSmallestVTForIndex(MVT VecVT, unsigned MaxIdx, SDLoc DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool useRVVForFixedLengthVectorVT(MVT VT, const RISCVSubtarget &Subtarget)
static bool isValidVisniInsertExtractIndex(SDValue Idx)
static Value * useTpOffset(IRBuilderBase &IRB, unsigned Offset)
static SDValue combineAddOfBooleanXor(SDNode *N, SelectionDAG &DAG)
static SDValue getZeroPaddedAdd(const SDLoc &DL, SDValue A, SDValue B, SelectionDAG &DAG)
Given fixed length vectors A and B with equal element types, but possibly different number of element...
const uint32_t ModeMask32
static SDValue combineTruncOfSraSext(SDNode *N, SelectionDAG &DAG)
static SDValue getVSlideup(SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const SDLoc &DL, EVT VT, SDValue Passthru, SDValue Op, SDValue Offset, SDValue Mask, SDValue VL, unsigned Policy=RISCVVType::TAIL_UNDISTURBED_MASK_UNDISTURBED)
static MachineBasicBlock * emitSplitF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const RISCVSubtarget &Subtarget)
static SDValue combineVqdotAccum(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static MachineBasicBlock * emitVFROUND_NOEXCEPT_MASK(MachineInstr &MI, MachineBasicBlock *BB, unsigned CVTXOpc)
static SDValue SplitVectorOp(SDValue Op, SelectionDAG &DAG)
static SDValue combineToVCPOP(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static unsigned negateFMAOpcode(unsigned Opcode, bool NegMul, bool NegAcc)
static SDValue lowerScalarInsert(SDValue Scalar, SDValue VL, MVT VT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerBuildVectorViaVID(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue transformAddShlImm(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue tryFoldSelectIntoOp(SDNode *N, SelectionDAG &DAG, SDValue TrueVal, SDValue FalseVal, bool Swapped)
static SDValue lowerBitreverseShuffle(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerConstant(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool matchIndexAsShuffle(EVT VT, SDValue Index, SDValue Mask, SmallVector< int > &ShuffleMask)
Match the index vector of a scatter or gather node as the shuffle mask which performs the rearrangeme...
static SDValue performVFMADD_VLCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue lowerFixedVectorSegStoreIntrinsics(unsigned IntNo, SDValue Op, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
static SDValue combineBinOpToReduce(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue SplitVPOp(SDValue Op, SelectionDAG &DAG)
static SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static void processVCIXOperands(SDValue &OrigOp, SmallVectorImpl< SDValue > &Operands, SelectionDAG &DAG)
static SDValue widenVectorOpsToi8(SDValue N, const SDLoc &DL, SelectionDAG &DAG)
static SDValue lowerINT_TO_FP(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerVectorFTRUNC_FCEIL_FFLOOR_FROUND(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerFTRUNC_FCEIL_FFLOOR_FROUND(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::optional< VIDSequence > isSimpleVIDSequence(SDValue Op, unsigned EltSizeInBits)
static SDValue lowerVectorXRINT_XROUND(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static uint64_t computeGREVOrGORC(uint64_t x, unsigned ShAmt, bool IsGORC)
static SDValue lowerVECTOR_SHUFFLEAsRotate(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isSimm12Constant(SDValue V)
static RISCVFPRndMode::RoundingMode matchRoundingOp(unsigned Opc)
static SDValue lowerVectorStrictFTRUNC_FCEIL_FFLOOR_FROUND(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue combineTruncSelectToSMaxUSat(SDNode *N, SelectionDAG &DAG)
static bool isElementRotate(const std::array< std::pair< int, int >, 2 > &SrcInfo, unsigned NumElts)
static SDValue performBITREVERSECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue transformAddImmMulImm(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue combineSubOfBoolean(SDNode *N, SelectionDAG &DAG)
static SDValue matchSplatAsGather(SDValue SplatVal, MVT VT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isValidEGW(int EGS, EVT VT, const RISCVSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLEAsVRGatherVX(ShuffleVectorSDNode *SVN, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
Match a single source shuffle which is an identity except that some particular element is repeated.
static bool isNonZeroAVL(SDValue AVL)
static SDValue lowerFP_TO_INT(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static MVT getQDOTXResultType(MVT OpVT)
static SDValue lowerVECTOR_SHUFFLEAsVSlideup(const SDLoc &DL, MVT VT, SDValue V1, SDValue V2, ArrayRef< int > Mask, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
static SDValue getVCIXISDNodeWCHAIN(SDValue &Op, SelectionDAG &DAG, unsigned Type)
static SDValue getLargeGlobalAddress(GlobalAddressSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG)
static MachineBasicBlock * emitReadCounterWidePseudo(MachineInstr &MI, MachineBasicBlock *BB)
static SDValue getWideningSpread(SDValue V, unsigned Factor, unsigned Index, const SDLoc &DL, SelectionDAG &DAG)
static cl::opt< bool > AllowSplatInVW_W(DEBUG_TYPE "-form-vw-w-with-splat", cl::Hidden, cl::desc("Allow the formation of VW_W operations (e.g., " "VWADD_W) with splat constants"), cl::init(false))
static SDValue unpackF64OnRV32DSoftABI(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const CCValAssign &HiVA, const SDLoc &DL)
static SDValue foldConcatVector(SDValue V1, SDValue V2)
If concat_vector(V1,V2) could be folded away to some existing vector source, return it.
static SDValue tryMemPairCombine(SelectionDAG &DAG, LSBaseSDNode *LSNode1, LSBaseSDNode *LSNode2, SDValue BasePtr, uint64_t Imm)
static std::tuple< unsigned, SDValue, SDValue > getRVVFPReductionOpAndOperands(SDValue Op, SelectionDAG &DAG, EVT EltVT, const RISCVSubtarget &Subtarget)
static SDValue performFP_TO_INTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue combineBinOpOfExtractToReduceTree(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Perform two related transforms whose purpose is to incrementally recognize an explode_vector followed...
static SDValue lowerBuildVectorViaPacking(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Double the element size of the build vector to reduce the number of vslide1down in the build vector c...
static SDValue performTRUNCATECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerSelectToBinOp(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue combineShlAddIAdd(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerBuildVectorViaDominantValues(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Try and optimize BUILD_VECTORs with "dominant values" - these are values which constitute a large pro...
static bool isCompressMask(ArrayRef< int > Mask)
static SDValue expandMulToNAFSequence(SDNode *N, SelectionDAG &DAG, uint64_t MulAmt)
static SDValue combineToVWMACC(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isZipEven(const std::array< std::pair< int, int >, 2 > &SrcInfo, ArrayRef< int > Mask, unsigned &Factor)
Given a shuffle which can be represented as a pair of two slides, see if it is a zipeven idiom.
static SDValue combineVectorSizedSetCCEquality(EVT VT, SDValue X, SDValue Y, ISD::CondCode CC, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Try to map an integer comparison with size > XLEN to vector instructions before type legalization spl...
static SDValue performBUILD_VECTORCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
If we have a build_vector where each lane is binop X, C, where C is a constant (but not necessarily t...
static LLT getMaskTypeFor(LLT VecTy)
Return the type of the mask type suitable for masking the provided vector type.
static unsigned getRISCVWOpcode(unsigned Opcode)
const SmallVectorImpl< MachineOperand > & Cond
Contains matchers for matching SelectionDAG nodes and values.
static bool isCommutative(Instruction *I, Value *ValWithUses)
static Type * getValueType(Value *V)
Returns the type of the given value/instruction V.
This file defines the SmallSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static constexpr int Concat[]
opStatus convertFromAPInt(const APInt &Input, bool IsSigned, roundingMode RM)
opStatus convertToInteger(MutableArrayRef< integerPart > Input, unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const
static APFloat getNaN(const fltSemantics &Sem, bool Negative=false, uint64_t payload=0)
Factory for NaN values.
Class for arbitrary precision integers.
bool isNegatedPowerOf2() const
Check if this APInt's negated value is a power of two greater than zero.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
uint64_t getZExtValue() const
Get zero extended value.
void setBitsFrom(unsigned loBit)
Set the top bits starting from loBit.
unsigned getActiveBits() const
Compute the number of active bits in the value.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
bool sgt(const APInt &RHS) const
Signed greater than comparison.
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
bool ugt(const APInt &RHS) const
Unsigned greater than comparison.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
unsigned getBitWidth() const
Return the number of bits in the APInt.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
bool isNegative() const
Determine sign of this APInt.
LLVM_ABI APInt sdiv(const APInt &RHS) const
Signed division function for APInt.
void clearAllBits()
Set every bit to 0.
unsigned countr_zero() const
Count the number of trailing zero bits.
bool isSignedIntN(unsigned N) const
Check if this APInt has an N-bits signed integer value.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
unsigned getSignificantBits() const
Get the minimum bit size for this signed APInt.
LLVM_ABI void insertBits(const APInt &SubBits, unsigned bitPosition)
Insert the bits from a smaller APInt starting at bitPosition.
bool isShiftedMask() const
Return true if this APInt value contains a non-empty sequence of ones with the remainder zero.
LLVM_ABI APInt srem(const APInt &RHS) const
Function for signed remainder operation.
bool isMask(unsigned numBits) const
bool isNonNegative() const
Determine if this APInt Value is non-negative (>= 0)
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
bool slt(const APInt &RHS) const
Signed less than comparison.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
void setLowBits(unsigned loBits)
Set the bottom loBits bits.
LLVM_ABI APInt extractBits(unsigned numBits, unsigned bitPosition) const
Return an APInt with the extracted bits [bitPosition,bitPosition+numBits).
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)
Constructs an APInt value that has a contiguous range of bits set.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
int64_t getSExtValue() const
Get sign extended value.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
An arbitrary precision integer that knows its signedness.
an instruction to allocate memory on the stack
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
An instruction that atomically checks whether a specified value is in a memory location,...
Value * getCompareOperand()
an instruction that atomically reads a memory location, combines it with another value,...
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ USubCond
Subtract only if no unsigned overflow.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ UMax
*p = old >unsigned v ? old : v
@ UDecWrap
Decrement one until a minimum value or zero.
bool isFloatingPointOperation() const
BinOp getOperation() const
AtomicOrdering getOrdering() const
Returns the ordering constraint of this rmw instruction.
This is an SDNode representing atomic operations.
const SDValue & getBasePtr() const
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
static LLVM_ABI BaseIndexOffset match(const SDNode *N, const SelectionDAG &DAG)
Parses tree in N for base, index, offset addresses.
LLVM Basic Block Representation.
LLVM_ABI const Module * getModule() const
Return the module owning the function this basic block belongs to, or nullptr if the function does no...
bool test(unsigned Idx) const
bool all() const
all - Returns true if all bits are set.
CCState - This class holds information needed while lowering arguments and return values.
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
LLVM_ABI void AnalyzeCallOperands(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeCallOperands - Analyze the outgoing arguments to a call, incorporating info about the passed v...
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
LLVM_ABI bool isIndirectCall() const
Return true if the callsite is an indirect call.
This class represents a function call, abstracting a target machine's calling convention.
bool isExactlyValue(double V) const
We don't rely on operator== working on double values, as it returns true for things that are clearly ...
This is the shared class of boolean and integer constants.
bool isMinusOne() const
This function will return true iff every bit in this constant is set to true.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
int64_t getSExtValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
unsigned getPointerSizeInBits(unsigned AS=0) const
The size in bits of the pointer representation in a given address space.
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
const ValueT & at(const_arg_type_t< KeyT > Val) const
at - Return the entry for the specified key, or abort if no such entry exists.
Implements a dense probed hash-table based set.
Diagnostic information for unsupported feature in backend.
static constexpr ElementCount getScalable(ScalarTy MinVal)
static constexpr ElementCount getFixed(ScalarTy MinVal)
Tagged union holding either a T or a Error.
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
uint64_t getFnAttributeAsParsedInteger(StringRef Kind, uint64_t Default=0) const
For a string attribute Kind, parse attribute as an integer.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
AttributeList getAttributes() const
Return the attribute list for this Function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Argument * getArg(unsigned i) const
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Helper struct to store a base, index and offset that forms an address.
int64_t getOffset() const
bool hasExternalWeakLinkage() const
Module * getParent()
Get the module that this global value is contained inside of...
Common base class shared among various IRBuilders.
Value * CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
BasicBlock * GetInsertBlock() const
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
static InstructionCost getInvalid(CostType Val=0)
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
Base class for LoadSDNode and StoreSDNode.
bool isIndexed() const
Return true if this is a pre/post inc/dec load/store.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
static constexpr LocationSize beforeOrAfterPointer()
Any location before or after the base pointer (but still within the underlying object).
Context object for machine code objects.
Base class for the full range of assembler expressions which are needed for parsing.
MCContext & getContext() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
const MDOperand & getOperand(unsigned I) const
static MVT getFloatingPointVT(unsigned BitWidth)
static auto integer_fixedlen_vector_valuetypes()
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
bool isRISCVVectorTuple() const
Return true if this is a RISCV vector tuple type where the runtime length is machine dependent.
uint64_t getScalarSizeInBits() const
MVT changeVectorElementType(MVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
bool bitsLE(MVT VT) const
Return true if this has no more bits than VT.
unsigned getVectorNumElements() const
static MVT getRISCVVectorTupleVT(unsigned Sz, unsigned NFields)
bool isVector() const
Return true if this is a vector value type.
bool isInteger() const
Return true if this is an integer or a vector integer type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
static MVT getScalableVectorVT(MVT VT, unsigned NumElements)
unsigned getRISCVVectorTupleNumFields() const
Given a RISC-V vector tuple type, return the num_fields.
MVT changeTypeToInteger()
Return the type converted to an equivalently sized integer or vector with integer element type.
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
bool bitsLT(MVT VT) const
Return true if this has less bits than VT.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
LLVM_ABI const fltSemantics & getFltSemantics() const
Returns an APFloat semantics tag appropriate for the value type.
bool bitsGT(MVT VT) const
Return true if this has more bits than VT.
bool isFixedLengthVector() const
ElementCount getVectorElementCount() const
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool bitsGE(MVT VT) const
Return true if this has no less bits than VT.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
bool isValid() const
Return true if this is a valid simple valuetype.
static MVT getIntegerVT(unsigned BitWidth)
MVT getDoubleNumVectorElementsVT() const
MVT getHalfNumVectorElementsVT() const
Return a VT for a vector type with the same element type but half the number of elements.
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
static auto integer_scalable_vector_valuetypes()
MVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
static auto fp_fixedlen_vector_valuetypes()
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
void push_back(MachineInstr *MI)
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
Instructions::iterator instr_iterator
instr_iterator instr_end()
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
LLVM_ABI void collectDebugValues(SmallVectorImpl< MachineInstr * > &DbgValues)
Scan instructions immediately following MI and collect any matching DBG_VALUEs.
void setFlag(MIFlag Flag)
Set a MI flag.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
@ EK_Custom32
EK_Custom32 - Each entry is a 32-bit value that is custom lowered by the TargetLowering::LowerCustomJ...
A description of a memory reference used in the backend.
const MDNode * getRanges() const
Return the range tag for the memory reference.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MONonTemporal
The memory access is non-temporal.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
const MachinePointerInfo & getPointerInfo() const
Flags getFlags() const
Return the raw flags of the source value,.
AAMDNodes getAAInfo() const
Return the AA tags for the memory reference.
Align getBaseAlign() const
Return the minimum known alignment in bytes of the base address, without the offset.
MachineOperand class - Representation of each machine instruction operand.
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
This is an abstract virtual class for memory operations.
bool isSimple() const
Returns true if the memory operation is neither atomic or volatile.
AtomicOrdering getSuccessOrdering() const
Return the atomic ordering requirements for this memory operation.
MachineMemOperand * getMemOperand() const
Return a MachineMemOperand object describing the memory reference performed by operation.
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
A Module instance is used to store all the information related to an LLVM module.
Metadata * getModuleFlag(StringRef Key) const
Return the corresponding value if Key appears in module flags, otherwise return null.
A RISCV-specific constant pool value.
static RISCVConstantPoolValue * Create(const GlobalValue *GV)
RISCVMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private RISCV-...
void setVarArgsFrameIndex(int Index)
int getVarArgsFrameIndex() const
void setVarArgsSaveSize(int Size)
void addSExt32Register(Register Reg)
unsigned getMaxLMULForFixedLengthVectors() const
bool hasVInstructionsI64() const
bool hasVInstructionsF64() const
bool hasStdExtZfhOrZhinx() const
bool hasShlAdd(int64_t ShAmt) const
unsigned getRealMinVLen() const
bool useRVVForFixedLengthVectors() const
bool hasVInstructionsBF16Minimal() const
bool hasVInstructionsF16Minimal() const
bool hasConditionalMoveFusion() const
bool hasVInstructionsF16() const
unsigned getMaxBuildIntsCost() const
bool hasVInstructions() const
bool isRegisterReservedByUser(Register i) const override
std::optional< unsigned > getRealVLen() const
bool useConstantPoolForLargeInts() const
unsigned getRealMaxVLen() const
const RISCVRegisterInfo * getRegisterInfo() const override
const RISCVInstrInfo * getInstrInfo() const override
bool hasBEXTILike() const
const RISCVTargetLowering * getTargetLowering() const override
bool hasVInstructionsF32() const
bool hasCZEROLike() const
static std::pair< unsigned, unsigned > computeVLMAXBounds(MVT ContainerVT, const RISCVSubtarget &Subtarget)
static std::pair< unsigned, unsigned > decomposeSubvectorInsertExtractToSubRegs(MVT VecVT, MVT SubVecVT, unsigned InsertExtractIdx, const RISCVRegisterInfo *TRI)
ArrayRef< MCPhysReg > getRoundingControlRegisters() const override
Returns a 0 terminated array of rounding control registers that can be attached into strict FP call.
static MVT getM1VT(MVT VT)
Given a vector (either fixed or scalable), return the scalable vector corresponding to a vector regis...
InstructionCost getVRGatherVVCost(MVT VT) const
Return the cost of a vrgather.vv instruction for the type VT.
bool getIndexedAddressParts(SDNode *Op, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const
static unsigned getSubregIndexByMVT(MVT VT, unsigned Index)
Value * getIRStackGuard(IRBuilderBase &IRB) const override
If the target has a standard location for the stack protector cookie, returns the address of that loc...
bool shouldConvertFpToSat(unsigned Op, EVT FPVT, EVT VT) const override
Should we generate fp_to_si_sat and fp_to_ui_sat from type FPVT to type VT from min(max(fptoi)) satur...
InlineAsm::ConstraintCode getInlineAsmMemConstraint(StringRef ConstraintCode) const override
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
bool mayBeEmittedAsTailCall(const CallInst *CI) const override
Return true if the target may be able emit the call instruction as a tail call.
RISCVTargetLowering(const TargetMachine &TM, const RISCVSubtarget &STI)
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
Instruction * emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
Inserts in the IR a target-specific intrinsic specifying a fence.
bool isTruncateFree(Type *SrcTy, Type *DstTy) const override
Return true if it's free to truncate a value of type FromTy to type ToTy.
bool shouldRemoveExtendFromGSIndex(SDValue Extend, EVT DataVT) const override
Value * emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI, Value *AlignedAddr, Value *Incr, Value *Mask, Value *ShiftAmt, AtomicOrdering Ord) const override
Perform a masked atomicrmw using a target-specific intrinsic.
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const override
Returns true if the target allows unaligned memory accesses of the specified type.
const Constant * getTargetConstantFromLoad(LoadSDNode *LD) const override
This method returns the constant pool value that will be loaded by LD.
const RISCVSubtarget & getSubtarget() const
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
bool preferScalarizeSplat(SDNode *N) const override
bool shouldExtendTypeInLibCall(EVT Type) const override
Returns true if arguments should be extended in lib calls.
bool isLegalAddImmediate(int64_t Imm) const override
Return true if the specified immediate is legal add immediate, that is the target has add instruction...
bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const override
Returns true if arguments should be sign-extended in lib calls.
const MCExpr * LowerCustomJumpTableEntry(const MachineJumpTableInfo *MJTI, const MachineBasicBlock *MBB, unsigned uid, MCContext &Ctx) const override
InstructionCost getVRGatherVICost(MVT VT) const
Return the cost of a vrgather.vi (or vx) instruction for the type VT.
bool shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const override
Return true if it is beneficial to convert a load of a constant to just the constant itself.
bool targetShrinkDemandedConstant(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, TargetLoweringOpt &TLO) const override
bool shouldExpandBuildVectorWithShuffles(EVT VT, unsigned DefinedValues) const override
MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Return the register type for a given MVT, ensuring vectors are treated as a series of gpr sized integ...
bool decomposeMulByConstant(LLVMContext &Context, EVT VT, SDValue C) const override
Return true if it is profitable to transform an integer multiplication-by-constant into simpler opera...
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, LLVMContext &Context, const Type *RetTy) const override
This hook should be implemented to check whether the return values described by the Outs array can fi...
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
bool hasAndNotCompare(SDValue Y) const override
Return true if the target should transform: (X & Y) == Y ---> (~X & Y) == 0 (X & Y) !...
bool shouldScalarizeBinop(SDValue VecOp) const override
Try to convert an extract element of a vector binary operation into an extract element followed by a ...
bool isDesirableToCommuteWithShift(const SDNode *N, CombineLevel Level) const override
Return true if it is profitable to move this shift by a constant amount through its operand,...
bool areTwoSDNodeTargetMMOFlagsMergeable(const MemSDNode &NodeX, const MemSDNode &NodeY) const override
Return true if it is valid to merge the TargetMMOFlags in two SDNodes.
bool hasBitTest(SDValue X, SDValue Y) const override
Return true if the target has a bit-test instruction: (X & (1 << Y)) ==/!= 0 This knowledge can be us...
static unsigned computeVLMAX(unsigned VectorBits, unsigned EltSize, unsigned MinSize)
bool shouldExpandCttzElements(EVT VT) const override
Return true if the @llvm.experimental.cttz.elts intrinsic should be expanded using generic code in Se...
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
Value * emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, AtomicCmpXchgInst *CI, Value *AlignedAddr, Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const override
Perform a masked cmpxchg using a target-specific intrinsic.
bool isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize) const override
Returns true if the target can instruction select the specified FP immediate natively.
InstructionCost getLMULCost(MVT VT) const
Return the cost of LMUL for linear operations.
unsigned getJumpTableEncoding() const override
Return the entry encoding for a jump table in the current function.
bool isMulAddWithConstProfitable(SDValue AddNode, SDValue ConstNode) const override
Return true if it may be profitable to transform (mul (add x, c1), c2) -> (add (mul x,...
InstructionCost getVSlideVICost(MVT VT) const
Return the cost of a vslidedown.vi or vslideup.vi instruction for the type VT.
bool fallBackToDAGISel(const Instruction &Inst) const override
EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
bool isCtpopFast(EVT VT) const override
Return true if ctpop instruction is fast.
unsigned ComputeNumSignBitsForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
This method can be implemented by targets that want to expose additional information about sign bits ...
MVT getContainerForFixedLengthVector(MVT VT) const
static unsigned getRegClassIDForVecVT(MVT VT)
Register getExceptionPointerRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
TargetLowering::AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return true if EXTRACT_SUBVECTOR is cheap for extracting this result type from this source type with ...
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
MachineBasicBlock * emitDynamicProbedAlloc(MachineInstr &MI, MachineBasicBlock *MBB) const
MachineMemOperand::Flags getTargetMMOFlags(const Instruction &I) const override
This callback is used to inspect load/store instructions and add target-specific MachineMemOperand fl...
SDValue computeVLMax(MVT VecVT, const SDLoc &DL, SelectionDAG &DAG) const
bool signExtendConstant(const ConstantInt *CI) const override
Return true if this constant should be sign extended when promoting to a larger type.
bool shouldTransformSignedTruncationCheck(EVT XVT, unsigned KeptBits) const override
Should we tranform the IR-optimal check for whether given truncation down into KeptBits would be trun...
bool shouldProduceAndByConstByHoistingConstFromShiftsLHSOfAnd(SDValue X, ConstantSDNode *XC, ConstantSDNode *CC, SDValue Y, unsigned OldShiftOpcode, unsigned NewShiftOpcode, SelectionDAG &DAG) const override
Given the pattern (X & (C l>>/<< Y)) ==/!= 0 return true if it should be transformed into: ((X <</l>>...
bool hasInlineStackProbe(const MachineFunction &MF) const override
True if stack clash protection is enabled for this functions.
bool hasAndNot(SDValue Y) const override
Return true if the target has a bitwise and-not operation: X = ~A & B This can be used to simplify se...
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Returns the register with the specified architectural or ABI name.
InstructionCost getVSlideVXCost(MVT VT) const
Return the cost of a vslidedown.vx or vslideup.vx instruction for the type VT.
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override
Return true if result of the specified node is used by a return node only.
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const override
Return true if an FMA operation is faster than a pair of fmul and fadd instructions.
TargetLowering::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *CI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
Register getExceptionSelectorRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
unsigned getCustomCtpopCost(EVT VT, ISD::CondCode Cond) const override
Return the maximum number of "x & (x - 1)" operations that can be done instead of deferring to a cust...
void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override
This method should be implemented by targets that mark instructions with the 'hasPostISelHook' flag.
bool isShuffleMaskLegal(ArrayRef< int > M, EVT VT) const override
Return true if the given shuffle mask can be codegen'd directly, or if it should be stack expanded.
bool isCheapToSpeculateCttz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic cttz.
bool isLegalICmpImmediate(int64_t Imm) const override
Return true if the specified immediate is legal icmp immediate, that is the target has icmp instructi...
ISD::NodeType getExtendForAtomicCmpSwapArg() const override
Returns how the platform's atomic compare and swap expects its comparison value to be extended (ZERO_...
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower the incoming (formal) arguments, described by the Ins array,...
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I, MachineFunction &MF, unsigned Intrinsic) const override
Given an intrinsic, checks if on the target the intrinsic will need to map to a MemIntrinsicNode (tou...
unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const override
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
bool isLegalElementTypeForRVV(EVT ScalarTy) const
bool isVScaleKnownToBeAPowerOfTwo() const override
Return true only if vscale must be a power of two.
int getLegalZfaFPImm(const APFloat &Imm, EVT VT) const
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
Lower the specified operand into the Ops vector.
bool splitValueIntoRegisterParts(SelectionDAG &DAG, const SDLoc &DL, SDValue Val, SDValue *Parts, unsigned NumParts, MVT PartVT, std::optional< CallingConv::ID > CC) const override
Target-specific splitting of values into parts that fit a register storing a legal type.
Instruction * emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Return the number of registers for a given MVT, ensuring vectors are treated as a series of gpr sized...
ConstraintType getConstraintType(StringRef Constraint) const override
getConstraintType - Given a constraint letter, return the type of constraint it is for this target.
MachineInstr * EmitKCFICheck(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator &MBBI, const TargetInstrInfo *TII) const override
bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool PoisonOnly, bool ConsiderFlags, unsigned Depth) const override
Return true if Op can create undef or poison from non-undef & non-poison operands.
bool isIntDivCheap(EVT VT, AttributeList Attr) const override
Return true if integer divide is usually cheaper than a sequence of several shifts,...
SDValue expandIndirectJTBranch(const SDLoc &dl, SDValue Value, SDValue Addr, int JTI, SelectionDAG &DAG) const override
Expands target specific indirect branch for the case of JumpTable expansion.
static unsigned getRegClassIDForLMUL(RISCVVType::VLMUL LMul)
unsigned getNumRegisters(LLVMContext &Context, EVT VT, std::optional< MVT > RegisterVT=std::nullopt) const override
Return the number of registers for a given MVT, for inline assembly.
bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
Returns true by value, base pointer and offset pointer and addressing mode by reference if this node ...
bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
Returns true by value, base pointer and offset pointer and addressing mode by reference if the node's...
SDValue joinRegisterPartsIntoValue(SelectionDAG &DAG, const SDLoc &DL, const SDValue *Parts, unsigned NumParts, MVT PartVT, EVT ValueVT, std::optional< CallingConv::ID > CC) const override
Target-specific combining of register parts into its original value.
bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const override
Return if the target supports combining a chain like:
bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override
Return true if sign-extension from FromTy to ToTy is cheaper than zero-extension.
bool isLegalStridedLoadStore(EVT DataType, Align Alignment) const
Return true if a stride load store of the given result type and alignment is legal.
static bool isSpreadMask(ArrayRef< int > Mask, unsigned Factor, unsigned &Index)
Match a mask which "spreads" the leading elements of a vector evenly across the result.
static RISCVVType::VLMUL getLMUL(MVT VT)
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth) const override
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
bool shouldFoldSelectWithIdentityConstant(unsigned BinOpcode, EVT VT, unsigned SelectOpcode, SDValue X, SDValue Y) const override
Return true if pulling a binary operation into a select with an identity constant is profitable.
unsigned getStackProbeSize(const MachineFunction &MF, Align StackAlign) const
bool shouldInsertFencesForAtomic(const Instruction *I) const override
Whether AtomicExpandPass should automatically insert fences and reduce ordering for this atomic.
Wrapper class representing virtual and physical registers.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
ArrayRef< SDUse > ops() const
const APInt & getAsAPIntVal() const
Helper method returns the APInt value of a ConstantSDNode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
iterator_range< use_iterator > uses()
SDNodeFlags getFlags() const
size_t use_size() const
Return the number of uses of this node.
MVT getSimpleValueType(unsigned ResNo) const
Return the type of a specified result as a simple type.
static bool hasPredecessorHelper(const SDNode *N, SmallPtrSetImpl< const SDNode * > &Visited, SmallVectorImpl< const SDNode * > &Worklist, unsigned int MaxSteps=0, bool TopologicalPrune=false)
Returns true if N is a predecessor of any node in Worklist.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
const SDValue & getOperand(unsigned Num) const
std::optional< APInt > bitcastToAPInt() const
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
void setCFIType(uint32_t Type)
bool isUndef() const
Returns true if the node type is UNDEF or POISON.
iterator_range< user_iterator > users()
Represents a use of a SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
const APInt & getConstantOperandAPInt(unsigned i) const
uint64_t getScalarValueSizeInBits() const
uint64_t getConstantOperandVal(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getOpcode() const
unsigned getNumOperands() const
virtual bool isTargetStrictFPOpcode(unsigned Opcode) const
Returns true if a node with the given target-specific opcode has strict floating-point semantics.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI Align getReducedAlign(EVT VT, bool UseABI)
In most cases this function returns the ABI alignment for a given type, except for illegal vector typ...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
SDValue getExtractVectorElt(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Extract element at Idx from Vec.
LLVM_ABI unsigned ComputeMaxSignificantBits(SDValue Op, unsigned Depth=0) const
Get the upper bound on bit size for this Value Op as a signed integer.
LLVM_ABI SDValue getMaskedGather(SDVTList VTs, EVT MemVT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType, ISD::LoadExtType ExtTy)
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL)
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDValue getNeutralElement(unsigned Opcode, const SDLoc &DL, EVT VT, SDNodeFlags Flags)
Get the (commutative) neutral element for the given opcode, if it exists.
LLVM_ABI SDValue getAtomicLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT MemVT, EVT VT, SDValue Chain, SDValue Ptr, MachineMemOperand *MMO)
LLVM_ABI SDValue getVScale(const SDLoc &DL, EVT VT, APInt MulImm, bool ConstantFold=true)
Return a node that represents the runtime scaling 'MulImm * RuntimeVL'.
LLVM_ABI SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
LLVM_ABI SDValue getStridedLoadVP(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, const SDLoc &DL, SDValue Chain, SDValue Ptr, SDValue Offset, SDValue Stride, SDValue Mask, SDValue EVL, EVT MemVT, MachineMemOperand *MMO, bool IsExpanding=false)
LLVM_ABI SDValue makeEquivalentMemoryOrdering(SDValue OldChain, SDValue NewMemOpChain)
If an existing load has uses of its chain, create a token factor node with that chain and the new mem...
LLVM_ABI SDValue getJumpTableDebugInfo(int JTI, SDValue Chain, const SDLoc &DL)
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false)
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
bool isSafeToSpeculativelyExecute(unsigned Opcode) const
Some opcodes may create immediate undefined behavior when used with some values (integer division-by-...
LLVM_ABI SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
SDValue getExtractSubvector(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Return the VT typed sub-vector of Vec at Idx.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getElementCount(const SDLoc &DL, EVT VT, ElementCount EC, bool ConstantFold=true)
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
SDValue getInsertSubvector(const SDLoc &DL, SDValue Vec, SDValue SubVec, unsigned Idx)
Insert SubVec at the Idx element of Vec.
LLVM_ABI SDValue getStepVector(const SDLoc &DL, EVT ResVT, const APInt &StepVal)
Returns a vector of type ResVT whose elements contain the linear sequence <0, Step,...
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
LLVM_ABI bool shouldOptForSize() const
std::pair< SDValue, SDValue > SplitVectorOperand(const SDNode *N, unsigned OpNo)
Split the node's operand with EXTRACT_SUBVECTOR and return the low/high part.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
LLVM_ABI SDValue getVPZExtOrTrunc(const SDLoc &DL, EVT VT, SDValue Op, SDValue Mask, SDValue EVL)
Convert a vector-predicated Op, which must be an integer vector, to the vector-type VT,...
const TargetLowering & getTargetLoweringInfo() const
LLVM_ABI SDValue getStridedStoreVP(SDValue Chain, const SDLoc &DL, SDValue Val, SDValue Ptr, SDValue Offset, SDValue Stride, SDValue Mask, SDValue EVL, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
bool NewNodesMustHaveLegalTypes
When true, additional steps are taken to ensure that getConstant() and similar functions return DAG n...
LLVM_ABI std::pair< EVT, EVT > GetSplitDestVTs(const EVT &VT) const
Compute the VTs needed for the low/hi parts of a type which is split (or expanded) into two not neces...
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
LLVM_ABI SDValue getGatherVP(SDVTList VTs, EVT VT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType)
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI bool isSplatValue(SDValue V, const APInt &DemandedElts, APInt &UndefElts, unsigned Depth=0) const
Test whether V has a splatted value for all the demanded elements.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
const SelectionDAGTargetInfo & getSelectionDAGInfo() const
LLVM_ABI SDValue getStoreVP(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, SDValue Offset, SDValue Mask, SDValue EVL, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags=SDNodeFlags())
Returns sum of the base pointer and offset.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue getSplatVector(EVT VT, const SDLoc &DL, SDValue Op)
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI bool SignBitIsZero(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero.
SDValue getInsertVectorElt(const SDLoc &DL, SDValue Vec, SDValue Elt, unsigned Idx)
Insert Elt into Vec at offset Idx.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDValue > Ops, SDNodeFlags Flags=SDNodeFlags())
LLVM_ABI SDValue getMaskedStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Base, SDValue Offset, SDValue Mask, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
LLVM_ABI std::pair< SDValue, SDValue > getStrictFPExtendOrRound(SDValue Op, SDValue Chain, const SDLoc &DL, EVT VT)
Convert Op, which must be a STRICT operation of float type, to the float type VT, by either extending...
LLVM_ABI std::pair< SDValue, SDValue > SplitEVL(SDValue N, EVT VecVT, const SDLoc &DL)
Split the explicit vector length parameter of a VP operation.
LLVM_ABI SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either any-extending or truncat...
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getScatterVP(SDVTList VTs, EVT VT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
LLVM_ABI SDValue getFPExtendOrRound(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of float type, to the float type VT, by either extending or rounding (by tr...
LLVM_ABI bool isKnownNeverNaN(SDValue Op, const APInt &DemandedElts, bool SNaN=false, unsigned Depth=0) const
Test whether the given SDValue (or all elements of it, if it is a vector) is known to never be NaN in...
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI SDValue getBoolConstant(bool V, const SDLoc &DL, EVT VT, EVT OpVT)
Create a true or false constant of type VT using the target's BooleanContent for type OpVT.
SDValue getTargetBlockAddress(const BlockAddress *BA, EVT VT, int64_t Offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
void addCallSiteInfo(const SDNode *Node, CallSiteInfo &&CallInfo)
Set CallSiteInfo to be associated with Node.
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Base, SDValue Offset, SDValue Mask, SDValue Src0, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, ISD::LoadExtType, bool IsExpanding=false)
SDValue getSplat(EVT VT, const SDLoc &DL, SDValue Op)
Returns a node representing a splat of one value into all lanes of the provided vector type.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
LLVM_ABI SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a logical NOT operation as (XOR Val, BooleanOne).
LLVM_ABI SDValue getMaskedScatter(SDVTList VTs, EVT MemVT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType, bool IsTruncating=false)
static LLVM_ABI bool isSelectMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from its source vectors without lane crossings.
static LLVM_ABI bool isBitRotateMask(ArrayRef< int > Mask, unsigned EltSizeInBits, unsigned MinSubElts, unsigned MaxSubElts, unsigned &NumSubElts, unsigned &RotateAmt)
Checks if the shuffle is a bit rotation of the first operand across multiple subelements,...
static LLVM_ABI bool isSingleSourceMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector.
static LLVM_ABI bool isDeInterleaveMaskOfFactor(ArrayRef< int > Mask, unsigned Factor, unsigned &Index)
Check if the mask is a DE-interleave mask of the given factor Factor like: <Index,...
static LLVM_ABI bool isIdentityMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector without lane crossin...
static LLVM_ABI bool isReverseMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask swaps the order of elements from exactly one source vector.
static LLVM_ABI bool isInsertSubvectorMask(ArrayRef< int > Mask, int NumSrcElts, int &NumSubElts, int &Index)
Return true if this shuffle mask is an insert subvector mask.
static LLVM_ABI bool isInterleaveMask(ArrayRef< int > Mask, unsigned Factor, unsigned NumInputElts, SmallVectorImpl< unsigned > &StartIndexes)
Return true if the mask interleaves one or more input vectors together.
This SDNode is used to implement the code generator support for the llvm IR shufflevector instruction...
int getSplatIndex() const
ArrayRef< int > getMask() const
static LLVM_ABI bool isSplatMask(ArrayRef< int > Mask)
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
pointer data()
Return a pointer to the vector's buffer, even if empty().
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
StringRef - Represent a constant reference to a string, i.e.
constexpr size_t size() const
size - Get the string size.
LLVM_ABI std::string lower() const
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, T Value)
Information about stack frame layout on the target.
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
TargetInstrInfo - Interface to description of machine instruction set.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
bool PredictableSelectIsExpensive
Tells the code generator that select is more expensive than a branch if the branch is usually predict...
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
unsigned MaxStoresPerMemcpyOptSize
Likewise for functions with the OptSize attribute.
MachineBasicBlock * emitPatchPoint(MachineInstr &MI, MachineBasicBlock *MBB) const
Replace/modify any TargetFrameIndex operands with a targte-dependent sequence of memory operands that...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
virtual unsigned getMinimumJumpTableEntries() const
Return lower limit for number of blocks in a jump table.
const TargetMachine & getTargetMachine() const
unsigned MaxLoadsPerMemcmp
Specify maximum number of load instructions per memcmp call.
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
unsigned MaxGluedStoresPerMemcpy
Specify max number of store instructions to glue in inlined memcpy.
virtual bool isZExtFree(Type *FromTy, Type *ToTy) const
Return true if any actual instruction that defines a value of type FromTy implicitly zero-extends the...
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
void setOperationPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
Convenience method to set an operation to Promote and specify the type in a single call.
unsigned getMinCmpXchgSizeInBits() const
Returns the size of the smallest cmpxchg or ll/sc instruction the backend supports.
virtual unsigned getNumRegisters(LLVMContext &Context, EVT VT, std::optional< MVT > RegisterVT=std::nullopt) const
Return the number of registers that this ValueType will eventually require.
void setIndexedLoadAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed load does or does not work with the specified type and indicate w...
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
virtual unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
bool isOperationCustom(unsigned Op, EVT VT) const
Return true if the operation uses custom lowering, regardless of whether the type is legal or not.
unsigned MaxStoresPerMemsetOptSize
Likewise for functions with the OptSize attribute.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
unsigned MaxStoresPerMemmove
Specify maximum number of store instructions per memmove call.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
virtual bool isTruncateFree(Type *FromTy, Type *ToTy) const
Return true if it's free to truncate a value of type FromTy to type ToTy.
unsigned MaxStoresPerMemmoveOptSize
Likewise for functions with the OptSize attribute.
virtual bool shouldFoldSelectWithSingleBitTest(EVT VT, const APInt &AndMask) const
virtual Value * getIRStackGuard(IRBuilderBase &IRB) const
If the target has a standard location for the stack protector guard, returns the address of that loca...
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
bool EnableExtLdPromotion
void setIndexedStoreAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed store does or does not work with the specified type and indicate ...
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
bool isOperationLegal(unsigned Op, EVT VT) const
Return true if the specified operation is legal on this target.
unsigned MaxStoresPerMemset
Specify maximum number of store instructions per memset call.
void setPartialReduceMLAAction(unsigned Opc, MVT AccVT, MVT InputVT, LegalizeAction Action)
Indicate how a PARTIAL_REDUCE_U/SMLA node with Acc type AccVT and Input type InputVT should be treate...
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
unsigned MaxLoadsPerMemcmpOptSize
Likewise for functions with the OptSize attribute.
virtual bool isBinOp(unsigned Opcode) const
Return true if the node is a math/logic binary operator.
void setMinCmpXchgSizeInBits(unsigned SizeInBits)
Sets the minimum cmpxchg or ll/sc size supported by the backend.
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
void setCondCodeAction(ArrayRef< ISD::CondCode > CCs, MVT VT, LegalizeAction Action)
Indicate that the specified condition code is or isn't supported on the target and indicate what to d...
virtual std::pair< const TargetRegisterClass *, uint8_t > findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const
Return the largest legal super-reg register class of the register class for the specified type and it...
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
std::vector< ArgListEntry > ArgListTy
bool allowsMemoryAccessForAlignment(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
This function returns true if the memory access is aligned or if the target allows this specific unal...
unsigned MaxStoresPerMemcpy
Specify maximum number of store instructions per memcpy call.
bool isOperationLegalOrCustomOrPromote(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual MVT getVPExplicitVectorLengthTy() const
Returns the type to be used for the EVL/AVL operand of VP nodes: ISD::VP_ADD, ISD::VP_SUB,...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
SDValue expandAddSubSat(SDNode *Node, SelectionDAG &DAG) const
Method for building the DAG expansion of ISD::[US][ADD|SUB]SAT.
SDValue buildSDIVPow2WithCMov(SDNode *N, const APInt &Divisor, SelectionDAG &DAG, SmallVectorImpl< SDNode * > &Created) const
Build sdiv by power-of-2 with conditional move instructions Ref: "Hacker's Delight" by Henry Warren 1...
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
virtual SDValue expandIndirectJTBranch(const SDLoc &dl, SDValue Value, SDValue Addr, int JTI, SelectionDAG &DAG) const
Expands target specific indirect branch for the case of JumpTable expansion.
virtual InlineAsm::ConstraintCode getInlineAsmMemConstraint(StringRef ConstraintCode) const
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
virtual SDValue LowerToTLSEmulatedModel(const GlobalAddressSDNode *GA, SelectionDAG &DAG) const
Lower TLS global address SDNode for target independent emulated TLS model.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
bool isPositionIndependent() const
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
virtual bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0) const
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
TargetLowering(const TargetLowering &)=delete
virtual unsigned combineRepeatedFPDivisors() const
Indicate whether this target prefers to combine FDIVs with the same divisor.
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
virtual unsigned getJumpTableEncoding() const
Return the entry encoding for a jump table in the current function.
virtual bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool PoisonOnly, bool ConsiderFlags, unsigned Depth) const
Return true if Op can create undef or poison from non-undef & non-poison operands.
Primary interface to the complete machine description for the target machine.
TLSModel::Model getTLSModel(const GlobalValue *GV) const
Returns the TLS model which should be used for the given global variable.
const Triple & getTargetTriple() const
bool useTLSDESC() const
Returns true if this target uses TLS Descriptors.
const MCSubtargetInfo * getMCSubtargetInfo() const
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
virtual TargetLoweringObjectFile * getObjFileLowering() const
unsigned EmitCallGraphSection
Emit section containing call graph metadata.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual bool isRegisterReservedByUser(Register R) const
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
Target - Wrapper for Target specific information.
bool isOSBinFormatCOFF() const
Tests whether the OS uses the COFF binary format.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
LLVM_ABI Type * getStructElementType(unsigned N) const
LLVM_ABI bool isScalableTy(SmallPtrSetImpl< const Type * > &Visited) const
Return true if this is a type whose size is a known multiple of vscale.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
bool isStructTy() const
True if this is an instance of StructType.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isTargetExtTy() const
Return true if this is a target extension type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
A Use represents the edge between a Value definition and its users.
User * getUser() const
Returns the User that contains this Use.
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
std::pair< iterator, bool > insert(const ValueT &V)
constexpr bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
constexpr ScalarTy getFixedValue() const
static constexpr bool isKnownLE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
constexpr LeafTy multiplyCoefficientBy(ScalarTy RHS) const
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
constexpr bool isZero() const
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ RISCV_VectorCall
Calling convention used for RISC-V V-extension.
@ PreserveMost
Used for runtime calls that preserves most registers.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ SPIR_KERNEL
Used for SPIR kernel functions.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
@ GRAAL
Used by GraalVM. Two additional registers are reserved.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI bool isConstantSplatVectorAllOnes(const SDNode *N, bool BuildVectorOnly=false)
Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where all of the elements are ~0 ...
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ ADD
Simple integer binary arithmetic operators.
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ FADD
Simple binary floating point operators.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ STRICT_FSQRT
Constrained versions of libm-equivalent floating point intrinsics.
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ SIGN_EXTEND
Conversion operators.
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ CTTZ_ZERO_UNDEF
Bit counting operators with an undefined result for zero inputs.
@ VECTOR_INTERLEAVE
VECTOR_INTERLEAVE(VEC1, VEC2, ...) - Returns N vectors from N input vectors, where N is the factor to...
@ STEP_VECTOR
STEP_VECTOR(IMM) - Returns a scalable vector whose lanes are comprised of a linear sequence of unsign...
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ UNDEF
UNDEF - An undefined node.
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
@ GET_ROUNDING
Returns current rounding mode: -1 Undefined 0 Round to 0 1 Round to nearest, ties to even 2 Round to ...
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ SSHLSAT
RESULT = [US]SHLSAT(LHS, RHS) - Perform saturation left shift.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ VECTOR_REVERSE
VECTOR_REVERSE(VECTOR) - Returns a vector, of the same type as VECTOR, whose elements are shuffled us...
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ STRICT_SINT_TO_FP
STRICT_[US]INT_TO_FP - Convert a signed or unsigned integer to a floating point value.
@ EH_DWARF_CFA
EH_DWARF_CFA - This node represents the pointer to the DWARF Canonical Frame Address (CFA),...
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
@ STRICT_FADD
Constrained versions of the binary floating point operators.
@ SPLAT_VECTOR_PARTS
SPLAT_VECTOR_PARTS(SCALAR1, SCALAR2, ...) - Returns a vector with the scalar values joined together a...
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ VECTOR_SPLICE
VECTOR_SPLICE(VEC1, VEC2, IMM) - Returns a subvector of the same type as VEC1/VEC2 from CONCAT_VECTOR...
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ VECTOR_COMPRESS
VECTOR_COMPRESS(Vec, Mask, Passthru) consecutively place vector elements based on mask e....
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ VECTOR_DEINTERLEAVE
VECTOR_DEINTERLEAVE(VEC1, VEC2, ...) - Returns N vectors from N input vectors, where N is the factor ...
@ TRUNCATE_SSAT_S
TRUNCATE_[SU]SAT_[SU] - Truncate for saturated operand [SU] located in middle, prefix for SAT means i...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
LLVM_ABI bool isBuildVectorOfConstantSDNodes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR node of all ConstantSDNode or undef.
bool isNormalStore(const SDNode *N)
Returns true if the specified node is a non-truncating and unindexed store.
bool isExtOpcode(unsigned Opcode)
LLVM_ABI bool isConstantSplatVectorAllZeros(const SDNode *N, bool BuildVectorOnly=false)
Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where all of the elements are 0 o...
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
LLVM_ABI std::optional< unsigned > getVPMaskIdx(unsigned Opcode)
The operand position of the vector mask.
LLVM_ABI std::optional< unsigned > getVPExplicitVectorLengthIdx(unsigned Opcode)
The operand position of the explicit vector length parameter.
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
MemIndexType
MemIndexType enum - This enum defines how to interpret MGATHER/SCATTER's index parameter when calcula...
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
LLVM_ABI bool isBuildVectorOfConstantFPSDNodes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR node of all ConstantFPSDNode or undef.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LLVM_ABI bool isBuildVectorAllOnes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are ~0 or undef.
LLVM_ABI NodeType getVecReduceBaseOpcode(unsigned VecReduceOpcode)
Get underlying scalar opcode for VECREDUCE opcode.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
LLVM_ABI bool isVPOpcode(unsigned Opcode)
Whether this is a vector-predicated Opcode.
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
bool isIntEqualitySetCC(CondCode Code)
Return true if this is a setcc instruction that performs an equality comparison when used with intege...
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
@ Bitcast
Perform the operation on a different, but equivalently sized type.
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
CastInst_match< OpTy, TruncInst > m_Trunc(const OpTy &Op)
Matches Trunc.
BinaryOp_match< LHS, RHS, Instruction::Xor > m_Xor(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::FMul > m_FMul(const LHS &L, const RHS &R)
TwoOps_match< Val_t, Idx_t, Instruction::ExtractElement > m_ExtractElt(const Val_t &Val, const Idx_t &Idx)
Matches ExtractElementInst.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
deferredval_ty< Value > m_Deferred(Value *const &V)
Like m_Specific(), but works if the specific value to match is determined as part of the same match()...
match_combine_or< BinaryOp_match< LHS, RHS, Instruction::Add >, DisjointOr_match< LHS, RHS > > m_AddLike(const LHS &L, const RHS &R)
Match either "add" or "or disjoint".
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
FNeg_match< OpTy > m_FNeg(const OpTy &X)
Match 'fneg X' as 'fsub -0.0, X'.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
ThreeOps_match< Val_t, Elt_t, Idx_t, Instruction::InsertElement > m_InsertElt(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx)
Matches InsertElementInst.
unsigned getBrCond(CondCode CC, unsigned SelectOpc=0)
static RISCVVType::VLMUL getLMul(uint64_t TSFlags)
static int getFRMOpNum(const MCInstrDesc &Desc)
static unsigned getSEWOpNum(const MCInstrDesc &Desc)
int getLoadFPImm(APFloat FPImm)
getLoadFPImm - Return a 5-bit binary encoding of the floating-point immediate value.
InstSeq generateInstSeq(int64_t Val, const MCSubtargetInfo &STI)
int getIntMatCost(const APInt &Val, unsigned Size, const MCSubtargetInfo &STI, bool CompressionCost, bool FreeZeroes)
InstSeq generateTwoRegInstSeq(int64_t Val, const MCSubtargetInfo &STI, unsigned &ShiftAmt, unsigned &AddOpc)
SmallVector< Inst, 8 > InstSeq
static VLMUL encodeLMUL(unsigned LMUL, bool Fractional)
static unsigned decodeVSEW(unsigned VSEW)
@ TAIL_UNDISTURBED_MASK_UNDISTURBED
LLVM_ABI std::pair< unsigned, bool > decodeVLMUL(VLMUL VLMul)
static unsigned encodeSEW(unsigned SEW)
static constexpr unsigned FPMASK_Negative_Zero
static constexpr unsigned FPMASK_Positive_Subnormal
static constexpr unsigned FPMASK_Positive_Normal
static constexpr unsigned FPMASK_Negative_Subnormal
static constexpr unsigned FPMASK_Negative_Normal
static constexpr unsigned FPMASK_Positive_Infinity
static constexpr unsigned FPMASK_Negative_Infinity
static constexpr unsigned FPMASK_Quiet_NaN
ArrayRef< MCPhysReg > getArgGPRs(const RISCVABI::ABI ABI)
static constexpr unsigned FPMASK_Signaling_NaN
static constexpr unsigned FPMASK_Positive_Zero
static constexpr unsigned RVVBitsPerBlock
static constexpr unsigned RVVBytesPerBlock
LLVM_ABI Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
@ Kill
The last use of a register.
BinaryOpc_match< LHS, RHS > m_Srl(const LHS &L, const RHS &R)
Or< Preds... > m_AnyOf(const Preds &...preds)
auto m_Node(unsigned Opcode, const OpndPreds &...preds)
bool sd_match(SDNode *N, const SelectionDAG *DAG, Pattern &&P)
ConstantInt_match m_ConstInt()
Match any integer constants or splat of an integer constant.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
@ System
Synchronized with respect to all concurrently executing threads.
initializer< Ty > init(const Ty &Val)
uint32_t read32le(const void *P)
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
FunctionAddr VTableAddr Value
bool CC_RISCV_FastCC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
bool CC_RISCV_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static const MachineMemOperand::Flags MONontemporalBit1
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
MCCodeEmitter * createRISCVMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
static const MachineMemOperand::Flags MONontemporalBit0
bool RISCVCCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
RISCVCCAssignFn - This target-specific function extends the default CCValAssign with additional infor...
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI bool widenShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Try to transform a shuffle mask by replacing elements with the scaled index for an equivalent mask of...
LLVM_ABI Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
LLVM_ABI bool isNullOrNullSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndefs=false)
Return true if the value is a constant 0 integer or a splatted vector of a constant 0 integer (with n...
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
bool isReleaseOrStronger(AtomicOrdering AO)
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere.
constexpr bool has_single_bit(T Value) noexcept
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
FunctionAddr VTableAddr Count
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
bool CC_RISCV(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI bool isOneOrOneSplat(SDValue V, bool AllowUndefs=false)
Return true if the value is a constant 1 integer or a splatted vector of a constant 1 integer (with n...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
auto drop_end(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the last N elements excluded.
AtomicOrdering
Atomic ordering for LLVM's memory model.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
LLVM_ABI void narrowShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Replace each shuffle mask index with the scaled sequential indices for an equivalent mask of narrowed...
LLVM_ABI bool isMaskedSlidePair(ArrayRef< int > Mask, int NumElts, std::array< std::pair< int, int >, 2 > &SrcInfo)
Does this shuffle mask represent either one slide shuffle or a pair of two slide shuffles,...
@ Xor
Bitwise or logical XOR of integers.
@ SMin
Signed integer min implemented in terms of select(cmp()).
@ Sub
Subtraction of integers.
unsigned getKillRegState(bool B)
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
FunctionAddr VTableAddr Next
DWARFExpression::Operation Op
RoundingMode
Rounding mode.
@ TowardZero
roundTowardZero.
@ NearestTiesToEven
roundTiesToEven.
@ TowardPositive
roundTowardPositive.
@ NearestTiesToAway
roundTiesToAway.
@ TowardNegative
roundTowardNegative.
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
bool isAcquireOrStronger(AtomicOrdering AO)
constexpr unsigned BitWidth
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
LLVM_ABI void processShuffleMasks(ArrayRef< int > Mask, unsigned NumOfSrcRegs, unsigned NumOfDestRegs, unsigned NumOfUsedRegs, function_ref< void()> NoInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned)> SingleInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned, bool)> ManyInputsAction)
Splits and processes shuffle mask depending on the number of input and output registers.
unsigned Log2(Align A)
Returns the log2 of the alignment.
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
LLVM_ABI bool isNeutralConstant(unsigned Opc, SDNodeFlags Flags, SDValue V, unsigned OperandNo)
Returns true if V is a neutral element of Opc with Flags.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
auto mask(ShuffFunc S, unsigned Length, OptArgs... args) -> MaskT
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
static constexpr roundingMode rmNearestTiesToEven
static LLVM_ABI unsigned int semanticsPrecision(const fltSemantics &)
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint64_t value() const
This is a hole in the type system and should not be abused.
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
uint64_t getScalarStoreSize() const
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
bool isByteSized() const
Return true if the bit size is a multiple of 8.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
unsigned getRISCVVectorTupleNumFields() const
Given a RISCV vector tuple type, return the num_fields.
uint64_t getScalarSizeInBits() const
EVT getHalfSizedIntegerVT(LLVMContext &Context) const
Finds the smallest simple value type that is greater than or equal to half the width of this EVT.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
bool isRISCVVectorTuple() const
Return true if this is a vector value type.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isFixedLengthVector() const
EVT getRoundIntegerType(LLVMContext &Context) const
Rounds the bit-width of the given integer EVT up to the nearest power of two (and at least to eight),...
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
bool bitsGE(EVT VT) const
Return true if this has no less bits than VT.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
EVT changeVectorElementType(EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
bool isInteger() const
Return true if this is an integer or a vector integer type.
static LLVM_ABI KnownBits ashr(const KnownBits &LHS, const KnownBits &RHS, bool ShAmtNonZero=false, bool Exact=false)
Compute known bits for ashr(LHS, RHS).
static LLVM_ABI KnownBits urem(const KnownBits &LHS, const KnownBits &RHS)
Compute known bits for urem(LHS, RHS).
bool isUnknown() const
Returns true if we don't know any bits.
unsigned countMaxTrailingZeros() const
Returns the maximum number of trailing zero bits possible.
KnownBits trunc(unsigned BitWidth) const
Return known bits for a truncation of the value we're tracking.
unsigned getBitWidth() const
Get the bit width of this value.
KnownBits zext(unsigned BitWidth) const
Return known bits for a zero extension of the value we're tracking.
void resetAll()
Resets the known state of all bits.
static LLVM_ABI KnownBits lshr(const KnownBits &LHS, const KnownBits &RHS, bool ShAmtNonZero=false, bool Exact=false)
Compute known bits for lshr(LHS, RHS).
unsigned countMaxActiveBits() const
Returns the maximum number of bits needed to represent all possible unsigned values with these known ...
KnownBits intersectWith(const KnownBits &RHS) const
Returns KnownBits information that is known to be true for both this and RHS.
KnownBits sext(unsigned BitWidth) const
Return known bits for a sign extension of the value we're tracking.
static 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)