38#include "llvm/IR/IntrinsicsRISCV.h"
53#define DEBUG_TYPE "riscv-lower"
59 cl::desc(
"Give the maximum size (in number of nodes) of the web of "
60 "instructions that we will consider for VW expansion"),
65 cl::desc(
"Allow the formation of VW_W operations (e.g., "
66 "VWADD_W) with splat constants"),
71 cl::desc(
"Set the minimum number of repetitions of a divisor to allow "
72 "transformation to multiplications by the reciprocal"),
77 cl::desc(
"Give the maximum number of instructions that we will "
78 "use for creating a floating-point immediate value"),
89 !Subtarget.hasStdExtF()) {
90 errs() <<
"Hard-float 'f' ABI can't be used for a target that "
91 "doesn't support the F instruction set extension (ignoring "
95 !Subtarget.hasStdExtD()) {
96 errs() <<
"Hard-float 'd' ABI can't be used for a target that "
97 "doesn't support the D instruction set extension (ignoring "
121 if (Subtarget.hasStdExtZfhmin())
123 if (Subtarget.hasStdExtZfbfmin())
125 if (Subtarget.hasStdExtF())
127 if (Subtarget.hasStdExtD())
129 if (Subtarget.hasStdExtZhinxmin())
131 if (Subtarget.hasStdExtZfinx())
133 if (Subtarget.hasStdExtZdinx()) {
141 MVT::nxv1i1, MVT::nxv2i1, MVT::nxv4i1, MVT::nxv8i1,
142 MVT::nxv16i1, MVT::nxv32i1, MVT::nxv64i1};
144 MVT::nxv1i8, MVT::nxv2i8, MVT::nxv4i8, MVT::nxv8i8, MVT::nxv16i8,
145 MVT::nxv32i8, MVT::nxv64i8, MVT::nxv1i16, MVT::nxv2i16, MVT::nxv4i16,
146 MVT::nxv8i16, MVT::nxv16i16, MVT::nxv32i16, MVT::nxv1i32, MVT::nxv2i32,
147 MVT::nxv4i32, MVT::nxv8i32, MVT::nxv16i32, MVT::nxv1i64, MVT::nxv2i64,
148 MVT::nxv4i64, MVT::nxv8i64};
150 MVT::nxv1f16, MVT::nxv2f16, MVT::nxv4f16,
151 MVT::nxv8f16, MVT::nxv16f16, MVT::nxv32f16};
153 MVT::nxv1bf16, MVT::nxv2bf16, MVT::nxv4bf16,
154 MVT::nxv8bf16, MVT::nxv16bf16, MVT::nxv32bf16};
156 MVT::nxv1f32, MVT::nxv2f32, MVT::nxv4f32, MVT::nxv8f32, MVT::nxv16f32};
158 MVT::nxv1f64, MVT::nxv2f64, MVT::nxv4f64, MVT::nxv8f64};
160 MVT::riscv_nxv1i8x2, MVT::riscv_nxv1i8x3, MVT::riscv_nxv1i8x4,
161 MVT::riscv_nxv1i8x5, MVT::riscv_nxv1i8x6, MVT::riscv_nxv1i8x7,
162 MVT::riscv_nxv1i8x8, MVT::riscv_nxv2i8x2, MVT::riscv_nxv2i8x3,
163 MVT::riscv_nxv2i8x4, MVT::riscv_nxv2i8x5, MVT::riscv_nxv2i8x6,
164 MVT::riscv_nxv2i8x7, MVT::riscv_nxv2i8x8, MVT::riscv_nxv4i8x2,
165 MVT::riscv_nxv4i8x3, MVT::riscv_nxv4i8x4, MVT::riscv_nxv4i8x5,
166 MVT::riscv_nxv4i8x6, MVT::riscv_nxv4i8x7, MVT::riscv_nxv4i8x8,
167 MVT::riscv_nxv8i8x2, MVT::riscv_nxv8i8x3, MVT::riscv_nxv8i8x4,
168 MVT::riscv_nxv8i8x5, MVT::riscv_nxv8i8x6, MVT::riscv_nxv8i8x7,
169 MVT::riscv_nxv8i8x8, MVT::riscv_nxv16i8x2, MVT::riscv_nxv16i8x3,
170 MVT::riscv_nxv16i8x4, MVT::riscv_nxv32i8x2};
173 auto addRegClassForRVV = [
this](
MVT VT) {
177 if (VT.getVectorMinNumElements() < MinElts)
180 unsigned Size = VT.getSizeInBits().getKnownMinValue();
183 RC = &RISCV::VRRegClass;
185 RC = &RISCV::VRM2RegClass;
187 RC = &RISCV::VRM4RegClass;
189 RC = &RISCV::VRM8RegClass;
196 for (
MVT VT : BoolVecVTs)
197 addRegClassForRVV(VT);
198 for (
MVT VT : IntVecVTs) {
199 if (VT.getVectorElementType() == MVT::i64 &&
202 addRegClassForRVV(VT);
206 for (
MVT VT : F16VecVTs)
207 addRegClassForRVV(VT);
210 for (
MVT VT : BF16VecVTs)
211 addRegClassForRVV(VT);
214 for (
MVT VT : F32VecVTs)
215 addRegClassForRVV(VT);
218 for (
MVT VT : F64VecVTs)
219 addRegClassForRVV(VT);
222 auto addRegClassForFixedVectors = [
this](
MVT VT) {
229 if (useRVVForFixedLengthVectorVT(VT))
230 addRegClassForFixedVectors(VT);
233 if (useRVVForFixedLengthVectorVT(VT))
234 addRegClassForFixedVectors(VT);
294 if (!(Subtarget.hasVendorXCValu() && !Subtarget.
is64Bit())) {
304 if (!Subtarget.hasVendorXTHeadBb())
309 if (!Subtarget.hasStdExtZbb() && !Subtarget.hasVendorXTHeadBb() &&
310 !(Subtarget.hasVendorXCValu() && !Subtarget.
is64Bit()))
320 if (!Subtarget.hasStdExtZbb())
326 if (!Subtarget.hasStdExtZmmul()) {
328 }
else if (Subtarget.
is64Bit()) {
335 if (!Subtarget.hasStdExtM()) {
338 }
else if (Subtarget.
is64Bit()) {
340 {MVT::i8, MVT::i16, MVT::i32},
Custom);
350 if (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) {
353 }
else if (Subtarget.hasVendorXTHeadBb()) {
357 }
else if (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit()) {
366 (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb() ||
367 Subtarget.hasVendorXTHeadBb())
371 if (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit()) {
379 if (Subtarget.hasStdExtZbb() ||
380 (Subtarget.hasVendorXCValu() && !Subtarget.
is64Bit())) {
385 if (Subtarget.hasStdExtZbb() ||
386 (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit())) {
393 if (Subtarget.hasStdExtZbb() || Subtarget.hasVendorXTHeadBb() ||
394 (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit())) {
403 if (Subtarget.hasVendorXCValu() && !Subtarget.
is64Bit()) {
405 }
else if (Subtarget.hasShortForwardBranchOpt()) {
408 }
else if (Subtarget.
is64Bit()) {
414 else if (!Subtarget.hasVendorXTHeadCondMov())
417 static const unsigned FPLegalNodeTypes[] = {
431 static const unsigned FPOpToExpand[] = {
435 static const unsigned FPRndMode[] = {
439 static const unsigned ZfhminZfbfminPromoteOps[] = {
450 if (Subtarget.hasStdExtZfbfmin()) {
473 if (Subtarget.hasStdExtZfa())
500 Subtarget.hasStdExtZfh() && Subtarget.hasStdExtZfa() ?
Legal :
Promote);
542 if (Subtarget.hasStdExtZfa()) {
560 if (Subtarget.hasStdExtZfa()) {
642 if (Subtarget.hasStdExtZicbop()) {
646 if (Subtarget.hasStdExtA()) {
648 if (Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas())
652 }
else if (Subtarget.hasForcedAtomics()) {
676 {MVT::i8, MVT::i16},
Custom);
687 static const unsigned IntegerVPOps[] = {
688 ISD::VP_ADD, ISD::VP_SUB, ISD::VP_MUL,
689 ISD::VP_SDIV, ISD::VP_UDIV, ISD::VP_SREM,
690 ISD::VP_UREM, ISD::VP_AND, ISD::VP_OR,
691 ISD::VP_XOR, ISD::VP_SRA, ISD::VP_SRL,
692 ISD::VP_SHL, ISD::VP_REDUCE_ADD, ISD::VP_REDUCE_AND,
693 ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR, ISD::VP_REDUCE_SMAX,
694 ISD::VP_REDUCE_SMIN, ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN,
695 ISD::VP_MERGE, ISD::VP_SELECT, ISD::VP_FP_TO_SINT,
696 ISD::VP_FP_TO_UINT, ISD::VP_SETCC, ISD::VP_SIGN_EXTEND,
697 ISD::VP_ZERO_EXTEND, ISD::VP_TRUNCATE, ISD::VP_SMIN,
698 ISD::VP_SMAX, ISD::VP_UMIN, ISD::VP_UMAX,
699 ISD::VP_ABS, ISD::EXPERIMENTAL_VP_REVERSE, ISD::EXPERIMENTAL_VP_SPLICE,
700 ISD::VP_SADDSAT, ISD::VP_UADDSAT, ISD::VP_SSUBSAT,
701 ISD::VP_USUBSAT, ISD::VP_CTTZ_ELTS, ISD::VP_CTTZ_ELTS_ZERO_UNDEF,
702 ISD::EXPERIMENTAL_VP_SPLAT};
704 static const unsigned FloatingPointVPOps[] = {
705 ISD::VP_FADD, ISD::VP_FSUB, ISD::VP_FMUL,
706 ISD::VP_FDIV, ISD::VP_FNEG, ISD::VP_FABS,
707 ISD::VP_FMA, ISD::VP_REDUCE_FADD, ISD::VP_REDUCE_SEQ_FADD,
708 ISD::VP_REDUCE_FMIN, ISD::VP_REDUCE_FMAX, ISD::VP_MERGE,
709 ISD::VP_SELECT, ISD::VP_SINT_TO_FP, ISD::VP_UINT_TO_FP,
710 ISD::VP_SETCC, ISD::VP_FP_ROUND, ISD::VP_FP_EXTEND,
711 ISD::VP_SQRT, ISD::VP_FMINNUM, ISD::VP_FMAXNUM,
712 ISD::VP_FCEIL, ISD::VP_FFLOOR, ISD::VP_FROUND,
713 ISD::VP_FROUNDEVEN, ISD::VP_FCOPYSIGN, ISD::VP_FROUNDTOZERO,
714 ISD::VP_FRINT, ISD::VP_FNEARBYINT, ISD::VP_IS_FPCLASS,
715 ISD::VP_FMINIMUM, ISD::VP_FMAXIMUM, ISD::VP_LRINT,
716 ISD::VP_LLRINT, ISD::EXPERIMENTAL_VP_REVERSE,
717 ISD::EXPERIMENTAL_VP_SPLICE, ISD::VP_REDUCE_FMINIMUM,
718 ISD::VP_REDUCE_FMAXIMUM, ISD::EXPERIMENTAL_VP_SPLAT};
720 static const unsigned IntegerVecReduceOps[] = {
725 static const unsigned FloatingPointVecReduceOps[] = {
729 static const unsigned FloatingPointLibCallOps[] = {
742 ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR,
743 ISD::VP_REDUCE_SMAX, ISD::VP_REDUCE_SMIN,
744 ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN},
748 for (
MVT VT : BoolVecVTs) {
778 {ISD::VP_REDUCE_AND, ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR}, VT,
802 ISD::VP_TRUNCATE, ISD::VP_SETCC},
818 for (
MVT VT : IntVecVTs) {
829 if (VT.getVectorElementType() == MVT::i64 && !Subtarget.hasStdExtV())
879 {ISD::VP_LOAD, ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
880 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER, ISD::VP_SCATTER},
904 if (Subtarget.hasStdExtZvkb()) {
912 if (Subtarget.hasStdExtZvbb()) {
916 ISD::VP_CTTZ_ZERO_UNDEF, ISD::VP_CTPOP},
922 ISD::VP_CTTZ_ZERO_UNDEF, ISD::VP_CTPOP},
931 ISD::VP_CTLZ_ZERO_UNDEF, ISD::VP_CTTZ_ZERO_UNDEF},
939 for (
MVT VT : VecTupleVTs) {
960 static const unsigned ZvfhminZvfbfminPromoteOps[] = {
970 static const unsigned ZvfhminZvfbfminPromoteVPOps[] = {
985 ISD::VP_FROUNDTOZERO,
991 ISD::VP_REDUCE_FMINIMUM,
992 ISD::VP_REDUCE_FMAXIMUM};
995 const auto SetCommonVFPActions = [&](
MVT VT) {
1030 {ISD::VP_LOAD, ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1031 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER, ISD::VP_SCATTER},
1064 const auto SetCommonVFPExtLoadTruncStoreActions =
1066 for (
auto SmallVT : SmallerVTs) {
1074 const auto SetCommonPromoteToF32Actions = [&](
MVT VT) {
1099 ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1100 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1123 for (
MVT VT : F16VecVTs) {
1126 SetCommonVFPActions(VT);
1129 for (
MVT VT : F16VecVTs) {
1132 SetCommonPromoteToF32Actions(VT);
1137 for (
MVT VT : BF16VecVTs) {
1140 SetCommonPromoteToF32Actions(VT);
1145 for (
MVT VT : F32VecVTs) {
1148 SetCommonVFPActions(VT);
1149 SetCommonVFPExtLoadTruncStoreActions(VT, F16VecVTs);
1150 SetCommonVFPExtLoadTruncStoreActions(VT, BF16VecVTs);
1155 for (
MVT VT : F64VecVTs) {
1158 SetCommonVFPActions(VT);
1159 SetCommonVFPExtLoadTruncStoreActions(VT, F16VecVTs);
1160 SetCommonVFPExtLoadTruncStoreActions(VT, BF16VecVTs);
1161 SetCommonVFPExtLoadTruncStoreActions(VT, F32VecVTs);
1167 if (!useRVVForFixedLengthVectorVT(VT))
1213 {ISD::VP_REDUCE_AND, ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR}, VT,
1240 ISD::VP_SETCC, ISD::VP_TRUNCATE},
1264 ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1265 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1302 if (Subtarget.hasStdExtZvkb())
1305 if (Subtarget.hasStdExtZvbb()) {
1329 if (!useRVVForFixedLengthVectorVT(VT))
1350 ISD::VP_SCATTER, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1351 ISD::EXPERIMENTAL_VP_STRIDED_STORE},
1367 if (Subtarget.hasStdExtZfhmin()) {
1391 if (Subtarget.hasStdExtZfbfmin()) {
1451 if (Subtarget.hasStdExtZfbfmin())
1460 if (Subtarget.hasStdExtA())
1463 if (Subtarget.hasForcedAtomics()) {
1473 if (Subtarget.hasVendorXTHeadMemIdx()) {
1489 if (Subtarget.hasVendorXCVmem() && !Subtarget.
is64Bit()) {
1515 if (Subtarget.hasStdExtZbb())
1518 if ((Subtarget.hasStdExtZbs() && Subtarget.
is64Bit()) ||
1522 if (Subtarget.hasStdExtZbkb())
1531 ISD::VP_GATHER, ISD::VP_SCATTER,
ISD::SRA,
1534 ISD::VP_STORE, ISD::VP_TRUNCATE, ISD::EXPERIMENTAL_VP_REVERSE,
1540 if (Subtarget.hasVendorXTHeadMemPair())
1583MVT RISCVTargetLowering::getVPExplicitVectorLengthTy()
const {
1588bool RISCVTargetLowering::shouldExpandGetVectorLength(
EVT TripCountVT,
1590 bool IsScalable)
const {
1597 if (TripCountVT != MVT::i32 && TripCountVT != Subtarget.
getXLenVT())
1622 unsigned Intrinsic)
const {
1623 auto &
DL =
I.getDataLayout();
1625 auto SetRVVLoadStoreInfo = [&](
unsigned PtrOp,
bool IsStore,
1626 bool IsUnitStrided,
bool UsePtrVal =
false) {
1631 Info.ptrVal =
I.getArgOperand(PtrOp);
1633 Info.fallbackAddressSpace =
1634 I.getArgOperand(PtrOp)->getType()->getPointerAddressSpace();
1638 MemTy =
I.getArgOperand(0)->getType();
1641 MemTy =
I.getType();
1651 if (cast<TargetExtType>(MemTy)->
getName() ==
"riscv.vector.tuple")
1654 1 << cast<ConstantInt>(
I.getArgOperand(
I.arg_size() - 1))
1656 Info.align =
DL.getABITypeAlign(MemTy);
1666 if (
I.hasMetadata(LLVMContext::MD_nontemporal))
1670 switch (Intrinsic) {
1673 case Intrinsic::riscv_masked_atomicrmw_xchg_i32:
1674 case Intrinsic::riscv_masked_atomicrmw_add_i32:
1675 case Intrinsic::riscv_masked_atomicrmw_sub_i32:
1676 case Intrinsic::riscv_masked_atomicrmw_nand_i32:
1677 case Intrinsic::riscv_masked_atomicrmw_max_i32:
1678 case Intrinsic::riscv_masked_atomicrmw_min_i32:
1679 case Intrinsic::riscv_masked_atomicrmw_umax_i32:
1680 case Intrinsic::riscv_masked_atomicrmw_umin_i32:
1681 case Intrinsic::riscv_masked_cmpxchg_i32:
1683 Info.memVT = MVT::i32;
1684 Info.ptrVal =
I.getArgOperand(0);
1690 case Intrinsic::riscv_seg2_load:
1691 case Intrinsic::riscv_seg3_load:
1692 case Intrinsic::riscv_seg4_load:
1693 case Intrinsic::riscv_seg5_load:
1694 case Intrinsic::riscv_seg6_load:
1695 case Intrinsic::riscv_seg7_load:
1696 case Intrinsic::riscv_seg8_load:
1697 return SetRVVLoadStoreInfo( 0,
false,
1699 case Intrinsic::riscv_seg2_store:
1700 case Intrinsic::riscv_seg3_store:
1701 case Intrinsic::riscv_seg4_store:
1702 case Intrinsic::riscv_seg5_store:
1703 case Intrinsic::riscv_seg6_store:
1704 case Intrinsic::riscv_seg7_store:
1705 case Intrinsic::riscv_seg8_store:
1707 return SetRVVLoadStoreInfo(
I.arg_size() - 2,
1710 case Intrinsic::riscv_vle:
1711 case Intrinsic::riscv_vle_mask:
1712 case Intrinsic::riscv_vleff:
1713 case Intrinsic::riscv_vleff_mask:
1714 return SetRVVLoadStoreInfo( 1,
1718 case Intrinsic::riscv_vse:
1719 case Intrinsic::riscv_vse_mask:
1720 return SetRVVLoadStoreInfo( 1,
1724 case Intrinsic::riscv_vlse:
1725 case Intrinsic::riscv_vlse_mask:
1726 case Intrinsic::riscv_vloxei:
1727 case Intrinsic::riscv_vloxei_mask:
1728 case Intrinsic::riscv_vluxei:
1729 case Intrinsic::riscv_vluxei_mask:
1730 return SetRVVLoadStoreInfo( 1,
1733 case Intrinsic::riscv_vsse:
1734 case Intrinsic::riscv_vsse_mask:
1735 case Intrinsic::riscv_vsoxei:
1736 case Intrinsic::riscv_vsoxei_mask:
1737 case Intrinsic::riscv_vsuxei:
1738 case Intrinsic::riscv_vsuxei_mask:
1739 return SetRVVLoadStoreInfo( 1,
1742 case Intrinsic::riscv_vlseg2:
1743 case Intrinsic::riscv_vlseg3:
1744 case Intrinsic::riscv_vlseg4:
1745 case Intrinsic::riscv_vlseg5:
1746 case Intrinsic::riscv_vlseg6:
1747 case Intrinsic::riscv_vlseg7:
1748 case Intrinsic::riscv_vlseg8:
1749 case Intrinsic::riscv_vlseg2ff:
1750 case Intrinsic::riscv_vlseg3ff:
1751 case Intrinsic::riscv_vlseg4ff:
1752 case Intrinsic::riscv_vlseg5ff:
1753 case Intrinsic::riscv_vlseg6ff:
1754 case Intrinsic::riscv_vlseg7ff:
1755 case Intrinsic::riscv_vlseg8ff:
1756 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1759 case Intrinsic::riscv_vlseg2_mask:
1760 case Intrinsic::riscv_vlseg3_mask:
1761 case Intrinsic::riscv_vlseg4_mask:
1762 case Intrinsic::riscv_vlseg5_mask:
1763 case Intrinsic::riscv_vlseg6_mask:
1764 case Intrinsic::riscv_vlseg7_mask:
1765 case Intrinsic::riscv_vlseg8_mask:
1766 case Intrinsic::riscv_vlseg2ff_mask:
1767 case Intrinsic::riscv_vlseg3ff_mask:
1768 case Intrinsic::riscv_vlseg4ff_mask:
1769 case Intrinsic::riscv_vlseg5ff_mask:
1770 case Intrinsic::riscv_vlseg6ff_mask:
1771 case Intrinsic::riscv_vlseg7ff_mask:
1772 case Intrinsic::riscv_vlseg8ff_mask:
1773 return SetRVVLoadStoreInfo(
I.arg_size() - 5,
1776 case Intrinsic::riscv_vlsseg2:
1777 case Intrinsic::riscv_vlsseg3:
1778 case Intrinsic::riscv_vlsseg4:
1779 case Intrinsic::riscv_vlsseg5:
1780 case Intrinsic::riscv_vlsseg6:
1781 case Intrinsic::riscv_vlsseg7:
1782 case Intrinsic::riscv_vlsseg8:
1783 case Intrinsic::riscv_vloxseg2:
1784 case Intrinsic::riscv_vloxseg3:
1785 case Intrinsic::riscv_vloxseg4:
1786 case Intrinsic::riscv_vloxseg5:
1787 case Intrinsic::riscv_vloxseg6:
1788 case Intrinsic::riscv_vloxseg7:
1789 case Intrinsic::riscv_vloxseg8:
1790 case Intrinsic::riscv_vluxseg2:
1791 case Intrinsic::riscv_vluxseg3:
1792 case Intrinsic::riscv_vluxseg4:
1793 case Intrinsic::riscv_vluxseg5:
1794 case Intrinsic::riscv_vluxseg6:
1795 case Intrinsic::riscv_vluxseg7:
1796 case Intrinsic::riscv_vluxseg8:
1797 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
1800 case Intrinsic::riscv_vlsseg2_mask:
1801 case Intrinsic::riscv_vlsseg3_mask:
1802 case Intrinsic::riscv_vlsseg4_mask:
1803 case Intrinsic::riscv_vlsseg5_mask:
1804 case Intrinsic::riscv_vlsseg6_mask:
1805 case Intrinsic::riscv_vlsseg7_mask:
1806 case Intrinsic::riscv_vlsseg8_mask:
1807 case Intrinsic::riscv_vloxseg2_mask:
1808 case Intrinsic::riscv_vloxseg3_mask:
1809 case Intrinsic::riscv_vloxseg4_mask:
1810 case Intrinsic::riscv_vloxseg5_mask:
1811 case Intrinsic::riscv_vloxseg6_mask:
1812 case Intrinsic::riscv_vloxseg7_mask:
1813 case Intrinsic::riscv_vloxseg8_mask:
1814 case Intrinsic::riscv_vluxseg2_mask:
1815 case Intrinsic::riscv_vluxseg3_mask:
1816 case Intrinsic::riscv_vluxseg4_mask:
1817 case Intrinsic::riscv_vluxseg5_mask:
1818 case Intrinsic::riscv_vluxseg6_mask:
1819 case Intrinsic::riscv_vluxseg7_mask:
1820 case Intrinsic::riscv_vluxseg8_mask:
1821 return SetRVVLoadStoreInfo(
I.arg_size() - 6,
1824 case Intrinsic::riscv_vsseg2:
1825 case Intrinsic::riscv_vsseg3:
1826 case Intrinsic::riscv_vsseg4:
1827 case Intrinsic::riscv_vsseg5:
1828 case Intrinsic::riscv_vsseg6:
1829 case Intrinsic::riscv_vsseg7:
1830 case Intrinsic::riscv_vsseg8:
1831 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1834 case Intrinsic::riscv_vsseg2_mask:
1835 case Intrinsic::riscv_vsseg3_mask:
1836 case Intrinsic::riscv_vsseg4_mask:
1837 case Intrinsic::riscv_vsseg5_mask:
1838 case Intrinsic::riscv_vsseg6_mask:
1839 case Intrinsic::riscv_vsseg7_mask:
1840 case Intrinsic::riscv_vsseg8_mask:
1841 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
1844 case Intrinsic::riscv_vssseg2:
1845 case Intrinsic::riscv_vssseg3:
1846 case Intrinsic::riscv_vssseg4:
1847 case Intrinsic::riscv_vssseg5:
1848 case Intrinsic::riscv_vssseg6:
1849 case Intrinsic::riscv_vssseg7:
1850 case Intrinsic::riscv_vssseg8:
1851 case Intrinsic::riscv_vsoxseg2:
1852 case Intrinsic::riscv_vsoxseg3:
1853 case Intrinsic::riscv_vsoxseg4:
1854 case Intrinsic::riscv_vsoxseg5:
1855 case Intrinsic::riscv_vsoxseg6:
1856 case Intrinsic::riscv_vsoxseg7:
1857 case Intrinsic::riscv_vsoxseg8:
1858 case Intrinsic::riscv_vsuxseg2:
1859 case Intrinsic::riscv_vsuxseg3:
1860 case Intrinsic::riscv_vsuxseg4:
1861 case Intrinsic::riscv_vsuxseg5:
1862 case Intrinsic::riscv_vsuxseg6:
1863 case Intrinsic::riscv_vsuxseg7:
1864 case Intrinsic::riscv_vsuxseg8:
1865 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
1868 case Intrinsic::riscv_vssseg2_mask:
1869 case Intrinsic::riscv_vssseg3_mask:
1870 case Intrinsic::riscv_vssseg4_mask:
1871 case Intrinsic::riscv_vssseg5_mask:
1872 case Intrinsic::riscv_vssseg6_mask:
1873 case Intrinsic::riscv_vssseg7_mask:
1874 case Intrinsic::riscv_vssseg8_mask:
1875 case Intrinsic::riscv_vsoxseg2_mask:
1876 case Intrinsic::riscv_vsoxseg3_mask:
1877 case Intrinsic::riscv_vsoxseg4_mask:
1878 case Intrinsic::riscv_vsoxseg5_mask:
1879 case Intrinsic::riscv_vsoxseg6_mask:
1880 case Intrinsic::riscv_vsoxseg7_mask:
1881 case Intrinsic::riscv_vsoxseg8_mask:
1882 case Intrinsic::riscv_vsuxseg2_mask:
1883 case Intrinsic::riscv_vsuxseg3_mask:
1884 case Intrinsic::riscv_vsuxseg4_mask:
1885 case Intrinsic::riscv_vsuxseg5_mask:
1886 case Intrinsic::riscv_vsuxseg6_mask:
1887 case Intrinsic::riscv_vsuxseg7_mask:
1888 case Intrinsic::riscv_vsuxseg8_mask:
1889 return SetRVVLoadStoreInfo(
I.arg_size() - 5,
1930 return isInt<12>(Imm);
1934 return isInt<12>(Imm);
1947 return (SrcBits == 64 && DestBits == 32);
1958 return (SrcBits == 64 && DestBits == 32);
1969 if (SrcBits == DestBits * 2) {
1980 if (
auto *LD = dyn_cast<LoadSDNode>(Val)) {
1981 EVT MemVT = LD->getMemoryVT();
1982 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
1992 return Subtarget.
is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
2000 return Subtarget.hasStdExtZbb() ||
2001 (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit());
2005 return Subtarget.hasStdExtZbb() || Subtarget.hasVendorXTHeadBb() ||
2006 (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit());
2017 if (!Subtarget.hasStdExtZbs() && !Subtarget.hasVendorXTHeadBs())
2022 return !Mask->getValue().isSignedIntN(12) && Mask->getValue().isPowerOf2();
2026 EVT VT =
Y.getValueType();
2032 return (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
2033 (!isa<ConstantSDNode>(
Y) || cast<ConstantSDNode>(
Y)->isOpaque());
2038 if (Subtarget.hasStdExtZbs())
2039 return X.getValueType().isScalarInteger();
2040 auto *
C = dyn_cast<ConstantSDNode>(
Y);
2042 if (Subtarget.hasVendorXTHeadBs())
2043 return C !=
nullptr;
2045 return C &&
C->getAPIntValue().ule(10);
2065 if (BitSize > Subtarget.
getXLen())
2069 int64_t Val = Imm.getSExtValue();
2077 if (!Subtarget.enableUnalignedScalarMem())
2093 unsigned OldShiftOpcode,
unsigned NewShiftOpcode,
2100 if (XC && OldShiftOpcode ==
ISD::SRL && XC->isOne())
2104 if (NewShiftOpcode ==
ISD::SRL &&
CC->isOne())
2148 if (!Subtarget.hasStdExtZfa())
2151 bool IsSupportedVT =
false;
2152 if (VT == MVT::f16) {
2153 IsSupportedVT = Subtarget.hasStdExtZfh() || Subtarget.hasStdExtZvfh();
2154 }
else if (VT == MVT::f32) {
2155 IsSupportedVT =
true;
2156 }
else if (VT == MVT::f64) {
2157 assert(Subtarget.hasStdExtD() &&
"Expect D extension");
2158 IsSupportedVT =
true;
2168 bool ForCodeSize)
const {
2169 bool IsLegalVT =
false;
2172 else if (VT == MVT::f32)
2174 else if (VT == MVT::f64)
2176 else if (VT == MVT::bf16)
2177 IsLegalVT = Subtarget.hasStdExtZfbfmin();
2189 return Imm.isZero();
2193 if (Imm.isNegZero())
2198 const int FmvCost = Subtarget.hasStdExtZfinx() ? 0 : 1;
2201 Subtarget.
getXLen(), Subtarget);
2207 unsigned Index)
const {
2220 if (EltVT == MVT::i1)
2233 if (Index + ResElts <= MinVLMAX && Index < 31)
2242 return (ResElts * 2) == SrcElts && (Index == 0 || Index == ResElts);
2261 std::optional<MVT> RegisterVT)
const {
2263 if (VT == (Subtarget.
is64Bit() ? MVT::i128 : MVT::i64) && RegisterVT &&
2264 *RegisterVT == MVT::Untyped)
2284 unsigned &NumIntermediates,
MVT &RegisterVT)
const {
2286 Context,
CC, VT, IntermediateVT, NumIntermediates, RegisterVT);
2301 isa<ConstantSDNode>(
LHS.getOperand(1))) {
2307 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
2320 if (
auto *RHSC = dyn_cast<ConstantSDNode>(
RHS)) {
2321 int64_t
C = RHSC->getSExtValue();
2359 if (VT.
SimpleTy >= MVT::riscv_nxv1i8x2 &&
2360 VT.
SimpleTy <= MVT::riscv_nxv1i8x8)
2362 if (VT.
SimpleTy >= MVT::riscv_nxv2i8x2 &&
2363 VT.
SimpleTy <= MVT::riscv_nxv2i8x8)
2365 if (VT.
SimpleTy >= MVT::riscv_nxv4i8x2 &&
2366 VT.
SimpleTy <= MVT::riscv_nxv4i8x8)
2368 if (VT.
SimpleTy >= MVT::riscv_nxv8i8x2 &&
2369 VT.
SimpleTy <= MVT::riscv_nxv8i8x8)
2371 if (VT.
SimpleTy >= MVT::riscv_nxv16i8x2 &&
2372 VT.
SimpleTy <= MVT::riscv_nxv16i8x4)
2374 if (VT.
SimpleTy == MVT::riscv_nxv32i8x2)
2384 switch (KnownSize) {
2412 return RISCV::VRRegClassID;
2414 return RISCV::VRM2RegClassID;
2416 return RISCV::VRM4RegClassID;
2418 return RISCV::VRM8RegClassID;
2428 static_assert(RISCV::sub_vrm1_7 == RISCV::sub_vrm1_0 + 7,
2429 "Unexpected subreg numbering");
2430 return RISCV::sub_vrm1_0 + Index;
2433 static_assert(RISCV::sub_vrm2_3 == RISCV::sub_vrm2_0 + 3,
2434 "Unexpected subreg numbering");
2435 return RISCV::sub_vrm2_0 + Index;
2438 static_assert(RISCV::sub_vrm4_1 == RISCV::sub_vrm4_0 + 1,
2439 "Unexpected subreg numbering");
2440 return RISCV::sub_vrm4_0 + Index;
2448 unsigned RegsPerField =
2451 switch (RegsPerField) {
2454 return RISCV::VRN2M1RegClassID;
2456 return RISCV::VRN3M1RegClassID;
2458 return RISCV::VRN4M1RegClassID;
2460 return RISCV::VRN5M1RegClassID;
2462 return RISCV::VRN6M1RegClassID;
2464 return RISCV::VRN7M1RegClassID;
2466 return RISCV::VRN8M1RegClassID;
2470 return RISCV::VRN2M2RegClassID;
2472 return RISCV::VRN3M2RegClassID;
2474 return RISCV::VRN4M2RegClassID;
2478 return RISCV::VRN2M4RegClassID;
2486 return RISCV::VRRegClassID;
2495std::pair<unsigned, unsigned>
2497 MVT VecVT,
MVT SubVecVT,
unsigned InsertExtractIdx,
2499 static_assert((RISCV::VRM8RegClassID > RISCV::VRM4RegClassID &&
2500 RISCV::VRM4RegClassID > RISCV::VRM2RegClassID &&
2501 RISCV::VRM2RegClassID > RISCV::VRRegClassID),
2502 "Register classes not ordered");
2509 if (VecRegClassID == SubRegClassID)
2510 return {RISCV::NoSubRegister, 0};
2513 "Only allow scalable vector subvector.");
2515 "Invalid vector tuple insert/extract for vector and subvector with "
2526 unsigned SubRegIdx = RISCV::NoSubRegister;
2527 for (
const unsigned RCID :
2528 {RISCV::VRM4RegClassID, RISCV::VRM2RegClassID, RISCV::VRRegClassID})
2529 if (VecRegClassID > RCID && SubRegClassID <= RCID) {
2533 SubRegIdx =
TRI->composeSubRegIndices(SubRegIdx,
2538 return {SubRegIdx, InsertExtractIdx};
2543bool RISCVTargetLowering::mergeStoresAfterLegalization(
EVT VT)
const {
2574unsigned RISCVTargetLowering::combineRepeatedFPDivisors()
const {
2581 "Unexpected opcode");
2583 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
2585 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
2588 return Op.getOperand(
II->VLOperand + 1 + HasChain);
2662bool RISCVTargetLowering::useRVVForFixedLengthVectorVT(
MVT VT)
const {
2663 return ::useRVVForFixedLengthVectorVT(VT, Subtarget);
2672 "Expected legal fixed length vector!");
2675 unsigned MaxELen = Subtarget.
getELen();
2709 return ::getContainerForFixedLengthVector(*
this, VT,
getSubtarget());
2716 "Expected to convert into a scalable vector!");
2717 assert(V.getValueType().isFixedLengthVector() &&
2718 "Expected a fixed length vector operand!");
2728 "Expected to convert into a fixed length vector!");
2729 assert(V.getValueType().isScalableVector() &&
2730 "Expected a scalable vector operand!");
2753static std::pair<SDValue, SDValue>
2762static std::pair<SDValue, SDValue>
2775static std::pair<SDValue, SDValue>
2792std::pair<unsigned, unsigned>
2808 return std::make_pair(MinVLMAX, MaxVLMAX);
2820 EVT VT,
unsigned DefinedValues)
const {
2834 std::tie(LMul, Fractional) =
2837 Cost = LMul <= DLenFactor ? (DLenFactor / LMul) : 1;
2839 Cost = (LMul * DLenFactor);
2882 Op.getValueType() == MVT::bf16) {
2883 bool IsStrict =
Op->isStrictFPOpcode();
2888 {Op.getOperand(0), Op.getOperand(1)});
2890 {
Op.getValueType(), MVT::Other},
2896 DAG.
getNode(
Op.getOpcode(),
DL, MVT::f32,
Op.getOperand(0)),
2911 MVT DstVT =
Op.getSimpleValueType();
2912 EVT SatVT = cast<VTSDNode>(
Op.getOperand(1))->getVT();
2920 Src.getValueType() == MVT::bf16) {
2927 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
2935 Opc,
DL, DstVT, Src,
2949 MVT SrcVT = Src.getSimpleValueType();
2955 if (SatVT != DstEltVT)
2958 MVT DstContainerVT = DstVT;
2959 MVT SrcContainerVT = SrcVT;
2965 "Expected same element count");
2974 {Src, Src, DAG.getCondCode(ISD::SETNE),
2975 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
2979 if (DstEltSize > (2 * SrcEltSize)) {
2985 MVT CvtContainerVT = DstContainerVT;
2986 MVT CvtEltVT = DstEltVT;
2987 if (SrcEltSize > (2 * DstEltSize)) {
2996 while (CvtContainerVT != DstContainerVT) {
3002 Res = DAG.
getNode(ClipOpc,
DL, CvtContainerVT, Res, Mask, VL);
3009 Res, DAG.
getUNDEF(DstContainerVT), VL);
3019 bool IsStrict =
Op->isStrictFPOpcode();
3020 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
3030 {
Op.getOperand(0), SrcVal});
3031 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
3032 {Ext.getValue(1), Ext.getValue(0)});
3046 case ISD::VP_FROUNDEVEN:
3050 case ISD::VP_FROUNDTOZERO:
3054 case ISD::VP_FFLOOR:
3062 case ISD::VP_FROUND:
3079 MVT VT =
Op.getSimpleValueType();
3086 MVT ContainerVT = VT;
3093 if (
Op->isVPOpcode()) {
3094 Mask =
Op.getOperand(1);
3098 VL =
Op.getOperand(2);
3120 DAG.
getUNDEF(ContainerVT), MaxValNode, VL);
3134 switch (
Op.getOpcode()) {
3142 case ISD::VP_FFLOOR:
3145 case ISD::VP_FROUND:
3146 case ISD::VP_FROUNDEVEN:
3147 case ISD::VP_FROUNDTOZERO: {
3159 case ISD::VP_FNEARBYINT:
3172 Src, Src, Mask, VL);
3187 MVT VT =
Op.getSimpleValueType();
3191 MVT ContainerVT = VT;
3203 MVT MaskVT = Mask.getSimpleValueType();
3206 {Chain, Src, Src, DAG.getCondCode(ISD::SETUNE),
3207 DAG.getUNDEF(MaskVT), Mask, VL});
3211 {Chain, Src, Src, Src, Unorder, VL});
3212 Chain = Src.getValue(1);
3228 DAG.
getUNDEF(ContainerVT), MaxValNode, VL);
3240 switch (
Op.getOpcode()) {
3251 {Chain, Src, Mask, DAG.getTargetConstant(FRM, DL, XLenVT), VL});
3257 DAG.
getVTList(IntVT, MVT::Other), Chain, Src, Mask, VL);
3261 DAG.
getVTList(ContainerVT, MVT::Other), Chain, Src,
3270 DAG.
getVTList(ContainerVT, MVT::Other), Chain,
3271 Truncated, Mask, VL);
3277 Src, Src, Mask, VL);
3287 MVT VT =
Op.getSimpleValueType();
3315 MVT VT =
Op.getSimpleValueType();
3320 MVT ContainerVT = VT;
3365 "Unexpected vector MVT");
3393 return std::nullopt;
3411 unsigned EltSizeInBits) {
3414 return std::nullopt;
3415 bool IsInteger =
Op.getValueType().isInteger();
3417 std::optional<unsigned> SeqStepDenom;
3418 std::optional<APInt> SeqStepNum;
3419 std::optional<APInt> SeqAddend;
3420 std::optional<std::pair<APInt, unsigned>> PrevElt;
3421 assert(EltSizeInBits >=
Op.getValueType().getScalarSizeInBits());
3426 const unsigned OpSize =
Op.getScalarValueSizeInBits();
3428 if (Elt.isUndef()) {
3429 Elts[
Idx] = std::nullopt;
3433 Elts[
Idx] = Elt->getAsAPIntVal().trunc(OpSize).zext(EltSizeInBits);
3438 return std::nullopt;
3439 Elts[
Idx] = *ExactInteger;
3452 unsigned IdxDiff =
Idx - PrevElt->second;
3453 APInt ValDiff = *Elt - PrevElt->first;
3461 int64_t Remainder = ValDiff.
srem(IdxDiff);
3466 return std::nullopt;
3467 ValDiff = ValDiff.
sdiv(IdxDiff);
3472 SeqStepNum = ValDiff;
3473 else if (ValDiff != SeqStepNum)
3474 return std::nullopt;
3477 SeqStepDenom = IdxDiff;
3478 else if (IdxDiff != *SeqStepDenom)
3479 return std::nullopt;
3483 if (!PrevElt || PrevElt->first != *Elt)
3484 PrevElt = std::make_pair(*Elt,
Idx);
3488 if (!SeqStepNum || !SeqStepDenom)
3489 return std::nullopt;
3497 (
APInt(EltSizeInBits,
Idx,
false,
true) *
3499 .sdiv(*SeqStepDenom);
3501 APInt Addend = *Elt - ExpectedVal;
3504 else if (Addend != SeqAddend)
3505 return std::nullopt;
3508 assert(SeqAddend &&
"Must have an addend if we have a step");
3510 return VIDSequence{SeqStepNum->getSExtValue(), *SeqStepDenom,
3511 SeqAddend->getSExtValue()};
3526 MVT SrcVT = Src.getSimpleValueType();
3536 auto *CIdx = dyn_cast<ConstantSDNode>(
Idx);
3542 MVT ContainerVT = VT;
3546 MVT SrcContainerVT = SrcVT;
3581 MVT VT =
Op.getSimpleValueType();
3593 unsigned MostCommonCount = 0;
3595 unsigned NumUndefElts =
3603 unsigned NumScalarLoads = 0;
3609 unsigned &Count = ValueCounts[V];
3611 if (
auto *CFP = dyn_cast<ConstantFPSDNode>(V))
3612 NumScalarLoads += !CFP->isExactlyValue(+0.0);
3617 if (++Count >= MostCommonCount) {
3619 MostCommonCount = Count;
3623 assert(DominantValue &&
"Not expecting an all-undef BUILD_VECTOR");
3624 unsigned NumDefElts = NumElts - NumUndefElts;
3625 unsigned DominantValueCountThreshold = NumDefElts <= 2 ? 0 : NumDefElts - 2;
3631 ((MostCommonCount > DominantValueCountThreshold) ||
3644 !LastOp.isUndef() && ValueCounts[LastOp] == 1 &&
3645 LastOp != DominantValue) {
3654 Processed.insert(LastOp);
3659 const SDValue &V = OpIdx.value();
3660 if (V.isUndef() || !Processed.insert(V).second)
3662 if (ValueCounts[V] == 1) {
3671 return DAG.getConstant(V == V1, DL, XLenVT);
3687 MVT VT =
Op.getSimpleValueType();
3717 unsigned NumViaIntegerBits = std::clamp(NumElts, 8u, Subtarget.
getXLen());
3718 NumViaIntegerBits = std::min(NumViaIntegerBits, Subtarget.
getELen());
3726 unsigned IntegerViaVecElts =
divideCeil(NumElts, NumViaIntegerBits);
3727 MVT IntegerViaVecVT =
3732 unsigned BitPos = 0, IntegerEltIdx = 0;
3735 for (
unsigned I = 0;
I < NumElts;) {
3737 bool BitValue = !V.isUndef() && V->getAsZExtVal();
3738 Bits |= ((
uint64_t)BitValue << BitPos);
3744 if (
I % NumViaIntegerBits == 0 ||
I == NumElts) {
3745 if (NumViaIntegerBits <= 32)
3746 Bits = SignExtend64<32>(Bits);
3748 Elts[IntegerEltIdx] = Elt;
3757 if (NumElts < NumViaIntegerBits) {
3761 assert(IntegerViaVecVT == MVT::v1i8 &&
"Unexpected mask vector type");
3789 int64_t StepNumerator = SimpleVID->StepNumerator;
3790 unsigned StepDenominator = SimpleVID->StepDenominator;
3791 int64_t Addend = SimpleVID->Addend;
3793 assert(StepNumerator != 0 &&
"Invalid step");
3794 bool Negate =
false;
3795 int64_t SplatStepVal = StepNumerator;
3799 if (StepNumerator != 1 && StepNumerator !=
INT64_MIN &&
3801 Negate = StepNumerator < 0;
3803 SplatStepVal =
Log2_64(std::abs(StepNumerator));
3810 if (((StepOpcode ==
ISD::MUL && isInt<12>(SplatStepVal)) ||
3811 (StepOpcode ==
ISD::SHL && isUInt<5>(SplatStepVal))) &&
3813 (SplatStepVal >= 0 || StepDenominator == 1) && isInt<5>(Addend)) {
3816 MVT VIDContainerVT =
3824 if ((StepOpcode ==
ISD::MUL && SplatStepVal != 1) ||
3825 (StepOpcode ==
ISD::SHL && SplatStepVal != 0)) {
3827 VID = DAG.
getNode(StepOpcode,
DL, VIDVT, VID, SplatStep);
3829 if (StepDenominator != 1) {
3834 if (Addend != 0 || Negate) {
3853 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32) &&
3854 "Unexpected sequence type");
3858 unsigned ViaVecLen =
3862 uint64_t EltMask = maskTrailingOnes<uint64_t>(EltBitSize);
3865 for (
const auto &OpIdx :
enumerate(
Op->op_values())) {
3866 const auto &SeqV = OpIdx.value();
3867 if (!SeqV.isUndef())
3869 ((SeqV->getAsZExtVal() & EltMask) << (OpIdx.index() * EltBitSize));
3875 if (ViaIntVT == MVT::i32)
3876 SplatValue = SignExtend64<32>(SplatValue);
3898 const auto *BV = cast<BuildVectorSDNode>(
Op);
3901 BV->getRepeatedSequence(Sequence) &&
3902 (Sequence.size() * EltBitSize) <= Subtarget.
getELen()) {
3903 unsigned SeqLen = Sequence.size();
3905 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32 ||
3906 ViaIntVT == MVT::i64) &&
3907 "Unexpected sequence type");
3912 const unsigned RequiredVL = NumElts / SeqLen;
3913 const unsigned ViaVecLen =
3915 NumElts : RequiredVL;
3918 unsigned EltIdx = 0;
3919 uint64_t EltMask = maskTrailingOnes<uint64_t>(EltBitSize);
3923 for (
const auto &SeqV : Sequence) {
3924 if (!SeqV.isUndef())
3926 ((SeqV->getAsZExtVal() & EltMask) << (EltIdx * EltBitSize));
3933 if (ViaIntVT == MVT::i32)
3934 SplatValue = SignExtend64<32>(SplatValue);
3940 (!Subtarget.
is64Bit() && ViaIntVT == MVT::i64)) &&
3941 "Unexpected bitcast sequence");
3942 if (ViaIntVT.
bitsLE(XLenVT) || isInt<32>(SplatValue)) {
3945 MVT ViaContainerVT =
3952 if (ViaVecLen != RequiredVL)
3972 Source, DAG, Subtarget);
3992 return RISCV::PACKH;
3994 return Subtarget.
is64Bit() ? RISCV::PACKW : RISCV::PACK;
4009 MVT VT =
Op.getSimpleValueType();
4017 if (!Subtarget.hasStdExtZbb() || !Subtarget.hasStdExtZba())
4022 if (ElemSizeInBits >= std::min(Subtarget.
getELen(), Subtarget.
getXLen()) ||
4036 if (Subtarget.hasStdExtZbkb())
4041 ElemDL, XLenVT,
A,
B),
4053 NewOperands.
reserve(NumElts / 2);
4055 NewOperands.
push_back(pack(
Op.getOperand(i),
Op.getOperand(i + 1)));
4065 MVT VT =
Op.getSimpleValueType();
4076 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) || EltVT == MVT::bf16) {
4081 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4082 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin())) {
4085 if (
auto *
C = dyn_cast<ConstantFPSDNode>(Elem)) {
4169 auto OneVRegOfOps =
ArrayRef(BuildVectorOps).
slice(i, ElemsPerVReg);
4173 unsigned InsertIdx = (i / ElemsPerVReg) * NumOpElts;
4196 unsigned NumUndefElts =
4198 unsigned NumDefElts = NumElts - NumUndefElts;
4199 if (NumDefElts >= 8 && NumDefElts > NumElts / 2 &&
4206 for (
unsigned i = 0; i < NumElts; i++) {
4208 if (i < NumElts / 2) {
4215 bool SelectMaskVal = (i < NumElts / 2);
4218 assert(SubVecAOps.
size() == NumElts && SubVecBOps.
size() == NumElts &&
4219 MaskVals.
size() == NumElts);
4254 unsigned UndefCount = 0;
4261 LinearBudget -= PerSlideCost;
4264 LinearBudget -= PerSlideCost;
4267 LinearBudget -= PerSlideCost;
4270 if (LinearBudget < 0)
4275 "Illegal type which will result in reserved encoding");
4300 Vec,
Offset, Mask, VL, Policy);
4313 Vec,
Offset, Mask, VL, Policy);
4323 if (isa<ConstantSDNode>(
Lo) && isa<ConstantSDNode>(
Hi)) {
4324 int32_t LoC = cast<ConstantSDNode>(
Lo)->getSExtValue();
4325 int32_t HiC = cast<ConstantSDNode>(
Hi)->getSExtValue();
4328 if ((LoC >> 31) == HiC)
4339 (isa<RegisterSDNode>(VL) &&
4340 cast<RegisterSDNode>(VL)->
getReg() == RISCV::X0))
4342 else if (isa<ConstantSDNode>(VL) && isUInt<4>(VL->
getAsZExtVal()))
4357 isa<ConstantSDNode>(
Hi.getOperand(1)) &&
4358 Hi.getConstantOperandVal(1) == 31)
4377 assert(Scalar.getValueType() == MVT::i64 &&
"Unexpected VT!");
4389 bool HasPassthru = Passthru && !Passthru.
isUndef();
4390 if (!HasPassthru && !Passthru)
4397 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
4398 EltVT == MVT::bf16) {
4399 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4400 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
4414 if (Scalar.getValueType().bitsLE(XLenVT)) {
4421 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4425 assert(XLenVT == MVT::i32 && Scalar.getValueType() == MVT::i64 &&
4426 "Unexpected scalar for splat lowering!");
4450 SDValue ExtractedVal = Scalar.getOperand(0);
4455 MVT ExtractedContainerVT = ExtractedVT;
4458 DAG, ExtractedContainerVT, Subtarget);
4460 ExtractedVal, DAG, Subtarget);
4462 if (ExtractedContainerVT.
bitsLE(VT))
4477 if (!Scalar.getValueType().bitsLE(XLenVT))
4480 VT,
DL, DAG, Subtarget);
4488 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4508 if (Src != V2.getOperand(0))
4513 if (!Src.getValueType().isFixedLengthVector() ||
4514 Src.getValueType().getVectorNumElements() != (NumElts * 2))
4519 V2.getConstantOperandVal(1) != NumElts)
4537 int Size = Mask.size();
4539 assert(
Size == (
int)NumElts &&
"Unexpected mask size");
4545 EvenSrc = StartIndexes[0];
4546 OddSrc = StartIndexes[1];
4549 if (EvenSrc != 0 && OddSrc != 0)
4559 int HalfNumElts = NumElts / 2;
4560 return ((EvenSrc % HalfNumElts) == 0) && ((OddSrc % HalfNumElts) == 0);
4576 int Size = Mask.size();
4588 for (
int i = 0; i !=
Size; ++i) {
4594 int StartIdx = i - (M %
Size);
4602 int CandidateRotation = StartIdx < 0 ? -StartIdx :
Size - StartIdx;
4605 Rotation = CandidateRotation;
4606 else if (Rotation != CandidateRotation)
4611 int MaskSrc = M <
Size ? 0 : 1;
4616 int &TargetSrc = StartIdx < 0 ? HiSrc : LoSrc;
4621 TargetSrc = MaskSrc;
4622 else if (TargetSrc != MaskSrc)
4629 assert(Rotation != 0 &&
"Failed to locate a viable rotation!");
4630 assert((LoSrc >= 0 || HiSrc >= 0) &&
4631 "Failed to find a rotated input vector!");
4645 ElementCount SrcEC = Src.getValueType().getVectorElementCount();
4652 unsigned Shift = Index * EltBits;
4679 auto findNonEXTRACT_SUBVECTORParent =
4680 [](
SDValue Parent) -> std::pair<SDValue, uint64_t> {
4685 Parent.getOperand(0).getSimpleValueType().isFixedLengthVector()) {
4686 Offset += Parent.getConstantOperandVal(1);
4687 Parent = Parent.getOperand(0);
4689 return std::make_pair(Parent,
Offset);
4692 auto [V1Src, V1IndexOffset] = findNonEXTRACT_SUBVECTORParent(V1);
4693 auto [V2Src, V2IndexOffset] = findNonEXTRACT_SUBVECTORParent(V2);
4702 for (
size_t i = 0; i != NewMask.
size(); ++i) {
4703 if (NewMask[i] == -1)
4706 if (
static_cast<size_t>(NewMask[i]) < NewMask.
size()) {
4707 NewMask[i] = NewMask[i] + V1IndexOffset;
4711 NewMask[i] = NewMask[i] - NewMask.
size() + V2IndexOffset;
4717 if (NewMask[0] <= 0)
4721 for (
unsigned i = 1; i != NewMask.
size(); ++i)
4722 if (NewMask[i - 1] + 1 != NewMask[i])
4726 MVT SrcVT = Src.getSimpleValueType();
4757 int NumSubElts, Index;
4762 bool OpsSwapped = Mask[Index] < (int)NumElts;
4763 SDValue InPlace = OpsSwapped ? V2 : V1;
4764 SDValue ToInsert = OpsSwapped ? V1 : V2;
4774 if (NumSubElts + Index >= (
int)NumElts)
4788 Res =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, InPlace, ToInsert,
4800 bool OpsSwapped =
false;
4801 if (!isa<BuildVectorSDNode>(V1)) {
4802 if (!isa<BuildVectorSDNode>(V2))
4807 SDValue Splat = cast<BuildVectorSDNode>(V1)->getSplatValue();
4815 const unsigned E = Mask.size() - ((
Offset > 0) ?
Offset : 0);
4816 for (
unsigned i = S; i != E; ++i)
4817 if (Mask[i] >= 0 && (
unsigned)Mask[i] !=
Base + i +
Offset)
4823 bool IsVSlidedown = isSlideMask(Mask, OpsSwapped ? 0 : NumElts, 1);
4824 if (!IsVSlidedown && !isSlideMask(Mask, OpsSwapped ? 0 : NumElts, -1))
4827 const int InsertIdx = Mask[IsVSlidedown ? (NumElts - 1) : 0];
4829 if (InsertIdx < 0 || InsertIdx / NumElts != (
unsigned)OpsSwapped)
4852 auto OpCode = IsVSlidedown ?
4857 auto Vec = DAG.
getNode(OpCode,
DL, ContainerVT,
4860 Splat, TrueMask, VL);
4871 for (
unsigned i = 0; i < Mask.size(); i++)
4872 LaneIsUndef[i % Factor] &= (Mask[i] == -1);
4875 for (
unsigned i = 0; i < Factor; i++) {
4886 for (
unsigned i = 0; i < Mask.size() / Factor; i++) {
4887 unsigned j = i * Factor + Index;
4888 if (Mask[j] != -1 && (
unsigned)Mask[j] != i)
4901 MVT VT = V.getSimpleValueType();
4916 EC.multiplyCoefficientBy(Factor));
4935 MVT VecContainerVT = VecVT;
4952 MVT WideContainerVT = WideVT;
4958 EvenV = DAG.
getBitcast(VecContainerVT, EvenV);
4965 if (Subtarget.hasStdExtZvbb()) {
4970 OffsetVec, Passthru, Mask, VL);
4972 Interleaved, EvenV, Passthru, Mask, VL);
4980 OddV, Passthru, Mask, VL);
4986 OddV, AllOnesVec, Passthru, Mask, VL);
4994 Interleaved, OddsMul, Passthru, Mask, VL);
5001 Interleaved = DAG.
getBitcast(ResultContainerVT, Interleaved);
5047 if (ViaEltSize > NumElts)
5056 if (ViaEltSize > NumElts)
5062 if (ViaEltSize > NumElts)
5071 MVT &RotateVT,
unsigned &RotateAmt) {
5077 unsigned NumSubElts;
5079 NumElts, NumSubElts, RotateAmt))
5082 NumElts / NumSubElts);
5150 unsigned NumOfSrcRegs = NumElts / NumOpElts;
5151 unsigned NumOfDestRegs = NumElts / NumOpElts;
5160 Mask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs,
5161 [&]() {
Operands.emplace_back(); },
5162 [&](
ArrayRef<int> SrcSubMask,
unsigned SrcVecIdx,
unsigned DstVecIdx) {
5163 Operands.emplace_back().emplace_back(
5164 SrcVecIdx, UINT_MAX,
5167 [&](
ArrayRef<int> SrcSubMask,
unsigned Idx1,
unsigned Idx2,
bool NewReg) {
5173 assert(
Operands.size() == NumOfDestRegs &&
"Whole vector must be processed");
5178 unsigned NumShuffles = std::accumulate(
5185 for (const auto &P : Data) {
5186 unsigned Idx2 = std::get<1>(P);
5187 ArrayRef<int> Mask = std::get<2>(P);
5188 if (Idx2 != UINT_MAX)
5190 else if (ShuffleVectorInst::isIdentityMask(Mask, Mask.size()))
5195 if ((NumOfDestRegs > 2 && NumShuffles > NumOfDestRegs) ||
5196 (NumOfDestRegs <= 2 && NumShuffles >= 4))
5198 auto ExtractValue = [&, &DAG = DAG](
SDValue SrcVec,
unsigned ExtractIdx) {
5200 DAG.getVectorIdxConstant(ExtractIdx,
DL));
5204 auto PerformShuffle = [&, &DAG = DAG](
SDValue SubVec1,
SDValue SubVec2,
5206 SDValue SubVec = DAG.getVectorShuffle(OneRegVT,
DL, SubVec1, SubVec2, Mask);
5209 SDValue Vec = DAG.getUNDEF(ContainerVT);
5214 for (
unsigned I : seq<unsigned>(
Data.size())) {
5215 const auto &[Idx1, Idx2,
_] =
Data[
I];
5218 "Expected both indices to be extracted already.");
5221 SDValue V = ExtractValue(Idx1 >= NumOfSrcRegs ? V2 : V1,
5222 (Idx1 % NumOfSrcRegs) * NumOpElts);
5224 if (Idx2 != UINT_MAX)
5225 Values[Idx2] = ExtractValue(Idx2 >= NumOfSrcRegs ? V2 : V1,
5226 (Idx2 % NumOfSrcRegs) * NumOpElts);
5229 for (
const auto &[Idx1, Idx2, Mask] :
Data) {
5231 SDValue V2 = Idx2 == UINT_MAX ? V1 : Values.
at(Idx2);
5232 V = PerformShuffle(V1, V2, Mask);
5236 unsigned InsertIdx =
I * NumOpElts;
5239 DAG.getVectorIdxConstant(InsertIdx,
DL));
5249 bool SawUndef =
false;
5250 for (
unsigned i = 0; i < Mask.size(); i++) {
5251 if (Mask[i] == -1) {
5257 if (i > (
unsigned)Mask[i])
5259 if (Mask[i] <=
Last)
5290 for (
int Idx : Mask) {
5293 unsigned SrcIdx =
Idx % Mask.size();
5295 if (Srcs[SrcIdx] == -1)
5298 else if (Srcs[SrcIdx] != Src)
5304 for (
int Lane : Srcs) {
5317 for (
unsigned I = 0;
I < Mask.size();
I++) {
5321 NewMask[
I] = Mask[
I] % Mask.size();
5335 MVT VT =
Op.getSimpleValueType();
5343 if (ElementSize > 32)
5366 MVT VT =
Op.getSimpleValueType();
5381 V2 = V2.isUndef() ? DAG.
getUNDEF(WidenVT)
5405 V.getOperand(0).getSimpleValueType().getVectorNumElements();
5406 V = V.getOperand(
Offset / OpElements);
5412 auto *Ld = cast<LoadSDNode>(V);
5422 SDValue Ops[] = {Ld->getChain(),
5436 MVT SplatVT = ContainerVT;
5439 if (SVT == MVT::bf16 ||
5440 (SVT == MVT::f16 && !Subtarget.hasStdExtZfh())) {
5449 V = DAG.
getLoad(SVT,
DL, Ld->getChain(), NewAddr,
5450 Ld->getPointerInfo().getWithOffset(
Offset),
5451 Ld->getOriginalAlign(),
5455 Ld->getPointerInfo().getWithOffset(
Offset), SVT,
5456 Ld->getOriginalAlign(),
5457 Ld->getMemOperand()->getFlags());
5469 assert(Lane < (
int)NumElts &&
"Unexpected lane!");
5472 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
5494 if (Subtarget.hasStdExtZvkb())
5505 LoV = LoSrc == 0 ? V1 : V2;
5509 HiV = HiSrc == 0 ? V1 : V2;
5515 unsigned InvRotate = NumElts - Rotation;
5525 Res =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, Res, LoV,
5543 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
5544 for (
unsigned Factor = 2; Factor <= MaxFactor; Factor <<= 1) {
5560 int EvenSrc, OddSrc;
5568 bool LaneIsUndef[2] = {
true,
true};
5569 for (
unsigned i = 0; i < Mask.size(); i++)
5570 LaneIsUndef[i % 2] &= (Mask[i] == -1);
5572 int Size = Mask.size();
5574 if (LaneIsUndef[0]) {
5577 assert(EvenSrc >= 0 &&
"Undef source?");
5578 EvenV = (EvenSrc /
Size) == 0 ? V1 : V2;
5583 if (LaneIsUndef[1]) {
5586 assert(OddSrc >= 0 &&
"Undef source?");
5587 OddV = (OddSrc /
Size) == 0 ? V1 : V2;
5597 assert(!V1.
isUndef() &&
"Unexpected shuffle canonicalization");
5609 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
5610 for (
unsigned Factor = 4; Factor <= MaxFactor; Factor <<= 1) {
5634 for (
auto Idx : Mask) {
5647 any_of(Mask, [&](
const auto &
Idx) {
return Idx > 255; })) {
5676 MVT IndexContainerVT =
5681 for (
int MaskIndex : Mask) {
5682 bool IsLHSIndex = MaskIndex < (int)NumElts && MaskIndex >= 0;
5691 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
5701 for (
int MaskIndex : Mask) {
5702 bool IsLHSOrUndefIndex = MaskIndex < (int)NumElts;
5703 ShuffleMaskLHS.
push_back(IsLHSOrUndefIndex && MaskIndex >= 0
5705 ShuffleMaskRHS.
push_back(IsLHSOrUndefIndex ? -1 : (MaskIndex - NumElts));
5736 for (
int MaskIndex : Mask) {
5737 bool SelectMaskVal = (MaskIndex < (int)NumElts) ^ !SwapOps;
5741 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
5773RISCVTargetLowering::lowerCTLZ_CTTZ_ZERO_UNDEF(
SDValue Op,
5775 MVT VT =
Op.getSimpleValueType();
5779 MVT ContainerVT = VT;
5782 if (
Op->isVPOpcode()) {
5783 Mask =
Op.getOperand(1);
5787 VL =
Op.getOperand(2);
5793 MVT FloatEltVT = (EltSize >= 32) ? MVT::f64 : MVT::f32;
5795 FloatEltVT = MVT::f32;
5802 "Expected legal float type!");
5809 }
else if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF) {
5812 Src = DAG.
getNode(ISD::VP_AND,
DL, VT, Src, Neg, Mask, VL);
5817 if (FloatVT.
bitsGT(VT)) {
5818 if (
Op->isVPOpcode())
5819 FloatVal = DAG.
getNode(ISD::VP_UINT_TO_FP,
DL, FloatVT, Src, Mask, VL);
5828 if (!
Op->isVPOpcode())
5832 MVT ContainerFloatVT =
5835 Src, Mask, RTZRM, VL);
5842 unsigned ShiftAmt = FloatEltVT == MVT::f64 ? 52 : 23;
5846 if (
Op->isVPOpcode()) {
5855 else if (IntVT.
bitsGT(VT))
5860 unsigned ExponentBias = FloatEltVT == MVT::f64 ? 1023 : 127;
5865 if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF)
5866 return DAG.
getNode(ISD::VP_SUB,
DL, VT, Exp,
5871 unsigned Adjust = ExponentBias + (EltSize - 1);
5873 if (
Op->isVPOpcode())
5883 else if (
Op.getOpcode() == ISD::VP_CTLZ)
5884 Res = DAG.
getNode(ISD::VP_UMIN,
DL, VT, Res,
5894 MVT SrcVT =
Source.getSimpleValueType();
5903 SrcVT = ContainerVT;
5916 if (
Op->getOpcode() == ISD::VP_CTTZ_ELTS_ZERO_UNDEF)
5933 auto *
Load = cast<LoadSDNode>(
Op);
5934 assert(Load &&
Load->getMemoryVT().isVector() &&
"Expected vector load");
5937 Load->getMemoryVT(),
5938 *
Load->getMemOperand()))
5942 MVT VT =
Op.getSimpleValueType();
5944 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
5945 "Unexpected unaligned RVV load type");
5949 "Expecting equally-sized RVV vector types to be legal");
5951 Load->getPointerInfo(),
Load->getOriginalAlign(),
5952 Load->getMemOperand()->getFlags());
5962 auto *
Store = cast<StoreSDNode>(
Op);
5963 assert(Store &&
Store->getValue().getValueType().isVector() &&
5964 "Expected vector store");
5967 Store->getMemoryVT(),
5968 *
Store->getMemOperand()))
5975 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
5976 "Unexpected unaligned RVV store type");
5980 "Expecting equally-sized RVV vector types to be legal");
5981 StoredVal = DAG.
getBitcast(NewVT, StoredVal);
5983 Store->getPointerInfo(),
Store->getOriginalAlign(),
5984 Store->getMemOperand()->getFlags());
5989 assert(
Op.getValueType() == MVT::i64 &&
"Unexpected VT");
5991 int64_t Imm = cast<ConstantSDNode>(
Op)->getSExtValue();
6018 unsigned ShiftAmt, AddOpc;
6029 MVT VT =
Op.getSimpleValueType();
6030 const APFloat &
Imm = cast<ConstantFPSDNode>(
Op)->getValueAPF();
6033 bool Negate =
false;
6037 if (Index < 0 &&
Imm.isNegative()) {
6065 if (Subtarget.hasStdExtZtso()) {
6089 MVT VT =
Op.getSimpleValueType();
6091 unsigned Check =
Op.getConstantOperandVal(1);
6092 unsigned TDCMask = 0;
6120 MVT VT0 =
Op.getOperand(0).getSimpleValueType();
6125 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6127 VL =
Op.getOperand(3);
6130 VL,
Op->getFlags());
6145 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6147 MVT MaskContainerVT =
6150 VL =
Op.getOperand(3);
6155 Mask, VL,
Op->getFlags());
6158 DAG.
getUNDEF(ContainerDstVT), TDCMaskV, VL);
6163 DAG.
getUNDEF(ContainerVT), Mask, VL});
6167 TDCMaskV, DAG.
getUNDEF(ContainerDstVT), Mask, VL);
6171 DAG.
getUNDEF(ContainerDstVT), SplatZero, VL);
6175 DAG.
getUNDEF(ContainerVT), Mask, VL});
6191 MVT VT =
Op.getSimpleValueType();
6218 return DAG.
getNode(Opc,
DL, VT, NewX, NewY);
6225 MVT ContainerVT = VT;
6233 if (
Op->isVPOpcode()) {
6234 Mask =
Op.getOperand(2);
6238 VL =
Op.getOperand(3);
6246 {X, X, DAG.getCondCode(ISD::SETOEQ),
6247 DAG.getUNDEF(ContainerVT), Mask, VL});
6255 {Y, Y, DAG.getCondCode(ISD::SETOEQ),
6256 DAG.getUNDEF(ContainerVT), Mask, VL});
6266 DAG.
getUNDEF(ContainerVT), Mask, VL);
6276 "Wrong opcode for lowering FABS or FNEG.");
6279 MVT VT =
Op.getSimpleValueType();
6280 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
6287 Mask = Mask.sext(Subtarget.
getXLen());
6300 MVT VT =
Op.getSimpleValueType();
6301 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
6311 if (SignSize == Subtarget.
getXLen()) {
6313 }
else if (SignSize == 16) {
6315 }
else if (SignSize == 32) {
6317 }
else if (SignSize == 64) {
6318 assert(XLenVT == MVT::i32 &&
"Unexpected type");
6328 if (ShiftAmount > 0) {
6331 }
else if (ShiftAmount < 0) {
6357#define OP_CASE(NODE) \
6359 return RISCVISD::NODE##_VL;
6360#define VP_CASE(NODE) \
6361 case ISD::VP_##NODE: \
6362 return RISCVISD::NODE##_VL;
6364 switch (
Op.getOpcode()) {
6442 case ISD::VP_CTLZ_ZERO_UNDEF:
6445 case ISD::VP_CTTZ_ZERO_UNDEF:
6454 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
6459 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
6464 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
6467 case ISD::VP_SELECT:
6476 case ISD::VP_SIGN_EXTEND:
6478 case ISD::VP_ZERO_EXTEND:
6480 case ISD::VP_FP_TO_SINT:
6482 case ISD::VP_FP_TO_UINT:
6485 case ISD::VP_FMINNUM:
6488 case ISD::VP_FMAXNUM:
6493 case ISD::VP_LLRINT:
6505 "not a RISC-V target specific op");
6509 "adding target specific op should update this function");
6529 "not a RISC-V target specific op");
6533 "adding target specific op should update this function");
6546 if (
Op.getValueType() == MVT::nxv32f16 &&
6550 if (
Op.getValueType() == MVT::nxv32bf16)
6563 if (!
Op.getOperand(j).getValueType().isVector()) {
6564 LoOperands[j] =
Op.getOperand(j);
6565 HiOperands[j] =
Op.getOperand(j);
6568 std::tie(LoOperands[j], HiOperands[j]) =
6573 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
6575 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
6590 std::tie(LoOperands[j], HiOperands[j]) =
6594 if (!
Op.getOperand(j).getValueType().isVector()) {
6595 LoOperands[j] =
Op.getOperand(j);
6596 HiOperands[j] =
Op.getOperand(j);
6599 std::tie(LoOperands[j], HiOperands[j]) =
6604 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
6606 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
6616 auto [EVLLo, EVLHi] =
6617 DAG.
SplitEVL(
Op.getOperand(3),
Op.getOperand(1).getValueType(),
DL);
6621 {Op.getOperand(0), Lo, MaskLo, EVLLo},
Op->getFlags());
6623 {ResLo, Hi, MaskHi, EVLHi},
Op->getFlags());
6641 if (!
Op.getOperand(j).getValueType().isVector()) {
6642 LoOperands[j] =
Op.getOperand(j);
6643 HiOperands[j] =
Op.getOperand(j);
6646 std::tie(LoOperands[j], HiOperands[j]) =
6651 DAG.
getNode(
Op.getOpcode(),
DL, LoVTs, LoOperands,
Op->getFlags());
6654 DAG.
getNode(
Op.getOpcode(),
DL, HiVTs, HiOperands,
Op->getFlags());
6663 switch (
Op.getOpcode()) {
6669 return lowerGlobalAddress(
Op, DAG);
6671 return lowerBlockAddress(
Op, DAG);
6673 return lowerConstantPool(
Op, DAG);
6675 return lowerJumpTable(
Op, DAG);
6677 return lowerGlobalTLSAddress(
Op, DAG);
6681 return lowerConstantFP(
Op, DAG);
6683 return lowerSELECT(
Op, DAG);
6685 return lowerBRCOND(
Op, DAG);
6687 return lowerVASTART(
Op, DAG);
6689 return lowerFRAMEADDR(
Op, DAG);
6691 return lowerRETURNADDR(
Op, DAG);
6693 return lowerShiftLeftParts(
Op, DAG);
6695 return lowerShiftRightParts(
Op, DAG,
true);
6697 return lowerShiftRightParts(
Op, DAG,
false);
6700 if (
Op.getValueType().isFixedLengthVector()) {
6701 assert(Subtarget.hasStdExtZvkb());
6702 return lowerToScalableOp(
Op, DAG);
6704 assert(Subtarget.hasVendorXTHeadBb() &&
6705 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
6706 "Unexpected custom legalization");
6708 if (!isa<ConstantSDNode>(
Op.getOperand(1)))
6713 EVT VT =
Op.getValueType();
6717 if (Op0VT == MVT::i16 &&
6719 (VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
6723 if (VT == MVT::f32 && Op0VT == MVT::i32 && Subtarget.
is64Bit() &&
6728 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.
is64Bit() &&
6744 "Unexpected types");
6778 return LowerINTRINSIC_WO_CHAIN(
Op, DAG);
6780 return LowerINTRINSIC_W_CHAIN(
Op, DAG);
6782 return LowerINTRINSIC_VOID(
Op, DAG);
6784 return LowerIS_FPCLASS(
Op, DAG);
6786 MVT VT =
Op.getSimpleValueType();
6788 assert(Subtarget.hasStdExtZvbb());
6789 return lowerToScalableOp(
Op, DAG);
6792 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected custom legalization");
6802 if (!
Op.getSimpleValueType().isVector())
6804 return lowerVectorTruncLike(
Op, DAG);
6807 if (
Op.getOperand(0).getValueType().isVector() &&
6808 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
6809 return lowerVectorMaskExt(
Op, DAG, 1);
6812 if (
Op.getOperand(0).getValueType().isVector() &&
6813 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
6814 return lowerVectorMaskExt(
Op, DAG, -1);
6817 return lowerSPLAT_VECTOR_PARTS(
Op, DAG);
6819 return lowerINSERT_VECTOR_ELT(
Op, DAG);
6821 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
6823 MVT VT =
Op.getSimpleValueType();
6831 MVT ContainerVT = VT;
6839 DAG.
getUNDEF(ContainerVT), Scalar, VL);
6843 DAG.
getUNDEF(ContainerVT), Scalar, VL);
6851 MVT VT =
Op.getSimpleValueType();
6871 }
else if ((Val % 8) == 0) {
6887 if (
Op.getValueType() == MVT::f16 && Subtarget.
is64Bit() &&
6888 Op.getOperand(1).getValueType() == MVT::i32) {
6905 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
6908 return lowerStrictFPExtendOrRoundLike(
Op, DAG);
6911 if (
Op.getValueType().isVector() &&
6912 ((
Op.getValueType().getScalarType() == MVT::f16 &&
6915 Op.getValueType().getScalarType() == MVT::bf16)) {
6931 Op1.getValueType().isVector() &&
6932 ((Op1.getValueType().getScalarType() == MVT::f16 &&
6935 Op1.getValueType().getScalarType() == MVT::bf16)) {
6941 Op1.getValueType().getVectorElementCount());
6944 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), WidenVec);
6954 MVT VT =
Op.getSimpleValueType();
6957 bool IsStrict =
Op->isStrictFPOpcode();
6958 SDValue Src =
Op.getOperand(0 + IsStrict);
6959 MVT SrcVT = Src.getSimpleValueType();
6970 "Unexpected vector element types");
6974 if (EltSize > (2 * SrcEltSize)) {
6986 Op.getOperand(0), Ext);
6990 assert(SrcEltVT == MVT::f16 &&
"Unexpected FP_TO_[US]INT lowering");
6995 auto [FExt, Chain] =
6997 return DAG.
getNode(
Op.getOpcode(),
DL,
Op->getVTList(), Chain, FExt);
7004 if (SrcEltSize > (2 * EltSize)) {
7007 assert(EltVT == MVT::f16 &&
"Unexpected [US]_TO_FP lowering");
7012 Op.getOperand(0), Src);
7027 Op.getOperand(0), Src);
7041 unsigned RVVOpc = 0;
7042 switch (
Op.getOpcode()) {
7074 "Expected same element count");
7081 Op.getOperand(0), Src, Mask, VL);
7085 Src = DAG.
getNode(RVVOpc,
DL, ContainerVT, Src, Mask, VL);
7100 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
7107 MVT VT =
Op.getSimpleValueType();
7127 bool IsStrict =
Op->isStrictFPOpcode();
7128 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7132 std::tie(Res, Chain) =
7133 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
7148 bool IsStrict =
Op->isStrictFPOpcode();
7149 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7155 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
7156 CallOptions,
DL, Chain);
7173 if (
Op.getValueType().isVector())
7178 assert(
Op.getOperand(0).getValueType() == MVT::f16 &&
7179 "Unexpected custom legalisation");
7182 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), Ext);
7188 assert(
Op.getOperand(1).getValueType() == MVT::f16 &&
7189 "Unexpected custom legalisation");
7192 {
Op.getOperand(0),
Op.getOperand(1)});
7193 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
7194 {Ext.getValue(1), Ext.getValue(0)});
7201 return lowerVECREDUCE(
Op, DAG);
7205 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7206 return lowerVectorMaskVecReduction(
Op, DAG,
false);
7207 return lowerVECREDUCE(
Op, DAG);
7214 return lowerFPVECREDUCE(
Op, DAG);
7215 case ISD::VP_REDUCE_ADD:
7216 case ISD::VP_REDUCE_UMAX:
7217 case ISD::VP_REDUCE_SMAX:
7218 case ISD::VP_REDUCE_UMIN:
7219 case ISD::VP_REDUCE_SMIN:
7220 case ISD::VP_REDUCE_FADD:
7221 case ISD::VP_REDUCE_SEQ_FADD:
7222 case ISD::VP_REDUCE_FMIN:
7223 case ISD::VP_REDUCE_FMAX:
7224 case ISD::VP_REDUCE_FMINIMUM:
7225 case ISD::VP_REDUCE_FMAXIMUM:
7228 return lowerVPREDUCE(
Op, DAG);
7229 case ISD::VP_REDUCE_AND:
7230 case ISD::VP_REDUCE_OR:
7231 case ISD::VP_REDUCE_XOR:
7232 if (
Op.getOperand(1).getValueType().getVectorElementType() == MVT::i1)
7233 return lowerVectorMaskVecReduction(
Op, DAG,
true);
7234 return lowerVPREDUCE(
Op, DAG);
7235 case ISD::VP_CTTZ_ELTS:
7236 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
7237 return lowerVPCttzElements(
Op, DAG);
7241 DAG.
getUNDEF(ContainerVT), DAG, Subtarget);
7244 return lowerINSERT_SUBVECTOR(
Op, DAG);
7246 return lowerEXTRACT_SUBVECTOR(
Op, DAG);
7248 return lowerVECTOR_DEINTERLEAVE(
Op, DAG);
7250 return lowerVECTOR_INTERLEAVE(
Op, DAG);
7252 return lowerSTEP_VECTOR(
Op, DAG);
7254 return lowerVECTOR_REVERSE(
Op, DAG);
7256 return lowerVECTOR_SPLICE(
Op, DAG);
7260 MVT VT =
Op.getSimpleValueType();
7262 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
7263 EltVT == MVT::bf16) {
7266 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
7267 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
7277 if (EltVT == MVT::i1)
7278 return lowerVectorMaskSplat(
Op, DAG);
7287 MVT VT =
Op.getSimpleValueType();
7288 MVT ContainerVT = VT;
7306 Op->ops().take_front(HalfNumOps));
7308 Op->ops().drop_front(HalfNumOps));
7312 unsigned NumOpElts =
7313 Op.getOperand(0).getSimpleValueType().getVectorMinNumElements();
7316 SDValue SubVec = OpIdx.value();
7327 auto *Load = cast<LoadSDNode>(
Op);
7328 EVT VecTy = Load->getMemoryVT();
7335 unsigned NumElts = Sz / (NF * 8);
7336 int Log2LMUL =
Log2_64(NumElts) - 3;
7339 Flag.setNoUnsignedWrap(
true);
7341 SDValue BasePtr = Load->getBasePtr();
7349 for (
unsigned i = 0; i < NF; ++i) {
7362 if (
auto V = expandUnalignedRVVLoad(
Op, DAG))
7364 if (
Op.getValueType().isFixedLengthVector())
7365 return lowerFixedLengthVectorLoadToRVV(
Op, DAG);
7369 auto *Store = cast<StoreSDNode>(
Op);
7370 SDValue StoredVal = Store->getValue();
7378 unsigned NumElts = Sz / (NF * 8);
7379 int Log2LMUL =
Log2_64(NumElts) - 3;
7382 Flag.setNoUnsignedWrap(
true);
7384 SDValue Chain = Store->getChain();
7385 SDValue BasePtr = Store->getBasePtr();
7392 for (
unsigned i = 0; i < NF; ++i) {
7396 Ret = DAG.
getStore(Chain,
DL, Extract, BasePtr,
7398 Store->getOriginalAlign(),
7399 Store->getMemOperand()->getFlags());
7400 Chain = Ret.getValue(0);
7406 if (
auto V = expandUnalignedRVVStore(
Op, DAG))
7408 if (
Op.getOperand(1).getValueType().isFixedLengthVector())
7409 return lowerFixedLengthVectorStoreToRVV(
Op, DAG);
7414 return lowerMaskedLoad(
Op, DAG);
7417 return lowerMaskedStore(
Op, DAG);
7419 return lowerVectorCompress(
Op, DAG);
7428 EVT VT =
Op.getValueType();
7439 MVT OpVT =
Op.getOperand(0).getSimpleValueType();
7441 MVT VT =
Op.getSimpleValueType();
7446 "Unexpected CondCode");
7454 if (isa<ConstantSDNode>(
RHS)) {
7455 int64_t Imm = cast<ConstantSDNode>(
RHS)->getSExtValue();
7456 if (Imm != 0 && isInt<12>((
uint64_t)Imm + 1)) {
7478 return lowerFixedLengthVectorSetccToRVV(
Op, DAG);
7494 return lowerToScalableOp(
Op, DAG);
7498 if (
Op.getSimpleValueType().isFixedLengthVector())
7499 return lowerToScalableOp(
Op, DAG);
7501 assert(
Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.
is64Bit() &&
7502 "Unexpected custom legalisation");
7506 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
7532 return lowerToScalableOp(
Op, DAG);
7536 EVT VT =
Op->getValueType(0);
7551 return lowerABS(
Op, DAG);
7556 if (Subtarget.hasStdExtZvbb())
7557 return lowerToScalableOp(
Op, DAG);
7559 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
7561 return lowerFixedLengthVectorSelectToRVV(
Op, DAG);
7563 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
7567 return lowerFixedLengthVectorFCOPYSIGNToRVV(
Op, DAG);
7576 return lowerToScalableOp(
Op, DAG);
7579 return lowerVectorStrictFSetcc(
Op, DAG);
7589 case ISD::VP_GATHER:
7590 return lowerMaskedGather(
Op, DAG);
7592 case ISD::VP_SCATTER:
7593 return lowerMaskedScatter(
Op, DAG);
7595 return lowerGET_ROUNDING(
Op, DAG);
7597 return lowerSET_ROUNDING(
Op, DAG);
7599 return lowerEH_DWARF_CFA(
Op, DAG);
7601 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7602 return lowerVPMergeMask(
Op, DAG);
7604 case ISD::VP_SELECT:
7612 case ISD::VP_UADDSAT:
7613 case ISD::VP_USUBSAT:
7614 case ISD::VP_SADDSAT:
7615 case ISD::VP_SSUBSAT:
7617 case ISD::VP_LLRINT:
7618 return lowerVPOp(
Op, DAG);
7622 return lowerLogicVPOp(
Op, DAG);
7631 case ISD::VP_FMINNUM:
7632 case ISD::VP_FMAXNUM:
7633 case ISD::VP_FCOPYSIGN:
7640 return lowerVPOp(
Op, DAG);
7641 case ISD::VP_IS_FPCLASS:
7642 return LowerIS_FPCLASS(
Op, DAG);
7643 case ISD::VP_SIGN_EXTEND:
7644 case ISD::VP_ZERO_EXTEND:
7645 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
7646 return lowerVPExtMaskOp(
Op, DAG);
7647 return lowerVPOp(
Op, DAG);
7648 case ISD::VP_TRUNCATE:
7649 return lowerVectorTruncLike(
Op, DAG);
7650 case ISD::VP_FP_EXTEND:
7651 case ISD::VP_FP_ROUND:
7652 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
7653 case ISD::VP_SINT_TO_FP:
7654 case ISD::VP_UINT_TO_FP:
7655 if (
Op.getValueType().isVector() &&
7656 ((
Op.getValueType().getScalarType() == MVT::f16 &&
7659 Op.getValueType().getScalarType() == MVT::bf16)) {
7672 case ISD::VP_FP_TO_SINT:
7673 case ISD::VP_FP_TO_UINT:
7675 Op1.getValueType().isVector() &&
7676 ((Op1.getValueType().getScalarType() == MVT::f16 &&
7679 Op1.getValueType().getScalarType() == MVT::bf16)) {
7685 Op1.getValueType().getVectorElementCount());
7689 {WidenVec, Op.getOperand(1), Op.getOperand(2)});
7691 return lowerVPFPIntConvOp(
Op, DAG);
7695 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
7696 return lowerVPSetCCMaskOp(
Op, DAG);
7702 case ISD::VP_BITREVERSE:
7704 return lowerVPOp(
Op, DAG);
7706 case ISD::VP_CTLZ_ZERO_UNDEF:
7707 if (Subtarget.hasStdExtZvbb())
7708 return lowerVPOp(
Op, DAG);
7709 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
7711 case ISD::VP_CTTZ_ZERO_UNDEF:
7712 if (Subtarget.hasStdExtZvbb())
7713 return lowerVPOp(
Op, DAG);
7714 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
7716 return lowerVPOp(
Op, DAG);
7717 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
7718 return lowerVPStridedLoad(
Op, DAG);
7719 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
7720 return lowerVPStridedStore(
Op, DAG);
7722 case ISD::VP_FFLOOR:
7724 case ISD::VP_FNEARBYINT:
7725 case ISD::VP_FROUND:
7726 case ISD::VP_FROUNDEVEN:
7727 case ISD::VP_FROUNDTOZERO:
7731 case ISD::VP_FMAXIMUM:
7732 case ISD::VP_FMINIMUM:
7736 case ISD::EXPERIMENTAL_VP_SPLICE:
7737 return lowerVPSpliceExperimental(
Op, DAG);
7738 case ISD::EXPERIMENTAL_VP_REVERSE:
7739 return lowerVPReverseExperimental(
Op, DAG);
7740 case ISD::EXPERIMENTAL_VP_SPLAT:
7741 return lowerVPSplatExperimental(
Op, DAG);
7744 "llvm.clear_cache only needs custom lower on Linux targets");
7747 return emitFlushICache(DAG,
Op.getOperand(0),
Op.getOperand(1),
7748 Op.getOperand(2), Flags,
DL);
7751 return lowerDYNAMIC_STACKALLOC(
Op, DAG);
7753 return lowerINIT_TRAMPOLINE(
Op, DAG);
7755 return lowerADJUST_TRAMPOLINE(
Op, DAG);
7762 MakeLibCallOptions CallOptions;
7763 std::pair<SDValue, SDValue> CallResult =
7764 makeLibCall(DAG, RTLIB::RISCV_FLUSH_ICACHE, MVT::isVoid,
7765 {Start,
End, Flags}, CallOptions,
DL, InChain);
7768 return CallResult.second;
7781 std::unique_ptr<MCCodeEmitter> CodeEmitter(
7788 const Value *TrmpAddr = cast<SrcValueSDNode>(
Op.getOperand(4))->getValue();
7800 constexpr unsigned StaticChainOffset = 16;
7801 constexpr unsigned FunctionAddressOffset = 24;
7805 auto GetEncoding = [&](
const MCInst &MC) {
7808 CodeEmitter->encodeInstruction(MC, CB, Fixups, *STI);
7818 GetEncoding(
MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X7).addImm(0)),
7823 MCInstBuilder(RISCV::LD).addReg(RISCV::X5).addReg(RISCV::X7).addImm(
7824 FunctionAddressOffset)),
7828 MCInstBuilder(RISCV::LD).addReg(RISCV::X7).addReg(RISCV::X7).addImm(
7829 StaticChainOffset)),
7848 SDValue FunctionAddress =
Op.getOperand(2);
7852 struct OffsetValuePair {
7856 } OffsetValues[] = {
7857 {StaticChainOffset, StaticChain},
7858 {FunctionAddressOffset, FunctionAddress},
7863 DAG.
getConstant(OffsetValue.Offset, dl, MVT::i64));
7864 OffsetValue.Addr =
Addr;
7865 OutChains[
Idx + 4] =
7874 SDValue EndOfTrmp = OffsetValues[0].Addr;
7888 return Op.getOperand(0);
7905 N->getOffset(), Flags);
7934template <
class NodeTy>
7936 bool IsLocal,
bool IsExternWeak)
const {
7946 if (IsLocal && !Subtarget.allowTaggedGlobals())
8016 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
8025 return getAddr(
N, DAG);
8032 return getAddr(
N, DAG);
8039 return getAddr(
N, DAG);
8044 bool UseGOT)
const {
8108 Args.push_back(Entry);
8141 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
8155 Addr = getStaticTLSAddr(
N, DAG,
false);
8158 Addr = getStaticTLSAddr(
N, DAG,
true);
8163 : getDynamicTLSAddr(
N, DAG);
8180 if (
LHS == LHS2 &&
RHS == RHS2) {
8185 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
8193 return std::nullopt;
8201 MVT VT =
N->getSimpleValueType(0);
8231 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV)) {
8234 if (~TrueVal == FalseVal) {
8274 if (Subtarget.hasShortForwardBranchOpt())
8277 unsigned SelOpNo = 0;
8287 unsigned ConstSelOpNo = 1;
8288 unsigned OtherSelOpNo = 2;
8289 if (!dyn_cast<ConstantSDNode>(Sel->
getOperand(ConstSelOpNo))) {
8294 ConstantSDNode *ConstSelOpNode = dyn_cast<ConstantSDNode>(ConstSelOp);
8295 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
8299 ConstantSDNode *ConstBinOpNode = dyn_cast<ConstantSDNode>(ConstBinOp);
8300 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
8306 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
8308 std::swap(NewConstOps[0], NewConstOps[1]);
8320 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
8322 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
8325 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
8326 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
8335 MVT VT =
Op.getSimpleValueType();
8349 if ((Subtarget.hasStdExtZicond() || Subtarget.hasVendorXVentanaCondOps()) &&
8377 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV)) {
8381 TrueVal, Subtarget.
getXLen(), Subtarget,
true);
8383 FalseVal, Subtarget.
getXLen(), Subtarget,
true);
8384 bool IsCZERO_NEZ = TrueValCost <= FalseValCost;
8386 IsCZERO_NEZ ? FalseVal - TrueVal : TrueVal - FalseVal,
DL, VT);
8391 DL, VT, LHSVal, CondV);
8407 if (
Op.hasOneUse()) {
8408 unsigned UseOpc =
Op->user_begin()->getOpcode();
8417 return lowerSELECT(NewSel, DAG);
8446 SDValue Ops[] = {CondV,
Zero, SetNE, TrueV, FalseV};
8467 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV) &&
8471 if (TrueVal - 1 == FalseVal)
8473 if (TrueVal + 1 == FalseVal)
8480 RHS == TrueV && LHS == FalseV) {
8497 if (isa<ConstantSDNode>(TrueV) && !isa<ConstantSDNode>(FalseV)) {
8523 LHS, RHS, TargetCC,
Op.getOperand(2));
8541 const Value *SV = cast<SrcValueSDNode>(
Op.getOperand(2))->getValue();
8553 int XLenInBytes = Subtarget.
getXLen() / 8;
8555 EVT VT =
Op.getValueType();
8558 unsigned Depth =
Op.getConstantOperandVal(0);
8560 int Offset = -(XLenInBytes * 2);
8577 int XLenInBytes = Subtarget.
getXLen() / 8;
8582 EVT VT =
Op.getValueType();
8584 unsigned Depth =
Op.getConstantOperandVal(0);
8586 int Off = -XLenInBytes;
8587 SDValue FrameAddr = lowerFRAMEADDR(
Op, DAG);
8606 EVT VT =
Lo.getValueType();
8645 EVT VT =
Lo.getValueType();
8696 MVT VT =
Op.getSimpleValueType();
8722 MVT VecVT =
Op.getSimpleValueType();
8724 "Unexpected SPLAT_VECTOR_PARTS lowering");
8730 MVT ContainerVT = VecVT;
8750 int64_t ExtTrueVal)
const {
8752 MVT VecVT =
Op.getSimpleValueType();
8755 assert(Src.getValueType().isVector() &&
8756 Src.getValueType().getVectorElementType() == MVT::i1);
8777 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
8779 DAG.
getUNDEF(ContainerVT), SplatTrueVal, VL);
8782 SplatZero, DAG.
getUNDEF(ContainerVT), VL);
8787SDValue RISCVTargetLowering::lowerFixedLengthVectorExtendToRVV(
8789 MVT ExtVT =
Op.getSimpleValueType();
8793 MVT VT =
Op.getOperand(0).getSimpleValueType();
8819 bool IsVPTrunc =
Op.getOpcode() == ISD::VP_TRUNCATE;
8821 EVT MaskVT =
Op.getValueType();
8824 "Unexpected type for vector mask lowering");
8826 MVT VecVT = Src.getSimpleValueType();
8830 VL =
Op.getOperand(2);
8833 MVT ContainerVT = VecVT;
8839 MVT MaskContainerVT =
8846 std::tie(Mask, VL) =
8854 DAG.
getUNDEF(ContainerVT), SplatOne, VL);
8856 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
8860 DAG.
getUNDEF(ContainerVT), Mask, VL);
8863 DAG.
getUNDEF(MaskContainerVT), Mask, VL});
8871 unsigned Opc =
Op.getOpcode();
8872 bool IsVPTrunc = Opc == ISD::VP_TRUNCATE;
8875 MVT VT =
Op.getSimpleValueType();
8877 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
8881 return lowerVectorMaskTruncLike(
Op, DAG);
8889 MVT SrcVT = Src.getSimpleValueType();
8894 "Unexpected vector truncate lowering");
8896 MVT ContainerVT = SrcVT;
8900 VL =
Op.getOperand(2);
8913 std::tie(Mask, VL) =
8929 }
while (SrcEltVT != DstEltVT);
8938RISCVTargetLowering::lowerStrictFPExtendOrRoundLike(
SDValue Op,
8943 MVT VT =
Op.getSimpleValueType();
8944 MVT SrcVT = Src.getSimpleValueType();
8945 MVT ContainerVT = VT;
8968 Chain, Src, Mask, VL);
8969 Chain = Src.getValue(1);
8976 Chain, Src, Mask, VL);
8987RISCVTargetLowering::lowerVectorFPExtendOrRoundLike(
SDValue Op,
8990 Op.getOpcode() == ISD::VP_FP_ROUND ||
Op.getOpcode() == ISD::VP_FP_EXTEND;
8997 MVT VT =
Op.getSimpleValueType();
8999 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
9002 MVT SrcVT = Src.getSimpleValueType();
9004 bool IsDirectExtend =
9012 bool IsDirectConv = IsDirectExtend || IsDirectTrunc;
9015 MVT ContainerVT = VT;
9019 VL =
Op.getOperand(2);
9033 std::tie(Mask, VL) =
9039 Src = DAG.
getNode(ConvOpc,
DL, ContainerVT, Src, Mask, VL);
9045 unsigned InterConvOpc =
9050 DAG.
getNode(InterConvOpc,
DL, InterVT, Src, Mask, VL);
9052 DAG.
getNode(ConvOpc,
DL, ContainerVT, IntermediateConv, Mask, VL);
9063static std::optional<MVT>
9069 const unsigned MinVLMAX = VectorBitsMin / EltSize;
9071 if (MaxIdx < MinVLMAX)
9073 else if (MaxIdx < MinVLMAX * 2)
9075 else if (MaxIdx < MinVLMAX * 4)
9080 return std::nullopt;
9093 MVT VecVT =
Op.getSimpleValueType();
9110 ValVT == MVT::bf16) {
9119 MVT ContainerVT = VecVT;
9128 MVT OrigContainerVT = ContainerVT;
9131 if (
auto *IdxC = dyn_cast<ConstantSDNode>(
Idx)) {
9132 const unsigned OrigIdx = IdxC->getZExtValue();
9135 DL, DAG, Subtarget)) {
9136 ContainerVT = *ShrunkVT;
9145 VLEN && ContainerVT.
bitsGT(M1VT)) {
9148 unsigned RemIdx = OrigIdx % ElemsPerVReg;
9149 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
9150 unsigned ExtractIdx =
9167 if (!IsLegalInsert && isa<ConstantSDNode>(Val)) {
9168 const auto *CVal = cast<ConstantSDNode>(Val);
9169 if (isInt<32>(CVal->getSExtValue())) {
9170 IsLegalInsert =
true;
9179 if (IsLegalInsert) {
9185 Vec = DAG.
getNode(Opc,
DL, ContainerVT, Vec, Val, VL);
9201 std::tie(ValLo, ValHi) = DAG.
SplitScalar(Val,
DL, MVT::i32, MVT::i32);
9202 MVT I32ContainerVT =
9213 Vec, Vec, ValLo, I32Mask, InsertI64VL);
9218 Tail, ValInVec, ValHi, I32Mask, InsertI64VL);
9220 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
9225 ValInVec, AlignedIdx);
9235 DAG.
getUNDEF(I32ContainerVT), ValLo,
9236 I32Mask, InsertI64VL);
9238 DAG.
getUNDEF(I32ContainerVT), ValInVec, ValHi,
9239 I32Mask, InsertI64VL);
9241 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
9254 Idx, Mask, InsertVL, Policy);
9258 Slideup, AlignedIdx);
9273 EVT EltVT =
Op.getValueType();
9280 MVT ContainerVT = VecVT;
9296 unsigned WidenVecLen;
9299 unsigned MaxEEW = Subtarget.
getELen();
9304 "the number of elements should be power of 2");
9308 ExtractBitIdx =
Idx;
9310 WideEltVT = LargestEltVT;
9313 ExtractElementIdx = DAG.
getNode(
9324 Vec, ExtractElementIdx);
9340 EltVT == MVT::bf16) {
9350 MVT ContainerVT = VecVT;
9361 if (
auto *IdxC = dyn_cast<ConstantSDNode>(
Idx);
9362 IdxC && VLen && VecVT.
getSizeInBits().getKnownMinValue() > *VLen) {
9364 unsigned OrigIdx = IdxC->getZExtValue();
9367 unsigned RemIdx = OrigIdx % ElemsPerVReg;
9368 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
9369 unsigned ExtractIdx =
9379 std::optional<uint64_t> MaxIdx;
9382 if (
auto *IdxC = dyn_cast<ConstantSDNode>(
Idx))
9383 MaxIdx = IdxC->getZExtValue();
9385 if (
auto SmallerVT =
9387 ContainerVT = *SmallerVT;
9434 "Unexpected opcode");
9441 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
9446 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
9447 if (!
II || !
II->hasScalarOperand())
9450 unsigned SplatOp =
II->ScalarOperand + 1 + HasChain;
9463 if (OpVT.
bitsLT(XLenVT)) {
9470 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
9480 assert(
II->ScalarOperand > 0 &&
"Unexpected splat operand!");
9481 MVT VT =
Op.getOperand(SplatOp - 1).getSimpleValueType();
9484 assert(XLenVT == MVT::i32 && OpVT == MVT::i64 &&
9495 case Intrinsic::riscv_vslide1up:
9496 case Intrinsic::riscv_vslide1down:
9497 case Intrinsic::riscv_vslide1up_mask:
9498 case Intrinsic::riscv_vslide1down_mask: {
9501 bool IsMasked = NumOps == 7;
9507 std::tie(ScalarLo, ScalarHi) =
9515 if (isa<ConstantSDNode>(AVL)) {
9516 const auto [MinVLMAX, MaxVLMAX] =
9520 if (AVLInt <= MinVLMAX) {
9522 }
else if (AVLInt >= 2 * MaxVLMAX) {
9556 if (IntNo == Intrinsic::riscv_vslide1up ||
9557 IntNo == Intrinsic::riscv_vslide1up_mask) {
9559 ScalarHi, I32Mask, I32VL);
9561 ScalarLo, I32Mask, I32VL);
9564 ScalarLo, I32Mask, I32VL);
9566 ScalarHi, I32Mask, I32VL);
9615 const unsigned ElementWidth = 8;
9620 [[maybe_unused]]
unsigned MinVF =
9623 [[maybe_unused]]
unsigned VF =
N->getConstantOperandVal(2);
9627 bool Fractional = VF < LMul1VF;
9628 unsigned LMulVal = Fractional ? LMul1VF / VF : VF / LMul1VF;
9649 MVT ContainerVT = OpVT;
9676 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
9680 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
9681 if (!
II || !
II->hasScalarOperand())
9684 unsigned SplatOp =
II->ScalarOperand + 1;
9697 if (OpVT.
bitsLT(XLenVT)) {
9700 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
9711 EVT ValType = V.getValueType();
9712 if (ValType.isVector() && ValType.isFloatingPoint()) {
9715 ValType.getVectorElementCount());
9718 if (ValType.isFixedLengthVector()) {
9720 DAG, V.getSimpleValueType(), Subtarget);
9736 unsigned IntNo =
Op.getConstantOperandVal(0);
9743 case Intrinsic::riscv_tuple_insert: {
9751 case Intrinsic::riscv_tuple_extract: {
9758 case Intrinsic::thread_pointer: {
9762 case Intrinsic::riscv_orc_b:
9763 case Intrinsic::riscv_brev8:
9764 case Intrinsic::riscv_sha256sig0:
9765 case Intrinsic::riscv_sha256sig1:
9766 case Intrinsic::riscv_sha256sum0:
9767 case Intrinsic::riscv_sha256sum1:
9768 case Intrinsic::riscv_sm3p0:
9769 case Intrinsic::riscv_sm3p1: {
9782 return DAG.
getNode(Opc,
DL, XLenVT,
Op.getOperand(1));
9784 case Intrinsic::riscv_sm4ks:
9785 case Intrinsic::riscv_sm4ed: {
9789 return DAG.
getNode(Opc,
DL, XLenVT,
Op.getOperand(1),
Op.getOperand(2),
9792 case Intrinsic::riscv_zip:
9793 case Intrinsic::riscv_unzip: {
9796 return DAG.
getNode(Opc,
DL, XLenVT,
Op.getOperand(1));
9798 case Intrinsic::riscv_mopr:
9802 case Intrinsic::riscv_moprr: {
9804 Op.getOperand(2),
Op.getOperand(3));
9806 case Intrinsic::riscv_clmul:
9809 case Intrinsic::riscv_clmulh:
9810 case Intrinsic::riscv_clmulr: {
9813 return DAG.
getNode(Opc,
DL, XLenVT,
Op.getOperand(1),
Op.getOperand(2));
9815 case Intrinsic::experimental_get_vector_length:
9817 case Intrinsic::experimental_cttz_elts:
9819 case Intrinsic::riscv_vmv_x_s: {
9823 case Intrinsic::riscv_vfmv_f_s:
9826 case Intrinsic::riscv_vmv_v_x:
9828 Op.getOperand(3),
Op.getSimpleValueType(),
DL, DAG,
9830 case Intrinsic::riscv_vfmv_v_f:
9832 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
9833 case Intrinsic::riscv_vmv_s_x: {
9836 if (
Scalar.getValueType().bitsLE(XLenVT)) {
9839 Op.getOperand(1), Scalar,
Op.getOperand(3));
9842 assert(
Scalar.getValueType() == MVT::i64 &&
"Unexpected scalar VT!");
9859 MVT VT =
Op.getSimpleValueType();
9864 if (
Op.getOperand(1).isUndef())
9880 case Intrinsic::riscv_vfmv_s_f:
9882 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
9884 case Intrinsic::riscv_vaesdf_vv:
9885 case Intrinsic::riscv_vaesdf_vs:
9886 case Intrinsic::riscv_vaesdm_vv:
9887 case Intrinsic::riscv_vaesdm_vs:
9888 case Intrinsic::riscv_vaesef_vv:
9889 case Intrinsic::riscv_vaesef_vs:
9890 case Intrinsic::riscv_vaesem_vv:
9891 case Intrinsic::riscv_vaesem_vs:
9892 case Intrinsic::riscv_vaeskf1:
9893 case Intrinsic::riscv_vaeskf2:
9894 case Intrinsic::riscv_vaesz_vs:
9895 case Intrinsic::riscv_vsm4k:
9896 case Intrinsic::riscv_vsm4r_vv:
9897 case Intrinsic::riscv_vsm4r_vs: {
9898 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
9899 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
9900 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
9905 case Intrinsic::riscv_vsm3c:
9906 case Intrinsic::riscv_vsm3me: {
9907 if (!
isValidEGW(8,
Op.getSimpleValueType(), Subtarget) ||
9908 !
isValidEGW(8,
Op->getOperand(1).getSimpleValueType(), Subtarget))
9913 case Intrinsic::riscv_vsha2ch:
9914 case Intrinsic::riscv_vsha2cl:
9915 case Intrinsic::riscv_vsha2ms: {
9916 if (
Op->getSimpleValueType(0).getScalarSizeInBits() == 64 &&
9917 !Subtarget.hasStdExtZvknhb())
9919 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
9920 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
9921 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
9925 case Intrinsic::riscv_sf_vc_v_x:
9926 case Intrinsic::riscv_sf_vc_v_i:
9927 case Intrinsic::riscv_sf_vc_v_xv:
9928 case Intrinsic::riscv_sf_vc_v_iv:
9929 case Intrinsic::riscv_sf_vc_v_vv:
9930 case Intrinsic::riscv_sf_vc_v_fv:
9931 case Intrinsic::riscv_sf_vc_v_xvv:
9932 case Intrinsic::riscv_sf_vc_v_ivv:
9933 case Intrinsic::riscv_sf_vc_v_vvv:
9934 case Intrinsic::riscv_sf_vc_v_fvv:
9935 case Intrinsic::riscv_sf_vc_v_xvw:
9936 case Intrinsic::riscv_sf_vc_v_ivw:
9937 case Intrinsic::riscv_sf_vc_v_vvw:
9938 case Intrinsic::riscv_sf_vc_v_fvw: {
9939 MVT VT =
Op.getSimpleValueType();
9976 MVT VT =
Op.getSimpleValueType();
9980 if (VT.isFloatingPoint()) {
9985 if (VT.isFixedLengthVector())
9995 if (VT.isFixedLengthVector())
9997 if (VT.isFloatingPoint())
10016 unsigned IntNo =
Op.getConstantOperandVal(1);
10020 case Intrinsic::riscv_seg2_load:
10021 case Intrinsic::riscv_seg3_load:
10022 case Intrinsic::riscv_seg4_load:
10023 case Intrinsic::riscv_seg5_load:
10024 case Intrinsic::riscv_seg6_load:
10025 case Intrinsic::riscv_seg7_load:
10026 case Intrinsic::riscv_seg8_load: {
10029 Intrinsic::riscv_vlseg2, Intrinsic::riscv_vlseg3,
10030 Intrinsic::riscv_vlseg4, Intrinsic::riscv_vlseg5,
10031 Intrinsic::riscv_vlseg6, Intrinsic::riscv_vlseg7,
10032 Intrinsic::riscv_vlseg8};
10033 unsigned NF =
Op->getNumValues() - 1;
10034 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
10036 MVT VT =
Op->getSimpleValueType(0);
10044 auto *
Load = cast<MemIntrinsicSDNode>(
Op);
10056 Load->getMemoryVT(),
Load->getMemOperand());
10058 for (
unsigned int RetIdx = 0; RetIdx < NF; RetIdx++) {
10067 case Intrinsic::riscv_sf_vc_v_x_se:
10069 case Intrinsic::riscv_sf_vc_v_i_se:
10071 case Intrinsic::riscv_sf_vc_v_xv_se:
10073 case Intrinsic::riscv_sf_vc_v_iv_se:
10075 case Intrinsic::riscv_sf_vc_v_vv_se:
10077 case Intrinsic::riscv_sf_vc_v_fv_se:
10079 case Intrinsic::riscv_sf_vc_v_xvv_se:
10081 case Intrinsic::riscv_sf_vc_v_ivv_se:
10083 case Intrinsic::riscv_sf_vc_v_vvv_se:
10085 case Intrinsic::riscv_sf_vc_v_fvv_se:
10087 case Intrinsic::riscv_sf_vc_v_xvw_se:
10089 case Intrinsic::riscv_sf_vc_v_ivw_se:
10091 case Intrinsic::riscv_sf_vc_v_vvw_se:
10093 case Intrinsic::riscv_sf_vc_v_fvw_se:
10102 unsigned IntNo =
Op.getConstantOperandVal(1);
10106 case Intrinsic::riscv_seg2_store:
10107 case Intrinsic::riscv_seg3_store:
10108 case Intrinsic::riscv_seg4_store:
10109 case Intrinsic::riscv_seg5_store:
10110 case Intrinsic::riscv_seg6_store:
10111 case Intrinsic::riscv_seg7_store:
10112 case Intrinsic::riscv_seg8_store: {
10115 Intrinsic::riscv_vsseg2, Intrinsic::riscv_vsseg3,
10116 Intrinsic::riscv_vsseg4, Intrinsic::riscv_vsseg5,
10117 Intrinsic::riscv_vsseg6, Intrinsic::riscv_vsseg7,
10118 Intrinsic::riscv_vsseg8};
10121 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
10123 MVT VT =
Op->getOperand(2).getSimpleValueType();
10133 auto *FixedIntrinsic = cast<MemIntrinsicSDNode>(
Op);
10136 for (
unsigned i = 0; i < NF; i++)
10140 ContainerVT, FixedIntrinsic->getOperand(2 + i), DAG, Subtarget),
10144 FixedIntrinsic->getChain(),
10153 FixedIntrinsic->getMemoryVT(), FixedIntrinsic->getMemOperand());
10155 case Intrinsic::riscv_sf_vc_xv_se:
10157 case Intrinsic::riscv_sf_vc_iv_se:
10159 case Intrinsic::riscv_sf_vc_vv_se:
10161 case Intrinsic::riscv_sf_vc_fv_se:
10163 case Intrinsic::riscv_sf_vc_xvv_se:
10165 case Intrinsic::riscv_sf_vc_ivv_se:
10167 case Intrinsic::riscv_sf_vc_vvv_se:
10169 case Intrinsic::riscv_sf_vc_fvv_se:
10171 case Intrinsic::riscv_sf_vc_xvw_se:
10173 case Intrinsic::riscv_sf_vc_ivw_se:
10175 case Intrinsic::riscv_sf_vc_vvw_se:
10177 case Intrinsic::riscv_sf_vc_fvw_se:
10185 switch (ISDOpcode) {
10188 case ISD::VP_REDUCE_ADD:
10191 case ISD::VP_REDUCE_UMAX:
10194 case ISD::VP_REDUCE_SMAX:
10197 case ISD::VP_REDUCE_UMIN:
10200 case ISD::VP_REDUCE_SMIN:
10203 case ISD::VP_REDUCE_AND:
10206 case ISD::VP_REDUCE_OR:
10209 case ISD::VP_REDUCE_XOR:
10212 case ISD::VP_REDUCE_FADD:
10214 case ISD::VP_REDUCE_SEQ_FADD:
10216 case ISD::VP_REDUCE_FMAX:
10217 case ISD::VP_REDUCE_FMAXIMUM:
10219 case ISD::VP_REDUCE_FMIN:
10220 case ISD::VP_REDUCE_FMINIMUM:
10230 SDValue Vec =
Op.getOperand(IsVP ? 1 : 0);
10235 Op.getOpcode() == ISD::VP_REDUCE_AND ||
10236 Op.getOpcode() == ISD::VP_REDUCE_OR ||
10237 Op.getOpcode() == ISD::VP_REDUCE_XOR) &&
10238 "Unexpected reduction lowering");
10242 MVT ContainerVT = VecVT;
10250 Mask =
Op.getOperand(2);
10251 VL =
Op.getOperand(3);
10253 std::tie(Mask, VL) =
10258 switch (
Op.getOpcode()) {
10262 case ISD::VP_REDUCE_AND: {
10274 case ISD::VP_REDUCE_OR:
10280 case ISD::VP_REDUCE_XOR: {
10304 return DAG.
getNode(BaseOpc,
DL,
Op.getValueType(), SetCC,
Op.getOperand(0));
10308 auto *RegisterAVL = dyn_cast<RegisterSDNode>(AVL);
10309 auto *ImmAVL = dyn_cast<ConstantSDNode>(AVL);
10310 return (RegisterAVL && RegisterAVL->getReg() == RISCV::X0) ||
10311 (ImmAVL && ImmAVL->getZExtValue() >= 1);
10327 auto InnerVT = VecVT.
bitsLE(M1VT) ? VecVT : M1VT;
10331 auto InnerVL = NonZeroAVL ? VL : DAG.
getConstant(1,
DL, XLenVT);
10334 if (M1VT != InnerVT)
10340 SDValue Ops[] = {PassThru, Vec, InitialValue, Mask, VL, Policy};
10359 VecEVT =
Lo.getValueType();
10372 MVT ContainerVT = VecVT;
10392 Mask, VL,
DL, DAG, Subtarget);
10398static std::tuple<unsigned, SDValue, SDValue>
10402 auto Flags =
Op->getFlags();
10403 unsigned Opcode =
Op.getOpcode();
10427 return std::make_tuple(RVVOpc,
Op.getOperand(0), Front);
10435 MVT VecEltVT =
Op.getSimpleValueType();
10437 unsigned RVVOpcode;
10438 SDValue VectorVal, ScalarVal;
10439 std::tie(RVVOpcode, VectorVal, ScalarVal) =
10443 MVT ContainerVT = VecVT;
10449 MVT ResVT =
Op.getSimpleValueType();
10452 VL,
DL, DAG, Subtarget);
10457 if (
Op->getFlags().hasNoNaNs())
10463 {VectorVal, VectorVal, DAG.getCondCode(ISD::SETNE),
10464 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
10470 DL, ResVT, NoNaNs, Res,
10477 unsigned Opc =
Op.getOpcode();
10500 Vec, Mask, VL,
DL, DAG, Subtarget);
10501 if ((Opc != ISD::VP_REDUCE_FMINIMUM && Opc != ISD::VP_REDUCE_FMAXIMUM) ||
10502 Op->getFlags().hasNoNaNs())
10519 DL, ResVT, NoNaNs, Res,
10532 unsigned OrigIdx =
Op.getConstantOperandVal(2);
10535 if (OrigIdx == 0 && Vec.
isUndef())
10546 assert(OrigIdx % 8 == 0 &&
"Invalid index");
10549 "Unexpected mask vector lowering");
10581 MVT ContainerVT = VecVT;
10588 DAG.
getUNDEF(ContainerVT), SubVec,
10605 if (OrigIdx == 0) {
10610 SubVec =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, Vec, SubVec,
10611 SlideupAmt, Mask, VL, Policy);
10619 MVT ContainerVecVT = VecVT;
10625 MVT ContainerSubVecVT = SubVecVT;
10631 unsigned SubRegIdx;
10641 ContainerVecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
10642 SubRegIdx = Decompose.first;
10644 (OrigIdx % Vscale));
10648 ContainerVecVT, ContainerSubVecVT, OrigIdx,
TRI);
10649 SubRegIdx = Decompose.first;
10656 bool ExactlyVecRegSized =
10658 .isKnownMultipleOf(Subtarget.
expandVScale(VecRegSize));
10673 if (RemIdx.
isZero() && (ExactlyVecRegSized || Vec.
isUndef())) {
10677 if (SubRegIdx == RISCV::NoSubRegister) {
10700 MVT InterSubVT = ContainerVecVT;
10701 SDValue AlignedExtract = Vec;
10741 SubVec =
getVSlideup(DAG, Subtarget,
DL, InterSubVT, AlignedExtract, SubVec,
10742 SlideupAmt, Mask, VL, Policy);
10747 if (ContainerVecVT.
bitsGT(InterSubVT))
10756 return DAG.
getBitcast(
Op.getSimpleValueType(), SubVec);
10762 MVT SubVecVT =
Op.getSimpleValueType();
10767 unsigned OrigIdx =
Op.getConstantOperandVal(1);
10783 assert(OrigIdx % 8 == 0 &&
"Invalid index");
10786 "Unexpected mask vector lowering");
10820 MVT ContainerVT = VecVT;
10828 if (
auto ShrunkVT =
10830 ContainerVT = *ShrunkVT;
10843 DAG.
getUNDEF(ContainerVT), Vec, SlidedownAmt, Mask, VL);
10855 MVT ContainerSubVecVT = SubVecVT;
10859 unsigned SubRegIdx;
10869 VecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
10870 SubRegIdx = Decompose.first;
10872 (OrigIdx % Vscale));
10876 VecVT, ContainerSubVecVT, OrigIdx,
TRI);
10877 SubRegIdx = Decompose.first;
10904 MVT InterSubVT = VecVT;
10909 assert(SubRegIdx != RISCV::NoSubRegister);
10929 Vec, SlidedownAmt, Mask, VL);
10938 return DAG.
getBitcast(
Op.getSimpleValueType(), Slidedown);
10945 MVT VT =
N.getSimpleValueType();
10949 assert(
Op.getSimpleValueType() == VT &&
10950 "Operands and result must be same type");
10954 unsigned NumVals =
N->getNumValues();
10957 NumVals,
N.getValueType().changeVectorElementType(MVT::i8)));
10960 for (
unsigned I = 0;
I < NumVals;
I++) {
10966 if (TruncVals.
size() > 1)
10968 return TruncVals.
front();
10974 MVT VecVT =
Op.getSimpleValueType();
10977 "vector_interleave on non-scalable vector!");
10988 EVT SplitVT = Op0Lo.getValueType();
10991 DAG.
getVTList(SplitVT, SplitVT), Op0Lo, Op0Hi);
10993 DAG.
getVTList(SplitVT, SplitVT), Op1Lo, Op1Hi);
11007 Op.getOperand(0),
Op.getOperand(1));
11026 EvenSplat = DAG.
getBitcast(MVT::nxv64i1, EvenSplat);
11031 OddSplat = DAG.
getBitcast(MVT::nxv64i1, OddSplat);
11037 EvenMask, DAG.
getUNDEF(ConcatVT));
11053 MVT VecVT =
Op.getSimpleValueType();
11056 "vector_interleave on non-scalable vector!");
11069 EVT SplitVT = Op0Lo.getValueType();
11072 DAG.
getVTList(SplitVT, SplitVT), Op0Lo, Op1Lo);
11074 DAG.
getVTList(SplitVT, SplitVT), Op0Hi, Op1Hi);
11096 Op.getOperand(0),
Op.getOperand(1));
11144 MVT VT =
Op.getSimpleValueType();
11149 uint64_t StepValImm =
Op.getConstantOperandVal(0);
11150 if (StepValImm != 1) {
11159 VL, VT,
DL, DAG, Subtarget);
11174 MVT VecVT =
Op.getSimpleValueType();
11183 MVT ContainerVT = VecVT;
11237 unsigned MaxVLMAX =
11247 if (MaxVLMAX > 256 && EltSize == 8) {
11276 assert(isUInt<16>(MaxVLMAX - 1));
11302 DAG.
getUNDEF(ContainerVT), Mask, VL);
11314 MVT VecVT =
Op.getSimpleValueType();
11318 int64_t ImmValue = cast<ConstantSDNode>(
Op.getOperand(2))->getSExtValue();
11319 SDValue DownOffset, UpOffset;
11320 if (ImmValue >= 0) {
11336 DownOffset, TrueMask, UpOffset);
11337 return getVSlideup(DAG, Subtarget,
DL, VecVT, SlideDown, V2, UpOffset,
11343RISCVTargetLowering::lowerFixedLengthVectorLoadToRVV(
SDValue Op,
11346 auto *
Load = cast<LoadSDNode>(
Op);
11349 Load->getMemoryVT(),
11350 *
Load->getMemOperand()) &&
11351 "Expecting a correctly-aligned load");
11353 MVT VT =
Op.getSimpleValueType();
11359 const auto [MinVLMAX, MaxVLMAX] =
11362 getLMUL1VT(ContainerVT).bitsLE(ContainerVT)) {
11376 IsMaskOp ? Intrinsic::riscv_vlm : Intrinsic::riscv_vle,
DL, XLenVT);
11379 Ops.push_back(DAG.
getUNDEF(ContainerVT));
11380 Ops.push_back(
Load->getBasePtr());
11385 Load->getMemoryVT(),
Load->getMemOperand());
11392RISCVTargetLowering::lowerFixedLengthVectorStoreToRVV(
SDValue Op,
11395 auto *
Store = cast<StoreSDNode>(
Op);
11398 Store->getMemoryVT(),
11399 *
Store->getMemOperand()) &&
11400 "Expecting a correctly-aligned store");
11421 const auto [MinVLMAX, MaxVLMAX] =
11424 getLMUL1VT(ContainerVT).bitsLE(ContainerVT)) {
11435 IsMaskOp ? Intrinsic::riscv_vsm : Intrinsic::riscv_vse,
DL, XLenVT);
11438 {Store->getChain(), IntID, NewValue, Store->getBasePtr(), VL},
11439 Store->getMemoryVT(),
Store->getMemOperand());
11445 MVT VT =
Op.getSimpleValueType();
11447 const auto *MemSD = cast<MemSDNode>(
Op);
11448 EVT MemVT = MemSD->getMemoryVT();
11450 SDValue Chain = MemSD->getChain();
11454 bool IsExpandingLoad =
false;
11455 if (
const auto *VPLoad = dyn_cast<VPLoadSDNode>(
Op)) {
11456 Mask = VPLoad->getMask();
11458 VL = VPLoad->getVectorLength();
11460 const auto *MLoad = cast<MaskedLoadSDNode>(
Op);
11461 Mask = MLoad->getMask();
11462 PassThru = MLoad->getPassThru();
11463 IsExpandingLoad = MLoad->isExpandingLoad();
11470 MVT ContainerVT = VT;
11484 if (!IsUnmasked && IsExpandingLoad) {
11491 unsigned IntID = IsUnmasked || IsExpandingLoad ? Intrinsic::riscv_vle
11492 : Intrinsic::riscv_vle_mask;
11494 if (IntID == Intrinsic::riscv_vle)
11495 Ops.push_back(DAG.
getUNDEF(ContainerVT));
11497 Ops.push_back(PassThru);
11498 Ops.push_back(BasePtr);
11499 if (IntID == Intrinsic::riscv_vle_mask)
11500 Ops.push_back(Mask);
11502 if (IntID == Intrinsic::riscv_vle_mask)
11509 Chain =
Result.getValue(1);
11511 MVT IndexVT = ContainerVT;
11516 bool UseVRGATHEREI16 =
false;
11524 UseVRGATHEREI16 =
true;
11530 DAG.
getUNDEF(IndexVT), Mask, ExpandingVL);
11534 DL, ContainerVT, Result, Iota, PassThru, Mask, ExpandingVL);
11547 const auto *MemSD = cast<MemSDNode>(
Op);
11548 EVT MemVT = MemSD->getMemoryVT();
11550 SDValue Chain = MemSD->getChain();
11554 bool IsCompressingStore =
false;
11555 if (
const auto *VPStore = dyn_cast<VPStoreSDNode>(
Op)) {
11556 Val = VPStore->getValue();
11557 Mask = VPStore->getMask();
11558 VL = VPStore->getVectorLength();
11560 const auto *MStore = cast<MaskedStoreSDNode>(
Op);
11561 Val = MStore->getValue();
11562 Mask = MStore->getMask();
11563 IsCompressingStore = MStore->isCompressingStore();
11572 MVT ContainerVT = VT;
11577 if (!IsUnmasked || IsCompressingStore) {
11586 if (IsCompressingStore) {
11589 DAG.
getUNDEF(ContainerVT), Val, Mask, VL);
11596 IsUnmasked ? Intrinsic::riscv_vse : Intrinsic::riscv_vse_mask;
11598 Ops.push_back(Val);
11599 Ops.push_back(BasePtr);
11601 Ops.push_back(Mask);
11605 DAG.
getVTList(MVT::Other), Ops, MemVT, MMO);
11617 MVT ContainerVT = VT;
11630 Passthru, Val, Mask, VL);
11639RISCVTargetLowering::lowerFixedLengthVectorSetccToRVV(
SDValue Op,
11641 MVT InVT =
Op.getOperand(0).getSimpleValueType();
11644 MVT VT =
Op.getSimpleValueType();
11658 {Op1, Op2,
Op.getOperand(2), DAG.
getUNDEF(MaskVT), Mask, VL});
11665 unsigned Opc =
Op.getOpcode();
11672 MVT VT =
Op.getSimpleValueType();
11705 MVT ContainerInVT = InVT;
11724 {Chain, Op1, Op1, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
11728 {Chain, Op2, Op2, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
11736 {Chain, Op1, Op2, CC, Mask, Mask, VL});
11741 {Chain, Op1, Op2, CC, DAG.getUNDEF(MaskVT), Mask, VL});
11754 MVT VT =
Op.getSimpleValueType();
11758 "Unexpected type for ISD::ABS");
11760 MVT ContainerVT = VT;
11767 if (
Op->getOpcode() == ISD::VP_ABS) {
11768 Mask =
Op->getOperand(1);
11772 VL =
Op->getOperand(2);
11780 DAG.
getUNDEF(ContainerVT), Mask, VL);
11782 DAG.
getUNDEF(ContainerVT), Mask, VL);
11789SDValue RISCVTargetLowering::lowerFixedLengthVectorFCOPYSIGNToRVV(
11792 MVT VT =
Op.getSimpleValueType();
11796 "Can only handle COPYSIGN with matching types.");
11805 Sign, DAG.
getUNDEF(ContainerVT), Mask, VL);
11810SDValue RISCVTargetLowering::lowerFixedLengthVectorSelectToRVV(
11812 MVT VT =
Op.getSimpleValueType();
11815 MVT I1ContainerVT =
11829 Op2, DAG.
getUNDEF(ContainerVT), VL);
11840 MVT VT =
Op.getSimpleValueType();
11845 for (
const SDValue &V :
Op->op_values()) {
11846 assert(!isa<VTSDNode>(V) &&
"Unexpected VTSDNode node!");
11849 if (!
V.getValueType().isVector()) {
11855 assert(useRVVForFixedLengthVectorVT(
V.getSimpleValueType()) &&
11856 "Only fixed length vectors are supported!");
11870 if (
Op->isStrictFPOpcode()) {
11879 DAG.
getNode(NewOpc,
DL, ContainerVT, Ops,
Op->getFlags());
11893 MVT VT =
Op.getSimpleValueType();
11896 MVT ContainerVT = VT;
11902 assert(!isa<VTSDNode>(V) &&
"Unexpected VTSDNode node!");
11905 if (HasPassthruOp) {
11908 if (*MaskIdx == OpIdx.index())
11912 if (
Op.getOpcode() == ISD::VP_MERGE) {
11916 assert(
Op.getOpcode() == ISD::VP_SELECT);
11928 if (!
V.getValueType().isFixedLengthVector()) {
11933 MVT OpVT =
V.getSimpleValueType();
11935 assert(useRVVForFixedLengthVectorVT(OpVT) &&
11936 "Only fixed length vectors are supported!");
11941 return DAG.
getNode(RISCVISDOpc,
DL, VT, Ops,
Op->getFlags());
11951 MVT VT =
Op.getSimpleValueType();
11957 MVT ContainerVT = VT;
11967 DAG.
getUNDEF(ContainerVT), Zero, VL);
11970 Op.getOpcode() == ISD::VP_ZERO_EXTEND ? 1 : -1,
DL, XLenVT);
11972 DAG.
getUNDEF(ContainerVT), SplatValue, VL);
11975 ZeroSplat, DAG.
getUNDEF(ContainerVT), VL);
11984 MVT VT =
Op.getSimpleValueType();
11988 ISD::CondCode Condition = cast<CondCodeSDNode>(
Op.getOperand(2))->get();
11992 MVT ContainerVT = VT;
12002 switch (Condition) {
12070 MVT DstVT =
Op.getSimpleValueType();
12071 MVT SrcVT = Src.getSimpleValueType();
12084 if (DstEltSize >= SrcEltSize) {
12093 if (SrcEltSize == 1) {
12104 ZeroSplat, DAG.
getUNDEF(IntVT), VL);
12105 }
else if (DstEltSize > (2 * SrcEltSize)) {
12109 Src = DAG.
getNode(RISCVISDExtOpc,
DL, IntVT, Src, Mask, VL);
12115 "Wrong input/output vector types");
12118 if (DstEltSize > (2 * SrcEltSize)) {
12134 MVT InterimFVT = DstVT;
12135 if (SrcEltSize > (2 * DstEltSize)) {
12136 assert(SrcEltSize == (4 * DstEltSize) &&
"Unexpected types!");
12143 if (InterimFVT != DstVT) {
12149 "Wrong input/output vector types");
12153 if (DstEltSize == 1) {
12156 assert(SrcEltSize >= 16 &&
"Unexpected FP type!");
12166 DAG.
getUNDEF(InterimIVT), SplatZero, VL);
12176 while (InterimIVT != DstVT) {
12188 MVT VT =
Op.getSimpleValueType();
12197 MVT VT =
Op.getSimpleValueType();
12211 MVT ContainerVT = VT;
12232 SplatZero, DAG.
getUNDEF(PromotedVT), VL);
12235 SplatOne, SplatZero, DAG.
getUNDEF(PromotedVT), VLMax);
12239 TrueVal, FalseVal, FalseVal, VL);
12254RISCVTargetLowering::lowerVPSpliceExperimental(
SDValue Op,
12266 MVT VT =
Op.getSimpleValueType();
12267 MVT ContainerVT = VT;
12277 if (IsMaskVector) {
12288 SplatZeroOp1, DAG.
getUNDEF(ContainerVT), EVL1);
12297 SplatZeroOp2, DAG.
getUNDEF(ContainerVT), EVL2);
12300 int64_t ImmValue = cast<ConstantSDNode>(
Offset)->getSExtValue();
12301 SDValue DownOffset, UpOffset;
12302 if (ImmValue >= 0) {
12316 Op1, DownOffset, Mask, UpOffset);
12320 if (IsMaskVector) {
12324 {Result, DAG.getConstant(0, DL, ContainerVT),
12325 DAG.getCondCode(ISD::SETNE), DAG.getUNDEF(getMaskTypeFor(ContainerVT)),
12340 MVT VT =
Op.getSimpleValueType();
12342 MVT ContainerVT = VT;
12358RISCVTargetLowering::lowerVPReverseExperimental(
SDValue Op,
12361 MVT VT =
Op.getSimpleValueType();
12368 MVT ContainerVT = VT;
12376 MVT GatherVT = ContainerVT;
12380 if (IsMaskVector) {
12391 SplatZero, DAG.
getUNDEF(IndicesVT), EVL);
12397 unsigned MaxVLMAX =
12406 if (MaxVLMAX > 256 && EltSize == 8) {
12434 DAG.
getUNDEF(GatherVT), Result, Diff, Mask, EVL);
12436 if (IsMaskVector) {
12459 DAG.
getUNDEF(IndicesVT), VecLen, EVL);
12461 DAG.
getUNDEF(IndicesVT), Mask, EVL);
12463 DAG.
getUNDEF(GatherVT), Mask, EVL);
12465 if (IsMaskVector) {
12480 MVT VT =
Op.getSimpleValueType();
12482 return lowerVPOp(
Op, DAG);
12489 MVT ContainerVT = VT;
12508 MVT VT =
Op.getSimpleValueType();
12509 MVT ContainerVT = VT;
12515 auto *VPNode = cast<VPStridedLoadSDNode>(
Op);
12521 : Intrinsic::riscv_vlse_mask,
12524 DAG.
getUNDEF(ContainerVT), VPNode->getBasePtr(),
12525 VPNode->getStride()};
12533 Ops.
push_back(VPNode->getVectorLength());
12541 VPNode->getMemoryVT(), VPNode->getMemOperand());
12555 auto *VPNode = cast<VPStridedStoreSDNode>(
Op);
12556 SDValue StoreVal = VPNode->getValue();
12558 MVT ContainerVT = VT;
12569 : Intrinsic::riscv_vsse_mask,
12572 VPNode->getBasePtr(), VPNode->getStride()};
12580 Ops.
push_back(VPNode->getVectorLength());
12583 Ops, VPNode->getMemoryVT(),
12584 VPNode->getMemOperand());
12596 MVT VT =
Op.getSimpleValueType();
12598 const auto *MemSD = cast<MemSDNode>(
Op.getNode());
12599 EVT MemVT = MemSD->getMemoryVT();
12601 SDValue Chain = MemSD->getChain();
12607 if (
auto *VPGN = dyn_cast<VPGatherSDNode>(
Op.getNode())) {
12608 Index = VPGN->getIndex();
12609 Mask = VPGN->getMask();
12611 VL = VPGN->getVectorLength();
12616 auto *MGN = cast<MaskedGatherSDNode>(
Op.getNode());
12617 Index = MGN->getIndex();
12618 Mask = MGN->getMask();
12619 PassThru = MGN->getPassThru();
12623 MVT IndexVT =
Index.getSimpleValueType();
12627 "Unexpected VTs!");
12628 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
12631 "Unexpected extending MGATHER/VP_GATHER");
12637 MVT ContainerVT = VT;
12661 IsUnmasked ? Intrinsic::riscv_vluxei : Intrinsic::riscv_vluxei_mask;
12678 Chain =
Result.getValue(1);
12695 const auto *MemSD = cast<MemSDNode>(
Op.getNode());
12696 EVT MemVT = MemSD->getMemoryVT();
12698 SDValue Chain = MemSD->getChain();
12701 [[maybe_unused]]
bool IsTruncatingStore =
false;
12704 if (
auto *VPSN = dyn_cast<VPScatterSDNode>(
Op.getNode())) {
12705 Index = VPSN->getIndex();
12706 Mask = VPSN->getMask();
12707 Val = VPSN->getValue();
12708 VL = VPSN->getVectorLength();
12710 IsTruncatingStore =
false;
12713 auto *MSN = cast<MaskedScatterSDNode>(
Op.getNode());
12714 Index = MSN->getIndex();
12715 Mask = MSN->getMask();
12716 Val = MSN->getValue();
12717 IsTruncatingStore = MSN->isTruncatingStore();
12721 MVT IndexVT =
Index.getSimpleValueType();
12725 "Unexpected VTs!");
12726 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
12729 assert(!IsTruncatingStore &&
"Unexpected truncating MSCATTER/VP_SCATTER");
12735 MVT ContainerVT = VT;
12759 IsUnmasked ? Intrinsic::riscv_vsoxei : Intrinsic::riscv_vsoxei_mask;
12769 DAG.
getVTList(MVT::Other), Ops, MemVT, MMO);
12785 static const int Table =
12814 static const unsigned Table =
12837 bool isRISCV64 = Subtarget.
is64Bit();
12901 switch (
N->getOpcode()) {
12903 llvm_unreachable(
"Don't know how to custom type legalize this operation!");
12909 "Unexpected custom legalisation");
12910 bool IsStrict =
N->isStrictFPOpcode();
12913 SDValue Op0 = IsStrict ?
N->getOperand(1) :
N->getOperand(0);
12931 Opc,
DL, VTs, Chain, Op0,
12965 std::tie(Result, Chain) =
12966 makeLibCall(DAG, LC,
N->getValueType(0), Op0, CallOptions,
DL, Chain);
12994 Op0.
getValueType() == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
13005 assert(!Subtarget.
is64Bit() &&
"READCYCLECOUNTER/READSTEADYCOUNTER only "
13006 "has custom type legalization on riscv32");
13008 SDValue LoCounter, HiCounter;
13019 N->getOperand(0), LoCounter, HiCounter);
13043 unsigned Size =
N->getSimpleValueType(0).getSizeInBits();
13044 unsigned XLen = Subtarget.
getXLen();
13047 assert(
Size == (XLen * 2) &&
"Unexpected custom legalisation");
13055 if (LHSIsU == RHSIsU)
13072 if (RHSIsU && LHSIsS && !RHSIsS)
13074 else if (LHSIsU && RHSIsS && !LHSIsS)
13084 "Unexpected custom legalisation");
13091 "Unexpected custom legalisation");
13094 if (
N->getOpcode() ==
ISD::SHL && Subtarget.hasStdExtZbs() &&
13120 "Unexpected custom legalisation");
13121 assert((Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb() ||
13122 Subtarget.hasVendorXTHeadBb()) &&
13123 "Unexpected custom legalization");
13124 if (!isa<ConstantSDNode>(
N->getOperand(1)) &&
13125 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()))
13134 "Unexpected custom legalisation");
13148 MVT VT =
N->getSimpleValueType(0);
13149 assert((VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32) &&
13150 Subtarget.
is64Bit() && Subtarget.hasStdExtM() &&
13151 "Unexpected custom legalisation");
13163 if (VT != MVT::i32)
13172 "Unexpected custom legalisation");
13176 if (!isa<ConstantSDNode>(
N->getOperand(1)))
13193 EVT OType =
N->getValueType(1);
13206 "Unexpected custom legalisation");
13223 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1), Res,
13227 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1),
N->getOperand(0),
13245 !Subtarget.hasStdExtZbb() &&
"Unexpected custom legalisation");
13254 "Unexpected custom legalisation");
13260 "Unexpected custom legalisation");
13262 if (Subtarget.hasStdExtZbb()) {
13296 EVT VT =
N->getValueType(0);
13301 if (VT == MVT::i16 &&
13303 (Op0VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
13306 }
else if (VT == MVT::i32 && Op0VT == MVT::f32 && Subtarget.
is64Bit() &&
13311 }
else if (VT == MVT::i64 && Op0VT == MVT::f64 && !Subtarget.
is64Bit() &&
13314 DAG.
getVTList(MVT::i32, MVT::i32), Op0);
13335 MVT VT =
N->getSimpleValueType(0);
13337 assert((VT == MVT::i16 || (VT == MVT::i32 && Subtarget.
is64Bit())) &&
13338 "Unexpected custom legalisation");
13341 "Unexpected extension");
13367 assert(!Subtarget.
is64Bit() &&
N->getValueType(0) == MVT::i64 &&
13369 "Unexpected EXTRACT_VECTOR_ELT legalization");
13372 MVT ContainerVT = VecVT;
13400 DAG.
getUNDEF(ContainerVT), Mask, VL);
13408 unsigned IntNo =
N->getConstantOperandVal(0);
13412 "Don't know how to custom type legalize this intrinsic!");
13413 case Intrinsic::experimental_get_vector_length: {
13418 case Intrinsic::experimental_cttz_elts: {
13424 case Intrinsic::riscv_orc_b:
13425 case Intrinsic::riscv_brev8:
13426 case Intrinsic::riscv_sha256sig0:
13427 case Intrinsic::riscv_sha256sig1:
13428 case Intrinsic::riscv_sha256sum0:
13429 case Intrinsic::riscv_sha256sum1:
13430 case Intrinsic::riscv_sm3p0:
13431 case Intrinsic::riscv_sm3p1: {
13432 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
13452 case Intrinsic::riscv_sm4ks:
13453 case Intrinsic::riscv_sm4ed: {
13461 DAG.
getNode(Opc,
DL, MVT::i64, NewOp0, NewOp1,
N->getOperand(3));
13465 case Intrinsic::riscv_mopr: {
13466 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
13476 case Intrinsic::riscv_moprr: {
13477 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
13489 case Intrinsic::riscv_clmul: {
13490 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
13501 case Intrinsic::riscv_clmulh:
13502 case Intrinsic::riscv_clmulr: {
13503 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
13531 case Intrinsic::riscv_vmv_x_s: {
13532 EVT VT =
N->getValueType(0);
13534 if (VT.
bitsLT(XLenVT)) {
13543 "Unexpected custom legalization");
13581 case ISD::VP_REDUCE_ADD:
13582 case ISD::VP_REDUCE_AND:
13583 case ISD::VP_REDUCE_OR:
13584 case ISD::VP_REDUCE_XOR:
13585 case ISD::VP_REDUCE_SMAX:
13586 case ISD::VP_REDUCE_UMAX:
13587 case ISD::VP_REDUCE_SMIN:
13588 case ISD::VP_REDUCE_UMIN:
13652 const EVT VT =
N->getValueType(0);
13653 const unsigned Opc =
N->getOpcode();
13660 (Opc !=
ISD::FADD || !
N->getFlags().hasAllowReassociation()))
13665 "Inconsistent mappings");
13676 !isa<ConstantSDNode>(
RHS.getOperand(1)))
13679 uint64_t RHSIdx = cast<ConstantSDNode>(
RHS.getOperand(1))->getLimitedValue();
13694 LHS.getOperand(0) == SrcVec && isa<ConstantSDNode>(
LHS.getOperand(1))) {
13696 cast<ConstantSDNode>(
LHS.getOperand(1))->getLimitedValue();
13697 if (0 == std::min(LHSIdx, RHSIdx) && 1 == std::max(LHSIdx, RHSIdx)) {
13701 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
N->getFlags());
13708 if (
LHS.getOpcode() != ReduceOpc)
13723 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
13724 ReduceVec->
getFlags() &
N->getFlags());
13734 auto BinOpToRVVReduce = [](
unsigned Opc) {
13763 auto IsReduction = [&BinOpToRVVReduce](
SDValue V,
unsigned Opc) {
13766 V.getOperand(0).getOpcode() == BinOpToRVVReduce(Opc);
13769 unsigned Opc =
N->getOpcode();
13770 unsigned ReduceIdx;
13771 if (IsReduction(
N->getOperand(0), Opc))
13773 else if (IsReduction(
N->getOperand(1), Opc))
13779 if (Opc ==
ISD::FADD && !
N->getFlags().hasAllowReassociation())
13782 SDValue Extract =
N->getOperand(ReduceIdx);
13814 SDValue NewStart =
N->getOperand(1 - ReduceIdx);
13841 if (!Subtarget.hasStdExtZba())
13845 EVT VT =
N->getValueType(0);
13857 auto *N0C = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
13858 auto *N1C = dyn_cast<ConstantSDNode>(N1->
getOperand(1));
13861 int64_t C0 = N0C->getSExtValue();
13862 int64_t C1 = N1C->getSExtValue();
13863 if (C0 <= 0 || C1 <= 0)
13867 int64_t Bits = std::min(C0, C1);
13868 int64_t Diff = std::abs(C0 - C1);
13869 if (Diff != 1 && Diff != 2 && Diff != 3)
13896 EVT VT =
N->getValueType(0);
13904 if ((!Subtarget.hasStdExtZicond() &&
13905 !Subtarget.hasVendorXVentanaCondOps()) ||
13927 bool SwapSelectOps;
13933 SwapSelectOps =
false;
13934 NonConstantVal = FalseVal;
13936 SwapSelectOps =
true;
13937 NonConstantVal = TrueVal;
13943 FalseVal = DAG.
getNode(
N->getOpcode(),
SDLoc(
N), VT, OtherOp, NonConstantVal);
13991 EVT VT =
N->getValueType(0);
13999 auto *N0C = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
14000 auto *N1C = dyn_cast<ConstantSDNode>(
N->getOperand(1));
14006 if (!N0C->hasOneUse())
14008 int64_t C0 = N0C->getSExtValue();
14009 int64_t C1 = N1C->getSExtValue();
14011 if (C0 == -1 || C0 == 0 || C0 == 1 || isInt<12>(C1))
14014 if ((C1 / C0) != 0 && isInt<12>(C1 / C0) && isInt<12>(C1 % C0) &&
14015 !isInt<12>(C0 * (C1 / C0))) {
14018 }
else if ((C1 / C0 + 1) != 0 && isInt<12>(C1 / C0 + 1) &&
14019 isInt<12>(C1 % C0 - C0) && !isInt<12>(C0 * (C1 / C0 + 1))) {
14022 }
else if ((C1 / C0 - 1) != 0 && isInt<12>(C1 / C0 - 1) &&
14023 isInt<12>(C1 % C0 + C0) && !isInt<12>(C0 * (C1 / C0 - 1))) {
14050 EVT VT =
N->getValueType(0);
14081 unsigned OuterExtend =
14085 OuterExtend,
SDLoc(
N), VT,
14093 EVT VT =
N->getValueType(0);
14141 EVT VT =
N->getValueType(0);
14145 auto *N0C = dyn_cast<ConstantSDNode>(N0);
14151 APInt ImmValMinus1 = N0C->getAPIntValue() - 1;
14161 if (!isIntEqualitySetCC(CCVal) || !SetCCOpVT.
isInteger())
14184 if (!Subtarget.hasStdExtZbb())
14187 EVT VT =
N->getValueType(0);
14189 if (VT != Subtarget.
getXLenVT() && VT != MVT::i32 && VT != MVT::i16)
14198 auto *ShAmtCLeft = dyn_cast<ConstantSDNode>(N0.
getOperand(1));
14201 unsigned ShiftedAmount = 8 - ShAmtCLeft->getZExtValue();
14203 if (ShiftedAmount >= 8)
14207 SDValue RightShiftOperand = N1;
14209 if (ShiftedAmount != 0) {
14212 auto *ShAmtCRight = dyn_cast<ConstantSDNode>(N1.
getOperand(1));
14213 if (!ShAmtCRight || ShAmtCRight->getZExtValue() != ShiftedAmount)
14222 if (LeftShiftOperand != RightShiftOperand)
14226 Mask <<= ShiftedAmount;
14240 EVT VT =
N->getValueType(0);
14271 bool IsAnd =
N->getOpcode() ==
ISD::AND;
14295 EVT VT =
N->getValueType(0);
14319 EVT VT =
N->getValueType(0);
14346 if (CondLHS != True)
14353 if (!CondRHSC || CondRHSC->
getAPIntValue() != (1ULL << ScalarBits))
14365 if (!FalseRHSC || !FalseRHSC->
isZero())
14385 EVT VT =
N->getValueType(0);
14392 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() && VT == MVT::i1 &&
14419 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
14471 EVT VT =
N->getValueType(0);
14517 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
14542 auto *ConstN00 = dyn_cast<ConstantSDNode>(N0.
getOperand(0));
14547 const APInt &Imm = ConstN00->getAPIntValue();
14548 if ((Imm + 1).isSignedIntN(12))
14569 EVT VT =
N->getValueType(0);
14581 const bool HasShlAdd =
14582 Subtarget.hasStdExtZba() || Subtarget.hasVendorXTHeadBa();
14596 for (
uint64_t Divisor : {3, 5, 9}) {
14597 if (MulAmt % Divisor != 0)
14599 uint64_t MulAmt2 = MulAmt / Divisor;
14606 if (
X.getOpcode() ==
ISD::AND && isa<ConstantSDNode>(
X.getOperand(1)) &&
14607 X.getConstantOperandVal(1) == UINT64_C(0xffffffff)) {
14624 if (MulAmt2 == 3 || MulAmt2 == 5 || MulAmt2 == 9) {
14640 if (ScaleShift >= 1 && ScaleShift < 4) {
14641 unsigned ShiftAmt =
Log2_64((MulAmt & (MulAmt - 1)));
14655 for (
uint64_t Divisor : {3, 5, 9}) {
14660 if ((
C >> TZ) == Divisor && (TZ == 1 || TZ == 2 || TZ == 3)) {
14671 if (MulAmt > 2 &&
isPowerOf2_64((MulAmt - 1) & (MulAmt - 2))) {
14673 if (ScaleShift >= 1 && ScaleShift < 4) {
14674 unsigned ShiftAmt =
Log2_64(((MulAmt - 1) & (MulAmt - 2)));
14700 uint64_t MulAmtLowBit = MulAmt & (-MulAmt);
14702 uint64_t ShiftAmt1 = MulAmt + MulAmtLowBit;
14713 for (
uint64_t Divisor : {3, 5, 9}) {
14714 if (MulAmt % Divisor != 0)
14716 uint64_t MulAmt2 = MulAmt / Divisor;
14719 for (
uint64_t Divisor2 : {3, 5, 9}) {
14720 if (MulAmt2 % Divisor2 != 0)
14722 uint64_t MulAmt3 = MulAmt2 / Divisor2;
14745 EVT VT =
N->getValueType(0);
14752 if (
N->getOperand(0).getOpcode() !=
ISD::AND ||
14753 N->getOperand(0).getOperand(0).getOpcode() !=
ISD::SRL)
14766 if (!V1.
isMask(HalfSize) || V2 != (1ULL | 1ULL << HalfSize) ||
14767 V3 != (HalfSize - 1))
14783 EVT VT =
N->getValueType(0);
14791 unsigned AddSubOpc;
14797 auto IsAddSubWith1 = [&](
SDValue V) ->
bool {
14798 AddSubOpc = V->getOpcode();
14800 SDValue Opnd = V->getOperand(1);
14801 MulOper = V->getOperand(0);
14810 if (IsAddSubWith1(N0)) {
14812 return DAG.
getNode(AddSubOpc,
DL, VT, N1, MulVal);
14815 if (IsAddSubWith1(N1)) {
14817 return DAG.
getNode(AddSubOpc,
DL, VT, N0, MulVal);
14832 if (isIndexTypeSigned(IndexType))
14835 if (!
N->hasOneUse())
14838 EVT VT =
N.getValueType();
14877 EVT SrcVT = Src.getValueType();
14881 NewElen = std::max(NewElen, 8U);
14904 EVT VT =
N->getValueType(0);
14907 if (OpVT != MVT::i64 || !Subtarget.
is64Bit())
14911 auto *N1C = dyn_cast<ConstantSDNode>(N1);
14923 if (!isIntEqualitySetCC(
Cond))
14932 const APInt &C1 = N1C->getAPIntValue();
14950 EVT VT =
N->getValueType(0);
14951 EVT SrcVT = cast<VTSDNode>(
N->getOperand(1))->
getVT();
14952 unsigned Opc = Src.getOpcode();
14957 Subtarget.hasStdExtZfhmin())
14959 Src.getOperand(0));
14963 VT == MVT::i64 && !isa<ConstantSDNode>(Src.getOperand(1)) &&
14966 Src.getOperand(1));
14974struct CombineResult;
14976enum ExtKind :
uint8_t { ZExt = 1 << 0, SExt = 1 << 1, FPExt = 1 << 2 };
15003struct NodeExtensionHelper {
15012 bool SupportsFPExt;
15015 bool EnforceOneUse;
15030 return OrigOperand;
15041 unsigned getExtOpc(ExtKind SupportsExt)
const {
15042 switch (SupportsExt) {
15043 case ExtKind::SExt:
15045 case ExtKind::ZExt:
15047 case ExtKind::FPExt:
15058 std::optional<ExtKind> SupportsExt)
const {
15059 if (!SupportsExt.has_value())
15060 return OrigOperand;
15062 MVT NarrowVT = getNarrowType(Root, *SupportsExt);
15066 if (
Source.getValueType() == NarrowVT)
15070 if (
Source.getValueType().getVectorElementType() == MVT::bf16) {
15076 unsigned ExtOpc = getExtOpc(*SupportsExt);
15080 auto [
Mask, VL] = getMaskAndVL(Root, DAG, Subtarget);
15087 return DAG.
getNode(ExtOpc,
DL, NarrowVT, Source, Mask, VL);
15099 DAG.
getUNDEF(NarrowVT), Source, VL);
15112 static MVT getNarrowType(
const SDNode *Root, ExtKind SupportsExt) {
15118 MVT EltVT = SupportsExt == ExtKind::FPExt
15120 :
MVT::getIntegerVT(NarrowSize);
15122 assert((
int)NarrowSize >= (SupportsExt == ExtKind::FPExt ? 16 : 8) &&
15123 "Trying to extend something we can't represent");
15130 static unsigned getSExtOpcode(
unsigned Opcode) {
15153 static unsigned getZExtOpcode(
unsigned Opcode) {
15179 static unsigned getFPExtOpcode(
unsigned Opcode) {
15204 static unsigned getSUOpcode(
unsigned Opcode) {
15206 "SU is only supported for MUL");
15212 static unsigned getWOpcode(
unsigned Opcode, ExtKind SupportsExt) {
15232 using CombineToTry = std::function<std::optional<CombineResult>(
15233 SDNode * ,
const NodeExtensionHelper & ,
15238 bool needToPromoteOtherUsers()
const {
return EnforceOneUse; }
15242 unsigned Opc = OrigOperand.
getOpcode();
15246 "Unexpected Opcode");
15259 unsigned ScalarBits =
Op.getValueSizeInBits();
15261 if (ScalarBits < EltBits) {
15264 !Subtarget.
is64Bit() &&
"Unexpected splat");
15266 SupportsSExt =
true;
15270 SupportsZExt =
true;
15272 EnforceOneUse =
false;
15276 unsigned NarrowSize = EltBits / 2;
15279 if (NarrowSize < 8)
15283 SupportsSExt =
true;
15287 SupportsZExt =
true;
15289 EnforceOneUse =
false;
15292 bool isSupportedFPExtend(
SDNode *Root,
MVT NarrowEltVT,
15299 if (NarrowEltVT == MVT::bf16 && (!Subtarget.hasStdExtZvfbfwma() ||
15309 SupportsZExt =
false;
15310 SupportsSExt =
false;
15311 SupportsFPExt =
false;
15312 EnforceOneUse =
true;
15313 unsigned Opc = OrigOperand.
getOpcode();
15335 SupportsZExt =
true;
15338 SupportsSExt =
true;
15343 if (!isSupportedFPExtend(Root, NarrowEltVT, Subtarget))
15345 SupportsFPExt =
true;
15350 fillUpExtensionSupportForSplat(Root, DAG, Subtarget);
15362 if (!isSupportedFPExtend(Root,
Op.getOperand(0).getSimpleValueType(),
15367 unsigned ScalarBits =
Op.getOperand(0).getValueSizeInBits();
15368 if (NarrowSize != ScalarBits)
15371 SupportsFPExt =
true;
15380 static bool isSupportedRoot(
const SDNode *Root,
15409 Subtarget.hasStdExtZvbb();
15411 return Subtarget.hasStdExtZvbb();
15425 assert(isSupportedRoot(Root, Subtarget) &&
15426 "Trying to build an helper with an "
15427 "unsupported root");
15428 assert(OperandIdx < 2 &&
"Requesting something else than LHS or RHS");
15444 if (OperandIdx == 1) {
15453 EnforceOneUse =
false;
15458 fillUpExtensionSupport(Root, DAG, Subtarget);
15464 static std::pair<SDValue, SDValue>
15467 assert(isSupportedRoot(Root, Subtarget) &&
"Unexpected root");
15486 switch (
N->getOpcode()) {
15528struct CombineResult {
15530 unsigned TargetOpcode;
15532 std::optional<ExtKind> LHSExt;
15533 std::optional<ExtKind> RHSExt;
15537 NodeExtensionHelper
LHS;
15539 NodeExtensionHelper
RHS;
15541 CombineResult(
unsigned TargetOpcode,
SDNode *Root,
15542 const NodeExtensionHelper &
LHS, std::optional<ExtKind> LHSExt,
15543 const NodeExtensionHelper &
RHS, std::optional<ExtKind> RHSExt)
15544 : TargetOpcode(TargetOpcode), LHSExt(LHSExt), RHSExt(RHSExt), Root(Root),
15553 std::tie(Mask, VL) =
15554 NodeExtensionHelper::getMaskAndVL(Root, DAG, Subtarget);
15568 LHS.getOrCreateExtendedOp(Root, DAG, Subtarget, LHSExt),
15569 RHS.getOrCreateExtendedOp(Root, DAG, Subtarget, RHSExt),
15570 Passthru, Mask, VL);
15584static std::optional<CombineResult>
15585canFoldToVWWithSameExtensionImpl(
SDNode *Root,
const NodeExtensionHelper &LHS,
15586 const NodeExtensionHelper &RHS,
15589 if ((AllowExtMask & ExtKind::ZExt) &&
LHS.SupportsZExt &&
RHS.SupportsZExt)
15590 return CombineResult(NodeExtensionHelper::getZExtOpcode(Root->
getOpcode()),
15591 Root, LHS, {ExtKind::ZExt}, RHS,
15593 if ((AllowExtMask & ExtKind::SExt) &&
LHS.SupportsSExt &&
RHS.SupportsSExt)
15594 return CombineResult(NodeExtensionHelper::getSExtOpcode(Root->
getOpcode()),
15595 Root, LHS, {ExtKind::SExt}, RHS,
15597 if ((AllowExtMask & ExtKind::FPExt) &&
LHS.SupportsFPExt &&
RHS.SupportsFPExt)
15598 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
15599 Root, LHS, {ExtKind::FPExt}, RHS,
15601 return std::nullopt;
15610static std::optional<CombineResult>
15611canFoldToVWWithSameExtension(
SDNode *Root,
const NodeExtensionHelper &LHS,
15614 return canFoldToVWWithSameExtensionImpl(
15615 Root, LHS, RHS, ExtKind::ZExt | ExtKind::SExt | ExtKind::FPExt, DAG,
15623static std::optional<CombineResult>
15624canFoldToVW_W(
SDNode *Root,
const NodeExtensionHelper &LHS,
15627 if (
RHS.SupportsFPExt)
15628 return CombineResult(
15629 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::FPExt),
15630 Root, LHS, std::nullopt, RHS, {ExtKind::FPExt});
15637 return CombineResult(
15638 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::ZExt), Root,
15639 LHS, std::nullopt, RHS, {ExtKind::ZExt});
15641 return CombineResult(
15642 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::SExt), Root,
15643 LHS, std::nullopt, RHS, {ExtKind::SExt});
15644 return std::nullopt;
15651static std::optional<CombineResult>
15652canFoldToVWWithSEXT(
SDNode *Root,
const NodeExtensionHelper &LHS,
15655 return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::SExt, DAG,
15663static std::optional<CombineResult>
15664canFoldToVWWithZEXT(
SDNode *Root,
const NodeExtensionHelper &LHS,
15667 return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::ZExt, DAG,
15675static std::optional<CombineResult>
15676canFoldToVWWithFPEXT(
SDNode *Root,
const NodeExtensionHelper &LHS,
15679 return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::FPExt, DAG,
15687static std::optional<CombineResult>
15688canFoldToVW_SU(
SDNode *Root,
const NodeExtensionHelper &LHS,
15692 if (!
LHS.SupportsSExt || !
RHS.SupportsZExt)
15693 return std::nullopt;
15694 return CombineResult(NodeExtensionHelper::getSUOpcode(Root->
getOpcode()),
15695 Root, LHS, {ExtKind::SExt}, RHS,
15700NodeExtensionHelper::getSupportedFoldings(
const SDNode *Root) {
15711 Strategies.
push_back(canFoldToVWWithSameExtension);
15720 Strategies.
push_back(canFoldToVWWithSameExtension);
15725 Strategies.
push_back(canFoldToVWWithSameExtension);
15732 Strategies.
push_back(canFoldToVWWithZEXT);
15737 Strategies.
push_back(canFoldToVWWithSEXT);
15742 Strategies.
push_back(canFoldToVWWithZEXT);
15747 Strategies.
push_back(canFoldToVWWithFPEXT);
15776 if (!NodeExtensionHelper::isSupportedRoot(
N, Subtarget))
15782 Inserted.insert(
N);
15785 while (!Worklist.
empty()) {
15788 NodeExtensionHelper
LHS(Root, 0, DAG, Subtarget);
15789 NodeExtensionHelper
RHS(Root, 1, DAG, Subtarget);
15790 auto AppendUsersIfNeeded = [&Worklist, &Subtarget,
15791 &Inserted](
const NodeExtensionHelper &
Op) {
15792 if (
Op.needToPromoteOtherUsers()) {
15795 if (!NodeExtensionHelper::isSupportedRoot(TheUser, Subtarget))
15800 if (Inserted.insert(TheUser).second)
15813 NodeExtensionHelper::getSupportedFoldings(Root);
15815 assert(!FoldingStrategies.
empty() &&
"Nothing to be folded");
15816 bool Matched =
false;
15817 for (
int Attempt = 0;
15818 (Attempt != 1 + NodeExtensionHelper::isCommutative(Root)) && !Matched;
15821 for (NodeExtensionHelper::CombineToTry FoldingStrategy :
15822 FoldingStrategies) {
15823 std::optional<CombineResult> Res =
15824 FoldingStrategy(Root,
LHS,
RHS, DAG, Subtarget);
15831 if (Res->LHSExt.has_value())
15832 if (!AppendUsersIfNeeded(
LHS))
15834 if (Res->RHSExt.has_value())
15835 if (!AppendUsersIfNeeded(
RHS))
15847 SDValue InputRootReplacement;
15854 for (CombineResult Res : CombinesToApply) {
15855 SDValue NewValue = Res.materialize(DAG, Subtarget);
15856 if (!InputRootReplacement) {
15858 "First element is expected to be the current node");
15859 InputRootReplacement = NewValue;
15864 for (std::pair<SDValue, SDValue> OldNewValues : ValuesToReplace) {
15868 return InputRootReplacement;
15875 unsigned Opc =
N->getOpcode();
15880 SDValue MergeOp =
N->getOperand(1);
15881 unsigned MergeOpc = MergeOp.
getOpcode();
15892 SDValue Passthru =
N->getOperand(2);
15906 Z = Z.getOperand(1);
15912 {Y, X, Y, MergeOp->getOperand(0), N->getOperand(4)},
15919 [[maybe_unused]]
unsigned Opc =
N->getOpcode();
15948 EVT NewMemVT = (MemVT == MVT::i32) ? MVT::i64 : MVT::i128;
15954 auto Ext = cast<LoadSDNode>(LSNode1)->getExtensionType();
15956 if (MemVT == MVT::i32)
15962 Opcode,
SDLoc(LSNode1), DAG.
getVTList({XLenVT, XLenVT, MVT::Other}),
15997 if (!Subtarget.hasVendorXTHeadMemPair())
16009 auto ExtractBaseAndOffset = [](
SDValue Ptr) -> std::pair<SDValue, uint64_t> {
16011 if (
auto *C1 = dyn_cast<ConstantSDNode>(
Ptr->getOperand(1)))
16012 return {
Ptr->getOperand(0), C1->getZExtValue()};
16016 auto [Base1, Offset1] = ExtractBaseAndOffset(LSNode1->
getOperand(OpNum));
16037 auto [Base2, Offset2] = ExtractBaseAndOffset(LSNode2->
getOperand(OpNum));
16040 if (Base1 != Base2)
16044 bool Valid =
false;
16045 if (MemVT == MVT::i32) {
16047 if ((Offset1 + 4 == Offset2) && isShiftedUInt<2, 3>(Offset1))
16049 }
else if (MemVT == MVT::i64) {
16051 if ((Offset1 + 8 == Offset2) && isShiftedUInt<2, 4>(Offset1))
16085 if (Src->isStrictFPOpcode())
16093 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
16103 EVT VT =
N->getValueType(0);
16106 MVT SrcVT = Src.getSimpleValueType();
16107 MVT SrcContainerVT = SrcVT;
16109 SDValue XVal = Src.getOperand(0);
16136 FpToInt = DAG.
getNode(Opc,
DL, ContainerVT, XVal, Mask, VL);
16140 FpToInt = DAG.
getNode(Opc,
DL, ContainerVT, XVal, Mask,
16153 if (VT != MVT::i32 && VT != XLenVT)
16183 EVT DstVT =
N->getValueType(0);
16184 if (DstVT != XLenVT)
16190 if (Src->isStrictFPOpcode())
16198 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
16201 EVT SatVT = cast<VTSDNode>(
N->getOperand(1))->getVT();
16210 if (SatVT == DstVT)
16212 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
16218 Src = Src.getOperand(0);
16239 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected extension");
16245 EVT VT =
N->getValueType(0);
16260 auto *VPLoad = dyn_cast<VPLoadSDNode>(
N->getOperand(0));
16264 EVT LoadVT = VPLoad->getValueType(0);
16268 N->getOperand(2) != VPLoad->getVectorLength() ||
16269 !
N->getOperand(0).hasOneUse())
16276 SDValue LoadMask = VPLoad->getMask();
16281 if (LoadMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
16283 LoadMask.
getOperand(2) != VPLoad->getVectorLength())
16291 SDValue NumElem = VPLoad->getVectorLength();
16292 uint64_t ElemWidthByte = VPLoad->getValueType(0).getScalarSizeInBits() / 8;
16304 PtrInfo, VPLoad->getMemOperand()->getFlags(),
16308 LoadVT,
DL, VPLoad->getChain(),
Base, Stride, LoadMask,
16309 VPLoad->getVectorLength(), MMO, VPLoad->isExpandingLoad());
16321 auto *VPStore = cast<VPStoreSDNode>(
N);
16323 if (VPStore->getValue().getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE)
16326 SDValue VPReverse = VPStore->getValue();
16332 VPStore->getVectorLength() != VPReverse.
getOperand(2) ||
16336 SDValue StoreMask = VPStore->getMask();
16341 if (StoreMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
16343 StoreMask.
getOperand(2) != VPStore->getVectorLength())
16351 SDValue NumElem = VPStore->getVectorLength();
16365 PtrInfo, VPStore->getMemOperand()->getFlags(),
16370 VPStore->getOffset(), Stride, StoreMask, VPStore->getVectorLength(),
16371 VPStore->getMemoryVT(), MMO, VPStore->getAddressingMode(),
16372 VPStore->isTruncatingStore(), VPStore->isCompressingStore());
16384 EVT VT =
N->getValueType(0);
16396 if (In.getOpcode() != ISD::VP_SRL || In.getOperand(2) != Mask ||
16397 In.getOperand(3) != VL)
16406 if (
LHS.getOpcode() != ISD::VP_ADD ||
LHS.getOperand(2) != Mask ||
16407 LHS.getOperand(3) != VL)
16414 if (V.getOpcode() != ISD::VP_ADD || V.getOperand(2) != Mask ||
16415 V.getOperand(3) != VL)
16427 if (!FindAdd(LHS0, LHS1) && !FindAdd(LHS1, LHS0))
16441 if (
Op.getOpcode() != ISD::VP_ZERO_EXTEND ||
Op.getOperand(1) != Mask ||
16442 Op.getOperand(2) != VL)
16452 Operands[0].getOperand(0), Mask, VL);
16454 Operands[1].getOperand(0), Mask, VL);
16459 {NewOp0, NewOp1, DAG.
getUNDEF(VT), Mask, VL});
16508 unsigned Offset = IsStrict ? 1 : 0;
16515 auto invertIfNegative = [&Mask, &VL](
SDValue &V) {
16517 V.getOperand(2) == VL) {
16519 V = V.getOperand(0);
16526 bool NegA = invertIfNegative(
A);
16527 bool NegB = invertIfNegative(
B);
16528 bool NegC = invertIfNegative(
C);
16531 if (!NegA && !NegB && !NegC)
16537 {N->getOperand(0), A, B, C, Mask, VL});
16561 EVT VT =
N->getValueType(0);
16566 if (!isa<ConstantSDNode>(
N->getOperand(1)))
16568 uint64_t ShAmt =
N->getConstantOperandVal(1);
16576 cast<VTSDNode>(N0.
getOperand(1))->getVT().getSizeInBits();
16581 if (LShAmt < ExtSize) {
16594 if (ShAmt > 32 || VT != MVT::i64)
16610 AddC = dyn_cast<ConstantSDNode>(N0.
getOperand(IsAdd ? 1 : 0));
16623 !isa<ConstantSDNode>(U->getOperand(1)) ||
16624 U->getConstantOperandVal(1) > 32)
16679 if (!
Cond.hasOneUse())
16698 EVT VT =
Cond.getValueType();
16743 LHS =
LHS.getOperand(0);
16753 LHS.getOperand(0).getValueType() == Subtarget.
getXLenVT()) {
16757 CCVal = cast<CondCodeSDNode>(
LHS.getOperand(2))->get();
16761 RHS =
LHS.getOperand(1);
16762 LHS =
LHS.getOperand(0);
16771 RHS =
LHS.getOperand(1);
16772 LHS =
LHS.getOperand(0);
16788 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
16829 bool Commutative =
true;
16830 unsigned Opc = TrueVal.getOpcode();
16838 Commutative =
false;
16846 if (!TrueVal.hasOneUse() || isa<ConstantSDNode>(FalseVal))
16850 if (FalseVal == TrueVal.getOperand(0))
16852 else if (Commutative && FalseVal == TrueVal.getOperand(1))
16857 EVT VT =
N->getValueType(0);
16859 SDValue OtherOp = TrueVal.getOperand(1 - OpToFold);
16865 assert(IdentityOperand &&
"No identity operand!");
16870 DAG.
getSelect(
DL, OtherOpVT,
N->getOperand(0), OtherOp, IdentityOperand);
16871 return DAG.
getNode(TrueVal.getOpcode(),
DL, VT, FalseVal, NewSel);
16892 CountZeroes =
N->getOperand(2);
16893 ValOnZero =
N->getOperand(1);
16895 CountZeroes =
N->getOperand(1);
16896 ValOnZero =
N->getOperand(2);
16915 if (
Cond->getOperand(0) != CountZeroesArgument)
16931 CountZeroes, BitWidthMinusOne);
16941 EVT VT =
N->getValueType(0);
16942 EVT CondVT =
Cond.getValueType();
16950 (Subtarget.hasStdExtZicond() || Subtarget.hasVendorXVentanaCondOps())) {
16956 const APInt &MaskVal =
LHS.getConstantOperandAPInt(1);
16967 if (!TrueVal.hasOneUse() || !FalseVal.hasOneUse())
16971 if (TrueVal.getOpcode() ==
ISD::SUB && FalseVal.getOpcode() ==
ISD::ADD) {
16979 SDValue A = FalseVal.getOperand(0);
16980 SDValue B = FalseVal.getOperand(1);
16982 return ((TrueVal.getOperand(0) ==
A && TrueVal.getOperand(1) ==
B) ||
16983 (TrueVal.getOperand(1) ==
A && TrueVal.getOperand(0) ==
B));
16991 EVT VT =
N->getValueType(0);
16993 SDValue TrueVal =
N->getOperand(1);
16994 SDValue FalseVal =
N->getOperand(2);
17000 SDValue Sub = SwapCC ? TrueVal : FalseVal;
17024 SDValue TrueVal =
N->getOperand(1);
17025 SDValue FalseVal =
N->getOperand(2);
17040 EVT VT =
N->getValueType(0);
17047 const unsigned Opcode =
N->op_begin()->getNode()->getOpcode();
17062 if (
Op.isUndef()) {
17075 if (
Op.getOpcode() != Opcode || !
Op.hasOneUse())
17079 if (!isa<ConstantSDNode>(
Op.getOperand(1)) &&
17080 !isa<ConstantFPSDNode>(
Op.getOperand(1)))
17084 if (
Op.getOperand(0).getValueType() !=
Op.getOperand(1).getValueType())
17112 const unsigned InVecOpcode = InVec->
getOpcode();
17122 if (!isa<ConstantSDNode>(InValRHS) && !isa<ConstantFPSDNode>(InValRHS))
17129 InVecLHS, InValLHS, EltNo);
17131 InVecRHS, InValRHS, EltNo);
17140 auto *IndexC = dyn_cast<ConstantSDNode>(EltNo);
17143 unsigned Elt = IndexC->getZExtValue();
17151 unsigned ConcatOpIdx = Elt / ConcatNumElts;
17154 ConcatOp, InVal, NewIdx);
17158 ConcatOps[ConcatOpIdx] = ConcatOp;
17170 EVT VT =
N->getValueType(0);
17180 auto *BaseLd = dyn_cast<LoadSDNode>(
N->getOperand(0));
17182 !
SDValue(BaseLd, 0).hasOneUse())
17185 EVT BaseLdVT = BaseLd->getValueType(0);
17192 auto *Ld = dyn_cast<LoadSDNode>(
Op);
17193 if (!Ld || !Ld->isSimple() || !
Op.hasOneUse() ||
17195 Ld->getValueType(0) != BaseLdVT)
17204 using PtrDiff = std::pair<std::variant<int64_t, SDValue>,
bool>;
17206 LoadSDNode *Ld2) -> std::optional<PtrDiff> {
17211 if (BIO1.equalBaseIndex(BIO2, DAG))
17216 SDValue P2 = Ld2->getBasePtr();
17219 if (P1.getOpcode() ==
ISD::ADD && P1.getOperand(0) == P2)
17220 return {{P1.getOperand(1),
true}};
17222 return std::nullopt;
17226 auto BaseDiff = GetPtrDiff(Lds[0], Lds[1]);
17231 for (
auto *It = Lds.
begin() + 1; It != Lds.
end() - 1; It++)
17232 if (GetPtrDiff(*It, *std::next(It)) != BaseDiff)
17240 unsigned WideScalarBitWidth =
17253 auto [StrideVariant, MustNegateStride] = *BaseDiff;
17255 std::holds_alternative<SDValue>(StrideVariant)
17256 ? std::get<SDValue>(StrideVariant)
17259 if (MustNegateStride)
17267 if (
auto *ConstStride = dyn_cast<ConstantSDNode>(Stride);
17268 ConstStride && ConstStride->getSExtValue() >= 0)
17272 ConstStride->getSExtValue() * (
N->getNumOperands() - 1);
17278 BaseLd->getPointerInfo(), BaseLd->getMemOperand()->getFlags(), MemSize,
17282 WideVecVT,
DL, BaseLd->getChain(), BaseLd->getBasePtr(), Stride,
17296 EVT VT =
N->getValueType(0);
17308 SDValue Sub = SwapCC ? V1 : V2;
17313 for (
int MaskIndex : Mask) {
17314 bool SelectMaskVal = (MaskIndex < (int)NumElts);
17317 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
17355 if (
N->getValueType(0).isFixedLengthVector())
17358 SDValue Addend =
N->getOperand(0);
17362 SDValue AddPassthruOp =
N->getOperand(2);
17363 if (!AddPassthruOp.
isUndef())
17367 auto IsVWMulOpc = [](
unsigned Opc) {
17386 if (!MulPassthruOp.
isUndef())
17396 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
17397 }(
N, DAG, Subtarget);
17402 if (AddMask != MulMask || AddVL != MulVL)
17407 "Unexpected opcode after VWMACC_VL");
17409 "Unexpected opcode after VWMACC_VL!");
17411 "Unexpected opcode after VWMUL_VL!");
17413 "Unexpected opcode after VWMUL_VL!");
17416 EVT VT =
N->getValueType(0);
17432 const EVT IndexVT = Index.getValueType();
17436 if (!isIndexTypeSigned(IndexType))
17468 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
17471 if (Index->getOperand(i)->isUndef())
17473 uint64_t C = Index->getConstantOperandVal(i);
17474 if (
C % ElementSize != 0)
17476 C =
C / ElementSize;
17480 ActiveLanes.
set(
C);
17482 return ActiveLanes.
all();
17500 if (NumElems % 2 != 0)
17504 const unsigned WiderElementSize = ElementSize * 2;
17505 if (WiderElementSize > ST.getELen()/8)
17508 if (!ST.enableUnalignedVectorMem() && BaseAlign < WiderElementSize)
17511 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
17514 if (Index->getOperand(i)->isUndef())
17518 uint64_t C = Index->getConstantOperandVal(i);
17520 if (
C % WiderElementSize != 0)
17525 if (
C !=
Last + ElementSize)
17542 (isa<RegisterSDNode>(VL) &&
17543 cast<RegisterSDNode>(VL)->getReg() == RISCV::X0);
17545 Mask.getOperand(0) != VL)
17548 auto IsTruncNode = [&](
SDValue V) {
17550 V.getOperand(1) == Mask && V.getOperand(2) == VL;
17557 while (IsTruncNode(
Op)) {
17558 if (!
Op.hasOneUse())
17560 Op =
Op.getOperand(0);
17595 MVT VT =
N->getSimpleValueType(0);
17600 auto MatchMinMax = [&VL, &Mask](
SDValue V,
unsigned Opc,
unsigned OpcVL,
17602 if (V.getOpcode() != Opc &&
17603 !(V.getOpcode() == OpcVL && V.getOperand(2).isUndef() &&
17604 V.getOperand(3) == Mask && V.getOperand(4) == VL))
17612 Op.getOperand(1).getValueType().isFixedLengthVector() &&
17614 Op.getOperand(1).getOperand(0).getValueType() ==
Op.getValueType() &&
17616 Op =
Op.getOperand(1).getOperand(0);
17619 return V.getOperand(0);
17622 Op.getOperand(2) == VL) {
17623 if (
auto *Op1 = dyn_cast<ConstantSDNode>(
Op.getOperand(1))) {
17625 Op1->getAPIntValue().sextOrTrunc(
Op.getScalarValueSizeInBits());
17626 return V.getOperand(0);
17635 auto DetectUSatPattern = [&](
SDValue V) {
17660 V.getOperand(1), DAG.
getUNDEF(V.getValueType()),
17666 auto DetectSSatPattern = [&](
SDValue V) {
17668 unsigned NumSrcBits = V.getScalarValueSizeInBits();
17676 if (HiC == SignedMax && LoC == SignedMin)
17682 if (HiC == SignedMax && LoC == SignedMin)
17692 Src.getOperand(1) == Mask && Src.getOperand(2) == VL &&
17694 Src = Src.getOperand(0);
17698 if ((Val = DetectUSatPattern(Src)))
17700 else if ((Val = DetectSSatPattern(Src)))
17710 Val = DAG.
getNode(ClipOpc,
DL, ValVT, Val, Mask, VL);
17711 }
while (ValVT != VT);
17725 EVT VT =
N->getValueType(0);
17733 Src = Src.getOperand(0);
17738 Src = Src.getOperand(0);
17739 EVT SrcEVT = Src.getValueType();
17771 auto SimplifyDemandedLowBitsHelper = [&](
unsigned OpNo,
unsigned LowBits) {
17782 switch (
N->getOpcode()) {
17802 APInt V =
C->getValueAPF().bitcastToAPInt();
17837 if (SimplifyDemandedLowBitsHelper(0, 32) ||
17838 SimplifyDemandedLowBitsHelper(1, 5))
17846 if (SimplifyDemandedLowBitsHelper(0, 32))
17863 MVT VT =
N->getSimpleValueType(0);
17866 if (
auto *CFP = dyn_cast<ConstantFPSDNode>(Op0)) {
17879 "Unexpected value type!");
17884 cast<LoadSDNode>(Op0)->isSimple()) {
17886 auto *LN0 = cast<LoadSDNode>(Op0);
17889 LN0->getBasePtr(), IVT, LN0->getMemOperand());
17913 EVT VT =
N->getValueType(0);
17966 if (!
C || !
C->getValueAPF().isExactlyValue(+1.0))
17968 EVT VT =
N->getValueType(0);
17997 if (
N->getValueType(0) == MVT::i64 && Subtarget.
is64Bit()) {
18002 Src.getOperand(0));
18007 Src.getOperand(0), Src.getOperand(1));
18019 case ISD::VP_TRUNCATE:
18032 unsigned Opc =
N->getOpcode();
18047 return DAG.
getNode(InvOpc,
SDLoc(
N),
N->getValueType(0), Val, NewCond);
18057 N->getValueType(0), Val,
Cond.getOperand(0));
18068 SDValue FalseV =
N->getOperand(4);
18070 EVT VT =
N->getValueType(0);
18073 if (TrueV == FalseV)
18078 if (!Subtarget.hasShortForwardBranchOpt() && isa<ConstantSDNode>(TrueV) &&
18084 int64_t TrueSImm = cast<ConstantSDNode>(TrueV)->getSExtValue();
18085 int64_t FalseSImm = cast<ConstantSDNode>(FalseV)->getSExtValue();
18088 if (isInt<12>(TrueSImm) && isInt<12>(FalseSImm) &&
18089 isInt<12>(TrueSImm - FalseSImm)) {
18105 {LHS, RHS, CC, TrueV, FalseV});
18172 N->getOperand(0),
LHS,
RHS,
CC,
N->getOperand(4));
18185 EVT VT =
N->getValueType(0);
18209 const auto *MGN = cast<MaskedGatherSDNode>(
N);
18210 const EVT VT =
N->getValueType(0);
18211 SDValue Index = MGN->getIndex();
18212 SDValue ScaleOp = MGN->getScale();
18214 assert(!MGN->isIndexScaled() &&
18215 "Scaled gather/scatter should not be formed");
18220 N->getVTList(), MGN->getMemoryVT(),
DL,
18221 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
18222 MGN->getBasePtr(), Index, ScaleOp},
18223 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
18227 N->getVTList(), MGN->getMemoryVT(),
DL,
18228 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
18229 MGN->getBasePtr(), Index, ScaleOp},
18230 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
18236 if (std::optional<VIDSequence> SimpleVID =
18238 SimpleVID && SimpleVID->StepDenominator == 1) {
18239 const int64_t StepNumerator = SimpleVID->StepNumerator;
18240 const int64_t Addend = SimpleVID->Addend;
18247 assert(MGN->getBasePtr()->getValueType(0) == PtrVT);
18255 VT,
DL, MGN->getChain(), BasePtr,
18257 EVL, MGN->getMemOperand());
18259 StridedLoad, MGN->getPassThru(), EVL);
18269 MGN->getBasePtr(), DAG.
getUNDEF(XLenVT),
18271 MGN->getMemoryVT(), MGN->getMemOperand(),
18280 MGN->getMemOperand()->getBaseAlign(), Subtarget)) {
18282 for (
unsigned i = 0; i < Index->getNumOperands(); i += 2)
18283 NewIndices.
push_back(Index.getOperand(i));
18284 EVT IndexVT = Index.getValueType()
18285 .getHalfNumVectorElementsVT(*DAG.
getContext());
18291 assert(EltCnt.isKnownEven() &&
"Splitting vector, but not in half!");
18293 EltCnt.divideCoefficientBy(2));
18296 EltCnt.divideCoefficientBy(2));
18301 {MGN->getChain(), Passthru, Mask, MGN->getBasePtr(),
18310 const auto *MSN = cast<MaskedScatterSDNode>(
N);
18311 SDValue Index = MSN->getIndex();
18312 SDValue ScaleOp = MSN->getScale();
18314 assert(!MSN->isIndexScaled() &&
18315 "Scaled gather/scatter should not be formed");
18320 N->getVTList(), MSN->getMemoryVT(),
DL,
18321 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
18323 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
18327 N->getVTList(), MSN->getMemoryVT(),
DL,
18328 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
18330 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
18332 EVT VT = MSN->getValue()->getValueType(0);
18334 if (!MSN->isTruncatingStore() &&
18338 return DAG.
getMaskedStore(MSN->getChain(),
DL, Shuffle, MSN->getBasePtr(),
18339 DAG.
getUNDEF(XLenVT), MSN->getMask(),
18340 MSN->getMemoryVT(), MSN->getMemOperand(),
18345 case ISD::VP_GATHER: {
18346 const auto *VPGN = cast<VPGatherSDNode>(
N);
18347 SDValue Index = VPGN->getIndex();
18348 SDValue ScaleOp = VPGN->getScale();
18350 assert(!VPGN->isIndexScaled() &&
18351 "Scaled gather/scatter should not be formed");
18356 {VPGN->getChain(), VPGN->getBasePtr(), Index,
18357 ScaleOp, VPGN->getMask(),
18358 VPGN->getVectorLength()},
18359 VPGN->getMemOperand(), IndexType);
18363 {VPGN->getChain(), VPGN->getBasePtr(), Index,
18364 ScaleOp, VPGN->getMask(),
18365 VPGN->getVectorLength()},
18366 VPGN->getMemOperand(), IndexType);
18370 case ISD::VP_SCATTER: {
18371 const auto *VPSN = cast<VPScatterSDNode>(
N);
18372 SDValue Index = VPSN->getIndex();
18373 SDValue ScaleOp = VPSN->getScale();
18375 assert(!VPSN->isIndexScaled() &&
18376 "Scaled gather/scatter should not be formed");
18381 {VPSN->getChain(), VPSN->getValue(),
18382 VPSN->getBasePtr(), Index, ScaleOp,
18383 VPSN->getMask(), VPSN->getVectorLength()},
18384 VPSN->getMemOperand(), IndexType);
18388 {VPSN->getChain(), VPSN->getValue(),
18389 VPSN->getBasePtr(), Index, ScaleOp,
18390 VPSN->getMask(), VPSN->getVectorLength()},
18391 VPSN->getMemOperand(), IndexType);
18405 EVT VT =
N->getValueType(0);
18408 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt,
18409 N->getOperand(2),
N->getOperand(3),
N->getOperand(4));
18427 EVT VT =
N->getValueType(0);
18431 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt);
18471 auto *Store = cast<StoreSDNode>(
N);
18472 SDValue Chain = Store->getChain();
18473 EVT MemVT = Store->getMemoryVT();
18474 SDValue Val = Store->getValue();
18477 bool IsScalarizable =
18479 Store->isSimple() &&
18509 NewVT, *Store->getMemOperand())) {
18511 return DAG.
getStore(Chain,
DL, NewV, Store->getBasePtr(),
18512 Store->getPointerInfo(), Store->getOriginalAlign(),
18513 Store->getMemOperand()->getFlags());
18521 if (
auto *L = dyn_cast<LoadSDNode>(Val);
18523 L->hasNUsesOfValue(1, 0) && L->hasNUsesOfValue(1, 1) &&
18525 L->getMemoryVT() == MemVT) {
18528 NewVT, *Store->getMemOperand()) &&
18530 NewVT, *L->getMemOperand())) {
18532 L->getPointerInfo(), L->getOriginalAlign(),
18533 L->getMemOperand()->getFlags());
18534 return DAG.
getStore(Chain,
DL, NewL, Store->getBasePtr(),
18535 Store->getPointerInfo(), Store->getOriginalAlign(),
18536 Store->getMemOperand()->getFlags());
18548 MVT VecVT = Src.getSimpleValueType();
18555 Store->getChain(),
DL, Src, Store->getBasePtr(), Store->getOffset(),
18558 Store->getMemOperand(), Store->getAddressingMode(),
18559 Store->isTruncatingStore(),
false);
18566 EVT VT =
N->getValueType(0);
18592 const MVT VT =
N->getSimpleValueType(0);
18593 SDValue Passthru =
N->getOperand(0);
18594 SDValue Scalar =
N->getOperand(1);
18603 const MVT VT =
N->getSimpleValueType(0);
18604 SDValue Passthru =
N->getOperand(0);
18605 SDValue Scalar =
N->getOperand(1);
18610 unsigned ScalarSize = Scalar.getValueSizeInBits();
18612 if (ScalarSize > EltWidth && Passthru.
isUndef())
18613 if (SimplifyDemandedLowBitsHelper(1, EltWidth))
18620 (!Const || Const->isZero() ||
18621 !Const->getAPIntValue().sextOrTrunc(EltWidth).isSignedIntN(5)))
18631 if (
N->getOperand(0).isUndef() &&
18634 Src.getOperand(0).getValueType().isScalableVector()) {
18635 EVT VT =
N->getValueType(0);
18636 EVT SrcVT = Src.getOperand(0).getValueType();
18640 return Src.getOperand(0);
18646 const MVT VT =
N->getSimpleValueType(0);
18647 SDValue Passthru =
N->getOperand(0);
18648 SDValue Scalar =
N->getOperand(1);
18652 Scalar.getOperand(0).getValueType() ==
N->getValueType(0))
18653 return Scalar.getOperand(0);
18662 DAG.
getNode(
N->getOpcode(),
DL, M1VT, M1Passthru, Scalar, VL);
18672 Const && !Const->isZero() && isInt<5>(Const->getSExtValue()) &&
18680 MVT VecVT =
N->getOperand(0).getSimpleValueType();
18682 if (M1VT.
bitsLT(VecVT)) {
18693 unsigned IntNo =
N->getConstantOperandVal(IntOpNo);
18698 case Intrinsic::riscv_vcpop:
18699 case Intrinsic::riscv_vcpop_mask:
18700 case Intrinsic::riscv_vfirst:
18701 case Intrinsic::riscv_vfirst_mask: {
18703 if (IntNo == Intrinsic::riscv_vcpop_mask ||
18704 IntNo == Intrinsic::riscv_vfirst_mask)
18705 VL =
N->getOperand(3);
18710 EVT VT =
N->getValueType(0);
18711 if (IntNo == Intrinsic::riscv_vfirst ||
18712 IntNo == Intrinsic::riscv_vfirst_mask)
18718 case ISD::EXPERIMENTAL_VP_REVERSE:
18720 case ISD::VP_STORE:
18725 EVT VT =
N->getValueType(0);
18736 for (
unsigned i = 0; i < NF; ++i)
18743 if ((SrcVT == MVT::v1i1 || SrcVT == MVT::v2i1 || SrcVT == MVT::v4i1) &&
18766 EVT XVT,
unsigned KeptBits)
const {
18771 if (XVT != MVT::i32 && XVT != MVT::i64)
18775 if (KeptBits == 32 || KeptBits == 64)
18779 return Subtarget.hasStdExtZbb() &&
18780 ((KeptBits == 8 && XVT == MVT::i64 && !Subtarget.
is64Bit()) ||
18788 "Expected shift op");
18806 if (!isa<StoreSDNode>(
Use) && !isa<LoadSDNode>(
Use))
18815 return isUsedByLdSt(N0.
getNode(),
N);
18817 auto *C1 = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
18818 auto *C2 = dyn_cast<ConstantSDNode>(
N->getOperand(1));
18821 if (Subtarget.hasStdExtZba() && C2 && C2->getZExtValue() >= 1 &&
18822 C2->getZExtValue() <= 3 &&
N->hasOneUse() &&
18823 N->user_begin()->getOpcode() ==
ISD::ADD &&
18824 !isUsedByLdSt(*
N->user_begin(),
nullptr) &&
18825 !isa<ConstantSDNode>(
N->user_begin()->getOperand(1)))
18829 const APInt &C1Int = C1->getAPIntValue();
18830 APInt ShiftedC1Int = C1Int << C2->getAPIntValue();
18856 if (C1Cost < ShiftedC1Cost)
18879 EVT VT =
Op.getValueType();
18883 unsigned Opcode =
Op.getOpcode();
18891 const APInt &Mask =
C->getAPIntValue();
18900 auto IsLegalMask = [ShrunkMask, ExpandedMask](
const APInt &Mask) ->
bool {
18901 return ShrunkMask.
isSubsetOf(Mask) && Mask.isSubsetOf(ExpandedMask);
18903 auto UseMask = [Mask,
Op, &TLO](
const APInt &NewMask) ->
bool {
18904 if (NewMask == Mask)
18909 Op.getOperand(0), NewC);
18922 APInt NewMask =
APInt(Mask.getBitWidth(), 0xffff);
18923 if (IsLegalMask(NewMask))
18924 return UseMask(NewMask);
18927 if (VT == MVT::i64) {
18929 if (IsLegalMask(NewMask))
18930 return UseMask(NewMask);
18945 APInt NewMask = ShrunkMask;
18946 if (MinSignedBits <= 12)
18948 else if (!
C->isOpaque() && MinSignedBits <= 32 && !ShrunkMask.
isSignedIntN(32))
18954 assert(IsLegalMask(NewMask));
18955 return UseMask(NewMask);
18959 static const uint64_t GREVMasks[] = {
18960 0x5555555555555555ULL, 0x3333333333333333ULL, 0x0F0F0F0F0F0F0F0FULL,
18961 0x00FF00FF00FF00FFULL, 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL};
18963 for (
unsigned Stage = 0; Stage != 6; ++Stage) {
18964 unsigned Shift = 1 << Stage;
18965 if (ShAmt & Shift) {
18967 uint64_t Res = ((x & Mask) << Shift) | ((x >> Shift) & Mask);
18979 const APInt &DemandedElts,
18981 unsigned Depth)
const {
18983 unsigned Opc =
Op.getOpcode();
18988 "Should use MaskedValueIsZero if you don't know whether Op"
18989 " is a target node!");
19072 assert(MinVLenB > 0 &&
"READ_VLENB without vector extension enabled?");
19075 if (MaxVLenB == MinVLenB)
19092 case Intrinsic::riscv_vsetvli:
19093 case Intrinsic::riscv_vsetvlimax: {
19094 bool HasAVL = IntNo == Intrinsic::riscv_vsetvli;
19095 unsigned VSEW =
Op.getConstantOperandVal(HasAVL + 1);
19101 MaxVL = (Fractional) ? MaxVL / LMul : MaxVL * LMul;
19104 if (HasAVL && isa<ConstantSDNode>(
Op.getOperand(1)))
19105 MaxVL = std::min(MaxVL,
Op.getConstantOperandVal(1));
19107 unsigned KnownZeroFirstBit =
Log2_32(MaxVL) + 1;
19120 unsigned Depth)
const {
19121 switch (
Op.getOpcode()) {
19127 if (Tmp == 1)
return 1;
19130 return std::min(Tmp, Tmp2);
19142 if (Tmp < 33)
return 1;
19167 unsigned XLen = Subtarget.
getXLen();
19168 unsigned EltBits =
Op.getOperand(0).getScalarValueSizeInBits();
19169 if (EltBits <= XLen)
19170 return XLen - EltBits + 1;
19174 unsigned IntNo =
Op.getConstantOperandVal(1);
19178 case Intrinsic::riscv_masked_atomicrmw_xchg_i64:
19179 case Intrinsic::riscv_masked_atomicrmw_add_i64:
19180 case Intrinsic::riscv_masked_atomicrmw_sub_i64:
19181 case Intrinsic::riscv_masked_atomicrmw_nand_i64:
19182 case Intrinsic::riscv_masked_atomicrmw_max_i64:
19183 case Intrinsic::riscv_masked_atomicrmw_min_i64:
19184 case Intrinsic::riscv_masked_atomicrmw_umax_i64:
19185 case Intrinsic::riscv_masked_atomicrmw_umin_i64:
19186 case Intrinsic::riscv_masked_cmpxchg_i64:
19194 assert(Subtarget.hasStdExtA());
19209 switch (
Op.getOpcode()) {
19215 return !
Op.getValueType().isInteger();
19223 assert(Ld &&
"Unexpected null LoadSDNode");
19231 auto *CNode = dyn_cast<ConstantPoolSDNode>(
Ptr);
19232 if (!CNode || CNode->isMachineConstantPoolEntry() ||
19233 CNode->getOffset() != 0)
19241 auto *CNode = GetSupportedConstantPool(
Ptr);
19242 if (!CNode || CNode->getTargetFlags() != 0)
19245 return CNode->getConstVal();
19253 auto *CNodeLo = GetSupportedConstantPool(
Ptr.getOperand(1));
19254 auto *CNodeHi = GetSupportedConstantPool(
Ptr.getOperand(0).getOperand(0));
19260 if (CNodeLo->getConstVal() != CNodeHi->getConstVal())
19263 return CNodeLo->getConstVal();
19268 assert(
MI.getOpcode() == RISCV::ReadCounterWide &&
"Unexpected instruction");
19300 Register ReadAgainReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
19303 int64_t LoCounter =
MI.getOperand(2).getImm();
19304 int64_t HiCounter =
MI.getOperand(3).getImm();
19314 BuildMI(LoopMBB,
DL,
TII->get(RISCV::CSRRS), ReadAgainReg)
19326 MI.eraseFromParent();
19334 assert(
MI.getOpcode() == RISCV::SplitF64Pseudo &&
"Unexpected instruction");
19342 Register SrcReg =
MI.getOperand(2).getReg();
19362 MI.eraseFromParent();
19369 assert(
MI.getOpcode() == RISCV::BuildPairF64Pseudo &&
19370 "Unexpected instruction");
19376 Register DstReg =
MI.getOperand(0).getReg();
19399 MI.eraseFromParent();
19404 switch (
MI.getOpcode()) {
19407 case RISCV::Select_GPR_Using_CC_GPR:
19408 case RISCV::Select_GPR_Using_CC_Imm:
19409 case RISCV::Select_FPR16_Using_CC_GPR:
19410 case RISCV::Select_FPR16INX_Using_CC_GPR:
19411 case RISCV::Select_FPR32_Using_CC_GPR:
19412 case RISCV::Select_FPR32INX_Using_CC_GPR:
19413 case RISCV::Select_FPR64_Using_CC_GPR:
19414 case RISCV::Select_FPR64INX_Using_CC_GPR:
19415 case RISCV::Select_FPR64IN32X_Using_CC_GPR:
19421 unsigned RelOpcode,
unsigned EqOpcode,
19424 Register DstReg =
MI.getOperand(0).getReg();
19425 Register Src1Reg =
MI.getOperand(1).getReg();
19426 Register Src2Reg =
MI.getOperand(2).getReg();
19428 Register SavedFFlags =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
19452 MI.eraseFromParent();
19503 F->insert(It, FirstMBB);
19504 F->insert(It, SecondMBB);
19505 F->insert(It, SinkMBB);
19554 First.eraseFromParent();
19593 if ((
MI.getOpcode() != RISCV::Select_GPR_Using_CC_GPR &&
19594 MI.getOpcode() != RISCV::Select_GPR_Using_CC_Imm) &&
19595 Next != BB->
end() && Next->getOpcode() ==
MI.getOpcode() &&
19596 Next->getOperand(5).getReg() ==
MI.getOperand(0).getReg() &&
19597 Next->getOperand(5).isKill())
19602 if (
MI.getOperand(2).isReg())
19603 RHS =
MI.getOperand(2).getReg();
19608 SelectDests.
insert(
MI.getOperand(0).getReg());
19612 SequenceMBBI != E; ++SequenceMBBI) {
19613 if (SequenceMBBI->isDebugInstr())
19616 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
19617 !SequenceMBBI->getOperand(2).isReg() ||
19618 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
19619 SequenceMBBI->getOperand(3).getImm() !=
CC ||
19620 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
19621 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
19623 LastSelectPseudo = &*SequenceMBBI;
19625 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
19628 if (SequenceMBBI->hasUnmodeledSideEffects() ||
19629 SequenceMBBI->mayLoadOrStore() ||
19630 SequenceMBBI->usesCustomInsertionHook())
19633 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
19648 F->insert(
I, IfFalseMBB);
19649 F->insert(
I, TailMBB);
19652 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
19658 TailMBB->
push_back(DebugInstr->removeFromParent());
19662 TailMBB->
splice(TailMBB->
end(), HeadMBB,
19672 if (
MI.getOperand(2).isImm())
19675 .
addImm(
MI.getOperand(2).getImm())
19687 auto SelectMBBI =
MI.getIterator();
19688 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
19690 while (SelectMBBI != SelectEnd) {
19691 auto Next = std::next(SelectMBBI);
19695 TII.get(RISCV::PHI), SelectMBBI->getOperand(0).getReg())
19696 .
addReg(SelectMBBI->getOperand(4).getReg())
19698 .
addReg(SelectMBBI->getOperand(5).getReg())
19713 RISCVVInversePseudosTable::getBaseInfo(MCOpcode, LMul, SEW);
19714 assert(
Inverse &&
"Unexpected LMUL and SEW pair for instruction");
19716 RISCV::lookupMaskedIntrinsicByUnmasked(
Inverse->Pseudo);
19717 assert(
Masked &&
"Could not find masked instruction for LMUL and SEW pair");
19723 unsigned CVTXOpc) {
19729 Register SavedFFLAGS =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
19742 .
add(
MI.getOperand(1))
19743 .
add(
MI.getOperand(2))
19744 .
add(
MI.getOperand(3))
19746 .
add(
MI.getOperand(4))
19747 .
add(
MI.getOperand(5))
19748 .
add(
MI.getOperand(6))
19763 .
add(
MI.getOperand(0))
19764 .
add(
MI.getOperand(1))
19766 .
add(
MI.getOperand(3))
19768 .
add(
MI.getOperand(4))
19769 .
add(
MI.getOperand(5))
19770 .
add(
MI.getOperand(6))
19780 MI.eraseFromParent();
19786 unsigned CmpOpc, F2IOpc, I2FOpc, FSGNJOpc, FSGNJXOpc;
19788 switch (
MI.getOpcode()) {
19791 case RISCV::PseudoFROUND_H:
19792 CmpOpc = RISCV::FLT_H;
19793 F2IOpc = RISCV::FCVT_W_H;
19794 I2FOpc = RISCV::FCVT_H_W;
19795 FSGNJOpc = RISCV::FSGNJ_H;
19796 FSGNJXOpc = RISCV::FSGNJX_H;
19797 RC = &RISCV::FPR16RegClass;
19799 case RISCV::PseudoFROUND_H_INX:
19800 CmpOpc = RISCV::FLT_H_INX;
19801 F2IOpc = RISCV::FCVT_W_H_INX;
19802 I2FOpc = RISCV::FCVT_H_W_INX;
19803 FSGNJOpc = RISCV::FSGNJ_H_INX;
19804 FSGNJXOpc = RISCV::FSGNJX_H_INX;
19805 RC = &RISCV::GPRF16RegClass;
19807 case RISCV::PseudoFROUND_S:
19808 CmpOpc = RISCV::FLT_S;
19809 F2IOpc = RISCV::FCVT_W_S;
19810 I2FOpc = RISCV::FCVT_S_W;
19811 FSGNJOpc = RISCV::FSGNJ_S;
19812 FSGNJXOpc = RISCV::FSGNJX_S;
19813 RC = &RISCV::FPR32RegClass;
19815 case RISCV::PseudoFROUND_S_INX:
19816 CmpOpc = RISCV::FLT_S_INX;
19817 F2IOpc = RISCV::FCVT_W_S_INX;
19818 I2FOpc = RISCV::FCVT_S_W_INX;
19819 FSGNJOpc = RISCV::FSGNJ_S_INX;
19820 FSGNJXOpc = RISCV::FSGNJX_S_INX;
19821 RC = &RISCV::GPRF32RegClass;
19823 case RISCV::PseudoFROUND_D:
19825 CmpOpc = RISCV::FLT_D;
19826 F2IOpc = RISCV::FCVT_L_D;
19827 I2FOpc = RISCV::FCVT_D_L;
19828 FSGNJOpc = RISCV::FSGNJ_D;
19829 FSGNJXOpc = RISCV::FSGNJX_D;
19830 RC = &RISCV::FPR64RegClass;
19832 case RISCV::PseudoFROUND_D_INX:
19834 CmpOpc = RISCV::FLT_D_INX;
19835 F2IOpc = RISCV::FCVT_L_D_INX;
19836 I2FOpc = RISCV::FCVT_D_L_INX;
19837 FSGNJOpc = RISCV::FSGNJ_D_INX;
19838 FSGNJXOpc = RISCV::FSGNJX_D_INX;
19839 RC = &RISCV::GPRRegClass;
19851 F->insert(
I, CvtMBB);
19852 F->insert(
I, DoneMBB);
19863 Register DstReg =
MI.getOperand(0).getReg();
19864 Register SrcReg =
MI.getOperand(1).getReg();
19865 Register MaxReg =
MI.getOperand(2).getReg();
19866 int64_t FRM =
MI.getOperand(3).getImm();
19871 Register FabsReg =
MRI.createVirtualRegister(RC);
19875 Register CmpReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
19890 Register F2IReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
19912 MI.eraseFromParent();
19919 switch (
MI.getOpcode()) {
19922 case RISCV::ReadCounterWide:
19924 "ReadCounterWide is only to be used on riscv32");
19926 case RISCV::Select_GPR_Using_CC_GPR:
19927 case RISCV::Select_GPR_Using_CC_Imm:
19928 case RISCV::Select_FPR16_Using_CC_GPR:
19929 case RISCV::Select_FPR16INX_Using_CC_GPR:
19930 case RISCV::Select_FPR32_Using_CC_GPR:
19931 case RISCV::Select_FPR32INX_Using_CC_GPR:
19932 case RISCV::Select_FPR64_Using_CC_GPR:
19933 case RISCV::Select_FPR64INX_Using_CC_GPR:
19934 case RISCV::Select_FPR64IN32X_Using_CC_GPR:
19936 case RISCV::BuildPairF64Pseudo:
19938 case RISCV::SplitF64Pseudo:
19940 case RISCV::PseudoQuietFLE_H:
19942 case RISCV::PseudoQuietFLE_H_INX:
19943 return emitQuietFCMP(
MI, BB, RISCV::FLE_H_INX, RISCV::FEQ_H_INX, Subtarget);
19944 case RISCV::PseudoQuietFLT_H:
19946 case RISCV::PseudoQuietFLT_H_INX:
19947 return emitQuietFCMP(
MI, BB, RISCV::FLT_H_INX, RISCV::FEQ_H_INX, Subtarget);
19948 case RISCV::PseudoQuietFLE_S:
19950 case RISCV::PseudoQuietFLE_S_INX:
19951 return emitQuietFCMP(
MI, BB, RISCV::FLE_S_INX, RISCV::FEQ_S_INX, Subtarget);
19952 case RISCV::PseudoQuietFLT_S:
19954 case RISCV::PseudoQuietFLT_S_INX:
19955 return emitQuietFCMP(
MI, BB, RISCV::FLT_S_INX, RISCV::FEQ_S_INX, Subtarget);
19956 case RISCV::PseudoQuietFLE_D:
19958 case RISCV::PseudoQuietFLE_D_INX:
19959 return emitQuietFCMP(
MI, BB, RISCV::FLE_D_INX, RISCV::FEQ_D_INX, Subtarget);
19960 case RISCV::PseudoQuietFLE_D_IN32X:
19963 case RISCV::PseudoQuietFLT_D:
19965 case RISCV::PseudoQuietFLT_D_INX:
19966 return emitQuietFCMP(
MI, BB, RISCV::FLT_D_INX, RISCV::FEQ_D_INX, Subtarget);
19967 case RISCV::PseudoQuietFLT_D_IN32X:
19971 case RISCV::PseudoVFROUND_NOEXCEPT_V_M1_MASK:
19973 case RISCV::PseudoVFROUND_NOEXCEPT_V_M2_MASK:
19975 case RISCV::PseudoVFROUND_NOEXCEPT_V_M4_MASK:
19977 case RISCV::PseudoVFROUND_NOEXCEPT_V_M8_MASK:
19979 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF2_MASK:
19981 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF4_MASK:
19983 case RISCV::PseudoFROUND_H:
19984 case RISCV::PseudoFROUND_H_INX:
19985 case RISCV::PseudoFROUND_S:
19986 case RISCV::PseudoFROUND_S_INX:
19987 case RISCV::PseudoFROUND_D:
19988 case RISCV::PseudoFROUND_D_INX:
19989 case RISCV::PseudoFROUND_D_IN32X:
19991 case RISCV::PROBED_STACKALLOC_DYN:
19993 case TargetOpcode::STATEPOINT:
19999 MI.addOperand(*
MI.getMF(),
20005 case TargetOpcode::STACKMAP:
20006 case TargetOpcode::PATCHPOINT:
20009 "supported on 64-bit targets");
20027 if (
MI.readsRegister(RISCV::FRM,
nullptr))
20033void RISCVTargetLowering::analyzeInputArgs(
20037 unsigned NumArgs = Ins.size();
20040 for (
unsigned i = 0; i != NumArgs; ++i) {
20041 MVT ArgVT = Ins[i].VT;
20044 Type *ArgTy =
nullptr;
20047 else if (Ins[i].isOrigArg())
20048 ArgTy = FType->
getParamType(Ins[i].getOrigArgIndex());
20051 true, IsRet, ArgTy)) {
20052 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type "
20059void RISCVTargetLowering::analyzeOutputArgs(
20063 unsigned NumArgs = Outs.
size();
20065 for (
unsigned i = 0; i != NumArgs; i++) {
20066 MVT ArgVT = Outs[i].VT;
20068 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
20071 Outs[i].IsFixed, IsRet, OrigTy)) {
20072 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type "
20123 if (In.isOrigArg()) {
20128 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
20129 (
BitWidth < 32 && In.Flags.isZExt())) {
20151 if (LocVT == MVT::i64 && VA.
getValVT() == MVT::f32)
20200 ExtType,
DL, LocVT, Chain, FIN,
20217 Register LoVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
20230 Register HiVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
20245 switch (CallConv) {
20255 if (Subtarget.hasStdExtE())
20259 "(Zdinx/D) instruction set extensions");
20263 if (Func.hasFnAttribute(
"interrupt")) {
20264 if (!Func.arg_empty())
20266 "Functions with the interrupt attribute cannot have arguments!");
20271 if (!(Kind ==
"user" || Kind ==
"supervisor" || Kind ==
"machine"))
20273 "Function interrupt attribute argument not supported!");
20278 unsigned XLenInBytes = Subtarget.
getXLen() / 8;
20280 std::vector<SDValue> OutChains;
20289 analyzeInputArgs(MF, CCInfo, Ins,
false,
20293 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
20314 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
20315 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
20317 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
20319 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
20348 int VarArgsSaveSize = XLenInBytes * (ArgRegs.
size() -
Idx);
20353 if (VarArgsSaveSize == 0) {
20357 int VaArgOffset = -VarArgsSaveSize;
20365 XLenInBytes, VaArgOffset -
static_cast<int>(XLenInBytes),
true);
20366 VarArgsSaveSize += XLenInBytes;
20373 for (
unsigned I =
Idx;
I < ArgRegs.
size(); ++
I) {
20378 Chain,
DL, ArgValue, FIN,
20380 OutChains.push_back(Store);
20394 if (!OutChains.empty()) {
20395 OutChains.push_back(Chain);
20405bool RISCVTargetLowering::isEligibleForTailCallOptimization(
20409 auto CalleeCC = CLI.CallConv;
20410 auto &Outs = CLI.Outs;
20412 auto CallerCC = Caller.getCallingConv();
20419 if (Caller.hasFnAttribute(
"interrupt"))
20434 for (
auto &VA : ArgLocs)
20440 auto IsCallerStructRet = Caller.hasStructRetAttr();
20441 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
20442 if (IsCallerStructRet || IsCalleeStructRet)
20447 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
20448 if (CalleeCC != CallerCC) {
20449 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
20450 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
20457 for (
auto &Arg : Outs)
20458 if (Arg.Flags.isByVal())
20493 if (Subtarget.hasStdExtE())
20497 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
20503 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
20509 "site marked musttail");
20516 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
20518 if (!Flags.isByVal())
20522 unsigned Size = Flags.getByValSize();
20523 Align Alignment = Flags.getNonZeroByValAlign();
20530 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
20532 false,
nullptr, IsTailCall,
20544 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
20547 SDValue ArgValue = OutVals[OutIdx];
20567 if (!StackPtr.getNode())
20579 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
20597 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
20598 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
20604 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
20605 SDValue PartValue = OutVals[OutIdx + 1];
20606 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
20618 int FI = cast<FrameIndexSDNode>(SpillSlot)->getIndex();
20620 DAG.
getStore(Chain,
DL, ArgValue, SpillSlot,
20622 for (
const auto &Part : Parts) {
20623 SDValue PartValue = Part.first;
20624 SDValue PartOffset = Part.second;
20631 ArgValue = SpillSlot;
20637 if (Flags.isByVal())
20638 ArgValue = ByValArgs[j++];
20645 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
20646 "for passing parameters");
20649 if (!StackPtr.getNode())
20663 if (!MemOpChains.
empty())
20669 for (
auto &Reg : RegsToPass) {
20670 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
20677 validateCCReservedRegs(RegsToPass, MF);
20681 "Return address register required, but has been reserved."});
20686 bool CalleeIsLargeExternalSymbol =
false;
20688 if (
auto *S = dyn_cast<GlobalAddressSDNode>(Callee))
20690 else if (
auto *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
20692 CalleeIsLargeExternalSymbol =
true;
20708 for (
auto &Reg : RegsToPass)
20713 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
20714 assert(Mask &&
"Missing call preserved mask for calling convention");
20722 "Unexpected CFI type for a direct call");
20730 bool NeedSWGuarded =
false;
20732 Subtarget.hasStdExtZicfilp() &&
20734 NeedSWGuarded =
true;
20748 Chain = DAG.
getNode(CallOpc,
DL, NodeTys, Ops);
20761 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_RISCV);
20764 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
20765 auto &VA = RVLocs[i];
20773 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
20774 assert(VA.needsCustom());
20795 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
20797 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
20798 MVT VT = Outs[i].VT;
20801 true,
true,
nullptr))
20833 for (
unsigned i = 0, e = RVLocs.size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
20834 SDValue Val = OutVals[OutIdx];
20843 DAG.
getVTList(MVT::i32, MVT::i32), Val);
20847 Register RegHi = RVLocs[++i].getLocReg();
20853 "Return value register required, but has been reserved."});
20869 "Return value register required, but has been reserved."});
20891 if (Func.hasFnAttribute(
"interrupt")) {
20892 if (!Func.getReturnType()->isVoidTy())
20894 "Functions with the interrupt attribute must have void return type!");
20900 if (Kind ==
"supervisor")
20906 return DAG.
getNode(RetOpc,
DL, MVT::Other, RetOps);
20909void RISCVTargetLowering::validateCCReservedRegs(
20910 const SmallVectorImpl<std::pair<llvm::Register, llvm::SDValue>> &Regs,
20919 F,
"Argument register required, but has been reserved."});
20925 if (
N->getNumValues() != 1)
20927 if (!
N->hasNUsesOfValue(1, 0))
20930 SDNode *Copy = *
N->user_begin();
20944 if (Copy->getOperand(Copy->getNumOperands() - 1).getValueType() == MVT::Glue)
20948 bool HasRet =
false;
20949 for (
SDNode *Node : Copy->users()) {
20957 Chain = Copy->getOperand(0);
20966#define NODE_NAME_CASE(NODE) \
20967 case RISCVISD::NODE: \
20968 return "RISCVISD::" #NODE;
21230#undef NODE_NAME_CASE
21237 if (Constraint.
size() == 1) {
21238 switch (Constraint[0]) {
21255 if (Constraint ==
"vr" || Constraint ==
"vd" || Constraint ==
"vm")
21257 if (Constraint ==
"cr" || Constraint ==
"cR" || Constraint ==
"cf")
21263std::pair<unsigned, const TargetRegisterClass *>
21269 if (Constraint.
size() == 1) {
21270 switch (Constraint[0]) {
21275 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
21276 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
21277 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
21278 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
21279 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
21280 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
21281 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
21283 if (VT == MVT::f16) {
21284 if (Subtarget.hasStdExtZfhmin())
21285 return std::make_pair(0U, &RISCV::FPR16RegClass);
21286 if (Subtarget.hasStdExtZhinxmin())
21287 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
21288 }
else if (VT == MVT::f32) {
21289 if (Subtarget.hasStdExtF())
21290 return std::make_pair(0U, &RISCV::FPR32RegClass);
21291 if (Subtarget.hasStdExtZfinx())
21292 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
21293 }
else if (VT == MVT::f64) {
21294 if (Subtarget.hasStdExtD())
21295 return std::make_pair(0U, &RISCV::FPR64RegClass);
21296 if (Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
21297 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
21298 if (Subtarget.hasStdExtZdinx() && Subtarget.
is64Bit())
21299 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
21303 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
21307 }
else if (Constraint ==
"vr") {
21308 for (
const auto *RC :
21309 {&RISCV::VRRegClass, &RISCV::VRM2RegClass, &RISCV::VRM4RegClass,
21310 &RISCV::VRM8RegClass, &RISCV::VRN2M1RegClass, &RISCV::VRN3M1RegClass,
21311 &RISCV::VRN4M1RegClass, &RISCV::VRN5M1RegClass,
21312 &RISCV::VRN6M1RegClass, &RISCV::VRN7M1RegClass,
21313 &RISCV::VRN8M1RegClass, &RISCV::VRN2M2RegClass,
21314 &RISCV::VRN3M2RegClass, &RISCV::VRN4M2RegClass,
21315 &RISCV::VRN2M4RegClass}) {
21317 return std::make_pair(0U, RC);
21319 }
else if (Constraint ==
"vd") {
21320 for (
const auto *RC :
21321 {&RISCV::VRNoV0RegClass, &RISCV::VRM2NoV0RegClass,
21322 &RISCV::VRM4NoV0RegClass, &RISCV::VRM8NoV0RegClass,
21323 &RISCV::VRN2M1NoV0RegClass, &RISCV::VRN3M1NoV0RegClass,
21324 &RISCV::VRN4M1NoV0RegClass, &RISCV::VRN5M1NoV0RegClass,
21325 &RISCV::VRN6M1NoV0RegClass, &RISCV::VRN7M1NoV0RegClass,
21326 &RISCV::VRN8M1NoV0RegClass, &RISCV::VRN2M2NoV0RegClass,
21327 &RISCV::VRN3M2NoV0RegClass, &RISCV::VRN4M2NoV0RegClass,
21328 &RISCV::VRN2M4NoV0RegClass}) {
21330 return std::make_pair(0U, RC);
21332 }
else if (Constraint ==
"vm") {
21333 if (
TRI->isTypeLegalForClass(RISCV::VMV0RegClass, VT.
SimpleTy))
21334 return std::make_pair(0U, &RISCV::VMV0RegClass);
21335 }
else if (Constraint ==
"cr") {
21336 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
21337 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
21338 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
21339 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
21340 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
21341 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
21343 return std::make_pair(0U, &RISCV::GPRCRegClass);
21344 }
else if (Constraint ==
"cR") {
21345 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
21346 }
else if (Constraint ==
"cf") {
21347 if (VT == MVT::f16) {
21348 if (Subtarget.hasStdExtZfhmin())
21349 return std::make_pair(0U, &RISCV::FPR16CRegClass);
21350 if (Subtarget.hasStdExtZhinxmin())
21351 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
21352 }
else if (VT == MVT::f32) {
21353 if (Subtarget.hasStdExtF())
21354 return std::make_pair(0U, &RISCV::FPR32CRegClass);
21355 if (Subtarget.hasStdExtZfinx())
21356 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
21357 }
else if (VT == MVT::f64) {
21358 if (Subtarget.hasStdExtD())
21359 return std::make_pair(0U, &RISCV::FPR64CRegClass);
21360 if (Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
21361 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
21362 if (Subtarget.hasStdExtZdinx() && Subtarget.
is64Bit())
21363 return std::make_pair(0U, &RISCV::GPRCRegClass);
21372 .
Case(
"{zero}", RISCV::X0)
21373 .
Case(
"{ra}", RISCV::X1)
21374 .
Case(
"{sp}", RISCV::X2)
21375 .
Case(
"{gp}", RISCV::X3)
21376 .
Case(
"{tp}", RISCV::X4)
21377 .
Case(
"{t0}", RISCV::X5)
21378 .
Case(
"{t1}", RISCV::X6)
21379 .
Case(
"{t2}", RISCV::X7)
21380 .
Cases(
"{s0}",
"{fp}", RISCV::X8)
21381 .
Case(
"{s1}", RISCV::X9)
21382 .
Case(
"{a0}", RISCV::X10)
21383 .
Case(
"{a1}", RISCV::X11)
21384 .
Case(
"{a2}", RISCV::X12)
21385 .
Case(
"{a3}", RISCV::X13)
21386 .
Case(
"{a4}", RISCV::X14)
21387 .
Case(
"{a5}", RISCV::X15)
21388 .
Case(
"{a6}", RISCV::X16)
21389 .
Case(
"{a7}", RISCV::X17)
21390 .
Case(
"{s2}", RISCV::X18)
21391 .
Case(
"{s3}", RISCV::X19)
21392 .
Case(
"{s4}", RISCV::X20)
21393 .
Case(
"{s5}", RISCV::X21)
21394 .
Case(
"{s6}", RISCV::X22)
21395 .
Case(
"{s7}", RISCV::X23)
21396 .
Case(
"{s8}", RISCV::X24)
21397 .
Case(
"{s9}", RISCV::X25)
21398 .
Case(
"{s10}", RISCV::X26)
21399 .
Case(
"{s11}", RISCV::X27)
21400 .
Case(
"{t3}", RISCV::X28)
21401 .
Case(
"{t4}", RISCV::X29)
21402 .
Case(
"{t5}", RISCV::X30)
21403 .
Case(
"{t6}", RISCV::X31)
21405 if (XRegFromAlias != RISCV::NoRegister)
21406 return std::make_pair(XRegFromAlias, &RISCV::GPRRegClass);
21415 if (Subtarget.hasStdExtF()) {
21417 .
Cases(
"{f0}",
"{ft0}", RISCV::F0_F)
21418 .
Cases(
"{f1}",
"{ft1}", RISCV::F1_F)
21419 .
Cases(
"{f2}",
"{ft2}", RISCV::F2_F)
21420 .
Cases(
"{f3}",
"{ft3}", RISCV::F3_F)
21421 .
Cases(
"{f4}",
"{ft4}", RISCV::F4_F)
21422 .
Cases(
"{f5}",
"{ft5}", RISCV::F5_F)
21423 .
Cases(
"{f6}",
"{ft6}", RISCV::F6_F)
21424 .
Cases(
"{f7}",
"{ft7}", RISCV::F7_F)
21425 .
Cases(
"{f8}",
"{fs0}", RISCV::F8_F)
21426 .
Cases(
"{f9}",
"{fs1}", RISCV::F9_F)
21427 .
Cases(
"{f10}",
"{fa0}", RISCV::F10_F)
21428 .
Cases(
"{f11}",
"{fa1}", RISCV::F11_F)
21429 .
Cases(
"{f12}",
"{fa2}", RISCV::F12_F)
21430 .
Cases(
"{f13}",
"{fa3}", RISCV::F13_F)
21431 .
Cases(
"{f14}",
"{fa4}", RISCV::F14_F)
21432 .
Cases(
"{f15}",
"{fa5}", RISCV::F15_F)
21433 .
Cases(
"{f16}",
"{fa6}", RISCV::F16_F)
21434 .
Cases(
"{f17}",
"{fa7}", RISCV::F17_F)
21435 .
Cases(
"{f18}",
"{fs2}", RISCV::F18_F)
21436 .
Cases(
"{f19}",
"{fs3}", RISCV::F19_F)
21437 .
Cases(
"{f20}",
"{fs4}", RISCV::F20_F)
21438 .
Cases(
"{f21}",
"{fs5}", RISCV::F21_F)
21439 .
Cases(
"{f22}",
"{fs6}", RISCV::F22_F)
21440 .
Cases(
"{f23}",
"{fs7}", RISCV::F23_F)
21441 .
Cases(
"{f24}",
"{fs8}", RISCV::F24_F)
21442 .
Cases(
"{f25}",
"{fs9}", RISCV::F25_F)
21443 .
Cases(
"{f26}",
"{fs10}", RISCV::F26_F)
21444 .
Cases(
"{f27}",
"{fs11}", RISCV::F27_F)
21445 .
Cases(
"{f28}",
"{ft8}", RISCV::F28_F)
21446 .
Cases(
"{f29}",
"{ft9}", RISCV::F29_F)
21447 .
Cases(
"{f30}",
"{ft10}", RISCV::F30_F)
21448 .
Cases(
"{f31}",
"{ft11}", RISCV::F31_F)
21450 if (FReg != RISCV::NoRegister) {
21451 assert(RISCV::F0_F <= FReg && FReg <= RISCV::F31_F &&
"Unknown fp-reg");
21452 if (Subtarget.hasStdExtD() && (VT == MVT::f64 || VT == MVT::Other)) {
21453 unsigned RegNo = FReg - RISCV::F0_F;
21454 unsigned DReg = RISCV::F0_D + RegNo;
21455 return std::make_pair(DReg, &RISCV::FPR64RegClass);
21457 if (VT == MVT::f32 || VT == MVT::Other)
21458 return std::make_pair(FReg, &RISCV::FPR32RegClass);
21459 if (Subtarget.hasStdExtZfhmin() && VT == MVT::f16) {
21460 unsigned RegNo = FReg - RISCV::F0_F;
21461 unsigned HReg = RISCV::F0_H + RegNo;
21462 return std::make_pair(HReg, &RISCV::FPR16RegClass);
21469 .
Case(
"{v0}", RISCV::V0)
21470 .
Case(
"{v1}", RISCV::V1)
21471 .
Case(
"{v2}", RISCV::V2)
21472 .
Case(
"{v3}", RISCV::V3)
21473 .
Case(
"{v4}", RISCV::V4)
21474 .
Case(
"{v5}", RISCV::V5)
21475 .
Case(
"{v6}", RISCV::V6)
21476 .
Case(
"{v7}", RISCV::V7)
21477 .
Case(
"{v8}", RISCV::V8)
21478 .
Case(
"{v9}", RISCV::V9)
21479 .
Case(
"{v10}", RISCV::V10)
21480 .
Case(
"{v11}", RISCV::V11)
21481 .
Case(
"{v12}", RISCV::V12)
21482 .
Case(
"{v13}", RISCV::V13)
21483 .
Case(
"{v14}", RISCV::V14)
21484 .
Case(
"{v15}", RISCV::V15)
21485 .
Case(
"{v16}", RISCV::V16)
21486 .
Case(
"{v17}", RISCV::V17)
21487 .
Case(
"{v18}", RISCV::V18)
21488 .
Case(
"{v19}", RISCV::V19)
21489 .
Case(
"{v20}", RISCV::V20)
21490 .
Case(
"{v21}", RISCV::V21)
21491 .
Case(
"{v22}", RISCV::V22)
21492 .
Case(
"{v23}", RISCV::V23)
21493 .
Case(
"{v24}", RISCV::V24)
21494 .
Case(
"{v25}", RISCV::V25)
21495 .
Case(
"{v26}", RISCV::V26)
21496 .
Case(
"{v27}", RISCV::V27)
21497 .
Case(
"{v28}", RISCV::V28)
21498 .
Case(
"{v29}", RISCV::V29)
21499 .
Case(
"{v30}", RISCV::V30)
21500 .
Case(
"{v31}", RISCV::V31)
21502 if (VReg != RISCV::NoRegister) {
21503 if (
TRI->isTypeLegalForClass(RISCV::VMRegClass, VT.
SimpleTy))
21504 return std::make_pair(VReg, &RISCV::VMRegClass);
21505 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, VT.
SimpleTy))
21506 return std::make_pair(VReg, &RISCV::VRRegClass);
21507 for (
const auto *RC :
21508 {&RISCV::VRM2RegClass, &RISCV::VRM4RegClass, &RISCV::VRM8RegClass}) {
21509 if (
TRI->isTypeLegalForClass(*RC, VT.
SimpleTy)) {
21510 VReg =
TRI->getMatchingSuperReg(VReg, RISCV::sub_vrm1_0, RC);
21511 return std::make_pair(VReg, RC);
21517 std::pair<Register, const TargetRegisterClass *> Res =
21523 if (Res.second == &RISCV::GPRF16RegClass ||
21524 Res.second == &RISCV::GPRF32RegClass ||
21525 Res.second == &RISCV::GPRPairRegClass)
21526 return std::make_pair(Res.first, &RISCV::GPRRegClass);
21534 if (ConstraintCode.
size() == 1) {
21535 switch (ConstraintCode[0]) {
21550 if (Constraint.
size() == 1) {
21551 switch (Constraint[0]) {
21554 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
21556 if (isInt<12>(CVal))
21569 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
21571 if (isUInt<5>(CVal))
21589 if (Subtarget.hasStdExtZtso()) {
21605 if (Subtarget.hasStdExtZtso()) {
21613 if (Subtarget.enableTrailingSeqCstFence() && isa<StoreInst>(Inst) &&
21632 if (Subtarget.hasForcedAtomics())
21637 if (Subtarget.hasStdExtZacas() &&
21638 (
Size >= 32 || Subtarget.hasStdExtZabha()))
21644 if (
Size < 32 && !Subtarget.hasStdExtZabha())
21657 return Intrinsic::riscv_masked_atomicrmw_xchg_i32;
21659 return Intrinsic::riscv_masked_atomicrmw_add_i32;
21661 return Intrinsic::riscv_masked_atomicrmw_sub_i32;
21663 return Intrinsic::riscv_masked_atomicrmw_nand_i32;
21665 return Intrinsic::riscv_masked_atomicrmw_max_i32;
21667 return Intrinsic::riscv_masked_atomicrmw_min_i32;
21669 return Intrinsic::riscv_masked_atomicrmw_umax_i32;
21671 return Intrinsic::riscv_masked_atomicrmw_umin_i32;
21680 return Intrinsic::riscv_masked_atomicrmw_xchg_i64;
21682 return Intrinsic::riscv_masked_atomicrmw_add_i64;
21684 return Intrinsic::riscv_masked_atomicrmw_sub_i64;
21686 return Intrinsic::riscv_masked_atomicrmw_nand_i64;
21688 return Intrinsic::riscv_masked_atomicrmw_max_i64;
21690 return Intrinsic::riscv_masked_atomicrmw_min_i64;
21692 return Intrinsic::riscv_masked_atomicrmw_umax_i64;
21694 return Intrinsic::riscv_masked_atomicrmw_umin_i64;
21720 unsigned XLen = Subtarget.
getXLen();
21744 unsigned ValWidth =
21749 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
21752 Builder.
CreateCall(LrwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
21764 if (Subtarget.hasForcedAtomics())
21768 if (!(Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas()) &&
21777 unsigned XLen = Subtarget.
getXLen();
21779 Intrinsic::ID CmpXchgIntrID = Intrinsic::riscv_masked_cmpxchg_i32;
21784 CmpXchgIntrID = Intrinsic::riscv_masked_cmpxchg_i64;
21788 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, Ordering});
21795 EVT DataVT)
const {
21811 return Subtarget.hasStdExtZfhmin();
21813 return Subtarget.hasStdExtF();
21815 return Subtarget.hasStdExtD();
21847 "RVVBitsPerBlock changed, audit needed");
21856 if (!Subtarget.hasVendorXTHeadMemIdx())
21862 Base =
Op->getOperand(0);
21864 int64_t RHSC =
RHS->getSExtValue();
21870 bool isLegalIndexedOffset =
false;
21871 for (
unsigned i = 0; i < 4; i++)
21872 if (isInt<5>(RHSC >> i) && ((RHSC % (1LL << i)) == 0)) {
21873 isLegalIndexedOffset =
true;
21877 if (!isLegalIndexedOffset)
21894 VT = LD->getMemoryVT();
21895 Ptr = LD->getBasePtr();
21896 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
21897 VT = ST->getMemoryVT();
21898 Ptr = ST->getBasePtr();
21914 if (Subtarget.hasVendorXCVmem() && !Subtarget.
is64Bit()) {
21919 Base = LS->getBasePtr();
21923 if (
Base ==
Op->getOperand(0))
21925 else if (
Base ==
Op->getOperand(1))
21937 VT = LD->getMemoryVT();
21938 Ptr = LD->getBasePtr();
21939 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
21940 VT = ST->getMemoryVT();
21941 Ptr = ST->getBasePtr();
21984 const Constant *PersonalityFn)
const {
21989 const Constant *PersonalityFn)
const {
22004 bool IsSigned)
const {
22019 const bool HasZmmul = Subtarget.hasStdExtZmmul();
22023 auto *ConstNode = cast<ConstantSDNode>(
C);
22024 const APInt &Imm = ConstNode->getAPIntValue();
22027 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
22028 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
22032 if (Subtarget.hasStdExtZba() && !Imm.isSignedIntN(12) &&
22033 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
22034 (Imm - 8).isPowerOf2()))
22039 if (!Imm.isSignedIntN(12) && Imm.countr_zero() < 12 &&
22040 ConstNode->hasOneUse()) {
22041 APInt ImmS = Imm.ashr(Imm.countr_zero());
22042 if ((ImmS + 1).isPowerOf2() || (ImmS - 1).isPowerOf2() ||
22043 (1 - ImmS).isPowerOf2())
22066 if (C1.
isSignedIntN(12) && !(C1 * C2).isSignedIntN(12))
22075 unsigned *
Fast)
const {
22078 *
Fast = Subtarget.enableUnalignedScalarMem();
22079 return Subtarget.enableUnalignedScalarMem();
22095 *
Fast = Subtarget.enableUnalignedVectorMem();
22096 return Subtarget.enableUnalignedVectorMem();
22105 if (FuncAttributes.
hasFnAttr(Attribute::NoImplicitFloat))
22117 if (
Op.size() < MinVLenInBytes)
22132 MVT PreferredVT = (
Op.isMemset() && !
Op.isZeroMemset()) ? MVT::i8 : ELenVT;
22136 if (PreferredVT != MVT::i8 && !Subtarget.enableUnalignedVectorMem()) {
22138 if (
Op.isFixedDstAlign())
22139 RequiredAlign = std::min(RequiredAlign,
Op.getDstAlign());
22141 RequiredAlign = std::min(RequiredAlign,
Op.getSrcAlign());
22149 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID>
CC)
const {
22150 bool IsABIRegCopy =
CC.has_value();
22153 MVT PairVT = Subtarget.
is64Bit() ? MVT::i128 : MVT::i64;
22154 if ((ValueVT == PairVT ||
22155 (!Subtarget.
is64Bit() && Subtarget.hasStdExtZdinx() &&
22156 ValueVT == MVT::f64)) &&
22157 NumParts == 1 && PartVT == MVT::Untyped) {
22160 if (ValueVT == MVT::f64)
22169 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
22170 PartVT == MVT::f32) {
22185 [[maybe_unused]]
unsigned ValLMUL =
22189 [[maybe_unused]]
unsigned PartLMUL =
22192 assert(ValNF == PartNF && ValLMUL == PartLMUL &&
22193 "RISC-V vector tuple type only accepts same register class type "
22209 if (PartVTBitSize % ValueVTBitSize == 0) {
22210 assert(PartVTBitSize >= ValueVTBitSize);
22217 if (ValueEltVT != PartEltVT) {
22218 if (PartVTBitSize > ValueVTBitSize) {
22220 assert(Count != 0 &&
"The number of element should not be zero.");
22221 EVT SameEltTypeVT =
22243 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID>
CC)
const {
22244 bool IsABIRegCopy =
CC.has_value();
22246 MVT PairVT = Subtarget.
is64Bit() ? MVT::i128 : MVT::i64;
22247 if ((ValueVT == PairVT ||
22248 (!Subtarget.
is64Bit() && Subtarget.hasStdExtZdinx() &&
22249 ValueVT == MVT::f64)) &&
22250 NumParts == 1 && PartVT == MVT::Untyped) {
22261 if (ValueVT == MVT::f64)
22266 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
22267 PartVT == MVT::f32) {
22284 if (PartVTBitSize % ValueVTBitSize == 0) {
22285 assert(PartVTBitSize >= ValueVTBitSize);
22286 EVT SameEltTypeVT = ValueVT;
22293 if (ValueEltVT != PartEltVT) {
22295 assert(Count != 0 &&
"The number of element should not be zero.");
22312 bool OptSize = Attr.
hasFnAttr(Attribute::MinSize);
22319 unsigned Opc =
N->getOpcode();
22347 if (M->getStackProtectorGuard() ==
"tls") {
22349 int Offset = M->getStackProtectorGuardOffset();
22357 VectorType *VTy,
unsigned Factor,
Align Alignment,
unsigned AddrSpace,
22371 if (
auto *FVTy = dyn_cast<FixedVectorType>(VTy)) {
22376 if (FVTy->getNumElements() < 2)
22391 return Factor * LMUL <= 8;
22395 Align Alignment)
const {
22407 if (!Subtarget.enableUnalignedVectorMem() &&
22415 Intrinsic::riscv_seg2_load, Intrinsic::riscv_seg3_load,
22416 Intrinsic::riscv_seg4_load, Intrinsic::riscv_seg5_load,
22417 Intrinsic::riscv_seg6_load, Intrinsic::riscv_seg7_load,
22418 Intrinsic::riscv_seg8_load};
22439 auto *VTy = cast<FixedVectorType>(Shuffles[0]->
getType());
22451 unsigned ScalarSizeInBytes = VTy->getScalarSizeInBits() / 8;
22452 Value *Stride = ConstantInt::get(XLenTy, Factor * ScalarSizeInBytes);
22453 Value *
Offset = ConstantInt::get(XLenTy, Indices[0] * ScalarSizeInBytes);
22460 {VTy, BasePtr->getType(), Stride->
getType()},
22461 {BasePtr, Stride, Mask, VL});
22464 Shuffles[0]->replaceAllUsesWith(CI);
22468 Value *VL = ConstantInt::get(XLenTy, VTy->getNumElements());
22474 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
22476 Shuffles[i]->replaceAllUsesWith(SubVec);
22483 Intrinsic::riscv_seg2_store, Intrinsic::riscv_seg3_store,
22484 Intrinsic::riscv_seg4_store, Intrinsic::riscv_seg5_store,
22485 Intrinsic::riscv_seg6_store, Intrinsic::riscv_seg7_store,
22486 Intrinsic::riscv_seg8_store};
22506 unsigned Factor)
const {
22509 auto *ShuffleVTy = cast<FixedVectorType>(SVI->
getType());
22512 ShuffleVTy->getNumElements() / Factor);
22514 SI->getPointerAddressSpace(),
22515 SI->getDataLayout()))
22526 unsigned ScalarSizeInBytes = ShuffleVTy->getScalarSizeInBits() / 8;
22528 auto *DataVTy = cast<FixedVectorType>(
Data->getType());
22529 Value *Stride = ConstantInt::get(XLenTy, Factor * ScalarSizeInBytes);
22530 Value *
Offset = ConstantInt::get(XLenTy, Index * ScalarSizeInBytes);
22536 Intrinsic::experimental_vp_strided_store,
22537 {
Data->getType(), BasePtr->getType(), Stride->
getType()},
22538 {
Data, BasePtr, Stride, Mask, VL});
22547 {VTy, SI->getPointerOperandType(), XLenTy});
22551 for (
unsigned i = 0; i < Factor; i++) {
22560 Value *VL = ConstantInt::get(XLenTy, VTy->getNumElements());
22561 Ops.
append({SI->getPointerOperand(), VL});
22570 unsigned Factor = DeinterleaveValues.
size();
22577 auto *ResVTy = cast<VectorType>(DeinterleaveValues[0]->
getType());
22588 if (
auto *FVTy = dyn_cast<FixedVectorType>(ResVTy)) {
22589 Value *VL = ConstantInt::get(XLenTy, FVTy->getNumElements());
22596 Intrinsic::riscv_vlseg2, Intrinsic::riscv_vlseg3,
22597 Intrinsic::riscv_vlseg4, Intrinsic::riscv_vlseg5,
22598 Intrinsic::riscv_vlseg6, Intrinsic::riscv_vlseg7,
22599 Intrinsic::riscv_vlseg8};
22601 unsigned SEW =
DL.getTypeSizeInBits(ResVTy->getElementType());
22602 unsigned NumElts = ResVTy->getElementCount().getKnownMinValue();
22606 NumElts * SEW / 8),
22612 IntrIds[Factor - 2], {VecTupTy, XLenTy},
22614 ConstantInt::get(XLenTy,
Log2_64(SEW))});
22618 for (
unsigned i = 0; i < Factor; ++i) {
22620 Intrinsic::riscv_tuple_extract, {ResVTy, VecTupTy},
22626 for (
auto [
Idx, DIV] :
enumerate(DeinterleaveValues)) {
22639 unsigned Factor = InterleaveValues.
size();
22646 auto *InVTy = cast<VectorType>(InterleaveValues[0]->
getType());
22650 SI->getPointerAddressSpace(),
DL))
22655 if (
auto *FVTy = dyn_cast<FixedVectorType>(InVTy)) {
22658 {InVTy, SI->getPointerOperandType(), XLenTy});
22661 InterleaveValues.
end());
22662 Value *VL = ConstantInt::get(XLenTy, FVTy->getNumElements());
22663 Ops.
append({SI->getPointerOperand(), VL});
22668 Intrinsic::riscv_vsseg2, Intrinsic::riscv_vsseg3,
22669 Intrinsic::riscv_vsseg4, Intrinsic::riscv_vsseg5,
22670 Intrinsic::riscv_vsseg6, Intrinsic::riscv_vsseg7,
22671 Intrinsic::riscv_vsseg8};
22673 unsigned SEW =
DL.getTypeSizeInBits(InVTy->getElementType());
22674 unsigned NumElts = InVTy->getElementCount().getKnownMinValue();
22676 SI->getContext(),
"riscv.vector.tuple",
22678 NumElts * SEW / 8),
22682 SI->getModule(), IntrIds[Factor - 2], {VecTupTy, XLenTy});
22687 for (
unsigned i = 0; i < Factor; ++i)
22689 Intrinsic::riscv_tuple_insert, {VecTupTy, InVTy},
22690 {StoredVal, InterleaveValues[i], Builder.getInt32(i)});
22692 Builder.
CreateCall(VssegNFunc, {StoredVal, SI->getPointerOperand(), VL,
22693 ConstantInt::get(XLenTy,
Log2_64(SEW))});
22704 "Invalid call instruction for a KCFI check");
22706 MBBI->getOpcode()));
22709 Target.setIsRenamable(
false);
22717#define GET_REGISTER_MATCHER
22718#include "RISCVGenAsmMatcher.inc"
22724 if (Reg == RISCV::NoRegister)
22726 if (Reg == RISCV::NoRegister)
22738 const MDNode *NontemporalInfo =
I.getMetadata(LLVMContext::MD_nontemporal);
22740 if (NontemporalInfo ==
nullptr)
22748 int NontemporalLevel = 5;
22749 const MDNode *RISCVNontemporalInfo =
22750 I.getMetadata(
"riscv-nontemporal-domain");
22751 if (RISCVNontemporalInfo !=
nullptr)
22754 cast<ConstantAsMetadata>(RISCVNontemporalInfo->
getOperand(0))
22758 assert((1 <= NontemporalLevel && NontemporalLevel <= 5) &&
22759 "RISC-V target doesn't support this non-temporal domain.");
22761 NontemporalLevel -= 2;
22763 if (NontemporalLevel & 0b1)
22765 if (NontemporalLevel & 0b10)
22778 return TargetFlags;
22788 return isTypeLegal(VT) && Subtarget.hasStdExtZvbb();
22791 return Subtarget.hasStdExtZbb() &&
22802 if (Subtarget.hasStdExtZalasr()) {
22803 if (Subtarget.hasStdExtZtso()) {
22808 auto *LI = dyn_cast<LoadInst>(
I);
22809 auto *SI = dyn_cast<StoreInst>(
I);
22819 return isa<LoadInst>(
I) || isa<StoreInst>(
I);
22826 return isa<LoadInst>(
I) || isa<StoreInst>(
I);
22833 if (
Op == Instruction::Add ||
Op == Instruction::Sub ||
22834 Op == Instruction::And ||
Op == Instruction::Or ||
22835 Op == Instruction::Xor ||
Op == Instruction::InsertElement ||
22836 Op == Instruction::ShuffleVector ||
Op == Instruction::Load ||
22837 Op == Instruction::Freeze ||
Op == Instruction::Store)
22845 !isa<ReturnInst>(&Inst))
22848 if (
const AllocaInst *AI = dyn_cast<AllocaInst>(&Inst)) {
22849 if (AI->getAllocatedType()->isScalableTy())
22857RISCVTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
22865 if (!Subtarget.hasShortForwardBranchOpt())
22867 EVT VT =
N->getValueType(0);
22868 if (!(VT == MVT::i32 || (VT == MVT::i64 && Subtarget.
is64Bit())))
22872 if (Divisor.
sgt(2048) || Divisor.
slt(-2048))
22877bool RISCVTargetLowering::shouldFoldSelectWithSingleBitTest(
22878 EVT VT,
const APInt &AndMask)
const {
22879 if (Subtarget.hasStdExtZicond() || Subtarget.hasVendorXVentanaCondOps())
22880 return !Subtarget.hasStdExtZbs() && AndMask.
ugt(1024);
22884unsigned RISCVTargetLowering::getMinimumJumpTableEntries()
const {
22892 if (Subtarget.hasStdExtZicfilp()) {
22916std::pair<const TargetRegisterClass *, uint8_t>
22936#define GET_RISCVVIntrinsicsTable_IMPL
22937#include "RISCVGenSearchableTables.inc"
22952 Align StackAlign)
const {
22956 unsigned StackProbeSize =
22960 return StackProbeSize ? StackProbeSize : StackAlign.
value();
22975 cast<ConstantSDNode>(
Op.getOperand(2))->getMaybeAlignValue();
22977 EVT VT =
Op.getValueType();
22998 Register TargetReg =
MI.getOperand(1).getReg();
23001 bool IsRV64 = Subtarget.
is64Bit();
23009 MF.
insert(MBBInsertPoint, LoopTestMBB);
23011 MF.
insert(MBBInsertPoint, ExitMBB);
23027 TII->get(IsRV64 ? RISCV::SD : RISCV::SW))
23050 MI.eraseFromParent();
23052 return ExitMBB->
begin()->getParent();
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 tryWidenMaskForShuffle(SDValue Op, SelectionDAG &DAG)
static SDValue performSETCCCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
static SDValue convertToScalableVector(SelectionDAG &DAG, EVT VT, SDValue V)
static SDValue convertFromScalableVector(SelectionDAG &DAG, EVT VT, SDValue V)
#define NODE_NAME_CASE(node)
static bool isConstant(const MachineInstr &MI)
AMDGPU Register Bank Select
static bool isZeroOrAllOnes(SDValue N, bool AllOnes)
static SDValue combineSelectAndUseCommutative(SDNode *N, bool AllOnes, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp, TargetLowering::DAGCombinerInfo &DCI, bool AllOnes=false)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static MCRegister MatchRegisterAltName(StringRef Name)
Maps from the set of all alternative registernames to a register number.
Function Alias Analysis Results
static SDValue getTargetNode(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,...
static Align getPrefTypeAlign(EVT VT, SelectionDAG &DAG)
static SDValue customLegalizeToWOpWithSExt(SDNode *N, SelectionDAG &DAG)
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 performVSELECTCombine(SDNode *N, SelectionDAG &DAG)
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 getName(Value *V)
static constexpr Register SPReg
static StringRef getExtensionType(StringRef Ext)
static SDValue performCONCAT_VECTORSCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue SplitVectorReductionOp(SDValue Op, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static MachineBasicBlock * 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 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 SDValue performVP_TRUNCATECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isInterleaveShuffle(ArrayRef< int > Mask, MVT VT, int &EvenSrc, int &OddSrc, const RISCVSubtarget &Subtarget)
Is this shuffle interleaving contiguous elements from one vector into the even elements and contiguou...
static bool narrowIndex(SDValue &N, ISD::MemIndexType IndexType, SelectionDAG &DAG)
According to the property that indexed load/store instructions zero-extend their indices,...
static 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 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 lowerDisjointIndicesShuffle(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Given a shuffle where the indices are disjoint between the two sources, e.g.:
static SDValue combineVWADDSUBWSelect(SDNode *N, SelectionDAG &DAG)
static MachineBasicBlock * EmitLoweredCascadedSelect(MachineInstr &First, MachineInstr &Second, MachineBasicBlock *ThisMBB, const RISCVSubtarget &Subtarget)
static SDValue performINSERT_VECTOR_ELTCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue lowerFABSorFNEG(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerFMAXIMUM_FMINIMUM(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue SplitStrictFPVectorOp(SDValue Op, SelectionDAG &DAG)
static SDValue tryDemorganOfBooleanCondition(SDValue Cond, SelectionDAG &DAG)
static SDValue performMemPairCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue combineDeMorganOfBoolean(SDNode *N, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLEAsVSlidedown(const SDLoc &DL, MVT VT, SDValue V1, SDValue V2, ArrayRef< int > Mask, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
static 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 SDValue lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static cl::opt< unsigned > NumRepeatedDivisors(DEBUG_TYPE "-fp-repeated-divisors", cl::Hidden, cl::desc("Set the minimum number of repetitions of a divisor to allow " "transformation to multiplications by the reciprocal"), cl::init(2))
static SDValue foldSelectOfCTTZOrCTLZ(SDNode *N, SelectionDAG &DAG)
static SDValue lowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue foldBinOpIntoSelectIfProfitable(SDNode *BO, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue combineVectorMulToSraBitcast(SDNode *N, SelectionDAG &DAG)
static SDValue combineScalarCTPOPToVCPOP(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
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 bool isSpreadMask(ArrayRef< int > Mask, unsigned Factor, unsigned &Index)
static unsigned getRISCVVLOp(SDValue Op)
Get a RISC-V target specified VL op for a given SDNode.
static unsigned getVecReduceOpcode(unsigned Opc)
Given a binary operator, return the associative generic ISD::VECREDUCE_OP which corresponds to it.
static std::pair< SDValue, SDValue > getDefaultVLOps(uint64_t NumElts, MVT ContainerVT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isPromotedOpNeedingSplit(SDValue Op, const RISCVSubtarget &Subtarget)
static SDValue performFP_TO_INT_SATCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue lowerReductionSeq(unsigned RVVOpcode, MVT ResVT, SDValue StartValue, SDValue Vec, SDValue Mask, SDValue VL, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Helper to lower a reduction sequence of the form: scalar = reduce_op vec, scalar_start.
static SDValue performVP_REVERSECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerGetVectorLength(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::pair< SDValue, SDValue > getDefaultScalableVLOps(MVT VecVT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue getVLOperand(SDValue Op)
static SDValue performVECTOR_SHUFFLECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue performVP_STORECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static MachineBasicBlock * emitFROUND(MachineInstr &MI, MachineBasicBlock *MBB, const RISCVSubtarget &Subtarget)
static SDValue getLargeExternalSymbol(ExternalSymbolSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG)
static SDValue lowerCttzElts(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
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 getDeinterleaveShiftAndTrunc(const SDLoc &DL, MVT VT, SDValue Src, unsigned Factor, unsigned Index, SelectionDAG &DAG)
static SDValue combineBinOpOfZExt(SDNode *N, SelectionDAG &DAG)
static bool matchSelectAddSub(SDValue TrueVal, SDValue FalseVal, bool &SwapCC)
static 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 SDValue getSingleShuffleSrc(MVT VT, MVT ContainerVT, SDValue V1, SDValue V2)
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 lowerINT_TO_FP(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerVectorFTRUNC_FCEIL_FFLOOR_FROUND(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerFTRUNC_FCEIL_FFLOOR_FROUND(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::optional< VIDSequence > isSimpleVIDSequence(SDValue Op, unsigned EltSizeInBits)
static SDValue 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 lowerFP_TO_INT(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLEAsVSlideup(const SDLoc &DL, MVT VT, SDValue V1, SDValue V2, ArrayRef< int > Mask, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
static SDValue getVCIXISDNodeWCHAIN(SDValue &Op, SelectionDAG &DAG, unsigned Type)
static SDValue getLargeGlobalAddress(GlobalAddressSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG)
static MachineBasicBlock * emitReadCounterWidePseudo(MachineInstr &MI, MachineBasicBlock *BB)
static SDValue getWideningSpread(SDValue V, unsigned Factor, unsigned Index, const SDLoc &DL, SelectionDAG &DAG)
static cl::opt< bool > AllowSplatInVW_W(DEBUG_TYPE "-form-vw-w-with-splat", cl::Hidden, cl::desc("Allow the formation of VW_W operations (e.g., " "VWADD_W) with splat constants"), cl::init(false))
static SDValue unpackF64OnRV32DSoftABI(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const CCValAssign &HiVA, const SDLoc &DL)
static SDValue tryMemPairCombine(SelectionDAG &DAG, LSBaseSDNode *LSNode1, LSBaseSDNode *LSNode2, SDValue BasePtr, uint64_t Imm)
static std::tuple< unsigned, SDValue, SDValue > getRVVFPReductionOpAndOperands(SDValue Op, SelectionDAG &DAG, EVT EltVT, const RISCVSubtarget &Subtarget)
static SDValue performFP_TO_INTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue combineBinOpOfExtractToReduceTree(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Perform two related transforms whose purpose is to incrementally recognize an explode_vector followed...
static SDValue lowerBuildVectorViaPacking(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Double the element size of the build vector to reduce the number of vslide1down in the build vector c...
static SDValue performTRUNCATECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerBuildVectorViaDominantValues(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Try and optimize BUILD_VECTORs with "dominant values" - these are values which constitute a large pro...
static bool isCompressMask(ArrayRef< int > Mask)
static 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.
static unsigned getRISCVWOpcode(unsigned Opcode)
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static Type * getValueType(Value *V)
Returns the type of the given value/instruction V.
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.
@ USubCond
Subtract only if no unsigned overflow.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ UMax
*p = old >unsigned v ? old : v
@ UDecWrap
Decrement one until a minimum value or zero.
bool isFloatingPointOperation() const
BinOp getOperation() const
AtomicOrdering getOrdering() const
Returns the ordering constraint of this rmw instruction.
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 Attribute getWithAlignment(LLVMContext &Context, Align Alignment)
Return a uniquified Attribute object that has the specific alignment set.
static BaseIndexOffset match(const SDNode *N, const SelectionDAG &DAG)
Parses tree in N for base, index, offset addresses.
LLVM Basic Block Representation.
const Module * getModule() const
Return the module owning the function this basic block belongs to, or nullptr if the function does no...
bool test(unsigned Idx) const
bool all() const
all - Returns true if all bits are set.
CCState - This class holds information needed while lowering arguments and return values.
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
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.
void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
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.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
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.
const ValueT & at(const_arg_type_t< KeyT > Val) const
at - Return the entry for the specified key, or abort if no such entry exists.
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
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)
Class to represent function types.
Type * getParamType(unsigned i) const
Parameter type accessors.
Type * getReturnType() const
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
uint64_t getFnAttributeAsParsedInteger(StringRef Kind, uint64_t Default=0) const
For a string attribute Kind, parse attribute as an integer.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
AttributeList getAttributes() const
Return the attribute list for this Function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Argument * getArg(unsigned i) const
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Helper struct to store a base, index and offset that forms an address.
int64_t getOffset() const
bool hasExternalWeakLinkage() const
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) 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, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) 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 * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, 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.
Value * CreatePtrAdd(Value *Ptr, Value *Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
BasicBlock * GetInsertBlock() const
IntegerType * getInt64Ty()
Fetch the type representing a 64-bit integer.
Value * getAllOnesMask(ElementCount NumElts)
Return an all true boolean vector (mask) with NumElts lanes.
CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
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="")
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
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)
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.
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()
Type * getPointerOperandType() const
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
static constexpr LocationSize beforeOrAfterPointer()
Any location before or after the base pointer (but still within the underlying object).
Context object for machine code objects.
Base class for the full range of assembler expressions which are needed for parsing.
Instances of this class represent a single low-level machine instruction.
MCContext & getContext() const
Generic base class for all target subtargets.
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.
bool isRISCVVectorTuple() const
Return true if this is a RISCV vector tuple type where the runtime length is machine dependent.
uint64_t getScalarSizeInBits() const
MVT changeVectorElementType(MVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
bool bitsLE(MVT VT) const
Return true if this has no more bits than VT.
unsigned getVectorNumElements() const
static MVT getRISCVVectorTupleVT(unsigned Sz, unsigned NFields)
bool isVector() const
Return true if this is a vector value type.
bool isInteger() const
Return true if this is an integer or a vector integer type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
static MVT getScalableVectorVT(MVT VT, unsigned NumElements)
unsigned getRISCVVectorTupleNumFields() const
Given a RISC-V vector tuple type, return the num_fields.
MVT changeTypeToInteger()
Return the type converted to an equivalently sized integer or vector with integer element type.
static MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
bool bitsLT(MVT VT) const
Return true if this has less bits than VT.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
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.
DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any debug instructions.
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.
A RISCV-specific constant pool value.
static RISCVConstantPoolValue * Create(const GlobalValue *GV)
RISCVMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private RISCV-...
void setVarArgsFrameIndex(int Index)
int getVarArgsFrameIndex() const
void setVarArgsSaveSize(int Size)
void addSExt32Register(Register Reg)
RISCVABI::ABI getTargetABI() const
unsigned getMinimumJumpTableEntries() const
bool hasStdExtCOrZca() const
unsigned getMaxLMULForFixedLengthVectors() const
bool hasVInstructionsI64() const
bool hasVInstructionsF64() const
unsigned getMaxStoresPerMemcpy(bool OptSize) const
bool hasStdExtDOrZdinx() const
unsigned getMaxLoadsPerMemcmp(bool OptSize) const
bool hasStdExtZfhOrZhinx() const
unsigned getRealMinVLen() const
unsigned getMaxStoresPerMemset(bool OptSize) 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
unsigned getMaxStoresPerMemmove(bool OptSize) const
bool hasVInstructionsF16Minimal() const
unsigned getMaxGluedStoresPerMemcpy() const
bool hasConditionalMoveFusion() const
bool hasVInstructionsF16() const
unsigned getMaxBuildIntsCost() const
bool useCCMovInsn() const
Align getPrefLoopAlignment() const
bool hasVInstructions() const
bool isRegisterReservedByUser(Register i) const override
std::optional< unsigned > getRealVLen() const
bool hasOptimizedSegmentLoadStore(unsigned NF) 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
const RISCVFrameLowering * getFrameLowering() const override
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...
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.
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 lowerInterleaveIntrinsicToStore(StoreInst *SI, ArrayRef< Value * > InterleaveValues) const override
Lower an interleave intrinsic to a target specific store intrinsic.
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 shouldExtendTypeInLibCall(EVT Type) const override
Returns true if arguments should be extended in lib calls.
bool isLegalAddImmediate(int64_t Imm) const override
Return true if the specified immediate is legal add immediate, that is the target has add instruction...
bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const override
Returns true if arguments should be sign-extended in lib calls.
const MCExpr * LowerCustomJumpTableEntry(const MachineJumpTableInfo *MJTI, const MachineBasicBlock *MBB, unsigned uid, MCContext &Ctx) const override
InstructionCost getVRGatherVICost(MVT VT) const
Return the cost of a vrgather.vi (or vx) instruction for the type VT.
bool shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const override
Return true if it is beneficial to convert a load of a constant to just the constant itself.
bool targetShrinkDemandedConstant(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, TargetLoweringOpt &TLO) const override
bool shouldExpandBuildVectorWithShuffles(EVT VT, unsigned DefinedValues) const override
MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Return the register type for a given MVT, ensuring vectors are treated as a series of gpr sized integ...
bool decomposeMulByConstant(LLVMContext &Context, EVT VT, SDValue C) const override
Return true if it is profitable to transform an integer multiplication-by-constant into simpler opera...
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, LLVMContext &Context, const Type *RetTy) const override
This hook should be implemented to check whether the return values described by the Outs array can fi...
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
bool hasAndNotCompare(SDValue Y) const override
Return true if the target should transform: (X & Y) == Y —> (~X & Y) == 0 (X & Y) !...
bool shouldScalarizeBinop(SDValue VecOp) const override
Try to convert an extract element of a vector binary operation into an extract element followed by a ...
bool isDesirableToCommuteWithShift(const SDNode *N, CombineLevel Level) const override
Return true if it is profitable to move this shift by a constant amount through its operand,...
bool areTwoSDNodeTargetMMOFlagsMergeable(const MemSDNode &NodeX, const MemSDNode &NodeY) const override
Return true if it is valid to merge the TargetMMOFlags in two SDNodes.
bool hasBitTest(SDValue X, SDValue Y) const override
Return true if the target has a bit-test instruction: (X & (1 << Y)) ==/!= 0 This knowledge can be us...
static unsigned computeVLMAX(unsigned VectorBits, unsigned EltSize, unsigned MinSize)
bool shouldExpandCttzElements(EVT VT) const override
Return true if the @llvm.experimental.cttz.elts intrinsic should be expanded using generic code in Se...
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
Value * emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, AtomicCmpXchgInst *CI, Value *AlignedAddr, Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const override
Perform a masked cmpxchg using a target-specific intrinsic.
bool isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize) const override
Returns true if the target can instruction select the specified FP immediate natively.
InstructionCost getLMULCost(MVT VT) const
Return the cost of LMUL for linear operations.
unsigned getJumpTableEncoding() const override
Return the entry encoding for a jump table in the current function.
bool isMulAddWithConstProfitable(SDValue AddNode, SDValue ConstNode) const override
Return true if it may be profitable to transform (mul (add x, c1), c2) -> (add (mul x,...
InstructionCost getVSlideVICost(MVT VT) const
Return the cost of a vslidedown.vi or vslideup.vi instruction for the type VT.
bool fallBackToDAGISel(const Instruction &Inst) const override
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
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.
MachineBasicBlock * emitDynamicProbedAlloc(MachineInstr &MI, MachineBasicBlock *MBB) const
MachineMemOperand::Flags getTargetMMOFlags(const Instruction &I) const override
This callback is used to inspect load/store instructions and add target-specific MachineMemOperand fl...
SDValue computeVLMax(MVT VecVT, const SDLoc &DL, SelectionDAG &DAG) const
bool signExtendConstant(const ConstantInt *CI) const override
Return true if this constant should be sign extended when promoting to a larger type.
bool shouldTransformSignedTruncationCheck(EVT XVT, unsigned KeptBits) const override
Should we tranform the IR-optimal check for whether given truncation down into KeptBits would be trun...
bool shouldProduceAndByConstByHoistingConstFromShiftsLHSOfAnd(SDValue X, ConstantSDNode *XC, ConstantSDNode *CC, SDValue Y, unsigned OldShiftOpcode, unsigned NewShiftOpcode, SelectionDAG &DAG) const override
Given the pattern (X & (C l>>/<< Y)) ==/!= 0 return true if it should be transformed into: ((X <</l>>...
bool hasInlineStackProbe(const MachineFunction &MF) const override
True if stack clash protection is enabled for this functions.
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.
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)
int getLegalZfaFPImm(const APFloat &Imm, EVT VT) const
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
Lower the specified operand into the Ops vector.
bool splitValueIntoRegisterParts(SelectionDAG &DAG, const SDLoc &DL, SDValue Val, SDValue *Parts, unsigned NumParts, MVT PartVT, std::optional< CallingConv::ID > CC) const override
Target-specific splitting of values into parts that fit a register storing a legal type.
Instruction * emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Return the number of registers for a given MVT, ensuring vectors are treated as a series of gpr sized...
ConstraintType getConstraintType(StringRef Constraint) const override
getConstraintType - Given a constraint letter, return the type of constraint it is for this target.
MachineInstr * EmitKCFICheck(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator &MBBI, const TargetInstrInfo *TII) const override
bool 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 lowerDeinterleaveIntrinsicToLoad(LoadInst *LI, ArrayRef< Value * > DeinterleaveValues) const override
Lower a deinterleave intrinsic to a target specific load intrinsic.
unsigned getNumRegisters(LLVMContext &Context, EVT VT, std::optional< MVT > RegisterVT=std::nullopt) const override
Return the number of registers for a given MVT, for inline assembly.
bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
Returns true by value, base pointer and offset pointer and addressing mode by reference if this node ...
bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
Returns true by value, base pointer and offset pointer and addressing mode by reference if the node's...
SDValue joinRegisterPartsIntoValue(SelectionDAG &DAG, const SDLoc &DL, const SDValue *Parts, unsigned NumParts, MVT PartVT, EVT ValueVT, std::optional< CallingConv::ID > CC) const override
Target-specific combining of register parts into its original value.
bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const override
Return if the target supports combining a chain like:
bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override
Return true if sign-extension from FromTy to ToTy is cheaper than zero-extension.
bool isLegalStridedLoadStore(EVT DataType, Align Alignment) const
Return true if a stride load store of the given result type and alignment is legal.
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...
unsigned getStackProbeSize(const MachineFunction &MF, Align StackAlign) const
bool shouldInsertFencesForAtomic(const Instruction *I) const override
Whether AtomicExpandPass should automatically insert fences and reduce ordering for this atomic.
Wrapper class representing virtual and physical registers.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
ArrayRef< SDUse > ops() const
const APInt & getAsAPIntVal() const
Helper method returns the APInt value of a ConstantSDNode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
iterator_range< use_iterator > uses()
SDNodeFlags getFlags() const
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
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.
iterator_range< user_iterator > users()
op_iterator op_end() const
op_iterator op_begin() const
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
static ScalableVectorType * get(Type *ElementType, unsigned MinNumElts)
virtual bool isTargetStrictFPOpcode(unsigned Opcode) const
Returns true if a node with the given target-specific opcode has strict floating-point semantics.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
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 getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
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 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 getRegister(Register Reg, EVT VT)
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,...
SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
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
SDValue getStridedStoreVP(SDValue Chain, const SDLoc &DL, SDValue Val, SDValue Ptr, SDValue Offset, SDValue Stride, SDValue Mask, SDValue EVL, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
bool NewNodesMustHaveLegalTypes
When true, additional steps are taken to ensure that getConstant() and similar functions return DAG n...
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 getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
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
const SelectionDAGTargetInfo & getSelectionDAGInfo() 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.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
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 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 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 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 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 isSelectMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from its source vectors without lane crossings.
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 isDeInterleaveMaskOfFactor(ArrayRef< int > Mask, unsigned Factor, unsigned &Index)
Check if the mask is a DE-interleave mask of the given factor Factor like: <Index,...
static 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.
void push_back(const T &Elt)
pointer data()
Return a pointer to the vector's buffer, even if empty().
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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)
static StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
static TargetExtType * get(LLVMContext &Context, StringRef Name, ArrayRef< Type * > Types={}, ArrayRef< unsigned > Ints={})
Return a target extension type having the specified name and optional type and integer parameters.
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
TargetInstrInfo - Interface to description of machine instruction set.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
bool PredictableSelectIsExpensive
Tells the code generator that select is more expensive than a branch if the branch is usually predict...
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
unsigned MaxStoresPerMemcpyOptSize
Likewise for functions with the OptSize attribute.
MachineBasicBlock * emitPatchPoint(MachineInstr &MI, MachineBasicBlock *MBB) const
Replace/modify any TargetFrameIndex operands with a targte-dependent sequence of memory operands that...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
const TargetMachine & getTargetMachine() const
unsigned MaxLoadsPerMemcmp
Specify maximum number of load instructions per memcmp call.
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
unsigned MaxGluedStoresPerMemcpy
Specify max number of store instructions to glue in inlined memcpy.
virtual bool isZExtFree(Type *FromTy, Type *ToTy) const
Return true if any actual instruction that defines a value of type FromTy implicitly zero-extends the...
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
void setOperationPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
Convenience method to set an operation to Promote and specify the type in a single call.
unsigned getMinCmpXchgSizeInBits() const
Returns the size of the smallest cmpxchg or ll/sc instruction the backend supports.
virtual unsigned getNumRegisters(LLVMContext &Context, EVT VT, std::optional< MVT > RegisterVT=std::nullopt) const
Return the number of registers that this ValueType will eventually require.
void setIndexedLoadAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed load does or does not work with the specified type and indicate w...
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
virtual unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
bool isOperationCustom(unsigned Op, EVT VT) const
Return true if the operation uses custom lowering, regardless of whether the type is legal or not.
unsigned MaxStoresPerMemsetOptSize
Likewise for functions with the OptSize attribute.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
unsigned MaxStoresPerMemmove
Specify maximum number of store instructions per memmove call.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
virtual bool isTruncateFree(Type *FromTy, Type *ToTy) const
Return true if it's free to truncate a value of type FromTy to type ToTy.
unsigned MaxStoresPerMemmoveOptSize
Likewise for functions with the OptSize attribute.
virtual bool shouldFoldSelectWithSingleBitTest(EVT VT, const APInt &AndMask) const
virtual Value * getIRStackGuard(IRBuilderBase &IRB) const
If the target has a standard location for the stack protector guard, returns the address of that loca...
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
bool EnableExtLdPromotion
void setIndexedStoreAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed store does or does not work with the specified type and indicate ...
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void 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.
unsigned MaxStoresPerMemset
Specify maximum number of store instructions per memset call.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
unsigned MaxLoadsPerMemcmpOptSize
Likewise for functions with the OptSize attribute.
virtual bool isBinOp(unsigned Opcode) const
Return true if the node is a math/logic binary operator.
void setMinCmpXchgSizeInBits(unsigned SizeInBits)
Sets the minimum cmpxchg or ll/sc size supported by the backend.
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
void setCondCodeAction(ArrayRef< ISD::CondCode > CCs, MVT VT, LegalizeAction Action)
Indicate that the specified condition code is or isn't supported on the target and indicate what to d...
virtual std::pair< const TargetRegisterClass *, uint8_t > findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const
Return the largest legal super-reg register class of the register class for the specified type and it...
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
std::vector< ArgListEntry > ArgListTy
bool allowsMemoryAccessForAlignment(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
This function returns true if the memory access is aligned or if the target allows this specific unal...
unsigned MaxStoresPerMemcpy
Specify maximum number of store instructions per memcpy call.
bool isOperationLegalOrCustomOrPromote(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
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.
const Triple & getTargetTriple() const
bool useTLSDESC() const
Returns true if this target uses TLS Descriptors.
const MCSubtargetInfo * getMCSubtargetInfo() const
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
virtual TargetLoweringObjectFile * getObjFileLowering() const
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 bool isRegisterReservedByUser(Register R) const
virtual const TargetInstrInfo * getInstrInfo() const
Target - Wrapper for Target specific information.
bool isOSBinFormatCOFF() const
Tests whether the OS uses the COFF binary format.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
The instances of the Type class are immutable: once they are created, they are never changed.
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.
bool isTargetExtTy() const
Return true if this is a target extension type.
bool isScalableTy(SmallPtrSetImpl< const Type * > &Visited) const
Return true if this is a type whose size is a known multiple of vscale.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
static IntegerType * getInt8Ty(LLVMContext &C)
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 * 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.
unsigned getOperandNo() const
Return the operand # of this use in its User.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
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 bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
constexpr ScalarTy getFixedValue() const
static constexpr bool isKnownLE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
constexpr LeafTy multiplyCoefficientBy(ScalarTy RHS) const
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
constexpr bool isZero() const
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char 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.
@ INIT_TRAMPOLINE
INIT_TRAMPOLINE - This corresponds to the init_trampoline intrinsic.
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ 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...
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ UNDEF
UNDEF - An undefined node.
@ 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,...
@ FFREXP
FFREXP - frexp, extract fractional and exponent component of a floating-point value.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ VECTOR_COMPRESS
VECTOR_COMPRESS(Vec, Mask, Passthru) consecutively place vector elements based on mask e....
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ 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...
@ ADJUST_TRAMPOLINE
ADJUST_TRAMPOLINE - This corresponds to the adjust_trampoline intrinsic.
@ 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.
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 * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
@ Bitcast
Perform the operation on a different, but equivalently sized type.
@ TAIL_UNDISTURBED_MASK_UNDISTURBED
static VLMUL getLMul(uint64_t TSFlags)
static int getFRMOpNum(const MCInstrDesc &Desc)
static unsigned getSEWOpNum(const MCInstrDesc &Desc)
@ SplitF64
Turns a f64 into a pair of i32s.
@ 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
@ BuildPairF64
Turns a pair of i32s into an f64.
@ BuildGPRPair
Turn a pair of i<xlen>s into an even-odd register pair (untyped).
@ STRICT_VFROUND_NOEXCEPT_VL
@ SPLAT_VECTOR_SPLIT_I64_VL
@ SplitGPRPair
Turn an even-odd register pair (untyped) into a pair of i<xlen>s.
@ 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
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)
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)
uint32_t read32le(const void *P)
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
bool CC_RISCV_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State)
static const MachineMemOperand::Flags MONontemporalBit1
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
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,...
MCCodeEmitter * createRISCVMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
static const MachineMemOperand::Flags MONontemporalBit0
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
bool widenShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Try to transform a shuffle mask by replacing elements with the scaled index for an equivalent mask of...
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.
bool CC_RISCV_FastCC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed, bool IsRet, Type *OrigTy)
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.
auto drop_end(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the last N elements excluded.
AtomicOrdering
Atomic ordering for LLVM's memory model.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
void narrowShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Replace each shuffle mask index with the scaled sequential indices for an equivalent mask of narrowed...
@ 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.
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...
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
bool RISCVCCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed, bool IsRet, Type *OrigTy)
RISCVCCAssignFn - This target-specific function extends the default CCValAssign with additional infor...
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.
void processShuffleMasks(ArrayRef< int > Mask, unsigned NumOfSrcRegs, unsigned NumOfDestRegs, unsigned NumOfUsedRegs, function_ref< void()> NoInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned)> SingleInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned, bool)> ManyInputsAction)
Splits and processes shuffle mask depending on the number of input and output registers.
unsigned Log2(Align A)
Returns the log2 of the alignment.
bool CC_RISCV(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed, bool IsRet, Type *OrigTy)
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.
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
uint64_t getScalarStoreSize() const
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
bool isByteSized() const
Return true if the bit size is a multiple of 8.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
unsigned getRISCVVectorTupleNumFields() const
Given a RISCV vector tuple type, return the num_fields.
uint64_t getScalarSizeInBits() const
EVT getHalfSizedIntegerVT(LLVMContext &Context) const
Finds the smallest simple value type that is greater than or equal to half the width of this EVT.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
bool isRISCVVectorTuple() const
Return true if this is a vector value type.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isFixedLengthVector() const
EVT getRoundIntegerType(LLVMContext &Context) const
Rounds the bit-width of the given integer EVT up to the nearest power of two (and at least to eight),...
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
bool bitsGE(EVT VT) const
Return true if this has no less bits than VT.
Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
EVT changeVectorElementType(EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
bool isInteger() const
Return true if this is an integer or a vector integer type.
static 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,...
static MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
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.
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)