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()) {
412 if (!Subtarget.hasVendorXTHeadCondMov())
415 static const unsigned FPLegalNodeTypes[] = {
429 static const unsigned FPOpToExpand[] = {
433 static const unsigned FPRndMode[] = {
437 static const unsigned ZfhminZfbfminPromoteOps[] = {
448 if (Subtarget.hasStdExtZfbfmin()) {
471 if (Subtarget.hasStdExtZfa())
498 Subtarget.hasStdExtZfh() && Subtarget.hasStdExtZfa() ?
Legal :
Promote);
540 if (Subtarget.hasStdExtZfa()) {
558 if (Subtarget.hasStdExtZfa()) {
640 if (Subtarget.hasStdExtZicbop()) {
644 if (Subtarget.hasStdExtA()) {
646 if (Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas())
650 }
else if (Subtarget.hasForcedAtomics()) {
674 {MVT::i8, MVT::i16},
Custom);
685 static const unsigned IntegerVPOps[] = {
686 ISD::VP_ADD, ISD::VP_SUB, ISD::VP_MUL,
687 ISD::VP_SDIV, ISD::VP_UDIV, ISD::VP_SREM,
688 ISD::VP_UREM, ISD::VP_AND, ISD::VP_OR,
689 ISD::VP_XOR, ISD::VP_SRA, ISD::VP_SRL,
690 ISD::VP_SHL, ISD::VP_REDUCE_ADD, ISD::VP_REDUCE_AND,
691 ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR, ISD::VP_REDUCE_SMAX,
692 ISD::VP_REDUCE_SMIN, ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN,
693 ISD::VP_MERGE, ISD::VP_SELECT, ISD::VP_FP_TO_SINT,
694 ISD::VP_FP_TO_UINT, ISD::VP_SETCC, ISD::VP_SIGN_EXTEND,
695 ISD::VP_ZERO_EXTEND, ISD::VP_TRUNCATE, ISD::VP_SMIN,
696 ISD::VP_SMAX, ISD::VP_UMIN, ISD::VP_UMAX,
697 ISD::VP_ABS, ISD::EXPERIMENTAL_VP_REVERSE, ISD::EXPERIMENTAL_VP_SPLICE,
698 ISD::VP_SADDSAT, ISD::VP_UADDSAT, ISD::VP_SSUBSAT,
699 ISD::VP_USUBSAT, ISD::VP_CTTZ_ELTS, ISD::VP_CTTZ_ELTS_ZERO_UNDEF,
700 ISD::EXPERIMENTAL_VP_SPLAT};
702 static const unsigned FloatingPointVPOps[] = {
703 ISD::VP_FADD, ISD::VP_FSUB, ISD::VP_FMUL,
704 ISD::VP_FDIV, ISD::VP_FNEG, ISD::VP_FABS,
705 ISD::VP_FMA, ISD::VP_REDUCE_FADD, ISD::VP_REDUCE_SEQ_FADD,
706 ISD::VP_REDUCE_FMIN, ISD::VP_REDUCE_FMAX, ISD::VP_MERGE,
707 ISD::VP_SELECT, ISD::VP_SINT_TO_FP, ISD::VP_UINT_TO_FP,
708 ISD::VP_SETCC, ISD::VP_FP_ROUND, ISD::VP_FP_EXTEND,
709 ISD::VP_SQRT, ISD::VP_FMINNUM, ISD::VP_FMAXNUM,
710 ISD::VP_FCEIL, ISD::VP_FFLOOR, ISD::VP_FROUND,
711 ISD::VP_FROUNDEVEN, ISD::VP_FCOPYSIGN, ISD::VP_FROUNDTOZERO,
712 ISD::VP_FRINT, ISD::VP_FNEARBYINT, ISD::VP_IS_FPCLASS,
713 ISD::VP_FMINIMUM, ISD::VP_FMAXIMUM, ISD::VP_LRINT,
714 ISD::VP_LLRINT, ISD::EXPERIMENTAL_VP_REVERSE,
715 ISD::EXPERIMENTAL_VP_SPLICE, ISD::VP_REDUCE_FMINIMUM,
716 ISD::VP_REDUCE_FMAXIMUM, ISD::EXPERIMENTAL_VP_SPLAT};
718 static const unsigned IntegerVecReduceOps[] = {
723 static const unsigned FloatingPointVecReduceOps[] = {
727 static const unsigned FloatingPointLibCallOps[] = {
740 ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR,
741 ISD::VP_REDUCE_SMAX, ISD::VP_REDUCE_SMIN,
742 ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN},
746 for (
MVT VT : BoolVecVTs) {
776 {ISD::VP_REDUCE_AND, ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR}, VT,
800 ISD::VP_TRUNCATE, ISD::VP_SETCC},
816 for (
MVT VT : IntVecVTs) {
827 if (VT.getVectorElementType() == MVT::i64 && !Subtarget.hasStdExtV())
877 {ISD::VP_LOAD, ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
878 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER, ISD::VP_SCATTER},
902 if (Subtarget.hasStdExtZvkb()) {
910 if (Subtarget.hasStdExtZvbb()) {
914 ISD::VP_CTTZ_ZERO_UNDEF, ISD::VP_CTPOP},
920 ISD::VP_CTTZ_ZERO_UNDEF, ISD::VP_CTPOP},
929 ISD::VP_CTLZ_ZERO_UNDEF, ISD::VP_CTTZ_ZERO_UNDEF},
937 for (
MVT VT : VecTupleVTs) {
958 static const unsigned ZvfhminZvfbfminPromoteOps[] = {
968 static const unsigned ZvfhminZvfbfminPromoteVPOps[] = {
983 ISD::VP_FROUNDTOZERO,
989 ISD::VP_REDUCE_FMINIMUM,
990 ISD::VP_REDUCE_FMAXIMUM};
993 const auto SetCommonVFPActions = [&](
MVT VT) {
1028 {ISD::VP_LOAD, ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1029 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER, ISD::VP_SCATTER},
1062 const auto SetCommonVFPExtLoadTruncStoreActions =
1064 for (
auto SmallVT : SmallerVTs) {
1072 const auto SetCommonPromoteToF32Actions = [&](
MVT VT) {
1097 ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1098 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1121 for (
MVT VT : F16VecVTs) {
1124 SetCommonVFPActions(VT);
1127 for (
MVT VT : F16VecVTs) {
1130 SetCommonPromoteToF32Actions(VT);
1135 for (
MVT VT : BF16VecVTs) {
1138 SetCommonPromoteToF32Actions(VT);
1143 for (
MVT VT : F32VecVTs) {
1146 SetCommonVFPActions(VT);
1147 SetCommonVFPExtLoadTruncStoreActions(VT, F16VecVTs);
1148 SetCommonVFPExtLoadTruncStoreActions(VT, BF16VecVTs);
1153 for (
MVT VT : F64VecVTs) {
1156 SetCommonVFPActions(VT);
1157 SetCommonVFPExtLoadTruncStoreActions(VT, F16VecVTs);
1158 SetCommonVFPExtLoadTruncStoreActions(VT, BF16VecVTs);
1159 SetCommonVFPExtLoadTruncStoreActions(VT, F32VecVTs);
1165 if (!useRVVForFixedLengthVectorVT(VT))
1211 {ISD::VP_REDUCE_AND, ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR}, VT,
1238 ISD::VP_SETCC, ISD::VP_TRUNCATE},
1262 ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1263 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1300 if (Subtarget.hasStdExtZvkb())
1303 if (Subtarget.hasStdExtZvbb()) {
1327 if (!useRVVForFixedLengthVectorVT(VT))
1348 ISD::VP_SCATTER, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1349 ISD::EXPERIMENTAL_VP_STRIDED_STORE},
1365 if (Subtarget.hasStdExtZfhmin()) {
1389 if (Subtarget.hasStdExtZfbfmin()) {
1449 if (Subtarget.hasStdExtZfbfmin())
1458 if (Subtarget.hasStdExtA())
1461 if (Subtarget.hasForcedAtomics()) {
1471 if (Subtarget.hasVendorXTHeadMemIdx()) {
1487 if (Subtarget.hasVendorXCVmem() && !Subtarget.
is64Bit()) {
1513 if (Subtarget.hasStdExtZbb())
1516 if ((Subtarget.hasStdExtZbs() && Subtarget.
is64Bit()) ||
1520 if (Subtarget.hasStdExtZbkb())
1533 ISD::VP_STORE, ISD::EXPERIMENTAL_VP_REVERSE,
1539 if (Subtarget.hasVendorXTHeadMemPair())
1582MVT RISCVTargetLowering::getVPExplicitVectorLengthTy()
const {
1587bool RISCVTargetLowering::shouldExpandGetVectorLength(
EVT TripCountVT,
1589 bool IsScalable)
const {
1596 if (TripCountVT != MVT::i32 && TripCountVT != Subtarget.
getXLenVT())
1621 unsigned Intrinsic)
const {
1622 auto &
DL =
I.getDataLayout();
1624 auto SetRVVLoadStoreInfo = [&](
unsigned PtrOp,
bool IsStore,
1625 bool IsUnitStrided,
bool UsePtrVal =
false) {
1630 Info.ptrVal =
I.getArgOperand(PtrOp);
1632 Info.fallbackAddressSpace =
1633 I.getArgOperand(PtrOp)->getType()->getPointerAddressSpace();
1637 MemTy =
I.getArgOperand(0)->getType();
1640 MemTy =
I.getType();
1650 if (cast<TargetExtType>(MemTy)->
getName() ==
"riscv.vector.tuple")
1653 1 << cast<ConstantInt>(
I.getArgOperand(
I.arg_size() - 1))
1655 Info.align =
DL.getABITypeAlign(MemTy);
1665 if (
I.hasMetadata(LLVMContext::MD_nontemporal))
1669 switch (Intrinsic) {
1672 case Intrinsic::riscv_masked_atomicrmw_xchg_i32:
1673 case Intrinsic::riscv_masked_atomicrmw_add_i32:
1674 case Intrinsic::riscv_masked_atomicrmw_sub_i32:
1675 case Intrinsic::riscv_masked_atomicrmw_nand_i32:
1676 case Intrinsic::riscv_masked_atomicrmw_max_i32:
1677 case Intrinsic::riscv_masked_atomicrmw_min_i32:
1678 case Intrinsic::riscv_masked_atomicrmw_umax_i32:
1679 case Intrinsic::riscv_masked_atomicrmw_umin_i32:
1680 case Intrinsic::riscv_masked_cmpxchg_i32:
1682 Info.memVT = MVT::i32;
1683 Info.ptrVal =
I.getArgOperand(0);
1689 case Intrinsic::riscv_seg2_load:
1690 case Intrinsic::riscv_seg3_load:
1691 case Intrinsic::riscv_seg4_load:
1692 case Intrinsic::riscv_seg5_load:
1693 case Intrinsic::riscv_seg6_load:
1694 case Intrinsic::riscv_seg7_load:
1695 case Intrinsic::riscv_seg8_load:
1696 return SetRVVLoadStoreInfo( 0,
false,
1698 case Intrinsic::riscv_seg2_store:
1699 case Intrinsic::riscv_seg3_store:
1700 case Intrinsic::riscv_seg4_store:
1701 case Intrinsic::riscv_seg5_store:
1702 case Intrinsic::riscv_seg6_store:
1703 case Intrinsic::riscv_seg7_store:
1704 case Intrinsic::riscv_seg8_store:
1706 return SetRVVLoadStoreInfo(
I.arg_size() - 2,
1709 case Intrinsic::riscv_vle:
1710 case Intrinsic::riscv_vle_mask:
1711 case Intrinsic::riscv_vleff:
1712 case Intrinsic::riscv_vleff_mask:
1713 return SetRVVLoadStoreInfo( 1,
1717 case Intrinsic::riscv_vse:
1718 case Intrinsic::riscv_vse_mask:
1719 return SetRVVLoadStoreInfo( 1,
1723 case Intrinsic::riscv_vlse:
1724 case Intrinsic::riscv_vlse_mask:
1725 case Intrinsic::riscv_vloxei:
1726 case Intrinsic::riscv_vloxei_mask:
1727 case Intrinsic::riscv_vluxei:
1728 case Intrinsic::riscv_vluxei_mask:
1729 return SetRVVLoadStoreInfo( 1,
1732 case Intrinsic::riscv_vsse:
1733 case Intrinsic::riscv_vsse_mask:
1734 case Intrinsic::riscv_vsoxei:
1735 case Intrinsic::riscv_vsoxei_mask:
1736 case Intrinsic::riscv_vsuxei:
1737 case Intrinsic::riscv_vsuxei_mask:
1738 return SetRVVLoadStoreInfo( 1,
1741 case Intrinsic::riscv_vlseg2:
1742 case Intrinsic::riscv_vlseg3:
1743 case Intrinsic::riscv_vlseg4:
1744 case Intrinsic::riscv_vlseg5:
1745 case Intrinsic::riscv_vlseg6:
1746 case Intrinsic::riscv_vlseg7:
1747 case Intrinsic::riscv_vlseg8:
1748 case Intrinsic::riscv_vlseg2ff:
1749 case Intrinsic::riscv_vlseg3ff:
1750 case Intrinsic::riscv_vlseg4ff:
1751 case Intrinsic::riscv_vlseg5ff:
1752 case Intrinsic::riscv_vlseg6ff:
1753 case Intrinsic::riscv_vlseg7ff:
1754 case Intrinsic::riscv_vlseg8ff:
1755 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1758 case Intrinsic::riscv_vlseg2_mask:
1759 case Intrinsic::riscv_vlseg3_mask:
1760 case Intrinsic::riscv_vlseg4_mask:
1761 case Intrinsic::riscv_vlseg5_mask:
1762 case Intrinsic::riscv_vlseg6_mask:
1763 case Intrinsic::riscv_vlseg7_mask:
1764 case Intrinsic::riscv_vlseg8_mask:
1765 case Intrinsic::riscv_vlseg2ff_mask:
1766 case Intrinsic::riscv_vlseg3ff_mask:
1767 case Intrinsic::riscv_vlseg4ff_mask:
1768 case Intrinsic::riscv_vlseg5ff_mask:
1769 case Intrinsic::riscv_vlseg6ff_mask:
1770 case Intrinsic::riscv_vlseg7ff_mask:
1771 case Intrinsic::riscv_vlseg8ff_mask:
1772 return SetRVVLoadStoreInfo(
I.arg_size() - 5,
1775 case Intrinsic::riscv_vlsseg2:
1776 case Intrinsic::riscv_vlsseg3:
1777 case Intrinsic::riscv_vlsseg4:
1778 case Intrinsic::riscv_vlsseg5:
1779 case Intrinsic::riscv_vlsseg6:
1780 case Intrinsic::riscv_vlsseg7:
1781 case Intrinsic::riscv_vlsseg8:
1782 case Intrinsic::riscv_vloxseg2:
1783 case Intrinsic::riscv_vloxseg3:
1784 case Intrinsic::riscv_vloxseg4:
1785 case Intrinsic::riscv_vloxseg5:
1786 case Intrinsic::riscv_vloxseg6:
1787 case Intrinsic::riscv_vloxseg7:
1788 case Intrinsic::riscv_vloxseg8:
1789 case Intrinsic::riscv_vluxseg2:
1790 case Intrinsic::riscv_vluxseg3:
1791 case Intrinsic::riscv_vluxseg4:
1792 case Intrinsic::riscv_vluxseg5:
1793 case Intrinsic::riscv_vluxseg6:
1794 case Intrinsic::riscv_vluxseg7:
1795 case Intrinsic::riscv_vluxseg8:
1796 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
1799 case Intrinsic::riscv_vlsseg2_mask:
1800 case Intrinsic::riscv_vlsseg3_mask:
1801 case Intrinsic::riscv_vlsseg4_mask:
1802 case Intrinsic::riscv_vlsseg5_mask:
1803 case Intrinsic::riscv_vlsseg6_mask:
1804 case Intrinsic::riscv_vlsseg7_mask:
1805 case Intrinsic::riscv_vlsseg8_mask:
1806 case Intrinsic::riscv_vloxseg2_mask:
1807 case Intrinsic::riscv_vloxseg3_mask:
1808 case Intrinsic::riscv_vloxseg4_mask:
1809 case Intrinsic::riscv_vloxseg5_mask:
1810 case Intrinsic::riscv_vloxseg6_mask:
1811 case Intrinsic::riscv_vloxseg7_mask:
1812 case Intrinsic::riscv_vloxseg8_mask:
1813 case Intrinsic::riscv_vluxseg2_mask:
1814 case Intrinsic::riscv_vluxseg3_mask:
1815 case Intrinsic::riscv_vluxseg4_mask:
1816 case Intrinsic::riscv_vluxseg5_mask:
1817 case Intrinsic::riscv_vluxseg6_mask:
1818 case Intrinsic::riscv_vluxseg7_mask:
1819 case Intrinsic::riscv_vluxseg8_mask:
1820 return SetRVVLoadStoreInfo(
I.arg_size() - 6,
1823 case Intrinsic::riscv_vsseg2:
1824 case Intrinsic::riscv_vsseg3:
1825 case Intrinsic::riscv_vsseg4:
1826 case Intrinsic::riscv_vsseg5:
1827 case Intrinsic::riscv_vsseg6:
1828 case Intrinsic::riscv_vsseg7:
1829 case Intrinsic::riscv_vsseg8:
1830 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1833 case Intrinsic::riscv_vsseg2_mask:
1834 case Intrinsic::riscv_vsseg3_mask:
1835 case Intrinsic::riscv_vsseg4_mask:
1836 case Intrinsic::riscv_vsseg5_mask:
1837 case Intrinsic::riscv_vsseg6_mask:
1838 case Intrinsic::riscv_vsseg7_mask:
1839 case Intrinsic::riscv_vsseg8_mask:
1840 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
1843 case Intrinsic::riscv_vssseg2:
1844 case Intrinsic::riscv_vssseg3:
1845 case Intrinsic::riscv_vssseg4:
1846 case Intrinsic::riscv_vssseg5:
1847 case Intrinsic::riscv_vssseg6:
1848 case Intrinsic::riscv_vssseg7:
1849 case Intrinsic::riscv_vssseg8:
1850 case Intrinsic::riscv_vsoxseg2:
1851 case Intrinsic::riscv_vsoxseg3:
1852 case Intrinsic::riscv_vsoxseg4:
1853 case Intrinsic::riscv_vsoxseg5:
1854 case Intrinsic::riscv_vsoxseg6:
1855 case Intrinsic::riscv_vsoxseg7:
1856 case Intrinsic::riscv_vsoxseg8:
1857 case Intrinsic::riscv_vsuxseg2:
1858 case Intrinsic::riscv_vsuxseg3:
1859 case Intrinsic::riscv_vsuxseg4:
1860 case Intrinsic::riscv_vsuxseg5:
1861 case Intrinsic::riscv_vsuxseg6:
1862 case Intrinsic::riscv_vsuxseg7:
1863 case Intrinsic::riscv_vsuxseg8:
1864 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
1867 case Intrinsic::riscv_vssseg2_mask:
1868 case Intrinsic::riscv_vssseg3_mask:
1869 case Intrinsic::riscv_vssseg4_mask:
1870 case Intrinsic::riscv_vssseg5_mask:
1871 case Intrinsic::riscv_vssseg6_mask:
1872 case Intrinsic::riscv_vssseg7_mask:
1873 case Intrinsic::riscv_vssseg8_mask:
1874 case Intrinsic::riscv_vsoxseg2_mask:
1875 case Intrinsic::riscv_vsoxseg3_mask:
1876 case Intrinsic::riscv_vsoxseg4_mask:
1877 case Intrinsic::riscv_vsoxseg5_mask:
1878 case Intrinsic::riscv_vsoxseg6_mask:
1879 case Intrinsic::riscv_vsoxseg7_mask:
1880 case Intrinsic::riscv_vsoxseg8_mask:
1881 case Intrinsic::riscv_vsuxseg2_mask:
1882 case Intrinsic::riscv_vsuxseg3_mask:
1883 case Intrinsic::riscv_vsuxseg4_mask:
1884 case Intrinsic::riscv_vsuxseg5_mask:
1885 case Intrinsic::riscv_vsuxseg6_mask:
1886 case Intrinsic::riscv_vsuxseg7_mask:
1887 case Intrinsic::riscv_vsuxseg8_mask:
1888 return SetRVVLoadStoreInfo(
I.arg_size() - 5,
1929 return isInt<12>(Imm);
1933 return isInt<12>(Imm);
1946 return (SrcBits == 64 && DestBits == 32);
1957 return (SrcBits == 64 && DestBits == 32);
1968 if (SrcBits == DestBits * 2) {
1979 if (
auto *LD = dyn_cast<LoadSDNode>(Val)) {
1980 EVT MemVT = LD->getMemoryVT();
1981 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
1991 return Subtarget.
is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
1999 return Subtarget.hasStdExtZbb() ||
2000 (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit());
2004 return Subtarget.hasStdExtZbb() || Subtarget.hasVendorXTHeadBb() ||
2005 (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit());
2016 if (!Subtarget.hasStdExtZbs() && !Subtarget.hasVendorXTHeadBs())
2021 return !Mask->getValue().isSignedIntN(12) && Mask->getValue().isPowerOf2();
2025 EVT VT =
Y.getValueType();
2031 return (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
2032 (!isa<ConstantSDNode>(
Y) || cast<ConstantSDNode>(
Y)->isOpaque());
2037 if (Subtarget.hasStdExtZbs())
2038 return X.getValueType().isScalarInteger();
2039 auto *
C = dyn_cast<ConstantSDNode>(
Y);
2041 if (Subtarget.hasVendorXTHeadBs())
2042 return C !=
nullptr;
2044 return C &&
C->getAPIntValue().ule(10);
2064 if (BitSize > Subtarget.
getXLen())
2068 int64_t Val = Imm.getSExtValue();
2076 if (!Subtarget.enableUnalignedScalarMem())
2092 unsigned OldShiftOpcode,
unsigned NewShiftOpcode,
2099 if (XC && OldShiftOpcode ==
ISD::SRL && XC->isOne())
2103 if (NewShiftOpcode ==
ISD::SRL &&
CC->isOne())
2147 if (!Subtarget.hasStdExtZfa())
2150 bool IsSupportedVT =
false;
2151 if (VT == MVT::f16) {
2152 IsSupportedVT = Subtarget.hasStdExtZfh() || Subtarget.hasStdExtZvfh();
2153 }
else if (VT == MVT::f32) {
2154 IsSupportedVT =
true;
2155 }
else if (VT == MVT::f64) {
2156 assert(Subtarget.hasStdExtD() &&
"Expect D extension");
2157 IsSupportedVT =
true;
2167 bool ForCodeSize)
const {
2168 bool IsLegalVT =
false;
2171 else if (VT == MVT::f32)
2173 else if (VT == MVT::f64)
2175 else if (VT == MVT::bf16)
2176 IsLegalVT = Subtarget.hasStdExtZfbfmin();
2188 return Imm.isZero();
2192 if (Imm.isNegZero())
2197 const int FmvCost = Subtarget.hasStdExtZfinx() ? 0 : 1;
2200 Subtarget.
getXLen(), Subtarget);
2206 unsigned Index)
const {
2219 if (EltVT == MVT::i1)
2232 if (Index + ResElts <= MinVLMAX && Index < 31)
2241 return (ResElts * 2) == SrcElts && (Index == 0 || Index == ResElts);
2260 std::optional<MVT> RegisterVT)
const {
2262 if (VT == (Subtarget.
is64Bit() ? MVT::i128 : MVT::i64) && RegisterVT &&
2263 *RegisterVT == MVT::Untyped)
2283 unsigned &NumIntermediates,
MVT &RegisterVT)
const {
2285 Context,
CC, VT, IntermediateVT, NumIntermediates, RegisterVT);
2300 isa<ConstantSDNode>(
LHS.getOperand(1))) {
2306 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
2319 if (
auto *RHSC = dyn_cast<ConstantSDNode>(
RHS)) {
2320 int64_t
C = RHSC->getSExtValue();
2358 if (VT.
SimpleTy >= MVT::riscv_nxv1i8x2 &&
2359 VT.
SimpleTy <= MVT::riscv_nxv1i8x8)
2361 if (VT.
SimpleTy >= MVT::riscv_nxv2i8x2 &&
2362 VT.
SimpleTy <= MVT::riscv_nxv2i8x8)
2364 if (VT.
SimpleTy >= MVT::riscv_nxv4i8x2 &&
2365 VT.
SimpleTy <= MVT::riscv_nxv4i8x8)
2367 if (VT.
SimpleTy >= MVT::riscv_nxv8i8x2 &&
2368 VT.
SimpleTy <= MVT::riscv_nxv8i8x8)
2370 if (VT.
SimpleTy >= MVT::riscv_nxv16i8x2 &&
2371 VT.
SimpleTy <= MVT::riscv_nxv16i8x4)
2373 if (VT.
SimpleTy == MVT::riscv_nxv32i8x2)
2383 switch (KnownSize) {
2411 return RISCV::VRRegClassID;
2413 return RISCV::VRM2RegClassID;
2415 return RISCV::VRM4RegClassID;
2417 return RISCV::VRM8RegClassID;
2427 static_assert(RISCV::sub_vrm1_7 == RISCV::sub_vrm1_0 + 7,
2428 "Unexpected subreg numbering");
2429 return RISCV::sub_vrm1_0 + Index;
2432 static_assert(RISCV::sub_vrm2_3 == RISCV::sub_vrm2_0 + 3,
2433 "Unexpected subreg numbering");
2434 return RISCV::sub_vrm2_0 + Index;
2437 static_assert(RISCV::sub_vrm4_1 == RISCV::sub_vrm4_0 + 1,
2438 "Unexpected subreg numbering");
2439 return RISCV::sub_vrm4_0 + Index;
2447 unsigned RegsPerField =
2450 switch (RegsPerField) {
2453 return RISCV::VRN2M1RegClassID;
2455 return RISCV::VRN3M1RegClassID;
2457 return RISCV::VRN4M1RegClassID;
2459 return RISCV::VRN5M1RegClassID;
2461 return RISCV::VRN6M1RegClassID;
2463 return RISCV::VRN7M1RegClassID;
2465 return RISCV::VRN8M1RegClassID;
2469 return RISCV::VRN2M2RegClassID;
2471 return RISCV::VRN3M2RegClassID;
2473 return RISCV::VRN4M2RegClassID;
2477 return RISCV::VRN2M4RegClassID;
2485 return RISCV::VRRegClassID;
2494std::pair<unsigned, unsigned>
2496 MVT VecVT,
MVT SubVecVT,
unsigned InsertExtractIdx,
2498 static_assert((RISCV::VRM8RegClassID > RISCV::VRM4RegClassID &&
2499 RISCV::VRM4RegClassID > RISCV::VRM2RegClassID &&
2500 RISCV::VRM2RegClassID > RISCV::VRRegClassID),
2501 "Register classes not ordered");
2508 if (VecRegClassID == SubRegClassID)
2509 return {RISCV::NoSubRegister, 0};
2512 "Only allow scalable vector subvector.");
2514 "Invalid vector tuple insert/extract for vector and subvector with "
2525 unsigned SubRegIdx = RISCV::NoSubRegister;
2526 for (
const unsigned RCID :
2527 {RISCV::VRM4RegClassID, RISCV::VRM2RegClassID, RISCV::VRRegClassID})
2528 if (VecRegClassID > RCID && SubRegClassID <= RCID) {
2532 SubRegIdx =
TRI->composeSubRegIndices(SubRegIdx,
2537 return {SubRegIdx, InsertExtractIdx};
2542bool RISCVTargetLowering::mergeStoresAfterLegalization(
EVT VT)
const {
2573unsigned RISCVTargetLowering::combineRepeatedFPDivisors()
const {
2580 "Unexpected opcode");
2582 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
2584 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
2587 return Op.getOperand(
II->VLOperand + 1 + HasChain);
2661bool RISCVTargetLowering::useRVVForFixedLengthVectorVT(
MVT VT)
const {
2662 return ::useRVVForFixedLengthVectorVT(VT, Subtarget);
2671 "Expected legal fixed length vector!");
2674 unsigned MaxELen = Subtarget.
getELen();
2708 return ::getContainerForFixedLengthVector(*
this, VT,
getSubtarget());
2715 "Expected to convert into a scalable vector!");
2716 assert(V.getValueType().isFixedLengthVector() &&
2717 "Expected a fixed length vector operand!");
2727 "Expected to convert into a fixed length vector!");
2728 assert(V.getValueType().isScalableVector() &&
2729 "Expected a scalable vector operand!");
2752static std::pair<SDValue, SDValue>
2761static std::pair<SDValue, SDValue>
2774static std::pair<SDValue, SDValue>
2791std::pair<unsigned, unsigned>
2807 return std::make_pair(MinVLMAX, MaxVLMAX);
2819 EVT VT,
unsigned DefinedValues)
const {
2833 std::tie(LMul, Fractional) =
2836 Cost = LMul <= DLenFactor ? (DLenFactor / LMul) : 1;
2838 Cost = (LMul * DLenFactor);
2881 Op.getValueType() == MVT::bf16) {
2882 bool IsStrict =
Op->isStrictFPOpcode();
2887 {Op.getOperand(0), Op.getOperand(1)});
2889 {
Op.getValueType(), MVT::Other},
2895 DAG.
getNode(
Op.getOpcode(),
DL, MVT::f32,
Op.getOperand(0)),
2910 MVT DstVT =
Op.getSimpleValueType();
2911 EVT SatVT = cast<VTSDNode>(
Op.getOperand(1))->getVT();
2919 Src.getValueType() == MVT::bf16) {
2926 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
2934 Opc,
DL, DstVT, Src,
2948 MVT SrcVT = Src.getSimpleValueType();
2954 if (SatVT != DstEltVT)
2957 MVT DstContainerVT = DstVT;
2958 MVT SrcContainerVT = SrcVT;
2964 "Expected same element count");
2973 {Src, Src, DAG.getCondCode(ISD::SETNE),
2974 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
2978 if (DstEltSize > (2 * SrcEltSize)) {
2984 MVT CvtContainerVT = DstContainerVT;
2985 MVT CvtEltVT = DstEltVT;
2986 if (SrcEltSize > (2 * DstEltSize)) {
2995 while (CvtContainerVT != DstContainerVT) {
3001 Res = DAG.
getNode(ClipOpc,
DL, CvtContainerVT, Res, Mask, VL);
3008 Res, DAG.
getUNDEF(DstContainerVT), VL);
3018 bool IsStrict =
Op->isStrictFPOpcode();
3019 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
3029 {
Op.getOperand(0), SrcVal});
3030 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
3031 {Ext.getValue(1), Ext.getValue(0)});
3045 case ISD::VP_FROUNDEVEN:
3049 case ISD::VP_FROUNDTOZERO:
3053 case ISD::VP_FFLOOR:
3061 case ISD::VP_FROUND:
3078 MVT VT =
Op.getSimpleValueType();
3085 MVT ContainerVT = VT;
3092 if (
Op->isVPOpcode()) {
3093 Mask =
Op.getOperand(1);
3097 VL =
Op.getOperand(2);
3119 DAG.
getUNDEF(ContainerVT), MaxValNode, VL);
3133 switch (
Op.getOpcode()) {
3141 case ISD::VP_FFLOOR:
3144 case ISD::VP_FROUND:
3145 case ISD::VP_FROUNDEVEN:
3146 case ISD::VP_FROUNDTOZERO: {
3158 case ISD::VP_FNEARBYINT:
3171 Src, Src, Mask, VL);
3186 MVT VT =
Op.getSimpleValueType();
3190 MVT ContainerVT = VT;
3202 MVT MaskVT = Mask.getSimpleValueType();
3205 {Chain, Src, Src, DAG.getCondCode(ISD::SETUNE),
3206 DAG.getUNDEF(MaskVT), Mask, VL});
3210 {Chain, Src, Src, Src, Unorder, VL});
3211 Chain = Src.getValue(1);
3227 DAG.
getUNDEF(ContainerVT), MaxValNode, VL);
3239 switch (
Op.getOpcode()) {
3250 {Chain, Src, Mask, DAG.getTargetConstant(FRM, DL, XLenVT), VL});
3256 DAG.
getVTList(IntVT, MVT::Other), Chain, Src, Mask, VL);
3260 DAG.
getVTList(ContainerVT, MVT::Other), Chain, Src,
3269 DAG.
getVTList(ContainerVT, MVT::Other), Chain,
3270 Truncated, Mask, VL);
3276 Src, Src, Mask, VL);
3286 MVT VT =
Op.getSimpleValueType();
3314 MVT VT =
Op.getSimpleValueType();
3319 MVT ContainerVT = VT;
3364 "Unexpected vector MVT");
3392 return std::nullopt;
3410 unsigned EltSizeInBits) {
3413 return std::nullopt;
3414 bool IsInteger =
Op.getValueType().isInteger();
3416 std::optional<unsigned> SeqStepDenom;
3417 std::optional<APInt> SeqStepNum;
3418 std::optional<APInt> SeqAddend;
3419 std::optional<std::pair<APInt, unsigned>> PrevElt;
3420 assert(EltSizeInBits >=
Op.getValueType().getScalarSizeInBits());
3425 const unsigned OpSize =
Op.getScalarValueSizeInBits();
3427 if (Elt.isUndef()) {
3428 Elts[
Idx] = std::nullopt;
3432 Elts[
Idx] = Elt->getAsAPIntVal().trunc(OpSize).zext(EltSizeInBits);
3437 return std::nullopt;
3438 Elts[
Idx] = *ExactInteger;
3451 unsigned IdxDiff =
Idx - PrevElt->second;
3452 APInt ValDiff = *Elt - PrevElt->first;
3460 int64_t Remainder = ValDiff.
srem(IdxDiff);
3465 return std::nullopt;
3466 ValDiff = ValDiff.
sdiv(IdxDiff);
3471 SeqStepNum = ValDiff;
3472 else if (ValDiff != SeqStepNum)
3473 return std::nullopt;
3476 SeqStepDenom = IdxDiff;
3477 else if (IdxDiff != *SeqStepDenom)
3478 return std::nullopt;
3482 if (!PrevElt || PrevElt->first != *Elt)
3483 PrevElt = std::make_pair(*Elt,
Idx);
3487 if (!SeqStepNum || !SeqStepDenom)
3488 return std::nullopt;
3496 (
APInt(EltSizeInBits,
Idx,
false,
true) *
3498 .sdiv(*SeqStepDenom);
3500 APInt Addend = *Elt - ExpectedVal;
3503 else if (Addend != SeqAddend)
3504 return std::nullopt;
3507 assert(SeqAddend &&
"Must have an addend if we have a step");
3509 return VIDSequence{SeqStepNum->getSExtValue(), *SeqStepDenom,
3510 SeqAddend->getSExtValue()};
3525 MVT SrcVT = Src.getSimpleValueType();
3535 auto *CIdx = dyn_cast<ConstantSDNode>(
Idx);
3541 MVT ContainerVT = VT;
3545 MVT SrcContainerVT = SrcVT;
3580 MVT VT =
Op.getSimpleValueType();
3592 unsigned MostCommonCount = 0;
3594 unsigned NumUndefElts =
3602 unsigned NumScalarLoads = 0;
3608 unsigned &Count = ValueCounts[V];
3610 if (
auto *CFP = dyn_cast<ConstantFPSDNode>(V))
3611 NumScalarLoads += !CFP->isExactlyValue(+0.0);
3616 if (++Count >= MostCommonCount) {
3618 MostCommonCount = Count;
3622 assert(DominantValue &&
"Not expecting an all-undef BUILD_VECTOR");
3623 unsigned NumDefElts = NumElts - NumUndefElts;
3624 unsigned DominantValueCountThreshold = NumDefElts <= 2 ? 0 : NumDefElts - 2;
3630 ((MostCommonCount > DominantValueCountThreshold) ||
3643 !LastOp.isUndef() && ValueCounts[LastOp] == 1 &&
3644 LastOp != DominantValue) {
3653 Processed.insert(LastOp);
3658 const SDValue &V = OpIdx.value();
3659 if (V.isUndef() || !Processed.insert(V).second)
3661 if (ValueCounts[V] == 1) {
3670 return DAG.getConstant(V == V1, DL, XLenVT);
3686 MVT VT =
Op.getSimpleValueType();
3716 unsigned NumViaIntegerBits = std::clamp(NumElts, 8u, Subtarget.
getXLen());
3717 NumViaIntegerBits = std::min(NumViaIntegerBits, Subtarget.
getELen());
3725 unsigned IntegerViaVecElts =
divideCeil(NumElts, NumViaIntegerBits);
3726 MVT IntegerViaVecVT =
3731 unsigned BitPos = 0, IntegerEltIdx = 0;
3734 for (
unsigned I = 0;
I < NumElts;) {
3736 bool BitValue = !V.isUndef() && V->getAsZExtVal();
3737 Bits |= ((
uint64_t)BitValue << BitPos);
3743 if (
I % NumViaIntegerBits == 0 ||
I == NumElts) {
3744 if (NumViaIntegerBits <= 32)
3745 Bits = SignExtend64<32>(Bits);
3747 Elts[IntegerEltIdx] = Elt;
3756 if (NumElts < NumViaIntegerBits) {
3760 assert(IntegerViaVecVT == MVT::v1i8 &&
"Unexpected mask vector type");
3788 int64_t StepNumerator = SimpleVID->StepNumerator;
3789 unsigned StepDenominator = SimpleVID->StepDenominator;
3790 int64_t Addend = SimpleVID->Addend;
3792 assert(StepNumerator != 0 &&
"Invalid step");
3793 bool Negate =
false;
3794 int64_t SplatStepVal = StepNumerator;
3798 if (StepNumerator != 1 && StepNumerator !=
INT64_MIN &&
3800 Negate = StepNumerator < 0;
3802 SplatStepVal =
Log2_64(std::abs(StepNumerator));
3809 if (((StepOpcode ==
ISD::MUL && isInt<12>(SplatStepVal)) ||
3810 (StepOpcode ==
ISD::SHL && isUInt<5>(SplatStepVal))) &&
3812 (SplatStepVal >= 0 || StepDenominator == 1) && isInt<5>(Addend)) {
3815 MVT VIDContainerVT =
3823 if ((StepOpcode ==
ISD::MUL && SplatStepVal != 1) ||
3824 (StepOpcode ==
ISD::SHL && SplatStepVal != 0)) {
3826 VID = DAG.
getNode(StepOpcode,
DL, VIDVT, VID, SplatStep);
3828 if (StepDenominator != 1) {
3833 if (Addend != 0 || Negate) {
3852 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32) &&
3853 "Unexpected sequence type");
3857 unsigned ViaVecLen =
3861 uint64_t EltMask = maskTrailingOnes<uint64_t>(EltBitSize);
3864 for (
const auto &OpIdx :
enumerate(
Op->op_values())) {
3865 const auto &SeqV = OpIdx.value();
3866 if (!SeqV.isUndef())
3868 ((SeqV->getAsZExtVal() & EltMask) << (OpIdx.index() * EltBitSize));
3874 if (ViaIntVT == MVT::i32)
3875 SplatValue = SignExtend64<32>(SplatValue);
3897 const auto *BV = cast<BuildVectorSDNode>(
Op);
3900 BV->getRepeatedSequence(Sequence) &&
3901 (Sequence.size() * EltBitSize) <= Subtarget.
getELen()) {
3902 unsigned SeqLen = Sequence.size();
3904 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32 ||
3905 ViaIntVT == MVT::i64) &&
3906 "Unexpected sequence type");
3911 const unsigned RequiredVL = NumElts / SeqLen;
3912 const unsigned ViaVecLen =
3914 NumElts : RequiredVL;
3917 unsigned EltIdx = 0;
3918 uint64_t EltMask = maskTrailingOnes<uint64_t>(EltBitSize);
3922 for (
const auto &SeqV : Sequence) {
3923 if (!SeqV.isUndef())
3925 ((SeqV->getAsZExtVal() & EltMask) << (EltIdx * EltBitSize));
3932 if (ViaIntVT == MVT::i32)
3933 SplatValue = SignExtend64<32>(SplatValue);
3939 (!Subtarget.
is64Bit() && ViaIntVT == MVT::i64)) &&
3940 "Unexpected bitcast sequence");
3941 if (ViaIntVT.
bitsLE(XLenVT) || isInt<32>(SplatValue)) {
3944 MVT ViaContainerVT =
3951 if (ViaVecLen != RequiredVL)
3971 Source, DAG, Subtarget);
3991 return RISCV::PACKH;
3993 return Subtarget.
is64Bit() ? RISCV::PACKW : RISCV::PACK;
4008 MVT VT =
Op.getSimpleValueType();
4016 if (!Subtarget.hasStdExtZbb() || !Subtarget.hasStdExtZba())
4021 if (ElemSizeInBits >= std::min(Subtarget.
getELen(), Subtarget.
getXLen()) ||
4035 if (Subtarget.hasStdExtZbkb())
4040 ElemDL, XLenVT,
A,
B),
4052 NewOperands.
reserve(NumElts / 2);
4054 NewOperands.
push_back(pack(
Op.getOperand(i),
Op.getOperand(i + 1)));
4064 MVT VT =
Op.getSimpleValueType();
4075 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) || EltVT == MVT::bf16) {
4080 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4081 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin())) {
4084 if (
auto *
C = dyn_cast<ConstantFPSDNode>(Elem)) {
4168 auto OneVRegOfOps =
ArrayRef(BuildVectorOps).
slice(i, ElemsPerVReg);
4172 unsigned InsertIdx = (i / ElemsPerVReg) * NumOpElts;
4195 unsigned NumUndefElts =
4197 unsigned NumDefElts = NumElts - NumUndefElts;
4198 if (NumDefElts >= 8 && NumDefElts > NumElts / 2 &&
4205 for (
unsigned i = 0; i < NumElts; i++) {
4207 if (i < NumElts / 2) {
4214 bool SelectMaskVal = (i < NumElts / 2);
4217 assert(SubVecAOps.
size() == NumElts && SubVecBOps.
size() == NumElts &&
4218 MaskVals.
size() == NumElts);
4253 unsigned UndefCount = 0;
4260 LinearBudget -= PerSlideCost;
4263 LinearBudget -= PerSlideCost;
4266 LinearBudget -= PerSlideCost;
4269 if (LinearBudget < 0)
4274 "Illegal type which will result in reserved encoding");
4299 Vec,
Offset, Mask, VL, Policy);
4312 Vec,
Offset, Mask, VL, Policy);
4322 if (isa<ConstantSDNode>(
Lo) && isa<ConstantSDNode>(
Hi)) {
4323 int32_t LoC = cast<ConstantSDNode>(
Lo)->getSExtValue();
4324 int32_t HiC = cast<ConstantSDNode>(
Hi)->getSExtValue();
4327 if ((LoC >> 31) == HiC)
4338 (isa<RegisterSDNode>(VL) &&
4339 cast<RegisterSDNode>(VL)->
getReg() == RISCV::X0))
4341 else if (isa<ConstantSDNode>(VL) && isUInt<4>(VL->
getAsZExtVal()))
4356 isa<ConstantSDNode>(
Hi.getOperand(1)) &&
4357 Hi.getConstantOperandVal(1) == 31)
4376 assert(Scalar.getValueType() == MVT::i64 &&
"Unexpected VT!");
4388 bool HasPassthru = Passthru && !Passthru.
isUndef();
4389 if (!HasPassthru && !Passthru)
4396 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
4397 EltVT == MVT::bf16) {
4398 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4399 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
4413 if (Scalar.getValueType().bitsLE(XLenVT)) {
4420 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4424 assert(XLenVT == MVT::i32 && Scalar.getValueType() == MVT::i64 &&
4425 "Unexpected scalar for splat lowering!");
4449 SDValue ExtractedVal = Scalar.getOperand(0);
4454 MVT ExtractedContainerVT = ExtractedVT;
4457 DAG, ExtractedContainerVT, Subtarget);
4459 ExtractedVal, DAG, Subtarget);
4461 if (ExtractedContainerVT.
bitsLE(VT))
4476 if (!Scalar.getValueType().bitsLE(XLenVT))
4479 VT,
DL, DAG, Subtarget);
4487 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4507 if (Src != V2.getOperand(0))
4512 if (Src.getValueType().getVectorNumElements() != (NumElts * 2))
4517 V2.getConstantOperandVal(1) != NumElts)
4535 int Size = Mask.size();
4537 assert(
Size == (
int)NumElts &&
"Unexpected mask size");
4543 EvenSrc = StartIndexes[0];
4544 OddSrc = StartIndexes[1];
4547 if (EvenSrc != 0 && OddSrc != 0)
4557 int HalfNumElts = NumElts / 2;
4558 return ((EvenSrc % HalfNumElts) == 0) && ((OddSrc % HalfNumElts) == 0);
4574 int Size = Mask.size();
4586 for (
int i = 0; i !=
Size; ++i) {
4592 int StartIdx = i - (M %
Size);
4600 int CandidateRotation = StartIdx < 0 ? -StartIdx :
Size - StartIdx;
4603 Rotation = CandidateRotation;
4604 else if (Rotation != CandidateRotation)
4609 int MaskSrc = M <
Size ? 0 : 1;
4614 int &TargetSrc = StartIdx < 0 ? HiSrc : LoSrc;
4619 TargetSrc = MaskSrc;
4620 else if (TargetSrc != MaskSrc)
4627 assert(Rotation != 0 &&
"Failed to locate a viable rotation!");
4628 assert((LoSrc >= 0 || HiSrc >= 0) &&
4629 "Failed to find a rotated input vector!");
4643 ElementCount SrcEC = Src.getValueType().getVectorElementCount();
4650 unsigned Shift = Index * EltBits;
4677 auto findNonEXTRACT_SUBVECTORParent =
4678 [](
SDValue Parent) -> std::pair<SDValue, uint64_t> {
4683 Parent.getOperand(0).getSimpleValueType().isFixedLengthVector()) {
4684 Offset += Parent.getConstantOperandVal(1);
4685 Parent = Parent.getOperand(0);
4687 return std::make_pair(Parent,
Offset);
4690 auto [V1Src, V1IndexOffset] = findNonEXTRACT_SUBVECTORParent(V1);
4691 auto [V2Src, V2IndexOffset] = findNonEXTRACT_SUBVECTORParent(V2);
4700 for (
size_t i = 0; i != NewMask.
size(); ++i) {
4701 if (NewMask[i] == -1)
4704 if (
static_cast<size_t>(NewMask[i]) < NewMask.
size()) {
4705 NewMask[i] = NewMask[i] + V1IndexOffset;
4709 NewMask[i] = NewMask[i] - NewMask.
size() + V2IndexOffset;
4715 if (NewMask[0] <= 0)
4719 for (
unsigned i = 1; i != NewMask.
size(); ++i)
4720 if (NewMask[i - 1] + 1 != NewMask[i])
4724 MVT SrcVT = Src.getSimpleValueType();
4755 int NumSubElts, Index;
4760 bool OpsSwapped = Mask[Index] < (int)NumElts;
4761 SDValue InPlace = OpsSwapped ? V2 : V1;
4762 SDValue ToInsert = OpsSwapped ? V1 : V2;
4772 if (NumSubElts + Index >= (
int)NumElts)
4786 Res =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, InPlace, ToInsert,
4798 bool OpsSwapped =
false;
4799 if (!isa<BuildVectorSDNode>(V1)) {
4800 if (!isa<BuildVectorSDNode>(V2))
4805 SDValue Splat = cast<BuildVectorSDNode>(V1)->getSplatValue();
4813 const unsigned E = Mask.size() - ((
Offset > 0) ?
Offset : 0);
4814 for (
unsigned i = S; i != E; ++i)
4815 if (Mask[i] >= 0 && (
unsigned)Mask[i] !=
Base + i +
Offset)
4821 bool IsVSlidedown = isSlideMask(Mask, OpsSwapped ? 0 : NumElts, 1);
4822 if (!IsVSlidedown && !isSlideMask(Mask, OpsSwapped ? 0 : NumElts, -1))
4825 const int InsertIdx = Mask[IsVSlidedown ? (NumElts - 1) : 0];
4827 if (InsertIdx < 0 || InsertIdx / NumElts != (
unsigned)OpsSwapped)
4850 auto OpCode = IsVSlidedown ?
4855 auto Vec = DAG.
getNode(OpCode,
DL, ContainerVT,
4858 Splat, TrueMask, VL);
4869 for (
unsigned i = 0; i < Mask.size(); i++)
4870 LaneIsUndef[i % Factor] &= (Mask[i] == -1);
4873 for (
unsigned i = 0; i < Factor; i++) {
4884 for (
unsigned i = 0; i < Mask.size() / Factor; i++) {
4885 unsigned j = i * Factor + Index;
4886 if (Mask[j] != -1 && (
unsigned)Mask[j] != i)
4899 MVT VT = V.getSimpleValueType();
4914 EC.multiplyCoefficientBy(Factor));
4933 MVT VecContainerVT = VecVT;
4950 MVT WideContainerVT = WideVT;
4956 EvenV = DAG.
getBitcast(VecContainerVT, EvenV);
4963 if (Subtarget.hasStdExtZvbb()) {
4968 OffsetVec, Passthru, Mask, VL);
4970 Interleaved, EvenV, Passthru, Mask, VL);
4978 OddV, Passthru, Mask, VL);
4984 OddV, AllOnesVec, Passthru, Mask, VL);
4992 Interleaved, OddsMul, Passthru, Mask, VL);
4999 Interleaved = DAG.
getBitcast(ResultContainerVT, Interleaved);
5045 if (ViaEltSize > NumElts)
5054 if (ViaEltSize > NumElts)
5060 if (ViaEltSize > NumElts)
5069 MVT &RotateVT,
unsigned &RotateAmt) {
5075 unsigned NumSubElts;
5077 NumElts, NumSubElts, RotateAmt))
5080 NumElts / NumSubElts);
5148 unsigned NumOfSrcRegs = NumElts / NumOpElts;
5149 unsigned NumOfDestRegs = NumElts / NumOpElts;
5158 Mask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs,
5159 [&]() {
Operands.emplace_back(); },
5160 [&](
ArrayRef<int> SrcSubMask,
unsigned SrcVecIdx,
unsigned DstVecIdx) {
5161 Operands.emplace_back().emplace_back(
5162 SrcVecIdx, UINT_MAX,
5165 [&](
ArrayRef<int> SrcSubMask,
unsigned Idx1,
unsigned Idx2,
bool NewReg) {
5171 assert(
Operands.size() == NumOfDestRegs &&
"Whole vector must be processed");
5176 unsigned NumShuffles = std::accumulate(
5183 for (const auto &P : Data) {
5184 unsigned Idx2 = std::get<1>(P);
5185 ArrayRef<int> Mask = std::get<2>(P);
5186 if (Idx2 != UINT_MAX)
5188 else if (ShuffleVectorInst::isIdentityMask(Mask, Mask.size()))
5193 if ((NumOfDestRegs > 2 && NumShuffles > NumOfDestRegs) ||
5194 (NumOfDestRegs <= 2 && NumShuffles >= 4))
5196 auto ExtractValue = [&, &DAG = DAG](
SDValue SrcVec,
unsigned ExtractIdx) {
5198 DAG.getVectorIdxConstant(ExtractIdx,
DL));
5202 auto PerformShuffle = [&, &DAG = DAG](
SDValue SubVec1,
SDValue SubVec2,
5204 SDValue SubVec = DAG.getVectorShuffle(OneRegVT,
DL, SubVec1, SubVec2, Mask);
5207 SDValue Vec = DAG.getUNDEF(ContainerVT);
5212 for (
unsigned I : seq<unsigned>(
Data.size())) {
5213 const auto &[Idx1, Idx2,
_] =
Data[
I];
5216 "Expected both indices to be extracted already.");
5219 SDValue V = ExtractValue(Idx1 >= NumOfSrcRegs ? V2 : V1,
5220 (Idx1 % NumOfSrcRegs) * NumOpElts);
5222 if (Idx2 != UINT_MAX)
5223 Values[Idx2] = ExtractValue(Idx2 >= NumOfSrcRegs ? V2 : V1,
5224 (Idx2 % NumOfSrcRegs) * NumOpElts);
5227 for (
const auto &[Idx1, Idx2, Mask] :
Data) {
5229 SDValue V2 = Idx2 == UINT_MAX ? V1 : Values.
at(Idx2);
5230 V = PerformShuffle(V1, V2, Mask);
5234 unsigned InsertIdx =
I * NumOpElts;
5237 DAG.getVectorIdxConstant(InsertIdx,
DL));
5247 bool SawUndef =
false;
5248 for (
unsigned i = 0; i < Mask.size(); i++) {
5249 if (Mask[i] == -1) {
5255 if (i > (
unsigned)Mask[i])
5257 if (Mask[i] <=
Last)
5288 for (
int Idx : Mask) {
5291 unsigned SrcIdx =
Idx % Mask.size();
5293 if (Srcs[SrcIdx] == -1)
5296 else if (Srcs[SrcIdx] != Src)
5302 for (
int Lane : Srcs) {
5315 for (
unsigned I = 0;
I < Mask.size();
I++) {
5319 NewMask[
I] = Mask[
I] % Mask.size();
5333 MVT VT =
Op.getSimpleValueType();
5341 if (ElementSize > 32)
5364 MVT VT =
Op.getSimpleValueType();
5379 V2 = V2.isUndef() ? DAG.
getUNDEF(WidenVT)
5403 V.getOperand(0).getSimpleValueType().getVectorNumElements();
5404 V = V.getOperand(
Offset / OpElements);
5410 auto *Ld = cast<LoadSDNode>(V);
5420 SDValue Ops[] = {Ld->getChain(),
5434 MVT SplatVT = ContainerVT;
5437 if (SVT == MVT::bf16 ||
5438 (SVT == MVT::f16 && !Subtarget.hasStdExtZfh())) {
5447 V = DAG.
getLoad(SVT,
DL, Ld->getChain(), NewAddr,
5448 Ld->getPointerInfo().getWithOffset(
Offset),
5449 Ld->getOriginalAlign(),
5453 Ld->getPointerInfo().getWithOffset(
Offset), SVT,
5454 Ld->getOriginalAlign(),
5455 Ld->getMemOperand()->getFlags());
5467 assert(Lane < (
int)NumElts &&
"Unexpected lane!");
5470 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
5492 if (Subtarget.hasStdExtZvkb())
5503 LoV = LoSrc == 0 ? V1 : V2;
5507 HiV = HiSrc == 0 ? V1 : V2;
5513 unsigned InvRotate = NumElts - Rotation;
5523 Res =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, Res, LoV,
5541 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
5542 for (
unsigned Factor = 2; Factor <= MaxFactor; Factor <<= 1) {
5558 int EvenSrc, OddSrc;
5566 bool LaneIsUndef[2] = {
true,
true};
5567 for (
unsigned i = 0; i < Mask.size(); i++)
5568 LaneIsUndef[i % 2] &= (Mask[i] == -1);
5570 int Size = Mask.size();
5572 if (LaneIsUndef[0]) {
5575 assert(EvenSrc >= 0 &&
"Undef source?");
5576 EvenV = (EvenSrc /
Size) == 0 ? V1 : V2;
5581 if (LaneIsUndef[1]) {
5584 assert(OddSrc >= 0 &&
"Undef source?");
5585 OddV = (OddSrc /
Size) == 0 ? V1 : V2;
5595 assert(!V1.
isUndef() &&
"Unexpected shuffle canonicalization");
5615 for (
auto Idx : Mask) {
5631 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
5632 for (
unsigned Factor = 4; Factor <= MaxFactor; Factor <<= 1) {
5645 any_of(Mask, [&](
const auto &
Idx) {
return Idx > 255; })) {
5674 MVT IndexContainerVT =
5679 for (
int MaskIndex : Mask) {
5680 bool IsLHSIndex = MaskIndex < (int)NumElts && MaskIndex >= 0;
5689 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
5699 for (
int MaskIndex : Mask) {
5700 bool IsLHSOrUndefIndex = MaskIndex < (int)NumElts;
5701 ShuffleMaskLHS.
push_back(IsLHSOrUndefIndex && MaskIndex >= 0
5703 ShuffleMaskRHS.
push_back(IsLHSOrUndefIndex ? -1 : (MaskIndex - NumElts));
5734 for (
int MaskIndex : Mask) {
5735 bool SelectMaskVal = (MaskIndex < (int)NumElts) ^ !SwapOps;
5739 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
5771RISCVTargetLowering::lowerCTLZ_CTTZ_ZERO_UNDEF(
SDValue Op,
5773 MVT VT =
Op.getSimpleValueType();
5777 MVT ContainerVT = VT;
5780 if (
Op->isVPOpcode()) {
5781 Mask =
Op.getOperand(1);
5785 VL =
Op.getOperand(2);
5791 MVT FloatEltVT = (EltSize >= 32) ? MVT::f64 : MVT::f32;
5793 FloatEltVT = MVT::f32;
5800 "Expected legal float type!");
5807 }
else if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF) {
5810 Src = DAG.
getNode(ISD::VP_AND,
DL, VT, Src, Neg, Mask, VL);
5815 if (FloatVT.
bitsGT(VT)) {
5816 if (
Op->isVPOpcode())
5817 FloatVal = DAG.
getNode(ISD::VP_UINT_TO_FP,
DL, FloatVT, Src, Mask, VL);
5826 if (!
Op->isVPOpcode())
5830 MVT ContainerFloatVT =
5833 Src, Mask, RTZRM, VL);
5840 unsigned ShiftAmt = FloatEltVT == MVT::f64 ? 52 : 23;
5844 if (
Op->isVPOpcode()) {
5853 else if (IntVT.
bitsGT(VT))
5858 unsigned ExponentBias = FloatEltVT == MVT::f64 ? 1023 : 127;
5863 if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF)
5864 return DAG.
getNode(ISD::VP_SUB,
DL, VT, Exp,
5869 unsigned Adjust = ExponentBias + (EltSize - 1);
5871 if (
Op->isVPOpcode())
5881 else if (
Op.getOpcode() == ISD::VP_CTLZ)
5882 Res = DAG.
getNode(ISD::VP_UMIN,
DL, VT, Res,
5892 MVT SrcVT =
Source.getSimpleValueType();
5901 SrcVT = ContainerVT;
5914 if (
Op->getOpcode() == ISD::VP_CTTZ_ELTS_ZERO_UNDEF)
5931 auto *
Load = cast<LoadSDNode>(
Op);
5932 assert(Load &&
Load->getMemoryVT().isVector() &&
"Expected vector load");
5935 Load->getMemoryVT(),
5936 *
Load->getMemOperand()))
5940 MVT VT =
Op.getSimpleValueType();
5942 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
5943 "Unexpected unaligned RVV load type");
5947 "Expecting equally-sized RVV vector types to be legal");
5949 Load->getPointerInfo(),
Load->getOriginalAlign(),
5950 Load->getMemOperand()->getFlags());
5960 auto *
Store = cast<StoreSDNode>(
Op);
5961 assert(Store &&
Store->getValue().getValueType().isVector() &&
5962 "Expected vector store");
5965 Store->getMemoryVT(),
5966 *
Store->getMemOperand()))
5973 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
5974 "Unexpected unaligned RVV store type");
5978 "Expecting equally-sized RVV vector types to be legal");
5979 StoredVal = DAG.
getBitcast(NewVT, StoredVal);
5981 Store->getPointerInfo(),
Store->getOriginalAlign(),
5982 Store->getMemOperand()->getFlags());
5987 assert(
Op.getValueType() == MVT::i64 &&
"Unexpected VT");
5989 int64_t Imm = cast<ConstantSDNode>(
Op)->getSExtValue();
6016 unsigned ShiftAmt, AddOpc;
6027 MVT VT =
Op.getSimpleValueType();
6028 const APFloat &
Imm = cast<ConstantFPSDNode>(
Op)->getValueAPF();
6031 bool Negate =
false;
6035 if (Index < 0 &&
Imm.isNegative()) {
6063 if (Subtarget.hasStdExtZtso()) {
6087 MVT VT =
Op.getSimpleValueType();
6089 unsigned Check =
Op.getConstantOperandVal(1);
6090 unsigned TDCMask = 0;
6118 MVT VT0 =
Op.getOperand(0).getSimpleValueType();
6123 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6125 VL =
Op.getOperand(3);
6128 VL,
Op->getFlags());
6143 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6145 MVT MaskContainerVT =
6148 VL =
Op.getOperand(3);
6153 Mask, VL,
Op->getFlags());
6156 DAG.
getUNDEF(ContainerDstVT), TDCMaskV, VL);
6161 DAG.
getUNDEF(ContainerVT), Mask, VL});
6165 TDCMaskV, DAG.
getUNDEF(ContainerDstVT), Mask, VL);
6169 DAG.
getUNDEF(ContainerDstVT), SplatZero, VL);
6173 DAG.
getUNDEF(ContainerVT), Mask, VL});
6189 MVT VT =
Op.getSimpleValueType();
6216 return DAG.
getNode(Opc,
DL, VT, NewX, NewY);
6223 MVT ContainerVT = VT;
6231 if (
Op->isVPOpcode()) {
6232 Mask =
Op.getOperand(2);
6236 VL =
Op.getOperand(3);
6244 {X, X, DAG.getCondCode(ISD::SETOEQ),
6245 DAG.getUNDEF(ContainerVT), Mask, VL});
6253 {Y, Y, DAG.getCondCode(ISD::SETOEQ),
6254 DAG.getUNDEF(ContainerVT), Mask, VL});
6264 DAG.
getUNDEF(ContainerVT), Mask, VL);
6274 "Wrong opcode for lowering FABS or FNEG.");
6277 MVT VT =
Op.getSimpleValueType();
6278 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
6285 Mask = Mask.sext(Subtarget.
getXLen());
6298 MVT VT =
Op.getSimpleValueType();
6299 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
6309 if (SignSize == Subtarget.
getXLen()) {
6311 }
else if (SignSize == 16) {
6313 }
else if (SignSize == 32) {
6315 }
else if (SignSize == 64) {
6316 assert(XLenVT == MVT::i32 &&
"Unexpected type");
6326 if (ShiftAmount > 0) {
6329 }
else if (ShiftAmount < 0) {
6355#define OP_CASE(NODE) \
6357 return RISCVISD::NODE##_VL;
6358#define VP_CASE(NODE) \
6359 case ISD::VP_##NODE: \
6360 return RISCVISD::NODE##_VL;
6362 switch (
Op.getOpcode()) {
6440 case ISD::VP_CTLZ_ZERO_UNDEF:
6443 case ISD::VP_CTTZ_ZERO_UNDEF:
6452 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
6457 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
6462 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
6465 case ISD::VP_SELECT:
6474 case ISD::VP_SIGN_EXTEND:
6476 case ISD::VP_ZERO_EXTEND:
6478 case ISD::VP_FP_TO_SINT:
6480 case ISD::VP_FP_TO_UINT:
6483 case ISD::VP_FMINNUM:
6486 case ISD::VP_FMAXNUM:
6491 case ISD::VP_LLRINT:
6503 "not a RISC-V target specific op");
6507 "adding target specific op should update this function");
6527 "not a RISC-V target specific op");
6531 "adding target specific op should update this function");
6544 if (
Op.getValueType() == MVT::nxv32f16 &&
6548 if (
Op.getValueType() == MVT::nxv32bf16)
6561 if (!
Op.getOperand(j).getValueType().isVector()) {
6562 LoOperands[j] =
Op.getOperand(j);
6563 HiOperands[j] =
Op.getOperand(j);
6566 std::tie(LoOperands[j], HiOperands[j]) =
6571 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
6573 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
6588 std::tie(LoOperands[j], HiOperands[j]) =
6592 if (!
Op.getOperand(j).getValueType().isVector()) {
6593 LoOperands[j] =
Op.getOperand(j);
6594 HiOperands[j] =
Op.getOperand(j);
6597 std::tie(LoOperands[j], HiOperands[j]) =
6602 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
6604 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
6614 auto [EVLLo, EVLHi] =
6615 DAG.
SplitEVL(
Op.getOperand(3),
Op.getOperand(1).getValueType(),
DL);
6619 {Op.getOperand(0), Lo, MaskLo, EVLLo},
Op->getFlags());
6621 {ResLo, Hi, MaskHi, EVLHi},
Op->getFlags());
6639 if (!
Op.getOperand(j).getValueType().isVector()) {
6640 LoOperands[j] =
Op.getOperand(j);
6641 HiOperands[j] =
Op.getOperand(j);
6644 std::tie(LoOperands[j], HiOperands[j]) =
6649 DAG.
getNode(
Op.getOpcode(),
DL, LoVTs, LoOperands,
Op->getFlags());
6652 DAG.
getNode(
Op.getOpcode(),
DL, HiVTs, HiOperands,
Op->getFlags());
6661 switch (
Op.getOpcode()) {
6667 return lowerGlobalAddress(
Op, DAG);
6669 return lowerBlockAddress(
Op, DAG);
6671 return lowerConstantPool(
Op, DAG);
6673 return lowerJumpTable(
Op, DAG);
6675 return lowerGlobalTLSAddress(
Op, DAG);
6679 return lowerConstantFP(
Op, DAG);
6681 return lowerSELECT(
Op, DAG);
6683 return lowerBRCOND(
Op, DAG);
6685 return lowerVASTART(
Op, DAG);
6687 return lowerFRAMEADDR(
Op, DAG);
6689 return lowerRETURNADDR(
Op, DAG);
6691 return lowerShiftLeftParts(
Op, DAG);
6693 return lowerShiftRightParts(
Op, DAG,
true);
6695 return lowerShiftRightParts(
Op, DAG,
false);
6698 if (
Op.getValueType().isFixedLengthVector()) {
6699 assert(Subtarget.hasStdExtZvkb());
6700 return lowerToScalableOp(
Op, DAG);
6702 assert(Subtarget.hasVendorXTHeadBb() &&
6703 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
6704 "Unexpected custom legalization");
6706 if (!isa<ConstantSDNode>(
Op.getOperand(1)))
6711 EVT VT =
Op.getValueType();
6715 if (Op0VT == MVT::i16 &&
6717 (VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
6721 if (VT == MVT::f32 && Op0VT == MVT::i32 && Subtarget.
is64Bit() &&
6726 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.
is64Bit() &&
6742 "Unexpected types");
6776 return LowerINTRINSIC_WO_CHAIN(
Op, DAG);
6778 return LowerINTRINSIC_W_CHAIN(
Op, DAG);
6780 return LowerINTRINSIC_VOID(
Op, DAG);
6782 return LowerIS_FPCLASS(
Op, DAG);
6784 MVT VT =
Op.getSimpleValueType();
6786 assert(Subtarget.hasStdExtZvbb());
6787 return lowerToScalableOp(
Op, DAG);
6790 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected custom legalization");
6800 if (!
Op.getSimpleValueType().isVector())
6802 return lowerVectorTruncLike(
Op, DAG);
6805 if (
Op.getOperand(0).getValueType().isVector() &&
6806 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
6807 return lowerVectorMaskExt(
Op, DAG, 1);
6810 if (
Op.getOperand(0).getValueType().isVector() &&
6811 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
6812 return lowerVectorMaskExt(
Op, DAG, -1);
6815 return lowerSPLAT_VECTOR_PARTS(
Op, DAG);
6817 return lowerINSERT_VECTOR_ELT(
Op, DAG);
6819 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
6821 MVT VT =
Op.getSimpleValueType();
6829 MVT ContainerVT = VT;
6837 DAG.
getUNDEF(ContainerVT), Scalar, VL);
6841 DAG.
getUNDEF(ContainerVT), Scalar, VL);
6849 MVT VT =
Op.getSimpleValueType();
6869 }
else if ((Val % 8) == 0) {
6885 if (
Op.getValueType() == MVT::f16 && Subtarget.
is64Bit() &&
6886 Op.getOperand(1).getValueType() == MVT::i32) {
6903 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
6906 return lowerStrictFPExtendOrRoundLike(
Op, DAG);
6909 if (
Op.getValueType().isVector() &&
6910 ((
Op.getValueType().getScalarType() == MVT::f16 &&
6913 Op.getValueType().getScalarType() == MVT::bf16)) {
6929 Op1.getValueType().isVector() &&
6930 ((Op1.getValueType().getScalarType() == MVT::f16 &&
6933 Op1.getValueType().getScalarType() == MVT::bf16)) {
6939 Op1.getValueType().getVectorElementCount());
6942 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), WidenVec);
6952 MVT VT =
Op.getSimpleValueType();
6955 bool IsStrict =
Op->isStrictFPOpcode();
6956 SDValue Src =
Op.getOperand(0 + IsStrict);
6957 MVT SrcVT = Src.getSimpleValueType();
6968 "Unexpected vector element types");
6972 if (EltSize > (2 * SrcEltSize)) {
6984 Op.getOperand(0), Ext);
6988 assert(SrcEltVT == MVT::f16 &&
"Unexpected FP_TO_[US]INT lowering");
6993 auto [FExt, Chain] =
6995 return DAG.
getNode(
Op.getOpcode(),
DL,
Op->getVTList(), Chain, FExt);
7002 if (SrcEltSize > (2 * EltSize)) {
7005 assert(EltVT == MVT::f16 &&
"Unexpected [US]_TO_FP lowering");
7010 Op.getOperand(0), Src);
7025 Op.getOperand(0), Src);
7039 unsigned RVVOpc = 0;
7040 switch (
Op.getOpcode()) {
7072 "Expected same element count");
7079 Op.getOperand(0), Src, Mask, VL);
7083 Src = DAG.
getNode(RVVOpc,
DL, ContainerVT, Src, Mask, VL);
7098 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
7105 MVT VT =
Op.getSimpleValueType();
7125 bool IsStrict =
Op->isStrictFPOpcode();
7126 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7130 std::tie(Res, Chain) =
7131 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
7146 bool IsStrict =
Op->isStrictFPOpcode();
7147 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7153 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
7154 CallOptions,
DL, Chain);
7171 if (
Op.getValueType().isVector())
7176 assert(
Op.getOperand(0).getValueType() == MVT::f16 &&
7177 "Unexpected custom legalisation");
7180 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), Ext);
7186 assert(
Op.getOperand(1).getValueType() == MVT::f16 &&
7187 "Unexpected custom legalisation");
7190 {
Op.getOperand(0),
Op.getOperand(1)});
7191 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
7192 {Ext.getValue(1), Ext.getValue(0)});
7199 return lowerVECREDUCE(
Op, DAG);
7203 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7204 return lowerVectorMaskVecReduction(
Op, DAG,
false);
7205 return lowerVECREDUCE(
Op, DAG);
7212 return lowerFPVECREDUCE(
Op, DAG);
7213 case ISD::VP_REDUCE_ADD:
7214 case ISD::VP_REDUCE_UMAX:
7215 case ISD::VP_REDUCE_SMAX:
7216 case ISD::VP_REDUCE_UMIN:
7217 case ISD::VP_REDUCE_SMIN:
7218 case ISD::VP_REDUCE_FADD:
7219 case ISD::VP_REDUCE_SEQ_FADD:
7220 case ISD::VP_REDUCE_FMIN:
7221 case ISD::VP_REDUCE_FMAX:
7222 case ISD::VP_REDUCE_FMINIMUM:
7223 case ISD::VP_REDUCE_FMAXIMUM:
7226 return lowerVPREDUCE(
Op, DAG);
7227 case ISD::VP_REDUCE_AND:
7228 case ISD::VP_REDUCE_OR:
7229 case ISD::VP_REDUCE_XOR:
7230 if (
Op.getOperand(1).getValueType().getVectorElementType() == MVT::i1)
7231 return lowerVectorMaskVecReduction(
Op, DAG,
true);
7232 return lowerVPREDUCE(
Op, DAG);
7233 case ISD::VP_CTTZ_ELTS:
7234 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
7235 return lowerVPCttzElements(
Op, DAG);
7239 DAG.
getUNDEF(ContainerVT), DAG, Subtarget);
7242 return lowerINSERT_SUBVECTOR(
Op, DAG);
7244 return lowerEXTRACT_SUBVECTOR(
Op, DAG);
7246 return lowerVECTOR_DEINTERLEAVE(
Op, DAG);
7248 return lowerVECTOR_INTERLEAVE(
Op, DAG);
7250 return lowerSTEP_VECTOR(
Op, DAG);
7252 return lowerVECTOR_REVERSE(
Op, DAG);
7254 return lowerVECTOR_SPLICE(
Op, DAG);
7258 MVT VT =
Op.getSimpleValueType();
7260 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
7261 EltVT == MVT::bf16) {
7264 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
7265 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
7275 if (EltVT == MVT::i1)
7276 return lowerVectorMaskSplat(
Op, DAG);
7285 MVT VT =
Op.getSimpleValueType();
7286 MVT ContainerVT = VT;
7304 Op->ops().take_front(HalfNumOps));
7306 Op->ops().drop_front(HalfNumOps));
7310 unsigned NumOpElts =
7311 Op.getOperand(0).getSimpleValueType().getVectorMinNumElements();
7314 SDValue SubVec = OpIdx.value();
7325 auto *Load = cast<LoadSDNode>(
Op);
7326 EVT VecTy = Load->getMemoryVT();
7333 unsigned NumElts = Sz / (NF * 8);
7334 int Log2LMUL =
Log2_64(NumElts) - 3;
7337 Flag.setNoUnsignedWrap(
true);
7339 SDValue BasePtr = Load->getBasePtr();
7347 for (
unsigned i = 0; i < NF; ++i) {
7360 if (
auto V = expandUnalignedRVVLoad(
Op, DAG))
7362 if (
Op.getValueType().isFixedLengthVector())
7363 return lowerFixedLengthVectorLoadToRVV(
Op, DAG);
7367 auto *Store = cast<StoreSDNode>(
Op);
7368 SDValue StoredVal = Store->getValue();
7376 unsigned NumElts = Sz / (NF * 8);
7377 int Log2LMUL =
Log2_64(NumElts) - 3;
7380 Flag.setNoUnsignedWrap(
true);
7382 SDValue Chain = Store->getChain();
7383 SDValue BasePtr = Store->getBasePtr();
7390 for (
unsigned i = 0; i < NF; ++i) {
7394 Ret = DAG.
getStore(Chain,
DL, Extract, BasePtr,
7396 Store->getOriginalAlign(),
7397 Store->getMemOperand()->getFlags());
7398 Chain = Ret.getValue(0);
7404 if (
auto V = expandUnalignedRVVStore(
Op, DAG))
7406 if (
Op.getOperand(1).getValueType().isFixedLengthVector())
7407 return lowerFixedLengthVectorStoreToRVV(
Op, DAG);
7412 return lowerMaskedLoad(
Op, DAG);
7415 return lowerMaskedStore(
Op, DAG);
7417 return lowerVectorCompress(
Op, DAG);
7426 EVT VT =
Op.getValueType();
7437 MVT OpVT =
Op.getOperand(0).getSimpleValueType();
7439 MVT VT =
Op.getSimpleValueType();
7444 "Unexpected CondCode");
7452 if (isa<ConstantSDNode>(
RHS)) {
7453 int64_t Imm = cast<ConstantSDNode>(
RHS)->getSExtValue();
7454 if (Imm != 0 && isInt<12>((
uint64_t)Imm + 1)) {
7476 return lowerFixedLengthVectorSetccToRVV(
Op, DAG);
7492 return lowerToScalableOp(
Op, DAG);
7496 if (
Op.getSimpleValueType().isFixedLengthVector())
7497 return lowerToScalableOp(
Op, DAG);
7499 assert(
Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.
is64Bit() &&
7500 "Unexpected custom legalisation");
7504 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
7530 return lowerToScalableOp(
Op, DAG);
7534 EVT VT =
Op->getValueType(0);
7549 return lowerABS(
Op, DAG);
7554 if (Subtarget.hasStdExtZvbb())
7555 return lowerToScalableOp(
Op, DAG);
7557 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
7559 return lowerFixedLengthVectorSelectToRVV(
Op, DAG);
7561 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
7565 return lowerFixedLengthVectorFCOPYSIGNToRVV(
Op, DAG);
7574 return lowerToScalableOp(
Op, DAG);
7577 return lowerVectorStrictFSetcc(
Op, DAG);
7587 case ISD::VP_GATHER:
7588 return lowerMaskedGather(
Op, DAG);
7590 case ISD::VP_SCATTER:
7591 return lowerMaskedScatter(
Op, DAG);
7593 return lowerGET_ROUNDING(
Op, DAG);
7595 return lowerSET_ROUNDING(
Op, DAG);
7597 return lowerEH_DWARF_CFA(
Op, DAG);
7599 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7600 return lowerVPMergeMask(
Op, DAG);
7602 case ISD::VP_SELECT:
7610 case ISD::VP_UADDSAT:
7611 case ISD::VP_USUBSAT:
7612 case ISD::VP_SADDSAT:
7613 case ISD::VP_SSUBSAT:
7615 case ISD::VP_LLRINT:
7616 return lowerVPOp(
Op, DAG);
7620 return lowerLogicVPOp(
Op, DAG);
7629 case ISD::VP_FMINNUM:
7630 case ISD::VP_FMAXNUM:
7631 case ISD::VP_FCOPYSIGN:
7638 return lowerVPOp(
Op, DAG);
7639 case ISD::VP_IS_FPCLASS:
7640 return LowerIS_FPCLASS(
Op, DAG);
7641 case ISD::VP_SIGN_EXTEND:
7642 case ISD::VP_ZERO_EXTEND:
7643 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
7644 return lowerVPExtMaskOp(
Op, DAG);
7645 return lowerVPOp(
Op, DAG);
7646 case ISD::VP_TRUNCATE:
7647 return lowerVectorTruncLike(
Op, DAG);
7648 case ISD::VP_FP_EXTEND:
7649 case ISD::VP_FP_ROUND:
7650 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
7651 case ISD::VP_SINT_TO_FP:
7652 case ISD::VP_UINT_TO_FP:
7653 if (
Op.getValueType().isVector() &&
7654 ((
Op.getValueType().getScalarType() == MVT::f16 &&
7657 Op.getValueType().getScalarType() == MVT::bf16)) {
7670 case ISD::VP_FP_TO_SINT:
7671 case ISD::VP_FP_TO_UINT:
7673 Op1.getValueType().isVector() &&
7674 ((Op1.getValueType().getScalarType() == MVT::f16 &&
7677 Op1.getValueType().getScalarType() == MVT::bf16)) {
7683 Op1.getValueType().getVectorElementCount());
7687 {WidenVec, Op.getOperand(1), Op.getOperand(2)});
7689 return lowerVPFPIntConvOp(
Op, DAG);
7693 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
7694 return lowerVPSetCCMaskOp(
Op, DAG);
7700 case ISD::VP_BITREVERSE:
7702 return lowerVPOp(
Op, DAG);
7704 case ISD::VP_CTLZ_ZERO_UNDEF:
7705 if (Subtarget.hasStdExtZvbb())
7706 return lowerVPOp(
Op, DAG);
7707 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
7709 case ISD::VP_CTTZ_ZERO_UNDEF:
7710 if (Subtarget.hasStdExtZvbb())
7711 return lowerVPOp(
Op, DAG);
7712 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
7714 return lowerVPOp(
Op, DAG);
7715 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
7716 return lowerVPStridedLoad(
Op, DAG);
7717 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
7718 return lowerVPStridedStore(
Op, DAG);
7720 case ISD::VP_FFLOOR:
7722 case ISD::VP_FNEARBYINT:
7723 case ISD::VP_FROUND:
7724 case ISD::VP_FROUNDEVEN:
7725 case ISD::VP_FROUNDTOZERO:
7729 case ISD::VP_FMAXIMUM:
7730 case ISD::VP_FMINIMUM:
7734 case ISD::EXPERIMENTAL_VP_SPLICE:
7735 return lowerVPSpliceExperimental(
Op, DAG);
7736 case ISD::EXPERIMENTAL_VP_REVERSE:
7737 return lowerVPReverseExperimental(
Op, DAG);
7738 case ISD::EXPERIMENTAL_VP_SPLAT:
7739 return lowerVPSplatExperimental(
Op, DAG);
7742 "llvm.clear_cache only needs custom lower on Linux targets");
7745 return emitFlushICache(DAG,
Op.getOperand(0),
Op.getOperand(1),
7746 Op.getOperand(2), Flags,
DL);
7749 return lowerDYNAMIC_STACKALLOC(
Op, DAG);
7751 return lowerINIT_TRAMPOLINE(
Op, DAG);
7753 return lowerADJUST_TRAMPOLINE(
Op, DAG);
7760 MakeLibCallOptions CallOptions;
7761 std::pair<SDValue, SDValue> CallResult =
7762 makeLibCall(DAG, RTLIB::RISCV_FLUSH_ICACHE, MVT::isVoid,
7763 {Start,
End, Flags}, CallOptions,
DL, InChain);
7766 return CallResult.second;
7779 std::unique_ptr<MCCodeEmitter> CodeEmitter(
7786 const Value *TrmpAddr = cast<SrcValueSDNode>(
Op.getOperand(4))->getValue();
7798 constexpr unsigned StaticChainOffset = 16;
7799 constexpr unsigned FunctionAddressOffset = 24;
7803 auto GetEncoding = [&](
const MCInst &MC) {
7806 CodeEmitter->encodeInstruction(MC, CB, Fixups, *STI);
7816 GetEncoding(
MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X7).addImm(0)),
7821 MCInstBuilder(RISCV::LD).addReg(RISCV::X5).addReg(RISCV::X7).addImm(
7822 FunctionAddressOffset)),
7826 MCInstBuilder(RISCV::LD).addReg(RISCV::X7).addReg(RISCV::X7).addImm(
7827 StaticChainOffset)),
7846 SDValue FunctionAddress =
Op.getOperand(2);
7850 struct OffsetValuePair {
7854 } OffsetValues[] = {
7855 {StaticChainOffset, StaticChain},
7856 {FunctionAddressOffset, FunctionAddress},
7861 DAG.
getConstant(OffsetValue.Offset, dl, MVT::i64));
7862 OffsetValue.Addr =
Addr;
7863 OutChains[
Idx + 4] =
7872 SDValue EndOfTrmp = OffsetValues[0].Addr;
7886 return Op.getOperand(0);
7903 N->getOffset(), Flags);
7932template <
class NodeTy>
7934 bool IsLocal,
bool IsExternWeak)
const {
7944 if (IsLocal && !Subtarget.allowTaggedGlobals())
8014 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
8023 return getAddr(
N, DAG);
8030 return getAddr(
N, DAG);
8037 return getAddr(
N, DAG);
8042 bool UseGOT)
const {
8106 Args.push_back(Entry);
8139 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
8153 Addr = getStaticTLSAddr(
N, DAG,
false);
8156 Addr = getStaticTLSAddr(
N, DAG,
true);
8161 : getDynamicTLSAddr(
N, DAG);
8178 if (
LHS == LHS2 &&
RHS == RHS2) {
8183 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
8191 return std::nullopt;
8199 MVT VT =
N->getSimpleValueType(0);
8229 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV)) {
8232 if (~TrueVal == FalseVal) {
8272 if (Subtarget.hasShortForwardBranchOpt())
8275 unsigned SelOpNo = 0;
8285 unsigned ConstSelOpNo = 1;
8286 unsigned OtherSelOpNo = 2;
8287 if (!dyn_cast<ConstantSDNode>(Sel->
getOperand(ConstSelOpNo))) {
8292 ConstantSDNode *ConstSelOpNode = dyn_cast<ConstantSDNode>(ConstSelOp);
8293 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
8297 ConstantSDNode *ConstBinOpNode = dyn_cast<ConstantSDNode>(ConstBinOp);
8298 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
8304 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
8306 std::swap(NewConstOps[0], NewConstOps[1]);
8318 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
8320 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
8323 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
8324 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
8333 MVT VT =
Op.getSimpleValueType();
8347 if ((Subtarget.hasStdExtZicond() || Subtarget.hasVendorXVentanaCondOps()) &&
8375 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV)) {
8379 TrueVal, Subtarget.
getXLen(), Subtarget,
true);
8381 FalseVal, Subtarget.
getXLen(), Subtarget,
true);
8382 bool IsCZERO_NEZ = TrueValCost <= FalseValCost;
8384 IsCZERO_NEZ ? FalseVal - TrueVal : TrueVal - FalseVal,
DL, VT);
8389 DL, VT, LHSVal, CondV);
8405 if (
Op.hasOneUse()) {
8406 unsigned UseOpc =
Op->user_begin()->getOpcode();
8415 return lowerSELECT(NewSel, DAG);
8444 SDValue Ops[] = {CondV,
Zero, SetNE, TrueV, FalseV};
8465 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV) &&
8469 if (TrueVal - 1 == FalseVal)
8471 if (TrueVal + 1 == FalseVal)
8478 RHS == TrueV && LHS == FalseV) {
8495 if (isa<ConstantSDNode>(TrueV) && !isa<ConstantSDNode>(FalseV)) {
8521 LHS, RHS, TargetCC,
Op.getOperand(2));
8539 const Value *SV = cast<SrcValueSDNode>(
Op.getOperand(2))->getValue();
8551 int XLenInBytes = Subtarget.
getXLen() / 8;
8553 EVT VT =
Op.getValueType();
8556 unsigned Depth =
Op.getConstantOperandVal(0);
8558 int Offset = -(XLenInBytes * 2);
8575 int XLenInBytes = Subtarget.
getXLen() / 8;
8580 EVT VT =
Op.getValueType();
8582 unsigned Depth =
Op.getConstantOperandVal(0);
8584 int Off = -XLenInBytes;
8585 SDValue FrameAddr = lowerFRAMEADDR(
Op, DAG);
8604 EVT VT =
Lo.getValueType();
8643 EVT VT =
Lo.getValueType();
8694 MVT VT =
Op.getSimpleValueType();
8720 MVT VecVT =
Op.getSimpleValueType();
8722 "Unexpected SPLAT_VECTOR_PARTS lowering");
8728 MVT ContainerVT = VecVT;
8748 int64_t ExtTrueVal)
const {
8750 MVT VecVT =
Op.getSimpleValueType();
8753 assert(Src.getValueType().isVector() &&
8754 Src.getValueType().getVectorElementType() == MVT::i1);
8775 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
8777 DAG.
getUNDEF(ContainerVT), SplatTrueVal, VL);
8780 SplatZero, DAG.
getUNDEF(ContainerVT), VL);
8785SDValue RISCVTargetLowering::lowerFixedLengthVectorExtendToRVV(
8787 MVT ExtVT =
Op.getSimpleValueType();
8791 MVT VT =
Op.getOperand(0).getSimpleValueType();
8817 bool IsVPTrunc =
Op.getOpcode() == ISD::VP_TRUNCATE;
8819 EVT MaskVT =
Op.getValueType();
8822 "Unexpected type for vector mask lowering");
8824 MVT VecVT = Src.getSimpleValueType();
8828 VL =
Op.getOperand(2);
8831 MVT ContainerVT = VecVT;
8837 MVT MaskContainerVT =
8844 std::tie(Mask, VL) =
8852 DAG.
getUNDEF(ContainerVT), SplatOne, VL);
8854 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
8858 DAG.
getUNDEF(ContainerVT), Mask, VL);
8861 DAG.
getUNDEF(MaskContainerVT), Mask, VL});
8869 unsigned Opc =
Op.getOpcode();
8870 bool IsVPTrunc = Opc == ISD::VP_TRUNCATE;
8873 MVT VT =
Op.getSimpleValueType();
8875 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
8879 return lowerVectorMaskTruncLike(
Op, DAG);
8887 MVT SrcVT = Src.getSimpleValueType();
8892 "Unexpected vector truncate lowering");
8894 MVT ContainerVT = SrcVT;
8898 VL =
Op.getOperand(2);
8911 std::tie(Mask, VL) =
8927 }
while (SrcEltVT != DstEltVT);
8936RISCVTargetLowering::lowerStrictFPExtendOrRoundLike(
SDValue Op,
8941 MVT VT =
Op.getSimpleValueType();
8942 MVT SrcVT = Src.getSimpleValueType();
8943 MVT ContainerVT = VT;
8966 Chain, Src, Mask, VL);
8967 Chain = Src.getValue(1);
8974 Chain, Src, Mask, VL);
8985RISCVTargetLowering::lowerVectorFPExtendOrRoundLike(
SDValue Op,
8988 Op.getOpcode() == ISD::VP_FP_ROUND ||
Op.getOpcode() == ISD::VP_FP_EXTEND;
8995 MVT VT =
Op.getSimpleValueType();
8997 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
9000 MVT SrcVT = Src.getSimpleValueType();
9002 bool IsDirectExtend =
9010 bool IsDirectConv = IsDirectExtend || IsDirectTrunc;
9013 MVT ContainerVT = VT;
9017 VL =
Op.getOperand(2);
9031 std::tie(Mask, VL) =
9037 Src = DAG.
getNode(ConvOpc,
DL, ContainerVT, Src, Mask, VL);
9043 unsigned InterConvOpc =
9048 DAG.
getNode(InterConvOpc,
DL, InterVT, Src, Mask, VL);
9050 DAG.
getNode(ConvOpc,
DL, ContainerVT, IntermediateConv, Mask, VL);
9061static std::optional<MVT>
9067 const unsigned MinVLMAX = VectorBitsMin / EltSize;
9069 if (MaxIdx < MinVLMAX)
9071 else if (MaxIdx < MinVLMAX * 2)
9073 else if (MaxIdx < MinVLMAX * 4)
9078 return std::nullopt;
9091 MVT VecVT =
Op.getSimpleValueType();
9108 ValVT == MVT::bf16) {
9117 MVT ContainerVT = VecVT;
9126 MVT OrigContainerVT = ContainerVT;
9129 if (
auto *IdxC = dyn_cast<ConstantSDNode>(
Idx)) {
9130 const unsigned OrigIdx = IdxC->getZExtValue();
9133 DL, DAG, Subtarget)) {
9134 ContainerVT = *ShrunkVT;
9143 VLEN && ContainerVT.
bitsGT(M1VT)) {
9146 unsigned RemIdx = OrigIdx % ElemsPerVReg;
9147 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
9148 unsigned ExtractIdx =
9165 if (!IsLegalInsert && isa<ConstantSDNode>(Val)) {
9166 const auto *CVal = cast<ConstantSDNode>(Val);
9167 if (isInt<32>(CVal->getSExtValue())) {
9168 IsLegalInsert =
true;
9177 if (IsLegalInsert) {
9183 Vec = DAG.
getNode(Opc,
DL, ContainerVT, Vec, Val, VL);
9199 std::tie(ValLo, ValHi) = DAG.
SplitScalar(Val,
DL, MVT::i32, MVT::i32);
9200 MVT I32ContainerVT =
9211 Vec, Vec, ValLo, I32Mask, InsertI64VL);
9216 Tail, ValInVec, ValHi, I32Mask, InsertI64VL);
9218 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
9223 ValInVec, AlignedIdx);
9233 DAG.
getUNDEF(I32ContainerVT), ValLo,
9234 I32Mask, InsertI64VL);
9236 DAG.
getUNDEF(I32ContainerVT), ValInVec, ValHi,
9237 I32Mask, InsertI64VL);
9239 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
9252 Idx, Mask, InsertVL, Policy);
9256 Slideup, AlignedIdx);
9271 EVT EltVT =
Op.getValueType();
9278 MVT ContainerVT = VecVT;
9294 unsigned WidenVecLen;
9297 unsigned MaxEEW = Subtarget.
getELen();
9302 "the number of elements should be power of 2");
9306 ExtractBitIdx =
Idx;
9308 WideEltVT = LargestEltVT;
9311 ExtractElementIdx = DAG.
getNode(
9322 Vec, ExtractElementIdx);
9338 EltVT == MVT::bf16) {
9348 MVT ContainerVT = VecVT;
9359 if (
auto *IdxC = dyn_cast<ConstantSDNode>(
Idx);
9360 IdxC && VLen && VecVT.
getSizeInBits().getKnownMinValue() > *VLen) {
9362 unsigned OrigIdx = IdxC->getZExtValue();
9365 unsigned RemIdx = OrigIdx % ElemsPerVReg;
9366 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
9367 unsigned ExtractIdx =
9377 std::optional<uint64_t> MaxIdx;
9380 if (
auto *IdxC = dyn_cast<ConstantSDNode>(
Idx))
9381 MaxIdx = IdxC->getZExtValue();
9383 if (
auto SmallerVT =
9385 ContainerVT = *SmallerVT;
9432 "Unexpected opcode");
9439 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
9444 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
9445 if (!
II || !
II->hasScalarOperand())
9448 unsigned SplatOp =
II->ScalarOperand + 1 + HasChain;
9461 if (OpVT.
bitsLT(XLenVT)) {
9468 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
9478 assert(
II->ScalarOperand > 0 &&
"Unexpected splat operand!");
9479 MVT VT =
Op.getOperand(SplatOp - 1).getSimpleValueType();
9482 assert(XLenVT == MVT::i32 && OpVT == MVT::i64 &&
9493 case Intrinsic::riscv_vslide1up:
9494 case Intrinsic::riscv_vslide1down:
9495 case Intrinsic::riscv_vslide1up_mask:
9496 case Intrinsic::riscv_vslide1down_mask: {
9499 bool IsMasked = NumOps == 7;
9505 std::tie(ScalarLo, ScalarHi) =
9513 if (isa<ConstantSDNode>(AVL)) {
9514 const auto [MinVLMAX, MaxVLMAX] =
9518 if (AVLInt <= MinVLMAX) {
9520 }
else if (AVLInt >= 2 * MaxVLMAX) {
9554 if (IntNo == Intrinsic::riscv_vslide1up ||
9555 IntNo == Intrinsic::riscv_vslide1up_mask) {
9557 ScalarHi, I32Mask, I32VL);
9559 ScalarLo, I32Mask, I32VL);
9562 ScalarLo, I32Mask, I32VL);
9564 ScalarHi, I32Mask, I32VL);
9613 const unsigned ElementWidth = 8;
9618 [[maybe_unused]]
unsigned MinVF =
9621 [[maybe_unused]]
unsigned VF =
N->getConstantOperandVal(2);
9625 bool Fractional = VF < LMul1VF;
9626 unsigned LMulVal = Fractional ? LMul1VF / VF : VF / LMul1VF;
9647 MVT ContainerVT = OpVT;
9674 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
9678 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
9679 if (!
II || !
II->hasScalarOperand())
9682 unsigned SplatOp =
II->ScalarOperand + 1;
9695 if (OpVT.
bitsLT(XLenVT)) {
9698 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
9709 EVT ValType = V.getValueType();
9710 if (ValType.isVector() && ValType.isFloatingPoint()) {
9713 ValType.getVectorElementCount());
9716 if (ValType.isFixedLengthVector()) {
9718 DAG, V.getSimpleValueType(), Subtarget);
9734 unsigned IntNo =
Op.getConstantOperandVal(0);
9741 case Intrinsic::riscv_tuple_insert: {
9749 case Intrinsic::riscv_tuple_extract: {
9756 case Intrinsic::thread_pointer: {
9760 case Intrinsic::riscv_orc_b:
9761 case Intrinsic::riscv_brev8:
9762 case Intrinsic::riscv_sha256sig0:
9763 case Intrinsic::riscv_sha256sig1:
9764 case Intrinsic::riscv_sha256sum0:
9765 case Intrinsic::riscv_sha256sum1:
9766 case Intrinsic::riscv_sm3p0:
9767 case Intrinsic::riscv_sm3p1: {
9780 return DAG.
getNode(Opc,
DL, XLenVT,
Op.getOperand(1));
9782 case Intrinsic::riscv_sm4ks:
9783 case Intrinsic::riscv_sm4ed: {
9787 return DAG.
getNode(Opc,
DL, XLenVT,
Op.getOperand(1),
Op.getOperand(2),
9790 case Intrinsic::riscv_zip:
9791 case Intrinsic::riscv_unzip: {
9794 return DAG.
getNode(Opc,
DL, XLenVT,
Op.getOperand(1));
9796 case Intrinsic::riscv_mopr:
9800 case Intrinsic::riscv_moprr: {
9802 Op.getOperand(2),
Op.getOperand(3));
9804 case Intrinsic::riscv_clmul:
9807 case Intrinsic::riscv_clmulh:
9808 case Intrinsic::riscv_clmulr: {
9811 return DAG.
getNode(Opc,
DL, XLenVT,
Op.getOperand(1),
Op.getOperand(2));
9813 case Intrinsic::experimental_get_vector_length:
9815 case Intrinsic::experimental_cttz_elts:
9817 case Intrinsic::riscv_vmv_x_s: {
9821 case Intrinsic::riscv_vfmv_f_s:
9824 case Intrinsic::riscv_vmv_v_x:
9826 Op.getOperand(3),
Op.getSimpleValueType(),
DL, DAG,
9828 case Intrinsic::riscv_vfmv_v_f:
9830 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
9831 case Intrinsic::riscv_vmv_s_x: {
9834 if (
Scalar.getValueType().bitsLE(XLenVT)) {
9837 Op.getOperand(1), Scalar,
Op.getOperand(3));
9840 assert(
Scalar.getValueType() == MVT::i64 &&
"Unexpected scalar VT!");
9857 MVT VT =
Op.getSimpleValueType();
9862 if (
Op.getOperand(1).isUndef())
9878 case Intrinsic::riscv_vfmv_s_f:
9880 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
9882 case Intrinsic::riscv_vaesdf_vv:
9883 case Intrinsic::riscv_vaesdf_vs:
9884 case Intrinsic::riscv_vaesdm_vv:
9885 case Intrinsic::riscv_vaesdm_vs:
9886 case Intrinsic::riscv_vaesef_vv:
9887 case Intrinsic::riscv_vaesef_vs:
9888 case Intrinsic::riscv_vaesem_vv:
9889 case Intrinsic::riscv_vaesem_vs:
9890 case Intrinsic::riscv_vaeskf1:
9891 case Intrinsic::riscv_vaeskf2:
9892 case Intrinsic::riscv_vaesz_vs:
9893 case Intrinsic::riscv_vsm4k:
9894 case Intrinsic::riscv_vsm4r_vv:
9895 case Intrinsic::riscv_vsm4r_vs: {
9896 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
9897 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
9898 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
9903 case Intrinsic::riscv_vsm3c:
9904 case Intrinsic::riscv_vsm3me: {
9905 if (!
isValidEGW(8,
Op.getSimpleValueType(), Subtarget) ||
9906 !
isValidEGW(8,
Op->getOperand(1).getSimpleValueType(), Subtarget))
9911 case Intrinsic::riscv_vsha2ch:
9912 case Intrinsic::riscv_vsha2cl:
9913 case Intrinsic::riscv_vsha2ms: {
9914 if (
Op->getSimpleValueType(0).getScalarSizeInBits() == 64 &&
9915 !Subtarget.hasStdExtZvknhb())
9917 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
9918 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
9919 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
9923 case Intrinsic::riscv_sf_vc_v_x:
9924 case Intrinsic::riscv_sf_vc_v_i:
9925 case Intrinsic::riscv_sf_vc_v_xv:
9926 case Intrinsic::riscv_sf_vc_v_iv:
9927 case Intrinsic::riscv_sf_vc_v_vv:
9928 case Intrinsic::riscv_sf_vc_v_fv:
9929 case Intrinsic::riscv_sf_vc_v_xvv:
9930 case Intrinsic::riscv_sf_vc_v_ivv:
9931 case Intrinsic::riscv_sf_vc_v_vvv:
9932 case Intrinsic::riscv_sf_vc_v_fvv:
9933 case Intrinsic::riscv_sf_vc_v_xvw:
9934 case Intrinsic::riscv_sf_vc_v_ivw:
9935 case Intrinsic::riscv_sf_vc_v_vvw:
9936 case Intrinsic::riscv_sf_vc_v_fvw: {
9937 MVT VT =
Op.getSimpleValueType();
9974 MVT VT =
Op.getSimpleValueType();
9978 if (VT.isFloatingPoint()) {
9983 if (VT.isFixedLengthVector())
9993 if (VT.isFixedLengthVector())
9995 if (VT.isFloatingPoint())
10014 unsigned IntNo =
Op.getConstantOperandVal(1);
10018 case Intrinsic::riscv_seg2_load:
10019 case Intrinsic::riscv_seg3_load:
10020 case Intrinsic::riscv_seg4_load:
10021 case Intrinsic::riscv_seg5_load:
10022 case Intrinsic::riscv_seg6_load:
10023 case Intrinsic::riscv_seg7_load:
10024 case Intrinsic::riscv_seg8_load: {
10027 Intrinsic::riscv_vlseg2, Intrinsic::riscv_vlseg3,
10028 Intrinsic::riscv_vlseg4, Intrinsic::riscv_vlseg5,
10029 Intrinsic::riscv_vlseg6, Intrinsic::riscv_vlseg7,
10030 Intrinsic::riscv_vlseg8};
10031 unsigned NF =
Op->getNumValues() - 1;
10032 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
10034 MVT VT =
Op->getSimpleValueType(0);
10042 auto *
Load = cast<MemIntrinsicSDNode>(
Op);
10054 Load->getMemoryVT(),
Load->getMemOperand());
10056 for (
unsigned int RetIdx = 0; RetIdx < NF; RetIdx++) {
10065 case Intrinsic::riscv_sf_vc_v_x_se:
10067 case Intrinsic::riscv_sf_vc_v_i_se:
10069 case Intrinsic::riscv_sf_vc_v_xv_se:
10071 case Intrinsic::riscv_sf_vc_v_iv_se:
10073 case Intrinsic::riscv_sf_vc_v_vv_se:
10075 case Intrinsic::riscv_sf_vc_v_fv_se:
10077 case Intrinsic::riscv_sf_vc_v_xvv_se:
10079 case Intrinsic::riscv_sf_vc_v_ivv_se:
10081 case Intrinsic::riscv_sf_vc_v_vvv_se:
10083 case Intrinsic::riscv_sf_vc_v_fvv_se:
10085 case Intrinsic::riscv_sf_vc_v_xvw_se:
10087 case Intrinsic::riscv_sf_vc_v_ivw_se:
10089 case Intrinsic::riscv_sf_vc_v_vvw_se:
10091 case Intrinsic::riscv_sf_vc_v_fvw_se:
10100 unsigned IntNo =
Op.getConstantOperandVal(1);
10104 case Intrinsic::riscv_seg2_store:
10105 case Intrinsic::riscv_seg3_store:
10106 case Intrinsic::riscv_seg4_store:
10107 case Intrinsic::riscv_seg5_store:
10108 case Intrinsic::riscv_seg6_store:
10109 case Intrinsic::riscv_seg7_store:
10110 case Intrinsic::riscv_seg8_store: {
10113 Intrinsic::riscv_vsseg2, Intrinsic::riscv_vsseg3,
10114 Intrinsic::riscv_vsseg4, Intrinsic::riscv_vsseg5,
10115 Intrinsic::riscv_vsseg6, Intrinsic::riscv_vsseg7,
10116 Intrinsic::riscv_vsseg8};
10119 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
10121 MVT VT =
Op->getOperand(2).getSimpleValueType();
10131 auto *FixedIntrinsic = cast<MemIntrinsicSDNode>(
Op);
10134 for (
unsigned i = 0; i < NF; i++)
10138 ContainerVT, FixedIntrinsic->getOperand(2 + i), DAG, Subtarget),
10142 FixedIntrinsic->getChain(),
10151 FixedIntrinsic->getMemoryVT(), FixedIntrinsic->getMemOperand());
10153 case Intrinsic::riscv_sf_vc_xv_se:
10155 case Intrinsic::riscv_sf_vc_iv_se:
10157 case Intrinsic::riscv_sf_vc_vv_se:
10159 case Intrinsic::riscv_sf_vc_fv_se:
10161 case Intrinsic::riscv_sf_vc_xvv_se:
10163 case Intrinsic::riscv_sf_vc_ivv_se:
10165 case Intrinsic::riscv_sf_vc_vvv_se:
10167 case Intrinsic::riscv_sf_vc_fvv_se:
10169 case Intrinsic::riscv_sf_vc_xvw_se:
10171 case Intrinsic::riscv_sf_vc_ivw_se:
10173 case Intrinsic::riscv_sf_vc_vvw_se:
10175 case Intrinsic::riscv_sf_vc_fvw_se:
10183 switch (ISDOpcode) {
10186 case ISD::VP_REDUCE_ADD:
10189 case ISD::VP_REDUCE_UMAX:
10192 case ISD::VP_REDUCE_SMAX:
10195 case ISD::VP_REDUCE_UMIN:
10198 case ISD::VP_REDUCE_SMIN:
10201 case ISD::VP_REDUCE_AND:
10204 case ISD::VP_REDUCE_OR:
10207 case ISD::VP_REDUCE_XOR:
10210 case ISD::VP_REDUCE_FADD:
10212 case ISD::VP_REDUCE_SEQ_FADD:
10214 case ISD::VP_REDUCE_FMAX:
10215 case ISD::VP_REDUCE_FMAXIMUM:
10217 case ISD::VP_REDUCE_FMIN:
10218 case ISD::VP_REDUCE_FMINIMUM:
10228 SDValue Vec =
Op.getOperand(IsVP ? 1 : 0);
10233 Op.getOpcode() == ISD::VP_REDUCE_AND ||
10234 Op.getOpcode() == ISD::VP_REDUCE_OR ||
10235 Op.getOpcode() == ISD::VP_REDUCE_XOR) &&
10236 "Unexpected reduction lowering");
10240 MVT ContainerVT = VecVT;
10248 Mask =
Op.getOperand(2);
10249 VL =
Op.getOperand(3);
10251 std::tie(Mask, VL) =
10256 switch (
Op.getOpcode()) {
10260 case ISD::VP_REDUCE_AND: {
10272 case ISD::VP_REDUCE_OR:
10278 case ISD::VP_REDUCE_XOR: {
10302 return DAG.
getNode(BaseOpc,
DL,
Op.getValueType(), SetCC,
Op.getOperand(0));
10306 auto *RegisterAVL = dyn_cast<RegisterSDNode>(AVL);
10307 auto *ImmAVL = dyn_cast<ConstantSDNode>(AVL);
10308 return (RegisterAVL && RegisterAVL->getReg() == RISCV::X0) ||
10309 (ImmAVL && ImmAVL->getZExtValue() >= 1);
10325 auto InnerVT = VecVT.
bitsLE(M1VT) ? VecVT : M1VT;
10329 auto InnerVL = NonZeroAVL ? VL : DAG.
getConstant(1,
DL, XLenVT);
10332 if (M1VT != InnerVT)
10338 SDValue Ops[] = {PassThru, Vec, InitialValue, Mask, VL, Policy};
10357 VecEVT =
Lo.getValueType();
10370 MVT ContainerVT = VecVT;
10390 Mask, VL,
DL, DAG, Subtarget);
10396static std::tuple<unsigned, SDValue, SDValue>
10400 auto Flags =
Op->getFlags();
10401 unsigned Opcode =
Op.getOpcode();
10425 return std::make_tuple(RVVOpc,
Op.getOperand(0), Front);
10433 MVT VecEltVT =
Op.getSimpleValueType();
10435 unsigned RVVOpcode;
10436 SDValue VectorVal, ScalarVal;
10437 std::tie(RVVOpcode, VectorVal, ScalarVal) =
10441 MVT ContainerVT = VecVT;
10447 MVT ResVT =
Op.getSimpleValueType();
10450 VL,
DL, DAG, Subtarget);
10455 if (
Op->getFlags().hasNoNaNs())
10461 {VectorVal, VectorVal, DAG.getCondCode(ISD::SETNE),
10462 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
10468 DL, ResVT, NoNaNs, Res,
10475 unsigned Opc =
Op.getOpcode();
10498 Vec, Mask, VL,
DL, DAG, Subtarget);
10499 if ((Opc != ISD::VP_REDUCE_FMINIMUM && Opc != ISD::VP_REDUCE_FMAXIMUM) ||
10500 Op->getFlags().hasNoNaNs())
10517 DL, ResVT, NoNaNs, Res,
10530 unsigned OrigIdx =
Op.getConstantOperandVal(2);
10533 if (OrigIdx == 0 && Vec.
isUndef())
10544 assert(OrigIdx % 8 == 0 &&
"Invalid index");
10547 "Unexpected mask vector lowering");
10579 MVT ContainerVT = VecVT;
10586 DAG.
getUNDEF(ContainerVT), SubVec,
10603 if (OrigIdx == 0) {
10608 SubVec =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, Vec, SubVec,
10609 SlideupAmt, Mask, VL, Policy);
10617 MVT ContainerVecVT = VecVT;
10623 MVT ContainerSubVecVT = SubVecVT;
10629 unsigned SubRegIdx;
10639 ContainerVecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
10640 SubRegIdx = Decompose.first;
10642 (OrigIdx % Vscale));
10646 ContainerVecVT, ContainerSubVecVT, OrigIdx,
TRI);
10647 SubRegIdx = Decompose.first;
10654 bool ExactlyVecRegSized =
10656 .isKnownMultipleOf(Subtarget.
expandVScale(VecRegSize));
10671 if (RemIdx.
isZero() && (ExactlyVecRegSized || Vec.
isUndef())) {
10675 if (SubRegIdx == RISCV::NoSubRegister) {
10698 MVT InterSubVT = ContainerVecVT;
10699 SDValue AlignedExtract = Vec;
10739 SubVec =
getVSlideup(DAG, Subtarget,
DL, InterSubVT, AlignedExtract, SubVec,
10740 SlideupAmt, Mask, VL, Policy);
10745 if (ContainerVecVT.
bitsGT(InterSubVT))
10754 return DAG.
getBitcast(
Op.getSimpleValueType(), SubVec);
10760 MVT SubVecVT =
Op.getSimpleValueType();
10765 unsigned OrigIdx =
Op.getConstantOperandVal(1);
10781 assert(OrigIdx % 8 == 0 &&
"Invalid index");
10784 "Unexpected mask vector lowering");
10818 MVT ContainerVT = VecVT;
10826 if (
auto ShrunkVT =
10828 ContainerVT = *ShrunkVT;
10841 DAG.
getUNDEF(ContainerVT), Vec, SlidedownAmt, Mask, VL);
10853 MVT ContainerSubVecVT = SubVecVT;
10857 unsigned SubRegIdx;
10867 VecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
10868 SubRegIdx = Decompose.first;
10870 (OrigIdx % Vscale));
10874 VecVT, ContainerSubVecVT, OrigIdx,
TRI);
10875 SubRegIdx = Decompose.first;
10902 MVT InterSubVT = VecVT;
10907 assert(SubRegIdx != RISCV::NoSubRegister);
10927 Vec, SlidedownAmt, Mask, VL);
10936 return DAG.
getBitcast(
Op.getSimpleValueType(), Slidedown);
10943 MVT VT =
N.getSimpleValueType();
10947 assert(
Op.getSimpleValueType() == VT &&
10948 "Operands and result must be same type");
10952 unsigned NumVals =
N->getNumValues();
10955 NumVals,
N.getValueType().changeVectorElementType(MVT::i8)));
10958 for (
unsigned I = 0;
I < NumVals;
I++) {
10964 if (TruncVals.
size() > 1)
10966 return TruncVals.
front();
10972 MVT VecVT =
Op.getSimpleValueType();
10975 "vector_interleave on non-scalable vector!");
10986 EVT SplitVT = Op0Lo.getValueType();
10989 DAG.
getVTList(SplitVT, SplitVT), Op0Lo, Op0Hi);
10991 DAG.
getVTList(SplitVT, SplitVT), Op1Lo, Op1Hi);
11005 Op.getOperand(0),
Op.getOperand(1));
11024 EvenSplat = DAG.
getBitcast(MVT::nxv64i1, EvenSplat);
11029 OddSplat = DAG.
getBitcast(MVT::nxv64i1, OddSplat);
11035 EvenMask, DAG.
getUNDEF(ConcatVT));
11051 MVT VecVT =
Op.getSimpleValueType();
11054 "vector_interleave on non-scalable vector!");
11067 EVT SplitVT = Op0Lo.getValueType();
11070 DAG.
getVTList(SplitVT, SplitVT), Op0Lo, Op1Lo);
11072 DAG.
getVTList(SplitVT, SplitVT), Op0Hi, Op1Hi);
11094 Op.getOperand(0),
Op.getOperand(1));
11142 MVT VT =
Op.getSimpleValueType();
11147 uint64_t StepValImm =
Op.getConstantOperandVal(0);
11148 if (StepValImm != 1) {
11157 VL, VT,
DL, DAG, Subtarget);
11172 MVT VecVT =
Op.getSimpleValueType();
11181 MVT ContainerVT = VecVT;
11235 unsigned MaxVLMAX =
11245 if (MaxVLMAX > 256 && EltSize == 8) {
11274 assert(isUInt<16>(MaxVLMAX - 1));
11300 DAG.
getUNDEF(ContainerVT), Mask, VL);
11312 MVT VecVT =
Op.getSimpleValueType();
11316 int64_t ImmValue = cast<ConstantSDNode>(
Op.getOperand(2))->getSExtValue();
11317 SDValue DownOffset, UpOffset;
11318 if (ImmValue >= 0) {
11334 DownOffset, TrueMask, UpOffset);
11335 return getVSlideup(DAG, Subtarget,
DL, VecVT, SlideDown, V2, UpOffset,
11341RISCVTargetLowering::lowerFixedLengthVectorLoadToRVV(
SDValue Op,
11344 auto *
Load = cast<LoadSDNode>(
Op);
11347 Load->getMemoryVT(),
11348 *
Load->getMemOperand()) &&
11349 "Expecting a correctly-aligned load");
11351 MVT VT =
Op.getSimpleValueType();
11357 const auto [MinVLMAX, MaxVLMAX] =
11360 getLMUL1VT(ContainerVT).bitsLE(ContainerVT)) {
11374 IsMaskOp ? Intrinsic::riscv_vlm : Intrinsic::riscv_vle,
DL, XLenVT);
11377 Ops.push_back(DAG.
getUNDEF(ContainerVT));
11378 Ops.push_back(
Load->getBasePtr());
11383 Load->getMemoryVT(),
Load->getMemOperand());
11390RISCVTargetLowering::lowerFixedLengthVectorStoreToRVV(
SDValue Op,
11393 auto *
Store = cast<StoreSDNode>(
Op);
11396 Store->getMemoryVT(),
11397 *
Store->getMemOperand()) &&
11398 "Expecting a correctly-aligned store");
11419 const auto [MinVLMAX, MaxVLMAX] =
11422 getLMUL1VT(ContainerVT).bitsLE(ContainerVT)) {
11433 IsMaskOp ? Intrinsic::riscv_vsm : Intrinsic::riscv_vse,
DL, XLenVT);
11436 {Store->getChain(), IntID, NewValue, Store->getBasePtr(), VL},
11437 Store->getMemoryVT(),
Store->getMemOperand());
11443 MVT VT =
Op.getSimpleValueType();
11445 const auto *MemSD = cast<MemSDNode>(
Op);
11446 EVT MemVT = MemSD->getMemoryVT();
11448 SDValue Chain = MemSD->getChain();
11452 bool IsExpandingLoad =
false;
11453 if (
const auto *VPLoad = dyn_cast<VPLoadSDNode>(
Op)) {
11454 Mask = VPLoad->getMask();
11456 VL = VPLoad->getVectorLength();
11458 const auto *MLoad = cast<MaskedLoadSDNode>(
Op);
11459 Mask = MLoad->getMask();
11460 PassThru = MLoad->getPassThru();
11461 IsExpandingLoad = MLoad->isExpandingLoad();
11468 MVT ContainerVT = VT;
11482 if (!IsUnmasked && IsExpandingLoad) {
11489 unsigned IntID = IsUnmasked || IsExpandingLoad ? Intrinsic::riscv_vle
11490 : Intrinsic::riscv_vle_mask;
11492 if (IntID == Intrinsic::riscv_vle)
11493 Ops.push_back(DAG.
getUNDEF(ContainerVT));
11495 Ops.push_back(PassThru);
11496 Ops.push_back(BasePtr);
11497 if (IntID == Intrinsic::riscv_vle_mask)
11498 Ops.push_back(Mask);
11500 if (IntID == Intrinsic::riscv_vle_mask)
11507 Chain =
Result.getValue(1);
11509 MVT IndexVT = ContainerVT;
11514 bool UseVRGATHEREI16 =
false;
11522 UseVRGATHEREI16 =
true;
11528 DAG.
getUNDEF(IndexVT), Mask, ExpandingVL);
11532 DL, ContainerVT, Result, Iota, PassThru, Mask, ExpandingVL);
11545 const auto *MemSD = cast<MemSDNode>(
Op);
11546 EVT MemVT = MemSD->getMemoryVT();
11548 SDValue Chain = MemSD->getChain();
11552 bool IsCompressingStore =
false;
11553 if (
const auto *VPStore = dyn_cast<VPStoreSDNode>(
Op)) {
11554 Val = VPStore->getValue();
11555 Mask = VPStore->getMask();
11556 VL = VPStore->getVectorLength();
11558 const auto *MStore = cast<MaskedStoreSDNode>(
Op);
11559 Val = MStore->getValue();
11560 Mask = MStore->getMask();
11561 IsCompressingStore = MStore->isCompressingStore();
11570 MVT ContainerVT = VT;
11575 if (!IsUnmasked || IsCompressingStore) {
11584 if (IsCompressingStore) {
11587 DAG.
getUNDEF(ContainerVT), Val, Mask, VL);
11594 IsUnmasked ? Intrinsic::riscv_vse : Intrinsic::riscv_vse_mask;
11596 Ops.push_back(Val);
11597 Ops.push_back(BasePtr);
11599 Ops.push_back(Mask);
11603 DAG.
getVTList(MVT::Other), Ops, MemVT, MMO);
11615 MVT ContainerVT = VT;
11628 Passthru, Val, Mask, VL);
11637RISCVTargetLowering::lowerFixedLengthVectorSetccToRVV(
SDValue Op,
11639 MVT InVT =
Op.getOperand(0).getSimpleValueType();
11642 MVT VT =
Op.getSimpleValueType();
11656 {Op1, Op2,
Op.getOperand(2), DAG.
getUNDEF(MaskVT), Mask, VL});
11663 unsigned Opc =
Op.getOpcode();
11670 MVT VT =
Op.getSimpleValueType();
11703 MVT ContainerInVT = InVT;
11722 {Chain, Op1, Op1, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
11726 {Chain, Op2, Op2, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
11734 {Chain, Op1, Op2, CC, Mask, Mask, VL});
11739 {Chain, Op1, Op2, CC, DAG.getUNDEF(MaskVT), Mask, VL});
11752 MVT VT =
Op.getSimpleValueType();
11756 "Unexpected type for ISD::ABS");
11758 MVT ContainerVT = VT;
11765 if (
Op->getOpcode() == ISD::VP_ABS) {
11766 Mask =
Op->getOperand(1);
11770 VL =
Op->getOperand(2);
11778 DAG.
getUNDEF(ContainerVT), Mask, VL);
11780 DAG.
getUNDEF(ContainerVT), Mask, VL);
11787SDValue RISCVTargetLowering::lowerFixedLengthVectorFCOPYSIGNToRVV(
11790 MVT VT =
Op.getSimpleValueType();
11794 "Can only handle COPYSIGN with matching types.");
11803 Sign, DAG.
getUNDEF(ContainerVT), Mask, VL);
11808SDValue RISCVTargetLowering::lowerFixedLengthVectorSelectToRVV(
11810 MVT VT =
Op.getSimpleValueType();
11813 MVT I1ContainerVT =
11827 Op2, DAG.
getUNDEF(ContainerVT), VL);
11838 MVT VT =
Op.getSimpleValueType();
11843 for (
const SDValue &V :
Op->op_values()) {
11844 assert(!isa<VTSDNode>(V) &&
"Unexpected VTSDNode node!");
11847 if (!
V.getValueType().isVector()) {
11853 assert(useRVVForFixedLengthVectorVT(
V.getSimpleValueType()) &&
11854 "Only fixed length vectors are supported!");
11868 if (
Op->isStrictFPOpcode()) {
11877 DAG.
getNode(NewOpc,
DL, ContainerVT, Ops,
Op->getFlags());
11891 MVT VT =
Op.getSimpleValueType();
11894 MVT ContainerVT = VT;
11900 assert(!isa<VTSDNode>(V) &&
"Unexpected VTSDNode node!");
11903 if (HasPassthruOp) {
11906 if (*MaskIdx == OpIdx.index())
11910 if (
Op.getOpcode() == ISD::VP_MERGE) {
11914 assert(
Op.getOpcode() == ISD::VP_SELECT);
11926 if (!
V.getValueType().isFixedLengthVector()) {
11931 MVT OpVT =
V.getSimpleValueType();
11933 assert(useRVVForFixedLengthVectorVT(OpVT) &&
11934 "Only fixed length vectors are supported!");
11939 return DAG.
getNode(RISCVISDOpc,
DL, VT, Ops,
Op->getFlags());
11949 MVT VT =
Op.getSimpleValueType();
11955 MVT ContainerVT = VT;
11965 DAG.
getUNDEF(ContainerVT), Zero, VL);
11968 Op.getOpcode() == ISD::VP_ZERO_EXTEND ? 1 : -1,
DL, XLenVT);
11970 DAG.
getUNDEF(ContainerVT), SplatValue, VL);
11973 ZeroSplat, DAG.
getUNDEF(ContainerVT), VL);
11982 MVT VT =
Op.getSimpleValueType();
11986 ISD::CondCode Condition = cast<CondCodeSDNode>(
Op.getOperand(2))->get();
11990 MVT ContainerVT = VT;
12000 switch (Condition) {
12068 MVT DstVT =
Op.getSimpleValueType();
12069 MVT SrcVT = Src.getSimpleValueType();
12082 if (DstEltSize >= SrcEltSize) {
12091 if (SrcEltSize == 1) {
12102 ZeroSplat, DAG.
getUNDEF(IntVT), VL);
12103 }
else if (DstEltSize > (2 * SrcEltSize)) {
12107 Src = DAG.
getNode(RISCVISDExtOpc,
DL, IntVT, Src, Mask, VL);
12113 "Wrong input/output vector types");
12116 if (DstEltSize > (2 * SrcEltSize)) {
12132 MVT InterimFVT = DstVT;
12133 if (SrcEltSize > (2 * DstEltSize)) {
12134 assert(SrcEltSize == (4 * DstEltSize) &&
"Unexpected types!");
12141 if (InterimFVT != DstVT) {
12147 "Wrong input/output vector types");
12151 if (DstEltSize == 1) {
12154 assert(SrcEltSize >= 16 &&
"Unexpected FP type!");
12164 DAG.
getUNDEF(InterimIVT), SplatZero, VL);
12174 while (InterimIVT != DstVT) {
12186 MVT VT =
Op.getSimpleValueType();
12195 MVT VT =
Op.getSimpleValueType();
12209 MVT ContainerVT = VT;
12230 SplatZero, DAG.
getUNDEF(PromotedVT), VL);
12233 SplatOne, SplatZero, DAG.
getUNDEF(PromotedVT), VLMax);
12237 TrueVal, FalseVal, FalseVal, VL);
12252RISCVTargetLowering::lowerVPSpliceExperimental(
SDValue Op,
12264 MVT VT =
Op.getSimpleValueType();
12265 MVT ContainerVT = VT;
12275 if (IsMaskVector) {
12286 SplatZeroOp1, DAG.
getUNDEF(ContainerVT), EVL1);
12295 SplatZeroOp2, DAG.
getUNDEF(ContainerVT), EVL2);
12298 int64_t ImmValue = cast<ConstantSDNode>(
Offset)->getSExtValue();
12299 SDValue DownOffset, UpOffset;
12300 if (ImmValue >= 0) {
12314 Op1, DownOffset, Mask, UpOffset);
12318 if (IsMaskVector) {
12322 {Result, DAG.getConstant(0, DL, ContainerVT),
12323 DAG.getCondCode(ISD::SETNE), DAG.getUNDEF(getMaskTypeFor(ContainerVT)),
12338 MVT VT =
Op.getSimpleValueType();
12340 MVT ContainerVT = VT;
12356RISCVTargetLowering::lowerVPReverseExperimental(
SDValue Op,
12359 MVT VT =
Op.getSimpleValueType();
12366 MVT ContainerVT = VT;
12374 MVT GatherVT = ContainerVT;
12378 if (IsMaskVector) {
12389 SplatZero, DAG.
getUNDEF(IndicesVT), EVL);
12395 unsigned MaxVLMAX =
12404 if (MaxVLMAX > 256 && EltSize == 8) {
12432 DAG.
getUNDEF(GatherVT), Result, Diff, Mask, EVL);
12434 if (IsMaskVector) {
12457 DAG.
getUNDEF(IndicesVT), VecLen, EVL);
12459 DAG.
getUNDEF(IndicesVT), Mask, EVL);
12461 DAG.
getUNDEF(GatherVT), Mask, EVL);
12463 if (IsMaskVector) {
12478 MVT VT =
Op.getSimpleValueType();
12480 return lowerVPOp(
Op, DAG);
12487 MVT ContainerVT = VT;
12506 MVT VT =
Op.getSimpleValueType();
12507 MVT ContainerVT = VT;
12513 auto *VPNode = cast<VPStridedLoadSDNode>(
Op);
12519 : Intrinsic::riscv_vlse_mask,
12522 DAG.
getUNDEF(ContainerVT), VPNode->getBasePtr(),
12523 VPNode->getStride()};
12531 Ops.
push_back(VPNode->getVectorLength());
12539 VPNode->getMemoryVT(), VPNode->getMemOperand());
12553 auto *VPNode = cast<VPStridedStoreSDNode>(
Op);
12554 SDValue StoreVal = VPNode->getValue();
12556 MVT ContainerVT = VT;
12567 : Intrinsic::riscv_vsse_mask,
12570 VPNode->getBasePtr(), VPNode->getStride()};
12578 Ops.
push_back(VPNode->getVectorLength());
12581 Ops, VPNode->getMemoryVT(),
12582 VPNode->getMemOperand());
12594 MVT VT =
Op.getSimpleValueType();
12596 const auto *MemSD = cast<MemSDNode>(
Op.getNode());
12597 EVT MemVT = MemSD->getMemoryVT();
12599 SDValue Chain = MemSD->getChain();
12605 if (
auto *VPGN = dyn_cast<VPGatherSDNode>(
Op.getNode())) {
12606 Index = VPGN->getIndex();
12607 Mask = VPGN->getMask();
12609 VL = VPGN->getVectorLength();
12614 auto *MGN = cast<MaskedGatherSDNode>(
Op.getNode());
12615 Index = MGN->getIndex();
12616 Mask = MGN->getMask();
12617 PassThru = MGN->getPassThru();
12621 MVT IndexVT =
Index.getSimpleValueType();
12625 "Unexpected VTs!");
12626 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
12629 "Unexpected extending MGATHER/VP_GATHER");
12635 MVT ContainerVT = VT;
12659 IsUnmasked ? Intrinsic::riscv_vluxei : Intrinsic::riscv_vluxei_mask;
12676 Chain =
Result.getValue(1);
12693 const auto *MemSD = cast<MemSDNode>(
Op.getNode());
12694 EVT MemVT = MemSD->getMemoryVT();
12696 SDValue Chain = MemSD->getChain();
12699 [[maybe_unused]]
bool IsTruncatingStore =
false;
12702 if (
auto *VPSN = dyn_cast<VPScatterSDNode>(
Op.getNode())) {
12703 Index = VPSN->getIndex();
12704 Mask = VPSN->getMask();
12705 Val = VPSN->getValue();
12706 VL = VPSN->getVectorLength();
12708 IsTruncatingStore =
false;
12711 auto *MSN = cast<MaskedScatterSDNode>(
Op.getNode());
12712 Index = MSN->getIndex();
12713 Mask = MSN->getMask();
12714 Val = MSN->getValue();
12715 IsTruncatingStore = MSN->isTruncatingStore();
12719 MVT IndexVT =
Index.getSimpleValueType();
12723 "Unexpected VTs!");
12724 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
12727 assert(!IsTruncatingStore &&
"Unexpected truncating MSCATTER/VP_SCATTER");
12733 MVT ContainerVT = VT;
12757 IsUnmasked ? Intrinsic::riscv_vsoxei : Intrinsic::riscv_vsoxei_mask;
12767 DAG.
getVTList(MVT::Other), Ops, MemVT, MMO);
12783 static const int Table =
12812 static const unsigned Table =
12835 bool isRISCV64 = Subtarget.
is64Bit();
12899 switch (
N->getOpcode()) {
12901 llvm_unreachable(
"Don't know how to custom type legalize this operation!");
12907 "Unexpected custom legalisation");
12908 bool IsStrict =
N->isStrictFPOpcode();
12911 SDValue Op0 = IsStrict ?
N->getOperand(1) :
N->getOperand(0);
12929 Opc,
DL, VTs, Chain, Op0,
12963 std::tie(Result, Chain) =
12964 makeLibCall(DAG, LC,
N->getValueType(0), Op0, CallOptions,
DL, Chain);
12992 Op0.
getValueType() == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
13003 assert(!Subtarget.
is64Bit() &&
"READCYCLECOUNTER/READSTEADYCOUNTER only "
13004 "has custom type legalization on riscv32");
13006 SDValue LoCounter, HiCounter;
13017 N->getOperand(0), LoCounter, HiCounter);
13041 unsigned Size =
N->getSimpleValueType(0).getSizeInBits();
13042 unsigned XLen = Subtarget.
getXLen();
13045 assert(
Size == (XLen * 2) &&
"Unexpected custom legalisation");
13053 if (LHSIsU == RHSIsU)
13070 if (RHSIsU && LHSIsS && !RHSIsS)
13072 else if (LHSIsU && RHSIsS && !LHSIsS)
13082 "Unexpected custom legalisation");
13089 "Unexpected custom legalisation");
13092 if (
N->getOpcode() ==
ISD::SHL && Subtarget.hasStdExtZbs() &&
13118 "Unexpected custom legalisation");
13119 assert((Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb() ||
13120 Subtarget.hasVendorXTHeadBb()) &&
13121 "Unexpected custom legalization");
13122 if (!isa<ConstantSDNode>(
N->getOperand(1)) &&
13123 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()))
13132 "Unexpected custom legalisation");
13146 MVT VT =
N->getSimpleValueType(0);
13147 assert((VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32) &&
13148 Subtarget.
is64Bit() && Subtarget.hasStdExtM() &&
13149 "Unexpected custom legalisation");
13161 if (VT != MVT::i32)
13170 "Unexpected custom legalisation");
13174 if (!isa<ConstantSDNode>(
N->getOperand(1)))
13191 EVT OType =
N->getValueType(1);
13204 "Unexpected custom legalisation");
13221 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1), Res,
13225 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1),
N->getOperand(0),
13243 !Subtarget.hasStdExtZbb() &&
"Unexpected custom legalisation");
13252 "Unexpected custom legalisation");
13258 "Unexpected custom legalisation");
13260 if (Subtarget.hasStdExtZbb()) {
13294 EVT VT =
N->getValueType(0);
13299 if (VT == MVT::i16 &&
13301 (Op0VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
13304 }
else if (VT == MVT::i32 && Op0VT == MVT::f32 && Subtarget.
is64Bit() &&
13309 }
else if (VT == MVT::i64 && Op0VT == MVT::f64 && !Subtarget.
is64Bit() &&
13312 DAG.
getVTList(MVT::i32, MVT::i32), Op0);
13333 MVT VT =
N->getSimpleValueType(0);
13335 assert((VT == MVT::i16 || (VT == MVT::i32 && Subtarget.
is64Bit())) &&
13336 "Unexpected custom legalisation");
13339 "Unexpected extension");
13365 assert(!Subtarget.
is64Bit() &&
N->getValueType(0) == MVT::i64 &&
13367 "Unexpected EXTRACT_VECTOR_ELT legalization");
13370 MVT ContainerVT = VecVT;
13398 DAG.
getUNDEF(ContainerVT), Mask, VL);
13406 unsigned IntNo =
N->getConstantOperandVal(0);
13410 "Don't know how to custom type legalize this intrinsic!");
13411 case Intrinsic::experimental_get_vector_length: {
13416 case Intrinsic::experimental_cttz_elts: {
13422 case Intrinsic::riscv_orc_b:
13423 case Intrinsic::riscv_brev8:
13424 case Intrinsic::riscv_sha256sig0:
13425 case Intrinsic::riscv_sha256sig1:
13426 case Intrinsic::riscv_sha256sum0:
13427 case Intrinsic::riscv_sha256sum1:
13428 case Intrinsic::riscv_sm3p0:
13429 case Intrinsic::riscv_sm3p1: {
13430 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
13450 case Intrinsic::riscv_sm4ks:
13451 case Intrinsic::riscv_sm4ed: {
13459 DAG.
getNode(Opc,
DL, MVT::i64, NewOp0, NewOp1,
N->getOperand(3));
13463 case Intrinsic::riscv_mopr: {
13464 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
13474 case Intrinsic::riscv_moprr: {
13475 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
13487 case Intrinsic::riscv_clmul: {
13488 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
13499 case Intrinsic::riscv_clmulh:
13500 case Intrinsic::riscv_clmulr: {
13501 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
13529 case Intrinsic::riscv_vmv_x_s: {
13530 EVT VT =
N->getValueType(0);
13532 if (VT.
bitsLT(XLenVT)) {
13541 "Unexpected custom legalization");
13579 case ISD::VP_REDUCE_ADD:
13580 case ISD::VP_REDUCE_AND:
13581 case ISD::VP_REDUCE_OR:
13582 case ISD::VP_REDUCE_XOR:
13583 case ISD::VP_REDUCE_SMAX:
13584 case ISD::VP_REDUCE_UMAX:
13585 case ISD::VP_REDUCE_SMIN:
13586 case ISD::VP_REDUCE_UMIN:
13650 const EVT VT =
N->getValueType(0);
13651 const unsigned Opc =
N->getOpcode();
13658 (Opc !=
ISD::FADD || !
N->getFlags().hasAllowReassociation()))
13663 "Inconsistent mappings");
13674 !isa<ConstantSDNode>(
RHS.getOperand(1)))
13677 uint64_t RHSIdx = cast<ConstantSDNode>(
RHS.getOperand(1))->getLimitedValue();
13692 LHS.getOperand(0) == SrcVec && isa<ConstantSDNode>(
LHS.getOperand(1))) {
13694 cast<ConstantSDNode>(
LHS.getOperand(1))->getLimitedValue();
13695 if (0 == std::min(LHSIdx, RHSIdx) && 1 == std::max(LHSIdx, RHSIdx)) {
13699 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
N->getFlags());
13706 if (
LHS.getOpcode() != ReduceOpc)
13721 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
13722 ReduceVec->
getFlags() &
N->getFlags());
13732 auto BinOpToRVVReduce = [](
unsigned Opc) {
13761 auto IsReduction = [&BinOpToRVVReduce](
SDValue V,
unsigned Opc) {
13764 V.getOperand(0).getOpcode() == BinOpToRVVReduce(Opc);
13767 unsigned Opc =
N->getOpcode();
13768 unsigned ReduceIdx;
13769 if (IsReduction(
N->getOperand(0), Opc))
13771 else if (IsReduction(
N->getOperand(1), Opc))
13777 if (Opc ==
ISD::FADD && !
N->getFlags().hasAllowReassociation())
13780 SDValue Extract =
N->getOperand(ReduceIdx);
13812 SDValue NewStart =
N->getOperand(1 - ReduceIdx);
13839 if (!Subtarget.hasStdExtZba())
13843 EVT VT =
N->getValueType(0);
13855 auto *N0C = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
13856 auto *N1C = dyn_cast<ConstantSDNode>(N1->
getOperand(1));
13859 int64_t C0 = N0C->getSExtValue();
13860 int64_t C1 = N1C->getSExtValue();
13861 if (C0 <= 0 || C1 <= 0)
13865 int64_t Bits = std::min(C0, C1);
13866 int64_t Diff = std::abs(C0 - C1);
13867 if (Diff != 1 && Diff != 2 && Diff != 3)
13894 EVT VT =
N->getValueType(0);
13902 if ((!Subtarget.hasStdExtZicond() &&
13903 !Subtarget.hasVendorXVentanaCondOps()) ||
13925 bool SwapSelectOps;
13931 SwapSelectOps =
false;
13932 NonConstantVal = FalseVal;
13934 SwapSelectOps =
true;
13935 NonConstantVal = TrueVal;
13941 FalseVal = DAG.
getNode(
N->getOpcode(),
SDLoc(
N), VT, OtherOp, NonConstantVal);
13989 EVT VT =
N->getValueType(0);
13997 auto *N0C = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
13998 auto *N1C = dyn_cast<ConstantSDNode>(
N->getOperand(1));
14004 if (!N0C->hasOneUse())
14006 int64_t C0 = N0C->getSExtValue();
14007 int64_t C1 = N1C->getSExtValue();
14009 if (C0 == -1 || C0 == 0 || C0 == 1 || isInt<12>(C1))
14012 if ((C1 / C0) != 0 && isInt<12>(C1 / C0) && isInt<12>(C1 % C0) &&
14013 !isInt<12>(C0 * (C1 / C0))) {
14016 }
else if ((C1 / C0 + 1) != 0 && isInt<12>(C1 / C0 + 1) &&
14017 isInt<12>(C1 % C0 - C0) && !isInt<12>(C0 * (C1 / C0 + 1))) {
14020 }
else if ((C1 / C0 - 1) != 0 && isInt<12>(C1 / C0 - 1) &&
14021 isInt<12>(C1 % C0 + C0) && !isInt<12>(C0 * (C1 / C0 - 1))) {
14048 EVT VT =
N->getValueType(0);
14079 unsigned OuterExtend =
14083 OuterExtend,
SDLoc(
N), VT,
14091 EVT VT =
N->getValueType(0);
14139 EVT VT =
N->getValueType(0);
14143 auto *N0C = dyn_cast<ConstantSDNode>(N0);
14149 APInt ImmValMinus1 = N0C->getAPIntValue() - 1;
14159 if (!isIntEqualitySetCC(CCVal) || !SetCCOpVT.
isInteger())
14182 if (!Subtarget.hasStdExtZbb())
14185 EVT VT =
N->getValueType(0);
14187 if (VT != Subtarget.
getXLenVT() && VT != MVT::i32 && VT != MVT::i16)
14196 auto *ShAmtCLeft = dyn_cast<ConstantSDNode>(N0.
getOperand(1));
14199 unsigned ShiftedAmount = 8 - ShAmtCLeft->getZExtValue();
14201 if (ShiftedAmount >= 8)
14205 SDValue RightShiftOperand = N1;
14207 if (ShiftedAmount != 0) {
14210 auto *ShAmtCRight = dyn_cast<ConstantSDNode>(N1.
getOperand(1));
14211 if (!ShAmtCRight || ShAmtCRight->getZExtValue() != ShiftedAmount)
14220 if (LeftShiftOperand != RightShiftOperand)
14224 Mask <<= ShiftedAmount;
14238 EVT VT =
N->getValueType(0);
14269 bool IsAnd =
N->getOpcode() ==
ISD::AND;
14293 EVT VT =
N->getValueType(0);
14317 EVT VT =
N->getValueType(0);
14344 if (CondLHS != True)
14351 if (!CondRHSC || CondRHSC->
getAPIntValue() != (1ULL << ScalarBits))
14363 if (!FalseRHSC || !FalseRHSC->
isZero())
14383 EVT VT =
N->getValueType(0);
14390 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() && VT == MVT::i1 &&
14417 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
14469 EVT VT =
N->getValueType(0);
14515 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
14540 auto *ConstN00 = dyn_cast<ConstantSDNode>(N0.
getOperand(0));
14545 const APInt &Imm = ConstN00->getAPIntValue();
14546 if ((Imm + 1).isSignedIntN(12))
14567 EVT VT =
N->getValueType(0);
14579 const bool HasShlAdd =
14580 Subtarget.hasStdExtZba() || Subtarget.hasVendorXTHeadBa();
14594 for (
uint64_t Divisor : {3, 5, 9}) {
14595 if (MulAmt % Divisor != 0)
14597 uint64_t MulAmt2 = MulAmt / Divisor;
14604 if (
X.getOpcode() ==
ISD::AND && isa<ConstantSDNode>(
X.getOperand(1)) &&
14605 X.getConstantOperandVal(1) == UINT64_C(0xffffffff)) {
14622 if (MulAmt2 == 3 || MulAmt2 == 5 || MulAmt2 == 9) {
14638 if (ScaleShift >= 1 && ScaleShift < 4) {
14639 unsigned ShiftAmt =
Log2_64((MulAmt & (MulAmt - 1)));
14653 for (
uint64_t Divisor : {3, 5, 9}) {
14658 if ((
C >> TZ) == Divisor && (TZ == 1 || TZ == 2 || TZ == 3)) {
14669 if (MulAmt > 2 &&
isPowerOf2_64((MulAmt - 1) & (MulAmt - 2))) {
14671 if (ScaleShift >= 1 && ScaleShift < 4) {
14672 unsigned ShiftAmt =
Log2_64(((MulAmt - 1) & (MulAmt - 2)));
14698 uint64_t MulAmtLowBit = MulAmt & (-MulAmt);
14700 uint64_t ShiftAmt1 = MulAmt + MulAmtLowBit;
14711 for (
uint64_t Divisor : {3, 5, 9}) {
14712 if (MulAmt % Divisor != 0)
14714 uint64_t MulAmt2 = MulAmt / Divisor;
14717 for (
uint64_t Divisor2 : {3, 5, 9}) {
14718 if (MulAmt2 % Divisor2 != 0)
14720 uint64_t MulAmt3 = MulAmt2 / Divisor2;
14743 EVT VT =
N->getValueType(0);
14750 if (
N->getOperand(0).getOpcode() !=
ISD::AND ||
14751 N->getOperand(0).getOperand(0).getOpcode() !=
ISD::SRL)
14764 if (!V1.
isMask(HalfSize) || V2 != (1ULL | 1ULL << HalfSize) ||
14765 V3 != (HalfSize - 1))
14781 EVT VT =
N->getValueType(0);
14789 unsigned AddSubOpc;
14795 auto IsAddSubWith1 = [&](
SDValue V) ->
bool {
14796 AddSubOpc = V->getOpcode();
14798 SDValue Opnd = V->getOperand(1);
14799 MulOper = V->getOperand(0);
14808 if (IsAddSubWith1(N0)) {
14810 return DAG.
getNode(AddSubOpc,
DL, VT, N1, MulVal);
14813 if (IsAddSubWith1(N1)) {
14815 return DAG.
getNode(AddSubOpc,
DL, VT, N0, MulVal);
14830 if (isIndexTypeSigned(IndexType))
14833 if (!
N->hasOneUse())
14836 EVT VT =
N.getValueType();
14875 EVT SrcVT = Src.getValueType();
14879 NewElen = std::max(NewElen, 8U);
14902 EVT VT =
N->getValueType(0);
14905 if (OpVT != MVT::i64 || !Subtarget.
is64Bit())
14909 auto *N1C = dyn_cast<ConstantSDNode>(N1);
14921 if (!isIntEqualitySetCC(
Cond))
14930 const APInt &C1 = N1C->getAPIntValue();
14948 EVT VT =
N->getValueType(0);
14949 EVT SrcVT = cast<VTSDNode>(
N->getOperand(1))->
getVT();
14950 unsigned Opc = Src.getOpcode();
14955 Subtarget.hasStdExtZfhmin())
14957 Src.getOperand(0));
14961 VT == MVT::i64 && !isa<ConstantSDNode>(Src.getOperand(1)) &&
14964 Src.getOperand(1));
14972struct CombineResult;
14974enum ExtKind :
uint8_t { ZExt = 1 << 0, SExt = 1 << 1, FPExt = 1 << 2 };
15001struct NodeExtensionHelper {
15010 bool SupportsFPExt;
15013 bool EnforceOneUse;
15028 return OrigOperand;
15039 unsigned getExtOpc(ExtKind SupportsExt)
const {
15040 switch (SupportsExt) {
15041 case ExtKind::SExt:
15043 case ExtKind::ZExt:
15045 case ExtKind::FPExt:
15056 std::optional<ExtKind> SupportsExt)
const {
15057 if (!SupportsExt.has_value())
15058 return OrigOperand;
15060 MVT NarrowVT = getNarrowType(Root, *SupportsExt);
15064 if (
Source.getValueType() == NarrowVT)
15068 if (
Source.getValueType().getVectorElementType() == MVT::bf16) {
15074 unsigned ExtOpc = getExtOpc(*SupportsExt);
15078 auto [
Mask, VL] = getMaskAndVL(Root, DAG, Subtarget);
15085 return DAG.
getNode(ExtOpc,
DL, NarrowVT, Source, Mask, VL);
15097 DAG.
getUNDEF(NarrowVT), Source, VL);
15110 static MVT getNarrowType(
const SDNode *Root, ExtKind SupportsExt) {
15116 MVT EltVT = SupportsExt == ExtKind::FPExt
15118 :
MVT::getIntegerVT(NarrowSize);
15120 assert((
int)NarrowSize >= (SupportsExt == ExtKind::FPExt ? 16 : 8) &&
15121 "Trying to extend something we can't represent");
15128 static unsigned getSExtOpcode(
unsigned Opcode) {
15151 static unsigned getZExtOpcode(
unsigned Opcode) {
15177 static unsigned getFPExtOpcode(
unsigned Opcode) {
15202 static unsigned getSUOpcode(
unsigned Opcode) {
15204 "SU is only supported for MUL");
15210 static unsigned getWOpcode(
unsigned Opcode, ExtKind SupportsExt) {
15230 using CombineToTry = std::function<std::optional<CombineResult>(
15231 SDNode * ,
const NodeExtensionHelper & ,
15236 bool needToPromoteOtherUsers()
const {
return EnforceOneUse; }
15240 unsigned Opc = OrigOperand.
getOpcode();
15244 "Unexpected Opcode");
15257 unsigned ScalarBits =
Op.getValueSizeInBits();
15259 if (ScalarBits < EltBits) {
15262 !Subtarget.
is64Bit() &&
"Unexpected splat");
15264 SupportsSExt =
true;
15268 SupportsZExt =
true;
15270 EnforceOneUse =
false;
15274 unsigned NarrowSize = EltBits / 2;
15277 if (NarrowSize < 8)
15281 SupportsSExt =
true;
15285 SupportsZExt =
true;
15287 EnforceOneUse =
false;
15290 bool isSupportedFPExtend(
SDNode *Root,
MVT NarrowEltVT,
15297 if (NarrowEltVT == MVT::bf16 && (!Subtarget.hasStdExtZvfbfwma() ||
15307 SupportsZExt =
false;
15308 SupportsSExt =
false;
15309 SupportsFPExt =
false;
15310 EnforceOneUse =
true;
15311 unsigned Opc = OrigOperand.
getOpcode();
15333 SupportsZExt =
true;
15336 SupportsSExt =
true;
15341 if (!isSupportedFPExtend(Root, NarrowEltVT, Subtarget))
15343 SupportsFPExt =
true;
15348 fillUpExtensionSupportForSplat(Root, DAG, Subtarget);
15360 if (!isSupportedFPExtend(Root,
Op.getOperand(0).getSimpleValueType(),
15365 unsigned ScalarBits =
Op.getOperand(0).getValueSizeInBits();
15366 if (NarrowSize != ScalarBits)
15369 SupportsFPExt =
true;
15378 static bool isSupportedRoot(
const SDNode *Root,
15407 Subtarget.hasStdExtZvbb();
15409 return Subtarget.hasStdExtZvbb();
15423 assert(isSupportedRoot(Root, Subtarget) &&
15424 "Trying to build an helper with an "
15425 "unsupported root");
15426 assert(OperandIdx < 2 &&
"Requesting something else than LHS or RHS");
15442 if (OperandIdx == 1) {
15451 EnforceOneUse =
false;
15456 fillUpExtensionSupport(Root, DAG, Subtarget);
15462 static std::pair<SDValue, SDValue>
15465 assert(isSupportedRoot(Root, Subtarget) &&
"Unexpected root");
15484 switch (
N->getOpcode()) {
15526struct CombineResult {
15528 unsigned TargetOpcode;
15530 std::optional<ExtKind> LHSExt;
15531 std::optional<ExtKind> RHSExt;
15535 NodeExtensionHelper
LHS;
15537 NodeExtensionHelper
RHS;
15539 CombineResult(
unsigned TargetOpcode,
SDNode *Root,
15540 const NodeExtensionHelper &
LHS, std::optional<ExtKind> LHSExt,
15541 const NodeExtensionHelper &
RHS, std::optional<ExtKind> RHSExt)
15542 : TargetOpcode(TargetOpcode), LHSExt(LHSExt), RHSExt(RHSExt), Root(Root),
15551 std::tie(Mask, VL) =
15552 NodeExtensionHelper::getMaskAndVL(Root, DAG, Subtarget);
15566 LHS.getOrCreateExtendedOp(Root, DAG, Subtarget, LHSExt),
15567 RHS.getOrCreateExtendedOp(Root, DAG, Subtarget, RHSExt),
15568 Passthru, Mask, VL);
15582static std::optional<CombineResult>
15583canFoldToVWWithSameExtensionImpl(
SDNode *Root,
const NodeExtensionHelper &LHS,
15584 const NodeExtensionHelper &RHS,
15587 if ((AllowExtMask & ExtKind::ZExt) &&
LHS.SupportsZExt &&
RHS.SupportsZExt)
15588 return CombineResult(NodeExtensionHelper::getZExtOpcode(Root->
getOpcode()),
15589 Root, LHS, {ExtKind::ZExt}, RHS,
15591 if ((AllowExtMask & ExtKind::SExt) &&
LHS.SupportsSExt &&
RHS.SupportsSExt)
15592 return CombineResult(NodeExtensionHelper::getSExtOpcode(Root->
getOpcode()),
15593 Root, LHS, {ExtKind::SExt}, RHS,
15595 if ((AllowExtMask & ExtKind::FPExt) &&
LHS.SupportsFPExt &&
RHS.SupportsFPExt)
15596 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
15597 Root, LHS, {ExtKind::FPExt}, RHS,
15599 return std::nullopt;
15608static std::optional<CombineResult>
15609canFoldToVWWithSameExtension(
SDNode *Root,
const NodeExtensionHelper &LHS,
15612 return canFoldToVWWithSameExtensionImpl(
15613 Root, LHS, RHS, ExtKind::ZExt | ExtKind::SExt | ExtKind::FPExt, DAG,
15621static std::optional<CombineResult>
15622canFoldToVW_W(
SDNode *Root,
const NodeExtensionHelper &LHS,
15625 if (
RHS.SupportsFPExt)
15626 return CombineResult(
15627 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::FPExt),
15628 Root, LHS, std::nullopt, RHS, {ExtKind::FPExt});
15635 return CombineResult(
15636 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::ZExt), Root,
15637 LHS, std::nullopt, RHS, {ExtKind::ZExt});
15639 return CombineResult(
15640 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::SExt), Root,
15641 LHS, std::nullopt, RHS, {ExtKind::SExt});
15642 return std::nullopt;
15649static std::optional<CombineResult>
15650canFoldToVWWithSEXT(
SDNode *Root,
const NodeExtensionHelper &LHS,
15653 return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::SExt, DAG,
15661static std::optional<CombineResult>
15662canFoldToVWWithZEXT(
SDNode *Root,
const NodeExtensionHelper &LHS,
15665 return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::ZExt, DAG,
15673static std::optional<CombineResult>
15674canFoldToVWWithFPEXT(
SDNode *Root,
const NodeExtensionHelper &LHS,
15677 return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::FPExt, DAG,
15685static std::optional<CombineResult>
15686canFoldToVW_SU(
SDNode *Root,
const NodeExtensionHelper &LHS,
15690 if (!
LHS.SupportsSExt || !
RHS.SupportsZExt)
15691 return std::nullopt;
15692 return CombineResult(NodeExtensionHelper::getSUOpcode(Root->
getOpcode()),
15693 Root, LHS, {ExtKind::SExt}, RHS,
15698NodeExtensionHelper::getSupportedFoldings(
const SDNode *Root) {
15709 Strategies.
push_back(canFoldToVWWithSameExtension);
15718 Strategies.
push_back(canFoldToVWWithSameExtension);
15723 Strategies.
push_back(canFoldToVWWithSameExtension);
15730 Strategies.
push_back(canFoldToVWWithZEXT);
15735 Strategies.
push_back(canFoldToVWWithSEXT);
15740 Strategies.
push_back(canFoldToVWWithZEXT);
15745 Strategies.
push_back(canFoldToVWWithFPEXT);
15774 if (!NodeExtensionHelper::isSupportedRoot(
N, Subtarget))
15780 Inserted.insert(
N);
15783 while (!Worklist.
empty()) {
15786 NodeExtensionHelper
LHS(Root, 0, DAG, Subtarget);
15787 NodeExtensionHelper
RHS(Root, 1, DAG, Subtarget);
15788 auto AppendUsersIfNeeded = [&Worklist, &Subtarget,
15789 &Inserted](
const NodeExtensionHelper &
Op) {
15790 if (
Op.needToPromoteOtherUsers()) {
15793 if (!NodeExtensionHelper::isSupportedRoot(TheUser, Subtarget))
15798 if (Inserted.insert(TheUser).second)
15811 NodeExtensionHelper::getSupportedFoldings(Root);
15813 assert(!FoldingStrategies.
empty() &&
"Nothing to be folded");
15814 bool Matched =
false;
15815 for (
int Attempt = 0;
15816 (Attempt != 1 + NodeExtensionHelper::isCommutative(Root)) && !Matched;
15819 for (NodeExtensionHelper::CombineToTry FoldingStrategy :
15820 FoldingStrategies) {
15821 std::optional<CombineResult> Res =
15822 FoldingStrategy(Root,
LHS,
RHS, DAG, Subtarget);
15829 if (Res->LHSExt.has_value())
15830 if (!AppendUsersIfNeeded(
LHS))
15832 if (Res->RHSExt.has_value())
15833 if (!AppendUsersIfNeeded(
RHS))
15845 SDValue InputRootReplacement;
15852 for (CombineResult Res : CombinesToApply) {
15853 SDValue NewValue = Res.materialize(DAG, Subtarget);
15854 if (!InputRootReplacement) {
15856 "First element is expected to be the current node");
15857 InputRootReplacement = NewValue;
15862 for (std::pair<SDValue, SDValue> OldNewValues : ValuesToReplace) {
15866 return InputRootReplacement;
15873 unsigned Opc =
N->getOpcode();
15878 SDValue MergeOp =
N->getOperand(1);
15879 unsigned MergeOpc = MergeOp.
getOpcode();
15890 SDValue Passthru =
N->getOperand(2);
15904 Z = Z.getOperand(1);
15910 {Y, X, Y, MergeOp->getOperand(0), N->getOperand(4)},
15917 [[maybe_unused]]
unsigned Opc =
N->getOpcode();
15946 EVT NewMemVT = (MemVT == MVT::i32) ? MVT::i64 : MVT::i128;
15952 auto Ext = cast<LoadSDNode>(LSNode1)->getExtensionType();
15954 if (MemVT == MVT::i32)
15960 Opcode,
SDLoc(LSNode1), DAG.
getVTList({XLenVT, XLenVT, MVT::Other}),
15995 if (!Subtarget.hasVendorXTHeadMemPair())
16007 auto ExtractBaseAndOffset = [](
SDValue Ptr) -> std::pair<SDValue, uint64_t> {
16009 if (
auto *C1 = dyn_cast<ConstantSDNode>(
Ptr->getOperand(1)))
16010 return {
Ptr->getOperand(0), C1->getZExtValue()};
16014 auto [Base1, Offset1] = ExtractBaseAndOffset(LSNode1->
getOperand(OpNum));
16035 auto [Base2, Offset2] = ExtractBaseAndOffset(LSNode2->
getOperand(OpNum));
16038 if (Base1 != Base2)
16042 bool Valid =
false;
16043 if (MemVT == MVT::i32) {
16045 if ((Offset1 + 4 == Offset2) && isShiftedUInt<2, 3>(Offset1))
16047 }
else if (MemVT == MVT::i64) {
16049 if ((Offset1 + 8 == Offset2) && isShiftedUInt<2, 4>(Offset1))
16083 if (Src->isStrictFPOpcode())
16091 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
16101 EVT VT =
N->getValueType(0);
16104 MVT SrcVT = Src.getSimpleValueType();
16105 MVT SrcContainerVT = SrcVT;
16107 SDValue XVal = Src.getOperand(0);
16134 FpToInt = DAG.
getNode(Opc,
DL, ContainerVT, XVal, Mask, VL);
16138 FpToInt = DAG.
getNode(Opc,
DL, ContainerVT, XVal, Mask,
16151 if (VT != MVT::i32 && VT != XLenVT)
16181 EVT DstVT =
N->getValueType(0);
16182 if (DstVT != XLenVT)
16188 if (Src->isStrictFPOpcode())
16196 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
16199 EVT SatVT = cast<VTSDNode>(
N->getOperand(1))->getVT();
16208 if (SatVT == DstVT)
16210 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
16216 Src = Src.getOperand(0);
16237 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected extension");
16243 EVT VT =
N->getValueType(0);
16258 auto *VPLoad = dyn_cast<VPLoadSDNode>(
N->getOperand(0));
16262 EVT LoadVT = VPLoad->getValueType(0);
16266 N->getOperand(2) != VPLoad->getVectorLength() ||
16267 !
N->getOperand(0).hasOneUse())
16274 SDValue LoadMask = VPLoad->getMask();
16279 if (LoadMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
16281 LoadMask.
getOperand(2) != VPLoad->getVectorLength())
16289 SDValue NumElem = VPLoad->getVectorLength();
16290 uint64_t ElemWidthByte = VPLoad->getValueType(0).getScalarSizeInBits() / 8;
16302 PtrInfo, VPLoad->getMemOperand()->getFlags(),
16306 LoadVT,
DL, VPLoad->getChain(),
Base, Stride, LoadMask,
16307 VPLoad->getVectorLength(), MMO, VPLoad->isExpandingLoad());
16319 auto *VPStore = cast<VPStoreSDNode>(
N);
16321 if (VPStore->getValue().getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE)
16324 SDValue VPReverse = VPStore->getValue();
16330 VPStore->getVectorLength() != VPReverse.
getOperand(2) ||
16334 SDValue StoreMask = VPStore->getMask();
16339 if (StoreMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
16341 StoreMask.
getOperand(2) != VPStore->getVectorLength())
16349 SDValue NumElem = VPStore->getVectorLength();
16363 PtrInfo, VPStore->getMemOperand()->getFlags(),
16368 VPStore->getOffset(), Stride, StoreMask, VPStore->getVectorLength(),
16369 VPStore->getMemoryVT(), MMO, VPStore->getAddressingMode(),
16370 VPStore->isTruncatingStore(), VPStore->isCompressingStore());
16419 unsigned Offset = IsStrict ? 1 : 0;
16426 auto invertIfNegative = [&Mask, &VL](
SDValue &V) {
16428 V.getOperand(2) == VL) {
16430 V = V.getOperand(0);
16437 bool NegA = invertIfNegative(
A);
16438 bool NegB = invertIfNegative(
B);
16439 bool NegC = invertIfNegative(
C);
16442 if (!NegA && !NegB && !NegC)
16448 {N->getOperand(0), A, B, C, Mask, VL});
16472 EVT VT =
N->getValueType(0);
16477 if (!isa<ConstantSDNode>(
N->getOperand(1)))
16479 uint64_t ShAmt =
N->getConstantOperandVal(1);
16487 cast<VTSDNode>(N0.
getOperand(1))->getVT().getSizeInBits();
16492 if (LShAmt < ExtSize) {
16505 if (ShAmt > 32 || VT != MVT::i64)
16521 AddC = dyn_cast<ConstantSDNode>(N0.
getOperand(IsAdd ? 1 : 0));
16534 !isa<ConstantSDNode>(U->getOperand(1)) ||
16535 U->getConstantOperandVal(1) > 32)
16590 if (!
Cond.hasOneUse())
16609 EVT VT =
Cond.getValueType();
16654 LHS =
LHS.getOperand(0);
16664 LHS.getOperand(0).getValueType() == Subtarget.
getXLenVT()) {
16668 CCVal = cast<CondCodeSDNode>(
LHS.getOperand(2))->get();
16672 RHS =
LHS.getOperand(1);
16673 LHS =
LHS.getOperand(0);
16682 RHS =
LHS.getOperand(1);
16683 LHS =
LHS.getOperand(0);
16699 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
16740 bool Commutative =
true;
16741 unsigned Opc = TrueVal.getOpcode();
16749 Commutative =
false;
16757 if (!TrueVal.hasOneUse() || isa<ConstantSDNode>(FalseVal))
16761 if (FalseVal == TrueVal.getOperand(0))
16763 else if (Commutative && FalseVal == TrueVal.getOperand(1))
16768 EVT VT =
N->getValueType(0);
16770 SDValue OtherOp = TrueVal.getOperand(1 - OpToFold);
16776 assert(IdentityOperand &&
"No identity operand!");
16781 DAG.
getSelect(
DL, OtherOpVT,
N->getOperand(0), OtherOp, IdentityOperand);
16782 return DAG.
getNode(TrueVal.getOpcode(),
DL, VT, FalseVal, NewSel);
16803 CountZeroes =
N->getOperand(2);
16804 ValOnZero =
N->getOperand(1);
16806 CountZeroes =
N->getOperand(1);
16807 ValOnZero =
N->getOperand(2);
16826 if (
Cond->getOperand(0) != CountZeroesArgument)
16842 CountZeroes, BitWidthMinusOne);
16852 EVT VT =
N->getValueType(0);
16853 EVT CondVT =
Cond.getValueType();
16861 (Subtarget.hasStdExtZicond() || Subtarget.hasVendorXVentanaCondOps())) {
16867 const APInt &MaskVal =
LHS.getConstantOperandAPInt(1);
16888 SDValue TrueVal =
N->getOperand(1);
16889 SDValue FalseVal =
N->getOperand(2);
16904 EVT VT =
N->getValueType(0);
16911 const unsigned Opcode =
N->op_begin()->getNode()->getOpcode();
16926 if (
Op.isUndef()) {
16939 if (
Op.getOpcode() != Opcode || !
Op.hasOneUse())
16943 if (!isa<ConstantSDNode>(
Op.getOperand(1)) &&
16944 !isa<ConstantFPSDNode>(
Op.getOperand(1)))
16948 if (
Op.getOperand(0).getValueType() !=
Op.getOperand(1).getValueType())
16976 const unsigned InVecOpcode = InVec->
getOpcode();
16986 if (!isa<ConstantSDNode>(InValRHS) && !isa<ConstantFPSDNode>(InValRHS))
16993 InVecLHS, InValLHS, EltNo);
16995 InVecRHS, InValRHS, EltNo);
17004 auto *IndexC = dyn_cast<ConstantSDNode>(EltNo);
17007 unsigned Elt = IndexC->getZExtValue();
17015 unsigned ConcatOpIdx = Elt / ConcatNumElts;
17018 ConcatOp, InVal, NewIdx);
17022 ConcatOps[ConcatOpIdx] = ConcatOp;
17034 EVT VT =
N->getValueType(0);
17044 auto *BaseLd = dyn_cast<LoadSDNode>(
N->getOperand(0));
17046 !
SDValue(BaseLd, 0).hasOneUse())
17049 EVT BaseLdVT = BaseLd->getValueType(0);
17056 auto *Ld = dyn_cast<LoadSDNode>(
Op);
17057 if (!Ld || !Ld->isSimple() || !
Op.hasOneUse() ||
17059 Ld->getValueType(0) != BaseLdVT)
17068 using PtrDiff = std::pair<std::variant<int64_t, SDValue>,
bool>;
17070 LoadSDNode *Ld2) -> std::optional<PtrDiff> {
17075 if (BIO1.equalBaseIndex(BIO2, DAG))
17080 SDValue P2 = Ld2->getBasePtr();
17086 return std::nullopt;
17090 auto BaseDiff = GetPtrDiff(Lds[0], Lds[1]);
17095 for (
auto *It = Lds.
begin() + 1; It != Lds.
end() - 1; It++)
17096 if (GetPtrDiff(*It, *std::next(It)) != BaseDiff)
17104 unsigned WideScalarBitWidth =
17117 auto [StrideVariant, MustNegateStride] = *BaseDiff;
17119 std::holds_alternative<SDValue>(StrideVariant)
17120 ? std::get<SDValue>(StrideVariant)
17123 if (MustNegateStride)
17131 if (
auto *ConstStride = dyn_cast<ConstantSDNode>(Stride);
17132 ConstStride && ConstStride->getSExtValue() >= 0)
17136 ConstStride->getSExtValue() * (
N->getNumOperands() - 1);
17142 BaseLd->getPointerInfo(), BaseLd->getMemOperand()->getFlags(), MemSize,
17146 WideVecVT,
DL, BaseLd->getChain(), BaseLd->getBasePtr(), Stride,
17164 EVT VT =
N->getValueType(0);
17192 if (
N->getValueType(0).isFixedLengthVector())
17195 SDValue Addend =
N->getOperand(0);
17199 SDValue AddPassthruOp =
N->getOperand(2);
17200 if (!AddPassthruOp.
isUndef())
17204 auto IsVWMulOpc = [](
unsigned Opc) {
17223 if (!MulPassthruOp.
isUndef())
17233 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
17234 }(
N, DAG, Subtarget);
17239 if (AddMask != MulMask || AddVL != MulVL)
17244 "Unexpected opcode after VWMACC_VL");
17246 "Unexpected opcode after VWMACC_VL!");
17248 "Unexpected opcode after VWMUL_VL!");
17250 "Unexpected opcode after VWMUL_VL!");
17253 EVT VT =
N->getValueType(0);
17269 const EVT IndexVT = Index.getValueType();
17273 if (!isIndexTypeSigned(IndexType))
17305 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
17308 if (Index->getOperand(i)->isUndef())
17310 uint64_t C = Index->getConstantOperandVal(i);
17311 if (
C % ElementSize != 0)
17313 C =
C / ElementSize;
17317 ActiveLanes.
set(
C);
17319 return ActiveLanes.
all();
17337 if (NumElems % 2 != 0)
17341 const unsigned WiderElementSize = ElementSize * 2;
17342 if (WiderElementSize > ST.getELen()/8)
17345 if (!ST.enableUnalignedVectorMem() && BaseAlign < WiderElementSize)
17348 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
17351 if (Index->getOperand(i)->isUndef())
17355 uint64_t C = Index->getConstantOperandVal(i);
17357 if (
C % WiderElementSize != 0)
17362 if (
C !=
Last + ElementSize)
17379 (isa<RegisterSDNode>(VL) &&
17380 cast<RegisterSDNode>(VL)->getReg() == RISCV::X0);
17382 Mask.getOperand(0) != VL)
17385 auto IsTruncNode = [&](
SDValue V) {
17387 V.getOperand(1) == Mask && V.getOperand(2) == VL;
17394 while (IsTruncNode(
Op)) {
17395 if (!
Op.hasOneUse())
17397 Op =
Op.getOperand(0);
17432 MVT VT =
N->getSimpleValueType(0);
17437 auto MatchMinMax = [&VL, &Mask](
SDValue V,
unsigned Opc,
unsigned OpcVL,
17439 if (V.getOpcode() != Opc &&
17440 !(V.getOpcode() == OpcVL && V.getOperand(2).isUndef() &&
17441 V.getOperand(3) == Mask && V.getOperand(4) == VL))
17449 Op.getOperand(1).getValueType().isFixedLengthVector() &&
17451 Op.getOperand(1).getOperand(0).getValueType() ==
Op.getValueType() &&
17453 Op =
Op.getOperand(1).getOperand(0);
17456 return V.getOperand(0);
17459 Op.getOperand(2) == VL) {
17460 if (
auto *Op1 = dyn_cast<ConstantSDNode>(
Op.getOperand(1))) {
17462 Op1->getAPIntValue().sextOrTrunc(
Op.getScalarValueSizeInBits());
17463 return V.getOperand(0);
17472 auto DetectUSatPattern = [&](
SDValue V) {
17497 V.getOperand(1), DAG.
getUNDEF(V.getValueType()),
17503 auto DetectSSatPattern = [&](
SDValue V) {
17505 unsigned NumSrcBits = V.getScalarValueSizeInBits();
17513 if (HiC == SignedMax && LoC == SignedMin)
17519 if (HiC == SignedMax && LoC == SignedMin)
17529 Src.getOperand(1) == Mask && Src.getOperand(2) == VL &&
17531 Src = Src.getOperand(0);
17535 if ((Val = DetectUSatPattern(Src)))
17537 else if ((Val = DetectSSatPattern(Src)))
17547 Val = DAG.
getNode(ClipOpc,
DL, ValVT, Val, Mask, VL);
17548 }
while (ValVT != VT);
17562 EVT VT =
N->getValueType(0);
17570 Src = Src.getOperand(0);
17575 Src = Src.getOperand(0);
17576 EVT SrcEVT = Src.getValueType();
17608 auto SimplifyDemandedLowBitsHelper = [&](
unsigned OpNo,
unsigned LowBits) {
17619 switch (
N->getOpcode()) {
17639 APInt V =
C->getValueAPF().bitcastToAPInt();
17674 if (SimplifyDemandedLowBitsHelper(0, 32) ||
17675 SimplifyDemandedLowBitsHelper(1, 5))
17683 if (SimplifyDemandedLowBitsHelper(0, 32))
17700 MVT VT =
N->getSimpleValueType(0);
17703 if (
auto *CFP = dyn_cast<ConstantFPSDNode>(Op0)) {
17716 "Unexpected value type!");
17721 cast<LoadSDNode>(Op0)->isSimple()) {
17723 auto *LN0 = cast<LoadSDNode>(Op0);
17726 LN0->getBasePtr(), IVT, LN0->getMemOperand());
17750 EVT VT =
N->getValueType(0);
17803 if (!
C || !
C->getValueAPF().isExactlyValue(+1.0))
17805 EVT VT =
N->getValueType(0);
17834 if (
N->getValueType(0) == MVT::i64 && Subtarget.
is64Bit()) {
17839 Src.getOperand(0));
17844 Src.getOperand(0), Src.getOperand(1));
17865 unsigned Opc =
N->getOpcode();
17880 return DAG.
getNode(InvOpc,
SDLoc(
N),
N->getValueType(0), Val, NewCond);
17890 N->getValueType(0), Val,
Cond.getOperand(0));
17901 SDValue FalseV =
N->getOperand(4);
17903 EVT VT =
N->getValueType(0);
17906 if (TrueV == FalseV)
17911 if (!Subtarget.hasShortForwardBranchOpt() && isa<ConstantSDNode>(TrueV) &&
17917 int64_t TrueSImm = cast<ConstantSDNode>(TrueV)->getSExtValue();
17918 int64_t FalseSImm = cast<ConstantSDNode>(FalseV)->getSExtValue();
17921 if (isInt<12>(TrueSImm) && isInt<12>(FalseSImm) &&
17922 isInt<12>(TrueSImm - FalseSImm)) {
17938 {LHS, RHS, CC, TrueV, FalseV});
18005 N->getOperand(0),
LHS,
RHS,
CC,
N->getOperand(4));
18018 EVT VT =
N->getValueType(0);
18042 const auto *MGN = cast<MaskedGatherSDNode>(
N);
18043 const EVT VT =
N->getValueType(0);
18044 SDValue Index = MGN->getIndex();
18045 SDValue ScaleOp = MGN->getScale();
18047 assert(!MGN->isIndexScaled() &&
18048 "Scaled gather/scatter should not be formed");
18053 N->getVTList(), MGN->getMemoryVT(),
DL,
18054 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
18055 MGN->getBasePtr(), Index, ScaleOp},
18056 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
18060 N->getVTList(), MGN->getMemoryVT(),
DL,
18061 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
18062 MGN->getBasePtr(), Index, ScaleOp},
18063 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
18069 if (std::optional<VIDSequence> SimpleVID =
18071 SimpleVID && SimpleVID->StepDenominator == 1) {
18072 const int64_t StepNumerator = SimpleVID->StepNumerator;
18073 const int64_t Addend = SimpleVID->Addend;
18080 assert(MGN->getBasePtr()->getValueType(0) == PtrVT);
18088 VT,
DL, MGN->getChain(), BasePtr,
18090 EVL, MGN->getMemOperand());
18092 StridedLoad, MGN->getPassThru(), EVL);
18102 MGN->getBasePtr(), DAG.
getUNDEF(XLenVT),
18104 MGN->getMemoryVT(), MGN->getMemOperand(),
18113 MGN->getMemOperand()->getBaseAlign(), Subtarget)) {
18115 for (
unsigned i = 0; i < Index->getNumOperands(); i += 2)
18116 NewIndices.
push_back(Index.getOperand(i));
18117 EVT IndexVT = Index.getValueType()
18118 .getHalfNumVectorElementsVT(*DAG.
getContext());
18124 assert(EltCnt.isKnownEven() &&
"Splitting vector, but not in half!");
18126 EltCnt.divideCoefficientBy(2));
18129 EltCnt.divideCoefficientBy(2));
18134 {MGN->getChain(), Passthru, Mask, MGN->getBasePtr(),
18143 const auto *MSN = cast<MaskedScatterSDNode>(
N);
18144 SDValue Index = MSN->getIndex();
18145 SDValue ScaleOp = MSN->getScale();
18147 assert(!MSN->isIndexScaled() &&
18148 "Scaled gather/scatter should not be formed");
18153 N->getVTList(), MSN->getMemoryVT(),
DL,
18154 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
18156 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
18160 N->getVTList(), MSN->getMemoryVT(),
DL,
18161 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
18163 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
18165 EVT VT = MSN->getValue()->getValueType(0);
18167 if (!MSN->isTruncatingStore() &&
18171 return DAG.
getMaskedStore(MSN->getChain(),
DL, Shuffle, MSN->getBasePtr(),
18172 DAG.
getUNDEF(XLenVT), MSN->getMask(),
18173 MSN->getMemoryVT(), MSN->getMemOperand(),
18178 case ISD::VP_GATHER: {
18179 const auto *VPGN = cast<VPGatherSDNode>(
N);
18180 SDValue Index = VPGN->getIndex();
18181 SDValue ScaleOp = VPGN->getScale();
18183 assert(!VPGN->isIndexScaled() &&
18184 "Scaled gather/scatter should not be formed");
18189 {VPGN->getChain(), VPGN->getBasePtr(), Index,
18190 ScaleOp, VPGN->getMask(),
18191 VPGN->getVectorLength()},
18192 VPGN->getMemOperand(), IndexType);
18196 {VPGN->getChain(), VPGN->getBasePtr(), Index,
18197 ScaleOp, VPGN->getMask(),
18198 VPGN->getVectorLength()},
18199 VPGN->getMemOperand(), IndexType);
18203 case ISD::VP_SCATTER: {
18204 const auto *VPSN = cast<VPScatterSDNode>(
N);
18205 SDValue Index = VPSN->getIndex();
18206 SDValue ScaleOp = VPSN->getScale();
18208 assert(!VPSN->isIndexScaled() &&
18209 "Scaled gather/scatter should not be formed");
18214 {VPSN->getChain(), VPSN->getValue(),
18215 VPSN->getBasePtr(), Index, ScaleOp,
18216 VPSN->getMask(), VPSN->getVectorLength()},
18217 VPSN->getMemOperand(), IndexType);
18221 {VPSN->getChain(), VPSN->getValue(),
18222 VPSN->getBasePtr(), Index, ScaleOp,
18223 VPSN->getMask(), VPSN->getVectorLength()},
18224 VPSN->getMemOperand(), IndexType);
18238 EVT VT =
N->getValueType(0);
18241 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt,
18242 N->getOperand(2),
N->getOperand(3),
N->getOperand(4));
18260 EVT VT =
N->getValueType(0);
18264 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt);
18304 auto *Store = cast<StoreSDNode>(
N);
18305 SDValue Chain = Store->getChain();
18306 EVT MemVT = Store->getMemoryVT();
18307 SDValue Val = Store->getValue();
18310 bool IsScalarizable =
18312 Store->isSimple() &&
18342 NewVT, *Store->getMemOperand())) {
18344 return DAG.
getStore(Chain,
DL, NewV, Store->getBasePtr(),
18345 Store->getPointerInfo(), Store->getOriginalAlign(),
18346 Store->getMemOperand()->getFlags());
18354 if (
auto *L = dyn_cast<LoadSDNode>(Val);
18356 L->hasNUsesOfValue(1, 0) && L->hasNUsesOfValue(1, 1) &&
18358 L->getMemoryVT() == MemVT) {
18361 NewVT, *Store->getMemOperand()) &&
18363 NewVT, *L->getMemOperand())) {
18365 L->getPointerInfo(), L->getOriginalAlign(),
18366 L->getMemOperand()->getFlags());
18367 return DAG.
getStore(Chain,
DL, NewL, Store->getBasePtr(),
18368 Store->getPointerInfo(), Store->getOriginalAlign(),
18369 Store->getMemOperand()->getFlags());
18381 MVT VecVT = Src.getSimpleValueType();
18388 Store->getChain(),
DL, Src, Store->getBasePtr(), Store->getOffset(),
18391 Store->getMemOperand(), Store->getAddressingMode(),
18392 Store->isTruncatingStore(),
false);
18399 EVT VT =
N->getValueType(0);
18425 const MVT VT =
N->getSimpleValueType(0);
18426 SDValue Passthru =
N->getOperand(0);
18427 SDValue Scalar =
N->getOperand(1);
18436 const MVT VT =
N->getSimpleValueType(0);
18437 SDValue Passthru =
N->getOperand(0);
18438 SDValue Scalar =
N->getOperand(1);
18443 unsigned ScalarSize = Scalar.getValueSizeInBits();
18445 if (ScalarSize > EltWidth && Passthru.
isUndef())
18446 if (SimplifyDemandedLowBitsHelper(1, EltWidth))
18453 (!Const || Const->isZero() ||
18454 !Const->getAPIntValue().sextOrTrunc(EltWidth).isSignedIntN(5)))
18464 if (
N->getOperand(0).isUndef() &&
18467 Src.getOperand(0).getValueType().isScalableVector()) {
18468 EVT VT =
N->getValueType(0);
18469 EVT SrcVT = Src.getOperand(0).getValueType();
18473 return Src.getOperand(0);
18479 const MVT VT =
N->getSimpleValueType(0);
18480 SDValue Passthru =
N->getOperand(0);
18481 SDValue Scalar =
N->getOperand(1);
18485 Scalar.getOperand(0).getValueType() ==
N->getValueType(0))
18486 return Scalar.getOperand(0);
18495 DAG.
getNode(
N->getOpcode(),
DL, M1VT, M1Passthru, Scalar, VL);
18505 Const && !Const->isZero() && isInt<5>(Const->getSExtValue()) &&
18513 MVT VecVT =
N->getOperand(0).getSimpleValueType();
18515 if (M1VT.
bitsLT(VecVT)) {
18526 unsigned IntNo =
N->getConstantOperandVal(IntOpNo);
18531 case Intrinsic::riscv_vcpop:
18532 case Intrinsic::riscv_vcpop_mask:
18533 case Intrinsic::riscv_vfirst:
18534 case Intrinsic::riscv_vfirst_mask: {
18536 if (IntNo == Intrinsic::riscv_vcpop_mask ||
18537 IntNo == Intrinsic::riscv_vfirst_mask)
18538 VL =
N->getOperand(3);
18543 EVT VT =
N->getValueType(0);
18544 if (IntNo == Intrinsic::riscv_vfirst ||
18545 IntNo == Intrinsic::riscv_vfirst_mask)
18551 case ISD::EXPERIMENTAL_VP_REVERSE:
18553 case ISD::VP_STORE:
18558 EVT VT =
N->getValueType(0);
18569 for (
unsigned i = 0; i < NF; ++i)
18576 if ((SrcVT == MVT::v1i1 || SrcVT == MVT::v2i1 || SrcVT == MVT::v4i1) &&
18599 EVT XVT,
unsigned KeptBits)
const {
18604 if (XVT != MVT::i32 && XVT != MVT::i64)
18608 if (KeptBits == 32 || KeptBits == 64)
18612 return Subtarget.hasStdExtZbb() &&
18613 ((KeptBits == 8 && XVT == MVT::i64 && !Subtarget.
is64Bit()) ||
18621 "Expected shift op");
18639 if (!isa<StoreSDNode>(
Use) && !isa<LoadSDNode>(
Use))
18648 return isUsedByLdSt(N0.
getNode(),
N);
18650 auto *C1 = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
18651 auto *C2 = dyn_cast<ConstantSDNode>(
N->getOperand(1));
18654 if (Subtarget.hasStdExtZba() && C2 && C2->getZExtValue() >= 1 &&
18655 C2->getZExtValue() <= 3 &&
N->hasOneUse() &&
18656 N->user_begin()->getOpcode() ==
ISD::ADD &&
18657 !isUsedByLdSt(*
N->user_begin(),
nullptr) &&
18658 !isa<ConstantSDNode>(
N->user_begin()->getOperand(1)))
18662 const APInt &C1Int = C1->getAPIntValue();
18663 APInt ShiftedC1Int = C1Int << C2->getAPIntValue();
18689 if (C1Cost < ShiftedC1Cost)
18712 EVT VT =
Op.getValueType();
18716 unsigned Opcode =
Op.getOpcode();
18724 const APInt &Mask =
C->getAPIntValue();
18733 auto IsLegalMask = [ShrunkMask, ExpandedMask](
const APInt &Mask) ->
bool {
18734 return ShrunkMask.
isSubsetOf(Mask) && Mask.isSubsetOf(ExpandedMask);
18736 auto UseMask = [Mask,
Op, &TLO](
const APInt &NewMask) ->
bool {
18737 if (NewMask == Mask)
18742 Op.getOperand(0), NewC);
18755 APInt NewMask =
APInt(Mask.getBitWidth(), 0xffff);
18756 if (IsLegalMask(NewMask))
18757 return UseMask(NewMask);
18760 if (VT == MVT::i64) {
18762 if (IsLegalMask(NewMask))
18763 return UseMask(NewMask);
18778 APInt NewMask = ShrunkMask;
18779 if (MinSignedBits <= 12)
18781 else if (!
C->isOpaque() && MinSignedBits <= 32 && !ShrunkMask.
isSignedIntN(32))
18787 assert(IsLegalMask(NewMask));
18788 return UseMask(NewMask);
18792 static const uint64_t GREVMasks[] = {
18793 0x5555555555555555ULL, 0x3333333333333333ULL, 0x0F0F0F0F0F0F0F0FULL,
18794 0x00FF00FF00FF00FFULL, 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL};
18796 for (
unsigned Stage = 0; Stage != 6; ++Stage) {
18797 unsigned Shift = 1 << Stage;
18798 if (ShAmt & Shift) {
18800 uint64_t Res = ((x & Mask) << Shift) | ((x >> Shift) & Mask);
18812 const APInt &DemandedElts,
18814 unsigned Depth)
const {
18816 unsigned Opc =
Op.getOpcode();
18821 "Should use MaskedValueIsZero if you don't know whether Op"
18822 " is a target node!");
18905 assert(MinVLenB > 0 &&
"READ_VLENB without vector extension enabled?");
18908 if (MaxVLenB == MinVLenB)
18925 case Intrinsic::riscv_vsetvli:
18926 case Intrinsic::riscv_vsetvlimax: {
18927 bool HasAVL = IntNo == Intrinsic::riscv_vsetvli;
18928 unsigned VSEW =
Op.getConstantOperandVal(HasAVL + 1);
18934 MaxVL = (Fractional) ? MaxVL / LMul : MaxVL * LMul;
18937 if (HasAVL && isa<ConstantSDNode>(
Op.getOperand(1)))
18938 MaxVL = std::min(MaxVL,
Op.getConstantOperandVal(1));
18940 unsigned KnownZeroFirstBit =
Log2_32(MaxVL) + 1;
18953 unsigned Depth)
const {
18954 switch (
Op.getOpcode()) {
18960 if (Tmp == 1)
return 1;
18963 return std::min(Tmp, Tmp2);
18975 if (Tmp < 33)
return 1;
19000 unsigned XLen = Subtarget.
getXLen();
19001 unsigned EltBits =
Op.getOperand(0).getScalarValueSizeInBits();
19002 if (EltBits <= XLen)
19003 return XLen - EltBits + 1;
19007 unsigned IntNo =
Op.getConstantOperandVal(1);
19011 case Intrinsic::riscv_masked_atomicrmw_xchg_i64:
19012 case Intrinsic::riscv_masked_atomicrmw_add_i64:
19013 case Intrinsic::riscv_masked_atomicrmw_sub_i64:
19014 case Intrinsic::riscv_masked_atomicrmw_nand_i64:
19015 case Intrinsic::riscv_masked_atomicrmw_max_i64:
19016 case Intrinsic::riscv_masked_atomicrmw_min_i64:
19017 case Intrinsic::riscv_masked_atomicrmw_umax_i64:
19018 case Intrinsic::riscv_masked_atomicrmw_umin_i64:
19019 case Intrinsic::riscv_masked_cmpxchg_i64:
19027 assert(Subtarget.hasStdExtA());
19042 switch (
Op.getOpcode()) {
19048 return !
Op.getValueType().isInteger();
19056 assert(Ld &&
"Unexpected null LoadSDNode");
19064 auto *CNode = dyn_cast<ConstantPoolSDNode>(
Ptr);
19065 if (!CNode || CNode->isMachineConstantPoolEntry() ||
19066 CNode->getOffset() != 0)
19074 auto *CNode = GetSupportedConstantPool(
Ptr);
19075 if (!CNode || CNode->getTargetFlags() != 0)
19078 return CNode->getConstVal();
19086 auto *CNodeLo = GetSupportedConstantPool(
Ptr.getOperand(1));
19087 auto *CNodeHi = GetSupportedConstantPool(
Ptr.getOperand(0).getOperand(0));
19093 if (CNodeLo->getConstVal() != CNodeHi->getConstVal())
19096 return CNodeLo->getConstVal();
19101 assert(
MI.getOpcode() == RISCV::ReadCounterWide &&
"Unexpected instruction");
19133 Register ReadAgainReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
19136 int64_t LoCounter =
MI.getOperand(2).getImm();
19137 int64_t HiCounter =
MI.getOperand(3).getImm();
19147 BuildMI(LoopMBB,
DL,
TII->get(RISCV::CSRRS), ReadAgainReg)
19159 MI.eraseFromParent();
19167 assert(
MI.getOpcode() == RISCV::SplitF64Pseudo &&
"Unexpected instruction");
19175 Register SrcReg =
MI.getOperand(2).getReg();
19195 MI.eraseFromParent();
19202 assert(
MI.getOpcode() == RISCV::BuildPairF64Pseudo &&
19203 "Unexpected instruction");
19209 Register DstReg =
MI.getOperand(0).getReg();
19232 MI.eraseFromParent();
19237 switch (
MI.getOpcode()) {
19240 case RISCV::Select_GPR_Using_CC_GPR:
19241 case RISCV::Select_GPR_Using_CC_Imm:
19242 case RISCV::Select_FPR16_Using_CC_GPR:
19243 case RISCV::Select_FPR16INX_Using_CC_GPR:
19244 case RISCV::Select_FPR32_Using_CC_GPR:
19245 case RISCV::Select_FPR32INX_Using_CC_GPR:
19246 case RISCV::Select_FPR64_Using_CC_GPR:
19247 case RISCV::Select_FPR64INX_Using_CC_GPR:
19248 case RISCV::Select_FPR64IN32X_Using_CC_GPR:
19254 unsigned RelOpcode,
unsigned EqOpcode,
19257 Register DstReg =
MI.getOperand(0).getReg();
19258 Register Src1Reg =
MI.getOperand(1).getReg();
19259 Register Src2Reg =
MI.getOperand(2).getReg();
19261 Register SavedFFlags =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
19285 MI.eraseFromParent();
19336 F->insert(It, FirstMBB);
19337 F->insert(It, SecondMBB);
19338 F->insert(It, SinkMBB);
19387 First.eraseFromParent();
19426 if ((
MI.getOpcode() != RISCV::Select_GPR_Using_CC_GPR &&
19427 MI.getOpcode() != RISCV::Select_GPR_Using_CC_Imm) &&
19428 Next != BB->
end() && Next->getOpcode() ==
MI.getOpcode() &&
19429 Next->getOperand(5).getReg() ==
MI.getOperand(0).getReg() &&
19430 Next->getOperand(5).isKill())
19435 if (
MI.getOperand(2).isReg())
19436 RHS =
MI.getOperand(2).getReg();
19441 SelectDests.
insert(
MI.getOperand(0).getReg());
19445 SequenceMBBI != E; ++SequenceMBBI) {
19446 if (SequenceMBBI->isDebugInstr())
19449 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
19450 !SequenceMBBI->getOperand(2).isReg() ||
19451 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
19452 SequenceMBBI->getOperand(3).getImm() !=
CC ||
19453 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
19454 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
19456 LastSelectPseudo = &*SequenceMBBI;
19458 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
19461 if (SequenceMBBI->hasUnmodeledSideEffects() ||
19462 SequenceMBBI->mayLoadOrStore() ||
19463 SequenceMBBI->usesCustomInsertionHook())
19466 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
19481 F->insert(
I, IfFalseMBB);
19482 F->insert(
I, TailMBB);
19485 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
19491 TailMBB->
push_back(DebugInstr->removeFromParent());
19495 TailMBB->
splice(TailMBB->
end(), HeadMBB,
19505 if (
MI.getOperand(2).isImm())
19508 .
addImm(
MI.getOperand(2).getImm())
19520 auto SelectMBBI =
MI.getIterator();
19521 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
19523 while (SelectMBBI != SelectEnd) {
19524 auto Next = std::next(SelectMBBI);
19528 TII.get(RISCV::PHI), SelectMBBI->getOperand(0).getReg())
19529 .
addReg(SelectMBBI->getOperand(4).getReg())
19531 .
addReg(SelectMBBI->getOperand(5).getReg())
19546 RISCVVInversePseudosTable::getBaseInfo(MCOpcode, LMul, SEW);
19547 assert(
Inverse &&
"Unexpected LMUL and SEW pair for instruction");
19549 RISCV::lookupMaskedIntrinsicByUnmasked(
Inverse->Pseudo);
19550 assert(
Masked &&
"Could not find masked instruction for LMUL and SEW pair");
19556 unsigned CVTXOpc) {
19562 Register SavedFFLAGS =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
19575 .
add(
MI.getOperand(1))
19576 .
add(
MI.getOperand(2))
19577 .
add(
MI.getOperand(3))
19579 .
add(
MI.getOperand(4))
19580 .
add(
MI.getOperand(5))
19581 .
add(
MI.getOperand(6))
19596 .
add(
MI.getOperand(0))
19597 .
add(
MI.getOperand(1))
19599 .
add(
MI.getOperand(3))
19601 .
add(
MI.getOperand(4))
19602 .
add(
MI.getOperand(5))
19603 .
add(
MI.getOperand(6))
19613 MI.eraseFromParent();
19619 unsigned CmpOpc, F2IOpc, I2FOpc, FSGNJOpc, FSGNJXOpc;
19621 switch (
MI.getOpcode()) {
19624 case RISCV::PseudoFROUND_H:
19625 CmpOpc = RISCV::FLT_H;
19626 F2IOpc = RISCV::FCVT_W_H;
19627 I2FOpc = RISCV::FCVT_H_W;
19628 FSGNJOpc = RISCV::FSGNJ_H;
19629 FSGNJXOpc = RISCV::FSGNJX_H;
19630 RC = &RISCV::FPR16RegClass;
19632 case RISCV::PseudoFROUND_H_INX:
19633 CmpOpc = RISCV::FLT_H_INX;
19634 F2IOpc = RISCV::FCVT_W_H_INX;
19635 I2FOpc = RISCV::FCVT_H_W_INX;
19636 FSGNJOpc = RISCV::FSGNJ_H_INX;
19637 FSGNJXOpc = RISCV::FSGNJX_H_INX;
19638 RC = &RISCV::GPRF16RegClass;
19640 case RISCV::PseudoFROUND_S:
19641 CmpOpc = RISCV::FLT_S;
19642 F2IOpc = RISCV::FCVT_W_S;
19643 I2FOpc = RISCV::FCVT_S_W;
19644 FSGNJOpc = RISCV::FSGNJ_S;
19645 FSGNJXOpc = RISCV::FSGNJX_S;
19646 RC = &RISCV::FPR32RegClass;
19648 case RISCV::PseudoFROUND_S_INX:
19649 CmpOpc = RISCV::FLT_S_INX;
19650 F2IOpc = RISCV::FCVT_W_S_INX;
19651 I2FOpc = RISCV::FCVT_S_W_INX;
19652 FSGNJOpc = RISCV::FSGNJ_S_INX;
19653 FSGNJXOpc = RISCV::FSGNJX_S_INX;
19654 RC = &RISCV::GPRF32RegClass;
19656 case RISCV::PseudoFROUND_D:
19658 CmpOpc = RISCV::FLT_D;
19659 F2IOpc = RISCV::FCVT_L_D;
19660 I2FOpc = RISCV::FCVT_D_L;
19661 FSGNJOpc = RISCV::FSGNJ_D;
19662 FSGNJXOpc = RISCV::FSGNJX_D;
19663 RC = &RISCV::FPR64RegClass;
19665 case RISCV::PseudoFROUND_D_INX:
19667 CmpOpc = RISCV::FLT_D_INX;
19668 F2IOpc = RISCV::FCVT_L_D_INX;
19669 I2FOpc = RISCV::FCVT_D_L_INX;
19670 FSGNJOpc = RISCV::FSGNJ_D_INX;
19671 FSGNJXOpc = RISCV::FSGNJX_D_INX;
19672 RC = &RISCV::GPRRegClass;
19684 F->insert(
I, CvtMBB);
19685 F->insert(
I, DoneMBB);
19696 Register DstReg =
MI.getOperand(0).getReg();
19697 Register SrcReg =
MI.getOperand(1).getReg();
19698 Register MaxReg =
MI.getOperand(2).getReg();
19699 int64_t FRM =
MI.getOperand(3).getImm();
19704 Register FabsReg =
MRI.createVirtualRegister(RC);
19708 Register CmpReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
19723 Register F2IReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
19745 MI.eraseFromParent();
19752 switch (
MI.getOpcode()) {
19755 case RISCV::ReadCounterWide:
19757 "ReadCounterWide is only to be used on riscv32");
19759 case RISCV::Select_GPR_Using_CC_GPR:
19760 case RISCV::Select_GPR_Using_CC_Imm:
19761 case RISCV::Select_FPR16_Using_CC_GPR:
19762 case RISCV::Select_FPR16INX_Using_CC_GPR:
19763 case RISCV::Select_FPR32_Using_CC_GPR:
19764 case RISCV::Select_FPR32INX_Using_CC_GPR:
19765 case RISCV::Select_FPR64_Using_CC_GPR:
19766 case RISCV::Select_FPR64INX_Using_CC_GPR:
19767 case RISCV::Select_FPR64IN32X_Using_CC_GPR:
19769 case RISCV::BuildPairF64Pseudo:
19771 case RISCV::SplitF64Pseudo:
19773 case RISCV::PseudoQuietFLE_H:
19775 case RISCV::PseudoQuietFLE_H_INX:
19776 return emitQuietFCMP(
MI, BB, RISCV::FLE_H_INX, RISCV::FEQ_H_INX, Subtarget);
19777 case RISCV::PseudoQuietFLT_H:
19779 case RISCV::PseudoQuietFLT_H_INX:
19780 return emitQuietFCMP(
MI, BB, RISCV::FLT_H_INX, RISCV::FEQ_H_INX, Subtarget);
19781 case RISCV::PseudoQuietFLE_S:
19783 case RISCV::PseudoQuietFLE_S_INX:
19784 return emitQuietFCMP(
MI, BB, RISCV::FLE_S_INX, RISCV::FEQ_S_INX, Subtarget);
19785 case RISCV::PseudoQuietFLT_S:
19787 case RISCV::PseudoQuietFLT_S_INX:
19788 return emitQuietFCMP(
MI, BB, RISCV::FLT_S_INX, RISCV::FEQ_S_INX, Subtarget);
19789 case RISCV::PseudoQuietFLE_D:
19791 case RISCV::PseudoQuietFLE_D_INX:
19792 return emitQuietFCMP(
MI, BB, RISCV::FLE_D_INX, RISCV::FEQ_D_INX, Subtarget);
19793 case RISCV::PseudoQuietFLE_D_IN32X:
19796 case RISCV::PseudoQuietFLT_D:
19798 case RISCV::PseudoQuietFLT_D_INX:
19799 return emitQuietFCMP(
MI, BB, RISCV::FLT_D_INX, RISCV::FEQ_D_INX, Subtarget);
19800 case RISCV::PseudoQuietFLT_D_IN32X:
19804 case RISCV::PseudoVFROUND_NOEXCEPT_V_M1_MASK:
19806 case RISCV::PseudoVFROUND_NOEXCEPT_V_M2_MASK:
19808 case RISCV::PseudoVFROUND_NOEXCEPT_V_M4_MASK:
19810 case RISCV::PseudoVFROUND_NOEXCEPT_V_M8_MASK:
19812 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF2_MASK:
19814 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF4_MASK:
19816 case RISCV::PseudoFROUND_H:
19817 case RISCV::PseudoFROUND_H_INX:
19818 case RISCV::PseudoFROUND_S:
19819 case RISCV::PseudoFROUND_S_INX:
19820 case RISCV::PseudoFROUND_D:
19821 case RISCV::PseudoFROUND_D_INX:
19822 case RISCV::PseudoFROUND_D_IN32X:
19824 case RISCV::PROBED_STACKALLOC_DYN:
19826 case TargetOpcode::STATEPOINT:
19832 MI.addOperand(*
MI.getMF(),
19838 case TargetOpcode::STACKMAP:
19839 case TargetOpcode::PATCHPOINT:
19842 "supported on 64-bit targets");
19860 if (
MI.readsRegister(RISCV::FRM,
nullptr))
19866void RISCVTargetLowering::analyzeInputArgs(
19870 unsigned NumArgs = Ins.size();
19873 for (
unsigned i = 0; i != NumArgs; ++i) {
19874 MVT ArgVT = Ins[i].VT;
19877 Type *ArgTy =
nullptr;
19880 else if (Ins[i].isOrigArg())
19881 ArgTy = FType->
getParamType(Ins[i].getOrigArgIndex());
19884 true, IsRet, ArgTy)) {
19885 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type "
19892void RISCVTargetLowering::analyzeOutputArgs(
19896 unsigned NumArgs = Outs.
size();
19898 for (
unsigned i = 0; i != NumArgs; i++) {
19899 MVT ArgVT = Outs[i].VT;
19901 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
19904 Outs[i].IsFixed, IsRet, OrigTy)) {
19905 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type "
19956 if (In.isOrigArg()) {
19961 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
19962 (
BitWidth < 32 && In.Flags.isZExt())) {
19984 if (LocVT == MVT::i64 && VA.
getValVT() == MVT::f32)
20033 ExtType,
DL, LocVT, Chain, FIN,
20050 Register LoVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
20063 Register HiVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
20078 switch (CallConv) {
20088 if (Subtarget.hasStdExtE())
20092 "(Zdinx/D) instruction set extensions");
20096 if (Func.hasFnAttribute(
"interrupt")) {
20097 if (!Func.arg_empty())
20099 "Functions with the interrupt attribute cannot have arguments!");
20104 if (!(Kind ==
"user" || Kind ==
"supervisor" || Kind ==
"machine"))
20106 "Function interrupt attribute argument not supported!");
20111 unsigned XLenInBytes = Subtarget.
getXLen() / 8;
20113 std::vector<SDValue> OutChains;
20122 analyzeInputArgs(MF, CCInfo, Ins,
false,
20126 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
20147 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
20148 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
20150 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
20152 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
20181 int VarArgsSaveSize = XLenInBytes * (ArgRegs.
size() -
Idx);
20186 if (VarArgsSaveSize == 0) {
20190 int VaArgOffset = -VarArgsSaveSize;
20198 XLenInBytes, VaArgOffset -
static_cast<int>(XLenInBytes),
true);
20199 VarArgsSaveSize += XLenInBytes;
20206 for (
unsigned I =
Idx;
I < ArgRegs.
size(); ++
I) {
20211 Chain,
DL, ArgValue, FIN,
20213 OutChains.push_back(Store);
20227 if (!OutChains.empty()) {
20228 OutChains.push_back(Chain);
20238bool RISCVTargetLowering::isEligibleForTailCallOptimization(
20242 auto CalleeCC = CLI.CallConv;
20243 auto &Outs = CLI.Outs;
20245 auto CallerCC = Caller.getCallingConv();
20252 if (Caller.hasFnAttribute(
"interrupt"))
20267 for (
auto &VA : ArgLocs)
20273 auto IsCallerStructRet = Caller.hasStructRetAttr();
20274 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
20275 if (IsCallerStructRet || IsCalleeStructRet)
20280 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
20281 if (CalleeCC != CallerCC) {
20282 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
20283 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
20290 for (
auto &Arg : Outs)
20291 if (Arg.Flags.isByVal())
20326 if (Subtarget.hasStdExtE())
20330 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
20336 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
20342 "site marked musttail");
20349 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
20351 if (!Flags.isByVal())
20355 unsigned Size = Flags.getByValSize();
20356 Align Alignment = Flags.getNonZeroByValAlign();
20363 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
20365 false,
nullptr, IsTailCall,
20377 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
20380 SDValue ArgValue = OutVals[OutIdx];
20400 if (!StackPtr.getNode())
20412 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
20430 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
20431 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
20437 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
20438 SDValue PartValue = OutVals[OutIdx + 1];
20439 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
20451 int FI = cast<FrameIndexSDNode>(SpillSlot)->getIndex();
20453 DAG.
getStore(Chain,
DL, ArgValue, SpillSlot,
20455 for (
const auto &Part : Parts) {
20456 SDValue PartValue = Part.first;
20457 SDValue PartOffset = Part.second;
20464 ArgValue = SpillSlot;
20470 if (Flags.isByVal())
20471 ArgValue = ByValArgs[j++];
20478 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
20479 "for passing parameters");
20482 if (!StackPtr.getNode())
20496 if (!MemOpChains.
empty())
20502 for (
auto &Reg : RegsToPass) {
20503 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
20510 validateCCReservedRegs(RegsToPass, MF);
20514 "Return address register required, but has been reserved."});
20519 bool CalleeIsLargeExternalSymbol =
false;
20521 if (
auto *S = dyn_cast<GlobalAddressSDNode>(Callee))
20523 else if (
auto *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
20525 CalleeIsLargeExternalSymbol =
true;
20541 for (
auto &Reg : RegsToPass)
20546 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
20547 assert(Mask &&
"Missing call preserved mask for calling convention");
20555 "Unexpected CFI type for a direct call");
20563 bool NeedSWGuarded =
false;
20565 Subtarget.hasStdExtZicfilp() &&
20567 NeedSWGuarded =
true;
20581 Chain = DAG.
getNode(CallOpc,
DL, NodeTys, Ops);
20594 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_RISCV);
20597 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
20598 auto &VA = RVLocs[i];
20606 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
20607 assert(VA.needsCustom());
20628 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
20630 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
20631 MVT VT = Outs[i].VT;
20634 true,
true,
nullptr))
20666 for (
unsigned i = 0, e = RVLocs.size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
20667 SDValue Val = OutVals[OutIdx];
20676 DAG.
getVTList(MVT::i32, MVT::i32), Val);
20680 Register RegHi = RVLocs[++i].getLocReg();
20686 "Return value register required, but has been reserved."});
20702 "Return value register required, but has been reserved."});
20724 if (Func.hasFnAttribute(
"interrupt")) {
20725 if (!Func.getReturnType()->isVoidTy())
20727 "Functions with the interrupt attribute must have void return type!");
20733 if (Kind ==
"supervisor")
20739 return DAG.
getNode(RetOpc,
DL, MVT::Other, RetOps);
20742void RISCVTargetLowering::validateCCReservedRegs(
20743 const SmallVectorImpl<std::pair<llvm::Register, llvm::SDValue>> &Regs,
20752 F,
"Argument register required, but has been reserved."});
20758 if (
N->getNumValues() != 1)
20760 if (!
N->hasNUsesOfValue(1, 0))
20763 SDNode *Copy = *
N->user_begin();
20777 if (Copy->getOperand(Copy->getNumOperands() - 1).getValueType() == MVT::Glue)
20781 bool HasRet =
false;
20782 for (
SDNode *Node : Copy->users()) {
20790 Chain = Copy->getOperand(0);
20799#define NODE_NAME_CASE(NODE) \
20800 case RISCVISD::NODE: \
20801 return "RISCVISD::" #NODE;
21063#undef NODE_NAME_CASE
21070 if (Constraint.
size() == 1) {
21071 switch (Constraint[0]) {
21088 if (Constraint ==
"vr" || Constraint ==
"vd" || Constraint ==
"vm")
21090 if (Constraint ==
"cr" || Constraint ==
"cf")
21096std::pair<unsigned, const TargetRegisterClass *>
21102 if (Constraint.
size() == 1) {
21103 switch (Constraint[0]) {
21108 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
21109 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
21110 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
21111 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
21112 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
21113 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
21114 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
21116 if (VT == MVT::f16) {
21117 if (Subtarget.hasStdExtZfhmin())
21118 return std::make_pair(0U, &RISCV::FPR16RegClass);
21119 if (Subtarget.hasStdExtZhinxmin())
21120 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
21121 }
else if (VT == MVT::f32) {
21122 if (Subtarget.hasStdExtF())
21123 return std::make_pair(0U, &RISCV::FPR32RegClass);
21124 if (Subtarget.hasStdExtZfinx())
21125 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
21126 }
else if (VT == MVT::f64) {
21127 if (Subtarget.hasStdExtD())
21128 return std::make_pair(0U, &RISCV::FPR64RegClass);
21129 if (Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
21130 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
21131 if (Subtarget.hasStdExtZdinx() && Subtarget.
is64Bit())
21132 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
21136 if (VT == MVT::f64 && !Subtarget.
is64Bit() && Subtarget.hasStdExtZdinx())
21137 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
21138 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
21142 }
else if (Constraint ==
"vr") {
21143 for (
const auto *RC :
21144 {&RISCV::VRRegClass, &RISCV::VRM2RegClass, &RISCV::VRM4RegClass,
21145 &RISCV::VRM8RegClass, &RISCV::VRN2M1RegClass, &RISCV::VRN3M1RegClass,
21146 &RISCV::VRN4M1RegClass, &RISCV::VRN5M1RegClass,
21147 &RISCV::VRN6M1RegClass, &RISCV::VRN7M1RegClass,
21148 &RISCV::VRN8M1RegClass, &RISCV::VRN2M2RegClass,
21149 &RISCV::VRN3M2RegClass, &RISCV::VRN4M2RegClass,
21150 &RISCV::VRN2M4RegClass}) {
21152 return std::make_pair(0U, RC);
21154 }
else if (Constraint ==
"vd") {
21155 for (
const auto *RC :
21156 {&RISCV::VRNoV0RegClass, &RISCV::VRM2NoV0RegClass,
21157 &RISCV::VRM4NoV0RegClass, &RISCV::VRM8NoV0RegClass,
21158 &RISCV::VRN2M1NoV0RegClass, &RISCV::VRN3M1NoV0RegClass,
21159 &RISCV::VRN4M1NoV0RegClass, &RISCV::VRN5M1NoV0RegClass,
21160 &RISCV::VRN6M1NoV0RegClass, &RISCV::VRN7M1NoV0RegClass,
21161 &RISCV::VRN8M1NoV0RegClass, &RISCV::VRN2M2NoV0RegClass,
21162 &RISCV::VRN3M2NoV0RegClass, &RISCV::VRN4M2NoV0RegClass,
21163 &RISCV::VRN2M4NoV0RegClass}) {
21165 return std::make_pair(0U, RC);
21167 }
else if (Constraint ==
"vm") {
21168 if (
TRI->isTypeLegalForClass(RISCV::VMV0RegClass, VT.
SimpleTy))
21169 return std::make_pair(0U, &RISCV::VMV0RegClass);
21170 }
else if (Constraint ==
"cr") {
21171 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
21172 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
21173 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
21174 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
21175 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
21176 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
21178 return std::make_pair(0U, &RISCV::GPRCRegClass);
21179 }
else if (Constraint ==
"cf") {
21180 if (VT == MVT::f16) {
21181 if (Subtarget.hasStdExtZfhmin())
21182 return std::make_pair(0U, &RISCV::FPR16CRegClass);
21183 if (Subtarget.hasStdExtZhinxmin())
21184 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
21185 }
else if (VT == MVT::f32) {
21186 if (Subtarget.hasStdExtF())
21187 return std::make_pair(0U, &RISCV::FPR32CRegClass);
21188 if (Subtarget.hasStdExtZfinx())
21189 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
21190 }
else if (VT == MVT::f64) {
21191 if (Subtarget.hasStdExtD())
21192 return std::make_pair(0U, &RISCV::FPR64CRegClass);
21193 if (Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
21194 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
21195 if (Subtarget.hasStdExtZdinx() && Subtarget.
is64Bit())
21196 return std::make_pair(0U, &RISCV::GPRCRegClass);
21205 .
Case(
"{zero}", RISCV::X0)
21206 .
Case(
"{ra}", RISCV::X1)
21207 .
Case(
"{sp}", RISCV::X2)
21208 .
Case(
"{gp}", RISCV::X3)
21209 .
Case(
"{tp}", RISCV::X4)
21210 .
Case(
"{t0}", RISCV::X5)
21211 .
Case(
"{t1}", RISCV::X6)
21212 .
Case(
"{t2}", RISCV::X7)
21213 .
Cases(
"{s0}",
"{fp}", RISCV::X8)
21214 .
Case(
"{s1}", RISCV::X9)
21215 .
Case(
"{a0}", RISCV::X10)
21216 .
Case(
"{a1}", RISCV::X11)
21217 .
Case(
"{a2}", RISCV::X12)
21218 .
Case(
"{a3}", RISCV::X13)
21219 .
Case(
"{a4}", RISCV::X14)
21220 .
Case(
"{a5}", RISCV::X15)
21221 .
Case(
"{a6}", RISCV::X16)
21222 .
Case(
"{a7}", RISCV::X17)
21223 .
Case(
"{s2}", RISCV::X18)
21224 .
Case(
"{s3}", RISCV::X19)
21225 .
Case(
"{s4}", RISCV::X20)
21226 .
Case(
"{s5}", RISCV::X21)
21227 .
Case(
"{s6}", RISCV::X22)
21228 .
Case(
"{s7}", RISCV::X23)
21229 .
Case(
"{s8}", RISCV::X24)
21230 .
Case(
"{s9}", RISCV::X25)
21231 .
Case(
"{s10}", RISCV::X26)
21232 .
Case(
"{s11}", RISCV::X27)
21233 .
Case(
"{t3}", RISCV::X28)
21234 .
Case(
"{t4}", RISCV::X29)
21235 .
Case(
"{t5}", RISCV::X30)
21236 .
Case(
"{t6}", RISCV::X31)
21238 if (XRegFromAlias != RISCV::NoRegister)
21239 return std::make_pair(XRegFromAlias, &RISCV::GPRRegClass);
21248 if (Subtarget.hasStdExtF()) {
21250 .
Cases(
"{f0}",
"{ft0}", RISCV::F0_F)
21251 .
Cases(
"{f1}",
"{ft1}", RISCV::F1_F)
21252 .
Cases(
"{f2}",
"{ft2}", RISCV::F2_F)
21253 .
Cases(
"{f3}",
"{ft3}", RISCV::F3_F)
21254 .
Cases(
"{f4}",
"{ft4}", RISCV::F4_F)
21255 .
Cases(
"{f5}",
"{ft5}", RISCV::F5_F)
21256 .
Cases(
"{f6}",
"{ft6}", RISCV::F6_F)
21257 .
Cases(
"{f7}",
"{ft7}", RISCV::F7_F)
21258 .
Cases(
"{f8}",
"{fs0}", RISCV::F8_F)
21259 .
Cases(
"{f9}",
"{fs1}", RISCV::F9_F)
21260 .
Cases(
"{f10}",
"{fa0}", RISCV::F10_F)
21261 .
Cases(
"{f11}",
"{fa1}", RISCV::F11_F)
21262 .
Cases(
"{f12}",
"{fa2}", RISCV::F12_F)
21263 .
Cases(
"{f13}",
"{fa3}", RISCV::F13_F)
21264 .
Cases(
"{f14}",
"{fa4}", RISCV::F14_F)
21265 .
Cases(
"{f15}",
"{fa5}", RISCV::F15_F)
21266 .
Cases(
"{f16}",
"{fa6}", RISCV::F16_F)
21267 .
Cases(
"{f17}",
"{fa7}", RISCV::F17_F)
21268 .
Cases(
"{f18}",
"{fs2}", RISCV::F18_F)
21269 .
Cases(
"{f19}",
"{fs3}", RISCV::F19_F)
21270 .
Cases(
"{f20}",
"{fs4}", RISCV::F20_F)
21271 .
Cases(
"{f21}",
"{fs5}", RISCV::F21_F)
21272 .
Cases(
"{f22}",
"{fs6}", RISCV::F22_F)
21273 .
Cases(
"{f23}",
"{fs7}", RISCV::F23_F)
21274 .
Cases(
"{f24}",
"{fs8}", RISCV::F24_F)
21275 .
Cases(
"{f25}",
"{fs9}", RISCV::F25_F)
21276 .
Cases(
"{f26}",
"{fs10}", RISCV::F26_F)
21277 .
Cases(
"{f27}",
"{fs11}", RISCV::F27_F)
21278 .
Cases(
"{f28}",
"{ft8}", RISCV::F28_F)
21279 .
Cases(
"{f29}",
"{ft9}", RISCV::F29_F)
21280 .
Cases(
"{f30}",
"{ft10}", RISCV::F30_F)
21281 .
Cases(
"{f31}",
"{ft11}", RISCV::F31_F)
21283 if (FReg != RISCV::NoRegister) {
21284 assert(RISCV::F0_F <= FReg && FReg <= RISCV::F31_F &&
"Unknown fp-reg");
21285 if (Subtarget.hasStdExtD() && (VT == MVT::f64 || VT == MVT::Other)) {
21286 unsigned RegNo = FReg - RISCV::F0_F;
21287 unsigned DReg = RISCV::F0_D + RegNo;
21288 return std::make_pair(DReg, &RISCV::FPR64RegClass);
21290 if (VT == MVT::f32 || VT == MVT::Other)
21291 return std::make_pair(FReg, &RISCV::FPR32RegClass);
21292 if (Subtarget.hasStdExtZfhmin() && VT == MVT::f16) {
21293 unsigned RegNo = FReg - RISCV::F0_F;
21294 unsigned HReg = RISCV::F0_H + RegNo;
21295 return std::make_pair(HReg, &RISCV::FPR16RegClass);
21302 .
Case(
"{v0}", RISCV::V0)
21303 .
Case(
"{v1}", RISCV::V1)
21304 .
Case(
"{v2}", RISCV::V2)
21305 .
Case(
"{v3}", RISCV::V3)
21306 .
Case(
"{v4}", RISCV::V4)
21307 .
Case(
"{v5}", RISCV::V5)
21308 .
Case(
"{v6}", RISCV::V6)
21309 .
Case(
"{v7}", RISCV::V7)
21310 .
Case(
"{v8}", RISCV::V8)
21311 .
Case(
"{v9}", RISCV::V9)
21312 .
Case(
"{v10}", RISCV::V10)
21313 .
Case(
"{v11}", RISCV::V11)
21314 .
Case(
"{v12}", RISCV::V12)
21315 .
Case(
"{v13}", RISCV::V13)
21316 .
Case(
"{v14}", RISCV::V14)
21317 .
Case(
"{v15}", RISCV::V15)
21318 .
Case(
"{v16}", RISCV::V16)
21319 .
Case(
"{v17}", RISCV::V17)
21320 .
Case(
"{v18}", RISCV::V18)
21321 .
Case(
"{v19}", RISCV::V19)
21322 .
Case(
"{v20}", RISCV::V20)
21323 .
Case(
"{v21}", RISCV::V21)
21324 .
Case(
"{v22}", RISCV::V22)
21325 .
Case(
"{v23}", RISCV::V23)
21326 .
Case(
"{v24}", RISCV::V24)
21327 .
Case(
"{v25}", RISCV::V25)
21328 .
Case(
"{v26}", RISCV::V26)
21329 .
Case(
"{v27}", RISCV::V27)
21330 .
Case(
"{v28}", RISCV::V28)
21331 .
Case(
"{v29}", RISCV::V29)
21332 .
Case(
"{v30}", RISCV::V30)
21333 .
Case(
"{v31}", RISCV::V31)
21335 if (VReg != RISCV::NoRegister) {
21336 if (
TRI->isTypeLegalForClass(RISCV::VMRegClass, VT.
SimpleTy))
21337 return std::make_pair(VReg, &RISCV::VMRegClass);
21338 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, VT.
SimpleTy))
21339 return std::make_pair(VReg, &RISCV::VRRegClass);
21340 for (
const auto *RC :
21341 {&RISCV::VRM2RegClass, &RISCV::VRM4RegClass, &RISCV::VRM8RegClass}) {
21342 if (
TRI->isTypeLegalForClass(*RC, VT.
SimpleTy)) {
21343 VReg =
TRI->getMatchingSuperReg(VReg, RISCV::sub_vrm1_0, RC);
21344 return std::make_pair(VReg, RC);
21350 std::pair<Register, const TargetRegisterClass *> Res =
21356 if (Res.second == &RISCV::GPRF16RegClass ||
21357 Res.second == &RISCV::GPRF32RegClass ||
21358 Res.second == &RISCV::GPRPairRegClass)
21359 return std::make_pair(Res.first, &RISCV::GPRRegClass);
21367 if (ConstraintCode.
size() == 1) {
21368 switch (ConstraintCode[0]) {
21383 if (Constraint.
size() == 1) {
21384 switch (Constraint[0]) {
21387 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
21389 if (isInt<12>(CVal))
21402 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
21404 if (isUInt<5>(CVal))
21422 if (Subtarget.hasStdExtZtso()) {
21438 if (Subtarget.hasStdExtZtso()) {
21446 if (Subtarget.enableTrailingSeqCstFence() && isa<StoreInst>(Inst) &&
21465 if (Subtarget.hasForcedAtomics())
21470 if (Subtarget.hasStdExtZacas() &&
21471 (
Size >= 32 || Subtarget.hasStdExtZabha()))
21477 if (
Size < 32 && !Subtarget.hasStdExtZabha())
21490 return Intrinsic::riscv_masked_atomicrmw_xchg_i32;
21492 return Intrinsic::riscv_masked_atomicrmw_add_i32;
21494 return Intrinsic::riscv_masked_atomicrmw_sub_i32;
21496 return Intrinsic::riscv_masked_atomicrmw_nand_i32;
21498 return Intrinsic::riscv_masked_atomicrmw_max_i32;
21500 return Intrinsic::riscv_masked_atomicrmw_min_i32;
21502 return Intrinsic::riscv_masked_atomicrmw_umax_i32;
21504 return Intrinsic::riscv_masked_atomicrmw_umin_i32;
21513 return Intrinsic::riscv_masked_atomicrmw_xchg_i64;
21515 return Intrinsic::riscv_masked_atomicrmw_add_i64;
21517 return Intrinsic::riscv_masked_atomicrmw_sub_i64;
21519 return Intrinsic::riscv_masked_atomicrmw_nand_i64;
21521 return Intrinsic::riscv_masked_atomicrmw_max_i64;
21523 return Intrinsic::riscv_masked_atomicrmw_min_i64;
21525 return Intrinsic::riscv_masked_atomicrmw_umax_i64;
21527 return Intrinsic::riscv_masked_atomicrmw_umin_i64;
21553 unsigned XLen = Subtarget.
getXLen();
21577 unsigned ValWidth =
21582 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
21585 Builder.
CreateCall(LrwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
21597 if (Subtarget.hasForcedAtomics())
21601 if (!(Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas()) &&
21610 unsigned XLen = Subtarget.
getXLen();
21612 Intrinsic::ID CmpXchgIntrID = Intrinsic::riscv_masked_cmpxchg_i32;
21617 CmpXchgIntrID = Intrinsic::riscv_masked_cmpxchg_i64;
21621 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, Ordering});
21628 EVT DataVT)
const {
21644 return Subtarget.hasStdExtZfhmin();
21646 return Subtarget.hasStdExtF();
21648 return Subtarget.hasStdExtD();
21680 "RVVBitsPerBlock changed, audit needed");
21689 if (!Subtarget.hasVendorXTHeadMemIdx())
21695 Base =
Op->getOperand(0);
21697 int64_t RHSC =
RHS->getSExtValue();
21703 bool isLegalIndexedOffset =
false;
21704 for (
unsigned i = 0; i < 4; i++)
21705 if (isInt<5>(RHSC >> i) && ((RHSC % (1LL << i)) == 0)) {
21706 isLegalIndexedOffset =
true;
21710 if (!isLegalIndexedOffset)
21727 VT = LD->getMemoryVT();
21728 Ptr = LD->getBasePtr();
21729 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
21730 VT = ST->getMemoryVT();
21731 Ptr = ST->getBasePtr();
21747 if (Subtarget.hasVendorXCVmem() && !Subtarget.
is64Bit()) {
21752 Base = LS->getBasePtr();
21756 if (
Base ==
Op->getOperand(0))
21758 else if (
Base ==
Op->getOperand(1))
21770 VT = LD->getMemoryVT();
21771 Ptr = LD->getBasePtr();
21772 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
21773 VT = ST->getMemoryVT();
21774 Ptr = ST->getBasePtr();
21817 const Constant *PersonalityFn)
const {
21822 const Constant *PersonalityFn)
const {
21837 bool IsSigned)
const {
21852 const bool HasZmmul = Subtarget.hasStdExtZmmul();
21856 auto *ConstNode = cast<ConstantSDNode>(
C);
21857 const APInt &Imm = ConstNode->getAPIntValue();
21860 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
21861 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
21865 if (Subtarget.hasStdExtZba() && !Imm.isSignedIntN(12) &&
21866 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
21867 (Imm - 8).isPowerOf2()))
21872 if (!Imm.isSignedIntN(12) && Imm.countr_zero() < 12 &&
21873 ConstNode->hasOneUse()) {
21874 APInt ImmS = Imm.ashr(Imm.countr_zero());
21875 if ((ImmS + 1).isPowerOf2() || (ImmS - 1).isPowerOf2() ||
21876 (1 - ImmS).isPowerOf2())
21899 if (C1.
isSignedIntN(12) && !(C1 * C2).isSignedIntN(12))
21908 unsigned *
Fast)
const {
21911 *
Fast = Subtarget.enableUnalignedScalarMem();
21912 return Subtarget.enableUnalignedScalarMem();
21928 *
Fast = Subtarget.enableUnalignedVectorMem();
21929 return Subtarget.enableUnalignedVectorMem();
21938 if (FuncAttributes.
hasFnAttr(Attribute::NoImplicitFloat))
21950 if (
Op.size() < MinVLenInBytes)
21965 MVT PreferredVT = (
Op.isMemset() && !
Op.isZeroMemset()) ? MVT::i8 : ELenVT;
21969 if (PreferredVT != MVT::i8 && !Subtarget.enableUnalignedVectorMem()) {
21971 if (
Op.isFixedDstAlign())
21972 RequiredAlign = std::min(RequiredAlign,
Op.getDstAlign());
21974 RequiredAlign = std::min(RequiredAlign,
Op.getSrcAlign());
21982 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID>
CC)
const {
21983 bool IsABIRegCopy =
CC.has_value();
21986 MVT PairVT = Subtarget.
is64Bit() ? MVT::i128 : MVT::i64;
21987 if ((ValueVT == PairVT ||
21988 (!Subtarget.
is64Bit() && Subtarget.hasStdExtZdinx() &&
21989 ValueVT == MVT::f64)) &&
21990 NumParts == 1 && PartVT == MVT::Untyped) {
21993 if (ValueVT == MVT::f64)
22002 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
22003 PartVT == MVT::f32) {
22018 [[maybe_unused]]
unsigned ValLMUL =
22022 [[maybe_unused]]
unsigned PartLMUL =
22025 assert(ValNF == PartNF && ValLMUL == PartLMUL &&
22026 "RISC-V vector tuple type only accepts same register class type "
22042 if (PartVTBitSize % ValueVTBitSize == 0) {
22043 assert(PartVTBitSize >= ValueVTBitSize);
22050 if (ValueEltVT != PartEltVT) {
22051 if (PartVTBitSize > ValueVTBitSize) {
22053 assert(Count != 0 &&
"The number of element should not be zero.");
22054 EVT SameEltTypeVT =
22076 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID>
CC)
const {
22077 bool IsABIRegCopy =
CC.has_value();
22079 MVT PairVT = Subtarget.
is64Bit() ? MVT::i128 : MVT::i64;
22080 if ((ValueVT == PairVT ||
22081 (!Subtarget.
is64Bit() && Subtarget.hasStdExtZdinx() &&
22082 ValueVT == MVT::f64)) &&
22083 NumParts == 1 && PartVT == MVT::Untyped) {
22094 if (ValueVT == MVT::f64)
22099 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
22100 PartVT == MVT::f32) {
22117 if (PartVTBitSize % ValueVTBitSize == 0) {
22118 assert(PartVTBitSize >= ValueVTBitSize);
22119 EVT SameEltTypeVT = ValueVT;
22126 if (ValueEltVT != PartEltVT) {
22128 assert(Count != 0 &&
"The number of element should not be zero.");
22145 bool OptSize = Attr.
hasFnAttr(Attribute::MinSize);
22152 unsigned Opc =
N->getOpcode();
22180 if (M->getStackProtectorGuard() ==
"tls") {
22182 int Offset = M->getStackProtectorGuardOffset();
22190 VectorType *VTy,
unsigned Factor,
Align Alignment,
unsigned AddrSpace,
22204 if (
auto *FVTy = dyn_cast<FixedVectorType>(VTy)) {
22209 if (FVTy->getNumElements() < 2)
22224 return Factor * LMUL <= 8;
22228 Align Alignment)
const {
22240 if (!Subtarget.enableUnalignedVectorMem() &&
22248 Intrinsic::riscv_seg2_load, Intrinsic::riscv_seg3_load,
22249 Intrinsic::riscv_seg4_load, Intrinsic::riscv_seg5_load,
22250 Intrinsic::riscv_seg6_load, Intrinsic::riscv_seg7_load,
22251 Intrinsic::riscv_seg8_load};
22272 auto *VTy = cast<FixedVectorType>(Shuffles[0]->
getType());
22284 unsigned ScalarSizeInBytes = VTy->getScalarSizeInBits() / 8;
22285 Value *Stride = ConstantInt::get(XLenTy, Factor * ScalarSizeInBytes);
22286 Value *
Offset = ConstantInt::get(XLenTy, Indices[0] * ScalarSizeInBytes);
22293 {VTy, BasePtr->getType(), Stride->
getType()},
22294 {BasePtr, Stride, Mask, VL});
22297 Shuffles[0]->replaceAllUsesWith(CI);
22301 Value *VL = ConstantInt::get(XLenTy, VTy->getNumElements());
22307 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
22309 Shuffles[i]->replaceAllUsesWith(SubVec);
22316 Intrinsic::riscv_seg2_store, Intrinsic::riscv_seg3_store,
22317 Intrinsic::riscv_seg4_store, Intrinsic::riscv_seg5_store,
22318 Intrinsic::riscv_seg6_store, Intrinsic::riscv_seg7_store,
22319 Intrinsic::riscv_seg8_store};
22339 unsigned Factor)
const {
22342 auto *ShuffleVTy = cast<FixedVectorType>(SVI->
getType());
22345 ShuffleVTy->getNumElements() / Factor);
22347 SI->getPointerAddressSpace(),
22348 SI->getDataLayout()))
22359 unsigned ScalarSizeInBytes = ShuffleVTy->getScalarSizeInBits() / 8;
22361 auto *DataVTy = cast<FixedVectorType>(
Data->getType());
22362 Value *Stride = ConstantInt::get(XLenTy, Factor * ScalarSizeInBytes);
22363 Value *
Offset = ConstantInt::get(XLenTy, Index * ScalarSizeInBytes);
22369 Intrinsic::experimental_vp_strided_store,
22370 {
Data->getType(), BasePtr->getType(), Stride->
getType()},
22371 {
Data, BasePtr, Stride, Mask, VL});
22380 {VTy, SI->getPointerOperandType(), XLenTy});
22384 for (
unsigned i = 0; i < Factor; i++) {
22393 Value *VL = ConstantInt::get(XLenTy, VTy->getNumElements());
22394 Ops.
append({SI->getPointerOperand(), VL});
22411 const unsigned Factor = 2;
22423 if (
auto *FVTy = dyn_cast<FixedVectorType>(ResVTy)) {
22424 Value *VL = ConstantInt::get(XLenTy, FVTy->getNumElements());
22431 Intrinsic::riscv_vlseg2, Intrinsic::riscv_vlseg3,
22432 Intrinsic::riscv_vlseg4, Intrinsic::riscv_vlseg5,
22433 Intrinsic::riscv_vlseg6, Intrinsic::riscv_vlseg7,
22434 Intrinsic::riscv_vlseg8};
22441 NumElts * SEW / 8),
22447 IntrIds[Factor - 2], {VecTupTy, XLenTy},
22449 ConstantInt::get(XLenTy,
Log2_64(SEW))});
22453 for (
unsigned i = 0; i < Factor; ++i) {
22455 Intrinsic::riscv_tuple_extract, {ResVTy, VecTupTy},
22473 if (
II->getIntrinsicID() != Intrinsic::vector_interleave2)
22476 const unsigned Factor = 2;
22478 VectorType *InVTy = cast<VectorType>(
II->getArgOperand(0)->getType());
22482 SI->getPointerAddressSpace(),
DL))
22487 if (
auto *FVTy = dyn_cast<FixedVectorType>(InVTy)) {
22488 Value *VL = ConstantInt::get(XLenTy, FVTy->getNumElements());
22490 {InVTy, SI->getPointerOperandType(), XLenTy},
22491 {
II->getArgOperand(0),
II->getArgOperand(1),
22492 SI->getPointerOperand(), VL});
22495 Intrinsic::riscv_vsseg2, Intrinsic::riscv_vsseg3,
22496 Intrinsic::riscv_vsseg4, Intrinsic::riscv_vsseg5,
22497 Intrinsic::riscv_vsseg6, Intrinsic::riscv_vsseg7,
22498 Intrinsic::riscv_vsseg8};
22503 SI->getContext(),
"riscv.vector.tuple",
22505 NumElts * SEW / 8),
22509 SI->getModule(), IntrIds[Factor - 2], {VecTupTy, XLenTy});
22514 for (
unsigned i = 0; i < Factor; ++i)
22516 Intrinsic::riscv_tuple_insert, {VecTupTy, InVTy},
22517 {StoredVal, II->getArgOperand(i), Builder.getInt32(i)});
22519 Builder.
CreateCall(VssegNFunc, {StoredVal, SI->getPointerOperand(), VL,
22520 ConstantInt::get(XLenTy,
Log2_64(SEW))});
22531 "Invalid call instruction for a KCFI check");
22533 MBBI->getOpcode()));
22536 Target.setIsRenamable(
false);
22544#define GET_REGISTER_MATCHER
22545#include "RISCVGenAsmMatcher.inc"
22551 if (Reg == RISCV::NoRegister)
22553 if (Reg == RISCV::NoRegister)
22565 const MDNode *NontemporalInfo =
I.getMetadata(LLVMContext::MD_nontemporal);
22567 if (NontemporalInfo ==
nullptr)
22575 int NontemporalLevel = 5;
22576 const MDNode *RISCVNontemporalInfo =
22577 I.getMetadata(
"riscv-nontemporal-domain");
22578 if (RISCVNontemporalInfo !=
nullptr)
22581 cast<ConstantAsMetadata>(RISCVNontemporalInfo->
getOperand(0))
22585 assert((1 <= NontemporalLevel && NontemporalLevel <= 5) &&
22586 "RISC-V target doesn't support this non-temporal domain.");
22588 NontemporalLevel -= 2;
22590 if (NontemporalLevel & 0b1)
22592 if (NontemporalLevel & 0b10)
22605 return TargetFlags;
22615 return isTypeLegal(VT) && Subtarget.hasStdExtZvbb();
22618 return Subtarget.hasStdExtZbb() &&
22629 if (Subtarget.hasStdExtZalasr()) {
22630 if (Subtarget.hasStdExtZtso()) {
22635 auto *LI = dyn_cast<LoadInst>(
I);
22636 auto *SI = dyn_cast<StoreInst>(
I);
22646 return isa<LoadInst>(
I) || isa<StoreInst>(
I);
22653 return isa<LoadInst>(
I) || isa<StoreInst>(
I);
22660 if (
Op == Instruction::Add ||
Op == Instruction::Sub ||
22661 Op == Instruction::And ||
Op == Instruction::Or ||
22662 Op == Instruction::Xor ||
Op == Instruction::InsertElement ||
22663 Op == Instruction::ShuffleVector ||
Op == Instruction::Load ||
22664 Op == Instruction::Freeze ||
Op == Instruction::Store)
22672 !isa<ReturnInst>(&Inst))
22675 if (
const AllocaInst *AI = dyn_cast<AllocaInst>(&Inst)) {
22676 if (AI->getAllocatedType()->isScalableTy())
22684RISCVTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
22692 if (!Subtarget.hasShortForwardBranchOpt())
22694 EVT VT =
N->getValueType(0);
22695 if (!(VT == MVT::i32 || (VT == MVT::i64 && Subtarget.
is64Bit())))
22699 if (Divisor.
sgt(2048) || Divisor.
slt(-2048))
22704bool RISCVTargetLowering::shouldFoldSelectWithSingleBitTest(
22705 EVT VT,
const APInt &AndMask)
const {
22706 if (Subtarget.hasStdExtZicond() || Subtarget.hasVendorXVentanaCondOps())
22707 return !Subtarget.hasStdExtZbs() && AndMask.
ugt(1024);
22711unsigned RISCVTargetLowering::getMinimumJumpTableEntries()
const {
22719 if (Subtarget.hasStdExtZicfilp()) {
22743std::pair<const TargetRegisterClass *, uint8_t>
22763#define GET_RISCVVIntrinsicsTable_IMPL
22764#include "RISCVGenSearchableTables.inc"
22779 Align StackAlign)
const {
22783 unsigned StackProbeSize =
22787 return StackProbeSize ? StackProbeSize : StackAlign.
value();
22802 cast<ConstantSDNode>(
Op.getOperand(2))->getMaybeAlignValue();
22804 EVT VT =
Op.getValueType();
22825 Register TargetReg =
MI.getOperand(1).getReg();
22828 bool IsRV64 = Subtarget.
is64Bit();
22836 MF.
insert(MBBInsertPoint, LoopTestMBB);
22838 MF.
insert(MBBInsertPoint, ExitMBB);
22854 TII->get(IsRV64 ? RISCV::SD : RISCV::SW))
22877 MI.eraseFromParent();
22879 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 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 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)
Custom legalize <N x i128> or <N x i256> to <M x ELEN>.
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 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) const override
Store the specified register of the given register class to the specified stack frame index.
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override
Load the specified register of the given register class from the specified stack frame index.
Common base class shared among various IRBuilders.
Value * CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
Value * 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.
A wrapper class for inspecting calls to intrinsic functions.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
This is an important class for using LLVM in a threaded context.
void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
Base class for LoadSDNode and StoreSDNode.
bool isIndexed() const
Return true if this is a pre/post inc/dec load/store.
An instruction for reading from memory.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
Value * getPointerOperand()
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
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 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 lowerInterleaveIntrinsicToStore(IntrinsicInst *II, StoreInst *SI, SmallVectorImpl< Instruction * > &DeadInsts) const override
Lower an interleave intrinsic to a target specific store intrinsic.
bool isDesirableToCommuteWithShift(const SDNode *N, CombineLevel Level) const override
Return true if it is profitable to move this shift by a constant amount through its operand,...
bool areTwoSDNodeTargetMMOFlagsMergeable(const MemSDNode &NodeX, const MemSDNode &NodeY) const override
Return true if it is valid to merge the TargetMMOFlags in two SDNodes.
bool hasBitTest(SDValue X, SDValue Y) const override
Return true if the target has a bit-test instruction: (X & (1 << Y)) ==/!= 0 This knowledge can be us...
static unsigned computeVLMAX(unsigned VectorBits, unsigned EltSize, unsigned MinSize)
bool shouldExpandCttzElements(EVT VT) const override
Return true if the @llvm.experimental.cttz.elts intrinsic should be expanded using generic code in Se...
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
Value * emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, AtomicCmpXchgInst *CI, Value *AlignedAddr, Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const override
Perform a masked cmpxchg using a target-specific intrinsic.
bool isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize) const override
Returns true if the target can instruction select the specified FP immediate natively.
InstructionCost getLMULCost(MVT VT) const
Return the cost of LMUL for linear operations.
unsigned getJumpTableEncoding() const override
Return the entry encoding for a jump table in the current function.
bool isMulAddWithConstProfitable(SDValue AddNode, SDValue ConstNode) const override
Return true if it may be profitable to transform (mul (add x, c1), c2) -> (add (mul x,...
InstructionCost getVSlideVICost(MVT VT) const
Return the cost of a vslidedown.vi or vslideup.vi instruction for the type VT.
bool fallBackToDAGISel(const Instruction &Inst) const override
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
bool 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 lowerDeinterleaveIntrinsicToLoad(IntrinsicInst *II, LoadInst *LI, SmallVectorImpl< Instruction * > &DeadInsts) const override
Lower a deinterleave intrinsic to a target specific load intrinsic.
bool shouldTransformSignedTruncationCheck(EVT XVT, unsigned KeptBits) const override
Should we tranform the IR-optimal check for whether given truncation down into KeptBits would be trun...
bool shouldProduceAndByConstByHoistingConstFromShiftsLHSOfAnd(SDValue X, ConstantSDNode *XC, ConstantSDNode *CC, SDValue Y, unsigned OldShiftOpcode, unsigned NewShiftOpcode, SelectionDAG &DAG) const override
Given the pattern (X & (C l>>/<< Y)) ==/!= 0 return true if it should be transformed into: ((X <</l>>...
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.
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 getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), AAResults *AA=nullptr)
SDValue getStridedLoadVP(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, const SDLoc &DL, SDValue Chain, SDValue Ptr, SDValue Offset, SDValue Stride, SDValue Mask, SDValue EVL, EVT MemVT, MachineMemOperand *MMO, bool IsExpanding=false)
SDValue makeEquivalentMemoryOrdering(SDValue OldChain, SDValue NewMemOpChain)
If an existing load has uses of its chain, create a token factor node with that chain and the new mem...
SDValue getJumpTableDebugInfo(int JTI, SDValue Chain, const SDLoc &DL)
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false)
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
bool isSafeToSpeculativelyExecute(unsigned Opcode) const
Some opcodes may create immediate undefined behavior when used with some values (integer division-by-...
SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
SDValue 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,...
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 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 * getContainedType(unsigned i) const
This method is used to implement the type iterator (defined at the end of the file).
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
A Use represents the edge between a Value definition and its users.
User * getUser() const
Returns the User that contains this Use.
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.
ElementCount getElementCount() const
Return an ElementCount instance to represent the (possibly scalable) number of elements in the vector...
Type * getElementType() const
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.
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...
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)