38#include "llvm/IR/IntrinsicsRISCV.h"
51#define DEBUG_TYPE "riscv-lower"
57 cl::desc(
"Give the maximum size (in number of nodes) of the web of "
58 "instructions that we will consider for VW expansion"),
63 cl::desc(
"Allow the formation of VW_W operations (e.g., "
64 "VWADD_W) with splat constants"),
69 cl::desc(
"Set the minimum number of repetitions of a divisor to allow "
70 "transformation to multiplications by the reciprocal"),
75 cl::desc(
"Give the maximum number of instructions that we will "
76 "use for creating a floating-point immediate value"),
87 !Subtarget.hasStdExtF()) {
88 errs() <<
"Hard-float 'f' ABI can't be used for a target that "
89 "doesn't support the F instruction set extension (ignoring "
93 !Subtarget.hasStdExtD()) {
94 errs() <<
"Hard-float 'd' ABI can't be used for a target that "
95 "doesn't support the D instruction set extension (ignoring "
119 if (Subtarget.hasStdExtZfhmin())
121 if (Subtarget.hasStdExtZfbfmin())
123 if (Subtarget.hasStdExtF())
125 if (Subtarget.hasStdExtD())
127 if (Subtarget.hasStdExtZhinxmin())
129 if (Subtarget.hasStdExtZfinx())
131 if (Subtarget.hasStdExtZdinx()) {
139 MVT::nxv1i1, MVT::nxv2i1, MVT::nxv4i1, MVT::nxv8i1,
140 MVT::nxv16i1, MVT::nxv32i1, MVT::nxv64i1};
142 MVT::nxv1i8, MVT::nxv2i8, MVT::nxv4i8, MVT::nxv8i8, MVT::nxv16i8,
143 MVT::nxv32i8, MVT::nxv64i8, MVT::nxv1i16, MVT::nxv2i16, MVT::nxv4i16,
144 MVT::nxv8i16, MVT::nxv16i16, MVT::nxv32i16, MVT::nxv1i32, MVT::nxv2i32,
145 MVT::nxv4i32, MVT::nxv8i32, MVT::nxv16i32, MVT::nxv1i64, MVT::nxv2i64,
146 MVT::nxv4i64, MVT::nxv8i64};
148 MVT::nxv1f16, MVT::nxv2f16, MVT::nxv4f16,
149 MVT::nxv8f16, MVT::nxv16f16, MVT::nxv32f16};
151 MVT::nxv1bf16, MVT::nxv2bf16, MVT::nxv4bf16,
152 MVT::nxv8bf16, MVT::nxv16bf16, MVT::nxv32bf16};
154 MVT::nxv1f32, MVT::nxv2f32, MVT::nxv4f32, MVT::nxv8f32, MVT::nxv16f32};
156 MVT::nxv1f64, MVT::nxv2f64, MVT::nxv4f64, MVT::nxv8f64};
159 auto addRegClassForRVV = [
this](
MVT VT) {
163 if (VT.getVectorMinNumElements() < MinElts)
166 unsigned Size = VT.getSizeInBits().getKnownMinValue();
169 RC = &RISCV::VRRegClass;
171 RC = &RISCV::VRM2RegClass;
173 RC = &RISCV::VRM4RegClass;
175 RC = &RISCV::VRM8RegClass;
182 for (
MVT VT : BoolVecVTs)
183 addRegClassForRVV(VT);
184 for (
MVT VT : IntVecVTs) {
185 if (VT.getVectorElementType() == MVT::i64 &&
188 addRegClassForRVV(VT);
192 for (
MVT VT : F16VecVTs)
193 addRegClassForRVV(VT);
196 for (
MVT VT : BF16VecVTs)
197 addRegClassForRVV(VT);
200 for (
MVT VT : F32VecVTs)
201 addRegClassForRVV(VT);
204 for (
MVT VT : F64VecVTs)
205 addRegClassForRVV(VT);
208 auto addRegClassForFixedVectors = [
this](
MVT VT) {
215 if (useRVVForFixedLengthVectorVT(VT))
216 addRegClassForFixedVectors(VT);
219 if (useRVVForFixedLengthVectorVT(VT))
220 addRegClassForFixedVectors(VT);
247 if (!(Subtarget.hasVendorXCValu() && !Subtarget.
is64Bit())) {
261 if (!Subtarget.hasStdExtZbb() && !Subtarget.hasVendorXTHeadBb() &&
262 !(Subtarget.hasVendorXCValu() && !Subtarget.
is64Bit()))
272 if (!Subtarget.hasStdExtZbb())
278 if (!Subtarget.hasStdExtZmmul()) {
280 }
else if (Subtarget.
is64Bit()) {
287 if (!Subtarget.hasStdExtM()) {
290 }
else if (Subtarget.
is64Bit()) {
292 {MVT::i8, MVT::i16, MVT::i32},
Custom);
302 if (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) {
305 }
else if (Subtarget.hasVendorXTHeadBb()) {
309 }
else if (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit()) {
318 (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb() ||
319 Subtarget.hasVendorXTHeadBb())
323 if (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit()) {
331 if (Subtarget.hasStdExtZbb() ||
332 (Subtarget.hasVendorXCValu() && !Subtarget.
is64Bit())) {
337 if (Subtarget.hasStdExtZbb() ||
338 (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit())) {
345 if (Subtarget.hasStdExtZbb() || Subtarget.hasVendorXTHeadBb() ||
346 (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit())) {
355 if (Subtarget.hasVendorXCValu() && !Subtarget.
is64Bit()) {
357 }
else if (Subtarget.hasShortForwardBranchOpt()) {
360 }
else if (Subtarget.
is64Bit()) {
364 if (!Subtarget.hasVendorXTHeadCondMov())
367 static const unsigned FPLegalNodeTypes[] = {
381 static const unsigned FPOpToExpand[] = {
385 static const unsigned FPRndMode[] = {
392 static const unsigned ZfhminZfbfminPromoteOps[] = {
408 if (Subtarget.hasStdExtZfbfmin()) {
491 if (Subtarget.hasStdExtZfa()) {
508 if (Subtarget.hasStdExtZfa()) {
580 if (Subtarget.hasStdExtZicbop()) {
584 if (Subtarget.hasStdExtA()) {
586 if (Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas())
590 }
else if (Subtarget.hasForcedAtomics()) {
614 {MVT::i8, MVT::i16},
Custom);
625 static const unsigned IntegerVPOps[] = {
626 ISD::VP_ADD, ISD::VP_SUB, ISD::VP_MUL,
627 ISD::VP_SDIV, ISD::VP_UDIV, ISD::VP_SREM,
628 ISD::VP_UREM, ISD::VP_AND, ISD::VP_OR,
629 ISD::VP_XOR, ISD::VP_SRA, ISD::VP_SRL,
630 ISD::VP_SHL, ISD::VP_REDUCE_ADD, ISD::VP_REDUCE_AND,
631 ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR, ISD::VP_REDUCE_SMAX,
632 ISD::VP_REDUCE_SMIN, ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN,
633 ISD::VP_MERGE, ISD::VP_SELECT, ISD::VP_FP_TO_SINT,
634 ISD::VP_FP_TO_UINT, ISD::VP_SETCC, ISD::VP_SIGN_EXTEND,
635 ISD::VP_ZERO_EXTEND, ISD::VP_TRUNCATE, ISD::VP_SMIN,
636 ISD::VP_SMAX, ISD::VP_UMIN, ISD::VP_UMAX,
637 ISD::VP_ABS, ISD::EXPERIMENTAL_VP_REVERSE, ISD::EXPERIMENTAL_VP_SPLICE,
638 ISD::VP_SADDSAT, ISD::VP_UADDSAT, ISD::VP_SSUBSAT,
639 ISD::VP_USUBSAT, ISD::VP_CTTZ_ELTS, ISD::VP_CTTZ_ELTS_ZERO_UNDEF,
640 ISD::EXPERIMENTAL_VP_SPLAT};
642 static const unsigned FloatingPointVPOps[] = {
643 ISD::VP_FADD, ISD::VP_FSUB, ISD::VP_FMUL,
644 ISD::VP_FDIV, ISD::VP_FNEG, ISD::VP_FABS,
645 ISD::VP_FMA, ISD::VP_REDUCE_FADD, ISD::VP_REDUCE_SEQ_FADD,
646 ISD::VP_REDUCE_FMIN, ISD::VP_REDUCE_FMAX, ISD::VP_MERGE,
647 ISD::VP_SELECT, ISD::VP_SINT_TO_FP, ISD::VP_UINT_TO_FP,
648 ISD::VP_SETCC, ISD::VP_FP_ROUND, ISD::VP_FP_EXTEND,
649 ISD::VP_SQRT, ISD::VP_FMINNUM, ISD::VP_FMAXNUM,
650 ISD::VP_FCEIL, ISD::VP_FFLOOR, ISD::VP_FROUND,
651 ISD::VP_FROUNDEVEN, ISD::VP_FCOPYSIGN, ISD::VP_FROUNDTOZERO,
652 ISD::VP_FRINT, ISD::VP_FNEARBYINT, ISD::VP_IS_FPCLASS,
653 ISD::VP_FMINIMUM, ISD::VP_FMAXIMUM, ISD::VP_LRINT,
654 ISD::VP_LLRINT, ISD::EXPERIMENTAL_VP_REVERSE,
655 ISD::EXPERIMENTAL_VP_SPLICE, ISD::VP_REDUCE_FMINIMUM,
656 ISD::VP_REDUCE_FMAXIMUM, ISD::EXPERIMENTAL_VP_SPLAT};
658 static const unsigned IntegerVecReduceOps[] = {
663 static const unsigned FloatingPointVecReduceOps[] = {
676 ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR,
677 ISD::VP_REDUCE_SMAX, ISD::VP_REDUCE_SMIN,
678 ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN},
682 for (
MVT VT : BoolVecVTs) {
712 {ISD::VP_REDUCE_AND, ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR}, VT,
736 ISD::VP_TRUNCATE, ISD::VP_SETCC},
752 for (
MVT VT : IntVecVTs) {
763 if (VT.getVectorElementType() == MVT::i64 && !Subtarget.hasStdExtV())
813 {ISD::VP_LOAD, ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
814 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER, ISD::VP_SCATTER},
838 if (Subtarget.hasStdExtZvkb()) {
846 if (Subtarget.hasStdExtZvbb()) {
850 ISD::VP_CTTZ_ZERO_UNDEF, ISD::VP_CTPOP},
856 ISD::VP_CTTZ_ZERO_UNDEF, ISD::VP_CTPOP},
865 ISD::VP_CTLZ_ZERO_UNDEF, ISD::VP_CTTZ_ZERO_UNDEF},
885 static const unsigned ZvfhminPromoteOps[] = {
895 static const unsigned ZvfhminPromoteVPOps[] = {
896 ISD::VP_FADD, ISD::VP_FSUB, ISD::VP_FMUL,
897 ISD::VP_FDIV, ISD::VP_FNEG, ISD::VP_FABS,
898 ISD::VP_FMA, ISD::VP_REDUCE_FADD, ISD::VP_REDUCE_SEQ_FADD,
899 ISD::VP_REDUCE_FMIN, ISD::VP_REDUCE_FMAX, ISD::VP_SQRT,
900 ISD::VP_FMINNUM, ISD::VP_FMAXNUM, ISD::VP_FCEIL,
901 ISD::VP_FFLOOR, ISD::VP_FROUND, ISD::VP_FROUNDEVEN,
902 ISD::VP_FCOPYSIGN, ISD::VP_FROUNDTOZERO, ISD::VP_FRINT,
903 ISD::VP_FNEARBYINT, ISD::VP_SETCC, ISD::VP_FMINIMUM,
904 ISD::VP_FMAXIMUM, ISD::VP_REDUCE_FMINIMUM, ISD::VP_REDUCE_FMAXIMUM};
907 const auto SetCommonVFPActions = [&](
MVT VT) {
952 {ISD::VP_LOAD, ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
953 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER, ISD::VP_SCATTER},
984 const auto SetCommonVFPExtLoadTruncStoreActions =
986 for (
auto SmallVT : SmallerVTs) {
993 for (
MVT VT : F16VecVTs) {
996 SetCommonVFPActions(VT);
999 for (
MVT VT : F16VecVTs) {
1010 ISD::VP_SINT_TO_FP, ISD::VP_UINT_TO_FP},
1015 if (Subtarget.hasStdExtZfhmin())
1021 if (VT == MVT::nxv32f16) {
1035 for (
MVT VT : BF16VecVTs) {
1046 if (Subtarget.hasStdExtZfbfmin())
1056 for (
MVT VT : F32VecVTs) {
1059 SetCommonVFPActions(VT);
1060 SetCommonVFPExtLoadTruncStoreActions(VT, F16VecVTs);
1065 for (
MVT VT : F64VecVTs) {
1068 SetCommonVFPActions(VT);
1069 SetCommonVFPExtLoadTruncStoreActions(VT, F16VecVTs);
1070 SetCommonVFPExtLoadTruncStoreActions(VT, F32VecVTs);
1076 if (!useRVVForFixedLengthVectorVT(VT))
1122 {ISD::VP_REDUCE_AND, ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR}, VT,
1149 ISD::VP_SETCC, ISD::VP_TRUNCATE},
1171 ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1172 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1209 if (Subtarget.hasStdExtZvkb())
1212 if (Subtarget.hasStdExtZvbb()) {
1234 if (!useRVVForFixedLengthVectorVT(VT))
1264 ISD::VP_SINT_TO_FP, ISD::VP_UINT_TO_FP},
1267 if (Subtarget.hasStdExtZfhmin()) {
1305 ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1306 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1352 if (Subtarget.hasStdExtA())
1355 if (Subtarget.hasForcedAtomics()) {
1365 if (Subtarget.hasVendorXTHeadMemIdx()) {
1381 if (Subtarget.hasVendorXCVmem() && !Subtarget.
is64Bit()) {
1406 if (Subtarget.hasStdExtZbb())
1409 if ((Subtarget.hasStdExtZbs() && Subtarget.
is64Bit()) ||
1413 if (Subtarget.hasStdExtZbkb())
1425 ISD::EXPERIMENTAL_VP_REVERSE,
ISD::MUL,
1428 if (Subtarget.hasVendorXTHeadMemPair())
1457MVT RISCVTargetLowering::getVPExplicitVectorLengthTy()
const {
1462bool RISCVTargetLowering::shouldExpandGetVectorLength(
EVT TripCountVT,
1464 bool IsScalable)
const {
1471 if (TripCountVT != MVT::i32 && TripCountVT != Subtarget.
getXLenVT())
1496 unsigned Intrinsic)
const {
1497 auto &
DL =
I.getDataLayout();
1499 auto SetRVVLoadStoreInfo = [&](
unsigned PtrOp,
bool IsStore,
1500 bool IsUnitStrided,
bool UsePtrVal =
false) {
1505 Info.ptrVal =
I.getArgOperand(PtrOp);
1507 Info.fallbackAddressSpace =
1508 I.getArgOperand(PtrOp)->getType()->getPointerAddressSpace();
1512 MemTy =
I.getArgOperand(0)->getType();
1515 MemTy =
I.getType();
1530 if (
I.hasMetadata(LLVMContext::MD_nontemporal))
1534 switch (Intrinsic) {
1537 case Intrinsic::riscv_masked_atomicrmw_xchg_i32:
1538 case Intrinsic::riscv_masked_atomicrmw_add_i32:
1539 case Intrinsic::riscv_masked_atomicrmw_sub_i32:
1540 case Intrinsic::riscv_masked_atomicrmw_nand_i32:
1541 case Intrinsic::riscv_masked_atomicrmw_max_i32:
1542 case Intrinsic::riscv_masked_atomicrmw_min_i32:
1543 case Intrinsic::riscv_masked_atomicrmw_umax_i32:
1544 case Intrinsic::riscv_masked_atomicrmw_umin_i32:
1545 case Intrinsic::riscv_masked_cmpxchg_i32:
1547 Info.memVT = MVT::i32;
1548 Info.ptrVal =
I.getArgOperand(0);
1554 case Intrinsic::riscv_seg2_load:
1555 case Intrinsic::riscv_seg3_load:
1556 case Intrinsic::riscv_seg4_load:
1557 case Intrinsic::riscv_seg5_load:
1558 case Intrinsic::riscv_seg6_load:
1559 case Intrinsic::riscv_seg7_load:
1560 case Intrinsic::riscv_seg8_load:
1561 return SetRVVLoadStoreInfo( 0,
false,
1563 case Intrinsic::riscv_seg2_store:
1564 case Intrinsic::riscv_seg3_store:
1565 case Intrinsic::riscv_seg4_store:
1566 case Intrinsic::riscv_seg5_store:
1567 case Intrinsic::riscv_seg6_store:
1568 case Intrinsic::riscv_seg7_store:
1569 case Intrinsic::riscv_seg8_store:
1571 return SetRVVLoadStoreInfo(
I.arg_size() - 2,
1574 case Intrinsic::riscv_vle:
1575 case Intrinsic::riscv_vle_mask:
1576 case Intrinsic::riscv_vleff:
1577 case Intrinsic::riscv_vleff_mask:
1578 return SetRVVLoadStoreInfo( 1,
1582 case Intrinsic::riscv_vse:
1583 case Intrinsic::riscv_vse_mask:
1584 return SetRVVLoadStoreInfo( 1,
1588 case Intrinsic::riscv_vlse:
1589 case Intrinsic::riscv_vlse_mask:
1590 case Intrinsic::riscv_vloxei:
1591 case Intrinsic::riscv_vloxei_mask:
1592 case Intrinsic::riscv_vluxei:
1593 case Intrinsic::riscv_vluxei_mask:
1594 return SetRVVLoadStoreInfo( 1,
1597 case Intrinsic::riscv_vsse:
1598 case Intrinsic::riscv_vsse_mask:
1599 case Intrinsic::riscv_vsoxei:
1600 case Intrinsic::riscv_vsoxei_mask:
1601 case Intrinsic::riscv_vsuxei:
1602 case Intrinsic::riscv_vsuxei_mask:
1603 return SetRVVLoadStoreInfo( 1,
1606 case Intrinsic::riscv_vlseg2:
1607 case Intrinsic::riscv_vlseg3:
1608 case Intrinsic::riscv_vlseg4:
1609 case Intrinsic::riscv_vlseg5:
1610 case Intrinsic::riscv_vlseg6:
1611 case Intrinsic::riscv_vlseg7:
1612 case Intrinsic::riscv_vlseg8:
1613 case Intrinsic::riscv_vlseg2ff:
1614 case Intrinsic::riscv_vlseg3ff:
1615 case Intrinsic::riscv_vlseg4ff:
1616 case Intrinsic::riscv_vlseg5ff:
1617 case Intrinsic::riscv_vlseg6ff:
1618 case Intrinsic::riscv_vlseg7ff:
1619 case Intrinsic::riscv_vlseg8ff:
1620 return SetRVVLoadStoreInfo(
I.arg_size() - 2,
1623 case Intrinsic::riscv_vlseg2_mask:
1624 case Intrinsic::riscv_vlseg3_mask:
1625 case Intrinsic::riscv_vlseg4_mask:
1626 case Intrinsic::riscv_vlseg5_mask:
1627 case Intrinsic::riscv_vlseg6_mask:
1628 case Intrinsic::riscv_vlseg7_mask:
1629 case Intrinsic::riscv_vlseg8_mask:
1630 case Intrinsic::riscv_vlseg2ff_mask:
1631 case Intrinsic::riscv_vlseg3ff_mask:
1632 case Intrinsic::riscv_vlseg4ff_mask:
1633 case Intrinsic::riscv_vlseg5ff_mask:
1634 case Intrinsic::riscv_vlseg6ff_mask:
1635 case Intrinsic::riscv_vlseg7ff_mask:
1636 case Intrinsic::riscv_vlseg8ff_mask:
1637 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
1640 case Intrinsic::riscv_vlsseg2:
1641 case Intrinsic::riscv_vlsseg3:
1642 case Intrinsic::riscv_vlsseg4:
1643 case Intrinsic::riscv_vlsseg5:
1644 case Intrinsic::riscv_vlsseg6:
1645 case Intrinsic::riscv_vlsseg7:
1646 case Intrinsic::riscv_vlsseg8:
1647 case Intrinsic::riscv_vloxseg2:
1648 case Intrinsic::riscv_vloxseg3:
1649 case Intrinsic::riscv_vloxseg4:
1650 case Intrinsic::riscv_vloxseg5:
1651 case Intrinsic::riscv_vloxseg6:
1652 case Intrinsic::riscv_vloxseg7:
1653 case Intrinsic::riscv_vloxseg8:
1654 case Intrinsic::riscv_vluxseg2:
1655 case Intrinsic::riscv_vluxseg3:
1656 case Intrinsic::riscv_vluxseg4:
1657 case Intrinsic::riscv_vluxseg5:
1658 case Intrinsic::riscv_vluxseg6:
1659 case Intrinsic::riscv_vluxseg7:
1660 case Intrinsic::riscv_vluxseg8:
1661 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1664 case Intrinsic::riscv_vlsseg2_mask:
1665 case Intrinsic::riscv_vlsseg3_mask:
1666 case Intrinsic::riscv_vlsseg4_mask:
1667 case Intrinsic::riscv_vlsseg5_mask:
1668 case Intrinsic::riscv_vlsseg6_mask:
1669 case Intrinsic::riscv_vlsseg7_mask:
1670 case Intrinsic::riscv_vlsseg8_mask:
1671 case Intrinsic::riscv_vloxseg2_mask:
1672 case Intrinsic::riscv_vloxseg3_mask:
1673 case Intrinsic::riscv_vloxseg4_mask:
1674 case Intrinsic::riscv_vloxseg5_mask:
1675 case Intrinsic::riscv_vloxseg6_mask:
1676 case Intrinsic::riscv_vloxseg7_mask:
1677 case Intrinsic::riscv_vloxseg8_mask:
1678 case Intrinsic::riscv_vluxseg2_mask:
1679 case Intrinsic::riscv_vluxseg3_mask:
1680 case Intrinsic::riscv_vluxseg4_mask:
1681 case Intrinsic::riscv_vluxseg5_mask:
1682 case Intrinsic::riscv_vluxseg6_mask:
1683 case Intrinsic::riscv_vluxseg7_mask:
1684 case Intrinsic::riscv_vluxseg8_mask:
1685 return SetRVVLoadStoreInfo(
I.arg_size() - 5,
1688 case Intrinsic::riscv_vsseg2:
1689 case Intrinsic::riscv_vsseg3:
1690 case Intrinsic::riscv_vsseg4:
1691 case Intrinsic::riscv_vsseg5:
1692 case Intrinsic::riscv_vsseg6:
1693 case Intrinsic::riscv_vsseg7:
1694 case Intrinsic::riscv_vsseg8:
1695 return SetRVVLoadStoreInfo(
I.arg_size() - 2,
1698 case Intrinsic::riscv_vsseg2_mask:
1699 case Intrinsic::riscv_vsseg3_mask:
1700 case Intrinsic::riscv_vsseg4_mask:
1701 case Intrinsic::riscv_vsseg5_mask:
1702 case Intrinsic::riscv_vsseg6_mask:
1703 case Intrinsic::riscv_vsseg7_mask:
1704 case Intrinsic::riscv_vsseg8_mask:
1705 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1708 case Intrinsic::riscv_vssseg2:
1709 case Intrinsic::riscv_vssseg3:
1710 case Intrinsic::riscv_vssseg4:
1711 case Intrinsic::riscv_vssseg5:
1712 case Intrinsic::riscv_vssseg6:
1713 case Intrinsic::riscv_vssseg7:
1714 case Intrinsic::riscv_vssseg8:
1715 case Intrinsic::riscv_vsoxseg2:
1716 case Intrinsic::riscv_vsoxseg3:
1717 case Intrinsic::riscv_vsoxseg4:
1718 case Intrinsic::riscv_vsoxseg5:
1719 case Intrinsic::riscv_vsoxseg6:
1720 case Intrinsic::riscv_vsoxseg7:
1721 case Intrinsic::riscv_vsoxseg8:
1722 case Intrinsic::riscv_vsuxseg2:
1723 case Intrinsic::riscv_vsuxseg3:
1724 case Intrinsic::riscv_vsuxseg4:
1725 case Intrinsic::riscv_vsuxseg5:
1726 case Intrinsic::riscv_vsuxseg6:
1727 case Intrinsic::riscv_vsuxseg7:
1728 case Intrinsic::riscv_vsuxseg8:
1729 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1732 case Intrinsic::riscv_vssseg2_mask:
1733 case Intrinsic::riscv_vssseg3_mask:
1734 case Intrinsic::riscv_vssseg4_mask:
1735 case Intrinsic::riscv_vssseg5_mask:
1736 case Intrinsic::riscv_vssseg6_mask:
1737 case Intrinsic::riscv_vssseg7_mask:
1738 case Intrinsic::riscv_vssseg8_mask:
1739 case Intrinsic::riscv_vsoxseg2_mask:
1740 case Intrinsic::riscv_vsoxseg3_mask:
1741 case Intrinsic::riscv_vsoxseg4_mask:
1742 case Intrinsic::riscv_vsoxseg5_mask:
1743 case Intrinsic::riscv_vsoxseg6_mask:
1744 case Intrinsic::riscv_vsoxseg7_mask:
1745 case Intrinsic::riscv_vsoxseg8_mask:
1746 case Intrinsic::riscv_vsuxseg2_mask:
1747 case Intrinsic::riscv_vsuxseg3_mask:
1748 case Intrinsic::riscv_vsuxseg4_mask:
1749 case Intrinsic::riscv_vsuxseg5_mask:
1750 case Intrinsic::riscv_vsuxseg6_mask:
1751 case Intrinsic::riscv_vsuxseg7_mask:
1752 case Intrinsic::riscv_vsuxseg8_mask:
1753 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
1794 return isInt<12>(Imm);
1798 return isInt<12>(Imm);
1811 return (SrcBits == 64 && DestBits == 32);
1822 return (SrcBits == 64 && DestBits == 32);
1833 if (SrcBits == DestBits * 2) {
1844 if (
auto *LD = dyn_cast<LoadSDNode>(Val)) {
1845 EVT MemVT = LD->getMemoryVT();
1846 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
1856 return Subtarget.
is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
1864 return Subtarget.hasStdExtZbb() ||
1865 (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit());
1869 return Subtarget.hasStdExtZbb() || Subtarget.hasVendorXTHeadBb() ||
1870 (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit());
1881 if (!Subtarget.hasStdExtZbs() && !Subtarget.hasVendorXTHeadBs())
1886 return !Mask->getValue().isSignedIntN(12) && Mask->getValue().isPowerOf2();
1890 EVT VT =
Y.getValueType();
1896 return (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
1897 (!isa<ConstantSDNode>(
Y) || cast<ConstantSDNode>(
Y)->isOpaque());
1902 if (Subtarget.hasStdExtZbs())
1903 return X.getValueType().isScalarInteger();
1904 auto *
C = dyn_cast<ConstantSDNode>(
Y);
1906 if (Subtarget.hasVendorXTHeadBs())
1907 return C !=
nullptr;
1909 return C &&
C->getAPIntValue().ule(10);
1929 if (BitSize > Subtarget.
getXLen())
1933 int64_t Val = Imm.getSExtValue();
1941 if (!Subtarget.enableUnalignedScalarMem())
1957 unsigned OldShiftOpcode,
unsigned NewShiftOpcode,
1964 if (XC && OldShiftOpcode ==
ISD::SRL && XC->isOne())
1968 if (NewShiftOpcode ==
ISD::SRL &&
CC->isOne())
1980 case Instruction::Add:
1981 case Instruction::Sub:
1982 case Instruction::Mul:
1983 case Instruction::And:
1984 case Instruction::Or:
1985 case Instruction::Xor:
1986 case Instruction::FAdd:
1987 case Instruction::FSub:
1988 case Instruction::FMul:
1989 case Instruction::FDiv:
1990 case Instruction::ICmp:
1991 case Instruction::FCmp:
1993 case Instruction::Shl:
1994 case Instruction::LShr:
1995 case Instruction::AShr:
1996 case Instruction::UDiv:
1997 case Instruction::SDiv:
1998 case Instruction::URem:
1999 case Instruction::SRem:
2000 case Instruction::Select:
2001 return Operand == 1;
2015 auto *
II = dyn_cast<IntrinsicInst>(
I);
2019 switch (
II->getIntrinsicID()) {
2020 case Intrinsic::fma:
2021 case Intrinsic::vp_fma:
2022 return Operand == 0 || Operand == 1;
2023 case Intrinsic::vp_shl:
2024 case Intrinsic::vp_lshr:
2025 case Intrinsic::vp_ashr:
2026 case Intrinsic::vp_udiv:
2027 case Intrinsic::vp_sdiv:
2028 case Intrinsic::vp_urem:
2029 case Intrinsic::vp_srem:
2030 case Intrinsic::ssub_sat:
2031 case Intrinsic::vp_ssub_sat:
2032 case Intrinsic::usub_sat:
2033 case Intrinsic::vp_usub_sat:
2034 return Operand == 1;
2036 case Intrinsic::vp_add:
2037 case Intrinsic::vp_mul:
2038 case Intrinsic::vp_and:
2039 case Intrinsic::vp_or:
2040 case Intrinsic::vp_xor:
2041 case Intrinsic::vp_fadd:
2042 case Intrinsic::vp_fmul:
2043 case Intrinsic::vp_icmp:
2044 case Intrinsic::vp_fcmp:
2045 case Intrinsic::smin:
2046 case Intrinsic::vp_smin:
2047 case Intrinsic::umin:
2048 case Intrinsic::vp_umin:
2049 case Intrinsic::smax:
2050 case Intrinsic::vp_smax:
2051 case Intrinsic::umax:
2052 case Intrinsic::vp_umax:
2053 case Intrinsic::sadd_sat:
2054 case Intrinsic::vp_sadd_sat:
2055 case Intrinsic::uadd_sat:
2056 case Intrinsic::vp_uadd_sat:
2058 case Intrinsic::vp_sub:
2059 case Intrinsic::vp_fsub:
2060 case Intrinsic::vp_fdiv:
2061 return Operand == 0 || Operand == 1;
2082 if (!Subtarget.sinkSplatOperands())
2085 for (
auto OpIdx :
enumerate(
I->operands())) {
2089 Instruction *
Op = dyn_cast<Instruction>(OpIdx.value().get());
2091 if (!
Op ||
any_of(Ops, [&](
Use *U) {
return U->get() ==
Op; }))
2100 if (cast<VectorType>(
Op->getType())->getElementType()->isIntegerTy(1))
2105 for (
Use &U :
Op->uses()) {
2157 if (!Subtarget.hasStdExtZfa())
2158 return std::make_pair(-1,
false);
2160 bool IsSupportedVT =
false;
2161 if (VT == MVT::f16) {
2162 IsSupportedVT = Subtarget.hasStdExtZfh() || Subtarget.hasStdExtZvfh();
2163 }
else if (VT == MVT::f32) {
2164 IsSupportedVT =
true;
2165 }
else if (VT == MVT::f64) {
2166 assert(Subtarget.hasStdExtD() &&
"Expect D extension");
2167 IsSupportedVT =
true;
2171 return std::make_pair(-1,
false);
2174 if (
Index < 0 && Imm.isNegative())
2178 return std::make_pair(
Index,
false);
2182 bool ForCodeSize)
const {
2183 bool IsLegalVT =
false;
2186 else if (VT == MVT::f32)
2188 else if (VT == MVT::f64)
2190 else if (VT == MVT::bf16)
2191 IsLegalVT = Subtarget.hasStdExtZfbfmin();
2203 return Imm.isZero();
2207 if (Imm.isNegZero())
2220 unsigned Index)
const {
2233 if (EltVT == MVT::i1)
2246 if (
Index + ResElts <= MinVLMAX &&
Index < 31)
2253 if ((ResElts * 2) != SrcElts)
2294 unsigned &NumIntermediates,
MVT &RegisterVT)
const {
2296 Context,
CC, VT, IntermediateVT, NumIntermediates, RegisterVT);
2311 isa<ConstantSDNode>(
LHS.getOperand(1))) {
2317 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
2330 if (
auto *RHSC = dyn_cast<ConstantSDNode>(
RHS)) {
2331 int64_t
C = RHSC->getSExtValue();
2373 switch (KnownSize) {
2401 return RISCV::VRRegClassID;
2403 return RISCV::VRM2RegClassID;
2405 return RISCV::VRM4RegClassID;
2407 return RISCV::VRM8RegClassID;
2417 static_assert(RISCV::sub_vrm1_7 == RISCV::sub_vrm1_0 + 7,
2418 "Unexpected subreg numbering");
2419 return RISCV::sub_vrm1_0 +
Index;
2422 static_assert(RISCV::sub_vrm2_3 == RISCV::sub_vrm2_0 + 3,
2423 "Unexpected subreg numbering");
2424 return RISCV::sub_vrm2_0 +
Index;
2427 static_assert(RISCV::sub_vrm4_1 == RISCV::sub_vrm4_0 + 1,
2428 "Unexpected subreg numbering");
2429 return RISCV::sub_vrm4_0 +
Index;
2436 return RISCV::VRRegClassID;
2445std::pair<unsigned, unsigned>
2447 MVT VecVT,
MVT SubVecVT,
unsigned InsertExtractIdx,
2449 static_assert((RISCV::VRM8RegClassID > RISCV::VRM4RegClassID &&
2450 RISCV::VRM4RegClassID > RISCV::VRM2RegClassID &&
2451 RISCV::VRM2RegClassID > RISCV::VRRegClassID),
2452 "Register classes not ordered");
2461 unsigned SubRegIdx = RISCV::NoSubRegister;
2462 for (
const unsigned RCID :
2463 {RISCV::VRM4RegClassID, RISCV::VRM2RegClassID, RISCV::VRRegClassID})
2464 if (VecRegClassID > RCID && SubRegClassID <= RCID) {
2468 SubRegIdx =
TRI->composeSubRegIndices(SubRegIdx,
2473 return {SubRegIdx, InsertExtractIdx};
2478bool RISCVTargetLowering::mergeStoresAfterLegalization(
EVT VT)
const {
2507unsigned RISCVTargetLowering::combineRepeatedFPDivisors()
const {
2514 "Unexpected opcode");
2516 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
2518 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
2521 return Op.getOperand(
II->VLOperand + 1 + HasChain);
2595bool RISCVTargetLowering::useRVVForFixedLengthVectorVT(
MVT VT)
const {
2596 return ::useRVVForFixedLengthVectorVT(VT, Subtarget);
2605 "Expected legal fixed length vector!");
2608 unsigned MaxELen = Subtarget.
getELen();
2642 return ::getContainerForFixedLengthVector(*
this, VT,
getSubtarget());
2649 "Expected to convert into a scalable vector!");
2650 assert(V.getValueType().isFixedLengthVector() &&
2651 "Expected a fixed length vector operand!");
2661 "Expected to convert into a fixed length vector!");
2662 assert(V.getValueType().isScalableVector() &&
2663 "Expected a scalable vector operand!");
2686static std::pair<SDValue, SDValue>
2695static std::pair<SDValue, SDValue>
2708static std::pair<SDValue, SDValue>
2725std::pair<unsigned, unsigned>
2741 return std::make_pair(MinVLMAX, MaxVLMAX);
2753 EVT VT,
unsigned DefinedValues)
const {
2767 std::tie(LMul, Fractional) =
2770 Cost = LMul <= DLenFactor ? (DLenFactor / LMul) : 1;
2772 Cost = (LMul * DLenFactor);
2817 MVT DstVT =
Op.getSimpleValueType();
2818 EVT SatVT = cast<VTSDNode>(
Op.getOperand(1))->getVT();
2826 Src.getValueType() == MVT::bf16) {
2833 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
2841 Opc,
DL, DstVT, Src,
2855 MVT SrcVT = Src.getSimpleValueType();
2861 if (SatVT != DstEltVT)
2864 MVT DstContainerVT = DstVT;
2865 MVT SrcContainerVT = SrcVT;
2871 "Expected same element count");
2880 {Src, Src, DAG.getCondCode(ISD::SETNE),
2881 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
2885 if (DstEltSize > (2 * SrcEltSize)) {
2891 MVT CvtContainerVT = DstContainerVT;
2892 MVT CvtEltVT = DstEltVT;
2893 if (SrcEltSize > (2 * DstEltSize)) {
2902 while (CvtContainerVT != DstContainerVT) {
2908 Res = DAG.
getNode(ClipOpc,
DL, CvtContainerVT, Res, Mask, VL);
2915 Res, DAG.
getUNDEF(DstContainerVT), VL);
2927 case ISD::VP_FROUNDEVEN:
2931 case ISD::VP_FROUNDTOZERO:
2935 case ISD::VP_FFLOOR:
2943 case ISD::VP_FROUND:
2959 MVT VT =
Op.getSimpleValueType();
2966 MVT ContainerVT = VT;
2973 if (
Op->isVPOpcode()) {
2974 Mask =
Op.getOperand(1);
2978 VL =
Op.getOperand(2);
3000 DAG.
getUNDEF(ContainerVT), MaxValNode, VL);
3014 switch (
Op.getOpcode()) {
3020 case ISD::VP_FFLOOR:
3023 case ISD::VP_FROUND:
3024 case ISD::VP_FROUNDEVEN:
3025 case ISD::VP_FROUNDTOZERO: {
3041 case ISD::VP_FNEARBYINT:
3054 Src, Src, Mask, VL);
3069 MVT VT =
Op.getSimpleValueType();
3073 MVT ContainerVT = VT;
3085 MVT MaskVT = Mask.getSimpleValueType();
3088 {Chain, Src, Src, DAG.getCondCode(ISD::SETUNE),
3089 DAG.getUNDEF(MaskVT), Mask, VL});
3093 {Chain, Src, Src, Src, Unorder, VL});
3094 Chain = Src.getValue(1);
3110 DAG.
getUNDEF(ContainerVT), MaxValNode, VL);
3122 switch (
Op.getOpcode()) {
3133 {Chain, Src, Mask, DAG.getTargetConstant(FRM, DL, XLenVT), VL});
3139 DAG.
getVTList(IntVT, MVT::Other), Chain, Src, Mask, VL);
3143 DAG.
getVTList(ContainerVT, MVT::Other), Chain, Src,
3152 DAG.
getVTList(ContainerVT, MVT::Other), Chain,
3153 Truncated, Mask, VL);
3159 Src, Src, Mask, VL);
3169 MVT VT =
Op.getSimpleValueType();
3197 MVT VT =
Op.getSimpleValueType();
3202 MVT ContainerVT = VT;
3245 "Unexpected vector MVT");
3273 return std::nullopt;
3291 unsigned EltSizeInBits) {
3294 return std::nullopt;
3295 bool IsInteger =
Op.getValueType().isInteger();
3297 std::optional<unsigned> SeqStepDenom;
3298 std::optional<APInt> SeqStepNum;
3299 std::optional<APInt> SeqAddend;
3300 std::optional<std::pair<APInt, unsigned>> PrevElt;
3301 assert(EltSizeInBits >=
Op.getValueType().getScalarSizeInBits());
3306 const unsigned OpSize =
Op.getScalarValueSizeInBits();
3308 if (Elt.isUndef()) {
3309 Elts[
Idx] = std::nullopt;
3313 Elts[
Idx] = Elt->getAsAPIntVal().trunc(OpSize).zext(EltSizeInBits);
3318 return std::nullopt;
3319 Elts[
Idx] = *ExactInteger;
3332 unsigned IdxDiff =
Idx - PrevElt->second;
3333 APInt ValDiff = *Elt - PrevElt->first;
3341 int64_t Remainder = ValDiff.
srem(IdxDiff);
3346 return std::nullopt;
3347 ValDiff = ValDiff.
sdiv(IdxDiff);
3352 SeqStepNum = ValDiff;
3353 else if (ValDiff != SeqStepNum)
3354 return std::nullopt;
3357 SeqStepDenom = IdxDiff;
3358 else if (IdxDiff != *SeqStepDenom)
3359 return std::nullopt;
3363 if (!PrevElt || PrevElt->first != *Elt)
3364 PrevElt = std::make_pair(*Elt,
Idx);
3368 if (!SeqStepNum || !SeqStepDenom)
3369 return std::nullopt;
3377 (
APInt(EltSizeInBits,
Idx) * *SeqStepNum).sdiv(*SeqStepDenom);
3379 APInt Addend = *Elt - ExpectedVal;
3382 else if (Addend != SeqAddend)
3383 return std::nullopt;
3386 assert(SeqAddend &&
"Must have an addend if we have a step");
3388 return VIDSequence{SeqStepNum->getSExtValue(), *SeqStepDenom,
3389 SeqAddend->getSExtValue()};
3410 MVT ContainerVT = VT;
3438 MVT VT =
Op.getSimpleValueType();
3450 unsigned MostCommonCount = 0;
3452 unsigned NumUndefElts =
3460 unsigned NumScalarLoads = 0;
3466 ValueCounts.
insert(std::make_pair(V, 0));
3467 unsigned &Count = ValueCounts[V];
3469 if (
auto *CFP = dyn_cast<ConstantFPSDNode>(V))
3470 NumScalarLoads += !CFP->isExactlyValue(+0.0);
3475 if (++Count >= MostCommonCount) {
3477 MostCommonCount = Count;
3481 assert(DominantValue &&
"Not expecting an all-undef BUILD_VECTOR");
3482 unsigned NumDefElts = NumElts - NumUndefElts;
3483 unsigned DominantValueCountThreshold = NumDefElts <= 2 ? 0 : NumDefElts - 2;
3489 ((MostCommonCount > DominantValueCountThreshold) ||
3502 !LastOp.isUndef() && ValueCounts[LastOp] == 1 &&
3503 LastOp != DominantValue) {
3512 Processed.insert(LastOp);
3517 const SDValue &V = OpIdx.value();
3518 if (V.isUndef() || !Processed.insert(V).second)
3520 if (ValueCounts[V] == 1) {
3529 return DAG.getConstant(V == V1, DL, XLenVT);
3545 MVT VT =
Op.getSimpleValueType();
3575 unsigned NumViaIntegerBits = std::clamp(NumElts, 8u, Subtarget.
getXLen());
3576 NumViaIntegerBits = std::min(NumViaIntegerBits, Subtarget.
getELen());
3584 unsigned IntegerViaVecElts =
divideCeil(NumElts, NumViaIntegerBits);
3585 MVT IntegerViaVecVT =
3590 unsigned BitPos = 0, IntegerEltIdx = 0;
3593 for (
unsigned I = 0;
I < NumElts;) {
3595 bool BitValue = !V.isUndef() && V->getAsZExtVal();
3596 Bits |= ((
uint64_t)BitValue << BitPos);
3602 if (
I % NumViaIntegerBits == 0 ||
I == NumElts) {
3603 if (NumViaIntegerBits <= 32)
3604 Bits = SignExtend64<32>(Bits);
3606 Elts[IntegerEltIdx] = Elt;
3615 if (NumElts < NumViaIntegerBits) {
3619 assert(IntegerViaVecVT == MVT::v1i8 &&
"Unexpected mask vector type");
3647 int64_t StepNumerator = SimpleVID->StepNumerator;
3648 unsigned StepDenominator = SimpleVID->StepDenominator;
3649 int64_t Addend = SimpleVID->Addend;
3651 assert(StepNumerator != 0 &&
"Invalid step");
3652 bool Negate =
false;
3653 int64_t SplatStepVal = StepNumerator;
3657 if (StepNumerator != 1 && StepNumerator !=
INT64_MIN &&
3659 Negate = StepNumerator < 0;
3661 SplatStepVal =
Log2_64(std::abs(StepNumerator));
3668 if (((StepOpcode ==
ISD::MUL && isInt<12>(SplatStepVal)) ||
3669 (StepOpcode ==
ISD::SHL && isUInt<5>(SplatStepVal))) &&
3671 (SplatStepVal >= 0 || StepDenominator == 1) && isInt<5>(Addend)) {
3674 MVT VIDContainerVT =
3682 if ((StepOpcode ==
ISD::MUL && SplatStepVal != 1) ||
3683 (StepOpcode ==
ISD::SHL && SplatStepVal != 0)) {
3685 VID = DAG.
getNode(StepOpcode,
DL, VIDVT, VID, SplatStep);
3687 if (StepDenominator != 1) {
3692 if (Addend != 0 || Negate) {
3711 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32) &&
3712 "Unexpected sequence type");
3716 unsigned ViaVecLen =
3720 uint64_t EltMask = maskTrailingOnes<uint64_t>(EltBitSize);
3723 for (
const auto &OpIdx :
enumerate(
Op->op_values())) {
3724 const auto &SeqV = OpIdx.value();
3725 if (!SeqV.isUndef())
3727 ((SeqV->getAsZExtVal() & EltMask) << (OpIdx.index() * EltBitSize));
3733 if (ViaIntVT == MVT::i32)
3734 SplatValue = SignExtend64<32>(SplatValue);
3756 const auto *BV = cast<BuildVectorSDNode>(
Op);
3759 BV->getRepeatedSequence(Sequence) &&
3760 (Sequence.size() * EltBitSize) <= Subtarget.
getELen()) {
3761 unsigned SeqLen = Sequence.size();
3763 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32 ||
3764 ViaIntVT == MVT::i64) &&
3765 "Unexpected sequence type");
3770 const unsigned RequiredVL = NumElts / SeqLen;
3771 const unsigned ViaVecLen =
3773 NumElts : RequiredVL;
3776 unsigned EltIdx = 0;
3777 uint64_t EltMask = maskTrailingOnes<uint64_t>(EltBitSize);
3781 for (
const auto &SeqV : Sequence) {
3782 if (!SeqV.isUndef())
3784 ((SeqV->getAsZExtVal() & EltMask) << (EltIdx * EltBitSize));
3791 if (ViaIntVT == MVT::i32)
3792 SplatValue = SignExtend64<32>(SplatValue);
3798 (!Subtarget.
is64Bit() && ViaIntVT == MVT::i64)) &&
3799 "Unexpected bitcast sequence");
3800 if (ViaIntVT.
bitsLE(XLenVT) || isInt<32>(SplatValue)) {
3803 MVT ViaContainerVT =
3810 if (ViaVecLen != RequiredVL)
3830 Source, DAG, Subtarget);
3850 return RISCV::PACKH;
3852 return Subtarget.
is64Bit() ? RISCV::PACKW : RISCV::PACK;
3867 MVT VT =
Op.getSimpleValueType();
3875 if (!Subtarget.hasStdExtZbb() || !Subtarget.hasStdExtZba())
3880 if (ElemSizeInBits >= std::min(Subtarget.
getELen(), Subtarget.
getXLen()) ||
3894 if (Subtarget.hasStdExtZbkb())
3899 ElemDL, XLenVT,
A,
B),
3906 Flags.setDisjoint(
true);
3912 NewOperands.
reserve(NumElts / 2);
3914 NewOperands.
push_back(pack(
Op.getOperand(i),
Op.getOperand(i + 1)));
3924 MVT VT =
Op.getSimpleValueType();
3935 MVT VT =
Op.getSimpleValueType();
3940 !Subtarget.hasStdExtZfhmin())
4012 auto OneVRegOfOps =
ArrayRef(BuildVectorOps).
slice(i, ElemsPerVReg);
4016 unsigned InsertIdx = (i / ElemsPerVReg) * NumOpElts;
4039 unsigned NumUndefElts =
4041 unsigned NumDefElts = NumElts - NumUndefElts;
4042 if (NumDefElts >= 8 && NumDefElts > NumElts / 2 &&
4049 for (
unsigned i = 0; i < NumElts; i++) {
4051 if (i < NumElts / 2) {
4058 bool SelectMaskVal = (i < NumElts / 2);
4061 assert(SubVecAOps.
size() == NumElts && SubVecBOps.
size() == NumElts &&
4062 MaskVals.
size() == NumElts);
4097 unsigned UndefCount = 0;
4104 LinearBudget -= PerSlideCost;
4107 LinearBudget -= PerSlideCost;
4110 LinearBudget -= PerSlideCost;
4113 if (LinearBudget < 0)
4118 "Illegal type which will result in reserved encoding");
4143 Vec,
Offset, Mask, VL, Policy);
4156 Vec,
Offset, Mask, VL, Policy);
4166 if (isa<ConstantSDNode>(
Lo) && isa<ConstantSDNode>(
Hi)) {
4167 int32_t LoC = cast<ConstantSDNode>(
Lo)->getSExtValue();
4168 int32_t HiC = cast<ConstantSDNode>(
Hi)->getSExtValue();
4171 if ((LoC >> 31) == HiC)
4182 (isa<RegisterSDNode>(VL) &&
4183 cast<RegisterSDNode>(VL)->
getReg() == RISCV::X0))
4185 else if (isa<ConstantSDNode>(VL) && isUInt<4>(VL->
getAsZExtVal()))
4200 isa<ConstantSDNode>(
Hi.getOperand(1)) &&
4201 Hi.getConstantOperandVal(1) == 31)
4220 assert(Scalar.getValueType() == MVT::i64 &&
"Unexpected VT!");
4232 bool HasPassthru = Passthru && !Passthru.
isUndef();
4233 if (!HasPassthru && !Passthru)
4241 if (Scalar.getValueType().bitsLE(XLenVT)) {
4248 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4252 assert(XLenVT == MVT::i32 && Scalar.getValueType() == MVT::i64 &&
4253 "Unexpected scalar for splat lowering!");
4277 SDValue ExtractedVal = Scalar.getOperand(0);
4282 MVT ExtractedContainerVT = ExtractedVT;
4285 DAG, ExtractedContainerVT, Subtarget);
4287 ExtractedVal, DAG, Subtarget);
4289 if (ExtractedContainerVT.
bitsLE(VT))
4304 if (!Scalar.getValueType().bitsLE(XLenVT))
4307 VT,
DL, DAG, Subtarget);
4315 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4341 if (Src != V2.getOperand(0))
4345 if (Src.getValueType().getVectorNumElements() != (Mask.size() * 2))
4350 V2.getConstantOperandVal(1) != Mask.size())
4354 if (Mask[0] != 0 && Mask[0] != 1)
4359 for (
unsigned i = 1; i != Mask.size(); ++i)
4360 if (Mask[i] != Mask[i - 1] + 2)
4378 int Size = Mask.size();
4380 assert(
Size == (
int)NumElts &&
"Unexpected mask size");
4386 EvenSrc = StartIndexes[0];
4387 OddSrc = StartIndexes[1];
4390 if (EvenSrc != 0 && OddSrc != 0)
4400 int HalfNumElts = NumElts / 2;
4401 return ((EvenSrc % HalfNumElts) == 0) && ((OddSrc % HalfNumElts) == 0);
4417 int Size = Mask.size();
4429 for (
int i = 0; i !=
Size; ++i) {
4435 int StartIdx = i - (M %
Size);
4443 int CandidateRotation = StartIdx < 0 ? -StartIdx :
Size - StartIdx;
4446 Rotation = CandidateRotation;
4447 else if (Rotation != CandidateRotation)
4452 int MaskSrc = M <
Size ? 0 : 1;
4457 int &TargetSrc = StartIdx < 0 ? HiSrc : LoSrc;
4462 TargetSrc = MaskSrc;
4463 else if (TargetSrc != MaskSrc)
4470 assert(Rotation != 0 &&
"Failed to locate a viable rotation!");
4471 assert((LoSrc >= 0 || HiSrc >= 0) &&
4472 "Failed to find a rotated input vector!");
4487 MVT ContainerVT = VT;
4490 assert(Src.getSimpleValueType().isFixedLengthVector());
4494 MVT SrcContainerVT =
4507 Src = DAG.
getBitcast(WideSrcContainerVT, Src);
4514 unsigned Shift = EvenElts ? 0 : EltBits;
4520 DAG.
getUNDEF(IntContainerVT), TrueMask, VL);
4546 auto findNonEXTRACT_SUBVECTORParent =
4547 [](
SDValue Parent) -> std::pair<SDValue, uint64_t> {
4552 Parent.getOperand(0).getSimpleValueType().isFixedLengthVector()) {
4553 Offset += Parent.getConstantOperandVal(1);
4554 Parent = Parent.getOperand(0);
4556 return std::make_pair(Parent,
Offset);
4559 auto [V1Src, V1IndexOffset] = findNonEXTRACT_SUBVECTORParent(V1);
4560 auto [V2Src, V2IndexOffset] = findNonEXTRACT_SUBVECTORParent(V2);
4569 for (
size_t i = 0; i != NewMask.
size(); ++i) {
4570 if (NewMask[i] == -1)
4573 if (
static_cast<size_t>(NewMask[i]) < NewMask.
size()) {
4574 NewMask[i] = NewMask[i] + V1IndexOffset;
4578 NewMask[i] = NewMask[i] - NewMask.
size() + V2IndexOffset;
4584 if (NewMask[0] <= 0)
4588 for (
unsigned i = 1; i != NewMask.
size(); ++i)
4589 if (NewMask[i - 1] + 1 != NewMask[i])
4593 MVT SrcVT = Src.getSimpleValueType();
4624 int NumSubElts,
Index;
4629 bool OpsSwapped = Mask[
Index] < (int)NumElts;
4630 SDValue InPlace = OpsSwapped ? V2 : V1;
4631 SDValue ToInsert = OpsSwapped ? V1 : V2;
4641 if (NumSubElts +
Index >= (
int)NumElts)
4655 Res =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, InPlace, ToInsert,
4667 bool OpsSwapped =
false;
4668 if (!isa<BuildVectorSDNode>(V1)) {
4669 if (!isa<BuildVectorSDNode>(V2))
4674 SDValue Splat = cast<BuildVectorSDNode>(V1)->getSplatValue();
4682 const unsigned E = Mask.size() - ((
Offset > 0) ?
Offset : 0);
4683 for (
unsigned i = S; i != E; ++i)
4684 if (Mask[i] >= 0 && (
unsigned)Mask[i] !=
Base + i +
Offset)
4690 bool IsVSlidedown = isSlideMask(Mask, OpsSwapped ? 0 : NumElts, 1);
4691 if (!IsVSlidedown && !isSlideMask(Mask, OpsSwapped ? 0 : NumElts, -1))
4694 const int InsertIdx = Mask[IsVSlidedown ? (NumElts - 1) : 0];
4696 if (InsertIdx < 0 || InsertIdx / NumElts != (
unsigned)OpsSwapped)
4701 auto OpCode = IsVSlidedown ?
4706 auto Vec = DAG.
getNode(OpCode,
DL, ContainerVT,
4709 Splat, TrueMask, VL);
4720 MVT VecContainerVT = VecVT;
4737 MVT WideContainerVT = WideVT;
4743 EvenV = DAG.
getBitcast(VecContainerVT, EvenV);
4756 }
else if (Subtarget.hasStdExtZvbb()) {
4761 OffsetVec, Passthru, Mask, VL);
4764 Interleaved, EvenV, Passthru, Mask, VL);
4772 Interleaved, OffsetVec, Passthru, Mask, VL);
4780 OddV, Passthru, Mask, VL);
4786 OddV, AllOnesVec, Passthru, Mask, VL);
4794 Interleaved, OddsMul, Passthru, Mask, VL);
4801 Interleaved = DAG.
getBitcast(ResultContainerVT, Interleaved);
4847 if (ViaEltSize > NumElts)
4856 if (ViaEltSize > NumElts)
4862 if (ViaEltSize > NumElts)
4871 MVT &RotateVT,
unsigned &RotateAmt) {
4877 unsigned NumSubElts;
4879 NumElts, NumSubElts, RotateAmt))
4882 NumElts / NumSubElts);
4944 unsigned VRegsPerSrc = NumElts / ElemsPerVReg;
4947 OutMasks(VRegsPerSrc, {-1, {}});
4952 for (
unsigned DstIdx = 0; DstIdx < Mask.size(); DstIdx++) {
4953 int DstVecIdx = DstIdx / ElemsPerVReg;
4954 int DstSubIdx = DstIdx % ElemsPerVReg;
4955 int SrcIdx = Mask[DstIdx];
4956 if (SrcIdx < 0 || (
unsigned)SrcIdx >= 2 * NumElts)
4958 int SrcVecIdx = SrcIdx / ElemsPerVReg;
4959 int SrcSubIdx = SrcIdx % ElemsPerVReg;
4960 if (OutMasks[DstVecIdx].first == -1)
4961 OutMasks[DstVecIdx].first = SrcVecIdx;
4962 if (OutMasks[DstVecIdx].first != SrcVecIdx)
4968 OutMasks[DstVecIdx].second.resize(ElemsPerVReg, -1);
4969 OutMasks[DstVecIdx].second[DstSubIdx] = SrcSubIdx;
4983 for (
unsigned DstVecIdx = 0 ; DstVecIdx < OutMasks.size(); DstVecIdx++) {
4984 auto &[SrcVecIdx, SrcSubMask] = OutMasks[DstVecIdx];
4985 if (SrcVecIdx == -1)
4987 unsigned ExtractIdx = (SrcVecIdx % VRegsPerSrc) * NumOpElts;
4994 unsigned InsertIdx = DstVecIdx * NumOpElts;
5007 MVT VT =
Op.getSimpleValueType();
5022 V2 = V2.isUndef() ? DAG.
getUNDEF(WidenVT)
5046 V.getOperand(0).getSimpleValueType().getVectorNumElements();
5047 V = V.getOperand(
Offset / OpElements);
5053 auto *Ld = cast<LoadSDNode>(V);
5063 SDValue Ops[] = {Ld->getChain(),
5077 MVT SplatVT = ContainerVT;
5080 if (SVT == MVT::f16 && !Subtarget.hasStdExtZfh()) {
5089 V = DAG.
getLoad(SVT,
DL, Ld->getChain(), NewAddr,
5090 Ld->getPointerInfo().getWithOffset(
Offset),
5091 Ld->getOriginalAlign(),
5095 Ld->getPointerInfo().getWithOffset(
Offset), SVT,
5096 Ld->getOriginalAlign(),
5097 Ld->getMemOperand()->getFlags());
5109 assert(Lane < (
int)NumElts &&
"Unexpected lane!");
5112 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
5134 if (Subtarget.hasStdExtZvkb())
5145 LoV = LoSrc == 0 ? V1 : V2;
5149 HiV = HiSrc == 0 ? V1 : V2;
5155 unsigned InvRotate = NumElts - Rotation;
5165 Res =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, Res, LoV,
5188 int EvenSrc, OddSrc;
5193 int Size = Mask.size();
5195 assert(EvenSrc >= 0 &&
"Undef source?");
5196 EvenV = (EvenSrc /
Size) == 0 ? V1 : V2;
5200 assert(OddSrc >= 0 &&
"Undef source?");
5201 OddV = (OddSrc /
Size) == 0 ? V1 : V2;
5210 assert(!V1.
isUndef() &&
"Unexpected shuffle canonicalization");
5219 any_of(Mask, [&](
const auto &
Idx) {
return Idx > 255; })) {
5248 MVT IndexContainerVT =
5253 for (
int MaskIndex : Mask) {
5254 bool IsLHSIndex = MaskIndex < (int)NumElts && MaskIndex >= 0;
5263 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
5273 for (
int MaskIndex : Mask) {
5274 bool IsLHSOrUndefIndex = MaskIndex < (int)NumElts;
5275 ShuffleMaskLHS.
push_back(IsLHSOrUndefIndex && MaskIndex >= 0
5277 ShuffleMaskRHS.
push_back(IsLHSOrUndefIndex ? -1 : (MaskIndex - NumElts));
5292 for (
int MaskIndex : Mask) {
5293 bool SelectMaskVal = (MaskIndex < (int)NumElts) ^ !SwapOps;
5297 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
5329RISCVTargetLowering::lowerCTLZ_CTTZ_ZERO_UNDEF(
SDValue Op,
5331 MVT VT =
Op.getSimpleValueType();
5335 MVT ContainerVT = VT;
5338 if (
Op->isVPOpcode()) {
5339 Mask =
Op.getOperand(1);
5343 VL =
Op.getOperand(2);
5349 MVT FloatEltVT = (EltSize >= 32) ? MVT::f64 : MVT::f32;
5351 FloatEltVT = MVT::f32;
5358 "Expected legal float type!");
5365 }
else if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF) {
5368 Src = DAG.
getNode(ISD::VP_AND,
DL, VT, Src, Neg, Mask, VL);
5373 if (FloatVT.
bitsGT(VT)) {
5374 if (
Op->isVPOpcode())
5375 FloatVal = DAG.
getNode(ISD::VP_UINT_TO_FP,
DL, FloatVT, Src, Mask, VL);
5384 if (!
Op->isVPOpcode())
5388 MVT ContainerFloatVT =
5391 Src, Mask, RTZRM, VL);
5398 unsigned ShiftAmt = FloatEltVT == MVT::f64 ? 52 : 23;
5402 if (
Op->isVPOpcode()) {
5411 else if (IntVT.
bitsGT(VT))
5416 unsigned ExponentBias = FloatEltVT == MVT::f64 ? 1023 : 127;
5421 if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF)
5422 return DAG.
getNode(ISD::VP_SUB,
DL, VT, Exp,
5427 unsigned Adjust = ExponentBias + (EltSize - 1);
5429 if (
Op->isVPOpcode())
5439 else if (
Op.getOpcode() == ISD::VP_CTLZ)
5440 Res = DAG.
getNode(ISD::VP_UMIN,
DL, VT, Res,
5450 MVT SrcVT =
Source.getSimpleValueType();
5459 SrcVT = ContainerVT;
5472 if (
Op->getOpcode() == ISD::VP_CTTZ_ELTS_ZERO_UNDEF)
5489 auto *
Load = cast<LoadSDNode>(
Op);
5490 assert(Load &&
Load->getMemoryVT().isVector() &&
"Expected vector load");
5493 Load->getMemoryVT(),
5494 *
Load->getMemOperand()))
5498 MVT VT =
Op.getSimpleValueType();
5500 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
5501 "Unexpected unaligned RVV load type");
5505 "Expecting equally-sized RVV vector types to be legal");
5507 Load->getPointerInfo(),
Load->getOriginalAlign(),
5508 Load->getMemOperand()->getFlags());
5518 auto *
Store = cast<StoreSDNode>(
Op);
5519 assert(Store &&
Store->getValue().getValueType().isVector() &&
5520 "Expected vector store");
5523 Store->getMemoryVT(),
5524 *
Store->getMemOperand()))
5531 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
5532 "Unexpected unaligned RVV store type");
5536 "Expecting equally-sized RVV vector types to be legal");
5537 StoredVal = DAG.
getBitcast(NewVT, StoredVal);
5539 Store->getPointerInfo(),
Store->getOriginalAlign(),
5540 Store->getMemOperand()->getFlags());
5545 assert(
Op.getValueType() == MVT::i64 &&
"Unexpected VT");
5547 int64_t Imm = cast<ConstantSDNode>(
Op)->getSExtValue();
5574 unsigned ShiftAmt, AddOpc;
5591 if (Subtarget.hasStdExtZtso()) {
5615 MVT VT =
Op.getSimpleValueType();
5617 unsigned Check =
Op.getConstantOperandVal(1);
5618 unsigned TDCMask = 0;
5646 MVT VT0 =
Op.getOperand(0).getSimpleValueType();
5651 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
5653 VL =
Op.getOperand(3);
5656 VL,
Op->getFlags());
5671 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
5673 MVT MaskContainerVT =
5676 VL =
Op.getOperand(3);
5681 Mask, VL,
Op->getFlags());
5684 DAG.
getUNDEF(ContainerDstVT), TDCMaskV, VL);
5689 DAG.
getUNDEF(ContainerVT), Mask, VL});
5693 TDCMaskV, DAG.
getUNDEF(ContainerDstVT), Mask, VL);
5697 DAG.
getUNDEF(ContainerDstVT), SplatZero, VL);
5701 DAG.
getUNDEF(ContainerVT), Mask, VL});
5717 MVT VT =
Op.getSimpleValueType();
5744 return DAG.
getNode(Opc,
DL, VT, NewX, NewY);
5751 MVT ContainerVT = VT;
5759 if (
Op->isVPOpcode()) {
5760 Mask =
Op.getOperand(2);
5764 VL =
Op.getOperand(3);
5772 {X, X, DAG.getCondCode(ISD::SETOEQ),
5773 DAG.getUNDEF(ContainerVT), Mask, VL});
5781 {Y, Y, DAG.getCondCode(ISD::SETOEQ),
5782 DAG.getUNDEF(ContainerVT), Mask, VL});
5792 DAG.
getUNDEF(ContainerVT), Mask, VL);
5800#define OP_CASE(NODE) \
5802 return RISCVISD::NODE##_VL;
5803#define VP_CASE(NODE) \
5804 case ISD::VP_##NODE: \
5805 return RISCVISD::NODE##_VL;
5807 switch (
Op.getOpcode()) {
5885 case ISD::VP_CTLZ_ZERO_UNDEF:
5888 case ISD::VP_CTTZ_ZERO_UNDEF:
5897 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
5902 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
5907 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
5910 case ISD::VP_SELECT:
5919 case ISD::VP_SIGN_EXTEND:
5921 case ISD::VP_ZERO_EXTEND:
5923 case ISD::VP_FP_TO_SINT:
5925 case ISD::VP_FP_TO_UINT:
5928 case ISD::VP_FMINNUM:
5931 case ISD::VP_FMAXNUM:
5936 case ISD::VP_LLRINT:
5948 "not a RISC-V target specific op");
5954 "adding target specific op should update this function");
5974 "not a RISC-V target specific op");
5980 "adding target specific op should update this function");
5999 if (!
Op.getOperand(j).getValueType().isVector()) {
6000 LoOperands[j] =
Op.getOperand(j);
6001 HiOperands[j] =
Op.getOperand(j);
6004 std::tie(LoOperands[j], HiOperands[j]) =
6009 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
6011 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
6026 std::tie(LoOperands[j], HiOperands[j]) =
6030 if (!
Op.getOperand(j).getValueType().isVector()) {
6031 LoOperands[j] =
Op.getOperand(j);
6032 HiOperands[j] =
Op.getOperand(j);
6035 std::tie(LoOperands[j], HiOperands[j]) =
6040 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
6042 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
6052 auto [EVLLo, EVLHi] =
6053 DAG.
SplitEVL(
Op.getOperand(3),
Op.getOperand(1).getValueType(),
DL);
6057 {Op.getOperand(0), Lo, MaskLo, EVLLo},
Op->getFlags());
6059 {ResLo, Hi, MaskHi, EVLHi},
Op->getFlags());
6077 if (!
Op.getOperand(j).getValueType().isVector()) {
6078 LoOperands[j] =
Op.getOperand(j);
6079 HiOperands[j] =
Op.getOperand(j);
6082 std::tie(LoOperands[j], HiOperands[j]) =
6087 DAG.
getNode(
Op.getOpcode(),
DL, LoVTs, LoOperands,
Op->getFlags());
6090 DAG.
getNode(
Op.getOpcode(),
DL, HiVTs, HiOperands,
Op->getFlags());
6099 switch (
Op.getOpcode()) {
6105 return lowerGlobalAddress(
Op, DAG);
6107 return lowerBlockAddress(
Op, DAG);
6109 return lowerConstantPool(
Op, DAG);
6111 return lowerJumpTable(
Op, DAG);
6113 return lowerGlobalTLSAddress(
Op, DAG);
6117 return lowerSELECT(
Op, DAG);
6119 return lowerBRCOND(
Op, DAG);
6121 return lowerVASTART(
Op, DAG);
6123 return lowerFRAMEADDR(
Op, DAG);
6125 return lowerRETURNADDR(
Op, DAG);
6127 return lowerShiftLeftParts(
Op, DAG);
6129 return lowerShiftRightParts(
Op, DAG,
true);
6131 return lowerShiftRightParts(
Op, DAG,
false);
6134 if (
Op.getValueType().isFixedLengthVector()) {
6135 assert(Subtarget.hasStdExtZvkb());
6136 return lowerToScalableOp(
Op, DAG);
6138 assert(Subtarget.hasVendorXTHeadBb() &&
6139 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
6140 "Unexpected custom legalization");
6142 if (!isa<ConstantSDNode>(
Op.getOperand(1)))
6147 EVT VT =
Op.getValueType();
6151 if (VT == MVT::f16 && Op0VT == MVT::i16 &&
6157 if (VT == MVT::bf16 && Op0VT == MVT::i16 &&
6158 Subtarget.hasStdExtZfbfmin()) {
6163 if (VT == MVT::f32 && Op0VT == MVT::i32 && Subtarget.
is64Bit() &&
6170 if (VT == MVT::f64 && Op0VT == MVT::i64 && XLenVT == MVT::i32) {
6187 "Unexpected types");
6221 return LowerINTRINSIC_WO_CHAIN(
Op, DAG);
6223 return LowerINTRINSIC_W_CHAIN(
Op, DAG);
6225 return LowerINTRINSIC_VOID(
Op, DAG);
6227 return LowerIS_FPCLASS(
Op, DAG);
6229 MVT VT =
Op.getSimpleValueType();
6231 assert(Subtarget.hasStdExtZvbb());
6232 return lowerToScalableOp(
Op, DAG);
6235 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected custom legalization");
6245 if (!
Op.getSimpleValueType().isVector())
6247 return lowerVectorTruncLike(
Op, DAG);
6250 if (
Op.getOperand(0).getValueType().isVector() &&
6251 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
6252 return lowerVectorMaskExt(
Op, DAG, 1);
6255 if (
Op.getOperand(0).getValueType().isVector() &&
6256 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
6257 return lowerVectorMaskExt(
Op, DAG, -1);
6260 return lowerSPLAT_VECTOR_PARTS(
Op, DAG);
6262 return lowerINSERT_VECTOR_ELT(
Op, DAG);
6264 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
6266 MVT VT =
Op.getSimpleValueType();
6274 MVT ContainerVT = VT;
6280 DAG.
getUNDEF(ContainerVT), Scalar, VL);
6287 MVT VT =
Op.getSimpleValueType();
6307 }
else if ((Val % 8) == 0) {
6323 if (
Op.getValueType() == MVT::f16 && Subtarget.
is64Bit() &&
6324 Op.getOperand(1).getValueType() == MVT::i32) {
6336 if (
Op.getValueType() == MVT::nxv32f16 &&
6343 EVT VT =
Op.getValueType();
6346 if (VT == MVT::f32 && Op0VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin())
6348 if (VT == MVT::f64 && Op0VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) {
6354 if (!
Op.getValueType().isVector())
6356 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
6360 EVT VT =
Op.getValueType();
6363 if (VT == MVT::bf16 && Op0VT == MVT::f32 && Subtarget.hasStdExtZfbfmin())
6365 if (VT == MVT::bf16 && Op0VT == MVT::f64 && Subtarget.hasStdExtZfbfmin() &&
6373 if (!
Op.getValueType().isVector())
6375 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
6379 return lowerStrictFPExtendOrRoundLike(
Op, DAG);
6382 if (
Op.getValueType().isVector() &&
6383 Op.getValueType().getScalarType() == MVT::f16 &&
6386 if (
Op.getValueType() == MVT::nxv32f16)
6401 Op1.getValueType().isVector() &&
6402 Op1.getValueType().getScalarType() == MVT::f16 &&
6405 if (Op1.getValueType() == MVT::nxv32f16)
6410 Op1.getValueType().getVectorElementCount());
6413 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), WidenVec);
6423 MVT VT =
Op.getSimpleValueType();
6427 bool IsStrict =
Op->isStrictFPOpcode();
6428 SDValue Src =
Op.getOperand(0 + IsStrict);
6430 MVT SrcVT = Src.getSimpleValueType();
6435 "Unexpected vector element types");
6439 if (EltSize > (2 * SrcEltSize)) {
6451 Op.getOperand(0), Ext);
6455 assert(SrcEltVT == MVT::f16 &&
"Unexpected FP_TO_[US]INT lowering");
6460 auto [FExt, Chain] =
6462 return DAG.
getNode(
Op.getOpcode(),
DL,
Op->getVTList(), Chain, FExt);
6469 if (SrcEltSize > (2 * EltSize)) {
6472 assert(EltVT == MVT::f16 &&
"Unexpected [US]_TO_FP lowering");
6477 Op.getOperand(0), Src);
6492 Op.getOperand(0), Src);
6506 unsigned RVVOpc = 0;
6507 switch (
Op.getOpcode()) {
6539 "Expected same element count");
6546 Op.getOperand(0), Src, Mask, VL);
6550 Src = DAG.
getNode(RVVOpc,
DL, ContainerVT, Src, Mask, VL);
6565 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
6572 MVT VT =
Op.getSimpleValueType();
6594 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
6610 makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg, CallOptions,
DL)
6630 return lowerVECREDUCE(
Op, DAG);
6634 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
6635 return lowerVectorMaskVecReduction(
Op, DAG,
false);
6636 return lowerVECREDUCE(
Op, DAG);
6643 return lowerFPVECREDUCE(
Op, DAG);
6644 case ISD::VP_REDUCE_ADD:
6645 case ISD::VP_REDUCE_UMAX:
6646 case ISD::VP_REDUCE_SMAX:
6647 case ISD::VP_REDUCE_UMIN:
6648 case ISD::VP_REDUCE_SMIN:
6649 case ISD::VP_REDUCE_FADD:
6650 case ISD::VP_REDUCE_SEQ_FADD:
6651 case ISD::VP_REDUCE_FMIN:
6652 case ISD::VP_REDUCE_FMAX:
6653 case ISD::VP_REDUCE_FMINIMUM:
6654 case ISD::VP_REDUCE_FMAXIMUM:
6655 if (
Op.getOperand(1).getValueType() == MVT::nxv32f16 &&
6659 return lowerVPREDUCE(
Op, DAG);
6660 case ISD::VP_REDUCE_AND:
6661 case ISD::VP_REDUCE_OR:
6662 case ISD::VP_REDUCE_XOR:
6663 if (
Op.getOperand(1).getValueType().getVectorElementType() == MVT::i1)
6664 return lowerVectorMaskVecReduction(
Op, DAG,
true);
6665 return lowerVPREDUCE(
Op, DAG);
6666 case ISD::VP_CTTZ_ELTS:
6667 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
6668 return lowerVPCttzElements(
Op, DAG);
6672 DAG.
getUNDEF(ContainerVT), DAG, Subtarget);
6675 return lowerINSERT_SUBVECTOR(
Op, DAG);
6677 return lowerEXTRACT_SUBVECTOR(
Op, DAG);
6679 return lowerVECTOR_DEINTERLEAVE(
Op, DAG);
6681 return lowerVECTOR_INTERLEAVE(
Op, DAG);
6683 return lowerSTEP_VECTOR(
Op, DAG);
6685 return lowerVECTOR_REVERSE(
Op, DAG);
6687 return lowerVECTOR_SPLICE(
Op, DAG);
6691 if ((
Op.getValueType().getScalarType() == MVT::f16 &&
6695 (
Op.getValueType().getScalarType() == MVT::bf16 &&
6697 Subtarget.hasStdExtZfbfmin()))) {
6698 if (
Op.getValueType() == MVT::nxv32f16 ||
6699 Op.getValueType() == MVT::nxv32bf16)
6711 if (
Op.getValueType().getVectorElementType() == MVT::i1)
6712 return lowerVectorMaskSplat(
Op, DAG);
6720 MVT VT =
Op.getSimpleValueType();
6721 MVT ContainerVT = VT;
6739 Op->ops().take_front(HalfNumOps));
6741 Op->ops().drop_front(HalfNumOps));
6745 unsigned NumOpElts =
6746 Op.getOperand(0).getSimpleValueType().getVectorMinNumElements();
6749 SDValue SubVec = OpIdx.value();
6760 if (
auto V = expandUnalignedRVVLoad(
Op, DAG))
6762 if (
Op.getValueType().isFixedLengthVector())
6763 return lowerFixedLengthVectorLoadToRVV(
Op, DAG);
6766 if (
auto V = expandUnalignedRVVStore(
Op, DAG))
6768 if (
Op.getOperand(1).getValueType().isFixedLengthVector())
6769 return lowerFixedLengthVectorStoreToRVV(
Op, DAG);
6773 return lowerMaskedLoad(
Op, DAG);
6776 return lowerMaskedStore(
Op, DAG);
6785 EVT VT =
Op.getValueType();
6796 MVT OpVT =
Op.getOperand(0).getSimpleValueType();
6798 MVT VT =
Op.getSimpleValueType();
6803 "Unexpected CondCode");
6811 if (isa<ConstantSDNode>(
RHS)) {
6812 int64_t Imm = cast<ConstantSDNode>(
RHS)->getSExtValue();
6813 if (Imm != 0 && isInt<12>((
uint64_t)Imm + 1)) {
6832 if (
Op.getOperand(0).getSimpleValueType() == MVT::nxv32f16 &&
6837 return lowerFixedLengthVectorSetccToRVV(
Op, DAG);
6853 return lowerToScalableOp(
Op, DAG);
6857 if (
Op.getSimpleValueType().isFixedLengthVector())
6858 return lowerToScalableOp(
Op, DAG);
6860 assert(
Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.
is64Bit() &&
6861 "Unexpected custom legalisation");
6873 if (
Op.getValueType() == MVT::nxv32f16 &&
6886 return lowerToScalableOp(
Op, DAG);
6889 return lowerToScalableOp(
Op, DAG);
6892 return lowerToScalableOp(
Op, DAG);
6896 EVT VT =
Op->getValueType(0);
6911 return lowerABS(
Op, DAG);
6916 if (Subtarget.hasStdExtZvbb())
6917 return lowerToScalableOp(
Op, DAG);
6919 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
6921 return lowerFixedLengthVectorSelectToRVV(
Op, DAG);
6923 if (
Op.getValueType() == MVT::nxv32f16 &&
6927 return lowerFixedLengthVectorFCOPYSIGNToRVV(
Op, DAG);
6934 if (
Op.getValueType() == MVT::nxv32f16 &&
6938 return lowerToScalableOp(
Op, DAG);
6941 return lowerVectorStrictFSetcc(
Op, DAG);
6951 case ISD::VP_GATHER:
6952 return lowerMaskedGather(
Op, DAG);
6954 case ISD::VP_SCATTER:
6955 return lowerMaskedScatter(
Op, DAG);
6957 return lowerGET_ROUNDING(
Op, DAG);
6959 return lowerSET_ROUNDING(
Op, DAG);
6961 return lowerEH_DWARF_CFA(
Op, DAG);
6962 case ISD::VP_SELECT:
6971 case ISD::VP_UADDSAT:
6972 case ISD::VP_USUBSAT:
6973 case ISD::VP_SADDSAT:
6974 case ISD::VP_SSUBSAT:
6976 case ISD::VP_LLRINT:
6977 return lowerVPOp(
Op, DAG);
6981 return lowerLogicVPOp(
Op, DAG);
6990 case ISD::VP_FMINNUM:
6991 case ISD::VP_FMAXNUM:
6992 case ISD::VP_FCOPYSIGN:
6993 if (
Op.getValueType() == MVT::nxv32f16 &&
7001 return lowerVPOp(
Op, DAG);
7002 case ISD::VP_IS_FPCLASS:
7003 return LowerIS_FPCLASS(
Op, DAG);
7004 case ISD::VP_SIGN_EXTEND:
7005 case ISD::VP_ZERO_EXTEND:
7006 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
7007 return lowerVPExtMaskOp(
Op, DAG);
7008 return lowerVPOp(
Op, DAG);
7009 case ISD::VP_TRUNCATE:
7010 return lowerVectorTruncLike(
Op, DAG);
7011 case ISD::VP_FP_EXTEND:
7012 case ISD::VP_FP_ROUND:
7013 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
7014 case ISD::VP_SINT_TO_FP:
7015 case ISD::VP_UINT_TO_FP:
7016 if (
Op.getValueType().isVector() &&
7017 Op.getValueType().getScalarType() == MVT::f16 &&
7020 if (
Op.getValueType() == MVT::nxv32f16)
7032 case ISD::VP_FP_TO_SINT:
7033 case ISD::VP_FP_TO_UINT:
7035 Op1.getValueType().isVector() &&
7036 Op1.getValueType().getScalarType() == MVT::f16 &&
7039 if (Op1.getValueType() == MVT::nxv32f16)
7044 Op1.getValueType().getVectorElementCount());
7048 {WidenVec, Op.getOperand(1), Op.getOperand(2)});
7050 return lowerVPFPIntConvOp(
Op, DAG);
7052 if (
Op.getOperand(0).getSimpleValueType() == MVT::nxv32f16 &&
7056 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
7057 return lowerVPSetCCMaskOp(
Op, DAG);
7063 case ISD::VP_BITREVERSE:
7065 return lowerVPOp(
Op, DAG);
7067 case ISD::VP_CTLZ_ZERO_UNDEF:
7068 if (Subtarget.hasStdExtZvbb())
7069 return lowerVPOp(
Op, DAG);
7070 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
7072 case ISD::VP_CTTZ_ZERO_UNDEF:
7073 if (Subtarget.hasStdExtZvbb())
7074 return lowerVPOp(
Op, DAG);
7075 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
7077 return lowerVPOp(
Op, DAG);
7078 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
7079 return lowerVPStridedLoad(
Op, DAG);
7080 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
7081 return lowerVPStridedStore(
Op, DAG);
7083 case ISD::VP_FFLOOR:
7085 case ISD::VP_FNEARBYINT:
7086 case ISD::VP_FROUND:
7087 case ISD::VP_FROUNDEVEN:
7088 case ISD::VP_FROUNDTOZERO:
7089 if (
Op.getValueType() == MVT::nxv32f16 &&
7094 case ISD::VP_FMAXIMUM:
7095 case ISD::VP_FMINIMUM:
7096 if (
Op.getValueType() == MVT::nxv32f16 &&
7101 case ISD::EXPERIMENTAL_VP_SPLICE:
7102 return lowerVPSpliceExperimental(
Op, DAG);
7103 case ISD::EXPERIMENTAL_VP_REVERSE:
7104 return lowerVPReverseExperimental(
Op, DAG);
7105 case ISD::EXPERIMENTAL_VP_SPLAT:
7106 return lowerVPSplatExperimental(
Op, DAG);
7109 "llvm.clear_cache only needs custom lower on Linux targets");
7112 return emitFlushICache(DAG,
Op.getOperand(0),
Op.getOperand(1),
7113 Op.getOperand(2), Flags,
DL);
7121 MakeLibCallOptions CallOptions;
7122 std::pair<SDValue, SDValue> CallResult =
7123 makeLibCall(DAG, RTLIB::RISCV_FLUSH_ICACHE, MVT::isVoid,
7124 {Start,
End, Flags}, CallOptions,
DL, InChain);
7127 return CallResult.second;
7144 N->getOffset(), Flags);
7152template <
class NodeTy>
7154 bool IsLocal,
bool IsExternWeak)
const {
7164 if (IsLocal && !Subtarget.allowTaggedGlobals())
7226 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
7235 return getAddr(
N, DAG);
7242 return getAddr(
N, DAG);
7249 return getAddr(
N, DAG);
7254 bool UseGOT)
const {
7318 Args.push_back(Entry);
7351 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
7365 Addr = getStaticTLSAddr(
N, DAG,
false);
7368 Addr = getStaticTLSAddr(
N, DAG,
true);
7373 : getDynamicTLSAddr(
N, DAG);
7390 if (
LHS == LHS2 &&
RHS == RHS2) {
7395 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
7403 return std::nullopt;
7411 MVT VT =
N->getSimpleValueType(0);
7441 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV)) {
7444 if (~TrueVal == FalseVal) {
7484 if (Subtarget.hasShortForwardBranchOpt())
7487 unsigned SelOpNo = 0;
7497 unsigned ConstSelOpNo = 1;
7498 unsigned OtherSelOpNo = 2;
7499 if (!dyn_cast<ConstantSDNode>(Sel->
getOperand(ConstSelOpNo))) {
7504 ConstantSDNode *ConstSelOpNode = dyn_cast<ConstantSDNode>(ConstSelOp);
7505 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
7509 ConstantSDNode *ConstBinOpNode = dyn_cast<ConstantSDNode>(ConstBinOp);
7510 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
7516 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
7518 std::swap(NewConstOps[0], NewConstOps[1]);
7530 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
7532 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
7535 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
7536 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
7545 MVT VT =
Op.getSimpleValueType();
7559 if ((Subtarget.hasStdExtZicond() || Subtarget.hasVendorXVentanaCondOps()) &&
7587 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV)) {
7591 TrueVal, Subtarget.
getXLen(), Subtarget,
true);
7593 FalseVal, Subtarget.
getXLen(), Subtarget,
true);
7594 bool IsCZERO_NEZ = TrueValCost <= FalseValCost;
7596 IsCZERO_NEZ ? FalseVal - TrueVal : TrueVal - FalseVal,
DL, VT);
7601 DL, VT, LHSVal, CondV);
7617 if (
Op.hasOneUse()) {
7618 unsigned UseOpc =
Op->use_begin()->getOpcode();
7627 return lowerSELECT(NewSel, DAG);
7656 SDValue Ops[] = {CondV,
Zero, SetNE, TrueV, FalseV};
7677 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV) &&
7681 if (TrueVal - 1 == FalseVal)
7683 if (TrueVal + 1 == FalseVal)
7690 RHS == TrueV && LHS == FalseV) {
7707 if (isa<ConstantSDNode>(TrueV) && !isa<ConstantSDNode>(FalseV)) {
7733 LHS, RHS, TargetCC,
Op.getOperand(2));
7751 const Value *SV = cast<SrcValueSDNode>(
Op.getOperand(2))->getValue();
7763 int XLenInBytes = Subtarget.
getXLen() / 8;
7765 EVT VT =
Op.getValueType();
7768 unsigned Depth =
Op.getConstantOperandVal(0);
7770 int Offset = -(XLenInBytes * 2);
7787 int XLenInBytes = Subtarget.
getXLen() / 8;
7792 EVT VT =
Op.getValueType();
7794 unsigned Depth =
Op.getConstantOperandVal(0);
7796 int Off = -XLenInBytes;
7797 SDValue FrameAddr = lowerFRAMEADDR(
Op, DAG);
7816 EVT VT =
Lo.getValueType();
7855 EVT VT =
Lo.getValueType();
7906 MVT VT =
Op.getSimpleValueType();
7932 MVT VecVT =
Op.getSimpleValueType();
7934 "Unexpected SPLAT_VECTOR_PARTS lowering");
7940 MVT ContainerVT = VecVT;
7960 int64_t ExtTrueVal)
const {
7962 MVT VecVT =
Op.getSimpleValueType();
7965 assert(Src.getValueType().isVector() &&
7966 Src.getValueType().getVectorElementType() == MVT::i1);
7987 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
7989 DAG.
getUNDEF(ContainerVT), SplatTrueVal, VL);
7992 SplatZero, DAG.
getUNDEF(ContainerVT), VL);
7997SDValue RISCVTargetLowering::lowerFixedLengthVectorExtendToRVV(
7999 MVT ExtVT =
Op.getSimpleValueType();
8003 MVT VT =
Op.getOperand(0).getSimpleValueType();
8029 bool IsVPTrunc =
Op.getOpcode() == ISD::VP_TRUNCATE;
8031 EVT MaskVT =
Op.getValueType();
8034 "Unexpected type for vector mask lowering");
8036 MVT VecVT = Src.getSimpleValueType();
8040 VL =
Op.getOperand(2);
8043 MVT ContainerVT = VecVT;
8049 MVT MaskContainerVT =
8056 std::tie(Mask, VL) =
8064 DAG.
getUNDEF(ContainerVT), SplatOne, VL);
8066 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
8070 DAG.
getUNDEF(ContainerVT), Mask, VL);
8073 DAG.
getUNDEF(MaskContainerVT), Mask, VL});
8081 unsigned Opc =
Op.getOpcode();
8082 bool IsVPTrunc = Opc == ISD::VP_TRUNCATE;
8085 MVT VT =
Op.getSimpleValueType();
8087 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
8091 return lowerVectorMaskTruncLike(
Op, DAG);
8099 MVT SrcVT = Src.getSimpleValueType();
8104 "Unexpected vector truncate lowering");
8106 MVT ContainerVT = SrcVT;
8110 VL =
Op.getOperand(2);
8123 std::tie(Mask, VL) =
8139 }
while (SrcEltVT != DstEltVT);
8148RISCVTargetLowering::lowerStrictFPExtendOrRoundLike(
SDValue Op,
8153 MVT VT =
Op.getSimpleValueType();
8154 MVT SrcVT = Src.getSimpleValueType();
8155 MVT ContainerVT = VT;
8178 Chain, Src, Mask, VL);
8179 Chain = Src.getValue(1);
8186 Chain, Src, Mask, VL);
8197RISCVTargetLowering::lowerVectorFPExtendOrRoundLike(
SDValue Op,
8200 Op.getOpcode() == ISD::VP_FP_ROUND ||
Op.getOpcode() == ISD::VP_FP_EXTEND;
8207 MVT VT =
Op.getSimpleValueType();
8209 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
8212 MVT SrcVT = Src.getSimpleValueType();
8214 bool IsDirectExtend =
8222 bool IsDirectConv = IsDirectExtend || IsDirectTrunc;
8225 MVT ContainerVT = VT;
8229 VL =
Op.getOperand(2);
8243 std::tie(Mask, VL) =
8249 Src = DAG.
getNode(ConvOpc,
DL, ContainerVT, Src, Mask, VL);
8255 unsigned InterConvOpc =
8260 DAG.
getNode(InterConvOpc,
DL, InterVT, Src, Mask, VL);
8262 DAG.
getNode(ConvOpc,
DL, ContainerVT, IntermediateConv, Mask, VL);
8273static std::optional<MVT>
8279 const unsigned MinVLMAX = VectorBitsMin / EltSize;
8281 if (MaxIdx < MinVLMAX)
8283 else if (MaxIdx < MinVLMAX * 2)
8285 else if (MaxIdx < MinVLMAX * 4)
8290 return std::nullopt;
8303 MVT VecVT =
Op.getSimpleValueType();
8317 MVT ContainerVT = VecVT;
8326 MVT OrigContainerVT = ContainerVT;
8329 if (
auto *IdxC = dyn_cast<ConstantSDNode>(
Idx)) {
8330 const unsigned OrigIdx = IdxC->getZExtValue();
8333 DL, DAG, Subtarget)) {
8334 ContainerVT = *ShrunkVT;
8343 VLEN && ContainerVT.
bitsGT(M1VT)) {
8346 unsigned RemIdx = OrigIdx % ElemsPerVReg;
8347 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
8348 unsigned ExtractIdx =
8367 if (!IsLegalInsert && isa<ConstantSDNode>(Val)) {
8368 const auto *CVal = cast<ConstantSDNode>(Val);
8369 if (isInt<32>(CVal->getSExtValue())) {
8370 IsLegalInsert =
true;
8379 if (IsLegalInsert) {
8385 Vec = DAG.
getNode(Opc,
DL, ContainerVT, Vec, Val, VL);
8401 std::tie(ValLo, ValHi) = DAG.
SplitScalar(Val,
DL, MVT::i32, MVT::i32);
8402 MVT I32ContainerVT =
8413 Vec, Vec, ValLo, I32Mask, InsertI64VL);
8418 Tail, ValInVec, ValHi, I32Mask, InsertI64VL);
8420 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
8425 ValInVec, AlignedIdx);
8435 DAG.
getUNDEF(I32ContainerVT), ValLo,
8436 I32Mask, InsertI64VL);
8438 DAG.
getUNDEF(I32ContainerVT), ValInVec, ValHi,
8439 I32Mask, InsertI64VL);
8441 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
8454 Idx, Mask, InsertVL, Policy);
8458 Slideup, AlignedIdx);
8473 EVT EltVT =
Op.getValueType();
8480 MVT ContainerVT = VecVT;
8496 unsigned WidenVecLen;
8499 unsigned MaxEEW = Subtarget.
getELen();
8504 "the number of elements should be power of 2");
8508 ExtractBitIdx =
Idx;
8510 WideEltVT = LargestEltVT;
8513 ExtractElementIdx = DAG.
getNode(
8524 Vec, ExtractElementIdx);
8540 MVT ContainerVT = VecVT;
8551 if (
auto *IdxC = dyn_cast<ConstantSDNode>(
Idx);
8552 IdxC && VLen && VecVT.
getSizeInBits().getKnownMinValue() > *VLen) {
8554 unsigned OrigIdx = IdxC->getZExtValue();
8557 unsigned RemIdx = OrigIdx % ElemsPerVReg;
8558 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
8559 unsigned ExtractIdx =
8569 std::optional<uint64_t> MaxIdx;
8572 if (
auto *IdxC = dyn_cast<ConstantSDNode>(
Idx))
8573 MaxIdx = IdxC->getZExtValue();
8575 if (
auto SmallerVT =
8577 ContainerVT = *SmallerVT;
8624 "Unexpected opcode");
8631 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
8636 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
8637 if (!
II || !
II->hasScalarOperand())
8640 unsigned SplatOp =
II->ScalarOperand + 1 + HasChain;
8653 if (OpVT.
bitsLT(XLenVT)) {
8660 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
8670 assert(
II->ScalarOperand > 0 &&
"Unexpected splat operand!");
8671 MVT VT =
Op.getOperand(SplatOp - 1).getSimpleValueType();
8674 assert(XLenVT == MVT::i32 && OpVT == MVT::i64 &&
8685 case Intrinsic::riscv_vslide1up:
8686 case Intrinsic::riscv_vslide1down:
8687 case Intrinsic::riscv_vslide1up_mask:
8688 case Intrinsic::riscv_vslide1down_mask: {
8691 bool IsMasked = NumOps == 7;
8697 std::tie(ScalarLo, ScalarHi) =
8705 if (isa<ConstantSDNode>(AVL)) {
8706 const auto [MinVLMAX, MaxVLMAX] =
8710 if (AVLInt <= MinVLMAX) {
8712 }
else if (AVLInt >= 2 * MaxVLMAX) {
8746 if (IntNo == Intrinsic::riscv_vslide1up ||
8747 IntNo == Intrinsic::riscv_vslide1up_mask) {
8749 ScalarHi, I32Mask, I32VL);
8751 ScalarLo, I32Mask, I32VL);
8754 ScalarLo, I32Mask, I32VL);
8756 ScalarHi, I32Mask, I32VL);
8805 const unsigned ElementWidth = 8;
8810 [[maybe_unused]]
unsigned MinVF =
8813 [[maybe_unused]]
unsigned VF =
N->getConstantOperandVal(2);
8817 bool Fractional = VF < LMul1VF;
8818 unsigned LMulVal = Fractional ? LMul1VF / VF : VF / LMul1VF;
8839 MVT ContainerVT = OpVT;
8866 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
8870 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
8871 if (!
II || !
II->hasScalarOperand())
8874 unsigned SplatOp =
II->ScalarOperand + 1;
8887 if (OpVT.
bitsLT(XLenVT)) {
8890 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
8903 EVT ValType = V.getValueType();
8904 if (ValType.isVector() && ValType.isFloatingPoint()) {
8907 ValType.getVectorElementCount());
8910 if (ValType.isFixedLengthVector()) {
8912 DAG, V.getSimpleValueType(), Subtarget);
8928 unsigned IntNo =
Op.getConstantOperandVal(0);
8935 case Intrinsic::thread_pointer: {
8939 case Intrinsic::riscv_orc_b:
8940 case Intrinsic::riscv_brev8:
8941 case Intrinsic::riscv_sha256sig0:
8942 case Intrinsic::riscv_sha256sig1:
8943 case Intrinsic::riscv_sha256sum0:
8944 case Intrinsic::riscv_sha256sum1:
8945 case Intrinsic::riscv_sm3p0:
8946 case Intrinsic::riscv_sm3p1: {
8959 return DAG.
getNode(Opc,
DL, XLenVT,
Op.getOperand(1));
8961 case Intrinsic::riscv_sm4ks:
8962 case Intrinsic::riscv_sm4ed: {
8966 return DAG.
getNode(Opc,
DL, XLenVT,
Op.getOperand(1),
Op.getOperand(2),
8969 case Intrinsic::riscv_zip:
8970 case Intrinsic::riscv_unzip: {
8973 return DAG.
getNode(Opc,
DL, XLenVT,
Op.getOperand(1));
8975 case Intrinsic::riscv_mopr:
8979 case Intrinsic::riscv_moprr: {
8981 Op.getOperand(2),
Op.getOperand(3));
8983 case Intrinsic::riscv_clmul:
8986 case Intrinsic::riscv_clmulh:
8987 case Intrinsic::riscv_clmulr: {
8990 return DAG.
getNode(Opc,
DL, XLenVT,
Op.getOperand(1),
Op.getOperand(2));
8992 case Intrinsic::experimental_get_vector_length:
8994 case Intrinsic::experimental_cttz_elts:
8996 case Intrinsic::riscv_vmv_x_s: {
9000 case Intrinsic::riscv_vfmv_f_s:
9003 case Intrinsic::riscv_vmv_v_x:
9005 Op.getOperand(3),
Op.getSimpleValueType(),
DL, DAG,
9007 case Intrinsic::riscv_vfmv_v_f:
9009 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
9010 case Intrinsic::riscv_vmv_s_x: {
9013 if (
Scalar.getValueType().bitsLE(XLenVT)) {
9016 Op.getOperand(1), Scalar,
Op.getOperand(3));
9019 assert(
Scalar.getValueType() == MVT::i64 &&
"Unexpected scalar VT!");
9036 MVT VT =
Op.getSimpleValueType();
9041 if (
Op.getOperand(1).isUndef())
9057 case Intrinsic::riscv_vfmv_s_f:
9059 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
9061 case Intrinsic::riscv_vaesdf_vv:
9062 case Intrinsic::riscv_vaesdf_vs:
9063 case Intrinsic::riscv_vaesdm_vv:
9064 case Intrinsic::riscv_vaesdm_vs:
9065 case Intrinsic::riscv_vaesef_vv:
9066 case Intrinsic::riscv_vaesef_vs:
9067 case Intrinsic::riscv_vaesem_vv:
9068 case Intrinsic::riscv_vaesem_vs:
9069 case Intrinsic::riscv_vaeskf1:
9070 case Intrinsic::riscv_vaeskf2:
9071 case Intrinsic::riscv_vaesz_vs:
9072 case Intrinsic::riscv_vsm4k:
9073 case Intrinsic::riscv_vsm4r_vv:
9074 case Intrinsic::riscv_vsm4r_vs: {
9075 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
9076 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
9077 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
9082 case Intrinsic::riscv_vsm3c:
9083 case Intrinsic::riscv_vsm3me: {
9084 if (!
isValidEGW(8,
Op.getSimpleValueType(), Subtarget) ||
9085 !
isValidEGW(8,
Op->getOperand(1).getSimpleValueType(), Subtarget))
9090 case Intrinsic::riscv_vsha2ch:
9091 case Intrinsic::riscv_vsha2cl:
9092 case Intrinsic::riscv_vsha2ms: {
9093 if (
Op->getSimpleValueType(0).getScalarSizeInBits() == 64 &&
9094 !Subtarget.hasStdExtZvknhb())
9096 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
9097 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
9098 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
9102 case Intrinsic::riscv_sf_vc_v_x:
9103 case Intrinsic::riscv_sf_vc_v_i:
9104 case Intrinsic::riscv_sf_vc_v_xv:
9105 case Intrinsic::riscv_sf_vc_v_iv:
9106 case Intrinsic::riscv_sf_vc_v_vv:
9107 case Intrinsic::riscv_sf_vc_v_fv:
9108 case Intrinsic::riscv_sf_vc_v_xvv:
9109 case Intrinsic::riscv_sf_vc_v_ivv:
9110 case Intrinsic::riscv_sf_vc_v_vvv:
9111 case Intrinsic::riscv_sf_vc_v_fvv:
9112 case Intrinsic::riscv_sf_vc_v_xvw:
9113 case Intrinsic::riscv_sf_vc_v_ivw:
9114 case Intrinsic::riscv_sf_vc_v_vvw:
9115 case Intrinsic::riscv_sf_vc_v_fvw: {
9116 MVT VT =
Op.getSimpleValueType();
9153 MVT VT =
Op.getSimpleValueType();
9157 if (VT.isFloatingPoint()) {
9162 if (VT.isFixedLengthVector())
9172 if (VT.isFixedLengthVector())
9174 if (VT.isFloatingPoint())
9193 unsigned IntNo =
Op.getConstantOperandVal(1);
9197 case Intrinsic::riscv_seg2_load:
9198 case Intrinsic::riscv_seg3_load:
9199 case Intrinsic::riscv_seg4_load:
9200 case Intrinsic::riscv_seg5_load:
9201 case Intrinsic::riscv_seg6_load:
9202 case Intrinsic::riscv_seg7_load:
9203 case Intrinsic::riscv_seg8_load: {
9206 Intrinsic::riscv_vlseg2, Intrinsic::riscv_vlseg3,
9207 Intrinsic::riscv_vlseg4, Intrinsic::riscv_vlseg5,
9208 Intrinsic::riscv_vlseg6, Intrinsic::riscv_vlseg7,
9209 Intrinsic::riscv_vlseg8};
9210 unsigned NF =
Op->getNumValues() - 1;
9211 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
9213 MVT VT =
Op->getSimpleValueType(0);
9218 auto *
Load = cast<MemIntrinsicSDNode>(
Op);
9220 ContainerVTs.push_back(MVT::Other);
9228 Load->getMemoryVT(),
Load->getMemOperand());
9230 for (
unsigned int RetIdx = 0; RetIdx < NF; RetIdx++)
9236 case Intrinsic::riscv_sf_vc_v_x_se:
9238 case Intrinsic::riscv_sf_vc_v_i_se:
9240 case Intrinsic::riscv_sf_vc_v_xv_se:
9242 case Intrinsic::riscv_sf_vc_v_iv_se:
9244 case Intrinsic::riscv_sf_vc_v_vv_se:
9246 case Intrinsic::riscv_sf_vc_v_fv_se:
9248 case Intrinsic::riscv_sf_vc_v_xvv_se:
9250 case Intrinsic::riscv_sf_vc_v_ivv_se:
9252 case Intrinsic::riscv_sf_vc_v_vvv_se:
9254 case Intrinsic::riscv_sf_vc_v_fvv_se:
9256 case Intrinsic::riscv_sf_vc_v_xvw_se:
9258 case Intrinsic::riscv_sf_vc_v_ivw_se:
9260 case Intrinsic::riscv_sf_vc_v_vvw_se:
9262 case Intrinsic::riscv_sf_vc_v_fvw_se:
9271 unsigned IntNo =
Op.getConstantOperandVal(1);
9275 case Intrinsic::riscv_seg2_store:
9276 case Intrinsic::riscv_seg3_store:
9277 case Intrinsic::riscv_seg4_store:
9278 case Intrinsic::riscv_seg5_store:
9279 case Intrinsic::riscv_seg6_store:
9280 case Intrinsic::riscv_seg7_store:
9281 case Intrinsic::riscv_seg8_store: {
9284 Intrinsic::riscv_vsseg2, Intrinsic::riscv_vsseg3,
9285 Intrinsic::riscv_vsseg4, Intrinsic::riscv_vsseg5,
9286 Intrinsic::riscv_vsseg6, Intrinsic::riscv_vsseg7,
9287 Intrinsic::riscv_vsseg8};
9290 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
9292 MVT VT =
Op->getOperand(2).getSimpleValueType();
9299 auto *FixedIntrinsic = cast<MemIntrinsicSDNode>(
Op);
9301 for (
unsigned i = 0; i < NF; i++)
9303 ContainerVT, FixedIntrinsic->getOperand(2 + i), DAG, Subtarget));
9308 FixedIntrinsic->getMemoryVT(), FixedIntrinsic->getMemOperand());
9310 case Intrinsic::riscv_sf_vc_xv_se:
9312 case Intrinsic::riscv_sf_vc_iv_se:
9314 case Intrinsic::riscv_sf_vc_vv_se:
9316 case Intrinsic::riscv_sf_vc_fv_se:
9318 case Intrinsic::riscv_sf_vc_xvv_se:
9320 case Intrinsic::riscv_sf_vc_ivv_se:
9322 case Intrinsic::riscv_sf_vc_vvv_se:
9324 case Intrinsic::riscv_sf_vc_fvv_se:
9326 case Intrinsic::riscv_sf_vc_xvw_se:
9328 case Intrinsic::riscv_sf_vc_ivw_se:
9330 case Intrinsic::riscv_sf_vc_vvw_se:
9332 case Intrinsic::riscv_sf_vc_fvw_se:
9340 switch (ISDOpcode) {
9343 case ISD::VP_REDUCE_ADD:
9346 case ISD::VP_REDUCE_UMAX:
9349 case ISD::VP_REDUCE_SMAX:
9352 case ISD::VP_REDUCE_UMIN:
9355 case ISD::VP_REDUCE_SMIN:
9358 case ISD::VP_REDUCE_AND:
9361 case ISD::VP_REDUCE_OR:
9364 case ISD::VP_REDUCE_XOR:
9367 case ISD::VP_REDUCE_FADD:
9369 case ISD::VP_REDUCE_SEQ_FADD:
9371 case ISD::VP_REDUCE_FMAX:
9372 case ISD::VP_REDUCE_FMAXIMUM:
9374 case ISD::VP_REDUCE_FMIN:
9375 case ISD::VP_REDUCE_FMINIMUM:
9385 SDValue Vec =
Op.getOperand(IsVP ? 1 : 0);
9390 Op.getOpcode() == ISD::VP_REDUCE_AND ||
9391 Op.getOpcode() == ISD::VP_REDUCE_OR ||
9392 Op.getOpcode() == ISD::VP_REDUCE_XOR) &&
9393 "Unexpected reduction lowering");
9397 MVT ContainerVT = VecVT;
9406 VL =
Op.getOperand(3);
9408 std::tie(Mask, VL) =
9413 switch (
Op.getOpcode()) {
9417 case ISD::VP_REDUCE_AND: {
9426 case ISD::VP_REDUCE_OR:
9432 case ISD::VP_REDUCE_XOR: {
9456 return DAG.
getNode(BaseOpc,
DL,
Op.getValueType(), SetCC,
Op.getOperand(0));
9460 auto *RegisterAVL = dyn_cast<RegisterSDNode>(AVL);
9461 auto *ImmAVL = dyn_cast<ConstantSDNode>(AVL);
9462 return (RegisterAVL && RegisterAVL->getReg() == RISCV::X0) ||
9463 (ImmAVL && ImmAVL->getZExtValue() >= 1);
9479 auto InnerVT = VecVT.
bitsLE(M1VT) ? VecVT : M1VT;
9483 auto InnerVL = NonZeroAVL ? VL : DAG.
getConstant(1,
DL, XLenVT);
9486 if (M1VT != InnerVT)
9492 SDValue Ops[] = {PassThru, Vec, InitialValue, Mask, VL, Policy};
9511 VecEVT =
Lo.getValueType();
9524 MVT ContainerVT = VecVT;
9544 Mask, VL,
DL, DAG, Subtarget);
9550static std::tuple<unsigned, SDValue, SDValue>
9554 auto Flags =
Op->getFlags();
9555 unsigned Opcode =
Op.getOpcode();
9579 return std::make_tuple(RVVOpc,
Op.getOperand(0), Front);
9587 MVT VecEltVT =
Op.getSimpleValueType();
9591 std::tie(RVVOpcode, VectorVal, ScalarVal) =
9595 MVT ContainerVT = VecVT;
9601 MVT ResVT =
Op.getSimpleValueType();
9604 VL,
DL, DAG, Subtarget);
9609 if (
Op->getFlags().hasNoNaNs())
9615 {VectorVal, VectorVal, DAG.getCondCode(ISD::SETNE),
9616 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
9622 DL, ResVT, NoNaNs, Res,
9629 unsigned Opc =
Op.getOpcode();
9652 Vec, Mask, VL,
DL, DAG, Subtarget);
9653 if ((Opc != ISD::VP_REDUCE_FMINIMUM && Opc != ISD::VP_REDUCE_FMAXIMUM) ||
9654 Op->getFlags().hasNoNaNs())
9671 DL, ResVT, NoNaNs, Res,
9684 unsigned OrigIdx =
Op.getConstantOperandVal(2);
9693 (OrigIdx != 0 || !Vec.
isUndef())) {
9696 assert(OrigIdx % 8 == 0 &&
"Invalid index");
9699 "Unexpected mask vector lowering");
9733 MVT ContainerVT = VecVT;
9769 SubVec =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, Vec, SubVec,
9770 SlideupAmt, Mask, VL, Policy);
9778 MVT ContainerVecVT = VecVT;
9784 MVT ContainerSubVecVT = SubVecVT;
9800 ContainerVecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
9801 SubRegIdx = Decompose.first;
9803 (OrigIdx % Vscale));
9807 ContainerVecVT, ContainerSubVecVT, OrigIdx,
TRI);
9808 SubRegIdx = Decompose.first;
9815 bool ExactlyVecRegSized =
9817 .isKnownMultipleOf(Subtarget.
expandVScale(VecRegSize));
9832 if (RemIdx.
isZero() && (ExactlyVecRegSized || Vec.
isUndef())) {
9836 if (SubRegIdx == RISCV::NoSubRegister) {
9855 MVT InterSubVT = ContainerVecVT;
9894 SubVec =
getVSlideup(DAG, Subtarget,
DL, InterSubVT, AlignedExtract, SubVec,
9895 SlideupAmt, Mask, VL, Policy);
9900 if (ContainerVecVT.
bitsGT(InterSubVT))
9909 return DAG.
getBitcast(
Op.getSimpleValueType(), SubVec);
9915 MVT SubVecVT =
Op.getSimpleValueType();
9920 unsigned OrigIdx =
Op.getConstantOperandVal(1);
9931 assert(OrigIdx % 8 == 0 &&
"Invalid index");
9934 "Unexpected mask vector lowering");
9973 MVT ContainerVT = VecVT;
9983 ContainerVT = *ShrunkVT;
9996 DAG.
getUNDEF(ContainerVT), Vec, SlidedownAmt, Mask, VL);
10008 MVT ContainerSubVecVT = SubVecVT;
10012 unsigned SubRegIdx;
10022 VecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
10023 SubRegIdx = Decompose.first;
10025 (OrigIdx % Vscale));
10029 VecVT, ContainerSubVecVT, OrigIdx,
TRI);
10030 SubRegIdx = Decompose.first;
10053 MVT InterSubVT = VecVT;
10057 assert(SubRegIdx != RISCV::NoSubRegister);
10070 Vec, SlidedownAmt, Mask, VL);
10079 return DAG.
getBitcast(
Op.getSimpleValueType(), Slidedown);
10086 MVT VT =
N.getSimpleValueType();
10090 assert(
Op.getSimpleValueType() == VT &&
10091 "Operands and result must be same type");
10095 unsigned NumVals =
N->getNumValues();
10098 NumVals,
N.getValueType().changeVectorElementType(MVT::i8)));
10101 for (
unsigned I = 0;
I < NumVals;
I++) {
10107 if (TruncVals.
size() > 1)
10109 return TruncVals.
front();
10115 MVT VecVT =
Op.getSimpleValueType();
10118 "vector_interleave on non-scalable vector!");
10129 EVT SplitVT = Op0Lo.getValueType();
10132 DAG.
getVTList(SplitVT, SplitVT), Op0Lo, Op0Hi);
10134 DAG.
getVTList(SplitVT, SplitVT), Op1Lo, Op1Hi);
10148 Op.getOperand(0),
Op.getOperand(1));
10175 Concat, EvenIdx, Passthru, Mask, VL);
10177 Concat, OddIdx, Passthru, Mask, VL);
10191 MVT VecVT =
Op.getSimpleValueType();
10194 "vector_interleave on non-scalable vector!");
10207 EVT SplitVT = Op0Lo.getValueType();
10210 DAG.
getVTList(SplitVT, SplitVT), Op0Lo, Op1Lo);
10212 DAG.
getVTList(SplitVT, SplitVT), Op0Hi, Op1Hi);
10234 Op.getOperand(0),
Op.getOperand(1));
10282 MVT VT =
Op.getSimpleValueType();
10287 uint64_t StepValImm =
Op.getConstantOperandVal(0);
10288 if (StepValImm != 1) {
10297 VL, VT,
DL, DAG, Subtarget);
10312 MVT VecVT =
Op.getSimpleValueType();
10320 MVT ContainerVT = VecVT;
10330 unsigned MaxVLMAX =
10340 if (MaxVLMAX > 256 && EltSize == 8) {
10369 assert(isUInt<16>(MaxVLMAX - 1));
10398 DAG.
getUNDEF(ContainerVT), Mask, VL);
10410 MVT VecVT =
Op.getSimpleValueType();
10414 int64_t ImmValue = cast<ConstantSDNode>(
Op.getOperand(2))->getSExtValue();
10415 SDValue DownOffset, UpOffset;
10416 if (ImmValue >= 0) {
10432 DownOffset, TrueMask, UpOffset);
10433 return getVSlideup(DAG, Subtarget,
DL, VecVT, SlideDown, V2, UpOffset,
10439RISCVTargetLowering::lowerFixedLengthVectorLoadToRVV(
SDValue Op,
10442 auto *
Load = cast<LoadSDNode>(
Op);
10445 Load->getMemoryVT(),
10446 *
Load->getMemOperand()) &&
10447 "Expecting a correctly-aligned load");
10449 MVT VT =
Op.getSimpleValueType();
10455 const auto [MinVLMAX, MaxVLMAX] =
10458 getLMUL1VT(ContainerVT).bitsLE(ContainerVT)) {
10472 IsMaskOp ? Intrinsic::riscv_vlm : Intrinsic::riscv_vle,
DL, XLenVT);
10481 Load->getMemoryVT(),
Load->getMemOperand());
10488RISCVTargetLowering::lowerFixedLengthVectorStoreToRVV(
SDValue Op,
10491 auto *
Store = cast<StoreSDNode>(
Op);
10494 Store->getMemoryVT(),
10495 *
Store->getMemOperand()) &&
10496 "Expecting a correctly-aligned store");
10517 const auto [MinVLMAX, MaxVLMAX] =
10520 getLMUL1VT(ContainerVT).bitsLE(ContainerVT)) {
10531 IsMaskOp ? Intrinsic::riscv_vsm : Intrinsic::riscv_vse,
DL, XLenVT);
10534 {Store->getChain(), IntID, NewValue, Store->getBasePtr(), VL},
10535 Store->getMemoryVT(),
Store->getMemOperand());
10541 MVT VT =
Op.getSimpleValueType();
10543 const auto *MemSD = cast<MemSDNode>(
Op);
10544 EVT MemVT = MemSD->getMemoryVT();
10546 SDValue Chain = MemSD->getChain();
10550 if (
const auto *VPLoad = dyn_cast<VPLoadSDNode>(
Op)) {
10551 Mask = VPLoad->getMask();
10553 VL = VPLoad->getVectorLength();
10555 const auto *MLoad = cast<MaskedLoadSDNode>(
Op);
10556 Mask = MLoad->getMask();
10557 PassThru = MLoad->getPassThru();
10564 MVT ContainerVT = VT;
10578 IsUnmasked ? Intrinsic::riscv_vle : Intrinsic::riscv_vle_mask;
10595 Chain =
Result.getValue(1);
10607 const auto *MemSD = cast<MemSDNode>(
Op);
10608 EVT MemVT = MemSD->getMemoryVT();
10610 SDValue Chain = MemSD->getChain();
10614 bool IsCompressingStore =
false;
10615 if (
const auto *VPStore = dyn_cast<VPStoreSDNode>(
Op)) {
10616 Val = VPStore->getValue();
10617 Mask = VPStore->getMask();
10618 VL = VPStore->getVectorLength();
10620 const auto *MStore = cast<MaskedStoreSDNode>(
Op);
10621 Val = MStore->getValue();
10622 Mask = MStore->getMask();
10623 IsCompressingStore = MStore->isCompressingStore();
10632 MVT ContainerVT = VT;
10637 if (!IsUnmasked || IsCompressingStore) {
10646 if (IsCompressingStore) {
10649 DAG.
getUNDEF(ContainerVT), Val, Mask, VL);
10656 IsUnmasked ? Intrinsic::riscv_vse : Intrinsic::riscv_vse_mask;
10665 DAG.
getVTList(MVT::Other), Ops, MemVT, MMO);
10669RISCVTargetLowering::lowerFixedLengthVectorSetccToRVV(
SDValue Op,
10671 MVT InVT =
Op.getOperand(0).getSimpleValueType();
10674 MVT VT =
Op.getSimpleValueType();
10688 {Op1, Op2,
Op.getOperand(2), DAG.
getUNDEF(MaskVT), Mask, VL});
10695 unsigned Opc =
Op.getOpcode();
10702 MVT VT =
Op.getSimpleValueType();
10735 MVT ContainerInVT = InVT;
10754 {Chain, Op1, Op1, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
10758 {Chain, Op2, Op2, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
10766 {Chain, Op1, Op2, CC, Mask, Mask, VL});
10771 {Chain, Op1, Op2, CC, DAG.getUNDEF(MaskVT), Mask, VL});
10784 MVT VT =
Op.getSimpleValueType();
10788 "Unexpected type for ISD::ABS");
10790 MVT ContainerVT = VT;
10797 if (
Op->getOpcode() == ISD::VP_ABS) {
10798 Mask =
Op->getOperand(1);
10802 VL =
Op->getOperand(2);
10810 DAG.
getUNDEF(ContainerVT), Mask, VL);
10812 DAG.
getUNDEF(ContainerVT), Mask, VL);
10819SDValue RISCVTargetLowering::lowerFixedLengthVectorFCOPYSIGNToRVV(
10822 MVT VT =
Op.getSimpleValueType();
10826 "Can only handle COPYSIGN with matching types.");
10835 Sign, DAG.
getUNDEF(ContainerVT), Mask, VL);
10840SDValue RISCVTargetLowering::lowerFixedLengthVectorSelectToRVV(
10842 MVT VT =
Op.getSimpleValueType();
10845 MVT I1ContainerVT =
10859 Op2, DAG.
getUNDEF(ContainerVT), VL);
10870 MVT VT =
Op.getSimpleValueType();
10875 for (
const SDValue &V :
Op->op_values()) {
10876 assert(!isa<VTSDNode>(V) &&
"Unexpected VTSDNode node!");
10879 if (!
V.getValueType().isVector()) {
10885 assert(useRVVForFixedLengthVectorVT(
V.getSimpleValueType()) &&
10886 "Only fixed length vectors are supported!");
10900 if (
Op->isStrictFPOpcode()) {
10909 DAG.
getNode(NewOpc,
DL, ContainerVT, Ops,
Op->getFlags());
10923 MVT VT =
Op.getSimpleValueType();
10926 MVT ContainerVT = VT;
10932 assert(!isa<VTSDNode>(V) &&
"Unexpected VTSDNode node!");
10935 if (HasPassthruOp) {
10938 if (*MaskIdx == OpIdx.index())
10942 if (
Op.getOpcode() == ISD::VP_MERGE) {
10946 assert(
Op.getOpcode() == ISD::VP_SELECT);
10953 if (!
V.getValueType().isFixedLengthVector()) {
10958 MVT OpVT =
V.getSimpleValueType();
10960 assert(useRVVForFixedLengthVectorVT(OpVT) &&
10961 "Only fixed length vectors are supported!");
10966 return DAG.
getNode(RISCVISDOpc,
DL, VT, Ops,
Op->getFlags());
10976 MVT VT =
Op.getSimpleValueType();
10982 MVT ContainerVT = VT;
10992 DAG.
getUNDEF(ContainerVT), Zero, VL);
10995 Op.getOpcode() == ISD::VP_ZERO_EXTEND ? 1 : -1,
DL, XLenVT);
10997 DAG.
getUNDEF(ContainerVT), SplatValue, VL);
11000 ZeroSplat, DAG.
getUNDEF(ContainerVT), VL);
11009 MVT VT =
Op.getSimpleValueType();
11013 ISD::CondCode Condition = cast<CondCodeSDNode>(
Op.getOperand(2))->get();
11017 MVT ContainerVT = VT;
11027 switch (Condition) {
11095 MVT DstVT =
Op.getSimpleValueType();
11096 MVT SrcVT = Src.getSimpleValueType();
11109 if (DstEltSize >= SrcEltSize) {
11118 if (SrcEltSize == 1) {
11129 ZeroSplat, DAG.
getUNDEF(IntVT), VL);
11130 }
else if (DstEltSize > (2 * SrcEltSize)) {
11134 Src = DAG.
getNode(RISCVISDExtOpc,
DL, IntVT, Src, Mask, VL);
11140 "Wrong input/output vector types");
11143 if (DstEltSize > (2 * SrcEltSize)) {
11159 MVT InterimFVT = DstVT;
11160 if (SrcEltSize > (2 * DstEltSize)) {
11161 assert(SrcEltSize == (4 * DstEltSize) &&
"Unexpected types!");
11168 if (InterimFVT != DstVT) {
11174 "Wrong input/output vector types");
11178 if (DstEltSize == 1) {
11181 assert(SrcEltSize >= 16 &&
"Unexpected FP type!");
11191 DAG.
getUNDEF(InterimIVT), SplatZero, VL);
11201 while (InterimIVT != DstVT) {
11213 MVT VT =
Op.getSimpleValueType();
11220RISCVTargetLowering::lowerVPSpliceExperimental(
SDValue Op,
11232 MVT VT =
Op.getSimpleValueType();
11233 MVT ContainerVT = VT;
11243 if (IsMaskVector) {
11254 SplatZeroOp1, DAG.
getUNDEF(ContainerVT), EVL1);
11263 SplatZeroOp2, DAG.
getUNDEF(ContainerVT), EVL2);
11266 int64_t ImmValue = cast<ConstantSDNode>(
Offset)->getSExtValue();
11267 SDValue DownOffset, UpOffset;
11268 if (ImmValue >= 0) {
11282 Op1, DownOffset, Mask, UpOffset);
11286 if (IsMaskVector) {
11290 {Result, DAG.getConstant(0, DL, ContainerVT),
11291 DAG.getCondCode(ISD::SETNE), DAG.getUNDEF(getMaskTypeFor(ContainerVT)),
11306 MVT VT =
Op.getSimpleValueType();
11308 MVT ContainerVT = VT;
11324RISCVTargetLowering::lowerVPReverseExperimental(
SDValue Op,
11327 MVT VT =
Op.getSimpleValueType();
11334 MVT ContainerVT = VT;
11342 MVT GatherVT = ContainerVT;
11346 if (IsMaskVector) {
11357 SplatZero, DAG.
getUNDEF(IndicesVT), EVL);
11363 unsigned MaxVLMAX =
11372 if (MaxVLMAX > 256 && EltSize == 8) {
11400 DAG.
getUNDEF(GatherVT), Result, Diff, Mask, EVL);
11402 if (IsMaskVector) {
11425 DAG.
getUNDEF(IndicesVT), VecLen, EVL);
11427 DAG.
getUNDEF(IndicesVT), Mask, EVL);
11429 DAG.
getUNDEF(GatherVT), Mask, EVL);
11431 if (IsMaskVector) {
11446 MVT VT =
Op.getSimpleValueType();
11448 return lowerVPOp(
Op, DAG);
11455 MVT ContainerVT = VT;
11474 MVT VT =
Op.getSimpleValueType();
11475 MVT ContainerVT = VT;
11481 auto *VPNode = cast<VPStridedLoadSDNode>(
Op);
11487 : Intrinsic::riscv_vlse_mask,
11490 DAG.
getUNDEF(ContainerVT), VPNode->getBasePtr(),
11491 VPNode->getStride()};
11499 Ops.
push_back(VPNode->getVectorLength());
11507 VPNode->getMemoryVT(), VPNode->getMemOperand());
11521 auto *VPNode = cast<VPStridedStoreSDNode>(
Op);
11522 SDValue StoreVal = VPNode->getValue();
11524 MVT ContainerVT = VT;
11535 : Intrinsic::riscv_vsse_mask,
11538 VPNode->getBasePtr(), VPNode->getStride()};
11546 Ops.
push_back(VPNode->getVectorLength());
11549 Ops, VPNode->getMemoryVT(),
11550 VPNode->getMemOperand());
11562 MVT VT =
Op.getSimpleValueType();
11564 const auto *MemSD = cast<MemSDNode>(
Op.getNode());
11565 EVT MemVT = MemSD->getMemoryVT();
11567 SDValue Chain = MemSD->getChain();
11573 if (
auto *VPGN = dyn_cast<VPGatherSDNode>(
Op.getNode())) {
11574 Index = VPGN->getIndex();
11575 Mask = VPGN->getMask();
11577 VL = VPGN->getVectorLength();
11582 auto *MGN = cast<MaskedGatherSDNode>(
Op.getNode());
11583 Index = MGN->getIndex();
11584 Mask = MGN->getMask();
11585 PassThru = MGN->getPassThru();
11589 MVT IndexVT =
Index.getSimpleValueType();
11593 "Unexpected VTs!");
11594 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
11597 "Unexpected extending MGATHER/VP_GATHER");
11603 MVT ContainerVT = VT;
11627 IsUnmasked ? Intrinsic::riscv_vluxei : Intrinsic::riscv_vluxei_mask;
11644 Chain =
Result.getValue(1);
11661 const auto *MemSD = cast<MemSDNode>(
Op.getNode());
11662 EVT MemVT = MemSD->getMemoryVT();
11664 SDValue Chain = MemSD->getChain();
11667 [[maybe_unused]]
bool IsTruncatingStore =
false;
11670 if (
auto *VPSN = dyn_cast<VPScatterSDNode>(
Op.getNode())) {
11671 Index = VPSN->getIndex();
11672 Mask = VPSN->getMask();
11673 Val = VPSN->getValue();
11674 VL = VPSN->getVectorLength();
11676 IsTruncatingStore =
false;
11679 auto *MSN = cast<MaskedScatterSDNode>(
Op.getNode());
11680 Index = MSN->getIndex();
11681 Mask = MSN->getMask();
11682 Val = MSN->getValue();
11683 IsTruncatingStore = MSN->isTruncatingStore();
11687 MVT IndexVT =
Index.getSimpleValueType();
11691 "Unexpected VTs!");
11692 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
11695 assert(!IsTruncatingStore &&
"Unexpected truncating MSCATTER/VP_SCATTER");
11701 MVT ContainerVT = VT;
11725 IsUnmasked ? Intrinsic::riscv_vsoxei : Intrinsic::riscv_vsoxei_mask;
11735 DAG.
getVTList(MVT::Other), Ops, MemVT, MMO);
11744 RISCVSysReg::lookupSysRegByName(
"FRM")->Encoding,
DL, XLenVT);
11752 static const int Table =
11776 RISCVSysReg::lookupSysRegByName(
"FRM")->Encoding,
DL, XLenVT);
11782 static const unsigned Table =
11805 bool isRISCV64 = Subtarget.
is64Bit();
11869 switch (
N->getOpcode()) {
11871 llvm_unreachable(
"Don't know how to custom type legalize this operation!");
11877 "Unexpected custom legalisation");
11878 bool IsStrict =
N->isStrictFPOpcode();
11881 SDValue Op0 = IsStrict ?
N->getOperand(1) :
N->getOperand(0);
11899 Opc,
DL, VTs, Chain, Op0,
11933 std::tie(Result, Chain) =
11934 makeLibCall(DAG, LC,
N->getValueType(0), Op0, CallOptions,
DL, Chain);
11962 Op0.
getValueType() == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
11973 assert(!Subtarget.
is64Bit() &&
"READCYCLECOUNTER/READSTEADYCOUNTER only "
11974 "has custom type legalization on riscv32");
11976 SDValue LoCounter, HiCounter;
11980 RISCVSysReg::lookupSysRegByName(
"CYCLE")->Encoding,
DL, XLenVT);
11982 RISCVSysReg::lookupSysRegByName(
"CYCLEH")->Encoding,
DL, XLenVT);
11985 RISCVSysReg::lookupSysRegByName(
"TIME")->Encoding,
DL, XLenVT);
11987 RISCVSysReg::lookupSysRegByName(
"TIMEH")->Encoding,
DL, XLenVT);
11991 N->getOperand(0), LoCounter, HiCounter);
12015 unsigned Size =
N->getSimpleValueType(0).getSizeInBits();
12016 unsigned XLen = Subtarget.
getXLen();
12019 assert(
Size == (XLen * 2) &&
"Unexpected custom legalisation");
12027 if (LHSIsU == RHSIsU)
12044 if (RHSIsU && LHSIsS && !RHSIsS)
12046 else if (LHSIsU && RHSIsS && !LHSIsS)
12056 "Unexpected custom legalisation");
12063 "Unexpected custom legalisation");
12066 if (
N->getOpcode() ==
ISD::SHL && Subtarget.hasStdExtZbs() &&
12092 "Unexpected custom legalisation");
12093 assert((Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb() ||
12094 Subtarget.hasVendorXTHeadBb()) &&
12095 "Unexpected custom legalization");
12096 if (!isa<ConstantSDNode>(
N->getOperand(1)) &&
12097 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()))
12106 "Unexpected custom legalisation");
12120 MVT VT =
N->getSimpleValueType(0);
12121 assert((VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32) &&
12122 Subtarget.
is64Bit() && Subtarget.hasStdExtM() &&
12123 "Unexpected custom legalisation");
12135 if (VT != MVT::i32)
12144 "Unexpected custom legalisation");
12148 if (!isa<ConstantSDNode>(
N->getOperand(1)))
12165 EVT OType =
N->getValueType(1);
12178 "Unexpected custom legalisation");
12195 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1), Res,
12199 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1),
N->getOperand(0),
12217 !Subtarget.hasStdExtZbb() &&
"Unexpected custom legalisation");
12226 "Unexpected custom legalisation");
12232 "Unexpected custom legalisation");
12234 if (Subtarget.hasStdExtZbb()) {
12268 EVT VT =
N->getValueType(0);
12273 if (VT == MVT::i16 && Op0VT == MVT::f16 &&
12277 }
else if (VT == MVT::i16 && Op0VT == MVT::bf16 &&
12278 Subtarget.hasStdExtZfbfmin()) {
12281 }
else if (VT == MVT::i32 && Op0VT == MVT::f32 && Subtarget.
is64Bit() &&
12286 }
else if (VT == MVT::i64 && Op0VT == MVT::f64 && XLenVT == MVT::i32) {
12288 DAG.
getVTList(MVT::i32, MVT::i32), Op0);
12309 MVT VT =
N->getSimpleValueType(0);
12311 assert((VT == MVT::i16 || (VT == MVT::i32 && Subtarget.
is64Bit())) &&
12312 "Unexpected custom legalisation");
12315 "Unexpected extension");
12341 assert(!Subtarget.
is64Bit() &&
N->getValueType(0) == MVT::i64 &&
12343 "Unexpected EXTRACT_VECTOR_ELT legalization");
12346 MVT ContainerVT = VecVT;
12374 DAG.
getUNDEF(ContainerVT), Mask, VL);
12382 unsigned IntNo =
N->getConstantOperandVal(0);
12386 "Don't know how to custom type legalize this intrinsic!");
12387 case Intrinsic::experimental_get_vector_length: {
12392 case Intrinsic::experimental_cttz_elts: {
12398 case Intrinsic::riscv_orc_b:
12399 case Intrinsic::riscv_brev8:
12400 case Intrinsic::riscv_sha256sig0:
12401 case Intrinsic::riscv_sha256sig1:
12402 case Intrinsic::riscv_sha256sum0:
12403 case Intrinsic::riscv_sha256sum1:
12404 case Intrinsic::riscv_sm3p0:
12405 case Intrinsic::riscv_sm3p1: {
12406 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
12426 case Intrinsic::riscv_sm4ks:
12427 case Intrinsic::riscv_sm4ed: {
12435 DAG.
getNode(Opc,
DL, MVT::i64, NewOp0, NewOp1,
N->getOperand(3));
12439 case Intrinsic::riscv_mopr: {
12440 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
12450 case Intrinsic::riscv_moprr: {
12451 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
12463 case Intrinsic::riscv_clmul: {
12464 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
12475 case Intrinsic::riscv_clmulh:
12476 case Intrinsic::riscv_clmulr: {
12477 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
12505 case Intrinsic::riscv_vmv_x_s: {
12506 EVT VT =
N->getValueType(0);
12508 if (VT.
bitsLT(XLenVT)) {
12517 "Unexpected custom legalization");
12555 case ISD::VP_REDUCE_ADD:
12556 case ISD::VP_REDUCE_AND:
12557 case ISD::VP_REDUCE_OR:
12558 case ISD::VP_REDUCE_XOR:
12559 case ISD::VP_REDUCE_SMAX:
12560 case ISD::VP_REDUCE_UMAX:
12561 case ISD::VP_REDUCE_SMIN:
12562 case ISD::VP_REDUCE_UMIN:
12626 const EVT VT =
N->getValueType(0);
12627 const unsigned Opc =
N->getOpcode();
12634 (Opc !=
ISD::FADD || !
N->getFlags().hasAllowReassociation()))
12639 "Inconsistent mappings");
12650 !isa<ConstantSDNode>(
RHS.getOperand(1)))
12653 uint64_t RHSIdx = cast<ConstantSDNode>(
RHS.getOperand(1))->getLimitedValue();
12668 LHS.getOperand(0) == SrcVec && isa<ConstantSDNode>(
LHS.getOperand(1))) {
12670 cast<ConstantSDNode>(
LHS.getOperand(1))->getLimitedValue();
12671 if (0 == std::min(LHSIdx, RHSIdx) && 1 == std::max(LHSIdx, RHSIdx)) {
12675 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
N->getFlags());
12682 if (
LHS.getOpcode() != ReduceOpc)
12697 auto Flags = ReduceVec->
getFlags();
12698 Flags.intersectWith(
N->getFlags());
12699 return DAG.
getNode(ReduceOpc,
DL, VT, Vec, Flags);
12709 auto BinOpToRVVReduce = [](
unsigned Opc) {
12738 auto IsReduction = [&BinOpToRVVReduce](
SDValue V,
unsigned Opc) {
12741 V.getOperand(0).getOpcode() == BinOpToRVVReduce(Opc);
12744 unsigned Opc =
N->getOpcode();
12745 unsigned ReduceIdx;
12746 if (IsReduction(
N->getOperand(0), Opc))
12748 else if (IsReduction(
N->getOperand(1), Opc))
12754 if (Opc ==
ISD::FADD && !
N->getFlags().hasAllowReassociation())
12757 SDValue Extract =
N->getOperand(ReduceIdx);
12789 SDValue NewStart =
N->getOperand(1 - ReduceIdx);
12816 if (!Subtarget.hasStdExtZba())
12820 EVT VT =
N->getValueType(0);
12832 auto *N0C = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
12833 auto *N1C = dyn_cast<ConstantSDNode>(N1->
getOperand(1));
12836 int64_t C0 = N0C->getSExtValue();
12837 int64_t C1 = N1C->getSExtValue();
12838 if (C0 <= 0 || C1 <= 0)
12842 int64_t Bits = std::min(C0, C1);
12843 int64_t Diff = std::abs(C0 - C1);
12844 if (Diff != 1 && Diff != 2 && Diff != 3)
12871 EVT VT =
N->getValueType(0);
12879 if ((!Subtarget.hasStdExtZicond() &&
12880 !Subtarget.hasVendorXVentanaCondOps()) ||
12902 bool SwapSelectOps;
12908 SwapSelectOps =
false;
12909 NonConstantVal = FalseVal;
12911 SwapSelectOps =
true;
12912 NonConstantVal = TrueVal;
12918 FalseVal = DAG.
getNode(
N->getOpcode(),
SDLoc(
N), VT, OtherOp, NonConstantVal);
12966 EVT VT =
N->getValueType(0);
12974 auto *N0C = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
12975 auto *N1C = dyn_cast<ConstantSDNode>(
N->getOperand(1));
12981 if (!N0C->hasOneUse())
12983 int64_t C0 = N0C->getSExtValue();
12984 int64_t C1 = N1C->getSExtValue();
12986 if (C0 == -1 || C0 == 0 || C0 == 1 || isInt<12>(C1))
12989 if ((C1 / C0) != 0 && isInt<12>(C1 / C0) && isInt<12>(C1 % C0) &&
12990 !isInt<12>(C0 * (C1 / C0))) {
12993 }
else if ((C1 / C0 + 1) != 0 && isInt<12>(C1 / C0 + 1) &&
12994 isInt<12>(C1 % C0 - C0) && !isInt<12>(C0 * (C1 / C0 + 1))) {
12997 }
else if ((C1 / C0 - 1) != 0 && isInt<12>(C1 / C0 - 1) &&
12998 isInt<12>(C1 % C0 + C0) && !isInt<12>(C0 * (C1 / C0 - 1))) {
13025 EVT VT =
N->getValueType(0);
13056 unsigned OuterExtend =
13060 OuterExtend,
SDLoc(
N), VT,
13068 EVT VT =
N->getValueType(0);
13116 EVT VT =
N->getValueType(0);
13120 auto *N0C = dyn_cast<ConstantSDNode>(N0);
13126 APInt ImmValMinus1 = N0C->getAPIntValue() - 1;
13136 if (!isIntEqualitySetCC(CCVal) || !SetCCOpVT.
isInteger())
13157 if (!Subtarget.hasStdExtZbb())
13160 EVT VT =
N->getValueType(0);
13162 if (VT != Subtarget.
getXLenVT() && VT != MVT::i32 && VT != MVT::i16)
13171 auto *ShAmtC = dyn_cast<ConstantSDNode>(N0.
getOperand(1));
13172 if (!ShAmtC || ShAmtC->getZExtValue() != 8)
13187 EVT VT =
N->getValueType(0);
13218 bool IsAnd =
N->getOpcode() ==
ISD::AND;
13242 EVT VT =
N->getValueType(0);
13266 EVT VT =
N->getValueType(0);
13293 if (CondLHS != True)
13300 if (!CondRHSC || CondRHSC->
getAPIntValue() != (1ULL << ScalarBits))
13312 if (!FalseRHSC || !FalseRHSC->
isZero())
13332 EVT VT =
N->getValueType(0);
13339 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() && VT == MVT::i1 &&
13366 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
13418 EVT VT =
N->getValueType(0);
13464 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
13489 auto *ConstN00 = dyn_cast<ConstantSDNode>(N0.
getOperand(0));
13494 const APInt &Imm = ConstN00->getAPIntValue();
13495 if ((Imm + 1).isSignedIntN(12))
13516 EVT VT =
N->getValueType(0);
13528 const bool HasShlAdd =
13529 Subtarget.hasStdExtZba() || Subtarget.hasVendorXTHeadBa();
13543 for (
uint64_t Divisor : {3, 5, 9}) {
13544 if (MulAmt % Divisor != 0)
13546 uint64_t MulAmt2 = MulAmt / Divisor;
13553 if (
X.getOpcode() ==
ISD::AND && isa<ConstantSDNode>(
X.getOperand(1)) &&
13554 X.getConstantOperandVal(1) == UINT64_C(0xffffffff)) {
13571 if (MulAmt2 == 3 || MulAmt2 == 5 || MulAmt2 == 9) {
13587 if (ScaleShift >= 1 && ScaleShift < 4) {
13588 unsigned ShiftAmt =
Log2_64((MulAmt & (MulAmt - 1)));
13602 for (
uint64_t Divisor : {3, 5, 9}) {
13607 if ((
C >> TZ) == Divisor && (TZ == 1 || TZ == 2 || TZ == 3)) {
13618 if (MulAmt > 2 &&
isPowerOf2_64((MulAmt - 1) & (MulAmt - 2))) {
13620 if (ScaleShift >= 1 && ScaleShift < 4) {
13621 unsigned ShiftAmt =
Log2_64(((MulAmt - 1) & (MulAmt - 2)));
13647 uint64_t MulAmtLowBit = MulAmt & (-MulAmt);
13649 uint64_t ShiftAmt1 = MulAmt + MulAmtLowBit;
13666 EVT VT =
N->getValueType(0);
13673 if (
N->getOperand(0).getOpcode() !=
ISD::AND ||
13674 N->getOperand(0).getOperand(0).getOpcode() !=
ISD::SRL)
13687 if (!V1.
isMask(HalfSize) || V2 != (1ULL | 1ULL << HalfSize) ||
13688 V3 != (HalfSize - 1))
13704 EVT VT =
N->getValueType(0);
13712 unsigned AddSubOpc;
13718 auto IsAddSubWith1 = [&](
SDValue V) ->
bool {
13719 AddSubOpc = V->getOpcode();
13721 SDValue Opnd = V->getOperand(1);
13722 MulOper = V->getOperand(0);
13731 if (IsAddSubWith1(N0)) {
13733 return DAG.
getNode(AddSubOpc,
DL, VT, N1, MulVal);
13736 if (IsAddSubWith1(N1)) {
13738 return DAG.
getNode(AddSubOpc,
DL, VT, N0, MulVal);
13753 if (isIndexTypeSigned(IndexType))
13756 if (!
N->hasOneUse())
13759 EVT VT =
N.getValueType();
13798 EVT SrcVT = Src.getValueType();
13802 NewElen = std::max(NewElen, 8U);
13825 EVT VT =
N->getValueType(0);
13828 if (OpVT != MVT::i64 || !Subtarget.
is64Bit())
13832 auto *N1C = dyn_cast<ConstantSDNode>(N1);
13844 if (!isIntEqualitySetCC(
Cond))
13853 const APInt &C1 = N1C->getAPIntValue();
13871 EVT VT =
N->getValueType(0);
13876 cast<VTSDNode>(
N->getOperand(1))->getVT().bitsGE(MVT::i16) &&
13877 Subtarget.hasStdExtZfhmin())
13879 Src.getOperand(0));
13887struct CombineResult;
13889enum ExtKind : uint8_t { ZExt = 1 << 0, SExt = 1 << 1, FPExt = 1 << 2 };
13916struct NodeExtensionHelper {
13925 bool SupportsFPExt;
13928 bool EnforceOneUse;
13943 return OrigOperand;
13954 unsigned getExtOpc(ExtKind SupportsExt)
const {
13955 switch (SupportsExt) {
13956 case ExtKind::SExt:
13958 case ExtKind::ZExt:
13960 case ExtKind::FPExt:
13971 std::optional<ExtKind> SupportsExt)
const {
13972 if (!SupportsExt.has_value())
13973 return OrigOperand;
13975 MVT NarrowVT = getNarrowType(Root, *SupportsExt);
13979 if (
Source.getValueType() == NarrowVT)
13982 unsigned ExtOpc = getExtOpc(*SupportsExt);
13986 auto [
Mask, VL] = getMaskAndVL(Root, DAG, Subtarget);
13993 return DAG.
getNode(ExtOpc,
DL, NarrowVT, Source, Mask, VL);
14005 DAG.
getUNDEF(NarrowVT), Source, VL);
14018 static MVT getNarrowType(
const SDNode *Root, ExtKind SupportsExt) {
14024 MVT EltVT = SupportsExt == ExtKind::FPExt
14026 :
MVT::getIntegerVT(NarrowSize);
14028 assert((
int)NarrowSize >= (SupportsExt == ExtKind::FPExt ? 16 : 8) &&
14029 "Trying to extend something we can't represent");
14036 static unsigned getSExtOpcode(
unsigned Opcode) {
14059 static unsigned getZExtOpcode(
unsigned Opcode) {
14085 static unsigned getFPExtOpcode(
unsigned Opcode) {
14110 static unsigned getSUOpcode(
unsigned Opcode) {
14112 "SU is only supported for MUL");
14118 static unsigned getWOpcode(
unsigned Opcode, ExtKind SupportsExt) {
14138 using CombineToTry = std::function<std::optional<CombineResult>(
14139 SDNode * ,
const NodeExtensionHelper & ,
14144 bool needToPromoteOtherUsers()
const {
return EnforceOneUse; }
14148 unsigned Opc = OrigOperand.
getOpcode();
14152 "Unexpected Opcode");
14165 unsigned ScalarBits =
Op.getValueSizeInBits();
14167 if (ScalarBits < EltBits) {
14170 !Subtarget.
is64Bit() &&
"Unexpected splat");
14172 SupportsSExt =
true;
14176 SupportsZExt =
true;
14178 EnforceOneUse =
false;
14182 unsigned NarrowSize = EltBits / 2;
14185 if (NarrowSize < 8)
14189 SupportsSExt =
true;
14193 SupportsZExt =
true;
14195 EnforceOneUse =
false;
14202 SupportsZExt =
false;
14203 SupportsSExt =
false;
14204 SupportsFPExt =
false;
14205 EnforceOneUse =
true;
14206 unsigned Opc = OrigOperand.
getOpcode();
14228 SupportsZExt =
true;
14231 SupportsSExt =
true;
14234 SupportsFPExt =
true;
14238 fillUpExtensionSupportForSplat(Root, DAG, Subtarget);
14251 unsigned ScalarBits =
Op.getOperand(0).getValueSizeInBits();
14252 if (NarrowSize != ScalarBits)
14255 SupportsFPExt =
true;
14264 static bool isSupportedRoot(
const SDNode *Root,
14293 Subtarget.hasStdExtZvbb();
14295 return Subtarget.hasStdExtZvbb();
14309 assert(isSupportedRoot(Root, Subtarget) &&
14310 "Trying to build an helper with an "
14311 "unsupported root");
14312 assert(OperandIdx < 2 &&
"Requesting something else than LHS or RHS");
14328 if (OperandIdx == 1) {
14337 EnforceOneUse =
false;
14342 fillUpExtensionSupport(Root, DAG, Subtarget);
14348 static std::pair<SDValue, SDValue>
14351 assert(isSupportedRoot(Root, Subtarget) &&
"Unexpected root");
14370 switch (
N->getOpcode()) {
14412struct CombineResult {
14414 unsigned TargetOpcode;
14416 std::optional<ExtKind> LHSExt;
14417 std::optional<ExtKind> RHSExt;
14421 NodeExtensionHelper
LHS;
14423 NodeExtensionHelper
RHS;
14425 CombineResult(
unsigned TargetOpcode,
SDNode *Root,
14426 const NodeExtensionHelper &
LHS, std::optional<ExtKind> LHSExt,
14427 const NodeExtensionHelper &
RHS, std::optional<ExtKind> RHSExt)
14428 : TargetOpcode(TargetOpcode), LHSExt(LHSExt), RHSExt(RHSExt), Root(Root),
14437 std::tie(Mask, VL) =
14438 NodeExtensionHelper::getMaskAndVL(Root, DAG, Subtarget);
14452 LHS.getOrCreateExtendedOp(Root, DAG, Subtarget, LHSExt),
14453 RHS.getOrCreateExtendedOp(Root, DAG, Subtarget, RHSExt),
14454 Passthru, Mask, VL);
14468static std::optional<CombineResult>
14469canFoldToVWWithSameExtensionImpl(
SDNode *Root,
const NodeExtensionHelper &LHS,
14470 const NodeExtensionHelper &RHS,
14473 if ((AllowExtMask & ExtKind::ZExt) &&
LHS.SupportsZExt &&
RHS.SupportsZExt)
14474 return CombineResult(NodeExtensionHelper::getZExtOpcode(Root->
getOpcode()),
14475 Root, LHS, {ExtKind::ZExt}, RHS,
14477 if ((AllowExtMask & ExtKind::SExt) &&
LHS.SupportsSExt &&
RHS.SupportsSExt)
14478 return CombineResult(NodeExtensionHelper::getSExtOpcode(Root->
getOpcode()),
14479 Root, LHS, {ExtKind::SExt}, RHS,
14481 if ((AllowExtMask & ExtKind::FPExt) &&
LHS.SupportsFPExt &&
RHS.SupportsFPExt)
14482 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
14483 Root, LHS, {ExtKind::FPExt}, RHS,
14485 return std::nullopt;
14494static std::optional<CombineResult>
14495canFoldToVWWithSameExtension(
SDNode *Root,
const NodeExtensionHelper &LHS,
14498 return canFoldToVWWithSameExtensionImpl(
14499 Root, LHS, RHS, ExtKind::ZExt | ExtKind::SExt | ExtKind::FPExt, DAG,
14507static std::optional<CombineResult>
14508canFoldToVW_W(
SDNode *Root,
const NodeExtensionHelper &LHS,
14511 if (
RHS.SupportsFPExt)
14512 return CombineResult(
14513 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::FPExt),
14514 Root, LHS, std::nullopt, RHS, {ExtKind::FPExt});
14521 return CombineResult(
14522 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::ZExt), Root,
14523 LHS, std::nullopt, RHS, {ExtKind::ZExt});
14525 return CombineResult(
14526 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::SExt), Root,
14527 LHS, std::nullopt, RHS, {ExtKind::SExt});
14528 return std::nullopt;
14535static std::optional<CombineResult>
14536canFoldToVWWithSEXT(
SDNode *Root,
const NodeExtensionHelper &LHS,
14539 return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::SExt, DAG,
14547static std::optional<CombineResult>
14548canFoldToVWWithZEXT(
SDNode *Root,
const NodeExtensionHelper &LHS,
14551 return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::ZExt, DAG,
14559static std::optional<CombineResult>
14560canFoldToVWWithFPEXT(
SDNode *Root,
const NodeExtensionHelper &LHS,
14563 return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::FPExt, DAG,
14571static std::optional<CombineResult>
14572canFoldToVW_SU(
SDNode *Root,
const NodeExtensionHelper &LHS,
14576 if (!
LHS.SupportsSExt || !
RHS.SupportsZExt)
14577 return std::nullopt;
14578 return CombineResult(NodeExtensionHelper::getSUOpcode(Root->
getOpcode()),
14579 Root, LHS, {ExtKind::SExt}, RHS,
14584NodeExtensionHelper::getSupportedFoldings(
const SDNode *Root) {
14595 Strategies.
push_back(canFoldToVWWithSameExtension);
14604 Strategies.
push_back(canFoldToVWWithSameExtension);
14609 Strategies.
push_back(canFoldToVWWithSameExtension);
14616 Strategies.
push_back(canFoldToVWWithZEXT);
14621 Strategies.
push_back(canFoldToVWWithSEXT);
14626 Strategies.
push_back(canFoldToVWWithZEXT);
14631 Strategies.
push_back(canFoldToVWWithFPEXT);
14660 if (!NodeExtensionHelper::isSupportedRoot(
N, Subtarget))
14666 Inserted.insert(
N);
14669 while (!Worklist.
empty()) {
14672 NodeExtensionHelper
LHS(Root, 0, DAG, Subtarget);
14673 NodeExtensionHelper
RHS(Root, 1, DAG, Subtarget);
14674 auto AppendUsersIfNeeded = [&Worklist, &Subtarget,
14675 &Inserted](
const NodeExtensionHelper &
Op) {
14676 if (
Op.needToPromoteOtherUsers()) {
14678 UE =
Op.OrigOperand->use_end();
14681 if (!NodeExtensionHelper::isSupportedRoot(TheUse, Subtarget))
14684 if (UI.getOperandNo() >= 2)
14686 if (Inserted.insert(TheUse).second)
14699 NodeExtensionHelper::getSupportedFoldings(Root);
14701 assert(!FoldingStrategies.
empty() &&
"Nothing to be folded");
14702 bool Matched =
false;
14703 for (
int Attempt = 0;
14704 (Attempt != 1 + NodeExtensionHelper::isCommutative(Root)) && !Matched;
14707 for (NodeExtensionHelper::CombineToTry FoldingStrategy :
14708 FoldingStrategies) {
14709 std::optional<CombineResult> Res =
14710 FoldingStrategy(Root,
LHS,
RHS, DAG, Subtarget);
14717 if (Res->LHSExt.has_value())
14718 if (!AppendUsersIfNeeded(
LHS))
14720 if (Res->RHSExt.has_value())
14721 if (!AppendUsersIfNeeded(
RHS))
14733 SDValue InputRootReplacement;
14740 for (CombineResult Res : CombinesToApply) {
14741 SDValue NewValue = Res.materialize(DAG, Subtarget);
14742 if (!InputRootReplacement) {
14744 "First element is expected to be the current node");
14745 InputRootReplacement = NewValue;
14750 for (std::pair<SDValue, SDValue> OldNewValues : ValuesToReplace) {
14754 return InputRootReplacement;
14761 unsigned Opc =
N->getOpcode();
14766 SDValue MergeOp =
N->getOperand(1);
14767 unsigned MergeOpc = MergeOp.
getOpcode();
14778 SDValue Passthru =
N->getOperand(2);
14792 Z = Z.getOperand(1);
14798 {Y, X, Y, MergeOp->getOperand(0), N->getOperand(4)},
14805 [[maybe_unused]]
unsigned Opc =
N->getOpcode();
14834 EVT NewMemVT = (MemVT == MVT::i32) ? MVT::i64 : MVT::i128;
14840 auto Ext = cast<LoadSDNode>(LSNode1)->getExtensionType();
14842 if (MemVT == MVT::i32)
14848 Opcode,
SDLoc(LSNode1), DAG.
getVTList({XLenVT, XLenVT, MVT::Other}),
14883 if (!Subtarget.hasVendorXTHeadMemPair())
14895 auto ExtractBaseAndOffset = [](
SDValue Ptr) -> std::pair<SDValue, uint64_t> {
14897 if (
auto *C1 = dyn_cast<ConstantSDNode>(
Ptr->getOperand(1)))
14898 return {
Ptr->getOperand(0), C1->getZExtValue()};
14902 auto [Base1, Offset1] = ExtractBaseAndOffset(LSNode1->
getOperand(OpNum));
14925 auto [Base2, Offset2] = ExtractBaseAndOffset(LSNode2->
getOperand(OpNum));
14928 if (Base1 != Base2)
14932 bool Valid =
false;
14933 if (MemVT == MVT::i32) {
14935 if ((Offset1 + 4 == Offset2) && isShiftedUInt<2, 3>(Offset1))
14937 }
else if (MemVT == MVT::i64) {
14939 if ((Offset1 + 8 == Offset2) && isShiftedUInt<2, 4>(Offset1))
14973 if (Src->isStrictFPOpcode() || Src->isTargetStrictFPOpcode())
14981 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
14991 EVT VT =
N->getValueType(0);
14994 MVT SrcVT = Src.getSimpleValueType();
14995 MVT SrcContainerVT = SrcVT;
14997 SDValue XVal = Src.getOperand(0);
15024 FpToInt = DAG.
getNode(Opc,
DL, ContainerVT, XVal, Mask, VL);
15028 FpToInt = DAG.
getNode(Opc,
DL, ContainerVT, XVal, Mask, VL);
15032 FpToInt = DAG.
getNode(Opc,
DL, ContainerVT, XVal, Mask,
15045 if (VT != MVT::i32 && VT != XLenVT)
15075 EVT DstVT =
N->getValueType(0);
15076 if (DstVT != XLenVT)
15082 if (Src->isStrictFPOpcode() || Src->isTargetStrictFPOpcode())
15090 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
15093 EVT SatVT = cast<VTSDNode>(
N->getOperand(1))->getVT();
15102 if (SatVT == DstVT)
15104 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
15110 Src = Src.getOperand(0);
15131 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected extension");
15137 EVT VT =
N->getValueType(0);
15190 unsigned Offset =
N->isTargetStrictFPOpcode();
15197 auto invertIfNegative = [&Mask, &VL](
SDValue &V) {
15199 V.getOperand(2) == VL) {
15201 V = V.getOperand(0);
15208 bool NegA = invertIfNegative(
A);
15209 bool NegB = invertIfNegative(
B);
15210 bool NegC = invertIfNegative(
C);
15213 if (!NegA && !NegB && !NegC)
15217 if (
N->isTargetStrictFPOpcode())
15219 {N->getOperand(0), A, B, C, Mask, VL});
15232 if (
N->getValueType(0).getVectorElementType() == MVT::f32 &&
15237 if (
N->isTargetStrictFPOpcode())
15247 EVT VT =
N->getValueType(0);
15252 if (!isa<ConstantSDNode>(
N->getOperand(1)))
15254 uint64_t ShAmt =
N->getConstantOperandVal(1);
15262 cast<VTSDNode>(N0.
getOperand(1))->getVT().getSizeInBits();
15267 if (LShAmt < ExtSize) {
15280 if (ShAmt > 32 || VT != MVT::i64)
15296 AddC = dyn_cast<ConstantSDNode>(N0.
getOperand(IsAdd ? 1 : 0));
15309 !isa<ConstantSDNode>(U->getOperand(1)) ||
15310 U->getConstantOperandVal(1) > 32)
15365 if (!
Cond.hasOneUse())
15384 EVT VT =
Cond.getValueType();
15429 LHS =
LHS.getOperand(0);
15439 LHS.getOperand(0).getValueType() == Subtarget.
getXLenVT()) {
15443 CCVal = cast<CondCodeSDNode>(
LHS.getOperand(2))->get();
15447 RHS =
LHS.getOperand(1);
15448 LHS =
LHS.getOperand(0);
15457 RHS =
LHS.getOperand(1);
15458 LHS =
LHS.getOperand(0);
15474 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
15515 bool Commutative =
true;
15516 unsigned Opc = TrueVal.getOpcode();
15524 Commutative =
false;
15532 if (!TrueVal.hasOneUse() || isa<ConstantSDNode>(FalseVal))
15536 if (FalseVal == TrueVal.getOperand(0))
15538 else if (Commutative && FalseVal == TrueVal.getOperand(1))
15543 EVT VT =
N->getValueType(0);
15545 SDValue OtherOp = TrueVal.getOperand(1 - OpToFold);
15551 assert(IdentityOperand &&
"No identity operand!");
15556 DAG.
getSelect(
DL, OtherOpVT,
N->getOperand(0), OtherOp, IdentityOperand);
15557 return DAG.
getNode(TrueVal.getOpcode(),
DL, VT, FalseVal, NewSel);
15578 CountZeroes =
N->getOperand(2);
15579 ValOnZero =
N->getOperand(1);
15581 CountZeroes =
N->getOperand(1);
15582 ValOnZero =
N->getOperand(2);
15601 if (
Cond->getOperand(0) != CountZeroesArgument)
15617 CountZeroes, BitWidthMinusOne);
15627 EVT VT =
N->getValueType(0);
15628 EVT CondVT =
Cond.getValueType();
15636 (Subtarget.hasStdExtZicond() || Subtarget.hasVendorXVentanaCondOps())) {
15642 const APInt &MaskVal =
LHS.getConstantOperandAPInt(1);
15663 SDValue TrueVal =
N->getOperand(1);
15664 SDValue FalseVal =
N->getOperand(2);
15679 EVT VT =
N->getValueType(0);
15686 const unsigned Opcode =
N->op_begin()->getNode()->getOpcode();
15701 if (
Op.isUndef()) {
15714 if (
Op.getOpcode() != Opcode || !
Op.hasOneUse())
15718 if (!isa<ConstantSDNode>(
Op.getOperand(1)) &&
15719 !isa<ConstantFPSDNode>(
Op.getOperand(1)))
15723 if (
Op.getOperand(0).getValueType() !=
Op.getOperand(1).getValueType())
15751 const unsigned InVecOpcode = InVec->
getOpcode();
15761 if (!isa<ConstantSDNode>(InValRHS) && !isa<ConstantFPSDNode>(InValRHS))
15768 InVecLHS, InValLHS, EltNo);
15770 InVecRHS, InValRHS, EltNo);
15779 auto *IndexC = dyn_cast<ConstantSDNode>(EltNo);
15782 unsigned Elt = IndexC->getZExtValue();
15790 unsigned ConcatOpIdx = Elt / ConcatNumElts;
15793 ConcatOp, InVal, NewIdx);
15797 ConcatOps[ConcatOpIdx] = ConcatOp;
15809 EVT VT =
N->getValueType(0);
15819 auto *BaseLd = dyn_cast<LoadSDNode>(
N->getOperand(0));
15821 !
SDValue(BaseLd, 0).hasOneUse())
15824 EVT BaseLdVT = BaseLd->getValueType(0);
15831 auto *Ld = dyn_cast<LoadSDNode>(
Op);
15832 if (!Ld || !Ld->isSimple() || !
Op.hasOneUse() ||
15834 Ld->getValueType(0) != BaseLdVT)
15843 using PtrDiff = std::pair<std::variant<int64_t, SDValue>,
bool>;
15845 LoadSDNode *Ld2) -> std::optional<PtrDiff> {
15850 if (BIO1.equalBaseIndex(BIO2, DAG))
15855 SDValue P2 = Ld2->getBasePtr();
15861 return std::nullopt;
15865 auto BaseDiff = GetPtrDiff(Lds[0], Lds[1]);
15870 for (
auto *It = Lds.
begin() + 1; It != Lds.
end() - 1; It++)
15871 if (GetPtrDiff(*It, *std::next(It)) != BaseDiff)
15879 unsigned WideScalarBitWidth =
15892 auto [StrideVariant, MustNegateStride] = *BaseDiff;
15894 std::holds_alternative<SDValue>(StrideVariant)
15895 ? std::get<SDValue>(StrideVariant)
15898 if (MustNegateStride)
15906 if (
auto *ConstStride = dyn_cast<ConstantSDNode>(Stride);
15907 ConstStride && ConstStride->getSExtValue() >= 0)
15911 ConstStride->getSExtValue() * (
N->getNumOperands() - 1);
15917 BaseLd->getPointerInfo(), BaseLd->getMemOperand()->getFlags(), MemSize,
15921 WideVecVT,
DL, BaseLd->getChain(), BaseLd->getBasePtr(), Stride,
15936 if (
N->getValueType(0).isFixedLengthVector())
15939 SDValue Addend =
N->getOperand(0);
15943 SDValue AddPassthruOp =
N->getOperand(2);
15944 if (!AddPassthruOp.
isUndef())
15948 auto IsVWMulOpc = [](
unsigned Opc) {
15967 if (!MulPassthruOp.
isUndef())
15977 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
15978 }(
N, DAG, Subtarget);
15983 if (AddMask != MulMask || AddVL != MulVL)
15988 "Unexpected opcode after VWMACC_VL");
15990 "Unexpected opcode after VWMACC_VL!");
15992 "Unexpected opcode after VWMUL_VL!");
15994 "Unexpected opcode after VWMUL_VL!");
15997 EVT VT =
N->getValueType(0);
16013 const EVT IndexVT =
Index.getValueType();
16017 if (!isIndexTypeSigned(IndexType))
16049 for (
unsigned i = 0; i <
Index->getNumOperands(); i++) {
16052 if (
Index->getOperand(i)->isUndef())
16055 if (
C % ElementSize != 0)
16057 C =
C / ElementSize;
16061 ActiveLanes.
set(
C);
16063 return ActiveLanes.
all();
16081 if (NumElems % 2 != 0)
16085 const unsigned WiderElementSize = ElementSize * 2;
16086 if (WiderElementSize > ST.getELen()/8)
16089 if (!ST.enableUnalignedVectorMem() && BaseAlign < WiderElementSize)
16092 for (
unsigned i = 0; i <
Index->getNumOperands(); i++) {
16095 if (
Index->getOperand(i)->isUndef())
16101 if (
C % WiderElementSize != 0)
16106 if (
C !=
Last + ElementSize)
16123 (isa<RegisterSDNode>(VL) &&
16124 cast<RegisterSDNode>(VL)->getReg() == RISCV::X0);
16126 Mask.getOperand(0) != VL)
16129 auto IsTruncNode = [&](
SDValue V) {
16131 V.getOperand(1) == Mask && V.getOperand(2) == VL;
16138 while (IsTruncNode(
Op)) {
16139 if (!
Op.hasOneUse())
16141 Op =
Op.getOperand(0);
16176 MVT VT =
N->getSimpleValueType(0);
16181 auto MatchMinMax = [&VL, &Mask](
SDValue V,
unsigned Opc,
unsigned OpcVL,
16183 if (V.getOpcode() != Opc &&
16184 !(V.getOpcode() == OpcVL && V.getOperand(2).isUndef() &&
16185 V.getOperand(3) == Mask && V.getOperand(4) == VL))
16193 Op.getOperand(1).getValueType().isFixedLengthVector() &&
16195 Op.getOperand(1).getOperand(0).getValueType() ==
Op.getValueType() &&
16197 Op =
Op.getOperand(1).getOperand(0);
16200 return V.getOperand(0);
16203 Op.getOperand(2) == VL) {
16204 if (
auto *Op1 = dyn_cast<ConstantSDNode>(
Op.getOperand(1))) {
16206 Op1->getAPIntValue().sextOrTrunc(
Op.getScalarValueSizeInBits());
16207 return V.getOperand(0);
16216 auto DetectUSatPattern = [&](
SDValue V) {
16241 V.getOperand(1), DAG.
getUNDEF(V.getValueType()),
16247 auto DetectSSatPattern = [&](
SDValue V) {
16249 unsigned NumSrcBits = V.getScalarValueSizeInBits();
16257 if (HiC == SignedMax && LoC == SignedMin)
16263 if (HiC == SignedMax && LoC == SignedMin)
16273 Src.getOperand(1) == Mask && Src.getOperand(2) == VL &&
16275 Src = Src.getOperand(0);
16279 if ((Val = DetectUSatPattern(Src)))
16281 else if ((Val = DetectSSatPattern(Src)))
16291 Val = DAG.
getNode(ClipOpc,
DL, ValVT, Val, Mask, VL);
16292 }
while (ValVT != VT);
16306 auto SimplifyDemandedLowBitsHelper = [&](
unsigned OpNo,
unsigned LowBits) {
16317 switch (
N->getOpcode()) {
16337 APInt V =
C->getValueAPF().bitcastToAPInt();
16372 if (SimplifyDemandedLowBitsHelper(0, 32) ||
16373 SimplifyDemandedLowBitsHelper(1, 5))
16381 if (SimplifyDemandedLowBitsHelper(0, 32))
16398 MVT VT =
N->getSimpleValueType(0);
16407 "Unexpected value type!");
16430 EVT VT =
N->getValueType(0);
16483 if (!
C || !
C->getValueAPF().isExactlyValue(+1.0))
16485 EVT VT =
N->getValueType(0);
16514 if (
N->getValueType(0) == MVT::i64 && Subtarget.
is64Bit()) {
16519 Src.getOperand(0));
16524 Src.getOperand(0), Src.getOperand(1));
16545 unsigned Opc =
N->getOpcode();
16560 return DAG.
getNode(InvOpc,
SDLoc(
N),
N->getValueType(0), Val, NewCond);
16570 N->getValueType(0), Val,
Cond.getOperand(0));
16581 SDValue FalseV =
N->getOperand(4);
16583 EVT VT =
N->getValueType(0);
16586 if (TrueV == FalseV)
16591 if (!Subtarget.hasShortForwardBranchOpt() && isa<ConstantSDNode>(TrueV) &&
16597 int64_t TrueSImm = cast<ConstantSDNode>(TrueV)->getSExtValue();
16598 int64_t FalseSImm = cast<ConstantSDNode>(FalseV)->getSExtValue();
16601 if (isInt<12>(TrueSImm) && isInt<12>(FalseSImm) &&
16602 isInt<12>(TrueSImm - FalseSImm)) {
16618 {LHS, RHS, CC, TrueV, FalseV});
16685 N->getOperand(0),
LHS,
RHS,
CC,
N->getOperand(4));
16698 EVT VT =
N->getValueType(0);
16722 const auto *MGN = cast<MaskedGatherSDNode>(
N);
16723 const EVT VT =
N->getValueType(0);
16725 SDValue ScaleOp = MGN->getScale();
16727 assert(!MGN->isIndexScaled() &&
16728 "Scaled gather/scatter should not be formed");
16733 N->getVTList(), MGN->getMemoryVT(),
DL,
16734 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
16735 MGN->getBasePtr(), Index, ScaleOp},
16736 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
16740 N->getVTList(), MGN->getMemoryVT(),
DL,
16741 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
16742 MGN->getBasePtr(), Index, ScaleOp},
16743 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
16749 if (std::optional<VIDSequence> SimpleVID =
16751 SimpleVID && SimpleVID->StepDenominator == 1) {
16752 const int64_t StepNumerator = SimpleVID->StepNumerator;
16753 const int64_t Addend = SimpleVID->Addend;
16760 assert(MGN->getBasePtr()->getValueType(0) == PtrVT);
16768 VT,
DL, MGN->getChain(), BasePtr,
16770 EVL, MGN->getMemOperand());
16772 StridedLoad, MGN->getPassThru(), EVL);
16782 MGN->getBasePtr(), DAG.
getUNDEF(XLenVT),
16784 MGN->getMemoryVT(), MGN->getMemOperand(),
16793 MGN->getMemOperand()->getBaseAlign(), Subtarget)) {
16795 for (
unsigned i = 0; i <
Index->getNumOperands(); i += 2)
16797 EVT IndexVT =
Index.getValueType()
16804 assert(EltCnt.isKnownEven() &&
"Splitting vector, but not in half!");
16806 EltCnt.divideCoefficientBy(2));
16809 EltCnt.divideCoefficientBy(2));
16814 {MGN->getChain(), Passthru, Mask, MGN->getBasePtr(),
16823 const auto *MSN = cast<MaskedScatterSDNode>(
N);
16825 SDValue ScaleOp = MSN->getScale();
16827 assert(!MSN->isIndexScaled() &&
16828 "Scaled gather/scatter should not be formed");
16833 N->getVTList(), MSN->getMemoryVT(),
DL,
16834 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
16836 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
16840 N->getVTList(), MSN->getMemoryVT(),
DL,
16841 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
16843 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
16845 EVT VT = MSN->getValue()->getValueType(0);
16847 if (!MSN->isTruncatingStore() &&
16851 return DAG.
getMaskedStore(MSN->getChain(),
DL, Shuffle, MSN->getBasePtr(),
16852 DAG.
getUNDEF(XLenVT), MSN->getMask(),
16853 MSN->getMemoryVT(), MSN->getMemOperand(),
16858 case ISD::VP_GATHER: {
16859 const auto *VPGN = cast<VPGatherSDNode>(
N);
16861 SDValue ScaleOp = VPGN->getScale();
16863 assert(!VPGN->isIndexScaled() &&
16864 "Scaled gather/scatter should not be formed");
16869 {VPGN->getChain(), VPGN->getBasePtr(), Index,
16870 ScaleOp, VPGN->getMask(),
16871 VPGN->getVectorLength()},
16872 VPGN->getMemOperand(), IndexType);
16876 {VPGN->getChain(), VPGN->getBasePtr(), Index,
16877 ScaleOp, VPGN->getMask(),
16878 VPGN->getVectorLength()},
16879 VPGN->getMemOperand(), IndexType);
16883 case ISD::VP_SCATTER: {
16884 const auto *VPSN = cast<VPScatterSDNode>(
N);
16886 SDValue ScaleOp = VPSN->getScale();
16888 assert(!VPSN->isIndexScaled() &&
16889 "Scaled gather/scatter should not be formed");
16894 {VPSN->getChain(), VPSN->getValue(),
16895 VPSN->getBasePtr(), Index, ScaleOp,
16896 VPSN->getMask(), VPSN->getVectorLength()},
16897 VPSN->getMemOperand(), IndexType);
16901 {VPSN->getChain(), VPSN->getValue(),
16902 VPSN->getBasePtr(), Index, ScaleOp,
16903 VPSN->getMask(), VPSN->getVectorLength()},
16904 VPSN->getMemOperand(), IndexType);
16918 EVT VT =
N->getValueType(0);
16921 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt,
16922 N->getOperand(2),
N->getOperand(3),
N->getOperand(4));
16940 EVT VT =
N->getValueType(0);
16944 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt);
16974 if (
N->getValueType(0).getVectorElementType() == MVT::f32 &&
16988 auto *Store = cast<StoreSDNode>(
N);
16989 SDValue Chain = Store->getChain();
16990 EVT MemVT = Store->getMemoryVT();
16991 SDValue Val = Store->getValue();
16994 bool IsScalarizable =
16996 Store->isSimple() &&
17026 NewVT, *Store->getMemOperand())) {
17028 return DAG.
getStore(Chain,
DL, NewV, Store->getBasePtr(),
17029 Store->getPointerInfo(), Store->getOriginalAlign(),
17030 Store->getMemOperand()->getFlags());
17038 if (
auto *L = dyn_cast<LoadSDNode>(Val);
17040 L->hasNUsesOfValue(1, 0) && L->hasNUsesOfValue(1, 1) &&
17042 L->getMemoryVT() == MemVT) {
17045 NewVT, *Store->getMemOperand()) &&
17047 NewVT, *L->getMemOperand())) {
17049 L->getPointerInfo(), L->getOriginalAlign(),
17050 L->getMemOperand()->getFlags());
17051 return DAG.
getStore(Chain,
DL, NewL, Store->getBasePtr(),
17052 Store->getPointerInfo(), Store->getOriginalAlign(),
17053 Store->getMemOperand()->getFlags());
17065 MVT VecVT = Src.getSimpleValueType();
17072 Store->getChain(),
DL, Src, Store->getBasePtr(), Store->getOffset(),
17075 Store->getMemOperand(), Store->getAddressingMode(),
17076 Store->isTruncatingStore(),
false);
17083 EVT VT =
N->getValueType(0);
17105 const MVT VT =
N->getSimpleValueType(0);
17106 SDValue Passthru =
N->getOperand(0);
17107 SDValue Scalar =
N->getOperand(1);
17116 const MVT VT =
N->getSimpleValueType(0);
17117 SDValue Passthru =
N->getOperand(0);
17118 SDValue Scalar =
N->getOperand(1);
17123 unsigned ScalarSize = Scalar.getValueSizeInBits();
17125 if (ScalarSize > EltWidth && Passthru.
isUndef())
17126 if (SimplifyDemandedLowBitsHelper(1, EltWidth))
17133 (!Const || Const->isZero() ||
17134 !Const->getAPIntValue().sextOrTrunc(EltWidth).isSignedIntN(5)))
17144 if (
N->getOperand(0).isUndef() &&
17147 Src.getOperand(0).getValueType().isScalableVector()) {
17148 EVT VT =
N->getValueType(0);
17149 EVT SrcVT = Src.getOperand(0).getValueType();
17153 return Src.getOperand(0);
17159 const MVT VT =
N->getSimpleValueType(0);
17160 SDValue Passthru =
N->getOperand(0);
17161 SDValue Scalar =
N->getOperand(1);
17165 Scalar.getOperand(0).getValueType() ==
N->getValueType(0))
17166 return Scalar.getOperand(0);
17175 DAG.
getNode(
N->getOpcode(),
DL, M1VT, M1Passthru, Scalar, VL);
17185 Const && !Const->isZero() && isInt<5>(Const->getSExtValue()) &&
17193 MVT VecVT =
N->getOperand(0).getSimpleValueType();
17195 if (M1VT.
bitsLT(VecVT)) {
17206 unsigned IntNo =
N->getConstantOperandVal(IntOpNo);
17211 case Intrinsic::riscv_vcpop:
17212 case Intrinsic::riscv_vcpop_mask:
17213 case Intrinsic::riscv_vfirst:
17214 case Intrinsic::riscv_vfirst_mask: {
17216 if (IntNo == Intrinsic::riscv_vcpop_mask ||
17217 IntNo == Intrinsic::riscv_vfirst_mask)
17218 VL =
N->getOperand(3);
17223 EVT VT =
N->getValueType(0);
17224 if (IntNo == Intrinsic::riscv_vfirst ||
17225 IntNo == Intrinsic::riscv_vfirst_mask)
17234 EVT VT =
N->getValueType(0);
17238 if ((SrcVT == MVT::v1i1 || SrcVT == MVT::v2i1 || SrcVT == MVT::v4i1) &&
17257 EVT XVT,
unsigned KeptBits)
const {
17262 if (XVT != MVT::i32 && XVT != MVT::i64)
17266 if (KeptBits == 32 || KeptBits == 64)
17270 return Subtarget.hasStdExtZbb() &&
17271 ((KeptBits == 8 && XVT == MVT::i64 && !Subtarget.
is64Bit()) ||
17279 "Expected shift op");
17290 auto *C1 = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
17291 auto *C2 = dyn_cast<ConstantSDNode>(
N->getOperand(1));
17293 const APInt &C1Int = C1->getAPIntValue();
17294 APInt ShiftedC1Int = C1Int << C2->getAPIntValue();
17320 if (C1Cost < ShiftedC1Cost)
17334 EVT VT =
Op.getValueType();
17338 unsigned Opcode =
Op.getOpcode();
17346 const APInt &Mask =
C->getAPIntValue();
17355 auto IsLegalMask = [ShrunkMask, ExpandedMask](
const APInt &Mask) ->
bool {
17356 return ShrunkMask.
isSubsetOf(Mask) && Mask.isSubsetOf(ExpandedMask);
17358 auto UseMask = [Mask,
Op, &TLO](
const APInt &NewMask) ->
bool {
17359 if (NewMask == Mask)
17364 Op.getOperand(0), NewC);
17377 APInt NewMask =
APInt(Mask.getBitWidth(), 0xffff);
17378 if (IsLegalMask(NewMask))
17379 return UseMask(NewMask);
17382 if (VT == MVT::i64) {
17384 if (IsLegalMask(NewMask))
17385 return UseMask(NewMask);
17400 APInt NewMask = ShrunkMask;
17401 if (MinSignedBits <= 12)
17403 else if (!
C->isOpaque() && MinSignedBits <= 32 && !ShrunkMask.
isSignedIntN(32))
17409 assert(IsLegalMask(NewMask));
17410 return UseMask(NewMask);
17414 static const uint64_t GREVMasks[] = {
17415 0x5555555555555555ULL, 0x3333333333333333ULL, 0x0F0F0F0F0F0F0F0FULL,
17416 0x00FF00FF00FF00FFULL, 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL};
17418 for (
unsigned Stage = 0; Stage != 6; ++Stage) {
17419 unsigned Shift = 1 << Stage;
17420 if (ShAmt & Shift) {
17422 uint64_t Res = ((x & Mask) << Shift) | ((x >> Shift) & Mask);
17434 const APInt &DemandedElts,
17436 unsigned Depth)
const {
17438 unsigned Opc =
Op.getOpcode();
17443 "Should use MaskedValueIsZero if you don't know whether Op"
17444 " is a target node!");
17527 assert(MinVLenB > 0 &&
"READ_VLENB without vector extension enabled?");
17530 if (MaxVLenB == MinVLenB)
17547 case Intrinsic::riscv_vsetvli:
17548 case Intrinsic::riscv_vsetvlimax: {
17549 bool HasAVL = IntNo == Intrinsic::riscv_vsetvli;
17550 unsigned VSEW =
Op.getConstantOperandVal(HasAVL + 1);
17556 MaxVL = (Fractional) ? MaxVL / LMul : MaxVL * LMul;
17559 if (HasAVL && isa<ConstantSDNode>(
Op.getOperand(1)))
17560 MaxVL = std::min(MaxVL,
Op.getConstantOperandVal(1));
17562 unsigned KnownZeroFirstBit =
Log2_32(MaxVL) + 1;
17575 unsigned Depth)
const {
17576 switch (
Op.getOpcode()) {
17582 if (Tmp == 1)
return 1;
17585 return std::min(Tmp, Tmp2);
17597 if (Tmp < 33)
return 1;
17622 unsigned XLen = Subtarget.
getXLen();
17623 unsigned EltBits =
Op.getOperand(0).getScalarValueSizeInBits();
17624 if (EltBits <= XLen)
17625 return XLen - EltBits + 1;
17629 unsigned IntNo =
Op.getConstantOperandVal(1);
17633 case Intrinsic::riscv_masked_atomicrmw_xchg_i64:
17634 case Intrinsic::riscv_masked_atomicrmw_add_i64:
17635 case Intrinsic::riscv_masked_atomicrmw_sub_i64:
17636 case Intrinsic::riscv_masked_atomicrmw_nand_i64:
17637 case Intrinsic::riscv_masked_atomicrmw_max_i64:
17638 case Intrinsic::riscv_masked_atomicrmw_min_i64:
17639 case Intrinsic::riscv_masked_atomicrmw_umax_i64:
17640 case Intrinsic::riscv_masked_atomicrmw_umin_i64:
17641 case Intrinsic::riscv_masked_cmpxchg_i64:
17649 assert(Subtarget.hasStdExtA());
17664 switch (
Op.getOpcode()) {
17670 return !
Op.getValueType().isInteger();
17678 assert(Ld &&
"Unexpected null LoadSDNode");
17686 auto *CNode = dyn_cast<ConstantPoolSDNode>(
Ptr);
17687 if (!CNode || CNode->isMachineConstantPoolEntry() ||
17688 CNode->getOffset() != 0)
17696 auto *CNode = GetSupportedConstantPool(
Ptr);
17697 if (!CNode || CNode->getTargetFlags() != 0)
17700 return CNode->getConstVal();
17708 auto *CNodeLo = GetSupportedConstantPool(
Ptr.getOperand(1));
17709 auto *CNodeHi = GetSupportedConstantPool(
Ptr.getOperand(0).getOperand(0));
17715 if (CNodeLo->getConstVal() != CNodeHi->getConstVal())
17718 return CNodeLo->getConstVal();
17723 assert(
MI.getOpcode() == RISCV::ReadCounterWide &&
"Unexpected instruction");
17755 Register ReadAgainReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
17758 int64_t LoCounter =
MI.getOperand(2).getImm();
17759 int64_t HiCounter =
MI.getOperand(3).getImm();
17769 BuildMI(LoopMBB,
DL,
TII->get(RISCV::CSRRS), ReadAgainReg)
17781 MI.eraseFromParent();
17789 assert(
MI.getOpcode() == RISCV::SplitF64Pseudo &&
"Unexpected instruction");
17797 Register SrcReg =
MI.getOperand(2).getReg();
17817 MI.eraseFromParent();
17824 assert(
MI.getOpcode() == RISCV::BuildPairF64Pseudo &&
17825 "Unexpected instruction");
17831 Register DstReg =
MI.getOperand(0).getReg();
17854 MI.eraseFromParent();
17859 switch (
MI.getOpcode()) {
17862 case RISCV::Select_GPR_Using_CC_GPR:
17863 case RISCV::Select_GPR_Using_CC_Imm:
17864 case RISCV::Select_FPR16_Using_CC_GPR:
17865 case RISCV::Select_FPR16INX_Using_CC_GPR:
17866 case RISCV::Select_FPR32_Using_CC_GPR:
17867 case RISCV::Select_FPR32INX_Using_CC_GPR:
17868 case RISCV::Select_FPR64_Using_CC_GPR:
17869 case RISCV::Select_FPR64INX_Using_CC_GPR:
17870 case RISCV::Select_FPR64IN32X_Using_CC_GPR:
17876 unsigned RelOpcode,
unsigned EqOpcode,
17879 Register DstReg =
MI.getOperand(0).getReg();
17880 Register Src1Reg =
MI.getOperand(1).getReg();
17881 Register Src2Reg =
MI.getOperand(2).getReg();
17883 Register SavedFFlags =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
17907 MI.eraseFromParent();
17958 F->insert(It, FirstMBB);
17959 F->insert(It, SecondMBB);
17960 F->insert(It, SinkMBB);
18009 First.eraseFromParent();
18048 if ((
MI.getOpcode() != RISCV::Select_GPR_Using_CC_GPR &&
18049 MI.getOpcode() != RISCV::Select_GPR_Using_CC_Imm) &&
18050 Next != BB->
end() && Next->getOpcode() ==
MI.getOpcode() &&
18051 Next->getOperand(5).getReg() ==
MI.getOperand(0).getReg() &&
18052 Next->getOperand(5).isKill())
18057 if (
MI.getOperand(2).isReg())
18058 RHS =
MI.getOperand(2).getReg();
18063 SelectDests.
insert(
MI.getOperand(0).getReg());
18067 SequenceMBBI != E; ++SequenceMBBI) {
18068 if (SequenceMBBI->isDebugInstr())
18071 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
18072 !SequenceMBBI->getOperand(2).isReg() ||
18073 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
18074 SequenceMBBI->getOperand(3).
getImm() !=
CC ||
18075 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
18076 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
18078 LastSelectPseudo = &*SequenceMBBI;
18080 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
18083 if (SequenceMBBI->hasUnmodeledSideEffects() ||
18084 SequenceMBBI->mayLoadOrStore() ||
18085 SequenceMBBI->usesCustomInsertionHook())
18088 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
18103 F->insert(
I, IfFalseMBB);
18104 F->insert(
I, TailMBB);
18107 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
18113 TailMBB->
push_back(DebugInstr->removeFromParent());
18117 TailMBB->
splice(TailMBB->
end(), HeadMBB,
18127 if (
MI.getOperand(2).isImm())
18130 .
addImm(
MI.getOperand(2).getImm())
18142 auto SelectMBBI =
MI.getIterator();
18143 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
18144 auto InsertionPoint = TailMBB->
begin();
18145 while (SelectMBBI != SelectEnd) {
18146 auto Next = std::next(SelectMBBI);
18149 BuildMI(*TailMBB, InsertionPoint, SelectMBBI->getDebugLoc(),
18150 TII.get(RISCV::PHI), SelectMBBI->getOperand(0).getReg())
18151 .
addReg(SelectMBBI->getOperand(4).getReg())
18153 .
addReg(SelectMBBI->getOperand(5).getReg())
18168 RISCVVInversePseudosTable::getBaseInfo(MCOpcode, LMul, SEW);
18169 assert(
Inverse &&
"Unexpected LMUL and SEW pair for instruction");
18171 RISCV::lookupMaskedIntrinsicByUnmasked(
Inverse->Pseudo);
18172 assert(
Masked &&
"Could not find masked instruction for LMUL and SEW pair");
18178 unsigned CVTXOpc) {
18184 Register SavedFFLAGS =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
18197 .
add(
MI.getOperand(1))
18198 .
add(
MI.getOperand(2))
18199 .
add(
MI.getOperand(3))
18201 .
add(
MI.getOperand(4))
18202 .
add(
MI.getOperand(5))
18203 .
add(
MI.getOperand(6))
18218 .
add(
MI.getOperand(0))
18219 .
add(
MI.getOperand(1))
18221 .
add(
MI.getOperand(3))
18223 .
add(
MI.getOperand(4))
18224 .
add(
MI.getOperand(5))
18225 .
add(
MI.getOperand(6))
18235 MI.eraseFromParent();
18241 unsigned CmpOpc, F2IOpc, I2FOpc, FSGNJOpc, FSGNJXOpc;
18243 switch (
MI.getOpcode()) {
18246 case RISCV::PseudoFROUND_H:
18247 CmpOpc = RISCV::FLT_H;
18248 F2IOpc = RISCV::FCVT_W_H;
18249 I2FOpc = RISCV::FCVT_H_W;
18250 FSGNJOpc = RISCV::FSGNJ_H;
18251 FSGNJXOpc = RISCV::FSGNJX_H;
18252 RC = &RISCV::FPR16RegClass;
18254 case RISCV::PseudoFROUND_H_INX:
18255 CmpOpc = RISCV::FLT_H_INX;
18256 F2IOpc = RISCV::FCVT_W_H_INX;
18257 I2FOpc = RISCV::FCVT_H_W_INX;
18258 FSGNJOpc = RISCV::FSGNJ_H_INX;
18259 FSGNJXOpc = RISCV::FSGNJX_H_INX;
18260 RC = &RISCV::GPRF16RegClass;
18262 case RISCV::PseudoFROUND_S:
18263 CmpOpc = RISCV::FLT_S;
18264 F2IOpc = RISCV::FCVT_W_S;
18265 I2FOpc = RISCV::FCVT_S_W;
18266 FSGNJOpc = RISCV::FSGNJ_S;
18267 FSGNJXOpc = RISCV::FSGNJX_S;
18268 RC = &RISCV::FPR32RegClass;
18270 case RISCV::PseudoFROUND_S_INX:
18271 CmpOpc = RISCV::FLT_S_INX;
18272 F2IOpc = RISCV::FCVT_W_S_INX;
18273 I2FOpc = RISCV::FCVT_S_W_INX;
18274 FSGNJOpc = RISCV::FSGNJ_S_INX;
18275 FSGNJXOpc = RISCV::FSGNJX_S_INX;
18276 RC = &RISCV::GPRF32RegClass;
18278 case RISCV::PseudoFROUND_D:
18280 CmpOpc = RISCV::FLT_D;
18281 F2IOpc = RISCV::FCVT_L_D;
18282 I2FOpc = RISCV::FCVT_D_L;
18283 FSGNJOpc = RISCV::FSGNJ_D;
18284 FSGNJXOpc = RISCV::FSGNJX_D;
18285 RC = &RISCV::FPR64RegClass;
18287 case RISCV::PseudoFROUND_D_INX:
18289 CmpOpc = RISCV::FLT_D_INX;
18290 F2IOpc = RISCV::FCVT_L_D_INX;
18291 I2FOpc = RISCV::FCVT_D_L_INX;
18292 FSGNJOpc = RISCV::FSGNJ_D_INX;
18293 FSGNJXOpc = RISCV::FSGNJX_D_INX;
18294 RC = &RISCV::GPRRegClass;
18306 F->insert(
I, CvtMBB);
18307 F->insert(
I, DoneMBB);
18318 Register DstReg =
MI.getOperand(0).getReg();
18319 Register SrcReg =
MI.getOperand(1).getReg();
18320 Register MaxReg =
MI.getOperand(2).getReg();
18321 int64_t FRM =
MI.getOperand(3).getImm();
18326 Register FabsReg =
MRI.createVirtualRegister(RC);
18330 Register CmpReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
18345 Register F2IReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
18367 MI.eraseFromParent();
18374 switch (
MI.getOpcode()) {
18377 case RISCV::ReadCounterWide:
18379 "ReadCounterWide is only to be used on riscv32");
18381 case RISCV::Select_GPR_Using_CC_GPR:
18382 case RISCV::Select_GPR_Using_CC_Imm:
18383 case RISCV::Select_FPR16_Using_CC_GPR:
18384 case RISCV::Select_FPR16INX_Using_CC_GPR:
18385 case RISCV::Select_FPR32_Using_CC_GPR:
18386 case RISCV::Select_FPR32INX_Using_CC_GPR:
18387 case RISCV::Select_FPR64_Using_CC_GPR:
18388 case RISCV::Select_FPR64INX_Using_CC_GPR:
18389 case RISCV::Select_FPR64IN32X_Using_CC_GPR:
18391 case RISCV::BuildPairF64Pseudo:
18393 case RISCV::SplitF64Pseudo:
18395 case RISCV::PseudoQuietFLE_H:
18397 case RISCV::PseudoQuietFLE_H_INX:
18398 return emitQuietFCMP(
MI, BB, RISCV::FLE_H_INX, RISCV::FEQ_H_INX, Subtarget);
18399 case RISCV::PseudoQuietFLT_H:
18401 case RISCV::PseudoQuietFLT_H_INX:
18402 return emitQuietFCMP(
MI, BB, RISCV::FLT_H_INX, RISCV::FEQ_H_INX, Subtarget);
18403 case RISCV::PseudoQuietFLE_S:
18405 case RISCV::PseudoQuietFLE_S_INX:
18406 return emitQuietFCMP(
MI, BB, RISCV::FLE_S_INX, RISCV::FEQ_S_INX, Subtarget);
18407 case RISCV::PseudoQuietFLT_S:
18409 case RISCV::PseudoQuietFLT_S_INX:
18410 return emitQuietFCMP(
MI, BB, RISCV::FLT_S_INX, RISCV::FEQ_S_INX, Subtarget);
18411 case RISCV::PseudoQuietFLE_D:
18413 case RISCV::PseudoQuietFLE_D_INX:
18414 return emitQuietFCMP(
MI, BB, RISCV::FLE_D_INX, RISCV::FEQ_D_INX, Subtarget);
18415 case RISCV::PseudoQuietFLE_D_IN32X:
18418 case RISCV::PseudoQuietFLT_D:
18420 case RISCV::PseudoQuietFLT_D_INX:
18421 return emitQuietFCMP(
MI, BB, RISCV::FLT_D_INX, RISCV::FEQ_D_INX, Subtarget);
18422 case RISCV::PseudoQuietFLT_D_IN32X:
18426 case RISCV::PseudoVFROUND_NOEXCEPT_V_M1_MASK:
18428 case RISCV::PseudoVFROUND_NOEXCEPT_V_M2_MASK:
18430 case RISCV::PseudoVFROUND_NOEXCEPT_V_M4_MASK:
18432 case RISCV::PseudoVFROUND_NOEXCEPT_V_M8_MASK:
18434 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF2_MASK:
18436 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF4_MASK:
18438 case RISCV::PseudoFROUND_H:
18439 case RISCV::PseudoFROUND_H_INX:
18440 case RISCV::PseudoFROUND_S:
18441 case RISCV::PseudoFROUND_S_INX:
18442 case RISCV::PseudoFROUND_D:
18443 case RISCV::PseudoFROUND_D_INX:
18444 case RISCV::PseudoFROUND_D_IN32X:
18446 case TargetOpcode::STATEPOINT:
18452 MI.addOperand(*
MI.getMF(),
18458 case TargetOpcode::STACKMAP:
18459 case TargetOpcode::PATCHPOINT:
18462 "supported on 64-bit targets");
18480 if (
MI.readsRegister(RISCV::FRM,
nullptr))
18512 RISCV::F10_H, RISCV::F11_H, RISCV::F12_H, RISCV::F13_H,
18513 RISCV::F14_H, RISCV::F15_H, RISCV::F16_H, RISCV::F17_H
18516 RISCV::F10_F, RISCV::F11_F, RISCV::F12_F, RISCV::F13_F,
18517 RISCV::F14_F, RISCV::F15_F, RISCV::F16_F, RISCV::F17_F
18520 RISCV::F10_D, RISCV::F11_D, RISCV::F12_D, RISCV::F13_D,
18521 RISCV::F14_D, RISCV::F15_D, RISCV::F16_D, RISCV::F17_D
18525 RISCV::V8, RISCV::V9, RISCV::V10, RISCV::V11, RISCV::V12, RISCV::V13,
18526 RISCV::V14, RISCV::V15, RISCV::V16, RISCV::V17, RISCV::V18, RISCV::V19,
18527 RISCV::V20, RISCV::V21, RISCV::V22, RISCV::V23};
18529 RISCV::V14M2, RISCV::V16M2, RISCV::V18M2,
18530 RISCV::V20M2, RISCV::V22M2};
18538 static const MCPhysReg ArgIGPRs[] = {RISCV::X10, RISCV::X11, RISCV::X12,
18539 RISCV::X13, RISCV::X14, RISCV::X15,
18540 RISCV::X16, RISCV::X17};
18542 static const MCPhysReg ArgEGPRs[] = {RISCV::X10, RISCV::X11, RISCV::X12,
18543 RISCV::X13, RISCV::X14, RISCV::X15};
18555 static const MCPhysReg FastCCIGPRs[] = {
18556 RISCV::X10, RISCV::X11, RISCV::X12, RISCV::X13, RISCV::X14, RISCV::X15,
18557 RISCV::X16, RISCV::X17, RISCV::X28, RISCV::X29, RISCV::X30, RISCV::X31};
18560 static const MCPhysReg FastCCEGPRs[] = {RISCV::X10, RISCV::X11, RISCV::X12,
18561 RISCV::X13, RISCV::X14, RISCV::X15};
18575 unsigned XLenInBytes = XLen / 8;
18588 Align StackAlign(XLenInBytes);
18589 if (!
EABI || XLen != 32)
18621 unsigned XLen =
DL.getLargestLegalIntTypeSizeInBits();
18622 assert(XLen == 32 || XLen == 64);
18623 MVT XLenVT = XLen == 32 ? MVT::i32 : MVT::i64;
18627 if (ArgFlags.
isNest()) {
18628 if (
unsigned Reg = State.
AllocateReg(RISCV::X7)) {
18636 if (!LocVT.
isVector() && IsRet && ValNo > 1)
18641 bool UseGPRForF16_F32 =
true;
18644 bool UseGPRForF64 =
true;
18656 UseGPRForF16_F32 = !IsFixed;
18660 UseGPRForF16_F32 = !IsFixed;
18661 UseGPRForF64 = !IsFixed;
18667 UseGPRForF16_F32 =
true;
18668 UseGPRForF64 =
true;
18675 if (UseGPRForF16_F32 &&
18676 (ValVT == MVT::f16 || ValVT == MVT::bf16 || ValVT == MVT::f32)) {
18679 }
else if (UseGPRForF64 && XLen == 64 && ValVT == MVT::f64) {
18696 unsigned TwoXLenInBytes = (2 * XLen) / 8;
18698 DL.getTypeAllocSize(OrigTy) == TwoXLenInBytes &&
18702 if (RegIdx != std::size(
ArgGPRs) && RegIdx % 2 == 1)
18711 "PendingLocs and PendingArgFlags out of sync");
18715 if (UseGPRForF64 && XLen == 32 && ValVT == MVT::f64) {
18716 assert(PendingLocs.
empty() &&
"Can't lower f64 if it is split");
18764 PendingLocs.
size() <= 2) {
18765 assert(PendingLocs.
size() == 2 &&
"Unexpected PendingLocs.size()");
18770 PendingLocs.
clear();
18771 PendingArgFlags.
clear();
18773 XLen, State, VA, AF, ValNo, ValVT, LocVT, ArgFlags,
18779 unsigned StoreSizeBytes = XLen / 8;
18782 if ((ValVT == MVT::f16 || ValVT == MVT::bf16) && !UseGPRForF16_F32)
18784 else if (ValVT == MVT::f32 && !UseGPRForF16_F32)
18786 else if (ValVT == MVT::f64 && !UseGPRForF64)
18822 if (!PendingLocs.
empty()) {
18824 assert(PendingLocs.
size() > 2 &&
"Unexpected PendingLocs.size()");
18826 for (
auto &It : PendingLocs) {
18828 It.convertToReg(Reg);
18833 PendingLocs.clear();
18834 PendingArgFlags.
clear();
18838 assert((!UseGPRForF16_F32 || !UseGPRForF64 || LocVT == XLenVT ||
18840 "Expected an XLenVT or vector types at this stage");
18858template <
typename ArgTy>
18860 for (
const auto &ArgIdx :
enumerate(Args)) {
18861 MVT ArgVT = ArgIdx.value().VT;
18863 return ArgIdx.index();
18865 return std::nullopt;
18868void RISCVTargetLowering::analyzeInputArgs(
18871 RISCVCCAssignFn Fn)
const {
18872 unsigned NumArgs =
Ins.size();
18885 for (
unsigned i = 0; i != NumArgs; ++i) {
18889 Type *ArgTy =
nullptr;
18891 ArgTy = FType->getReturnType();
18892 else if (Ins[i].isOrigArg())
18893 ArgTy = FType->getParamType(Ins[i].getOrigArgIndex());
18897 ArgFlags, CCInfo,
true, IsRet, ArgTy, *
this,
18899 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type "
18906void RISCVTargetLowering::analyzeOutputArgs(
18909 CallLoweringInfo *CLI, RISCVCCAssignFn Fn)
const {
18910 unsigned NumArgs = Outs.
size();
18920 for (
unsigned i = 0; i != NumArgs; i++) {
18921 MVT ArgVT = Outs[i].VT;
18923 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
18927 ArgFlags, CCInfo, Outs[i].IsFixed, IsRet, OrigTy, *
this,
18929 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type "
18978 if (In.isOrigArg()) {
18983 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
18984 (
BitWidth < 32 && In.Flags.isZExt())) {
19013 }
else if (LocVT == MVT::i64 && VA.
getValVT() == MVT::f32) {
19054 ExtType,
DL, LocVT, Chain, FIN,
19071 Register LoVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
19084 Register HiVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
19094 unsigned ValNo,
MVT ValVT,
MVT LocVT,
19097 bool IsFixed,
bool IsRet,
Type *OrigTy,
19100 if (LocVT == MVT::i32 || LocVT == MVT::i64) {
19109 if (LocVT == MVT::f16 &&
19110 (Subtarget.hasStdExtZfh() || Subtarget.hasStdExtZfhmin())) {
19112 RISCV::F10_H, RISCV::F11_H, RISCV::F12_H, RISCV::F13_H, RISCV::F14_H,
19113 RISCV::F15_H, RISCV::F16_H, RISCV::F17_H, RISCV::F0_H, RISCV::F1_H,
19114 RISCV::F2_H, RISCV::F3_H, RISCV::F4_H, RISCV::F5_H, RISCV::F6_H,
19115 RISCV::F7_H, RISCV::F28_H, RISCV::F29_H, RISCV::F30_H, RISCV::F31_H};
19116 if (
unsigned Reg = State.
AllocateReg(FPR16List)) {
19122 if (LocVT == MVT::f32 && Subtarget.hasStdExtF()) {
19124 RISCV::F10_F, RISCV::F11_F, RISCV::F12_F, RISCV::F13_F, RISCV::F14_F,
19125 RISCV::F15_F, RISCV::F16_F, RISCV::F17_F, RISCV::F0_F, RISCV::F1_F,
19126 RISCV::F2_F, RISCV::F3_F, RISCV::F4_F, RISCV::F5_F, RISCV::F6_F,
19127 RISCV::F7_F, RISCV::F28_F, RISCV::F29_F, RISCV::F30_F, RISCV::F31_F};
19128 if (
unsigned Reg = State.
AllocateReg(FPR32List)) {
19134 if (LocVT == MVT::f64 && Subtarget.hasStdExtD()) {
19136 RISCV::F10_D, RISCV::F11_D, RISCV::F12_D, RISCV::F13_D, RISCV::F14_D,
19137 RISCV::F15_D, RISCV::F16_D, RISCV::F17_D, RISCV::F0_D, RISCV::F1_D,
19138 RISCV::F2_D, RISCV::F3_D, RISCV::F4_D, RISCV::F5_D, RISCV::F6_D,
19139 RISCV::F7_D, RISCV::F28_D, RISCV::F29_D, RISCV::F30_D, RISCV::F31_D};
19140 if (
unsigned Reg = State.
AllocateReg(FPR64List)) {
19147 if ((LocVT == MVT::f16 &&
19148 (Subtarget.hasStdExtZhinx() || Subtarget.hasStdExtZhinxmin())) ||
19149 (LocVT == MVT::f32 && Subtarget.hasStdExtZfinx()) ||
19150 (LocVT == MVT::f64 && Subtarget.
is64Bit() &&
19151 Subtarget.hasStdExtZdinx())) {
19158 if (LocVT == MVT::f16) {
19164 if (LocVT == MVT::i32 || LocVT == MVT::f32) {
19170 if (LocVT == MVT::i64 || LocVT == MVT::f64) {
19178 if (AllocatedVReg) {
19213 if (ArgFlags.
isNest()) {
19215 "Attribute 'nest' is not supported in GHC calling convention");
19219 RISCV::X9, RISCV::X18, RISCV::X19, RISCV::X20, RISCV::X21, RISCV::X22,
19220 RISCV::X23, RISCV::X24, RISCV::X25, RISCV::X26, RISCV::X27};
19222 if (LocVT == MVT::i32 || LocVT == MVT::i64) {
19234 if (LocVT == MVT::f32 && Subtarget.hasStdExtF()) {
19237 static const MCPhysReg FPR32List[] = {RISCV::F8_F, RISCV::F9_F,
19238 RISCV::F18_F, RISCV::F19_F,
19239 RISCV::F20_F, RISCV::F21_F};
19240 if (
unsigned Reg = State.
AllocateReg(FPR32List)) {
19246 if (LocVT == MVT::f64 && Subtarget.hasStdExtD()) {
19249 static const MCPhysReg FPR64List[] = {RISCV::F22_D, RISCV::F23_D,
19250 RISCV::F24_D, RISCV::F25_D,
19251 RISCV::F26_D, RISCV::F27_D};
19252 if (
unsigned Reg = State.
AllocateReg(FPR64List)) {
19258 if ((LocVT == MVT::f32 && Subtarget.hasStdExtZfinx()) ||
19259 (LocVT == MVT::f64 && Subtarget.hasStdExtZdinx() &&
19279 switch (CallConv) {
19289 if (Subtarget.hasStdExtE())
19293 "(Zdinx/D) instruction set extensions");
19297 if (Func.hasFnAttribute(
"interrupt")) {
19298 if (!Func.arg_empty())
19300 "Functions with the interrupt attribute cannot have arguments!");
19305 if (!(Kind ==
"user" || Kind ==
"supervisor" || Kind ==
"machine"))
19307 "Function interrupt attribute argument not supported!");
19312 unsigned XLenInBytes = Subtarget.
getXLen() / 8;
19314 std::vector<SDValue> OutChains;
19323 analyzeInputArgs(MF, CCInfo, Ins,
false,
19327 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
19348 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
19349 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
19351 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
19353 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
19382 int VarArgsSaveSize = XLenInBytes * (ArgRegs.
size() -
Idx);
19387 if (VarArgsSaveSize == 0) {
19391 int VaArgOffset = -VarArgsSaveSize;
19399 XLenInBytes, VaArgOffset -
static_cast<int>(XLenInBytes),
true);
19400 VarArgsSaveSize += XLenInBytes;
19407 for (
unsigned I =
Idx;
I < ArgRegs.
size(); ++
I) {
19412 Chain,
DL, ArgValue, FIN,
19414 OutChains.push_back(Store);
19428 if (!OutChains.empty()) {
19429 OutChains.push_back(Chain);
19439bool RISCVTargetLowering::isEligibleForTailCallOptimization(
19443 auto CalleeCC = CLI.CallConv;
19444 auto &Outs = CLI.Outs;
19446 auto CallerCC = Caller.getCallingConv();
19453 if (Caller.hasFnAttribute(
"interrupt"))
19468 for (
auto &VA : ArgLocs)
19474 auto IsCallerStructRet = Caller.hasStructRetAttr();
19475 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
19476 if (IsCallerStructRet || IsCalleeStructRet)
19481 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
19482 if (CalleeCC != CallerCC) {
19483 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
19484 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
19491 for (
auto &Arg : Outs)
19492 if (Arg.Flags.isByVal())
19527 if (Subtarget.hasStdExtE())
19531 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
19537 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
19543 "site marked musttail");
19550 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
19552 if (!Flags.isByVal())
19556 unsigned Size = Flags.getByValSize();
19557 Align Alignment = Flags.getNonZeroByValAlign();
19564 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
19566 false,
nullptr, IsTailCall,
19578 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
19581 SDValue ArgValue = OutVals[OutIdx];
19601 if (!StackPtr.getNode())
19612 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
19630 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
19631 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
19637 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
19638 SDValue PartValue = OutVals[OutIdx + 1];
19639 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
19651 int FI = cast<FrameIndexSDNode>(SpillSlot)->getIndex();
19653 DAG.
getStore(Chain,
DL, ArgValue, SpillSlot,
19655 for (
const auto &Part : Parts) {
19656 SDValue PartValue = Part.first;
19657 SDValue PartOffset = Part.second;
19664 ArgValue = SpillSlot;
19670 if (Flags.isByVal())
19671 ArgValue = ByValArgs[j++];
19678 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
19679 "for passing parameters");
19682 if (!StackPtr.getNode())
19695 if (!MemOpChains.
empty())
19701 for (
auto &Reg : RegsToPass) {
19702 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
19709 validateCCReservedRegs(RegsToPass, MF);
19714 "Return address register required, but has been reserved."});
19733 for (
auto &Reg : RegsToPass)
19739 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
19740 assert(Mask &&
"Missing call preserved mask for calling convention");
19749 "Unexpected CFI type for a direct call");
19779 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
19780 auto &VA = RVLocs[i];
19788 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
19789 assert(VA.needsCustom());
19810 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
19814 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
19815 MVT VT = Outs[i].VT;
19819 ArgFlags, CCInfo,
true,
true,
19820 nullptr, *
this, Dispatcher))
19852 for (
unsigned i = 0, e = RVLocs.size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
19853 SDValue Val = OutVals[OutIdx];
19862 DAG.
getVTList(MVT::i32, MVT::i32), Val);
19866 Register RegHi = RVLocs[++i].getLocReg();
19872 "Return value register required, but has been reserved."});
19888 "Return value register required, but has been reserved."});
19910 if (Func.hasFnAttribute(
"interrupt")) {
19911 if (!Func.getReturnType()->isVoidTy())
19913 "Functions with the interrupt attribute must have void return type!");
19919 if (Kind ==
"supervisor")
19925 return DAG.
getNode(RetOpc,
DL, MVT::Other, RetOps);
19928void RISCVTargetLowering::validateCCReservedRegs(
19929 const SmallVectorImpl<std::pair<llvm::Register, llvm::SDValue>> &Regs,
19938 F,
"Argument register required, but has been reserved."});
19944 if (
N->getNumValues() != 1)
19946 if (!
N->hasNUsesOfValue(1, 0))
19949 SDNode *Copy = *
N->use_begin();
19963 if (Copy->getOperand(Copy->getNumOperands() - 1).getValueType() == MVT::Glue)
19967 bool HasRet =
false;
19968 for (
SDNode *Node : Copy->uses()) {
19976 Chain = Copy->getOperand(0);
19985#define NODE_NAME_CASE(NODE) \
19986 case RISCVISD::NODE: \
19987 return "RISCVISD::" #NODE;
20246#undef NODE_NAME_CASE
20253 if (Constraint.
size() == 1) {
20254 switch (Constraint[0]) {
20270 if (Constraint ==
"vr" || Constraint ==
"vm")
20276std::pair<unsigned, const TargetRegisterClass *>
20282 if (Constraint.
size() == 1) {
20283 switch (Constraint[0]) {
20288 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
20289 return std::make_pair(0U, &RISCV::GPRF16RegClass);
20290 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
20291 return std::make_pair(0U, &RISCV::GPRF32RegClass);
20292 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
20293 return std::make_pair(0U, &RISCV::GPRPairRegClass);
20294 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
20296 if (Subtarget.hasStdExtZfhmin() && VT == MVT::f16)
20297 return std::make_pair(0U, &RISCV::FPR16RegClass);
20298 if (Subtarget.hasStdExtF() && VT == MVT::f32)
20299 return std::make_pair(0U, &RISCV::FPR32RegClass);
20300 if (Subtarget.hasStdExtD() && VT == MVT::f64)
20301 return std::make_pair(0U, &RISCV::FPR64RegClass);
20306 }
else if (Constraint ==
"vr") {
20307 for (
const auto *RC : {&RISCV::VRRegClass, &RISCV::VRM2RegClass,
20308 &RISCV::VRM4RegClass, &RISCV::VRM8RegClass}) {
20310 return std::make_pair(0U, RC);
20312 }
else if (Constraint ==
"vm") {
20313 if (
TRI->isTypeLegalForClass(RISCV::VMV0RegClass, VT.
SimpleTy))
20314 return std::make_pair(0U, &RISCV::VMV0RegClass);
20322 .
Case(
"{zero}", RISCV::X0)
20323 .
Case(
"{ra}", RISCV::X1)
20324 .
Case(
"{sp}", RISCV::X2)
20325 .
Case(
"{gp}", RISCV::X3)
20326 .
Case(
"{tp}", RISCV::X4)
20327 .
Case(
"{t0}", RISCV::X5)
20328 .
Case(
"{t1}", RISCV::X6)
20329 .
Case(
"{t2}", RISCV::X7)
20330 .
Cases(
"{s0}",
"{fp}", RISCV::X8)
20331 .
Case(
"{s1}", RISCV::X9)
20332 .
Case(
"{a0}", RISCV::X10)
20333 .
Case(
"{a1}", RISCV::X11)
20334 .
Case(
"{a2}", RISCV::X12)
20335 .
Case(
"{a3}", RISCV::X13)
20336 .
Case(
"{a4}", RISCV::X14)
20337 .
Case(
"{a5}", RISCV::X15)
20338 .
Case(
"{a6}", RISCV::X16)
20339 .
Case(
"{a7}", RISCV::X17)
20340 .
Case(
"{s2}", RISCV::X18)
20341 .
Case(
"{s3}", RISCV::X19)
20342 .
Case(
"{s4}", RISCV::X20)
20343 .
Case(
"{s5}", RISCV::X21)
20344 .
Case(
"{s6}", RISCV::X22)
20345 .
Case(
"{s7}", RISCV::X23)
20346 .
Case(
"{s8}", RISCV::X24)
20347 .
Case(
"{s9}", RISCV::X25)
20348 .
Case(
"{s10}", RISCV::X26)
20349 .
Case(
"{s11}", RISCV::X27)
20350 .
Case(
"{t3}", RISCV::X28)
20351 .
Case(
"{t4}", RISCV::X29)
20352 .
Case(
"{t5}", RISCV::X30)
20353 .
Case(
"{t6}", RISCV::X31)
20355 if (XRegFromAlias != RISCV::NoRegister)
20356 return std::make_pair(XRegFromAlias, &RISCV::GPRRegClass);
20365 if (Subtarget.hasStdExtF()) {
20367 .
Cases(
"{f0}",
"{ft0}", RISCV::F0_F)
20368 .
Cases(
"{f1}",
"{ft1}", RISCV::F1_F)
20369 .
Cases(
"{f2}",
"{ft2}", RISCV::F2_F)
20370 .
Cases(
"{f3}",
"{ft3}", RISCV::F3_F)
20371 .
Cases(
"{f4}",
"{ft4}", RISCV::F4_F)
20372 .
Cases(
"{f5}",
"{ft5}", RISCV::F5_F)
20373 .
Cases(
"{f6}",
"{ft6}", RISCV::F6_F)
20374 .
Cases(
"{f7}",
"{ft7}", RISCV::F7_F)
20375 .
Cases(
"{f8}",
"{fs0}", RISCV::F8_F)
20376 .
Cases(
"{f9}",
"{fs1}", RISCV::F9_F)
20377 .
Cases(
"{f10}",
"{fa0}", RISCV::F10_F)
20378 .
Cases(
"{f11}",
"{fa1}", RISCV::F11_F)
20379 .
Cases(
"{f12}",
"{fa2}", RISCV::F12_F)
20380 .
Cases(
"{f13}",
"{fa3}", RISCV::F13_F)
20381 .
Cases(
"{f14}",
"{fa4}", RISCV::F14_F)
20382 .
Cases(
"{f15}",
"{fa5}", RISCV::F15_F)
20383 .
Cases(
"{f16}",
"{fa6}", RISCV::F16_F)
20384 .
Cases(
"{f17}",
"{fa7}", RISCV::F17_F)
20385 .
Cases(
"{f18}",
"{fs2}", RISCV::F18_F)
20386 .
Cases(
"{f19}",
"{fs3}", RISCV::F19_F)
20387 .
Cases(
"{f20}",
"{fs4}", RISCV::F20_F)
20388 .
Cases(
"{f21}",
"{fs5}", RISCV::F21_F)
20389 .
Cases(
"{f22}",
"{fs6}", RISCV::F22_F)
20390 .
Cases(
"{f23}",
"{fs7}", RISCV::F23_F)
20391 .
Cases(
"{f24}",
"{fs8}", RISCV::F24_F)
20392 .
Cases(
"{f25}",
"{fs9}", RISCV::F25_F)
20393 .
Cases(
"{f26}",
"{fs10}", RISCV::F26_F)
20394 .
Cases(
"{f27}",
"{fs11}", RISCV::F27_F)
20395 .
Cases(
"{f28}",
"{ft8}", RISCV::F28_F)
20396 .
Cases(
"{f29}",
"{ft9}", RISCV::F29_F)
20397 .
Cases(
"{f30}",
"{ft10}", RISCV::F30_F)
20398 .
Cases(
"{f31}",
"{ft11}", RISCV::F31_F)
20400 if (FReg != RISCV::NoRegister) {
20401 assert(RISCV::F0_F <= FReg && FReg <= RISCV::F31_F &&
"Unknown fp-reg");
20402 if (Subtarget.hasStdExtD() && (VT == MVT::f64 || VT == MVT::Other)) {
20403 unsigned RegNo = FReg - RISCV::F0_F;
20404 unsigned DReg = RISCV::F0_D + RegNo;
20405 return std::make_pair(DReg, &RISCV::FPR64RegClass);
20407 if (VT == MVT::f32 || VT == MVT::Other)
20408 return std::make_pair(FReg, &RISCV::FPR32RegClass);
20409 if (Subtarget.hasStdExtZfhmin() && VT == MVT::f16) {
20410 unsigned RegNo = FReg - RISCV::F0_F;
20411 unsigned HReg = RISCV::F0_H + RegNo;
20412 return std::make_pair(HReg, &RISCV::FPR16RegClass);
20419 .
Case(
"{v0}", RISCV::V0)
20420 .
Case(
"{v1}", RISCV::V1)
20421 .
Case(
"{v2}", RISCV::V2)
20422 .
Case(
"{v3}", RISCV::V3)
20423 .
Case(
"{v4}", RISCV::V4)
20424 .
Case(
"{v5}", RISCV::V5)
20425 .
Case(
"{v6}", RISCV::V6)
20426 .
Case(
"{v7}", RISCV::V7)
20427 .
Case(
"{v8}", RISCV::V8)
20428 .
Case(
"{v9}", RISCV::V9)
20429 .
Case(
"{v10}", RISCV::V10)
20430 .
Case(
"{v11}", RISCV::V11)
20431 .
Case(
"{v12}", RISCV::V12)
20432 .
Case(
"{v13}", RISCV::V13)
20433 .
Case(
"{v14}", RISCV::V14)
20434 .
Case(
"{v15}", RISCV::V15)
20435 .
Case(
"{v16}", RISCV::V16)
20436 .
Case(
"{v17}", RISCV::V17)
20437 .
Case(
"{v18}", RISCV::V18)
20438 .
Case(
"{v19}", RISCV::V19)
20439 .
Case(
"{v20}", RISCV::V20)
20440 .
Case(
"{v21}", RISCV::V21)
20441 .
Case(
"{v22}", RISCV::V22)
20442 .
Case(
"{v23}", RISCV::V23)
20443 .
Case(
"{v24}", RISCV::V24)
20444 .
Case(
"{v25}", RISCV::V25)
20445 .
Case(
"{v26}", RISCV::V26)
20446 .
Case(
"{v27}", RISCV::V27)
20447 .
Case(
"{v28}", RISCV::V28)
20448 .
Case(
"{v29}", RISCV::V29)
20449 .
Case(
"{v30}", RISCV::V30)
20450 .
Case(
"{v31}", RISCV::V31)
20452 if (VReg != RISCV::NoRegister) {
20453 if (
TRI->isTypeLegalForClass(RISCV::VMRegClass, VT.
SimpleTy))
20454 return std::make_pair(VReg, &RISCV::VMRegClass);
20455 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, VT.
SimpleTy))
20456 return std::make_pair(VReg, &RISCV::VRRegClass);
20457 for (
const auto *RC :
20458 {&RISCV::VRM2RegClass, &RISCV::VRM4RegClass, &RISCV::VRM8RegClass}) {
20459 if (
TRI->isTypeLegalForClass(*RC, VT.
SimpleTy)) {
20460 VReg =
TRI->getMatchingSuperReg(VReg, RISCV::sub_vrm1_0, RC);
20461 return std::make_pair(VReg, RC);
20467 std::pair<Register, const TargetRegisterClass *> Res =
20473 if (Res.second == &RISCV::GPRF16RegClass ||
20474 Res.second == &RISCV::GPRF32RegClass ||
20475 Res.second == &RISCV::GPRPairRegClass)
20476 return std::make_pair(Res.first, &RISCV::GPRRegClass);
20484 if (ConstraintCode.
size() == 1) {
20485 switch (ConstraintCode[0]) {
20500 if (Constraint.
size() == 1) {
20501 switch (Constraint[0]) {
20504 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
20506 if (isInt<12>(CVal))
20519 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
20521 if (isUInt<5>(CVal))
20539 if (Subtarget.hasStdExtZtso()) {
20555 if (Subtarget.hasStdExtZtso()) {
20563 if (Subtarget.enableTrailingSeqCstFence() && isa<StoreInst>(Inst) &&
20580 if (Subtarget.hasForcedAtomics())
20585 if (Subtarget.hasStdExtZacas() &&
20586 (
Size >= 32 || Subtarget.hasStdExtZabha()))
20592 if (
Size < 32 && !Subtarget.hasStdExtZabha())
20605 return Intrinsic::riscv_masked_atomicrmw_xchg_i32;
20607 return Intrinsic::riscv_masked_atomicrmw_add_i32;
20609 return Intrinsic::riscv_masked_atomicrmw_sub_i32;
20611 return Intrinsic::riscv_masked_atomicrmw_nand_i32;
20613 return Intrinsic::riscv_masked_atomicrmw_max_i32;
20615 return Intrinsic::riscv_masked_atomicrmw_min_i32;
20617 return Intrinsic::riscv_masked_atomicrmw_umax_i32;
20619 return Intrinsic::riscv_masked_atomicrmw_umin_i32;
20628 return Intrinsic::riscv_masked_atomicrmw_xchg_i64;
20630 return Intrinsic::riscv_masked_atomicrmw_add_i64;
20632 return Intrinsic::riscv_masked_atomicrmw_sub_i64;
20634 return Intrinsic::riscv_masked_atomicrmw_nand_i64;
20636 return Intrinsic::riscv_masked_atomicrmw_max_i64;
20638 return Intrinsic::riscv_masked_atomicrmw_min_i64;
20640 return Intrinsic::riscv_masked_atomicrmw_umax_i64;
20642 return Intrinsic::riscv_masked_atomicrmw_umin_i64;
20668 unsigned XLen = Subtarget.
getXLen();
20692 unsigned ValWidth =
20697 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
20700 Builder.
CreateCall(LrwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
20712 if (Subtarget.hasForcedAtomics())
20716 if (!(Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas()) &&
20725 unsigned XLen = Subtarget.
getXLen();
20727 Intrinsic::ID CmpXchgIntrID = Intrinsic::riscv_masked_cmpxchg_i32;
20732 CmpXchgIntrID = Intrinsic::riscv_masked_cmpxchg_i64;
20738 MaskedCmpXchg, {AlignedAddr, CmpVal, NewVal, Mask, Ordering});
20745 EVT DataVT)
const {
20761 return Subtarget.hasStdExtZfhmin();
20763 return Subtarget.hasStdExtF();
20765 return Subtarget.hasStdExtD();
20797 "RVVBitsPerBlock changed, audit needed");
20806 if (!Subtarget.hasVendorXTHeadMemIdx())
20812 Base =
Op->getOperand(0);
20814 int64_t RHSC =
RHS->getSExtValue();
20820 bool isLegalIndexedOffset =
false;
20821 for (
unsigned i = 0; i < 4; i++)
20822 if (isInt<5>(RHSC >> i) && ((RHSC % (1LL << i)) == 0)) {
20823 isLegalIndexedOffset =
true;
20827 if (!isLegalIndexedOffset)
20844 VT = LD->getMemoryVT();
20845 Ptr = LD->getBasePtr();
20846 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
20847 VT = ST->getMemoryVT();
20848 Ptr = ST->getBasePtr();
20864 if (Subtarget.hasVendorXCVmem() && !Subtarget.
is64Bit()) {
20869 Base = LS->getBasePtr();
20873 if (
Base ==
Op->getOperand(0))
20875 else if (
Base ==
Op->getOperand(1))
20887 VT = LD->getMemoryVT();
20888 Ptr = LD->getBasePtr();
20889 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
20890 VT = ST->getMemoryVT();
20891 Ptr = ST->getBasePtr();
20934 const Constant *PersonalityFn)
const {
20939 const Constant *PersonalityFn)
const {
20968 const bool HasZmmul = Subtarget.hasStdExtZmmul();
20972 auto *ConstNode = cast<ConstantSDNode>(
C);
20973 const APInt &Imm = ConstNode->getAPIntValue();
20976 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
20977 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
20981 if (Subtarget.hasStdExtZba() && !Imm.isSignedIntN(12) &&
20982 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
20983 (Imm - 8).isPowerOf2()))
20988 if (!Imm.isSignedIntN(12) && Imm.countr_zero() < 12 &&
20989 ConstNode->hasOneUse()) {
20990 APInt ImmS = Imm.ashr(Imm.countr_zero());
20991 if ((ImmS + 1).isPowerOf2() || (ImmS - 1).isPowerOf2() ||
20992 (1 - ImmS).isPowerOf2())
21015 if (C1.
isSignedIntN(12) && !(C1 * C2).isSignedIntN(12))
21024 unsigned *
Fast)
const {
21027 *
Fast = Subtarget.enableUnalignedScalarMem();
21028 return Subtarget.enableUnalignedScalarMem();
21044 *
Fast = Subtarget.enableUnalignedVectorMem();
21045 return Subtarget.enableUnalignedVectorMem();
21054 if (FuncAttributes.
hasFnAttr(Attribute::NoImplicitFloat))
21066 if (
Op.size() < MinVLenInBytes)
21081 MVT PreferredVT = (
Op.isMemset() && !
Op.isZeroMemset()) ? MVT::i8 : ELenVT;
21085 if (PreferredVT != MVT::i8 && !Subtarget.enableUnalignedVectorMem()) {
21087 if (
Op.isFixedDstAlign())
21088 RequiredAlign = std::min(RequiredAlign,
Op.getDstAlign());
21090 RequiredAlign = std::min(RequiredAlign,
Op.getSrcAlign());
21098 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID>
CC)
const {
21099 bool IsABIRegCopy =
CC.has_value();
21101 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
21102 PartVT == MVT::f32) {
21120 if (PartVTBitSize % ValueVTBitSize == 0) {
21121 assert(PartVTBitSize >= ValueVTBitSize);
21128 if (ValueEltVT != PartEltVT) {
21129 if (PartVTBitSize > ValueVTBitSize) {
21131 assert(Count != 0 &&
"The number of element should not be zero.");
21132 EVT SameEltTypeVT =
21153 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID>
CC)
const {
21154 bool IsABIRegCopy =
CC.has_value();
21155 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
21156 PartVT == MVT::f32) {
21173 if (PartVTBitSize % ValueVTBitSize == 0) {
21174 assert(PartVTBitSize >= ValueVTBitSize);
21175 EVT SameEltTypeVT = ValueVT;
21182 if (ValueEltVT != PartEltVT) {
21184 assert(Count != 0 &&
"The number of element should not be zero.");
21201 bool OptSize = Attr.
hasFnAttr(Attribute::MinSize);
21208 unsigned Opc =
N->getOpcode();
21238 VectorType *VTy,
unsigned Factor,
Align Alignment,
unsigned AddrSpace,
21252 if (
auto *FVTy = dyn_cast<FixedVectorType>(VTy)) {
21257 if (FVTy->getNumElements() < 2)
21272 return Factor * LMUL <= 8;
21276 Align Alignment)
const {
21288 if (!Subtarget.enableUnalignedVectorMem() &&
21296 Intrinsic::riscv_seg2_load, Intrinsic::riscv_seg3_load,
21297 Intrinsic::riscv_seg4_load, Intrinsic::riscv_seg5_load,
21298 Intrinsic::riscv_seg6_load, Intrinsic::riscv_seg7_load,
21299 Intrinsic::riscv_seg8_load};
21318 auto *VTy = cast<FixedVectorType>(Shuffles[0]->
getType());
21328 {VTy, LI->getPointerOperandType(), XLenTy});
21330 Value *VL = ConstantInt::get(XLenTy, VTy->getNumElements());
21335 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
21337 Shuffles[i]->replaceAllUsesWith(SubVec);
21344 Intrinsic::riscv_seg2_store, Intrinsic::riscv_seg3_store,
21345 Intrinsic::riscv_seg4_store, Intrinsic::riscv_seg5_store,
21346 Intrinsic::riscv_seg6_store, Intrinsic::riscv_seg7_store,
21347 Intrinsic::riscv_seg8_store};
21367 unsigned Factor)
const {
21369 auto *ShuffleVTy = cast<FixedVectorType>(SVI->
getType());
21372 ShuffleVTy->getNumElements() / Factor);
21374 SI->getPointerAddressSpace(),
21375 SI->getDataLayout()))
21382 {VTy, SI->getPointerOperandType(), XLenTy});
21387 for (
unsigned i = 0; i < Factor; i++) {
21396 Value *VL = ConstantInt::get(XLenTy, VTy->getNumElements());
21397 Ops.
append({SI->getPointerOperand(), VL});
21414 unsigned Factor = 2;
21429 if (
auto *FVTy = dyn_cast<FixedVectorType>(VTy)) {
21432 {ResVTy, LI->getPointerOperandType(), XLenTy});
21433 VL = ConstantInt::get(XLenTy, FVTy->getNumElements());
21436 Intrinsic::riscv_vlseg2, Intrinsic::riscv_vlseg3,
21437 Intrinsic::riscv_vlseg4, Intrinsic::riscv_vlseg5,
21438 Intrinsic::riscv_vlseg6, Intrinsic::riscv_vlseg7,
21439 Intrinsic::riscv_vlseg8};
21462 if (
II->getIntrinsicID() != Intrinsic::vector_interleave2)
21465 unsigned Factor = 2;
21468 VectorType *InVTy = cast<VectorType>(
II->getOperand(0)->getType());
21471 SI->getPointerAddressSpace(),
21472 SI->getDataLayout()))
21479 if (
auto *FVTy = dyn_cast<FixedVectorType>(VTy)) {
21482 {InVTy, SI->getPointerOperandType(), XLenTy});
21483 VL = ConstantInt::get(XLenTy, FVTy->getNumElements());
21486 Intrinsic::riscv_vsseg2, Intrinsic::riscv_vsseg3,
21487 Intrinsic::riscv_vsseg4, Intrinsic::riscv_vsseg5,
21488 Intrinsic::riscv_vsseg6, Intrinsic::riscv_vsseg7,
21489 Intrinsic::riscv_vsseg8};
21496 Builder.
CreateCall(VssegNFunc, {
II->getOperand(0),
II->getOperand(1),
21497 SI->getPointerOperand(), VL});
21507 "Invalid call instruction for a KCFI check");
21509 MBBI->getOpcode()));
21512 Target.setIsRenamable(
false);
21520#define GET_REGISTER_MATCHER
21521#include "RISCVGenAsmMatcher.inc"
21527 if (Reg == RISCV::NoRegister)
21529 if (Reg == RISCV::NoRegister)
21541 const MDNode *NontemporalInfo =
I.getMetadata(LLVMContext::MD_nontemporal);
21543 if (NontemporalInfo ==
nullptr)
21551 int NontemporalLevel = 5;
21552 const MDNode *RISCVNontemporalInfo =
21553 I.getMetadata(
"riscv-nontemporal-domain");
21554 if (RISCVNontemporalInfo !=
nullptr)
21557 cast<ConstantAsMetadata>(RISCVNontemporalInfo->
getOperand(0))
21561 assert((1 <= NontemporalLevel && NontemporalLevel <= 5) &&
21562 "RISC-V target doesn't support this non-temporal domain.");
21564 NontemporalLevel -= 2;
21566 if (NontemporalLevel & 0b1)
21568 if (NontemporalLevel & 0b10)
21581 return TargetFlags;
21591 return isTypeLegal(VT) && Subtarget.hasStdExtZvbb();
21594 return Subtarget.hasStdExtZbb() &&
21607 if (
Op == Instruction::Add ||
Op == Instruction::Sub ||
21608 Op == Instruction::And ||
Op == Instruction::Or ||
21609 Op == Instruction::Xor ||
Op == Instruction::InsertElement ||
21610 Op == Instruction::ShuffleVector ||
Op == Instruction::Load ||
21611 Op == Instruction::Freeze ||
Op == Instruction::Store)
21619 !isa<ReturnInst>(&Inst))
21622 if (
const AllocaInst *AI = dyn_cast<AllocaInst>(&Inst)) {
21623 if (AI->getAllocatedType()->isScalableTy())
21631RISCVTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
21639 if (!Subtarget.hasShortForwardBranchOpt())
21641 EVT VT =
N->getValueType(0);
21642 if (!(VT == MVT::i32 || (VT == MVT::i64 && Subtarget.
is64Bit())))
21646 if (Divisor.
sgt(2048) || Divisor.
slt(-2048))
21651bool RISCVTargetLowering::shouldFoldSelectWithSingleBitTest(
21652 EVT VT,
const APInt &AndMask)
const {
21653 if (Subtarget.hasStdExtZicond() || Subtarget.hasVendorXVentanaCondOps())
21654 return !Subtarget.hasStdExtZbs() && AndMask.
ugt(1024);
21658unsigned RISCVTargetLowering::getMinimumJumpTableEntries()
const {
21663template <
typename Arg>
21664void RVVArgDispatcher::constructArgInfos(
ArrayRef<Arg> ArgList) {
21667 auto isHomogeneousScalableVectorType = [](
ArrayRef<Arg> ArgList) {
21669 auto It = ArgList.
begin();
21670 MVT FirstArgRegType = It->VT;
21673 if (It == ArgList.
end() || It->Flags.isSplit())
21685 for (; It != ArgList.
end(); ++It)
21686 if (It->Flags.isSplit() || It->VT != FirstArgRegType)
21692 if (isHomogeneousScalableVectorType(ArgList)) {
21694 RVVArgInfos.push_back({(
unsigned)ArgList.
size(), ArgList[0].VT,
false});
21697 bool FirstVMaskAssigned =
false;
21698 for (
const auto &OutArg : ArgList) {
21699 MVT RegisterVT = OutArg.VT;
21709 RVVArgInfos.push_back({1, RegisterVT,
true});
21710 FirstVMaskAssigned =
true;
21714 RVVArgInfos.push_back({1, RegisterVT,
false});
21721void RVVArgDispatcher::constructArgInfos<Type *>(
ArrayRef<Type *> TypeList) {
21726 bool FirstVMaskAssigned =
false;
21727 for (
Type *Ty : TypeList) {
21737 RVVArgInfos.push_back(
21743 for (
unsigned Value = 0, NumValues = ValueVTs.
size();
Value != NumValues;
21758 if (!FirstVMaskAssigned &&
21760 RVVArgInfos.push_back({1, RegisterVT,
true});
21761 FirstVMaskAssigned =
true;
21765 RVVArgInfos.insert(RVVArgInfos.end(), NumRegs, {1, RegisterVT, false});
21771void RVVArgDispatcher::allocatePhysReg(
unsigned NF,
unsigned LMul,
21772 unsigned StartReg) {
21773 assert((StartReg % LMul) == 0 &&
21774 "Start register number should be multiple of lmul");
21793 for (
unsigned i = 0; i < NF; ++i)
21795 AllocatedPhysRegs.push_back(VRArrays[(StartReg - 8) / LMul + i]);
21797 AllocatedPhysRegs.push_back(
MCPhysReg());
21803void RVVArgDispatcher::compute() {
21805 auto allocate = [&](
const RVVArgInfo &
ArgInfo) {
21808 AllocatedPhysRegs.push_back(RISCV::V0);
21814 unsigned TotalRegsNeeded =
ArgInfo.NF * RegsNeeded;
21815 for (
unsigned StartReg = 0; StartReg + TotalRegsNeeded <=
NumArgVRs;
21816 StartReg += RegsNeeded) {
21817 uint32_t Map = ((1 << TotalRegsNeeded) - 1) << StartReg;
21818 if ((AssignedMap & Map) == 0) {
21819 allocatePhysReg(
ArgInfo.NF, RegsNeeded, StartReg + 8);
21820 AssignedMap |=
Map;
21825 allocatePhysReg(
ArgInfo.NF, RegsNeeded, 0);
21828 for (
unsigned i = 0; i < RVVArgInfos.size(); ++i)
21829 allocate(RVVArgInfos[i]);
21833 assert(CurIdx < AllocatedPhysRegs.size() &&
"Index out of range");
21834 return AllocatedPhysRegs[CurIdx++];
21841 if (Subtarget.hasStdExtZicfilp()) {
21853#define GET_RISCVVIntrinsicsTable_IMPL
21854#include "RISCVGenSearchableTables.inc"
unsigned const MachineRegisterInfo * MRI
static MCRegister MatchRegisterName(StringRef Name)
static EVT getContainerForFixedLengthVector(SelectionDAG &DAG, EVT VT)
static SDValue performORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const AArch64Subtarget *Subtarget, const AArch64TargetLowering &TLI)
static SDValue performANDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
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)
SmallVector< AArch64_IMM::ImmInsnModel, 4 > Insn
#define NODE_NAME_CASE(node)
static bool isConstant(const MachineInstr &MI)
amdgpu AMDGPU Register Bank Select
static bool isZeroOrAllOnes(SDValue N, bool AllOnes)
static SDValue combineSelectAndUseCommutative(SDNode *N, bool AllOnes, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp, TargetLowering::DAGCombinerInfo &DCI, bool AllOnes=false)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static MCRegister MatchRegisterAltName(StringRef Name)
Maps from the set of all alternative registernames to a register number.
Function Alias Analysis Results
static SDValue getTargetNode(GlobalAddressSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, unsigned Flags)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
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)
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
const HexagonInstrInfo * TII
This file defines an InstructionCost class that is used when calculating the cost of an instruction,...
const MCPhysReg ArgFPR32s[]
static Align getPrefTypeAlign(EVT VT, SelectionDAG &DAG)
static SDValue customLegalizeToWOpWithSExt(SDNode *N, SelectionDAG &DAG)
const MCPhysReg ArgFPR64s[]
const MCPhysReg ArgGPRs[]
static SDValue customLegalizeToWOp(SDNode *N, SelectionDAG &DAG, int NumOp, unsigned ExtOpc=ISD::ANY_EXTEND)
static Intrinsic::ID getIntrinsicForMaskedAtomicRMWBinOp(unsigned GRLen, AtomicRMWInst::BinOp BinOp)
loop Loop Strength Reduction
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
unsigned const TargetRegisterInfo * TRI
This file provides utility analysis objects describing memory locations.
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
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 performSRACombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const MipsSubtarget &Subtarget)
uint64_t IntrinsicInst * II
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
static CodeModel::Model getCodeModel(const PPCSubtarget &S, const TargetMachine &TM, const MachineOperand &MO)
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 * emitBuildPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const RISCVSubtarget &Subtarget)
static MachineBasicBlock * emitQuietFCMP(MachineInstr &MI, MachineBasicBlock *BB, unsigned RelOpcode, unsigned EqOpcode, const RISCVSubtarget &Subtarget)
static int isElementRotate(int &LoSrc, int &HiSrc, ArrayRef< int > Mask)
Match shuffles that concatenate two vectors, rotate the concatenation, and then extract the original ...
static const Intrinsic::ID FixedVlsegIntrIds[]
static SDValue lowerBuildVectorOfConstants(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static MVT getLMUL1VT(MVT VT)
static bool CC_RISCVAssign2XLen(unsigned XLen, CCState &State, CCValAssign VA1, ISD::ArgFlagsTy ArgFlags1, unsigned ValNo2, MVT ValVT2, MVT LocVT2, ISD::ArgFlagsTy ArgFlags2, bool EABI)
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 bool hasPassthruOp(unsigned Opcode)
Return true if a RISC-V target specified op has a passthru operand.
static SDValue combineTruncToVnclip(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::optional< APInt > getExactInteger(const APFloat &APF, uint32_t BitWidth)
static const MCPhysReg ArgVRM2s[]
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 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 RISCVISD::NodeType getRISCVWOpcode(unsigned Opcode)
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 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 const RISCV::RISCVMaskedPseudoInfo * lookupMaskedIntrinsic(uint16_t MCOpcode, RISCVII::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 bool isLegalBitRotate(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, MVT &RotateVT, unsigned &RotateAmt)
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 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 lowerFMAXIMUM_FMINIMUM(SDValue Op, 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 bool isDeinterleaveShuffle(MVT VT, MVT ContainerVT, SDValue V1, SDValue V2, ArrayRef< int > Mask, const RISCVSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLEAsVSlidedown(const SDLoc &DL, MVT VT, SDValue V1, SDValue V2, ArrayRef< int > Mask, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
static unsigned getRVVReductionOp(unsigned ISDOpcode)
static SDValue combineSubShiftToOrcB(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::optional< bool > matchSetCC(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue Val)
static SDValue lowerShuffleViaVRegSplitting(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue getVCIXISDNodeVOID(SDValue &Op, SelectionDAG &DAG, unsigned Type)
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 foldBinOpIntoSelectIfProfitable(SDNode *BO, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue combineVectorMulToSraBitcast(SDNode *N, SelectionDAG &DAG)
static bool hasMaskOp(unsigned Opcode)
Return true if a RISC-V target specified op has a mask operand.
static bool legalizeScatterGatherIndexType(SDLoc DL, SDValue &Index, ISD::MemIndexType &IndexType, RISCVTargetLowering::DAGCombinerInfo &DCI)
static SDValue combineSelectToBinOp(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
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 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 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 std::optional< unsigned > preAssignMask(const ArgTy &Args)
static SDValue getVLOperand(SDValue Op)
static SDValue lowerBUILD_VECTORvXf16(SDValue Op, SelectionDAG &DAG)
static MachineBasicBlock * emitFROUND(MachineInstr &MI, MachineBasicBlock *MBB, const RISCVSubtarget &Subtarget)
static SDValue lowerCttzElts(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerVectorIntrinsicScalars(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue performSIGN_EXTEND_INREGCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerVectorXRINT(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 combineBinOpOfZExt(SDNode *N, SelectionDAG &DAG)
static bool isSelectPseudo(MachineInstr &MI)
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 Value * useTpOffset(IRBuilderBase &IRB, unsigned Offset)
static SDValue combineAddOfBooleanXor(SDNode *N, SelectionDAG &DAG)
static SDValue combineTruncOfSraSext(SDNode *N, SelectionDAG &DAG)
static MachineBasicBlock * emitSplitF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const RISCVSubtarget &Subtarget)
static MachineBasicBlock * emitVFROUND_NOEXCEPT_MASK(MachineInstr &MI, MachineBasicBlock *BB, unsigned CVTXOpc)
static SDValue SplitVectorOp(SDValue Op, SelectionDAG &DAG)
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 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 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 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 getDeinterleaveViaVNSRL(const SDLoc &DL, MVT VT, SDValue Src, bool EvenElts, const RISCVSubtarget &Subtarget, 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=RISCVII::TAIL_UNDISTURBED_MASK_UNDISTURBED)
static uint64_t computeGREVOrGORC(uint64_t x, unsigned ShAmt, bool IsGORC)
static SDValue lowerVECTOR_SHUFFLEAsRotate(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
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 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 bool combine_CC(SDValue &LHS, SDValue &RHS, SDValue &CC, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isNonZeroAVL(SDValue AVL)
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 ArrayRef< MCPhysReg > getFastCCArgGPRs(const RISCVABI::ABI ABI)
static const MCPhysReg ArgVRM8s[]
static MachineBasicBlock * emitReadCounterWidePseudo(MachineInstr &MI, MachineBasicBlock *BB)
static const MCPhysReg ArgVRM4s[]
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 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 const MCPhysReg ArgFPR16s[]
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 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 void translateSetCCForBranch(const SDLoc &DL, SDValue &LHS, SDValue &RHS, ISD::CondCode &CC, SelectionDAG &DAG)
static SDValue combineToVWMACC(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
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 const Intrinsic::ID FixedVssegIntrIds[]
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=RISCVII::TAIL_UNDISTURBED_MASK_UNDISTURBED)
static LLT getMaskTypeFor(LLT VecTy)
Return the type of the mask type suitable for masking the provided vector type.
const SmallVectorImpl< MachineOperand > & Cond
const MachineOperand & RHS
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool isCommutative(Instruction *I)
This file defines the SmallSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static SymbolRef::Type getType(const Symbol *Sym)
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.
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.
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.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
bool isNegative() const
Determine sign of this APInt.
APInt sdiv(const APInt &RHS) const
Signed division function for APInt.
void clearAllBits()
Set every bit to 0.
bool isSignedIntN(unsigned N) const
Check if this APInt has an N-bits signed integer value.
static 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.
void insertBits(const APInt &SubBits, unsigned bitPosition)
Insert the bits from a smaller APInt starting at bitPosition.
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)
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.
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.
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.
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.
@ Min
*p = old <signed v ? old : v
@ 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.
bool hasFnAttr(Attribute::AttrKind Kind) const
Return true if the attribute exists for the function.
StringRef getValueAsString() const
Return the attribute's value as a string.
static BaseIndexOffset match(const SDNode *N, const SelectionDAG &DAG)
Parses tree in N for base, index, offset addresses.
LLVM Basic Block Representation.
const Function * getParent() const
Return the enclosing method, or null if none.
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.
MachineFunction & getMachineFunction() const
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
SmallVectorImpl< ISD::ArgFlagsTy > & getPendingArgFlags()
MCRegister AllocateReg(MCPhysReg Reg)
AllocateReg - Attempt to allocate one register.
int64_t AllocateStack(unsigned Size, Align Alignment)
AllocateStack - Allocate a chunk of stack space with the specified size and alignment.
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.
SmallVectorImpl< CCValAssign > & getPendingLocs()
void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
void addLoc(const CCValAssign &V)
CCValAssign - Represent assignment of one arg/retval to a location.
static CCValAssign getPending(unsigned ValNo, MVT ValVT, MVT LocVT, LocInfo HTP, unsigned ExtraInfo=0)
Register getLocReg() const
LocInfo getLocInfo() const
static CCValAssign getMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP, bool IsCustom=false)
static CCValAssign getReg(unsigned ValNo, MVT ValVT, unsigned RegNo, MVT LocVT, LocInfo HTP, bool IsCustom=false)
static CCValAssign getCustomReg(unsigned ValNo, MVT ValVT, unsigned RegNo, MVT LocVT, LocInfo HTP)
int64_t getLocMemOffset() const
unsigned getValNo() const
static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP)
bool isMustTailCall() const
Tests if this call site must be tail call optimized.
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
This is an important base class in LLVM.
static Constant * getAllOnesValue(Type *Ty)
This class represents an Operation in the Expression.
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
Layout pointer size, in bits FIXME: The defaults need to be removed once all of the backends/clients ...
Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
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)
static FixedVectorType * get(Type *ElementType, unsigned NumElts)
FunctionType * getFunctionType() const
Returns the FunctionType for me.
iterator_range< arg_iterator > args()
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
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.
Type * getReturnType() const
Returns the type of the ret val.
Argument * getArg(unsigned i) const
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...
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override
Store the specified register of the given register class to the specified stack frame index.
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override
Load the specified register of the given register class from the specified stack frame index.
Common base class shared among various IRBuilders.
Value * CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
FenceInst * CreateFence(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System, const Twine &Name="")
Value * CreateSExt(Value *V, Type *DestTy, const Twine &Name="")
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
BasicBlock * GetInsertBlock() const
IntegerType * getInt64Ty()
Fetch the type representing a 64-bit integer.
Value * CreateNot(Value *V, const Twine &Name="")
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
ConstantInt * getIntN(unsigned N, uint64_t C)
Get a constant N-bit value, zero extended or truncated from a 64-bit value.
Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")
AtomicRMWInst * CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr, Value *Val, MaybeAlign Align, AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args=std::nullopt, const Twine &Name="", MDNode *FPMathTag=nullptr)
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
static InstructionCost getInvalid(CostType Val=0)
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.
const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Class to represent integer types.
A wrapper class for inspecting calls to intrinsic functions.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
This is an important class for using LLVM in a threaded context.
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.
An instruction for reading from memory.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
Value * getPointerOperand()
Align getAlign() const
Return the alignment of the access that is being performed.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
Context object for machine code objects.
Base class for the full range of assembler expressions which are needed for parsing.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
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.
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
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)
MVT changeTypeToInteger()
Return the type converted to an equivalently sized integer or vector with integer element 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.
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()
void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
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.
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.
int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
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.
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)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
void insert(iterator MBBI, MachineBasicBlock *MBB)
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.
void collectDebugValues(SmallVectorImpl< MachineInstr * > &DbgValues)
Scan instructions immediately following MI and collect any matching DBG_VALUEs.
void setFlag(MIFlag Flag)
Set a MI flag.
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,...
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
void addLiveIn(MCRegister Reg, Register vreg=Register())
addLiveIn - Add the specified register as a live-in.
This is an abstract virtual class for memory operations.
bool isSimple() const
Returns true if the memory operation is neither atomic or volatile.
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.
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
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)
RISCVABI::ABI getTargetABI() const
unsigned getMinimumJumpTableEntries() const
bool hasStdExtCOrZca() const
unsigned getMaxLMULForFixedLengthVectors() const
bool hasVInstructionsI64() const
bool hasVInstructionsF64() const
bool hasStdExtDOrZdinx() const
bool hasStdExtZfhOrZhinx() const
unsigned getRealMinVLen() const
Quantity expandVScale(Quantity X) const
If the ElementCount or TypeSize X is scalable and VScale (VLEN) is exactly known, returns X converted...
bool useRVVForFixedLengthVectors() const
bool isTargetFuchsia() const
bool hasVInstructionsBF16Minimal() const
unsigned getDLenFactor() const
bool hasVInstructionsF16Minimal() const
bool hasConditionalMoveFusion() const
bool isRegisterReservedByUser(Register i) const
bool hasVInstructionsF16() const
unsigned getMaxBuildIntsCost() const
Align getPrefLoopAlignment() const
bool hasVInstructions() const
std::optional< unsigned > getRealVLen() const
bool useConstantPoolForLargeInts() const
Align getPrefFunctionAlignment() const
bool hasStdExtZfhminOrZhinxmin() const
unsigned getRealMaxVLen() const
const RISCVRegisterInfo * getRegisterInfo() const override
const RISCVInstrInfo * getInstrInfo() const override
const RISCVTargetLowering * getTargetLowering() const override
bool hasVInstructionsF32() const
bool isTargetAndroid() const
bool hasStdExtFOrZfinx() 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)
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...
bool shouldSinkOperands(Instruction *I, SmallVectorImpl< Use * > &Ops) const override
Check if sinking I's operands to I's basic block is profitable, because the operands can be folded in...
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 shouldFoldSelectWithIdentityConstant(unsigned BinOpcode, EVT VT) const override
Return true if pulling a binary operation into a select with an identity constant is profitable.
bool mayBeEmittedAsTailCall(const CallInst *CI) const override
Return true if the target may be able emit the call instruction as a tail call.
std::pair< int, bool > getLegalZfaFPImm(const APFloat &Imm, EVT VT) const
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.
EVT getOptimalMemOpType(const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
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
const char * getTargetNodeName(unsigned Opcode) const override
This method returns the name of a target specific DAG node.
bool canSplatOperand(Instruction *I, int Operand) const
Return true if the (vector) instruction I will be lowered to an instruction with a scalar splat opera...
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...
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 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 lowerInterleaveIntrinsicToStore(IntrinsicInst *II, StoreInst *SI, SmallVectorImpl< Instruction * > &DeadInsts) const override
Lower an interleave intrinsic to a target specific store intrinsic.
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 getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, LLVMContext &Context) const override
This hook should be implemented to check whether the return values described by the Outs array can fi...
bool lowerInterleavedLoad(LoadInst *LI, ArrayRef< ShuffleVectorInst * > Shuffles, ArrayRef< unsigned > Indices, unsigned Factor) const override
Lower an interleaved load into a vlsegN intrinsic.
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.
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 lowerDeinterleaveIntrinsicToLoad(IntrinsicInst *II, LoadInst *LI, SmallVectorImpl< Instruction * > &DeadInsts) const override
Lower a deinterleave intrinsic to a target specific load intrinsic.
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>>...
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...
static unsigned getRegClassIDForLMUL(RISCVII::VLMUL LMul)
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.
bool shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const override
Returns true if arguments should be sign-extended in lib calls.
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_...
bool lowerInterleavedStore(StoreInst *SI, ShuffleVectorInst *SVI, unsigned Factor) const override
Lower an interleaved store into a vssegN intrinsic.
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.
static RISCVII::VLMUL getLMUL(MVT VT)
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 isLegalInterleavedAccessType(VectorType *VTy, unsigned Factor, Align Alignment, unsigned AddrSpace, const DataLayout &) const
Returns whether or not generating a interleaved load/store intrinsic for this type will be legal.
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.
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.
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
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...
As per the spec, the rules for passing vector arguments are as follows:
static constexpr unsigned NumArgVRs
MCPhysReg getNextPhysReg()
Wrapper class representing virtual and physical registers.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
This class provides iterator support for SDUse operands that use a specific SDNode.
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
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
use_iterator use_begin() const
Provide iteration support to walk over all uses of an SDNode.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
void setCFIType(uint32_t Type)
bool isUndef() const
Return true if the type of the node type undefined.
op_iterator op_end() const
op_iterator op_begin() const
static use_iterator use_end()
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
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
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)
unsigned ComputeMaxSignificantBits(SDValue Op, unsigned Depth=0) const
Get the upper bound on bit size for this Value Op as a signed integer.
SDValue getMaskedGather(SDVTList VTs, EVT MemVT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType, ISD::LoadExtType ExtTy)
SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL)
SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
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),...
SDValue getNeutralElement(unsigned Opcode, const SDLoc &DL, EVT VT, SDNodeFlags Flags)
Get the (commutative) neutral element for the given opcode, if it exists.
SDValue getVScale(const SDLoc &DL, EVT VT, APInt MulImm, bool ConstantFold=true)
Return a node that represents the runtime scaling 'MulImm * RuntimeVL'.
SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
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(), AAResults *AA=nullptr)
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)
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...
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-...
SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
SDValue getElementCount(const SDLoc &DL, EVT VT, ElementCount EC, bool ConstantFold=true)
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,...
SDValue getStepVector(const SDLoc &DL, EVT ResVT, const APInt &StepVal)
Returns a vector of type ResVT whose elements contain the linear sequence <0, Step,...
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
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.
SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
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
bool NewNodesMustHaveLegalTypes
When true, additional steps are taken to ensure that getConstant() and similar functions return DAG n...
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).
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.
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.
SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
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...
SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
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
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)
SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags=SDNodeFlags())
Returns sum of the base pointer and offset.
void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
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.
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.
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 ...
bool SignBitIsZero(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero.
SDValue getRegister(unsigned Reg, EVT VT)
SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDValue > Ops, SDNodeFlags Flags=SDNodeFlags())
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)
SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
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...
std::pair< SDValue, SDValue > SplitEVL(SDValue N, EVT VecVT, const SDLoc &DL)
Split the explicit vector length parameter of a VP operation.
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, unsigned Reg, SDValue N)
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond)
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
SDValue getScatterVP(SDVTList VTs, EVT VT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType)
SDValue getValueType(EVT)
SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
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...
bool isKnownNeverNaN(SDValue Op, 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.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
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.
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)
SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
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 getCopyFromReg(SDValue Chain, const SDLoc &dl, unsigned Reg, EVT VT)
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
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.
SDValue getRegisterMask(const uint32_t *RegMask)
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...
SDValue getCondCode(ISD::CondCode Cond)
bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
LLVMContext * getContext() const
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=0, const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
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 getTargetInsertSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand, SDValue Subreg)
A convenience function for creating TargetInstrInfo::INSERT_SUBREG nodes.
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
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.
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.
SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a logical NOT operation as (XOR Val, BooleanOne).
SDValue getMaskedScatter(SDVTList VTs, EVT MemVT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType, bool IsTruncating=false)
This instruction constructs a fixed permutation of two input vectors.
static 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,...
VectorType * getType() const
Overload to return most specific vector type.
static void getShuffleMask(const Constant *Mask, SmallVectorImpl< int > &Result)
Convert the input shuffle mask operand to a vector of integers.
static bool isIdentityMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector without lane crossin...
static bool isReverseMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask swaps the order of elements from exactly one source vector.
static bool isInsertSubvectorMask(ArrayRef< int > Mask, int NumSrcElts, int &NumSubElts, int &Index)
Return true if this shuffle mask is an insert subvector mask.
static 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...
static bool isSplatMask(const int *Mask, EVT VT)
int getSplatIndex() const
ArrayRef< int > getMask() const
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.
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
An instruction for storing to memory.
This class is used to represent ISD::STORE nodes.
StringRef - Represent a constant reference to a string, i.e.
constexpr size_t size() const
size - Get the string size.
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)
Class to represent struct types.
bool containsHomogeneousScalableVectorTypes() const
Returns true if this struct contains homogeneous scalable vector types.
unsigned getNumElements() const
Random access to the elements.
Type * getTypeAtIndex(const Value *V) const
Given an index value into the type, return the type of the element.
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.
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.
const TargetMachine & getTargetMachine() const
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
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.
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.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
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.
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 setLibcallName(RTLIB::Libcall Call, const char *Name)
Rename the default libcall routine name for the specified libcall.
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.
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...
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...
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...
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...
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.
bool verifyReturnAddressArgumentIsConstant(SDValue Op, SelectionDAG &DAG) const
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.
bool useTLSDESC() const
Returns true if this target uses TLS Descriptors.
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual const TargetInstrInfo * getInstrInfo() const
Target - Wrapper for Target specific information.
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.
unsigned getIntegerBitWidth() const
Type * getStructElementType(unsigned N) const
static IntegerType * getIntNTy(LLVMContext &C, unsigned N)
bool isStructTy() const
True if this is an instance of StructType.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
bool isScalableTy() const
Return true if this is a type whose size is a known multiple of vscale.
bool isIntegerTy() const
True if this is an instance of IntegerType.
TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
Type * getContainedType(unsigned i) const
This method is used to implement the type iterator (defined at the end of the file).
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
A Use represents the edge between a Value definition and its users.
User * getUser() const
Returns the User that contains this Use.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVMContext & getContext() const
All values hold a context through their type.
Base class of all SIMD vector types.
constexpr ScalarTy getFixedValue() const
constexpr LeafTy multiplyCoefficientBy(ScalarTy RHS) const
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
constexpr bool isZero() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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.
@ RISCV_VectorCall
Calling convention used for RISC-V V-extension.
@ 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.
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.
@ STACKRESTORE
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain.
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ 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.
@ VECREDUCE_SEQ_FADD
Generic reduction nodes.
@ MLOAD
Masked load and store - consecutive vector load and store operations with additional mask operand tha...
@ 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.
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ 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 ...
@ VECREDUCE_FMAX
FMIN/FMAX nodes can have flags, for NaN/NoNaN variants.
@ FADD
Simple binary floating point operators.
@ VECREDUCE_FMAXIMUM
FMINIMUM/FMAXIMUM nodes propatate NaNs and signed zeroes using the llvm.minimum and llvm....
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ MEMBARRIER
MEMBARRIER - Compiler barrier only; generate a no-op.
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ 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.
@ SET_ROUNDING
Set rounding mode.
@ 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...
@ READSTEADYCOUNTER
READSTEADYCOUNTER - This corresponds to the readfixedcounter intrinsic.
@ VECREDUCE_FADD
These reductions have relaxed evaluation order semantics, and have a single vector operand.
@ CTTZ_ZERO_UNDEF
Bit counting operators with an undefined result for zero inputs.
@ PREFETCH
PREFETCH - This corresponds to a prefetch intrinsic.
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ BR_JT
BR_JT - Jumptable branch.
@ VECTOR_INTERLEAVE
VECTOR_INTERLEAVE(VEC1, VEC2) - Returns two vectors with all input and output vectors having the same...
@ STEP_VECTOR
STEP_VECTOR(IMM) - Returns a scalable vector whose lanes are comprised of a linear sequence of unsign...
@ 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.
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
@ VACOPY
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer,...
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ 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.
@ DEBUGTRAP
DEBUGTRAP - Trap intended to get the attention of a debugger.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ VSCALE
VSCALE(IMM) - Returns the runtime scaling factor used to calculate the number of elements within a sc...
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two values.
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
@ 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...
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ 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.
@ MGATHER
Masked gather and scatter - load and store operations for a vector of random addresses with additiona...
@ EH_DWARF_CFA
EH_DWARF_CFA - This node represents the pointer to the DWARF Canonical Frame Address (CFA),...
@ BF16_TO_FP
BF16_TO_FP, FP_TO_BF16 - These operators are used to perform promotions and truncation for bfloat16.
@ 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.
@ FMINIMUM
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0....
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ READCYCLECOUNTER
READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic.
@ 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.
@ TRAP
TRAP - Trapping instruction.
@ 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...
@ ATOMIC_SWAP
Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN,...
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ 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.
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
@ BRCOND
BRCOND - Conditional branch.
@ 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 two vectors with all input and output vectors having the sa...
@ FMINIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM - minimumnum/maximumnum that is same with FMINNUM_IEEE and FMAXNUM_IEEE besid...
@ 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,...
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 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...
CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
std::optional< unsigned > getVPMaskIdx(unsigned Opcode)
The operand position of the vector mask.
std::optional< unsigned > getVPExplicitVectorLengthIdx(unsigned Opcode)
The operand position of the explicit vector length parameter.
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...
bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
bool isBuildVectorOfConstantFPSDNodes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR node of all ConstantFPSDNode or undef.
static const int FIRST_TARGET_STRICTFP_OPCODE
FIRST_TARGET_STRICTFP_OPCODE - Target-specific pre-isel operations which cannot raise FP exceptions s...
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
bool isBuildVectorAllOnes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are ~0 or undef.
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).
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...
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=std::nullopt)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
@ Bitcast
Perform the operation on a different, but equivalently sized type.
ABI getTargetABI(StringRef ABIName)
bool match(Val *V, const Pattern &P)
cst_pred_ty< is_zero_int > m_ZeroInt()
Match an integer 0 or a vector with all elements equal to 0.
TwoOps_match< V1_t, V2_t, Instruction::ShuffleVector > m_Shuffle(const V1_t &v1, const V2_t &v2)
Matches ShuffleVectorInst independently of mask value.
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
auto m_Undef()
Match an arbitrary undef constant.
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.
@ TAIL_UNDISTURBED_MASK_UNDISTURBED
static VLMUL getLMul(uint64_t TSFlags)
static int getFRMOpNum(const MCInstrDesc &Desc)
static unsigned getSEWOpNum(const MCInstrDesc &Desc)
@ SW_GUARDED_BRIND
Software guarded BRIND node.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #3 and #4) ...
@ STRICT_VFCVT_RTZ_XU_F_VL
@ TRUNCATE_VECTOR_VL_USAT
@ LAST_RISCV_STRICTFP_OPCODE
@ STRICT_VFROUND_NOEXCEPT_VL
@ SPLAT_VECTOR_SPLIT_I64_VL
@ TRUNCATE_VECTOR_VL_SSAT
@ STRICT_VFCVT_RTZ_X_F_VL
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)
static unsigned decodeVSEW(unsigned VSEW)
std::pair< unsigned, bool > decodeVLMUL(RISCVII::VLMUL VLMUL)
static RISCVII::VLMUL encodeLMUL(unsigned LMUL, bool Fractional)
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
bool CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed, bool IsRet, Type *OrigTy, const RISCVTargetLowering &TLI, RVVArgDispatcher &RVVDispatcher)
bool CC_RISCV_FastCC(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed, bool IsRet, Type *OrigTy, const RISCVTargetLowering &TLI, RVVArgDispatcher &RVVDispatcher)
static constexpr unsigned FPMASK_Positive_Infinity
int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIndex)
static constexpr unsigned FPMASK_Negative_Infinity
static constexpr unsigned FPMASK_Quiet_NaN
ArrayRef< MCPhysReg > getArgGPRs(const RISCVABI::ABI ABI)
bool CC_RISCV_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State)
static constexpr unsigned FPMASK_Signaling_NaN
static constexpr unsigned FPMASK_Positive_Zero
static constexpr unsigned RVVBitsPerBlock
Libcall
RTLIB::Libcall enum - This enum defines all of the runtime library calls the backend can emit.
Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
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.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
@ System
Synchronized with respect to all concurrently executing threads.
Reg
All possible values of the reg field in the ModR/M byte.
initializer< Ty > init(const Ty &Val)
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.
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.
bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
static const MachineMemOperand::Flags MONontemporalBit0
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
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...
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.
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.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
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...
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...
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
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.
@ Xor
Bitwise or logical XOR of integers.
@ And
Bitwise or logical AND of integers.
@ SMin
Signed integer min implemented in terms of select(cmp()).
unsigned getKillRegState(bool B)
DWARFExpression::Operation Op
RoundingMode
Rounding mode.
@ TowardZero
roundTowardZero.
@ NearestTiesToEven
roundTiesToEven.
@ TowardPositive
roundTowardPositive.
@ NearestTiesToAway
roundTiesToAway.
@ TowardNegative
roundTowardNegative.
void ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL, Type *Ty, SmallVectorImpl< EVT > &ValueVTs, SmallVectorImpl< EVT > *MemVTs, SmallVectorImpl< TypeSize > *Offsets=nullptr, TypeSize StartingOffset=TypeSize::getZero())
ComputeValueVTs - Given an LLVM IR type, compute a sequence of EVTs that represent all the individual...
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...
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.
unsigned Log2(Align A)
Returns the log2 of the alignment.
llvm::SmallVector< int, 16 > createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs)
Create a sequential shuffle mask.
bool isNeutralConstant(unsigned Opc, SDNodeFlags Flags, SDValue V, unsigned OperandNo)
Returns true if V is a neutral element of Opc with Flags.
bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
static constexpr roundingMode rmNearestTiesToEven
static 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.
Helper struct shared between Function Specialization and SCCP Solver.
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.
ElementCount getVectorElementCount() const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
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.
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.
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.
Align getNonZeroOrigAlign() const
static 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.
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 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 KnownBits shl(const KnownBits &LHS, const KnownBits &RHS, bool NUW=false, bool NSW=false, bool ShAmtNonZero=false)
Compute known bits for shl(LHS, RHS).
This class contains a discriminated union of information about pointers in memory operands,...
MachinePointerInfo getWithOffset(int64_t O) const
static MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static 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.
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.
BitVector getReservedRegs(const MachineFunction &MF) const override
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
void AddToWorklist(SDNode *N)
bool isCalledByLegalizer() const
bool recursivelyDeleteUnusedNodes(SDNode *N)
bool isBeforeLegalize() const
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, bool Value=true)
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...
bool CombineTo(SDValue O, SDValue N)