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())
1531 ISD::EXPERIMENTAL_VP_REVERSE,
ISD::MUL,
1534 if (Subtarget.hasVendorXTHeadMemPair())
1577MVT RISCVTargetLowering::getVPExplicitVectorLengthTy()
const {
1582bool RISCVTargetLowering::shouldExpandGetVectorLength(
EVT TripCountVT,
1584 bool IsScalable)
const {
1591 if (TripCountVT != MVT::i32 && TripCountVT != Subtarget.
getXLenVT())
1616 unsigned Intrinsic)
const {
1617 auto &
DL =
I.getDataLayout();
1619 auto SetRVVLoadStoreInfo = [&](
unsigned PtrOp,
bool IsStore,
1620 bool IsUnitStrided,
bool UsePtrVal =
false) {
1625 Info.ptrVal =
I.getArgOperand(PtrOp);
1627 Info.fallbackAddressSpace =
1628 I.getArgOperand(PtrOp)->getType()->getPointerAddressSpace();
1632 MemTy =
I.getArgOperand(0)->getType();
1635 MemTy =
I.getType();
1645 if (cast<TargetExtType>(MemTy)->
getName() ==
"riscv.vector.tuple")
1648 1 << cast<ConstantInt>(
I.getArgOperand(
I.arg_size() - 1))
1650 Info.align =
DL.getABITypeAlign(MemTy);
1660 if (
I.hasMetadata(LLVMContext::MD_nontemporal))
1664 switch (Intrinsic) {
1667 case Intrinsic::riscv_masked_atomicrmw_xchg_i32:
1668 case Intrinsic::riscv_masked_atomicrmw_add_i32:
1669 case Intrinsic::riscv_masked_atomicrmw_sub_i32:
1670 case Intrinsic::riscv_masked_atomicrmw_nand_i32:
1671 case Intrinsic::riscv_masked_atomicrmw_max_i32:
1672 case Intrinsic::riscv_masked_atomicrmw_min_i32:
1673 case Intrinsic::riscv_masked_atomicrmw_umax_i32:
1674 case Intrinsic::riscv_masked_atomicrmw_umin_i32:
1675 case Intrinsic::riscv_masked_cmpxchg_i32:
1677 Info.memVT = MVT::i32;
1678 Info.ptrVal =
I.getArgOperand(0);
1684 case Intrinsic::riscv_seg2_load:
1685 case Intrinsic::riscv_seg3_load:
1686 case Intrinsic::riscv_seg4_load:
1687 case Intrinsic::riscv_seg5_load:
1688 case Intrinsic::riscv_seg6_load:
1689 case Intrinsic::riscv_seg7_load:
1690 case Intrinsic::riscv_seg8_load:
1691 return SetRVVLoadStoreInfo( 0,
false,
1693 case Intrinsic::riscv_seg2_store:
1694 case Intrinsic::riscv_seg3_store:
1695 case Intrinsic::riscv_seg4_store:
1696 case Intrinsic::riscv_seg5_store:
1697 case Intrinsic::riscv_seg6_store:
1698 case Intrinsic::riscv_seg7_store:
1699 case Intrinsic::riscv_seg8_store:
1701 return SetRVVLoadStoreInfo(
I.arg_size() - 2,
1704 case Intrinsic::riscv_vle:
1705 case Intrinsic::riscv_vle_mask:
1706 case Intrinsic::riscv_vleff:
1707 case Intrinsic::riscv_vleff_mask:
1708 return SetRVVLoadStoreInfo( 1,
1712 case Intrinsic::riscv_vse:
1713 case Intrinsic::riscv_vse_mask:
1714 return SetRVVLoadStoreInfo( 1,
1718 case Intrinsic::riscv_vlse:
1719 case Intrinsic::riscv_vlse_mask:
1720 case Intrinsic::riscv_vloxei:
1721 case Intrinsic::riscv_vloxei_mask:
1722 case Intrinsic::riscv_vluxei:
1723 case Intrinsic::riscv_vluxei_mask:
1724 return SetRVVLoadStoreInfo( 1,
1727 case Intrinsic::riscv_vsse:
1728 case Intrinsic::riscv_vsse_mask:
1729 case Intrinsic::riscv_vsoxei:
1730 case Intrinsic::riscv_vsoxei_mask:
1731 case Intrinsic::riscv_vsuxei:
1732 case Intrinsic::riscv_vsuxei_mask:
1733 return SetRVVLoadStoreInfo( 1,
1736 case Intrinsic::riscv_vlseg2:
1737 case Intrinsic::riscv_vlseg3:
1738 case Intrinsic::riscv_vlseg4:
1739 case Intrinsic::riscv_vlseg5:
1740 case Intrinsic::riscv_vlseg6:
1741 case Intrinsic::riscv_vlseg7:
1742 case Intrinsic::riscv_vlseg8:
1743 case Intrinsic::riscv_vlseg2ff:
1744 case Intrinsic::riscv_vlseg3ff:
1745 case Intrinsic::riscv_vlseg4ff:
1746 case Intrinsic::riscv_vlseg5ff:
1747 case Intrinsic::riscv_vlseg6ff:
1748 case Intrinsic::riscv_vlseg7ff:
1749 case Intrinsic::riscv_vlseg8ff:
1750 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1753 case Intrinsic::riscv_vlseg2_mask:
1754 case Intrinsic::riscv_vlseg3_mask:
1755 case Intrinsic::riscv_vlseg4_mask:
1756 case Intrinsic::riscv_vlseg5_mask:
1757 case Intrinsic::riscv_vlseg6_mask:
1758 case Intrinsic::riscv_vlseg7_mask:
1759 case Intrinsic::riscv_vlseg8_mask:
1760 case Intrinsic::riscv_vlseg2ff_mask:
1761 case Intrinsic::riscv_vlseg3ff_mask:
1762 case Intrinsic::riscv_vlseg4ff_mask:
1763 case Intrinsic::riscv_vlseg5ff_mask:
1764 case Intrinsic::riscv_vlseg6ff_mask:
1765 case Intrinsic::riscv_vlseg7ff_mask:
1766 case Intrinsic::riscv_vlseg8ff_mask:
1767 return SetRVVLoadStoreInfo(
I.arg_size() - 5,
1770 case Intrinsic::riscv_vlsseg2:
1771 case Intrinsic::riscv_vlsseg3:
1772 case Intrinsic::riscv_vlsseg4:
1773 case Intrinsic::riscv_vlsseg5:
1774 case Intrinsic::riscv_vlsseg6:
1775 case Intrinsic::riscv_vlsseg7:
1776 case Intrinsic::riscv_vlsseg8:
1777 case Intrinsic::riscv_vloxseg2:
1778 case Intrinsic::riscv_vloxseg3:
1779 case Intrinsic::riscv_vloxseg4:
1780 case Intrinsic::riscv_vloxseg5:
1781 case Intrinsic::riscv_vloxseg6:
1782 case Intrinsic::riscv_vloxseg7:
1783 case Intrinsic::riscv_vloxseg8:
1784 case Intrinsic::riscv_vluxseg2:
1785 case Intrinsic::riscv_vluxseg3:
1786 case Intrinsic::riscv_vluxseg4:
1787 case Intrinsic::riscv_vluxseg5:
1788 case Intrinsic::riscv_vluxseg6:
1789 case Intrinsic::riscv_vluxseg7:
1790 case Intrinsic::riscv_vluxseg8:
1791 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
1794 case Intrinsic::riscv_vlsseg2_mask:
1795 case Intrinsic::riscv_vlsseg3_mask:
1796 case Intrinsic::riscv_vlsseg4_mask:
1797 case Intrinsic::riscv_vlsseg5_mask:
1798 case Intrinsic::riscv_vlsseg6_mask:
1799 case Intrinsic::riscv_vlsseg7_mask:
1800 case Intrinsic::riscv_vlsseg8_mask:
1801 case Intrinsic::riscv_vloxseg2_mask:
1802 case Intrinsic::riscv_vloxseg3_mask:
1803 case Intrinsic::riscv_vloxseg4_mask:
1804 case Intrinsic::riscv_vloxseg5_mask:
1805 case Intrinsic::riscv_vloxseg6_mask:
1806 case Intrinsic::riscv_vloxseg7_mask:
1807 case Intrinsic::riscv_vloxseg8_mask:
1808 case Intrinsic::riscv_vluxseg2_mask:
1809 case Intrinsic::riscv_vluxseg3_mask:
1810 case Intrinsic::riscv_vluxseg4_mask:
1811 case Intrinsic::riscv_vluxseg5_mask:
1812 case Intrinsic::riscv_vluxseg6_mask:
1813 case Intrinsic::riscv_vluxseg7_mask:
1814 case Intrinsic::riscv_vluxseg8_mask:
1815 return SetRVVLoadStoreInfo(
I.arg_size() - 6,
1818 case Intrinsic::riscv_vsseg2:
1819 case Intrinsic::riscv_vsseg3:
1820 case Intrinsic::riscv_vsseg4:
1821 case Intrinsic::riscv_vsseg5:
1822 case Intrinsic::riscv_vsseg6:
1823 case Intrinsic::riscv_vsseg7:
1824 case Intrinsic::riscv_vsseg8:
1825 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1828 case Intrinsic::riscv_vsseg2_mask:
1829 case Intrinsic::riscv_vsseg3_mask:
1830 case Intrinsic::riscv_vsseg4_mask:
1831 case Intrinsic::riscv_vsseg5_mask:
1832 case Intrinsic::riscv_vsseg6_mask:
1833 case Intrinsic::riscv_vsseg7_mask:
1834 case Intrinsic::riscv_vsseg8_mask:
1835 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
1838 case Intrinsic::riscv_vssseg2:
1839 case Intrinsic::riscv_vssseg3:
1840 case Intrinsic::riscv_vssseg4:
1841 case Intrinsic::riscv_vssseg5:
1842 case Intrinsic::riscv_vssseg6:
1843 case Intrinsic::riscv_vssseg7:
1844 case Intrinsic::riscv_vssseg8:
1845 case Intrinsic::riscv_vsoxseg2:
1846 case Intrinsic::riscv_vsoxseg3:
1847 case Intrinsic::riscv_vsoxseg4:
1848 case Intrinsic::riscv_vsoxseg5:
1849 case Intrinsic::riscv_vsoxseg6:
1850 case Intrinsic::riscv_vsoxseg7:
1851 case Intrinsic::riscv_vsoxseg8:
1852 case Intrinsic::riscv_vsuxseg2:
1853 case Intrinsic::riscv_vsuxseg3:
1854 case Intrinsic::riscv_vsuxseg4:
1855 case Intrinsic::riscv_vsuxseg5:
1856 case Intrinsic::riscv_vsuxseg6:
1857 case Intrinsic::riscv_vsuxseg7:
1858 case Intrinsic::riscv_vsuxseg8:
1859 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
1862 case Intrinsic::riscv_vssseg2_mask:
1863 case Intrinsic::riscv_vssseg3_mask:
1864 case Intrinsic::riscv_vssseg4_mask:
1865 case Intrinsic::riscv_vssseg5_mask:
1866 case Intrinsic::riscv_vssseg6_mask:
1867 case Intrinsic::riscv_vssseg7_mask:
1868 case Intrinsic::riscv_vssseg8_mask:
1869 case Intrinsic::riscv_vsoxseg2_mask:
1870 case Intrinsic::riscv_vsoxseg3_mask:
1871 case Intrinsic::riscv_vsoxseg4_mask:
1872 case Intrinsic::riscv_vsoxseg5_mask:
1873 case Intrinsic::riscv_vsoxseg6_mask:
1874 case Intrinsic::riscv_vsoxseg7_mask:
1875 case Intrinsic::riscv_vsoxseg8_mask:
1876 case Intrinsic::riscv_vsuxseg2_mask:
1877 case Intrinsic::riscv_vsuxseg3_mask:
1878 case Intrinsic::riscv_vsuxseg4_mask:
1879 case Intrinsic::riscv_vsuxseg5_mask:
1880 case Intrinsic::riscv_vsuxseg6_mask:
1881 case Intrinsic::riscv_vsuxseg7_mask:
1882 case Intrinsic::riscv_vsuxseg8_mask:
1883 return SetRVVLoadStoreInfo(
I.arg_size() - 5,
1924 return isInt<12>(Imm);
1928 return isInt<12>(Imm);
1941 return (SrcBits == 64 && DestBits == 32);
1952 return (SrcBits == 64 && DestBits == 32);
1963 if (SrcBits == DestBits * 2) {
1974 if (
auto *LD = dyn_cast<LoadSDNode>(Val)) {
1975 EVT MemVT = LD->getMemoryVT();
1976 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
1986 return Subtarget.
is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
1994 return Subtarget.hasStdExtZbb() ||
1995 (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit());
1999 return Subtarget.hasStdExtZbb() || Subtarget.hasVendorXTHeadBb() ||
2000 (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit());
2011 if (!Subtarget.hasStdExtZbs() && !Subtarget.hasVendorXTHeadBs())
2016 return !Mask->getValue().isSignedIntN(12) && Mask->getValue().isPowerOf2();
2020 EVT VT =
Y.getValueType();
2026 return (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
2027 (!isa<ConstantSDNode>(
Y) || cast<ConstantSDNode>(
Y)->isOpaque());
2032 if (Subtarget.hasStdExtZbs())
2033 return X.getValueType().isScalarInteger();
2034 auto *
C = dyn_cast<ConstantSDNode>(
Y);
2036 if (Subtarget.hasVendorXTHeadBs())
2037 return C !=
nullptr;
2039 return C &&
C->getAPIntValue().ule(10);
2059 if (BitSize > Subtarget.
getXLen())
2063 int64_t Val = Imm.getSExtValue();
2071 if (!Subtarget.enableUnalignedScalarMem())
2087 unsigned OldShiftOpcode,
unsigned NewShiftOpcode,
2094 if (XC && OldShiftOpcode ==
ISD::SRL && XC->isOne())
2098 if (NewShiftOpcode ==
ISD::SRL &&
CC->isOne())
2142 if (!Subtarget.hasStdExtZfa())
2145 bool IsSupportedVT =
false;
2146 if (VT == MVT::f16) {
2147 IsSupportedVT = Subtarget.hasStdExtZfh() || Subtarget.hasStdExtZvfh();
2148 }
else if (VT == MVT::f32) {
2149 IsSupportedVT =
true;
2150 }
else if (VT == MVT::f64) {
2151 assert(Subtarget.hasStdExtD() &&
"Expect D extension");
2152 IsSupportedVT =
true;
2162 bool ForCodeSize)
const {
2163 bool IsLegalVT =
false;
2166 else if (VT == MVT::f32)
2168 else if (VT == MVT::f64)
2170 else if (VT == MVT::bf16)
2171 IsLegalVT = Subtarget.hasStdExtZfbfmin();
2183 return Imm.isZero();
2187 if (Imm.isNegZero())
2192 const int FmvCost = Subtarget.hasStdExtZfinx() ? 0 : 1;
2195 Subtarget.
getXLen(), Subtarget);
2201 unsigned Index)
const {
2214 if (EltVT == MVT::i1)
2227 if (Index + ResElts <= MinVLMAX && Index < 31)
2236 return (ResElts * 2) == SrcElts && (Index == 0 || Index == ResElts);
2255 std::optional<MVT> RegisterVT)
const {
2257 if (VT == (Subtarget.
is64Bit() ? MVT::i128 : MVT::i64) && RegisterVT &&
2258 *RegisterVT == MVT::Untyped)
2278 unsigned &NumIntermediates,
MVT &RegisterVT)
const {
2280 Context,
CC, VT, IntermediateVT, NumIntermediates, RegisterVT);
2295 isa<ConstantSDNode>(
LHS.getOperand(1))) {
2301 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
2314 if (
auto *RHSC = dyn_cast<ConstantSDNode>(
RHS)) {
2315 int64_t
C = RHSC->getSExtValue();
2353 if (VT.
SimpleTy >= MVT::riscv_nxv1i8x2 &&
2354 VT.
SimpleTy <= MVT::riscv_nxv1i8x8)
2356 if (VT.
SimpleTy >= MVT::riscv_nxv2i8x2 &&
2357 VT.
SimpleTy <= MVT::riscv_nxv2i8x8)
2359 if (VT.
SimpleTy >= MVT::riscv_nxv4i8x2 &&
2360 VT.
SimpleTy <= MVT::riscv_nxv4i8x8)
2362 if (VT.
SimpleTy >= MVT::riscv_nxv8i8x2 &&
2363 VT.
SimpleTy <= MVT::riscv_nxv8i8x8)
2365 if (VT.
SimpleTy >= MVT::riscv_nxv16i8x2 &&
2366 VT.
SimpleTy <= MVT::riscv_nxv16i8x4)
2368 if (VT.
SimpleTy == MVT::riscv_nxv32i8x2)
2378 switch (KnownSize) {
2406 return RISCV::VRRegClassID;
2408 return RISCV::VRM2RegClassID;
2410 return RISCV::VRM4RegClassID;
2412 return RISCV::VRM8RegClassID;
2422 static_assert(RISCV::sub_vrm1_7 == RISCV::sub_vrm1_0 + 7,
2423 "Unexpected subreg numbering");
2424 return RISCV::sub_vrm1_0 + Index;
2427 static_assert(RISCV::sub_vrm2_3 == RISCV::sub_vrm2_0 + 3,
2428 "Unexpected subreg numbering");
2429 return RISCV::sub_vrm2_0 + Index;
2432 static_assert(RISCV::sub_vrm4_1 == RISCV::sub_vrm4_0 + 1,
2433 "Unexpected subreg numbering");
2434 return RISCV::sub_vrm4_0 + Index;
2442 unsigned RegsPerField =
2445 switch (RegsPerField) {
2448 return RISCV::VRN2M1RegClassID;
2450 return RISCV::VRN3M1RegClassID;
2452 return RISCV::VRN4M1RegClassID;
2454 return RISCV::VRN5M1RegClassID;
2456 return RISCV::VRN6M1RegClassID;
2458 return RISCV::VRN7M1RegClassID;
2460 return RISCV::VRN8M1RegClassID;
2464 return RISCV::VRN2M2RegClassID;
2466 return RISCV::VRN3M2RegClassID;
2468 return RISCV::VRN4M2RegClassID;
2472 return RISCV::VRN2M4RegClassID;
2480 return RISCV::VRRegClassID;
2489std::pair<unsigned, unsigned>
2491 MVT VecVT,
MVT SubVecVT,
unsigned InsertExtractIdx,
2493 static_assert((RISCV::VRM8RegClassID > RISCV::VRM4RegClassID &&
2494 RISCV::VRM4RegClassID > RISCV::VRM2RegClassID &&
2495 RISCV::VRM2RegClassID > RISCV::VRRegClassID),
2496 "Register classes not ordered");
2503 if (VecRegClassID == SubRegClassID)
2504 return {RISCV::NoSubRegister, 0};
2507 "Only allow scalable vector subvector.");
2509 "Invalid vector tuple insert/extract for vector and subvector with "
2520 unsigned SubRegIdx = RISCV::NoSubRegister;
2521 for (
const unsigned RCID :
2522 {RISCV::VRM4RegClassID, RISCV::VRM2RegClassID, RISCV::VRRegClassID})
2523 if (VecRegClassID > RCID && SubRegClassID <= RCID) {
2527 SubRegIdx =
TRI->composeSubRegIndices(SubRegIdx,
2532 return {SubRegIdx, InsertExtractIdx};
2537bool RISCVTargetLowering::mergeStoresAfterLegalization(
EVT VT)
const {
2568unsigned RISCVTargetLowering::combineRepeatedFPDivisors()
const {
2575 "Unexpected opcode");
2577 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
2579 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
2582 return Op.getOperand(
II->VLOperand + 1 + HasChain);
2656bool RISCVTargetLowering::useRVVForFixedLengthVectorVT(
MVT VT)
const {
2657 return ::useRVVForFixedLengthVectorVT(VT, Subtarget);
2666 "Expected legal fixed length vector!");
2669 unsigned MaxELen = Subtarget.
getELen();
2703 return ::getContainerForFixedLengthVector(*
this, VT,
getSubtarget());
2710 "Expected to convert into a scalable vector!");
2711 assert(V.getValueType().isFixedLengthVector() &&
2712 "Expected a fixed length vector operand!");
2722 "Expected to convert into a fixed length vector!");
2723 assert(V.getValueType().isScalableVector() &&
2724 "Expected a scalable vector operand!");
2747static std::pair<SDValue, SDValue>
2756static std::pair<SDValue, SDValue>
2769static std::pair<SDValue, SDValue>
2786std::pair<unsigned, unsigned>
2802 return std::make_pair(MinVLMAX, MaxVLMAX);
2814 EVT VT,
unsigned DefinedValues)
const {
2828 std::tie(LMul, Fractional) =
2831 Cost = LMul <= DLenFactor ? (DLenFactor / LMul) : 1;
2833 Cost = (LMul * DLenFactor);
2876 Op.getValueType() == MVT::bf16) {
2877 bool IsStrict =
Op->isStrictFPOpcode();
2882 {Op.getOperand(0), Op.getOperand(1)});
2884 {
Op.getValueType(), MVT::Other},
2890 DAG.
getNode(
Op.getOpcode(),
DL, MVT::f32,
Op.getOperand(0)),
2905 MVT DstVT =
Op.getSimpleValueType();
2906 EVT SatVT = cast<VTSDNode>(
Op.getOperand(1))->getVT();
2914 Src.getValueType() == MVT::bf16) {
2921 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
2929 Opc,
DL, DstVT, Src,
2943 MVT SrcVT = Src.getSimpleValueType();
2949 if (SatVT != DstEltVT)
2952 MVT DstContainerVT = DstVT;
2953 MVT SrcContainerVT = SrcVT;
2959 "Expected same element count");
2968 {Src, Src, DAG.getCondCode(ISD::SETNE),
2969 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
2973 if (DstEltSize > (2 * SrcEltSize)) {
2979 MVT CvtContainerVT = DstContainerVT;
2980 MVT CvtEltVT = DstEltVT;
2981 if (SrcEltSize > (2 * DstEltSize)) {
2990 while (CvtContainerVT != DstContainerVT) {
2996 Res = DAG.
getNode(ClipOpc,
DL, CvtContainerVT, Res, Mask, VL);
3003 Res, DAG.
getUNDEF(DstContainerVT), VL);
3013 bool IsStrict =
Op->isStrictFPOpcode();
3014 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
3024 {
Op.getOperand(0), SrcVal});
3025 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
3026 {Ext.getValue(1), Ext.getValue(0)});
3040 case ISD::VP_FROUNDEVEN:
3044 case ISD::VP_FROUNDTOZERO:
3048 case ISD::VP_FFLOOR:
3056 case ISD::VP_FROUND:
3073 MVT VT =
Op.getSimpleValueType();
3080 MVT ContainerVT = VT;
3087 if (
Op->isVPOpcode()) {
3088 Mask =
Op.getOperand(1);
3092 VL =
Op.getOperand(2);
3114 DAG.
getUNDEF(ContainerVT), MaxValNode, VL);
3128 switch (
Op.getOpcode()) {
3136 case ISD::VP_FFLOOR:
3139 case ISD::VP_FROUND:
3140 case ISD::VP_FROUNDEVEN:
3141 case ISD::VP_FROUNDTOZERO: {
3153 case ISD::VP_FNEARBYINT:
3166 Src, Src, Mask, VL);
3181 MVT VT =
Op.getSimpleValueType();
3185 MVT ContainerVT = VT;
3197 MVT MaskVT = Mask.getSimpleValueType();
3200 {Chain, Src, Src, DAG.getCondCode(ISD::SETUNE),
3201 DAG.getUNDEF(MaskVT), Mask, VL});
3205 {Chain, Src, Src, Src, Unorder, VL});
3206 Chain = Src.getValue(1);
3222 DAG.
getUNDEF(ContainerVT), MaxValNode, VL);
3234 switch (
Op.getOpcode()) {
3245 {Chain, Src, Mask, DAG.getTargetConstant(FRM, DL, XLenVT), VL});
3251 DAG.
getVTList(IntVT, MVT::Other), Chain, Src, Mask, VL);
3255 DAG.
getVTList(ContainerVT, MVT::Other), Chain, Src,
3264 DAG.
getVTList(ContainerVT, MVT::Other), Chain,
3265 Truncated, Mask, VL);
3271 Src, Src, Mask, VL);
3281 MVT VT =
Op.getSimpleValueType();
3309 MVT VT =
Op.getSimpleValueType();
3314 MVT ContainerVT = VT;
3359 "Unexpected vector MVT");
3387 return std::nullopt;
3405 unsigned EltSizeInBits) {
3408 return std::nullopt;
3409 bool IsInteger =
Op.getValueType().isInteger();
3411 std::optional<unsigned> SeqStepDenom;
3412 std::optional<APInt> SeqStepNum;
3413 std::optional<APInt> SeqAddend;
3414 std::optional<std::pair<APInt, unsigned>> PrevElt;
3415 assert(EltSizeInBits >=
Op.getValueType().getScalarSizeInBits());
3420 const unsigned OpSize =
Op.getScalarValueSizeInBits();
3422 if (Elt.isUndef()) {
3423 Elts[
Idx] = std::nullopt;
3427 Elts[
Idx] = Elt->getAsAPIntVal().trunc(OpSize).zext(EltSizeInBits);
3432 return std::nullopt;
3433 Elts[
Idx] = *ExactInteger;
3446 unsigned IdxDiff =
Idx - PrevElt->second;
3447 APInt ValDiff = *Elt - PrevElt->first;
3455 int64_t Remainder = ValDiff.
srem(IdxDiff);
3460 return std::nullopt;
3461 ValDiff = ValDiff.
sdiv(IdxDiff);
3466 SeqStepNum = ValDiff;
3467 else if (ValDiff != SeqStepNum)
3468 return std::nullopt;
3471 SeqStepDenom = IdxDiff;
3472 else if (IdxDiff != *SeqStepDenom)
3473 return std::nullopt;
3477 if (!PrevElt || PrevElt->first != *Elt)
3478 PrevElt = std::make_pair(*Elt,
Idx);
3482 if (!SeqStepNum || !SeqStepDenom)
3483 return std::nullopt;
3491 (
APInt(EltSizeInBits,
Idx,
false,
true) *
3493 .sdiv(*SeqStepDenom);
3495 APInt Addend = *Elt - ExpectedVal;
3498 else if (Addend != SeqAddend)
3499 return std::nullopt;
3502 assert(SeqAddend &&
"Must have an addend if we have a step");
3504 return VIDSequence{SeqStepNum->getSExtValue(), *SeqStepDenom,
3505 SeqAddend->getSExtValue()};
3520 if (EltTy == MVT::i1 ||
3533 MVT ContainerVT = VT;
3562 MVT VT =
Op.getSimpleValueType();
3574 unsigned MostCommonCount = 0;
3576 unsigned NumUndefElts =
3584 unsigned NumScalarLoads = 0;
3590 unsigned &Count = ValueCounts[V];
3592 if (
auto *CFP = dyn_cast<ConstantFPSDNode>(V))
3593 NumScalarLoads += !CFP->isExactlyValue(+0.0);
3598 if (++Count >= MostCommonCount) {
3600 MostCommonCount = Count;
3604 assert(DominantValue &&
"Not expecting an all-undef BUILD_VECTOR");
3605 unsigned NumDefElts = NumElts - NumUndefElts;
3606 unsigned DominantValueCountThreshold = NumDefElts <= 2 ? 0 : NumDefElts - 2;
3612 ((MostCommonCount > DominantValueCountThreshold) ||
3625 !LastOp.isUndef() && ValueCounts[LastOp] == 1 &&
3626 LastOp != DominantValue) {
3635 Processed.insert(LastOp);
3640 const SDValue &V = OpIdx.value();
3641 if (V.isUndef() || !Processed.insert(V).second)
3643 if (ValueCounts[V] == 1) {
3652 return DAG.getConstant(V == V1, DL, XLenVT);
3668 MVT VT =
Op.getSimpleValueType();
3698 unsigned NumViaIntegerBits = std::clamp(NumElts, 8u, Subtarget.
getXLen());
3699 NumViaIntegerBits = std::min(NumViaIntegerBits, Subtarget.
getELen());
3707 unsigned IntegerViaVecElts =
divideCeil(NumElts, NumViaIntegerBits);
3708 MVT IntegerViaVecVT =
3713 unsigned BitPos = 0, IntegerEltIdx = 0;
3716 for (
unsigned I = 0;
I < NumElts;) {
3718 bool BitValue = !V.isUndef() && V->getAsZExtVal();
3719 Bits |= ((
uint64_t)BitValue << BitPos);
3725 if (
I % NumViaIntegerBits == 0 ||
I == NumElts) {
3726 if (NumViaIntegerBits <= 32)
3727 Bits = SignExtend64<32>(Bits);
3729 Elts[IntegerEltIdx] = Elt;
3738 if (NumElts < NumViaIntegerBits) {
3742 assert(IntegerViaVecVT == MVT::v1i8 &&
"Unexpected mask vector type");
3770 int64_t StepNumerator = SimpleVID->StepNumerator;
3771 unsigned StepDenominator = SimpleVID->StepDenominator;
3772 int64_t Addend = SimpleVID->Addend;
3774 assert(StepNumerator != 0 &&
"Invalid step");
3775 bool Negate =
false;
3776 int64_t SplatStepVal = StepNumerator;
3780 if (StepNumerator != 1 && StepNumerator !=
INT64_MIN &&
3782 Negate = StepNumerator < 0;
3784 SplatStepVal =
Log2_64(std::abs(StepNumerator));
3791 if (((StepOpcode ==
ISD::MUL && isInt<12>(SplatStepVal)) ||
3792 (StepOpcode ==
ISD::SHL && isUInt<5>(SplatStepVal))) &&
3794 (SplatStepVal >= 0 || StepDenominator == 1) && isInt<5>(Addend)) {
3797 MVT VIDContainerVT =
3805 if ((StepOpcode ==
ISD::MUL && SplatStepVal != 1) ||
3806 (StepOpcode ==
ISD::SHL && SplatStepVal != 0)) {
3808 VID = DAG.
getNode(StepOpcode,
DL, VIDVT, VID, SplatStep);
3810 if (StepDenominator != 1) {
3815 if (Addend != 0 || Negate) {
3834 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32) &&
3835 "Unexpected sequence type");
3839 unsigned ViaVecLen =
3843 uint64_t EltMask = maskTrailingOnes<uint64_t>(EltBitSize);
3846 for (
const auto &OpIdx :
enumerate(
Op->op_values())) {
3847 const auto &SeqV = OpIdx.value();
3848 if (!SeqV.isUndef())
3850 ((SeqV->getAsZExtVal() & EltMask) << (OpIdx.index() * EltBitSize));
3856 if (ViaIntVT == MVT::i32)
3857 SplatValue = SignExtend64<32>(SplatValue);
3879 const auto *BV = cast<BuildVectorSDNode>(
Op);
3882 BV->getRepeatedSequence(Sequence) &&
3883 (Sequence.size() * EltBitSize) <= Subtarget.
getELen()) {
3884 unsigned SeqLen = Sequence.size();
3886 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32 ||
3887 ViaIntVT == MVT::i64) &&
3888 "Unexpected sequence type");
3893 const unsigned RequiredVL = NumElts / SeqLen;
3894 const unsigned ViaVecLen =
3896 NumElts : RequiredVL;
3899 unsigned EltIdx = 0;
3900 uint64_t EltMask = maskTrailingOnes<uint64_t>(EltBitSize);
3904 for (
const auto &SeqV : Sequence) {
3905 if (!SeqV.isUndef())
3907 ((SeqV->getAsZExtVal() & EltMask) << (EltIdx * EltBitSize));
3914 if (ViaIntVT == MVT::i32)
3915 SplatValue = SignExtend64<32>(SplatValue);
3921 (!Subtarget.
is64Bit() && ViaIntVT == MVT::i64)) &&
3922 "Unexpected bitcast sequence");
3923 if (ViaIntVT.
bitsLE(XLenVT) || isInt<32>(SplatValue)) {
3926 MVT ViaContainerVT =
3933 if (ViaVecLen != RequiredVL)
3953 Source, DAG, Subtarget);
3973 return RISCV::PACKH;
3975 return Subtarget.
is64Bit() ? RISCV::PACKW : RISCV::PACK;
3990 MVT VT =
Op.getSimpleValueType();
3998 if (!Subtarget.hasStdExtZbb() || !Subtarget.hasStdExtZba())
4003 if (ElemSizeInBits >= std::min(Subtarget.
getELen(), Subtarget.
getXLen()) ||
4017 if (Subtarget.hasStdExtZbkb())
4022 ElemDL, XLenVT,
A,
B),
4034 NewOperands.
reserve(NumElts / 2);
4036 NewOperands.
push_back(pack(
Op.getOperand(i),
Op.getOperand(i + 1)));
4046 MVT VT =
Op.getSimpleValueType();
4057 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) || EltVT == MVT::bf16) {
4062 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4063 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin())) {
4066 if (
auto *
C = dyn_cast<ConstantFPSDNode>(Elem)) {
4150 auto OneVRegOfOps =
ArrayRef(BuildVectorOps).
slice(i, ElemsPerVReg);
4154 unsigned InsertIdx = (i / ElemsPerVReg) * NumOpElts;
4177 unsigned NumUndefElts =
4179 unsigned NumDefElts = NumElts - NumUndefElts;
4180 if (NumDefElts >= 8 && NumDefElts > NumElts / 2 &&
4187 for (
unsigned i = 0; i < NumElts; i++) {
4189 if (i < NumElts / 2) {
4196 bool SelectMaskVal = (i < NumElts / 2);
4199 assert(SubVecAOps.
size() == NumElts && SubVecBOps.
size() == NumElts &&
4200 MaskVals.
size() == NumElts);
4235 unsigned UndefCount = 0;
4242 LinearBudget -= PerSlideCost;
4245 LinearBudget -= PerSlideCost;
4248 LinearBudget -= PerSlideCost;
4251 if (LinearBudget < 0)
4256 "Illegal type which will result in reserved encoding");
4281 Vec,
Offset, Mask, VL, Policy);
4294 Vec,
Offset, Mask, VL, Policy);
4304 if (isa<ConstantSDNode>(
Lo) && isa<ConstantSDNode>(
Hi)) {
4305 int32_t LoC = cast<ConstantSDNode>(
Lo)->getSExtValue();
4306 int32_t HiC = cast<ConstantSDNode>(
Hi)->getSExtValue();
4309 if ((LoC >> 31) == HiC)
4320 (isa<RegisterSDNode>(VL) &&
4321 cast<RegisterSDNode>(VL)->
getReg() == RISCV::X0))
4323 else if (isa<ConstantSDNode>(VL) && isUInt<4>(VL->
getAsZExtVal()))
4338 isa<ConstantSDNode>(
Hi.getOperand(1)) &&
4339 Hi.getConstantOperandVal(1) == 31)
4358 assert(Scalar.getValueType() == MVT::i64 &&
"Unexpected VT!");
4370 bool HasPassthru = Passthru && !Passthru.
isUndef();
4371 if (!HasPassthru && !Passthru)
4378 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
4379 EltVT == MVT::bf16) {
4380 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4381 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
4395 if (Scalar.getValueType().bitsLE(XLenVT)) {
4402 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4406 assert(XLenVT == MVT::i32 && Scalar.getValueType() == MVT::i64 &&
4407 "Unexpected scalar for splat lowering!");
4431 SDValue ExtractedVal = Scalar.getOperand(0);
4436 MVT ExtractedContainerVT = ExtractedVT;
4439 DAG, ExtractedContainerVT, Subtarget);
4441 ExtractedVal, DAG, Subtarget);
4443 if (ExtractedContainerVT.
bitsLE(VT))
4458 if (!Scalar.getValueType().bitsLE(XLenVT))
4461 VT,
DL, DAG, Subtarget);
4469 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4489 if (Src != V2.getOperand(0))
4494 if (Src.getValueType().getVectorNumElements() != (NumElts * 2))
4499 V2.getConstantOperandVal(1) != NumElts)
4517 int Size = Mask.size();
4519 assert(
Size == (
int)NumElts &&
"Unexpected mask size");
4525 EvenSrc = StartIndexes[0];
4526 OddSrc = StartIndexes[1];
4529 if (EvenSrc != 0 && OddSrc != 0)
4539 int HalfNumElts = NumElts / 2;
4540 return ((EvenSrc % HalfNumElts) == 0) && ((OddSrc % HalfNumElts) == 0);
4556 int Size = Mask.size();
4568 for (
int i = 0; i !=
Size; ++i) {
4574 int StartIdx = i - (M %
Size);
4582 int CandidateRotation = StartIdx < 0 ? -StartIdx :
Size - StartIdx;
4585 Rotation = CandidateRotation;
4586 else if (Rotation != CandidateRotation)
4591 int MaskSrc = M <
Size ? 0 : 1;
4596 int &TargetSrc = StartIdx < 0 ? HiSrc : LoSrc;
4601 TargetSrc = MaskSrc;
4602 else if (TargetSrc != MaskSrc)
4609 assert(Rotation != 0 &&
"Failed to locate a viable rotation!");
4610 assert((LoSrc >= 0 || HiSrc >= 0) &&
4611 "Failed to find a rotated input vector!");
4625 ElementCount SrcEC = Src.getValueType().getVectorElementCount();
4632 unsigned Shift = Index * EltBits;
4659 auto findNonEXTRACT_SUBVECTORParent =
4660 [](
SDValue Parent) -> std::pair<SDValue, uint64_t> {
4665 Parent.getOperand(0).getSimpleValueType().isFixedLengthVector()) {
4666 Offset += Parent.getConstantOperandVal(1);
4667 Parent = Parent.getOperand(0);
4669 return std::make_pair(Parent,
Offset);
4672 auto [V1Src, V1IndexOffset] = findNonEXTRACT_SUBVECTORParent(V1);
4673 auto [V2Src, V2IndexOffset] = findNonEXTRACT_SUBVECTORParent(V2);
4682 for (
size_t i = 0; i != NewMask.
size(); ++i) {
4683 if (NewMask[i] == -1)
4686 if (
static_cast<size_t>(NewMask[i]) < NewMask.
size()) {
4687 NewMask[i] = NewMask[i] + V1IndexOffset;
4691 NewMask[i] = NewMask[i] - NewMask.
size() + V2IndexOffset;
4697 if (NewMask[0] <= 0)
4701 for (
unsigned i = 1; i != NewMask.
size(); ++i)
4702 if (NewMask[i - 1] + 1 != NewMask[i])
4706 MVT SrcVT = Src.getSimpleValueType();
4737 int NumSubElts, Index;
4742 bool OpsSwapped = Mask[Index] < (int)NumElts;
4743 SDValue InPlace = OpsSwapped ? V2 : V1;
4744 SDValue ToInsert = OpsSwapped ? V1 : V2;
4754 if (NumSubElts + Index >= (
int)NumElts)
4768 Res =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, InPlace, ToInsert,
4780 bool OpsSwapped =
false;
4781 if (!isa<BuildVectorSDNode>(V1)) {
4782 if (!isa<BuildVectorSDNode>(V2))
4787 SDValue Splat = cast<BuildVectorSDNode>(V1)->getSplatValue();
4795 const unsigned E = Mask.size() - ((
Offset > 0) ?
Offset : 0);
4796 for (
unsigned i = S; i != E; ++i)
4797 if (Mask[i] >= 0 && (
unsigned)Mask[i] !=
Base + i +
Offset)
4803 bool IsVSlidedown = isSlideMask(Mask, OpsSwapped ? 0 : NumElts, 1);
4804 if (!IsVSlidedown && !isSlideMask(Mask, OpsSwapped ? 0 : NumElts, -1))
4807 const int InsertIdx = Mask[IsVSlidedown ? (NumElts - 1) : 0];
4809 if (InsertIdx < 0 || InsertIdx / NumElts != (
unsigned)OpsSwapped)
4832 auto OpCode = IsVSlidedown ?
4837 auto Vec = DAG.
getNode(OpCode,
DL, ContainerVT,
4840 Splat, TrueMask, VL);
4851 for (
unsigned i = 0; i < Mask.size(); i++)
4852 LaneIsUndef[i % Factor] &= (Mask[i] == -1);
4855 for (
unsigned i = 0; i < Factor; i++) {
4866 for (
unsigned i = 0; i < Mask.size() / Factor; i++) {
4867 unsigned j = i * Factor + Index;
4868 if (Mask[j] != -1 && (
unsigned)Mask[j] != i)
4881 MVT VT = V.getSimpleValueType();
4896 EC.multiplyCoefficientBy(Factor));
4915 MVT VecContainerVT = VecVT;
4932 MVT WideContainerVT = WideVT;
4938 EvenV = DAG.
getBitcast(VecContainerVT, EvenV);
4945 if (Subtarget.hasStdExtZvbb()) {
4950 OffsetVec, Passthru, Mask, VL);
4952 Interleaved, EvenV, Passthru, Mask, VL);
4960 OddV, Passthru, Mask, VL);
4966 OddV, AllOnesVec, Passthru, Mask, VL);
4974 Interleaved, OddsMul, Passthru, Mask, VL);
4981 Interleaved = DAG.
getBitcast(ResultContainerVT, Interleaved);
5027 if (ViaEltSize > NumElts)
5036 if (ViaEltSize > NumElts)
5042 if (ViaEltSize > NumElts)
5051 MVT &RotateVT,
unsigned &RotateAmt) {
5057 unsigned NumSubElts;
5059 NumElts, NumSubElts, RotateAmt))
5062 NumElts / NumSubElts);
5130 unsigned NumOfSrcRegs = NumElts / NumOpElts;
5131 unsigned NumOfDestRegs = NumElts / NumOpElts;
5140 Mask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs,
5141 [&]() {
Operands.emplace_back(); },
5142 [&](
ArrayRef<int> SrcSubMask,
unsigned SrcVecIdx,
unsigned DstVecIdx) {
5143 Operands.emplace_back().emplace_back(
5144 SrcVecIdx, UINT_MAX,
5147 [&](
ArrayRef<int> SrcSubMask,
unsigned Idx1,
unsigned Idx2,
bool NewReg) {
5153 assert(
Operands.size() == NumOfDestRegs &&
"Whole vector must be processed");
5158 unsigned NumShuffles = std::accumulate(
5165 for (const auto &P : Data) {
5166 unsigned Idx2 = std::get<1>(P);
5167 ArrayRef<int> Mask = std::get<2>(P);
5168 if (Idx2 != UINT_MAX)
5170 else if (ShuffleVectorInst::isIdentityMask(Mask, Mask.size()))
5175 if ((NumOfDestRegs > 2 && NumShuffles > NumOfDestRegs) ||
5176 (NumOfDestRegs <= 2 && NumShuffles >= 4))
5178 auto ExtractValue = [&, &DAG = DAG](
SDValue SrcVec,
unsigned ExtractIdx) {
5180 DAG.getVectorIdxConstant(ExtractIdx,
DL));
5184 auto PerformShuffle = [&, &DAG = DAG](
SDValue SubVec1,
SDValue SubVec2,
5186 SDValue SubVec = DAG.getVectorShuffle(OneRegVT,
DL, SubVec1, SubVec2, Mask);
5189 SDValue Vec = DAG.getUNDEF(ContainerVT);
5194 for (
unsigned I : seq<unsigned>(
Data.size())) {
5195 const auto &[Idx1, Idx2,
_] =
Data[
I];
5198 "Expected both indices to be extracted already.");
5201 SDValue V = ExtractValue(Idx1 >= NumOfSrcRegs ? V2 : V1,
5202 (Idx1 % NumOfSrcRegs) * NumOpElts);
5204 if (Idx2 != UINT_MAX)
5205 Values[Idx2] = ExtractValue(Idx2 >= NumOfSrcRegs ? V2 : V1,
5206 (Idx2 % NumOfSrcRegs) * NumOpElts);
5209 for (
const auto &[Idx1, Idx2, Mask] :
Data) {
5211 SDValue V2 = Idx2 == UINT_MAX ? V1 : Values.
at(Idx2);
5212 V = PerformShuffle(V1, V2, Mask);
5216 unsigned InsertIdx =
I * NumOpElts;
5219 DAG.getVectorIdxConstant(InsertIdx,
DL));
5229 bool SawUndef =
false;
5230 for (
unsigned i = 0; i < Mask.size(); i++) {
5231 if (Mask[i] == -1) {
5237 if (i > (
unsigned)Mask[i])
5239 if (Mask[i] <=
Last)
5270 for (
int Idx : Mask) {
5273 unsigned SrcIdx =
Idx % Mask.size();
5275 if (Srcs[SrcIdx] == -1)
5278 else if (Srcs[SrcIdx] != Src)
5284 for (
int Lane : Srcs) {
5297 for (
unsigned I = 0;
I < Mask.size();
I++) {
5301 NewMask[
I] = Mask[
I] % Mask.size();
5315 MVT VT =
Op.getSimpleValueType();
5323 if (ElementSize > 32)
5346 MVT VT =
Op.getSimpleValueType();
5361 V2 = V2.isUndef() ? DAG.
getUNDEF(WidenVT)
5385 V.getOperand(0).getSimpleValueType().getVectorNumElements();
5386 V = V.getOperand(
Offset / OpElements);
5392 auto *Ld = cast<LoadSDNode>(V);
5402 SDValue Ops[] = {Ld->getChain(),
5416 MVT SplatVT = ContainerVT;
5419 if (SVT == MVT::bf16 ||
5420 (SVT == MVT::f16 && !Subtarget.hasStdExtZfh())) {
5429 V = DAG.
getLoad(SVT,
DL, Ld->getChain(), NewAddr,
5430 Ld->getPointerInfo().getWithOffset(
Offset),
5431 Ld->getOriginalAlign(),
5435 Ld->getPointerInfo().getWithOffset(
Offset), SVT,
5436 Ld->getOriginalAlign(),
5437 Ld->getMemOperand()->getFlags());
5449 assert(Lane < (
int)NumElts &&
"Unexpected lane!");
5452 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
5474 if (Subtarget.hasStdExtZvkb())
5485 LoV = LoSrc == 0 ? V1 : V2;
5489 HiV = HiSrc == 0 ? V1 : V2;
5495 unsigned InvRotate = NumElts - Rotation;
5505 Res =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, Res, LoV,
5523 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
5524 for (
unsigned Factor = 2; Factor <= MaxFactor; Factor <<= 1) {
5540 int EvenSrc, OddSrc;
5548 bool LaneIsUndef[2] = {
true,
true};
5549 for (
unsigned i = 0; i < Mask.size(); i++)
5550 LaneIsUndef[i % 2] &= (Mask[i] == -1);
5552 int Size = Mask.size();
5554 if (LaneIsUndef[0]) {
5557 assert(EvenSrc >= 0 &&
"Undef source?");
5558 EvenV = (EvenSrc /
Size) == 0 ? V1 : V2;
5563 if (LaneIsUndef[1]) {
5566 assert(OddSrc >= 0 &&
"Undef source?");
5567 OddV = (OddSrc /
Size) == 0 ? V1 : V2;
5577 assert(!V1.
isUndef() &&
"Unexpected shuffle canonicalization");
5597 for (
auto Idx : Mask) {
5613 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
5614 for (
unsigned Factor = 4; Factor <= MaxFactor; Factor <<= 1) {
5627 any_of(Mask, [&](
const auto &
Idx) {
return Idx > 255; })) {
5656 MVT IndexContainerVT =
5661 for (
int MaskIndex : Mask) {
5662 bool IsLHSIndex = MaskIndex < (int)NumElts && MaskIndex >= 0;
5671 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
5681 for (
int MaskIndex : Mask) {
5682 bool IsLHSOrUndefIndex = MaskIndex < (int)NumElts;
5683 ShuffleMaskLHS.
push_back(IsLHSOrUndefIndex && MaskIndex >= 0
5685 ShuffleMaskRHS.
push_back(IsLHSOrUndefIndex ? -1 : (MaskIndex - NumElts));
5716 for (
int MaskIndex : Mask) {
5717 bool SelectMaskVal = (MaskIndex < (int)NumElts) ^ !SwapOps;
5721 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
5753RISCVTargetLowering::lowerCTLZ_CTTZ_ZERO_UNDEF(
SDValue Op,
5755 MVT VT =
Op.getSimpleValueType();
5759 MVT ContainerVT = VT;
5762 if (
Op->isVPOpcode()) {
5763 Mask =
Op.getOperand(1);
5767 VL =
Op.getOperand(2);
5773 MVT FloatEltVT = (EltSize >= 32) ? MVT::f64 : MVT::f32;
5775 FloatEltVT = MVT::f32;
5782 "Expected legal float type!");
5789 }
else if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF) {
5792 Src = DAG.
getNode(ISD::VP_AND,
DL, VT, Src, Neg, Mask, VL);
5797 if (FloatVT.
bitsGT(VT)) {
5798 if (
Op->isVPOpcode())
5799 FloatVal = DAG.
getNode(ISD::VP_UINT_TO_FP,
DL, FloatVT, Src, Mask, VL);
5808 if (!
Op->isVPOpcode())
5812 MVT ContainerFloatVT =
5815 Src, Mask, RTZRM, VL);
5822 unsigned ShiftAmt = FloatEltVT == MVT::f64 ? 52 : 23;
5826 if (
Op->isVPOpcode()) {
5835 else if (IntVT.
bitsGT(VT))
5840 unsigned ExponentBias = FloatEltVT == MVT::f64 ? 1023 : 127;
5845 if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF)
5846 return DAG.
getNode(ISD::VP_SUB,
DL, VT, Exp,
5851 unsigned Adjust = ExponentBias + (EltSize - 1);
5853 if (
Op->isVPOpcode())
5863 else if (
Op.getOpcode() == ISD::VP_CTLZ)
5864 Res = DAG.
getNode(ISD::VP_UMIN,
DL, VT, Res,
5874 MVT SrcVT =
Source.getSimpleValueType();
5883 SrcVT = ContainerVT;
5896 if (
Op->getOpcode() == ISD::VP_CTTZ_ELTS_ZERO_UNDEF)
5913 auto *
Load = cast<LoadSDNode>(
Op);
5914 assert(Load &&
Load->getMemoryVT().isVector() &&
"Expected vector load");
5917 Load->getMemoryVT(),
5918 *
Load->getMemOperand()))
5922 MVT VT =
Op.getSimpleValueType();
5924 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
5925 "Unexpected unaligned RVV load type");
5929 "Expecting equally-sized RVV vector types to be legal");
5931 Load->getPointerInfo(),
Load->getOriginalAlign(),
5932 Load->getMemOperand()->getFlags());
5942 auto *
Store = cast<StoreSDNode>(
Op);
5943 assert(Store &&
Store->getValue().getValueType().isVector() &&
5944 "Expected vector store");
5947 Store->getMemoryVT(),
5948 *
Store->getMemOperand()))
5955 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
5956 "Unexpected unaligned RVV store type");
5960 "Expecting equally-sized RVV vector types to be legal");
5961 StoredVal = DAG.
getBitcast(NewVT, StoredVal);
5963 Store->getPointerInfo(),
Store->getOriginalAlign(),
5964 Store->getMemOperand()->getFlags());
5969 assert(
Op.getValueType() == MVT::i64 &&
"Unexpected VT");
5971 int64_t Imm = cast<ConstantSDNode>(
Op)->getSExtValue();
5998 unsigned ShiftAmt, AddOpc;
6009 MVT VT =
Op.getSimpleValueType();
6010 const APFloat &
Imm = cast<ConstantFPSDNode>(
Op)->getValueAPF();
6013 bool Negate =
false;
6017 if (Index < 0 &&
Imm.isNegative()) {
6045 if (Subtarget.hasStdExtZtso()) {
6069 MVT VT =
Op.getSimpleValueType();
6071 unsigned Check =
Op.getConstantOperandVal(1);
6072 unsigned TDCMask = 0;
6100 MVT VT0 =
Op.getOperand(0).getSimpleValueType();
6105 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6107 VL =
Op.getOperand(3);
6110 VL,
Op->getFlags());
6125 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6127 MVT MaskContainerVT =
6130 VL =
Op.getOperand(3);
6135 Mask, VL,
Op->getFlags());
6138 DAG.
getUNDEF(ContainerDstVT), TDCMaskV, VL);
6143 DAG.
getUNDEF(ContainerVT), Mask, VL});
6147 TDCMaskV, DAG.
getUNDEF(ContainerDstVT), Mask, VL);
6151 DAG.
getUNDEF(ContainerDstVT), SplatZero, VL);
6155 DAG.
getUNDEF(ContainerVT), Mask, VL});
6171 MVT VT =
Op.getSimpleValueType();
6198 return DAG.
getNode(Opc,
DL, VT, NewX, NewY);
6205 MVT ContainerVT = VT;
6213 if (
Op->isVPOpcode()) {
6214 Mask =
Op.getOperand(2);
6218 VL =
Op.getOperand(3);
6226 {X, X, DAG.getCondCode(ISD::SETOEQ),
6227 DAG.getUNDEF(ContainerVT), Mask, VL});
6235 {Y, Y, DAG.getCondCode(ISD::SETOEQ),
6236 DAG.getUNDEF(ContainerVT), Mask, VL});
6246 DAG.
getUNDEF(ContainerVT), Mask, VL);
6256 "Wrong opcode for lowering FABS or FNEG.");
6259 MVT VT =
Op.getSimpleValueType();
6260 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
6267 Mask = Mask.sext(Subtarget.
getXLen());
6280 MVT VT =
Op.getSimpleValueType();
6281 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
6291 if (SignSize == Subtarget.
getXLen()) {
6293 }
else if (SignSize == 16) {
6295 }
else if (SignSize == 32) {
6297 }
else if (SignSize == 64) {
6298 assert(XLenVT == MVT::i32 &&
"Unexpected type");
6308 if (ShiftAmount > 0) {
6311 }
else if (ShiftAmount < 0) {
6337#define OP_CASE(NODE) \
6339 return RISCVISD::NODE##_VL;
6340#define VP_CASE(NODE) \
6341 case ISD::VP_##NODE: \
6342 return RISCVISD::NODE##_VL;
6344 switch (
Op.getOpcode()) {
6422 case ISD::VP_CTLZ_ZERO_UNDEF:
6425 case ISD::VP_CTTZ_ZERO_UNDEF:
6434 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
6439 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
6444 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
6447 case ISD::VP_SELECT:
6456 case ISD::VP_SIGN_EXTEND:
6458 case ISD::VP_ZERO_EXTEND:
6460 case ISD::VP_FP_TO_SINT:
6462 case ISD::VP_FP_TO_UINT:
6465 case ISD::VP_FMINNUM:
6468 case ISD::VP_FMAXNUM:
6473 case ISD::VP_LLRINT:
6485 "not a RISC-V target specific op");
6489 "adding target specific op should update this function");
6509 "not a RISC-V target specific op");
6513 "adding target specific op should update this function");
6526 if (
Op.getValueType() == MVT::nxv32f16 &&
6530 if (
Op.getValueType() == MVT::nxv32bf16)
6543 if (!
Op.getOperand(j).getValueType().isVector()) {
6544 LoOperands[j] =
Op.getOperand(j);
6545 HiOperands[j] =
Op.getOperand(j);
6548 std::tie(LoOperands[j], HiOperands[j]) =
6553 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
6555 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
6570 std::tie(LoOperands[j], HiOperands[j]) =
6574 if (!
Op.getOperand(j).getValueType().isVector()) {
6575 LoOperands[j] =
Op.getOperand(j);
6576 HiOperands[j] =
Op.getOperand(j);
6579 std::tie(LoOperands[j], HiOperands[j]) =
6584 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
6586 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
6596 auto [EVLLo, EVLHi] =
6597 DAG.
SplitEVL(
Op.getOperand(3),
Op.getOperand(1).getValueType(),
DL);
6601 {Op.getOperand(0), Lo, MaskLo, EVLLo},
Op->getFlags());
6603 {ResLo, Hi, MaskHi, EVLHi},
Op->getFlags());
6621 if (!
Op.getOperand(j).getValueType().isVector()) {
6622 LoOperands[j] =
Op.getOperand(j);
6623 HiOperands[j] =
Op.getOperand(j);
6626 std::tie(LoOperands[j], HiOperands[j]) =
6631 DAG.
getNode(
Op.getOpcode(),
DL, LoVTs, LoOperands,
Op->getFlags());
6634 DAG.
getNode(
Op.getOpcode(),
DL, HiVTs, HiOperands,
Op->getFlags());
6643 switch (
Op.getOpcode()) {
6649 return lowerGlobalAddress(
Op, DAG);
6651 return lowerBlockAddress(
Op, DAG);
6653 return lowerConstantPool(
Op, DAG);
6655 return lowerJumpTable(
Op, DAG);
6657 return lowerGlobalTLSAddress(
Op, DAG);
6661 return lowerConstantFP(
Op, DAG);
6663 return lowerSELECT(
Op, DAG);
6665 return lowerBRCOND(
Op, DAG);
6667 return lowerVASTART(
Op, DAG);
6669 return lowerFRAMEADDR(
Op, DAG);
6671 return lowerRETURNADDR(
Op, DAG);
6673 return lowerShiftLeftParts(
Op, DAG);
6675 return lowerShiftRightParts(
Op, DAG,
true);
6677 return lowerShiftRightParts(
Op, DAG,
false);
6680 if (
Op.getValueType().isFixedLengthVector()) {
6681 assert(Subtarget.hasStdExtZvkb());
6682 return lowerToScalableOp(
Op, DAG);
6684 assert(Subtarget.hasVendorXTHeadBb() &&
6685 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
6686 "Unexpected custom legalization");
6688 if (!isa<ConstantSDNode>(
Op.getOperand(1)))
6693 EVT VT =
Op.getValueType();
6697 if (Op0VT == MVT::i16 &&
6699 (VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
6703 if (VT == MVT::f32 && Op0VT == MVT::i32 && Subtarget.
is64Bit() &&
6708 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.
is64Bit() &&
6724 "Unexpected types");
6758 return LowerINTRINSIC_WO_CHAIN(
Op, DAG);
6760 return LowerINTRINSIC_W_CHAIN(
Op, DAG);
6762 return LowerINTRINSIC_VOID(
Op, DAG);
6764 return LowerIS_FPCLASS(
Op, DAG);
6766 MVT VT =
Op.getSimpleValueType();
6768 assert(Subtarget.hasStdExtZvbb());
6769 return lowerToScalableOp(
Op, DAG);
6772 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected custom legalization");
6782 if (!
Op.getSimpleValueType().isVector())
6784 return lowerVectorTruncLike(
Op, DAG);
6787 if (
Op.getOperand(0).getValueType().isVector() &&
6788 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
6789 return lowerVectorMaskExt(
Op, DAG, 1);
6792 if (
Op.getOperand(0).getValueType().isVector() &&
6793 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
6794 return lowerVectorMaskExt(
Op, DAG, -1);
6797 return lowerSPLAT_VECTOR_PARTS(
Op, DAG);
6799 return lowerINSERT_VECTOR_ELT(
Op, DAG);
6801 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
6803 MVT VT =
Op.getSimpleValueType();
6811 MVT ContainerVT = VT;
6819 DAG.
getUNDEF(ContainerVT), Scalar, VL);
6823 DAG.
getUNDEF(ContainerVT), Scalar, VL);
6831 MVT VT =
Op.getSimpleValueType();
6851 }
else if ((Val % 8) == 0) {
6867 if (
Op.getValueType() == MVT::f16 && Subtarget.
is64Bit() &&
6868 Op.getOperand(1).getValueType() == MVT::i32) {
6885 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
6888 return lowerStrictFPExtendOrRoundLike(
Op, DAG);
6891 if (
Op.getValueType().isVector() &&
6892 ((
Op.getValueType().getScalarType() == MVT::f16 &&
6895 Op.getValueType().getScalarType() == MVT::bf16)) {
6911 Op1.getValueType().isVector() &&
6912 ((Op1.getValueType().getScalarType() == MVT::f16 &&
6915 Op1.getValueType().getScalarType() == MVT::bf16)) {
6921 Op1.getValueType().getVectorElementCount());
6924 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), WidenVec);
6934 MVT VT =
Op.getSimpleValueType();
6937 bool IsStrict =
Op->isStrictFPOpcode();
6938 SDValue Src =
Op.getOperand(0 + IsStrict);
6939 MVT SrcVT = Src.getSimpleValueType();
6950 "Unexpected vector element types");
6954 if (EltSize > (2 * SrcEltSize)) {
6966 Op.getOperand(0), Ext);
6970 assert(SrcEltVT == MVT::f16 &&
"Unexpected FP_TO_[US]INT lowering");
6975 auto [FExt, Chain] =
6977 return DAG.
getNode(
Op.getOpcode(),
DL,
Op->getVTList(), Chain, FExt);
6984 if (SrcEltSize > (2 * EltSize)) {
6987 assert(EltVT == MVT::f16 &&
"Unexpected [US]_TO_FP lowering");
6992 Op.getOperand(0), Src);
7007 Op.getOperand(0), Src);
7021 unsigned RVVOpc = 0;
7022 switch (
Op.getOpcode()) {
7054 "Expected same element count");
7061 Op.getOperand(0), Src, Mask, VL);
7065 Src = DAG.
getNode(RVVOpc,
DL, ContainerVT, Src, Mask, VL);
7080 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
7087 MVT VT =
Op.getSimpleValueType();
7107 bool IsStrict =
Op->isStrictFPOpcode();
7108 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7112 std::tie(Res, Chain) =
7113 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
7128 bool IsStrict =
Op->isStrictFPOpcode();
7129 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7135 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
7136 CallOptions,
DL, Chain);
7153 if (
Op.getValueType().isVector())
7158 assert(
Op.getOperand(0).getValueType() == MVT::f16 &&
7159 "Unexpected custom legalisation");
7162 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), Ext);
7168 assert(
Op.getOperand(1).getValueType() == MVT::f16 &&
7169 "Unexpected custom legalisation");
7172 {
Op.getOperand(0),
Op.getOperand(1)});
7173 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
7174 {Ext.getValue(1), Ext.getValue(0)});
7181 return lowerVECREDUCE(
Op, DAG);
7185 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7186 return lowerVectorMaskVecReduction(
Op, DAG,
false);
7187 return lowerVECREDUCE(
Op, DAG);
7194 return lowerFPVECREDUCE(
Op, DAG);
7195 case ISD::VP_REDUCE_ADD:
7196 case ISD::VP_REDUCE_UMAX:
7197 case ISD::VP_REDUCE_SMAX:
7198 case ISD::VP_REDUCE_UMIN:
7199 case ISD::VP_REDUCE_SMIN:
7200 case ISD::VP_REDUCE_FADD:
7201 case ISD::VP_REDUCE_SEQ_FADD:
7202 case ISD::VP_REDUCE_FMIN:
7203 case ISD::VP_REDUCE_FMAX:
7204 case ISD::VP_REDUCE_FMINIMUM:
7205 case ISD::VP_REDUCE_FMAXIMUM:
7208 return lowerVPREDUCE(
Op, DAG);
7209 case ISD::VP_REDUCE_AND:
7210 case ISD::VP_REDUCE_OR:
7211 case ISD::VP_REDUCE_XOR:
7212 if (
Op.getOperand(1).getValueType().getVectorElementType() == MVT::i1)
7213 return lowerVectorMaskVecReduction(
Op, DAG,
true);
7214 return lowerVPREDUCE(
Op, DAG);
7215 case ISD::VP_CTTZ_ELTS:
7216 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
7217 return lowerVPCttzElements(
Op, DAG);
7221 DAG.
getUNDEF(ContainerVT), DAG, Subtarget);
7224 return lowerINSERT_SUBVECTOR(
Op, DAG);
7226 return lowerEXTRACT_SUBVECTOR(
Op, DAG);
7228 return lowerVECTOR_DEINTERLEAVE(
Op, DAG);
7230 return lowerVECTOR_INTERLEAVE(
Op, DAG);
7232 return lowerSTEP_VECTOR(
Op, DAG);
7234 return lowerVECTOR_REVERSE(
Op, DAG);
7236 return lowerVECTOR_SPLICE(
Op, DAG);
7240 MVT VT =
Op.getSimpleValueType();
7242 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
7243 EltVT == MVT::bf16) {
7246 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
7247 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
7257 if (EltVT == MVT::i1)
7258 return lowerVectorMaskSplat(
Op, DAG);
7267 MVT VT =
Op.getSimpleValueType();
7268 MVT ContainerVT = VT;
7286 Op->ops().take_front(HalfNumOps));
7288 Op->ops().drop_front(HalfNumOps));
7292 unsigned NumOpElts =
7293 Op.getOperand(0).getSimpleValueType().getVectorMinNumElements();
7296 SDValue SubVec = OpIdx.value();
7307 auto *Load = cast<LoadSDNode>(
Op);
7308 EVT VecTy = Load->getMemoryVT();
7315 unsigned NumElts = Sz / (NF * 8);
7316 int Log2LMUL =
Log2_64(NumElts) - 3;
7319 Flag.setNoUnsignedWrap(
true);
7321 SDValue BasePtr = Load->getBasePtr();
7329 for (
unsigned i = 0; i < NF; ++i) {
7342 if (
auto V = expandUnalignedRVVLoad(
Op, DAG))
7344 if (
Op.getValueType().isFixedLengthVector())
7345 return lowerFixedLengthVectorLoadToRVV(
Op, DAG);
7349 auto *Store = cast<StoreSDNode>(
Op);
7350 SDValue StoredVal = Store->getValue();
7358 unsigned NumElts = Sz / (NF * 8);
7359 int Log2LMUL =
Log2_64(NumElts) - 3;
7362 Flag.setNoUnsignedWrap(
true);
7364 SDValue Chain = Store->getChain();
7365 SDValue BasePtr = Store->getBasePtr();
7372 for (
unsigned i = 0; i < NF; ++i) {
7376 Ret = DAG.
getStore(Chain,
DL, Extract, BasePtr,
7378 Store->getOriginalAlign(),
7379 Store->getMemOperand()->getFlags());
7380 Chain = Ret.getValue(0);
7386 if (
auto V = expandUnalignedRVVStore(
Op, DAG))
7388 if (
Op.getOperand(1).getValueType().isFixedLengthVector())
7389 return lowerFixedLengthVectorStoreToRVV(
Op, DAG);
7394 return lowerMaskedLoad(
Op, DAG);
7397 return lowerMaskedStore(
Op, DAG);
7399 return lowerVectorCompress(
Op, DAG);
7408 EVT VT =
Op.getValueType();
7419 MVT OpVT =
Op.getOperand(0).getSimpleValueType();
7421 MVT VT =
Op.getSimpleValueType();
7426 "Unexpected CondCode");
7434 if (isa<ConstantSDNode>(
RHS)) {
7435 int64_t Imm = cast<ConstantSDNode>(
RHS)->getSExtValue();
7436 if (Imm != 0 && isInt<12>((
uint64_t)Imm + 1)) {
7458 return lowerFixedLengthVectorSetccToRVV(
Op, DAG);
7474 return lowerToScalableOp(
Op, DAG);
7478 if (
Op.getSimpleValueType().isFixedLengthVector())
7479 return lowerToScalableOp(
Op, DAG);
7481 assert(
Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.
is64Bit() &&
7482 "Unexpected custom legalisation");
7486 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
7512 return lowerToScalableOp(
Op, DAG);
7516 EVT VT =
Op->getValueType(0);
7531 return lowerABS(
Op, DAG);
7536 if (Subtarget.hasStdExtZvbb())
7537 return lowerToScalableOp(
Op, DAG);
7539 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
7541 return lowerFixedLengthVectorSelectToRVV(
Op, DAG);
7543 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
7547 return lowerFixedLengthVectorFCOPYSIGNToRVV(
Op, DAG);
7556 return lowerToScalableOp(
Op, DAG);
7559 return lowerVectorStrictFSetcc(
Op, DAG);
7569 case ISD::VP_GATHER:
7570 return lowerMaskedGather(
Op, DAG);
7572 case ISD::VP_SCATTER:
7573 return lowerMaskedScatter(
Op, DAG);
7575 return lowerGET_ROUNDING(
Op, DAG);
7577 return lowerSET_ROUNDING(
Op, DAG);
7579 return lowerEH_DWARF_CFA(
Op, DAG);
7581 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7582 return lowerVPMergeMask(
Op, DAG);
7584 case ISD::VP_SELECT:
7592 case ISD::VP_UADDSAT:
7593 case ISD::VP_USUBSAT:
7594 case ISD::VP_SADDSAT:
7595 case ISD::VP_SSUBSAT:
7597 case ISD::VP_LLRINT:
7598 return lowerVPOp(
Op, DAG);
7602 return lowerLogicVPOp(
Op, DAG);
7611 case ISD::VP_FMINNUM:
7612 case ISD::VP_FMAXNUM:
7613 case ISD::VP_FCOPYSIGN:
7620 return lowerVPOp(
Op, DAG);
7621 case ISD::VP_IS_FPCLASS:
7622 return LowerIS_FPCLASS(
Op, DAG);
7623 case ISD::VP_SIGN_EXTEND:
7624 case ISD::VP_ZERO_EXTEND:
7625 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
7626 return lowerVPExtMaskOp(
Op, DAG);
7627 return lowerVPOp(
Op, DAG);
7628 case ISD::VP_TRUNCATE:
7629 return lowerVectorTruncLike(
Op, DAG);
7630 case ISD::VP_FP_EXTEND:
7631 case ISD::VP_FP_ROUND:
7632 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
7633 case ISD::VP_SINT_TO_FP:
7634 case ISD::VP_UINT_TO_FP:
7635 if (
Op.getValueType().isVector() &&
7636 ((
Op.getValueType().getScalarType() == MVT::f16 &&
7639 Op.getValueType().getScalarType() == MVT::bf16)) {
7652 case ISD::VP_FP_TO_SINT:
7653 case ISD::VP_FP_TO_UINT:
7655 Op1.getValueType().isVector() &&
7656 ((Op1.getValueType().getScalarType() == MVT::f16 &&
7659 Op1.getValueType().getScalarType() == MVT::bf16)) {
7665 Op1.getValueType().getVectorElementCount());
7669 {WidenVec, Op.getOperand(1), Op.getOperand(2)});
7671 return lowerVPFPIntConvOp(
Op, DAG);
7675 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
7676 return lowerVPSetCCMaskOp(
Op, DAG);
7682 case ISD::VP_BITREVERSE:
7684 return lowerVPOp(
Op, DAG);
7686 case ISD::VP_CTLZ_ZERO_UNDEF:
7687 if (Subtarget.hasStdExtZvbb())
7688 return lowerVPOp(
Op, DAG);
7689 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
7691 case ISD::VP_CTTZ_ZERO_UNDEF:
7692 if (Subtarget.hasStdExtZvbb())
7693 return lowerVPOp(
Op, DAG);
7694 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
7696 return lowerVPOp(
Op, DAG);
7697 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
7698 return lowerVPStridedLoad(
Op, DAG);
7699 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
7700 return lowerVPStridedStore(
Op, DAG);
7702 case ISD::VP_FFLOOR:
7704 case ISD::VP_FNEARBYINT:
7705 case ISD::VP_FROUND:
7706 case ISD::VP_FROUNDEVEN:
7707 case ISD::VP_FROUNDTOZERO:
7711 case ISD::VP_FMAXIMUM:
7712 case ISD::VP_FMINIMUM:
7716 case ISD::EXPERIMENTAL_VP_SPLICE:
7717 return lowerVPSpliceExperimental(
Op, DAG);
7718 case ISD::EXPERIMENTAL_VP_REVERSE:
7719 return lowerVPReverseExperimental(
Op, DAG);
7720 case ISD::EXPERIMENTAL_VP_SPLAT:
7721 return lowerVPSplatExperimental(
Op, DAG);
7724 "llvm.clear_cache only needs custom lower on Linux targets");
7727 return emitFlushICache(DAG,
Op.getOperand(0),
Op.getOperand(1),
7728 Op.getOperand(2), Flags,
DL);
7731 return lowerINIT_TRAMPOLINE(
Op, DAG);
7733 return lowerADJUST_TRAMPOLINE(
Op, DAG);
7740 MakeLibCallOptions CallOptions;
7741 std::pair<SDValue, SDValue> CallResult =
7742 makeLibCall(DAG, RTLIB::RISCV_FLUSH_ICACHE, MVT::isVoid,
7743 {Start,
End, Flags}, CallOptions,
DL, InChain);
7746 return CallResult.second;
7759 std::unique_ptr<MCCodeEmitter> CodeEmitter(
7766 const Value *TrmpAddr = cast<SrcValueSDNode>(
Op.getOperand(4))->getValue();
7778 constexpr unsigned StaticChainOffset = 16;
7779 constexpr unsigned FunctionAddressOffset = 24;
7783 auto GetEncoding = [&](
const MCInst &MC) {
7786 CodeEmitter->encodeInstruction(MC, CB, Fixups, *STI);
7796 GetEncoding(
MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X7).addImm(0)),
7801 MCInstBuilder(RISCV::LD).addReg(RISCV::X5).addReg(RISCV::X7).addImm(
7802 FunctionAddressOffset)),
7806 MCInstBuilder(RISCV::LD).addReg(RISCV::X7).addReg(RISCV::X7).addImm(
7807 StaticChainOffset)),
7826 SDValue FunctionAddress =
Op.getOperand(2);
7830 struct OffsetValuePair {
7834 } OffsetValues[] = {
7835 {StaticChainOffset, StaticChain},
7836 {FunctionAddressOffset, FunctionAddress},
7841 DAG.
getConstant(OffsetValue.Offset, dl, MVT::i64));
7842 OffsetValue.Addr =
Addr;
7843 OutChains[
Idx + 4] =
7852 SDValue EndOfTrmp = OffsetValues[0].Addr;
7866 return Op.getOperand(0);
7883 N->getOffset(), Flags);
7912template <
class NodeTy>
7914 bool IsLocal,
bool IsExternWeak)
const {
7924 if (IsLocal && !Subtarget.allowTaggedGlobals())
7994 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
8003 return getAddr(
N, DAG);
8010 return getAddr(
N, DAG);
8017 return getAddr(
N, DAG);
8022 bool UseGOT)
const {
8086 Args.push_back(Entry);
8119 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
8133 Addr = getStaticTLSAddr(
N, DAG,
false);
8136 Addr = getStaticTLSAddr(
N, DAG,
true);
8141 : getDynamicTLSAddr(
N, DAG);
8158 if (
LHS == LHS2 &&
RHS == RHS2) {
8163 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
8171 return std::nullopt;
8179 MVT VT =
N->getSimpleValueType(0);
8209 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV)) {
8212 if (~TrueVal == FalseVal) {
8252 if (Subtarget.hasShortForwardBranchOpt())
8255 unsigned SelOpNo = 0;
8265 unsigned ConstSelOpNo = 1;
8266 unsigned OtherSelOpNo = 2;
8267 if (!dyn_cast<ConstantSDNode>(Sel->
getOperand(ConstSelOpNo))) {
8272 ConstantSDNode *ConstSelOpNode = dyn_cast<ConstantSDNode>(ConstSelOp);
8273 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
8277 ConstantSDNode *ConstBinOpNode = dyn_cast<ConstantSDNode>(ConstBinOp);
8278 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
8284 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
8286 std::swap(NewConstOps[0], NewConstOps[1]);
8298 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
8300 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
8303 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
8304 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
8313 MVT VT =
Op.getSimpleValueType();
8327 if ((Subtarget.hasStdExtZicond() || Subtarget.hasVendorXVentanaCondOps()) &&
8355 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV)) {
8359 TrueVal, Subtarget.
getXLen(), Subtarget,
true);
8361 FalseVal, Subtarget.
getXLen(), Subtarget,
true);
8362 bool IsCZERO_NEZ = TrueValCost <= FalseValCost;
8364 IsCZERO_NEZ ? FalseVal - TrueVal : TrueVal - FalseVal,
DL, VT);
8369 DL, VT, LHSVal, CondV);
8385 if (
Op.hasOneUse()) {
8386 unsigned UseOpc =
Op->user_begin()->getOpcode();
8395 return lowerSELECT(NewSel, DAG);
8424 SDValue Ops[] = {CondV,
Zero, SetNE, TrueV, FalseV};
8445 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV) &&
8449 if (TrueVal - 1 == FalseVal)
8451 if (TrueVal + 1 == FalseVal)
8458 RHS == TrueV && LHS == FalseV) {
8475 if (isa<ConstantSDNode>(TrueV) && !isa<ConstantSDNode>(FalseV)) {
8501 LHS, RHS, TargetCC,
Op.getOperand(2));
8519 const Value *SV = cast<SrcValueSDNode>(
Op.getOperand(2))->getValue();
8531 int XLenInBytes = Subtarget.
getXLen() / 8;
8533 EVT VT =
Op.getValueType();
8536 unsigned Depth =
Op.getConstantOperandVal(0);
8538 int Offset = -(XLenInBytes * 2);
8555 int XLenInBytes = Subtarget.
getXLen() / 8;
8560 EVT VT =
Op.getValueType();
8562 unsigned Depth =
Op.getConstantOperandVal(0);
8564 int Off = -XLenInBytes;
8565 SDValue FrameAddr = lowerFRAMEADDR(
Op, DAG);
8584 EVT VT =
Lo.getValueType();
8623 EVT VT =
Lo.getValueType();
8674 MVT VT =
Op.getSimpleValueType();
8700 MVT VecVT =
Op.getSimpleValueType();
8702 "Unexpected SPLAT_VECTOR_PARTS lowering");
8708 MVT ContainerVT = VecVT;
8728 int64_t ExtTrueVal)
const {
8730 MVT VecVT =
Op.getSimpleValueType();
8733 assert(Src.getValueType().isVector() &&
8734 Src.getValueType().getVectorElementType() == MVT::i1);
8755 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
8757 DAG.
getUNDEF(ContainerVT), SplatTrueVal, VL);
8760 SplatZero, DAG.
getUNDEF(ContainerVT), VL);
8765SDValue RISCVTargetLowering::lowerFixedLengthVectorExtendToRVV(
8767 MVT ExtVT =
Op.getSimpleValueType();
8771 MVT VT =
Op.getOperand(0).getSimpleValueType();
8797 bool IsVPTrunc =
Op.getOpcode() == ISD::VP_TRUNCATE;
8799 EVT MaskVT =
Op.getValueType();
8802 "Unexpected type for vector mask lowering");
8804 MVT VecVT = Src.getSimpleValueType();
8808 VL =
Op.getOperand(2);
8811 MVT ContainerVT = VecVT;
8817 MVT MaskContainerVT =
8824 std::tie(Mask, VL) =
8832 DAG.
getUNDEF(ContainerVT), SplatOne, VL);
8834 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
8838 DAG.
getUNDEF(ContainerVT), Mask, VL);
8841 DAG.
getUNDEF(MaskContainerVT), Mask, VL});
8849 unsigned Opc =
Op.getOpcode();
8850 bool IsVPTrunc = Opc == ISD::VP_TRUNCATE;
8853 MVT VT =
Op.getSimpleValueType();
8855 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
8859 return lowerVectorMaskTruncLike(
Op, DAG);
8867 MVT SrcVT = Src.getSimpleValueType();
8872 "Unexpected vector truncate lowering");
8874 MVT ContainerVT = SrcVT;
8878 VL =
Op.getOperand(2);
8891 std::tie(Mask, VL) =
8907 }
while (SrcEltVT != DstEltVT);
8916RISCVTargetLowering::lowerStrictFPExtendOrRoundLike(
SDValue Op,
8921 MVT VT =
Op.getSimpleValueType();
8922 MVT SrcVT = Src.getSimpleValueType();
8923 MVT ContainerVT = VT;
8946 Chain, Src, Mask, VL);
8947 Chain = Src.getValue(1);
8954 Chain, Src, Mask, VL);
8965RISCVTargetLowering::lowerVectorFPExtendOrRoundLike(
SDValue Op,
8968 Op.getOpcode() == ISD::VP_FP_ROUND ||
Op.getOpcode() == ISD::VP_FP_EXTEND;
8975 MVT VT =
Op.getSimpleValueType();
8977 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
8980 MVT SrcVT = Src.getSimpleValueType();
8982 bool IsDirectExtend =
8990 bool IsDirectConv = IsDirectExtend || IsDirectTrunc;
8993 MVT ContainerVT = VT;
8997 VL =
Op.getOperand(2);
9011 std::tie(Mask, VL) =
9017 Src = DAG.
getNode(ConvOpc,
DL, ContainerVT, Src, Mask, VL);
9023 unsigned InterConvOpc =
9028 DAG.
getNode(InterConvOpc,
DL, InterVT, Src, Mask, VL);
9030 DAG.
getNode(ConvOpc,
DL, ContainerVT, IntermediateConv, Mask, VL);
9041static std::optional<MVT>
9047 const unsigned MinVLMAX = VectorBitsMin / EltSize;
9049 if (MaxIdx < MinVLMAX)
9051 else if (MaxIdx < MinVLMAX * 2)
9053 else if (MaxIdx < MinVLMAX * 4)
9058 return std::nullopt;
9071 MVT VecVT =
Op.getSimpleValueType();
9088 ValVT == MVT::bf16) {
9097 MVT ContainerVT = VecVT;
9106 MVT OrigContainerVT = ContainerVT;
9109 if (
auto *IdxC = dyn_cast<ConstantSDNode>(
Idx)) {
9110 const unsigned OrigIdx = IdxC->getZExtValue();
9113 DL, DAG, Subtarget)) {
9114 ContainerVT = *ShrunkVT;
9123 VLEN && ContainerVT.
bitsGT(M1VT)) {
9126 unsigned RemIdx = OrigIdx % ElemsPerVReg;
9127 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
9128 unsigned ExtractIdx =
9145 if (!IsLegalInsert && isa<ConstantSDNode>(Val)) {
9146 const auto *CVal = cast<ConstantSDNode>(Val);
9147 if (isInt<32>(CVal->getSExtValue())) {
9148 IsLegalInsert =
true;
9157 if (IsLegalInsert) {
9163 Vec = DAG.
getNode(Opc,
DL, ContainerVT, Vec, Val, VL);
9179 std::tie(ValLo, ValHi) = DAG.
SplitScalar(Val,
DL, MVT::i32, MVT::i32);
9180 MVT I32ContainerVT =
9191 Vec, Vec, ValLo, I32Mask, InsertI64VL);
9196 Tail, ValInVec, ValHi, I32Mask, InsertI64VL);
9198 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
9203 ValInVec, AlignedIdx);
9213 DAG.
getUNDEF(I32ContainerVT), ValLo,
9214 I32Mask, InsertI64VL);
9216 DAG.
getUNDEF(I32ContainerVT), ValInVec, ValHi,
9217 I32Mask, InsertI64VL);
9219 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
9232 Idx, Mask, InsertVL, Policy);
9236 Slideup, AlignedIdx);
9251 EVT EltVT =
Op.getValueType();
9258 MVT ContainerVT = VecVT;
9274 unsigned WidenVecLen;
9277 unsigned MaxEEW = Subtarget.
getELen();
9282 "the number of elements should be power of 2");
9286 ExtractBitIdx =
Idx;
9288 WideEltVT = LargestEltVT;
9291 ExtractElementIdx = DAG.
getNode(
9302 Vec, ExtractElementIdx);
9318 EltVT == MVT::bf16) {
9328 MVT ContainerVT = VecVT;
9339 if (
auto *IdxC = dyn_cast<ConstantSDNode>(
Idx);
9340 IdxC && VLen && VecVT.
getSizeInBits().getKnownMinValue() > *VLen) {
9342 unsigned OrigIdx = IdxC->getZExtValue();
9345 unsigned RemIdx = OrigIdx % ElemsPerVReg;
9346 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
9347 unsigned ExtractIdx =
9357 std::optional<uint64_t> MaxIdx;
9360 if (
auto *IdxC = dyn_cast<ConstantSDNode>(
Idx))
9361 MaxIdx = IdxC->getZExtValue();
9363 if (
auto SmallerVT =
9365 ContainerVT = *SmallerVT;
9412 "Unexpected opcode");
9419 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
9424 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
9425 if (!
II || !
II->hasScalarOperand())
9428 unsigned SplatOp =
II->ScalarOperand + 1 + HasChain;
9441 if (OpVT.
bitsLT(XLenVT)) {
9448 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
9458 assert(
II->ScalarOperand > 0 &&
"Unexpected splat operand!");
9459 MVT VT =
Op.getOperand(SplatOp - 1).getSimpleValueType();
9462 assert(XLenVT == MVT::i32 && OpVT == MVT::i64 &&
9473 case Intrinsic::riscv_vslide1up:
9474 case Intrinsic::riscv_vslide1down:
9475 case Intrinsic::riscv_vslide1up_mask:
9476 case Intrinsic::riscv_vslide1down_mask: {
9479 bool IsMasked = NumOps == 7;
9485 std::tie(ScalarLo, ScalarHi) =
9493 if (isa<ConstantSDNode>(AVL)) {
9494 const auto [MinVLMAX, MaxVLMAX] =
9498 if (AVLInt <= MinVLMAX) {
9500 }
else if (AVLInt >= 2 * MaxVLMAX) {
9534 if (IntNo == Intrinsic::riscv_vslide1up ||
9535 IntNo == Intrinsic::riscv_vslide1up_mask) {
9537 ScalarHi, I32Mask, I32VL);
9539 ScalarLo, I32Mask, I32VL);
9542 ScalarLo, I32Mask, I32VL);
9544 ScalarHi, I32Mask, I32VL);
9593 const unsigned ElementWidth = 8;
9598 [[maybe_unused]]
unsigned MinVF =
9601 [[maybe_unused]]
unsigned VF =
N->getConstantOperandVal(2);
9605 bool Fractional = VF < LMul1VF;
9606 unsigned LMulVal = Fractional ? LMul1VF / VF : VF / LMul1VF;
9627 MVT ContainerVT = OpVT;
9654 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
9658 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
9659 if (!
II || !
II->hasScalarOperand())
9662 unsigned SplatOp =
II->ScalarOperand + 1;
9675 if (OpVT.
bitsLT(XLenVT)) {
9678 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
9689 EVT ValType = V.getValueType();
9690 if (ValType.isVector() && ValType.isFloatingPoint()) {
9693 ValType.getVectorElementCount());
9696 if (ValType.isFixedLengthVector()) {
9698 DAG, V.getSimpleValueType(), Subtarget);
9714 unsigned IntNo =
Op.getConstantOperandVal(0);
9721 case Intrinsic::riscv_tuple_insert: {
9729 case Intrinsic::riscv_tuple_extract: {
9736 case Intrinsic::thread_pointer: {
9740 case Intrinsic::riscv_orc_b:
9741 case Intrinsic::riscv_brev8:
9742 case Intrinsic::riscv_sha256sig0:
9743 case Intrinsic::riscv_sha256sig1:
9744 case Intrinsic::riscv_sha256sum0:
9745 case Intrinsic::riscv_sha256sum1:
9746 case Intrinsic::riscv_sm3p0:
9747 case Intrinsic::riscv_sm3p1: {
9760 return DAG.
getNode(Opc,
DL, XLenVT,
Op.getOperand(1));
9762 case Intrinsic::riscv_sm4ks:
9763 case Intrinsic::riscv_sm4ed: {
9767 return DAG.
getNode(Opc,
DL, XLenVT,
Op.getOperand(1),
Op.getOperand(2),
9770 case Intrinsic::riscv_zip:
9771 case Intrinsic::riscv_unzip: {
9774 return DAG.
getNode(Opc,
DL, XLenVT,
Op.getOperand(1));
9776 case Intrinsic::riscv_mopr:
9780 case Intrinsic::riscv_moprr: {
9782 Op.getOperand(2),
Op.getOperand(3));
9784 case Intrinsic::riscv_clmul:
9787 case Intrinsic::riscv_clmulh:
9788 case Intrinsic::riscv_clmulr: {
9791 return DAG.
getNode(Opc,
DL, XLenVT,
Op.getOperand(1),
Op.getOperand(2));
9793 case Intrinsic::experimental_get_vector_length:
9795 case Intrinsic::experimental_cttz_elts:
9797 case Intrinsic::riscv_vmv_x_s: {
9801 case Intrinsic::riscv_vfmv_f_s:
9804 case Intrinsic::riscv_vmv_v_x:
9806 Op.getOperand(3),
Op.getSimpleValueType(),
DL, DAG,
9808 case Intrinsic::riscv_vfmv_v_f:
9810 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
9811 case Intrinsic::riscv_vmv_s_x: {
9814 if (
Scalar.getValueType().bitsLE(XLenVT)) {
9817 Op.getOperand(1), Scalar,
Op.getOperand(3));
9820 assert(
Scalar.getValueType() == MVT::i64 &&
"Unexpected scalar VT!");
9837 MVT VT =
Op.getSimpleValueType();
9842 if (
Op.getOperand(1).isUndef())
9858 case Intrinsic::riscv_vfmv_s_f:
9860 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
9862 case Intrinsic::riscv_vaesdf_vv:
9863 case Intrinsic::riscv_vaesdf_vs:
9864 case Intrinsic::riscv_vaesdm_vv:
9865 case Intrinsic::riscv_vaesdm_vs:
9866 case Intrinsic::riscv_vaesef_vv:
9867 case Intrinsic::riscv_vaesef_vs:
9868 case Intrinsic::riscv_vaesem_vv:
9869 case Intrinsic::riscv_vaesem_vs:
9870 case Intrinsic::riscv_vaeskf1:
9871 case Intrinsic::riscv_vaeskf2:
9872 case Intrinsic::riscv_vaesz_vs:
9873 case Intrinsic::riscv_vsm4k:
9874 case Intrinsic::riscv_vsm4r_vv:
9875 case Intrinsic::riscv_vsm4r_vs: {
9876 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
9877 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
9878 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
9883 case Intrinsic::riscv_vsm3c:
9884 case Intrinsic::riscv_vsm3me: {
9885 if (!
isValidEGW(8,
Op.getSimpleValueType(), Subtarget) ||
9886 !
isValidEGW(8,
Op->getOperand(1).getSimpleValueType(), Subtarget))
9891 case Intrinsic::riscv_vsha2ch:
9892 case Intrinsic::riscv_vsha2cl:
9893 case Intrinsic::riscv_vsha2ms: {
9894 if (
Op->getSimpleValueType(0).getScalarSizeInBits() == 64 &&
9895 !Subtarget.hasStdExtZvknhb())
9897 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
9898 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
9899 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
9903 case Intrinsic::riscv_sf_vc_v_x:
9904 case Intrinsic::riscv_sf_vc_v_i:
9905 case Intrinsic::riscv_sf_vc_v_xv:
9906 case Intrinsic::riscv_sf_vc_v_iv:
9907 case Intrinsic::riscv_sf_vc_v_vv:
9908 case Intrinsic::riscv_sf_vc_v_fv:
9909 case Intrinsic::riscv_sf_vc_v_xvv:
9910 case Intrinsic::riscv_sf_vc_v_ivv:
9911 case Intrinsic::riscv_sf_vc_v_vvv:
9912 case Intrinsic::riscv_sf_vc_v_fvv:
9913 case Intrinsic::riscv_sf_vc_v_xvw:
9914 case Intrinsic::riscv_sf_vc_v_ivw:
9915 case Intrinsic::riscv_sf_vc_v_vvw:
9916 case Intrinsic::riscv_sf_vc_v_fvw: {
9917 MVT VT =
Op.getSimpleValueType();
9954 MVT VT =
Op.getSimpleValueType();
9958 if (VT.isFloatingPoint()) {
9963 if (VT.isFixedLengthVector())
9973 if (VT.isFixedLengthVector())
9975 if (VT.isFloatingPoint())
9994 unsigned IntNo =
Op.getConstantOperandVal(1);
9998 case Intrinsic::riscv_seg2_load:
9999 case Intrinsic::riscv_seg3_load:
10000 case Intrinsic::riscv_seg4_load:
10001 case Intrinsic::riscv_seg5_load:
10002 case Intrinsic::riscv_seg6_load:
10003 case Intrinsic::riscv_seg7_load:
10004 case Intrinsic::riscv_seg8_load: {
10007 Intrinsic::riscv_vlseg2, Intrinsic::riscv_vlseg3,
10008 Intrinsic::riscv_vlseg4, Intrinsic::riscv_vlseg5,
10009 Intrinsic::riscv_vlseg6, Intrinsic::riscv_vlseg7,
10010 Intrinsic::riscv_vlseg8};
10011 unsigned NF =
Op->getNumValues() - 1;
10012 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
10014 MVT VT =
Op->getSimpleValueType(0);
10022 auto *
Load = cast<MemIntrinsicSDNode>(
Op);
10034 Load->getMemoryVT(),
Load->getMemOperand());
10036 for (
unsigned int RetIdx = 0; RetIdx < NF; RetIdx++) {
10045 case Intrinsic::riscv_sf_vc_v_x_se:
10047 case Intrinsic::riscv_sf_vc_v_i_se:
10049 case Intrinsic::riscv_sf_vc_v_xv_se:
10051 case Intrinsic::riscv_sf_vc_v_iv_se:
10053 case Intrinsic::riscv_sf_vc_v_vv_se:
10055 case Intrinsic::riscv_sf_vc_v_fv_se:
10057 case Intrinsic::riscv_sf_vc_v_xvv_se:
10059 case Intrinsic::riscv_sf_vc_v_ivv_se:
10061 case Intrinsic::riscv_sf_vc_v_vvv_se:
10063 case Intrinsic::riscv_sf_vc_v_fvv_se:
10065 case Intrinsic::riscv_sf_vc_v_xvw_se:
10067 case Intrinsic::riscv_sf_vc_v_ivw_se:
10069 case Intrinsic::riscv_sf_vc_v_vvw_se:
10071 case Intrinsic::riscv_sf_vc_v_fvw_se:
10080 unsigned IntNo =
Op.getConstantOperandVal(1);
10084 case Intrinsic::riscv_seg2_store:
10085 case Intrinsic::riscv_seg3_store:
10086 case Intrinsic::riscv_seg4_store:
10087 case Intrinsic::riscv_seg5_store:
10088 case Intrinsic::riscv_seg6_store:
10089 case Intrinsic::riscv_seg7_store:
10090 case Intrinsic::riscv_seg8_store: {
10093 Intrinsic::riscv_vsseg2, Intrinsic::riscv_vsseg3,
10094 Intrinsic::riscv_vsseg4, Intrinsic::riscv_vsseg5,
10095 Intrinsic::riscv_vsseg6, Intrinsic::riscv_vsseg7,
10096 Intrinsic::riscv_vsseg8};
10099 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
10101 MVT VT =
Op->getOperand(2).getSimpleValueType();
10111 auto *FixedIntrinsic = cast<MemIntrinsicSDNode>(
Op);
10114 for (
unsigned i = 0; i < NF; i++)
10118 ContainerVT, FixedIntrinsic->getOperand(2 + i), DAG, Subtarget),
10122 FixedIntrinsic->getChain(),
10131 FixedIntrinsic->getMemoryVT(), FixedIntrinsic->getMemOperand());
10133 case Intrinsic::riscv_sf_vc_xv_se:
10135 case Intrinsic::riscv_sf_vc_iv_se:
10137 case Intrinsic::riscv_sf_vc_vv_se:
10139 case Intrinsic::riscv_sf_vc_fv_se:
10141 case Intrinsic::riscv_sf_vc_xvv_se:
10143 case Intrinsic::riscv_sf_vc_ivv_se:
10145 case Intrinsic::riscv_sf_vc_vvv_se:
10147 case Intrinsic::riscv_sf_vc_fvv_se:
10149 case Intrinsic::riscv_sf_vc_xvw_se:
10151 case Intrinsic::riscv_sf_vc_ivw_se:
10153 case Intrinsic::riscv_sf_vc_vvw_se:
10155 case Intrinsic::riscv_sf_vc_fvw_se:
10163 switch (ISDOpcode) {
10166 case ISD::VP_REDUCE_ADD:
10169 case ISD::VP_REDUCE_UMAX:
10172 case ISD::VP_REDUCE_SMAX:
10175 case ISD::VP_REDUCE_UMIN:
10178 case ISD::VP_REDUCE_SMIN:
10181 case ISD::VP_REDUCE_AND:
10184 case ISD::VP_REDUCE_OR:
10187 case ISD::VP_REDUCE_XOR:
10190 case ISD::VP_REDUCE_FADD:
10192 case ISD::VP_REDUCE_SEQ_FADD:
10194 case ISD::VP_REDUCE_FMAX:
10195 case ISD::VP_REDUCE_FMAXIMUM:
10197 case ISD::VP_REDUCE_FMIN:
10198 case ISD::VP_REDUCE_FMINIMUM:
10208 SDValue Vec =
Op.getOperand(IsVP ? 1 : 0);
10213 Op.getOpcode() == ISD::VP_REDUCE_AND ||
10214 Op.getOpcode() == ISD::VP_REDUCE_OR ||
10215 Op.getOpcode() == ISD::VP_REDUCE_XOR) &&
10216 "Unexpected reduction lowering");
10220 MVT ContainerVT = VecVT;
10228 Mask =
Op.getOperand(2);
10229 VL =
Op.getOperand(3);
10231 std::tie(Mask, VL) =
10236 switch (
Op.getOpcode()) {
10240 case ISD::VP_REDUCE_AND: {
10252 case ISD::VP_REDUCE_OR:
10258 case ISD::VP_REDUCE_XOR: {
10282 return DAG.
getNode(BaseOpc,
DL,
Op.getValueType(), SetCC,
Op.getOperand(0));
10286 auto *RegisterAVL = dyn_cast<RegisterSDNode>(AVL);
10287 auto *ImmAVL = dyn_cast<ConstantSDNode>(AVL);
10288 return (RegisterAVL && RegisterAVL->getReg() == RISCV::X0) ||
10289 (ImmAVL && ImmAVL->getZExtValue() >= 1);
10305 auto InnerVT = VecVT.
bitsLE(M1VT) ? VecVT : M1VT;
10309 auto InnerVL = NonZeroAVL ? VL : DAG.
getConstant(1,
DL, XLenVT);
10312 if (M1VT != InnerVT)
10318 SDValue Ops[] = {PassThru, Vec, InitialValue, Mask, VL, Policy};
10337 VecEVT =
Lo.getValueType();
10350 MVT ContainerVT = VecVT;
10370 Mask, VL,
DL, DAG, Subtarget);
10376static std::tuple<unsigned, SDValue, SDValue>
10380 auto Flags =
Op->getFlags();
10381 unsigned Opcode =
Op.getOpcode();
10405 return std::make_tuple(RVVOpc,
Op.getOperand(0), Front);
10413 MVT VecEltVT =
Op.getSimpleValueType();
10415 unsigned RVVOpcode;
10416 SDValue VectorVal, ScalarVal;
10417 std::tie(RVVOpcode, VectorVal, ScalarVal) =
10421 MVT ContainerVT = VecVT;
10427 MVT ResVT =
Op.getSimpleValueType();
10430 VL,
DL, DAG, Subtarget);
10435 if (
Op->getFlags().hasNoNaNs())
10441 {VectorVal, VectorVal, DAG.getCondCode(ISD::SETNE),
10442 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
10448 DL, ResVT, NoNaNs, Res,
10455 unsigned Opc =
Op.getOpcode();
10478 Vec, Mask, VL,
DL, DAG, Subtarget);
10479 if ((Opc != ISD::VP_REDUCE_FMINIMUM && Opc != ISD::VP_REDUCE_FMAXIMUM) ||
10480 Op->getFlags().hasNoNaNs())
10497 DL, ResVT, NoNaNs, Res,
10510 unsigned OrigIdx =
Op.getConstantOperandVal(2);
10513 if (OrigIdx == 0 && Vec.
isUndef())
10524 assert(OrigIdx % 8 == 0 &&
"Invalid index");
10527 "Unexpected mask vector lowering");
10559 MVT ContainerVT = VecVT;
10566 DAG.
getUNDEF(ContainerVT), SubVec,
10583 if (OrigIdx == 0) {
10588 SubVec =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, Vec, SubVec,
10589 SlideupAmt, Mask, VL, Policy);
10597 MVT ContainerVecVT = VecVT;
10603 MVT ContainerSubVecVT = SubVecVT;
10609 unsigned SubRegIdx;
10619 ContainerVecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
10620 SubRegIdx = Decompose.first;
10622 (OrigIdx % Vscale));
10626 ContainerVecVT, ContainerSubVecVT, OrigIdx,
TRI);
10627 SubRegIdx = Decompose.first;
10634 bool ExactlyVecRegSized =
10636 .isKnownMultipleOf(Subtarget.
expandVScale(VecRegSize));
10651 if (RemIdx.
isZero() && (ExactlyVecRegSized || Vec.
isUndef())) {
10655 if (SubRegIdx == RISCV::NoSubRegister) {
10678 MVT InterSubVT = ContainerVecVT;
10679 SDValue AlignedExtract = Vec;
10719 SubVec =
getVSlideup(DAG, Subtarget,
DL, InterSubVT, AlignedExtract, SubVec,
10720 SlideupAmt, Mask, VL, Policy);
10725 if (ContainerVecVT.
bitsGT(InterSubVT))
10734 return DAG.
getBitcast(
Op.getSimpleValueType(), SubVec);
10740 MVT SubVecVT =
Op.getSimpleValueType();
10745 unsigned OrigIdx =
Op.getConstantOperandVal(1);
10761 assert(OrigIdx % 8 == 0 &&
"Invalid index");
10764 "Unexpected mask vector lowering");
10798 MVT ContainerVT = VecVT;
10806 if (
auto ShrunkVT =
10808 ContainerVT = *ShrunkVT;
10821 DAG.
getUNDEF(ContainerVT), Vec, SlidedownAmt, Mask, VL);
10833 MVT ContainerSubVecVT = SubVecVT;
10837 unsigned SubRegIdx;
10847 VecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
10848 SubRegIdx = Decompose.first;
10850 (OrigIdx % Vscale));
10854 VecVT, ContainerSubVecVT, OrigIdx,
TRI);
10855 SubRegIdx = Decompose.first;
10882 MVT InterSubVT = VecVT;
10887 assert(SubRegIdx != RISCV::NoSubRegister);
10907 Vec, SlidedownAmt, Mask, VL);
10916 return DAG.
getBitcast(
Op.getSimpleValueType(), Slidedown);
10923 MVT VT =
N.getSimpleValueType();
10927 assert(
Op.getSimpleValueType() == VT &&
10928 "Operands and result must be same type");
10932 unsigned NumVals =
N->getNumValues();
10935 NumVals,
N.getValueType().changeVectorElementType(MVT::i8)));
10938 for (
unsigned I = 0;
I < NumVals;
I++) {
10944 if (TruncVals.
size() > 1)
10946 return TruncVals.
front();
10952 MVT VecVT =
Op.getSimpleValueType();
10955 "vector_interleave on non-scalable vector!");
10966 EVT SplitVT = Op0Lo.getValueType();
10969 DAG.
getVTList(SplitVT, SplitVT), Op0Lo, Op0Hi);
10971 DAG.
getVTList(SplitVT, SplitVT), Op1Lo, Op1Hi);
10985 Op.getOperand(0),
Op.getOperand(1));
11004 EvenSplat = DAG.
getBitcast(MVT::nxv64i1, EvenSplat);
11009 OddSplat = DAG.
getBitcast(MVT::nxv64i1, OddSplat);
11015 EvenMask, DAG.
getUNDEF(ConcatVT));
11031 MVT VecVT =
Op.getSimpleValueType();
11034 "vector_interleave on non-scalable vector!");
11047 EVT SplitVT = Op0Lo.getValueType();
11050 DAG.
getVTList(SplitVT, SplitVT), Op0Lo, Op1Lo);
11052 DAG.
getVTList(SplitVT, SplitVT), Op0Hi, Op1Hi);
11074 Op.getOperand(0),
Op.getOperand(1));
11122 MVT VT =
Op.getSimpleValueType();
11127 uint64_t StepValImm =
Op.getConstantOperandVal(0);
11128 if (StepValImm != 1) {
11137 VL, VT,
DL, DAG, Subtarget);
11152 MVT VecVT =
Op.getSimpleValueType();
11161 MVT ContainerVT = VecVT;
11215 unsigned MaxVLMAX =
11225 if (MaxVLMAX > 256 && EltSize == 8) {
11254 assert(isUInt<16>(MaxVLMAX - 1));
11280 DAG.
getUNDEF(ContainerVT), Mask, VL);
11292 MVT VecVT =
Op.getSimpleValueType();
11296 int64_t ImmValue = cast<ConstantSDNode>(
Op.getOperand(2))->getSExtValue();
11297 SDValue DownOffset, UpOffset;
11298 if (ImmValue >= 0) {
11314 DownOffset, TrueMask, UpOffset);
11315 return getVSlideup(DAG, Subtarget,
DL, VecVT, SlideDown, V2, UpOffset,
11321RISCVTargetLowering::lowerFixedLengthVectorLoadToRVV(
SDValue Op,
11324 auto *
Load = cast<LoadSDNode>(
Op);
11327 Load->getMemoryVT(),
11328 *
Load->getMemOperand()) &&
11329 "Expecting a correctly-aligned load");
11331 MVT VT =
Op.getSimpleValueType();
11337 const auto [MinVLMAX, MaxVLMAX] =
11340 getLMUL1VT(ContainerVT).bitsLE(ContainerVT)) {
11354 IsMaskOp ? Intrinsic::riscv_vlm : Intrinsic::riscv_vle,
DL, XLenVT);
11357 Ops.push_back(DAG.
getUNDEF(ContainerVT));
11358 Ops.push_back(
Load->getBasePtr());
11363 Load->getMemoryVT(),
Load->getMemOperand());
11370RISCVTargetLowering::lowerFixedLengthVectorStoreToRVV(
SDValue Op,
11373 auto *
Store = cast<StoreSDNode>(
Op);
11376 Store->getMemoryVT(),
11377 *
Store->getMemOperand()) &&
11378 "Expecting a correctly-aligned store");
11399 const auto [MinVLMAX, MaxVLMAX] =
11402 getLMUL1VT(ContainerVT).bitsLE(ContainerVT)) {
11413 IsMaskOp ? Intrinsic::riscv_vsm : Intrinsic::riscv_vse,
DL, XLenVT);
11416 {Store->getChain(), IntID, NewValue, Store->getBasePtr(), VL},
11417 Store->getMemoryVT(),
Store->getMemOperand());
11423 MVT VT =
Op.getSimpleValueType();
11425 const auto *MemSD = cast<MemSDNode>(
Op);
11426 EVT MemVT = MemSD->getMemoryVT();
11428 SDValue Chain = MemSD->getChain();
11432 bool IsExpandingLoad =
false;
11433 if (
const auto *VPLoad = dyn_cast<VPLoadSDNode>(
Op)) {
11434 Mask = VPLoad->getMask();
11436 VL = VPLoad->getVectorLength();
11438 const auto *MLoad = cast<MaskedLoadSDNode>(
Op);
11439 Mask = MLoad->getMask();
11440 PassThru = MLoad->getPassThru();
11441 IsExpandingLoad = MLoad->isExpandingLoad();
11448 MVT ContainerVT = VT;
11462 if (!IsUnmasked && IsExpandingLoad) {
11469 unsigned IntID = IsUnmasked || IsExpandingLoad ? Intrinsic::riscv_vle
11470 : Intrinsic::riscv_vle_mask;
11472 if (IntID == Intrinsic::riscv_vle)
11473 Ops.push_back(DAG.
getUNDEF(ContainerVT));
11475 Ops.push_back(PassThru);
11476 Ops.push_back(BasePtr);
11477 if (IntID == Intrinsic::riscv_vle_mask)
11478 Ops.push_back(Mask);
11480 if (IntID == Intrinsic::riscv_vle_mask)
11487 Chain =
Result.getValue(1);
11489 MVT IndexVT = ContainerVT;
11494 bool UseVRGATHEREI16 =
false;
11502 UseVRGATHEREI16 =
true;
11508 DAG.
getUNDEF(IndexVT), Mask, ExpandingVL);
11512 DL, ContainerVT, Result, Iota, PassThru, Mask, ExpandingVL);
11525 const auto *MemSD = cast<MemSDNode>(
Op);
11526 EVT MemVT = MemSD->getMemoryVT();
11528 SDValue Chain = MemSD->getChain();
11532 bool IsCompressingStore =
false;
11533 if (
const auto *VPStore = dyn_cast<VPStoreSDNode>(
Op)) {
11534 Val = VPStore->getValue();
11535 Mask = VPStore->getMask();
11536 VL = VPStore->getVectorLength();
11538 const auto *MStore = cast<MaskedStoreSDNode>(
Op);
11539 Val = MStore->getValue();
11540 Mask = MStore->getMask();
11541 IsCompressingStore = MStore->isCompressingStore();
11550 MVT ContainerVT = VT;
11555 if (!IsUnmasked || IsCompressingStore) {
11564 if (IsCompressingStore) {
11567 DAG.
getUNDEF(ContainerVT), Val, Mask, VL);
11574 IsUnmasked ? Intrinsic::riscv_vse : Intrinsic::riscv_vse_mask;
11576 Ops.push_back(Val);
11577 Ops.push_back(BasePtr);
11579 Ops.push_back(Mask);
11583 DAG.
getVTList(MVT::Other), Ops, MemVT, MMO);
11595 MVT ContainerVT = VT;
11608 Passthru, Val, Mask, VL);
11617RISCVTargetLowering::lowerFixedLengthVectorSetccToRVV(
SDValue Op,
11619 MVT InVT =
Op.getOperand(0).getSimpleValueType();
11622 MVT VT =
Op.getSimpleValueType();
11636 {Op1, Op2,
Op.getOperand(2), DAG.
getUNDEF(MaskVT), Mask, VL});
11643 unsigned Opc =
Op.getOpcode();
11650 MVT VT =
Op.getSimpleValueType();
11683 MVT ContainerInVT = InVT;
11702 {Chain, Op1, Op1, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
11706 {Chain, Op2, Op2, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
11714 {Chain, Op1, Op2, CC, Mask, Mask, VL});
11719 {Chain, Op1, Op2, CC, DAG.getUNDEF(MaskVT), Mask, VL});
11732 MVT VT =
Op.getSimpleValueType();
11736 "Unexpected type for ISD::ABS");
11738 MVT ContainerVT = VT;
11745 if (
Op->getOpcode() == ISD::VP_ABS) {
11746 Mask =
Op->getOperand(1);
11750 VL =
Op->getOperand(2);
11758 DAG.
getUNDEF(ContainerVT), Mask, VL);
11760 DAG.
getUNDEF(ContainerVT), Mask, VL);
11767SDValue RISCVTargetLowering::lowerFixedLengthVectorFCOPYSIGNToRVV(
11770 MVT VT =
Op.getSimpleValueType();
11774 "Can only handle COPYSIGN with matching types.");
11783 Sign, DAG.
getUNDEF(ContainerVT), Mask, VL);
11788SDValue RISCVTargetLowering::lowerFixedLengthVectorSelectToRVV(
11790 MVT VT =
Op.getSimpleValueType();
11793 MVT I1ContainerVT =
11807 Op2, DAG.
getUNDEF(ContainerVT), VL);
11818 MVT VT =
Op.getSimpleValueType();
11823 for (
const SDValue &V :
Op->op_values()) {
11824 assert(!isa<VTSDNode>(V) &&
"Unexpected VTSDNode node!");
11827 if (!
V.getValueType().isVector()) {
11833 assert(useRVVForFixedLengthVectorVT(
V.getSimpleValueType()) &&
11834 "Only fixed length vectors are supported!");
11848 if (
Op->isStrictFPOpcode()) {
11857 DAG.
getNode(NewOpc,
DL, ContainerVT, Ops,
Op->getFlags());
11871 MVT VT =
Op.getSimpleValueType();
11874 MVT ContainerVT = VT;
11880 assert(!isa<VTSDNode>(V) &&
"Unexpected VTSDNode node!");
11883 if (HasPassthruOp) {
11886 if (*MaskIdx == OpIdx.index())
11890 if (
Op.getOpcode() == ISD::VP_MERGE) {
11894 assert(
Op.getOpcode() == ISD::VP_SELECT);
11906 if (!
V.getValueType().isFixedLengthVector()) {
11911 MVT OpVT =
V.getSimpleValueType();
11913 assert(useRVVForFixedLengthVectorVT(OpVT) &&
11914 "Only fixed length vectors are supported!");
11919 return DAG.
getNode(RISCVISDOpc,
DL, VT, Ops,
Op->getFlags());
11929 MVT VT =
Op.getSimpleValueType();
11935 MVT ContainerVT = VT;
11945 DAG.
getUNDEF(ContainerVT), Zero, VL);
11948 Op.getOpcode() == ISD::VP_ZERO_EXTEND ? 1 : -1,
DL, XLenVT);
11950 DAG.
getUNDEF(ContainerVT), SplatValue, VL);
11953 ZeroSplat, DAG.
getUNDEF(ContainerVT), VL);
11962 MVT VT =
Op.getSimpleValueType();
11966 ISD::CondCode Condition = cast<CondCodeSDNode>(
Op.getOperand(2))->get();
11970 MVT ContainerVT = VT;
11980 switch (Condition) {
12048 MVT DstVT =
Op.getSimpleValueType();
12049 MVT SrcVT = Src.getSimpleValueType();
12062 if (DstEltSize >= SrcEltSize) {
12071 if (SrcEltSize == 1) {
12082 ZeroSplat, DAG.
getUNDEF(IntVT), VL);
12083 }
else if (DstEltSize > (2 * SrcEltSize)) {
12087 Src = DAG.
getNode(RISCVISDExtOpc,
DL, IntVT, Src, Mask, VL);
12093 "Wrong input/output vector types");
12096 if (DstEltSize > (2 * SrcEltSize)) {
12112 MVT InterimFVT = DstVT;
12113 if (SrcEltSize > (2 * DstEltSize)) {
12114 assert(SrcEltSize == (4 * DstEltSize) &&
"Unexpected types!");
12121 if (InterimFVT != DstVT) {
12127 "Wrong input/output vector types");
12131 if (DstEltSize == 1) {
12134 assert(SrcEltSize >= 16 &&
"Unexpected FP type!");
12144 DAG.
getUNDEF(InterimIVT), SplatZero, VL);
12154 while (InterimIVT != DstVT) {
12166 MVT VT =
Op.getSimpleValueType();
12175 MVT VT =
Op.getSimpleValueType();
12189 MVT ContainerVT = VT;
12210 SplatZero, DAG.
getUNDEF(PromotedVT), VL);
12213 SplatOne, SplatZero, DAG.
getUNDEF(PromotedVT), VLMax);
12217 TrueVal, FalseVal, FalseVal, VL);
12232RISCVTargetLowering::lowerVPSpliceExperimental(
SDValue Op,
12244 MVT VT =
Op.getSimpleValueType();
12245 MVT ContainerVT = VT;
12255 if (IsMaskVector) {
12266 SplatZeroOp1, DAG.
getUNDEF(ContainerVT), EVL1);
12275 SplatZeroOp2, DAG.
getUNDEF(ContainerVT), EVL2);
12278 int64_t ImmValue = cast<ConstantSDNode>(
Offset)->getSExtValue();
12279 SDValue DownOffset, UpOffset;
12280 if (ImmValue >= 0) {
12294 Op1, DownOffset, Mask, UpOffset);
12298 if (IsMaskVector) {
12302 {Result, DAG.getConstant(0, DL, ContainerVT),
12303 DAG.getCondCode(ISD::SETNE), DAG.getUNDEF(getMaskTypeFor(ContainerVT)),
12318 MVT VT =
Op.getSimpleValueType();
12320 MVT ContainerVT = VT;
12336RISCVTargetLowering::lowerVPReverseExperimental(
SDValue Op,
12339 MVT VT =
Op.getSimpleValueType();
12346 MVT ContainerVT = VT;
12354 MVT GatherVT = ContainerVT;
12358 if (IsMaskVector) {
12369 SplatZero, DAG.
getUNDEF(IndicesVT), EVL);
12375 unsigned MaxVLMAX =
12384 if (MaxVLMAX > 256 && EltSize == 8) {
12412 DAG.
getUNDEF(GatherVT), Result, Diff, Mask, EVL);
12414 if (IsMaskVector) {
12437 DAG.
getUNDEF(IndicesVT), VecLen, EVL);
12439 DAG.
getUNDEF(IndicesVT), Mask, EVL);
12441 DAG.
getUNDEF(GatherVT), Mask, EVL);
12443 if (IsMaskVector) {
12458 MVT VT =
Op.getSimpleValueType();
12460 return lowerVPOp(
Op, DAG);
12467 MVT ContainerVT = VT;
12486 MVT VT =
Op.getSimpleValueType();
12487 MVT ContainerVT = VT;
12493 auto *VPNode = cast<VPStridedLoadSDNode>(
Op);
12499 : Intrinsic::riscv_vlse_mask,
12502 DAG.
getUNDEF(ContainerVT), VPNode->getBasePtr(),
12503 VPNode->getStride()};
12511 Ops.
push_back(VPNode->getVectorLength());
12519 VPNode->getMemoryVT(), VPNode->getMemOperand());
12533 auto *VPNode = cast<VPStridedStoreSDNode>(
Op);
12534 SDValue StoreVal = VPNode->getValue();
12536 MVT ContainerVT = VT;
12547 : Intrinsic::riscv_vsse_mask,
12550 VPNode->getBasePtr(), VPNode->getStride()};
12558 Ops.
push_back(VPNode->getVectorLength());
12561 Ops, VPNode->getMemoryVT(),
12562 VPNode->getMemOperand());
12574 MVT VT =
Op.getSimpleValueType();
12576 const auto *MemSD = cast<MemSDNode>(
Op.getNode());
12577 EVT MemVT = MemSD->getMemoryVT();
12579 SDValue Chain = MemSD->getChain();
12585 if (
auto *VPGN = dyn_cast<VPGatherSDNode>(
Op.getNode())) {
12586 Index = VPGN->getIndex();
12587 Mask = VPGN->getMask();
12589 VL = VPGN->getVectorLength();
12594 auto *MGN = cast<MaskedGatherSDNode>(
Op.getNode());
12595 Index = MGN->getIndex();
12596 Mask = MGN->getMask();
12597 PassThru = MGN->getPassThru();
12601 MVT IndexVT =
Index.getSimpleValueType();
12605 "Unexpected VTs!");
12606 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
12609 "Unexpected extending MGATHER/VP_GATHER");
12615 MVT ContainerVT = VT;
12639 IsUnmasked ? Intrinsic::riscv_vluxei : Intrinsic::riscv_vluxei_mask;
12656 Chain =
Result.getValue(1);
12673 const auto *MemSD = cast<MemSDNode>(
Op.getNode());
12674 EVT MemVT = MemSD->getMemoryVT();
12676 SDValue Chain = MemSD->getChain();
12679 [[maybe_unused]]
bool IsTruncatingStore =
false;
12682 if (
auto *VPSN = dyn_cast<VPScatterSDNode>(
Op.getNode())) {
12683 Index = VPSN->getIndex();
12684 Mask = VPSN->getMask();
12685 Val = VPSN->getValue();
12686 VL = VPSN->getVectorLength();
12688 IsTruncatingStore =
false;
12691 auto *MSN = cast<MaskedScatterSDNode>(
Op.getNode());
12692 Index = MSN->getIndex();
12693 Mask = MSN->getMask();
12694 Val = MSN->getValue();
12695 IsTruncatingStore = MSN->isTruncatingStore();
12699 MVT IndexVT =
Index.getSimpleValueType();
12703 "Unexpected VTs!");
12704 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
12707 assert(!IsTruncatingStore &&
"Unexpected truncating MSCATTER/VP_SCATTER");
12713 MVT ContainerVT = VT;
12737 IsUnmasked ? Intrinsic::riscv_vsoxei : Intrinsic::riscv_vsoxei_mask;
12747 DAG.
getVTList(MVT::Other), Ops, MemVT, MMO);
12763 static const int Table =
12792 static const unsigned Table =
12815 bool isRISCV64 = Subtarget.
is64Bit();
12879 switch (
N->getOpcode()) {
12881 llvm_unreachable(
"Don't know how to custom type legalize this operation!");
12887 "Unexpected custom legalisation");
12888 bool IsStrict =
N->isStrictFPOpcode();
12891 SDValue Op0 = IsStrict ?
N->getOperand(1) :
N->getOperand(0);
12909 Opc,
DL, VTs, Chain, Op0,
12943 std::tie(Result, Chain) =
12944 makeLibCall(DAG, LC,
N->getValueType(0), Op0, CallOptions,
DL, Chain);
12972 Op0.
getValueType() == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
12983 assert(!Subtarget.
is64Bit() &&
"READCYCLECOUNTER/READSTEADYCOUNTER only "
12984 "has custom type legalization on riscv32");
12986 SDValue LoCounter, HiCounter;
12997 N->getOperand(0), LoCounter, HiCounter);
13021 unsigned Size =
N->getSimpleValueType(0).getSizeInBits();
13022 unsigned XLen = Subtarget.
getXLen();
13025 assert(
Size == (XLen * 2) &&
"Unexpected custom legalisation");
13033 if (LHSIsU == RHSIsU)
13050 if (RHSIsU && LHSIsS && !RHSIsS)
13052 else if (LHSIsU && RHSIsS && !LHSIsS)
13062 "Unexpected custom legalisation");
13069 "Unexpected custom legalisation");
13072 if (
N->getOpcode() ==
ISD::SHL && Subtarget.hasStdExtZbs() &&
13098 "Unexpected custom legalisation");
13099 assert((Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb() ||
13100 Subtarget.hasVendorXTHeadBb()) &&
13101 "Unexpected custom legalization");
13102 if (!isa<ConstantSDNode>(
N->getOperand(1)) &&
13103 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()))
13112 "Unexpected custom legalisation");
13126 MVT VT =
N->getSimpleValueType(0);
13127 assert((VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32) &&
13128 Subtarget.
is64Bit() && Subtarget.hasStdExtM() &&
13129 "Unexpected custom legalisation");
13141 if (VT != MVT::i32)
13150 "Unexpected custom legalisation");
13154 if (!isa<ConstantSDNode>(
N->getOperand(1)))
13171 EVT OType =
N->getValueType(1);
13184 "Unexpected custom legalisation");
13201 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1), Res,
13205 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1),
N->getOperand(0),
13223 !Subtarget.hasStdExtZbb() &&
"Unexpected custom legalisation");
13232 "Unexpected custom legalisation");
13238 "Unexpected custom legalisation");
13240 if (Subtarget.hasStdExtZbb()) {
13274 EVT VT =
N->getValueType(0);
13279 if (VT == MVT::i16 &&
13281 (Op0VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
13284 }
else if (VT == MVT::i32 && Op0VT == MVT::f32 && Subtarget.
is64Bit() &&
13289 }
else if (VT == MVT::i64 && Op0VT == MVT::f64 && !Subtarget.
is64Bit() &&
13292 DAG.
getVTList(MVT::i32, MVT::i32), Op0);
13313 MVT VT =
N->getSimpleValueType(0);
13315 assert((VT == MVT::i16 || (VT == MVT::i32 && Subtarget.
is64Bit())) &&
13316 "Unexpected custom legalisation");
13319 "Unexpected extension");
13345 assert(!Subtarget.
is64Bit() &&
N->getValueType(0) == MVT::i64 &&
13347 "Unexpected EXTRACT_VECTOR_ELT legalization");
13350 MVT ContainerVT = VecVT;
13378 DAG.
getUNDEF(ContainerVT), Mask, VL);
13386 unsigned IntNo =
N->getConstantOperandVal(0);
13390 "Don't know how to custom type legalize this intrinsic!");
13391 case Intrinsic::experimental_get_vector_length: {
13396 case Intrinsic::experimental_cttz_elts: {
13402 case Intrinsic::riscv_orc_b:
13403 case Intrinsic::riscv_brev8:
13404 case Intrinsic::riscv_sha256sig0:
13405 case Intrinsic::riscv_sha256sig1:
13406 case Intrinsic::riscv_sha256sum0:
13407 case Intrinsic::riscv_sha256sum1:
13408 case Intrinsic::riscv_sm3p0:
13409 case Intrinsic::riscv_sm3p1: {
13410 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
13430 case Intrinsic::riscv_sm4ks:
13431 case Intrinsic::riscv_sm4ed: {
13439 DAG.
getNode(Opc,
DL, MVT::i64, NewOp0, NewOp1,
N->getOperand(3));
13443 case Intrinsic::riscv_mopr: {
13444 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
13454 case Intrinsic::riscv_moprr: {
13455 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
13467 case Intrinsic::riscv_clmul: {
13468 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
13479 case Intrinsic::riscv_clmulh:
13480 case Intrinsic::riscv_clmulr: {
13481 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
13509 case Intrinsic::riscv_vmv_x_s: {
13510 EVT VT =
N->getValueType(0);
13512 if (VT.
bitsLT(XLenVT)) {
13521 "Unexpected custom legalization");
13559 case ISD::VP_REDUCE_ADD:
13560 case ISD::VP_REDUCE_AND:
13561 case ISD::VP_REDUCE_OR:
13562 case ISD::VP_REDUCE_XOR:
13563 case ISD::VP_REDUCE_SMAX:
13564 case ISD::VP_REDUCE_UMAX:
13565 case ISD::VP_REDUCE_SMIN:
13566 case ISD::VP_REDUCE_UMIN:
13630 const EVT VT =
N->getValueType(0);
13631 const unsigned Opc =
N->getOpcode();
13638 (Opc !=
ISD::FADD || !
N->getFlags().hasAllowReassociation()))
13643 "Inconsistent mappings");
13654 !isa<ConstantSDNode>(
RHS.getOperand(1)))
13657 uint64_t RHSIdx = cast<ConstantSDNode>(
RHS.getOperand(1))->getLimitedValue();
13672 LHS.getOperand(0) == SrcVec && isa<ConstantSDNode>(
LHS.getOperand(1))) {
13674 cast<ConstantSDNode>(
LHS.getOperand(1))->getLimitedValue();
13675 if (0 == std::min(LHSIdx, RHSIdx) && 1 == std::max(LHSIdx, RHSIdx)) {
13679 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
N->getFlags());
13686 if (
LHS.getOpcode() != ReduceOpc)
13701 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
13702 ReduceVec->
getFlags() &
N->getFlags());
13712 auto BinOpToRVVReduce = [](
unsigned Opc) {
13741 auto IsReduction = [&BinOpToRVVReduce](
SDValue V,
unsigned Opc) {
13744 V.getOperand(0).getOpcode() == BinOpToRVVReduce(Opc);
13747 unsigned Opc =
N->getOpcode();
13748 unsigned ReduceIdx;
13749 if (IsReduction(
N->getOperand(0), Opc))
13751 else if (IsReduction(
N->getOperand(1), Opc))
13757 if (Opc ==
ISD::FADD && !
N->getFlags().hasAllowReassociation())
13760 SDValue Extract =
N->getOperand(ReduceIdx);
13792 SDValue NewStart =
N->getOperand(1 - ReduceIdx);
13819 if (!Subtarget.hasStdExtZba())
13823 EVT VT =
N->getValueType(0);
13835 auto *N0C = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
13836 auto *N1C = dyn_cast<ConstantSDNode>(N1->
getOperand(1));
13839 int64_t C0 = N0C->getSExtValue();
13840 int64_t C1 = N1C->getSExtValue();
13841 if (C0 <= 0 || C1 <= 0)
13845 int64_t Bits = std::min(C0, C1);
13846 int64_t Diff = std::abs(C0 - C1);
13847 if (Diff != 1 && Diff != 2 && Diff != 3)
13874 EVT VT =
N->getValueType(0);
13882 if ((!Subtarget.hasStdExtZicond() &&
13883 !Subtarget.hasVendorXVentanaCondOps()) ||
13905 bool SwapSelectOps;
13911 SwapSelectOps =
false;
13912 NonConstantVal = FalseVal;
13914 SwapSelectOps =
true;
13915 NonConstantVal = TrueVal;
13921 FalseVal = DAG.
getNode(
N->getOpcode(),
SDLoc(
N), VT, OtherOp, NonConstantVal);
13969 EVT VT =
N->getValueType(0);
13977 auto *N0C = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
13978 auto *N1C = dyn_cast<ConstantSDNode>(
N->getOperand(1));
13984 if (!N0C->hasOneUse())
13986 int64_t C0 = N0C->getSExtValue();
13987 int64_t C1 = N1C->getSExtValue();
13989 if (C0 == -1 || C0 == 0 || C0 == 1 || isInt<12>(C1))
13992 if ((C1 / C0) != 0 && isInt<12>(C1 / C0) && isInt<12>(C1 % C0) &&
13993 !isInt<12>(C0 * (C1 / C0))) {
13996 }
else if ((C1 / C0 + 1) != 0 && isInt<12>(C1 / C0 + 1) &&
13997 isInt<12>(C1 % C0 - C0) && !isInt<12>(C0 * (C1 / C0 + 1))) {
14000 }
else if ((C1 / C0 - 1) != 0 && isInt<12>(C1 / C0 - 1) &&
14001 isInt<12>(C1 % C0 + C0) && !isInt<12>(C0 * (C1 / C0 - 1))) {
14028 EVT VT =
N->getValueType(0);
14059 unsigned OuterExtend =
14063 OuterExtend,
SDLoc(
N), VT,
14071 EVT VT =
N->getValueType(0);
14119 EVT VT =
N->getValueType(0);
14123 auto *N0C = dyn_cast<ConstantSDNode>(N0);
14129 APInt ImmValMinus1 = N0C->getAPIntValue() - 1;
14139 if (!isIntEqualitySetCC(CCVal) || !SetCCOpVT.
isInteger())
14162 if (!Subtarget.hasStdExtZbb())
14165 EVT VT =
N->getValueType(0);
14167 if (VT != Subtarget.
getXLenVT() && VT != MVT::i32 && VT != MVT::i16)
14176 auto *ShAmtCLeft = dyn_cast<ConstantSDNode>(N0.
getOperand(1));
14179 unsigned ShiftedAmount = 8 - ShAmtCLeft->getZExtValue();
14181 if (ShiftedAmount >= 8)
14185 SDValue RightShiftOperand = N1;
14187 if (ShiftedAmount != 0) {
14190 auto *ShAmtCRight = dyn_cast<ConstantSDNode>(N1.
getOperand(1));
14191 if (!ShAmtCRight || ShAmtCRight->getZExtValue() != ShiftedAmount)
14200 if (LeftShiftOperand != RightShiftOperand)
14204 Mask <<= ShiftedAmount;
14218 EVT VT =
N->getValueType(0);
14249 bool IsAnd =
N->getOpcode() ==
ISD::AND;
14273 EVT VT =
N->getValueType(0);
14297 EVT VT =
N->getValueType(0);
14324 if (CondLHS != True)
14331 if (!CondRHSC || CondRHSC->
getAPIntValue() != (1ULL << ScalarBits))
14343 if (!FalseRHSC || !FalseRHSC->
isZero())
14363 EVT VT =
N->getValueType(0);
14370 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() && VT == MVT::i1 &&
14397 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
14449 EVT VT =
N->getValueType(0);
14495 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
14520 auto *ConstN00 = dyn_cast<ConstantSDNode>(N0.
getOperand(0));
14525 const APInt &Imm = ConstN00->getAPIntValue();
14526 if ((Imm + 1).isSignedIntN(12))
14547 EVT VT =
N->getValueType(0);
14559 const bool HasShlAdd =
14560 Subtarget.hasStdExtZba() || Subtarget.hasVendorXTHeadBa();
14574 for (
uint64_t Divisor : {3, 5, 9}) {
14575 if (MulAmt % Divisor != 0)
14577 uint64_t MulAmt2 = MulAmt / Divisor;
14584 if (
X.getOpcode() ==
ISD::AND && isa<ConstantSDNode>(
X.getOperand(1)) &&
14585 X.getConstantOperandVal(1) == UINT64_C(0xffffffff)) {
14602 if (MulAmt2 == 3 || MulAmt2 == 5 || MulAmt2 == 9) {
14618 if (ScaleShift >= 1 && ScaleShift < 4) {
14619 unsigned ShiftAmt =
Log2_64((MulAmt & (MulAmt - 1)));
14633 for (
uint64_t Divisor : {3, 5, 9}) {
14638 if ((
C >> TZ) == Divisor && (TZ == 1 || TZ == 2 || TZ == 3)) {
14649 if (MulAmt > 2 &&
isPowerOf2_64((MulAmt - 1) & (MulAmt - 2))) {
14651 if (ScaleShift >= 1 && ScaleShift < 4) {
14652 unsigned ShiftAmt =
Log2_64(((MulAmt - 1) & (MulAmt - 2)));
14678 uint64_t MulAmtLowBit = MulAmt & (-MulAmt);
14680 uint64_t ShiftAmt1 = MulAmt + MulAmtLowBit;
14691 for (
uint64_t Divisor : {3, 5, 9}) {
14692 if (MulAmt % Divisor != 0)
14694 uint64_t MulAmt2 = MulAmt / Divisor;
14697 for (
uint64_t Divisor2 : {3, 5, 9}) {
14698 if (MulAmt2 % Divisor2 != 0)
14700 uint64_t MulAmt3 = MulAmt2 / Divisor2;
14723 EVT VT =
N->getValueType(0);
14730 if (
N->getOperand(0).getOpcode() !=
ISD::AND ||
14731 N->getOperand(0).getOperand(0).getOpcode() !=
ISD::SRL)
14744 if (!V1.
isMask(HalfSize) || V2 != (1ULL | 1ULL << HalfSize) ||
14745 V3 != (HalfSize - 1))
14761 EVT VT =
N->getValueType(0);
14769 unsigned AddSubOpc;
14775 auto IsAddSubWith1 = [&](
SDValue V) ->
bool {
14776 AddSubOpc = V->getOpcode();
14778 SDValue Opnd = V->getOperand(1);
14779 MulOper = V->getOperand(0);
14788 if (IsAddSubWith1(N0)) {
14790 return DAG.
getNode(AddSubOpc,
DL, VT, N1, MulVal);
14793 if (IsAddSubWith1(N1)) {
14795 return DAG.
getNode(AddSubOpc,
DL, VT, N0, MulVal);
14810 if (isIndexTypeSigned(IndexType))
14813 if (!
N->hasOneUse())
14816 EVT VT =
N.getValueType();
14855 EVT SrcVT = Src.getValueType();
14859 NewElen = std::max(NewElen, 8U);
14882 EVT VT =
N->getValueType(0);
14885 if (OpVT != MVT::i64 || !Subtarget.
is64Bit())
14889 auto *N1C = dyn_cast<ConstantSDNode>(N1);
14901 if (!isIntEqualitySetCC(
Cond))
14910 const APInt &C1 = N1C->getAPIntValue();
14928 EVT VT =
N->getValueType(0);
14929 EVT SrcVT = cast<VTSDNode>(
N->getOperand(1))->
getVT();
14930 unsigned Opc = Src.getOpcode();
14935 Subtarget.hasStdExtZfhmin())
14937 Src.getOperand(0));
14941 VT == MVT::i64 && !isa<ConstantSDNode>(Src.getOperand(1)) &&
14944 Src.getOperand(1));
14952struct CombineResult;
14954enum ExtKind :
uint8_t { ZExt = 1 << 0, SExt = 1 << 1, FPExt = 1 << 2 };
14981struct NodeExtensionHelper {
14990 bool SupportsFPExt;
14993 bool EnforceOneUse;
15008 return OrigOperand;
15019 unsigned getExtOpc(ExtKind SupportsExt)
const {
15020 switch (SupportsExt) {
15021 case ExtKind::SExt:
15023 case ExtKind::ZExt:
15025 case ExtKind::FPExt:
15036 std::optional<ExtKind> SupportsExt)
const {
15037 if (!SupportsExt.has_value())
15038 return OrigOperand;
15040 MVT NarrowVT = getNarrowType(Root, *SupportsExt);
15044 if (
Source.getValueType() == NarrowVT)
15048 if (
Source.getValueType().getVectorElementType() == MVT::bf16) {
15054 unsigned ExtOpc = getExtOpc(*SupportsExt);
15058 auto [
Mask, VL] = getMaskAndVL(Root, DAG, Subtarget);
15065 return DAG.
getNode(ExtOpc,
DL, NarrowVT, Source, Mask, VL);
15077 DAG.
getUNDEF(NarrowVT), Source, VL);
15090 static MVT getNarrowType(
const SDNode *Root, ExtKind SupportsExt) {
15096 MVT EltVT = SupportsExt == ExtKind::FPExt
15098 :
MVT::getIntegerVT(NarrowSize);
15100 assert((
int)NarrowSize >= (SupportsExt == ExtKind::FPExt ? 16 : 8) &&
15101 "Trying to extend something we can't represent");
15108 static unsigned getSExtOpcode(
unsigned Opcode) {
15131 static unsigned getZExtOpcode(
unsigned Opcode) {
15157 static unsigned getFPExtOpcode(
unsigned Opcode) {
15182 static unsigned getSUOpcode(
unsigned Opcode) {
15184 "SU is only supported for MUL");
15190 static unsigned getWOpcode(
unsigned Opcode, ExtKind SupportsExt) {
15210 using CombineToTry = std::function<std::optional<CombineResult>(
15211 SDNode * ,
const NodeExtensionHelper & ,
15216 bool needToPromoteOtherUsers()
const {
return EnforceOneUse; }
15220 unsigned Opc = OrigOperand.
getOpcode();
15224 "Unexpected Opcode");
15237 unsigned ScalarBits =
Op.getValueSizeInBits();
15239 if (ScalarBits < EltBits) {
15242 !Subtarget.
is64Bit() &&
"Unexpected splat");
15244 SupportsSExt =
true;
15248 SupportsZExt =
true;
15250 EnforceOneUse =
false;
15254 unsigned NarrowSize = EltBits / 2;
15257 if (NarrowSize < 8)
15261 SupportsSExt =
true;
15265 SupportsZExt =
true;
15267 EnforceOneUse =
false;
15270 bool isSupportedFPExtend(
SDNode *Root,
MVT NarrowEltVT,
15277 if (NarrowEltVT == MVT::bf16 && (!Subtarget.hasStdExtZvfbfwma() ||
15287 SupportsZExt =
false;
15288 SupportsSExt =
false;
15289 SupportsFPExt =
false;
15290 EnforceOneUse =
true;
15291 unsigned Opc = OrigOperand.
getOpcode();
15313 SupportsZExt =
true;
15316 SupportsSExt =
true;
15321 if (!isSupportedFPExtend(Root, NarrowEltVT, Subtarget))
15323 SupportsFPExt =
true;
15328 fillUpExtensionSupportForSplat(Root, DAG, Subtarget);
15340 if (!isSupportedFPExtend(Root,
Op.getOperand(0).getSimpleValueType(),
15345 unsigned ScalarBits =
Op.getOperand(0).getValueSizeInBits();
15346 if (NarrowSize != ScalarBits)
15349 SupportsFPExt =
true;
15358 static bool isSupportedRoot(
const SDNode *Root,
15387 Subtarget.hasStdExtZvbb();
15389 return Subtarget.hasStdExtZvbb();
15403 assert(isSupportedRoot(Root, Subtarget) &&
15404 "Trying to build an helper with an "
15405 "unsupported root");
15406 assert(OperandIdx < 2 &&
"Requesting something else than LHS or RHS");
15422 if (OperandIdx == 1) {
15431 EnforceOneUse =
false;
15436 fillUpExtensionSupport(Root, DAG, Subtarget);
15442 static std::pair<SDValue, SDValue>
15445 assert(isSupportedRoot(Root, Subtarget) &&
"Unexpected root");
15464 switch (
N->getOpcode()) {
15506struct CombineResult {
15508 unsigned TargetOpcode;
15510 std::optional<ExtKind> LHSExt;
15511 std::optional<ExtKind> RHSExt;
15515 NodeExtensionHelper
LHS;
15517 NodeExtensionHelper
RHS;
15519 CombineResult(
unsigned TargetOpcode,
SDNode *Root,
15520 const NodeExtensionHelper &
LHS, std::optional<ExtKind> LHSExt,
15521 const NodeExtensionHelper &
RHS, std::optional<ExtKind> RHSExt)
15522 : TargetOpcode(TargetOpcode), LHSExt(LHSExt), RHSExt(RHSExt), Root(Root),
15531 std::tie(Mask, VL) =
15532 NodeExtensionHelper::getMaskAndVL(Root, DAG, Subtarget);
15546 LHS.getOrCreateExtendedOp(Root, DAG, Subtarget, LHSExt),
15547 RHS.getOrCreateExtendedOp(Root, DAG, Subtarget, RHSExt),
15548 Passthru, Mask, VL);
15562static std::optional<CombineResult>
15563canFoldToVWWithSameExtensionImpl(
SDNode *Root,
const NodeExtensionHelper &LHS,
15564 const NodeExtensionHelper &RHS,
15567 if ((AllowExtMask & ExtKind::ZExt) &&
LHS.SupportsZExt &&
RHS.SupportsZExt)
15568 return CombineResult(NodeExtensionHelper::getZExtOpcode(Root->
getOpcode()),
15569 Root, LHS, {ExtKind::ZExt}, RHS,
15571 if ((AllowExtMask & ExtKind::SExt) &&
LHS.SupportsSExt &&
RHS.SupportsSExt)
15572 return CombineResult(NodeExtensionHelper::getSExtOpcode(Root->
getOpcode()),
15573 Root, LHS, {ExtKind::SExt}, RHS,
15575 if ((AllowExtMask & ExtKind::FPExt) &&
LHS.SupportsFPExt &&
RHS.SupportsFPExt)
15576 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
15577 Root, LHS, {ExtKind::FPExt}, RHS,
15579 return std::nullopt;
15588static std::optional<CombineResult>
15589canFoldToVWWithSameExtension(
SDNode *Root,
const NodeExtensionHelper &LHS,
15592 return canFoldToVWWithSameExtensionImpl(
15593 Root, LHS, RHS, ExtKind::ZExt | ExtKind::SExt | ExtKind::FPExt, DAG,
15601static std::optional<CombineResult>
15602canFoldToVW_W(
SDNode *Root,
const NodeExtensionHelper &LHS,
15605 if (
RHS.SupportsFPExt)
15606 return CombineResult(
15607 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::FPExt),
15608 Root, LHS, std::nullopt, RHS, {ExtKind::FPExt});
15615 return CombineResult(
15616 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::ZExt), Root,
15617 LHS, std::nullopt, RHS, {ExtKind::ZExt});
15619 return CombineResult(
15620 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::SExt), Root,
15621 LHS, std::nullopt, RHS, {ExtKind::SExt});
15622 return std::nullopt;
15629static std::optional<CombineResult>
15630canFoldToVWWithSEXT(
SDNode *Root,
const NodeExtensionHelper &LHS,
15633 return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::SExt, DAG,
15641static std::optional<CombineResult>
15642canFoldToVWWithZEXT(
SDNode *Root,
const NodeExtensionHelper &LHS,
15645 return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::ZExt, DAG,
15653static std::optional<CombineResult>
15654canFoldToVWWithFPEXT(
SDNode *Root,
const NodeExtensionHelper &LHS,
15657 return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::FPExt, DAG,
15665static std::optional<CombineResult>
15666canFoldToVW_SU(
SDNode *Root,
const NodeExtensionHelper &LHS,
15670 if (!
LHS.SupportsSExt || !
RHS.SupportsZExt)
15671 return std::nullopt;
15672 return CombineResult(NodeExtensionHelper::getSUOpcode(Root->
getOpcode()),
15673 Root, LHS, {ExtKind::SExt}, RHS,
15678NodeExtensionHelper::getSupportedFoldings(
const SDNode *Root) {
15689 Strategies.
push_back(canFoldToVWWithSameExtension);
15698 Strategies.
push_back(canFoldToVWWithSameExtension);
15703 Strategies.
push_back(canFoldToVWWithSameExtension);
15710 Strategies.
push_back(canFoldToVWWithZEXT);
15715 Strategies.
push_back(canFoldToVWWithSEXT);
15720 Strategies.
push_back(canFoldToVWWithZEXT);
15725 Strategies.
push_back(canFoldToVWWithFPEXT);
15754 if (!NodeExtensionHelper::isSupportedRoot(
N, Subtarget))
15760 Inserted.insert(
N);
15763 while (!Worklist.
empty()) {
15766 NodeExtensionHelper
LHS(Root, 0, DAG, Subtarget);
15767 NodeExtensionHelper
RHS(Root, 1, DAG, Subtarget);
15768 auto AppendUsersIfNeeded = [&Worklist, &Subtarget,
15769 &Inserted](
const NodeExtensionHelper &
Op) {
15770 if (
Op.needToPromoteOtherUsers()) {
15773 if (!NodeExtensionHelper::isSupportedRoot(TheUser, Subtarget))
15778 if (Inserted.insert(TheUser).second)
15791 NodeExtensionHelper::getSupportedFoldings(Root);
15793 assert(!FoldingStrategies.
empty() &&
"Nothing to be folded");
15794 bool Matched =
false;
15795 for (
int Attempt = 0;
15796 (Attempt != 1 + NodeExtensionHelper::isCommutative(Root)) && !Matched;
15799 for (NodeExtensionHelper::CombineToTry FoldingStrategy :
15800 FoldingStrategies) {
15801 std::optional<CombineResult> Res =
15802 FoldingStrategy(Root,
LHS,
RHS, DAG, Subtarget);
15809 if (Res->LHSExt.has_value())
15810 if (!AppendUsersIfNeeded(
LHS))
15812 if (Res->RHSExt.has_value())
15813 if (!AppendUsersIfNeeded(
RHS))
15825 SDValue InputRootReplacement;
15832 for (CombineResult Res : CombinesToApply) {
15833 SDValue NewValue = Res.materialize(DAG, Subtarget);
15834 if (!InputRootReplacement) {
15836 "First element is expected to be the current node");
15837 InputRootReplacement = NewValue;
15842 for (std::pair<SDValue, SDValue> OldNewValues : ValuesToReplace) {
15846 return InputRootReplacement;
15853 unsigned Opc =
N->getOpcode();
15858 SDValue MergeOp =
N->getOperand(1);
15859 unsigned MergeOpc = MergeOp.
getOpcode();
15870 SDValue Passthru =
N->getOperand(2);
15884 Z = Z.getOperand(1);
15890 {Y, X, Y, MergeOp->getOperand(0), N->getOperand(4)},
15897 [[maybe_unused]]
unsigned Opc =
N->getOpcode();
15926 EVT NewMemVT = (MemVT == MVT::i32) ? MVT::i64 : MVT::i128;
15932 auto Ext = cast<LoadSDNode>(LSNode1)->getExtensionType();
15934 if (MemVT == MVT::i32)
15940 Opcode,
SDLoc(LSNode1), DAG.
getVTList({XLenVT, XLenVT, MVT::Other}),
15975 if (!Subtarget.hasVendorXTHeadMemPair())
15987 auto ExtractBaseAndOffset = [](
SDValue Ptr) -> std::pair<SDValue, uint64_t> {
15989 if (
auto *C1 = dyn_cast<ConstantSDNode>(
Ptr->getOperand(1)))
15990 return {
Ptr->getOperand(0), C1->getZExtValue()};
15994 auto [Base1, Offset1] = ExtractBaseAndOffset(LSNode1->
getOperand(OpNum));
16015 auto [Base2, Offset2] = ExtractBaseAndOffset(LSNode2->
getOperand(OpNum));
16018 if (Base1 != Base2)
16022 bool Valid =
false;
16023 if (MemVT == MVT::i32) {
16025 if ((Offset1 + 4 == Offset2) && isShiftedUInt<2, 3>(Offset1))
16027 }
else if (MemVT == MVT::i64) {
16029 if ((Offset1 + 8 == Offset2) && isShiftedUInt<2, 4>(Offset1))
16063 if (Src->isStrictFPOpcode())
16071 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
16081 EVT VT =
N->getValueType(0);
16084 MVT SrcVT = Src.getSimpleValueType();
16085 MVT SrcContainerVT = SrcVT;
16087 SDValue XVal = Src.getOperand(0);
16114 FpToInt = DAG.
getNode(Opc,
DL, ContainerVT, XVal, Mask, VL);
16118 FpToInt = DAG.
getNode(Opc,
DL, ContainerVT, XVal, Mask,
16131 if (VT != MVT::i32 && VT != XLenVT)
16161 EVT DstVT =
N->getValueType(0);
16162 if (DstVT != XLenVT)
16168 if (Src->isStrictFPOpcode())
16176 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
16179 EVT SatVT = cast<VTSDNode>(
N->getOperand(1))->getVT();
16188 if (SatVT == DstVT)
16190 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
16196 Src = Src.getOperand(0);
16217 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected extension");
16223 EVT VT =
N->getValueType(0);
16278 unsigned Offset = IsStrict ? 1 : 0;
16285 auto invertIfNegative = [&Mask, &VL](
SDValue &V) {
16287 V.getOperand(2) == VL) {
16289 V = V.getOperand(0);
16296 bool NegA = invertIfNegative(
A);
16297 bool NegB = invertIfNegative(
B);
16298 bool NegC = invertIfNegative(
C);
16301 if (!NegA && !NegB && !NegC)
16307 {N->getOperand(0), A, B, C, Mask, VL});
16331 EVT VT =
N->getValueType(0);
16336 if (!isa<ConstantSDNode>(
N->getOperand(1)))
16338 uint64_t ShAmt =
N->getConstantOperandVal(1);
16346 cast<VTSDNode>(N0.
getOperand(1))->getVT().getSizeInBits();
16351 if (LShAmt < ExtSize) {
16364 if (ShAmt > 32 || VT != MVT::i64)
16380 AddC = dyn_cast<ConstantSDNode>(N0.
getOperand(IsAdd ? 1 : 0));
16393 !isa<ConstantSDNode>(U->getOperand(1)) ||
16394 U->getConstantOperandVal(1) > 32)
16449 if (!
Cond.hasOneUse())
16468 EVT VT =
Cond.getValueType();
16513 LHS =
LHS.getOperand(0);
16523 LHS.getOperand(0).getValueType() == Subtarget.
getXLenVT()) {
16527 CCVal = cast<CondCodeSDNode>(
LHS.getOperand(2))->get();
16531 RHS =
LHS.getOperand(1);
16532 LHS =
LHS.getOperand(0);
16541 RHS =
LHS.getOperand(1);
16542 LHS =
LHS.getOperand(0);
16558 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
16599 bool Commutative =
true;
16600 unsigned Opc = TrueVal.getOpcode();
16608 Commutative =
false;
16616 if (!TrueVal.hasOneUse() || isa<ConstantSDNode>(FalseVal))
16620 if (FalseVal == TrueVal.getOperand(0))
16622 else if (Commutative && FalseVal == TrueVal.getOperand(1))
16627 EVT VT =
N->getValueType(0);
16629 SDValue OtherOp = TrueVal.getOperand(1 - OpToFold);
16635 assert(IdentityOperand &&
"No identity operand!");
16640 DAG.
getSelect(
DL, OtherOpVT,
N->getOperand(0), OtherOp, IdentityOperand);
16641 return DAG.
getNode(TrueVal.getOpcode(),
DL, VT, FalseVal, NewSel);
16662 CountZeroes =
N->getOperand(2);
16663 ValOnZero =
N->getOperand(1);
16665 CountZeroes =
N->getOperand(1);
16666 ValOnZero =
N->getOperand(2);
16685 if (
Cond->getOperand(0) != CountZeroesArgument)
16701 CountZeroes, BitWidthMinusOne);
16711 EVT VT =
N->getValueType(0);
16712 EVT CondVT =
Cond.getValueType();
16720 (Subtarget.hasStdExtZicond() || Subtarget.hasVendorXVentanaCondOps())) {
16726 const APInt &MaskVal =
LHS.getConstantOperandAPInt(1);
16747 SDValue TrueVal =
N->getOperand(1);
16748 SDValue FalseVal =
N->getOperand(2);
16763 EVT VT =
N->getValueType(0);
16770 const unsigned Opcode =
N->op_begin()->getNode()->getOpcode();
16785 if (
Op.isUndef()) {
16798 if (
Op.getOpcode() != Opcode || !
Op.hasOneUse())
16802 if (!isa<ConstantSDNode>(
Op.getOperand(1)) &&
16803 !isa<ConstantFPSDNode>(
Op.getOperand(1)))
16807 if (
Op.getOperand(0).getValueType() !=
Op.getOperand(1).getValueType())
16835 const unsigned InVecOpcode = InVec->
getOpcode();
16845 if (!isa<ConstantSDNode>(InValRHS) && !isa<ConstantFPSDNode>(InValRHS))
16852 InVecLHS, InValLHS, EltNo);
16854 InVecRHS, InValRHS, EltNo);
16863 auto *IndexC = dyn_cast<ConstantSDNode>(EltNo);
16866 unsigned Elt = IndexC->getZExtValue();
16874 unsigned ConcatOpIdx = Elt / ConcatNumElts;
16877 ConcatOp, InVal, NewIdx);
16881 ConcatOps[ConcatOpIdx] = ConcatOp;
16893 EVT VT =
N->getValueType(0);
16903 auto *BaseLd = dyn_cast<LoadSDNode>(
N->getOperand(0));
16905 !
SDValue(BaseLd, 0).hasOneUse())
16908 EVT BaseLdVT = BaseLd->getValueType(0);
16915 auto *Ld = dyn_cast<LoadSDNode>(
Op);
16916 if (!Ld || !Ld->isSimple() || !
Op.hasOneUse() ||
16918 Ld->getValueType(0) != BaseLdVT)
16927 using PtrDiff = std::pair<std::variant<int64_t, SDValue>,
bool>;
16929 LoadSDNode *Ld2) -> std::optional<PtrDiff> {
16934 if (BIO1.equalBaseIndex(BIO2, DAG))
16939 SDValue P2 = Ld2->getBasePtr();
16945 return std::nullopt;
16949 auto BaseDiff = GetPtrDiff(Lds[0], Lds[1]);
16954 for (
auto *It = Lds.
begin() + 1; It != Lds.
end() - 1; It++)
16955 if (GetPtrDiff(*It, *std::next(It)) != BaseDiff)
16963 unsigned WideScalarBitWidth =
16976 auto [StrideVariant, MustNegateStride] = *BaseDiff;
16978 std::holds_alternative<SDValue>(StrideVariant)
16979 ? std::get<SDValue>(StrideVariant)
16982 if (MustNegateStride)
16990 if (
auto *ConstStride = dyn_cast<ConstantSDNode>(Stride);
16991 ConstStride && ConstStride->getSExtValue() >= 0)
16995 ConstStride->getSExtValue() * (
N->getNumOperands() - 1);
17001 BaseLd->getPointerInfo(), BaseLd->getMemOperand()->getFlags(), MemSize,
17005 WideVecVT,
DL, BaseLd->getChain(), BaseLd->getBasePtr(), Stride,
17020 if (
N->getValueType(0).isFixedLengthVector())
17023 SDValue Addend =
N->getOperand(0);
17027 SDValue AddPassthruOp =
N->getOperand(2);
17028 if (!AddPassthruOp.
isUndef())
17032 auto IsVWMulOpc = [](
unsigned Opc) {
17051 if (!MulPassthruOp.
isUndef())
17061 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
17062 }(
N, DAG, Subtarget);
17067 if (AddMask != MulMask || AddVL != MulVL)
17072 "Unexpected opcode after VWMACC_VL");
17074 "Unexpected opcode after VWMACC_VL!");
17076 "Unexpected opcode after VWMUL_VL!");
17078 "Unexpected opcode after VWMUL_VL!");
17081 EVT VT =
N->getValueType(0);
17097 const EVT IndexVT = Index.getValueType();
17101 if (!isIndexTypeSigned(IndexType))
17133 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
17136 if (Index->getOperand(i)->isUndef())
17138 uint64_t C = Index->getConstantOperandVal(i);
17139 if (
C % ElementSize != 0)
17141 C =
C / ElementSize;
17145 ActiveLanes.
set(
C);
17147 return ActiveLanes.
all();
17165 if (NumElems % 2 != 0)
17169 const unsigned WiderElementSize = ElementSize * 2;
17170 if (WiderElementSize > ST.getELen()/8)
17173 if (!ST.enableUnalignedVectorMem() && BaseAlign < WiderElementSize)
17176 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
17179 if (Index->getOperand(i)->isUndef())
17183 uint64_t C = Index->getConstantOperandVal(i);
17185 if (
C % WiderElementSize != 0)
17190 if (
C !=
Last + ElementSize)
17207 (isa<RegisterSDNode>(VL) &&
17208 cast<RegisterSDNode>(VL)->getReg() == RISCV::X0);
17210 Mask.getOperand(0) != VL)
17213 auto IsTruncNode = [&](
SDValue V) {
17215 V.getOperand(1) == Mask && V.getOperand(2) == VL;
17222 while (IsTruncNode(
Op)) {
17223 if (!
Op.hasOneUse())
17225 Op =
Op.getOperand(0);
17260 MVT VT =
N->getSimpleValueType(0);
17265 auto MatchMinMax = [&VL, &Mask](
SDValue V,
unsigned Opc,
unsigned OpcVL,
17267 if (V.getOpcode() != Opc &&
17268 !(V.getOpcode() == OpcVL && V.getOperand(2).isUndef() &&
17269 V.getOperand(3) == Mask && V.getOperand(4) == VL))
17277 Op.getOperand(1).getValueType().isFixedLengthVector() &&
17279 Op.getOperand(1).getOperand(0).getValueType() ==
Op.getValueType() &&
17281 Op =
Op.getOperand(1).getOperand(0);
17284 return V.getOperand(0);
17287 Op.getOperand(2) == VL) {
17288 if (
auto *Op1 = dyn_cast<ConstantSDNode>(
Op.getOperand(1))) {
17290 Op1->getAPIntValue().sextOrTrunc(
Op.getScalarValueSizeInBits());
17291 return V.getOperand(0);
17300 auto DetectUSatPattern = [&](
SDValue V) {
17325 V.getOperand(1), DAG.
getUNDEF(V.getValueType()),
17331 auto DetectSSatPattern = [&](
SDValue V) {
17333 unsigned NumSrcBits = V.getScalarValueSizeInBits();
17341 if (HiC == SignedMax && LoC == SignedMin)
17347 if (HiC == SignedMax && LoC == SignedMin)
17357 Src.getOperand(1) == Mask && Src.getOperand(2) == VL &&
17359 Src = Src.getOperand(0);
17363 if ((Val = DetectUSatPattern(Src)))
17365 else if ((Val = DetectSSatPattern(Src)))
17375 Val = DAG.
getNode(ClipOpc,
DL, ValVT, Val, Mask, VL);
17376 }
while (ValVT != VT);
17390 EVT VT =
N->getValueType(0);
17398 Src = Src.getOperand(0);
17403 Src = Src.getOperand(0);
17404 EVT SrcEVT = Src.getValueType();
17436 auto SimplifyDemandedLowBitsHelper = [&](
unsigned OpNo,
unsigned LowBits) {
17447 switch (
N->getOpcode()) {
17467 APInt V =
C->getValueAPF().bitcastToAPInt();
17502 if (SimplifyDemandedLowBitsHelper(0, 32) ||
17503 SimplifyDemandedLowBitsHelper(1, 5))
17511 if (SimplifyDemandedLowBitsHelper(0, 32))
17528 MVT VT =
N->getSimpleValueType(0);
17531 if (
auto *CFP = dyn_cast<ConstantFPSDNode>(Op0)) {
17544 "Unexpected value type!");
17549 cast<LoadSDNode>(Op0)->isSimple()) {
17551 auto *LN0 = cast<LoadSDNode>(Op0);
17554 LN0->getBasePtr(), IVT, LN0->getMemOperand());
17578 EVT VT =
N->getValueType(0);
17631 if (!
C || !
C->getValueAPF().isExactlyValue(+1.0))
17633 EVT VT =
N->getValueType(0);
17662 if (
N->getValueType(0) == MVT::i64 && Subtarget.
is64Bit()) {
17667 Src.getOperand(0));
17672 Src.getOperand(0), Src.getOperand(1));
17693 unsigned Opc =
N->getOpcode();
17708 return DAG.
getNode(InvOpc,
SDLoc(
N),
N->getValueType(0), Val, NewCond);
17718 N->getValueType(0), Val,
Cond.getOperand(0));
17729 SDValue FalseV =
N->getOperand(4);
17731 EVT VT =
N->getValueType(0);
17734 if (TrueV == FalseV)
17739 if (!Subtarget.hasShortForwardBranchOpt() && isa<ConstantSDNode>(TrueV) &&
17745 int64_t TrueSImm = cast<ConstantSDNode>(TrueV)->getSExtValue();
17746 int64_t FalseSImm = cast<ConstantSDNode>(FalseV)->getSExtValue();
17749 if (isInt<12>(TrueSImm) && isInt<12>(FalseSImm) &&
17750 isInt<12>(TrueSImm - FalseSImm)) {
17766 {LHS, RHS, CC, TrueV, FalseV});
17833 N->getOperand(0),
LHS,
RHS,
CC,
N->getOperand(4));
17846 EVT VT =
N->getValueType(0);
17870 const auto *MGN = cast<MaskedGatherSDNode>(
N);
17871 const EVT VT =
N->getValueType(0);
17872 SDValue Index = MGN->getIndex();
17873 SDValue ScaleOp = MGN->getScale();
17875 assert(!MGN->isIndexScaled() &&
17876 "Scaled gather/scatter should not be formed");
17881 N->getVTList(), MGN->getMemoryVT(),
DL,
17882 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
17883 MGN->getBasePtr(), Index, ScaleOp},
17884 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
17888 N->getVTList(), MGN->getMemoryVT(),
DL,
17889 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
17890 MGN->getBasePtr(), Index, ScaleOp},
17891 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
17897 if (std::optional<VIDSequence> SimpleVID =
17899 SimpleVID && SimpleVID->StepDenominator == 1) {
17900 const int64_t StepNumerator = SimpleVID->StepNumerator;
17901 const int64_t Addend = SimpleVID->Addend;
17908 assert(MGN->getBasePtr()->getValueType(0) == PtrVT);
17916 VT,
DL, MGN->getChain(), BasePtr,
17918 EVL, MGN->getMemOperand());
17920 StridedLoad, MGN->getPassThru(), EVL);
17930 MGN->getBasePtr(), DAG.
getUNDEF(XLenVT),
17932 MGN->getMemoryVT(), MGN->getMemOperand(),
17941 MGN->getMemOperand()->getBaseAlign(), Subtarget)) {
17943 for (
unsigned i = 0; i < Index->getNumOperands(); i += 2)
17944 NewIndices.
push_back(Index.getOperand(i));
17945 EVT IndexVT = Index.getValueType()
17946 .getHalfNumVectorElementsVT(*DAG.
getContext());
17952 assert(EltCnt.isKnownEven() &&
"Splitting vector, but not in half!");
17954 EltCnt.divideCoefficientBy(2));
17957 EltCnt.divideCoefficientBy(2));
17962 {MGN->getChain(), Passthru, Mask, MGN->getBasePtr(),
17971 const auto *MSN = cast<MaskedScatterSDNode>(
N);
17972 SDValue Index = MSN->getIndex();
17973 SDValue ScaleOp = MSN->getScale();
17975 assert(!MSN->isIndexScaled() &&
17976 "Scaled gather/scatter should not be formed");
17981 N->getVTList(), MSN->getMemoryVT(),
DL,
17982 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
17984 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
17988 N->getVTList(), MSN->getMemoryVT(),
DL,
17989 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
17991 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
17993 EVT VT = MSN->getValue()->getValueType(0);
17995 if (!MSN->isTruncatingStore() &&
17999 return DAG.
getMaskedStore(MSN->getChain(),
DL, Shuffle, MSN->getBasePtr(),
18000 DAG.
getUNDEF(XLenVT), MSN->getMask(),
18001 MSN->getMemoryVT(), MSN->getMemOperand(),
18006 case ISD::VP_GATHER: {
18007 const auto *VPGN = cast<VPGatherSDNode>(
N);
18008 SDValue Index = VPGN->getIndex();
18009 SDValue ScaleOp = VPGN->getScale();
18011 assert(!VPGN->isIndexScaled() &&
18012 "Scaled gather/scatter should not be formed");
18017 {VPGN->getChain(), VPGN->getBasePtr(), Index,
18018 ScaleOp, VPGN->getMask(),
18019 VPGN->getVectorLength()},
18020 VPGN->getMemOperand(), IndexType);
18024 {VPGN->getChain(), VPGN->getBasePtr(), Index,
18025 ScaleOp, VPGN->getMask(),
18026 VPGN->getVectorLength()},
18027 VPGN->getMemOperand(), IndexType);
18031 case ISD::VP_SCATTER: {
18032 const auto *VPSN = cast<VPScatterSDNode>(
N);
18033 SDValue Index = VPSN->getIndex();
18034 SDValue ScaleOp = VPSN->getScale();
18036 assert(!VPSN->isIndexScaled() &&
18037 "Scaled gather/scatter should not be formed");
18042 {VPSN->getChain(), VPSN->getValue(),
18043 VPSN->getBasePtr(), Index, ScaleOp,
18044 VPSN->getMask(), VPSN->getVectorLength()},
18045 VPSN->getMemOperand(), IndexType);
18049 {VPSN->getChain(), VPSN->getValue(),
18050 VPSN->getBasePtr(), Index, ScaleOp,
18051 VPSN->getMask(), VPSN->getVectorLength()},
18052 VPSN->getMemOperand(), IndexType);
18066 EVT VT =
N->getValueType(0);
18069 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt,
18070 N->getOperand(2),
N->getOperand(3),
N->getOperand(4));
18088 EVT VT =
N->getValueType(0);
18092 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt);
18132 auto *Store = cast<StoreSDNode>(
N);
18133 SDValue Chain = Store->getChain();
18134 EVT MemVT = Store->getMemoryVT();
18135 SDValue Val = Store->getValue();
18138 bool IsScalarizable =
18140 Store->isSimple() &&
18170 NewVT, *Store->getMemOperand())) {
18172 return DAG.
getStore(Chain,
DL, NewV, Store->getBasePtr(),
18173 Store->getPointerInfo(), Store->getOriginalAlign(),
18174 Store->getMemOperand()->getFlags());
18182 if (
auto *L = dyn_cast<LoadSDNode>(Val);
18184 L->hasNUsesOfValue(1, 0) && L->hasNUsesOfValue(1, 1) &&
18186 L->getMemoryVT() == MemVT) {
18189 NewVT, *Store->getMemOperand()) &&
18191 NewVT, *L->getMemOperand())) {
18193 L->getPointerInfo(), L->getOriginalAlign(),
18194 L->getMemOperand()->getFlags());
18195 return DAG.
getStore(Chain,
DL, NewL, Store->getBasePtr(),
18196 Store->getPointerInfo(), Store->getOriginalAlign(),
18197 Store->getMemOperand()->getFlags());
18209 MVT VecVT = Src.getSimpleValueType();
18216 Store->getChain(),
DL, Src, Store->getBasePtr(), Store->getOffset(),
18219 Store->getMemOperand(), Store->getAddressingMode(),
18220 Store->isTruncatingStore(),
false);
18227 EVT VT =
N->getValueType(0);
18249 const MVT VT =
N->getSimpleValueType(0);
18250 SDValue Passthru =
N->getOperand(0);
18251 SDValue Scalar =
N->getOperand(1);
18260 const MVT VT =
N->getSimpleValueType(0);
18261 SDValue Passthru =
N->getOperand(0);
18262 SDValue Scalar =
N->getOperand(1);
18267 unsigned ScalarSize = Scalar.getValueSizeInBits();
18269 if (ScalarSize > EltWidth && Passthru.
isUndef())
18270 if (SimplifyDemandedLowBitsHelper(1, EltWidth))
18277 (!Const || Const->isZero() ||
18278 !Const->getAPIntValue().sextOrTrunc(EltWidth).isSignedIntN(5)))
18288 if (
N->getOperand(0).isUndef() &&
18291 Src.getOperand(0).getValueType().isScalableVector()) {
18292 EVT VT =
N->getValueType(0);
18293 EVT SrcVT = Src.getOperand(0).getValueType();
18297 return Src.getOperand(0);
18303 const MVT VT =
N->getSimpleValueType(0);
18304 SDValue Passthru =
N->getOperand(0);
18305 SDValue Scalar =
N->getOperand(1);
18309 Scalar.getOperand(0).getValueType() ==
N->getValueType(0))
18310 return Scalar.getOperand(0);
18319 DAG.
getNode(
N->getOpcode(),
DL, M1VT, M1Passthru, Scalar, VL);
18329 Const && !Const->isZero() && isInt<5>(Const->getSExtValue()) &&
18337 MVT VecVT =
N->getOperand(0).getSimpleValueType();
18339 if (M1VT.
bitsLT(VecVT)) {
18350 unsigned IntNo =
N->getConstantOperandVal(IntOpNo);
18355 case Intrinsic::riscv_vcpop:
18356 case Intrinsic::riscv_vcpop_mask:
18357 case Intrinsic::riscv_vfirst:
18358 case Intrinsic::riscv_vfirst_mask: {
18360 if (IntNo == Intrinsic::riscv_vcpop_mask ||
18361 IntNo == Intrinsic::riscv_vfirst_mask)
18362 VL =
N->getOperand(3);
18367 EVT VT =
N->getValueType(0);
18368 if (IntNo == Intrinsic::riscv_vfirst ||
18369 IntNo == Intrinsic::riscv_vfirst_mask)
18378 EVT VT =
N->getValueType(0);
18389 for (
unsigned i = 0; i < NF; ++i)
18396 if ((SrcVT == MVT::v1i1 || SrcVT == MVT::v2i1 || SrcVT == MVT::v4i1) &&
18419 EVT XVT,
unsigned KeptBits)
const {
18424 if (XVT != MVT::i32 && XVT != MVT::i64)
18428 if (KeptBits == 32 || KeptBits == 64)
18432 return Subtarget.hasStdExtZbb() &&
18433 ((KeptBits == 8 && XVT == MVT::i64 && !Subtarget.
is64Bit()) ||
18441 "Expected shift op");
18459 if (!isa<StoreSDNode>(
Use) && !isa<LoadSDNode>(
Use))
18468 return isUsedByLdSt(N0.
getNode(),
N);
18470 auto *C1 = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
18471 auto *C2 = dyn_cast<ConstantSDNode>(
N->getOperand(1));
18474 if (Subtarget.hasStdExtZba() && C2 && C2->getZExtValue() >= 1 &&
18475 C2->getZExtValue() <= 3 &&
N->hasOneUse() &&
18476 N->user_begin()->getOpcode() ==
ISD::ADD &&
18477 !isUsedByLdSt(*
N->user_begin(),
nullptr) &&
18478 !isa<ConstantSDNode>(
N->user_begin()->getOperand(1)))
18482 const APInt &C1Int = C1->getAPIntValue();
18483 APInt ShiftedC1Int = C1Int << C2->getAPIntValue();
18509 if (C1Cost < ShiftedC1Cost)
18532 EVT VT =
Op.getValueType();
18536 unsigned Opcode =
Op.getOpcode();
18544 const APInt &Mask =
C->getAPIntValue();
18553 auto IsLegalMask = [ShrunkMask, ExpandedMask](
const APInt &Mask) ->
bool {
18554 return ShrunkMask.
isSubsetOf(Mask) && Mask.isSubsetOf(ExpandedMask);
18556 auto UseMask = [Mask,
Op, &TLO](
const APInt &NewMask) ->
bool {
18557 if (NewMask == Mask)
18562 Op.getOperand(0), NewC);
18575 APInt NewMask =
APInt(Mask.getBitWidth(), 0xffff);
18576 if (IsLegalMask(NewMask))
18577 return UseMask(NewMask);
18580 if (VT == MVT::i64) {
18582 if (IsLegalMask(NewMask))
18583 return UseMask(NewMask);
18598 APInt NewMask = ShrunkMask;
18599 if (MinSignedBits <= 12)
18601 else if (!
C->isOpaque() && MinSignedBits <= 32 && !ShrunkMask.
isSignedIntN(32))
18607 assert(IsLegalMask(NewMask));
18608 return UseMask(NewMask);
18612 static const uint64_t GREVMasks[] = {
18613 0x5555555555555555ULL, 0x3333333333333333ULL, 0x0F0F0F0F0F0F0F0FULL,
18614 0x00FF00FF00FF00FFULL, 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL};
18616 for (
unsigned Stage = 0; Stage != 6; ++Stage) {
18617 unsigned Shift = 1 << Stage;
18618 if (ShAmt & Shift) {
18620 uint64_t Res = ((x & Mask) << Shift) | ((x >> Shift) & Mask);
18632 const APInt &DemandedElts,
18634 unsigned Depth)
const {
18636 unsigned Opc =
Op.getOpcode();
18641 "Should use MaskedValueIsZero if you don't know whether Op"
18642 " is a target node!");
18725 assert(MinVLenB > 0 &&
"READ_VLENB without vector extension enabled?");
18728 if (MaxVLenB == MinVLenB)
18745 case Intrinsic::riscv_vsetvli:
18746 case Intrinsic::riscv_vsetvlimax: {
18747 bool HasAVL = IntNo == Intrinsic::riscv_vsetvli;
18748 unsigned VSEW =
Op.getConstantOperandVal(HasAVL + 1);
18754 MaxVL = (Fractional) ? MaxVL / LMul : MaxVL * LMul;
18757 if (HasAVL && isa<ConstantSDNode>(
Op.getOperand(1)))
18758 MaxVL = std::min(MaxVL,
Op.getConstantOperandVal(1));
18760 unsigned KnownZeroFirstBit =
Log2_32(MaxVL) + 1;
18773 unsigned Depth)
const {
18774 switch (
Op.getOpcode()) {
18780 if (Tmp == 1)
return 1;
18783 return std::min(Tmp, Tmp2);
18795 if (Tmp < 33)
return 1;
18820 unsigned XLen = Subtarget.
getXLen();
18821 unsigned EltBits =
Op.getOperand(0).getScalarValueSizeInBits();
18822 if (EltBits <= XLen)
18823 return XLen - EltBits + 1;
18827 unsigned IntNo =
Op.getConstantOperandVal(1);
18831 case Intrinsic::riscv_masked_atomicrmw_xchg_i64:
18832 case Intrinsic::riscv_masked_atomicrmw_add_i64:
18833 case Intrinsic::riscv_masked_atomicrmw_sub_i64:
18834 case Intrinsic::riscv_masked_atomicrmw_nand_i64:
18835 case Intrinsic::riscv_masked_atomicrmw_max_i64:
18836 case Intrinsic::riscv_masked_atomicrmw_min_i64:
18837 case Intrinsic::riscv_masked_atomicrmw_umax_i64:
18838 case Intrinsic::riscv_masked_atomicrmw_umin_i64:
18839 case Intrinsic::riscv_masked_cmpxchg_i64:
18847 assert(Subtarget.hasStdExtA());
18862 switch (
Op.getOpcode()) {
18868 return !
Op.getValueType().isInteger();
18876 assert(Ld &&
"Unexpected null LoadSDNode");
18884 auto *CNode = dyn_cast<ConstantPoolSDNode>(
Ptr);
18885 if (!CNode || CNode->isMachineConstantPoolEntry() ||
18886 CNode->getOffset() != 0)
18894 auto *CNode = GetSupportedConstantPool(
Ptr);
18895 if (!CNode || CNode->getTargetFlags() != 0)
18898 return CNode->getConstVal();
18906 auto *CNodeLo = GetSupportedConstantPool(
Ptr.getOperand(1));
18907 auto *CNodeHi = GetSupportedConstantPool(
Ptr.getOperand(0).getOperand(0));
18913 if (CNodeLo->getConstVal() != CNodeHi->getConstVal())
18916 return CNodeLo->getConstVal();
18921 assert(
MI.getOpcode() == RISCV::ReadCounterWide &&
"Unexpected instruction");
18953 Register ReadAgainReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
18956 int64_t LoCounter =
MI.getOperand(2).getImm();
18957 int64_t HiCounter =
MI.getOperand(3).getImm();
18967 BuildMI(LoopMBB,
DL,
TII->get(RISCV::CSRRS), ReadAgainReg)
18979 MI.eraseFromParent();
18987 assert(
MI.getOpcode() == RISCV::SplitF64Pseudo &&
"Unexpected instruction");
18995 Register SrcReg =
MI.getOperand(2).getReg();
19015 MI.eraseFromParent();
19022 assert(
MI.getOpcode() == RISCV::BuildPairF64Pseudo &&
19023 "Unexpected instruction");
19029 Register DstReg =
MI.getOperand(0).getReg();
19052 MI.eraseFromParent();
19057 switch (
MI.getOpcode()) {
19060 case RISCV::Select_GPR_Using_CC_GPR:
19061 case RISCV::Select_GPR_Using_CC_Imm:
19062 case RISCV::Select_FPR16_Using_CC_GPR:
19063 case RISCV::Select_FPR16INX_Using_CC_GPR:
19064 case RISCV::Select_FPR32_Using_CC_GPR:
19065 case RISCV::Select_FPR32INX_Using_CC_GPR:
19066 case RISCV::Select_FPR64_Using_CC_GPR:
19067 case RISCV::Select_FPR64INX_Using_CC_GPR:
19068 case RISCV::Select_FPR64IN32X_Using_CC_GPR:
19074 unsigned RelOpcode,
unsigned EqOpcode,
19077 Register DstReg =
MI.getOperand(0).getReg();
19078 Register Src1Reg =
MI.getOperand(1).getReg();
19079 Register Src2Reg =
MI.getOperand(2).getReg();
19081 Register SavedFFlags =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
19105 MI.eraseFromParent();
19156 F->insert(It, FirstMBB);
19157 F->insert(It, SecondMBB);
19158 F->insert(It, SinkMBB);
19207 First.eraseFromParent();
19246 if ((
MI.getOpcode() != RISCV::Select_GPR_Using_CC_GPR &&
19247 MI.getOpcode() != RISCV::Select_GPR_Using_CC_Imm) &&
19248 Next != BB->
end() && Next->getOpcode() ==
MI.getOpcode() &&
19249 Next->getOperand(5).getReg() ==
MI.getOperand(0).getReg() &&
19250 Next->getOperand(5).isKill())
19255 if (
MI.getOperand(2).isReg())
19256 RHS =
MI.getOperand(2).getReg();
19261 SelectDests.
insert(
MI.getOperand(0).getReg());
19265 SequenceMBBI != E; ++SequenceMBBI) {
19266 if (SequenceMBBI->isDebugInstr())
19269 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
19270 !SequenceMBBI->getOperand(2).isReg() ||
19271 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
19272 SequenceMBBI->getOperand(3).getImm() !=
CC ||
19273 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
19274 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
19276 LastSelectPseudo = &*SequenceMBBI;
19278 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
19281 if (SequenceMBBI->hasUnmodeledSideEffects() ||
19282 SequenceMBBI->mayLoadOrStore() ||
19283 SequenceMBBI->usesCustomInsertionHook())
19286 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
19301 F->insert(
I, IfFalseMBB);
19302 F->insert(
I, TailMBB);
19305 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
19311 TailMBB->
push_back(DebugInstr->removeFromParent());
19315 TailMBB->
splice(TailMBB->
end(), HeadMBB,
19325 if (
MI.getOperand(2).isImm())
19328 .
addImm(
MI.getOperand(2).getImm())
19340 auto SelectMBBI =
MI.getIterator();
19341 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
19343 while (SelectMBBI != SelectEnd) {
19344 auto Next = std::next(SelectMBBI);
19348 TII.get(RISCV::PHI), SelectMBBI->getOperand(0).getReg())
19349 .
addReg(SelectMBBI->getOperand(4).getReg())
19351 .
addReg(SelectMBBI->getOperand(5).getReg())
19366 RISCVVInversePseudosTable::getBaseInfo(MCOpcode, LMul, SEW);
19367 assert(
Inverse &&
"Unexpected LMUL and SEW pair for instruction");
19369 RISCV::lookupMaskedIntrinsicByUnmasked(
Inverse->Pseudo);
19370 assert(
Masked &&
"Could not find masked instruction for LMUL and SEW pair");
19376 unsigned CVTXOpc) {
19382 Register SavedFFLAGS =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
19395 .
add(
MI.getOperand(1))
19396 .
add(
MI.getOperand(2))
19397 .
add(
MI.getOperand(3))
19399 .
add(
MI.getOperand(4))
19400 .
add(
MI.getOperand(5))
19401 .
add(
MI.getOperand(6))
19416 .
add(
MI.getOperand(0))
19417 .
add(
MI.getOperand(1))
19419 .
add(
MI.getOperand(3))
19421 .
add(
MI.getOperand(4))
19422 .
add(
MI.getOperand(5))
19423 .
add(
MI.getOperand(6))
19433 MI.eraseFromParent();
19439 unsigned CmpOpc, F2IOpc, I2FOpc, FSGNJOpc, FSGNJXOpc;
19441 switch (
MI.getOpcode()) {
19444 case RISCV::PseudoFROUND_H:
19445 CmpOpc = RISCV::FLT_H;
19446 F2IOpc = RISCV::FCVT_W_H;
19447 I2FOpc = RISCV::FCVT_H_W;
19448 FSGNJOpc = RISCV::FSGNJ_H;
19449 FSGNJXOpc = RISCV::FSGNJX_H;
19450 RC = &RISCV::FPR16RegClass;
19452 case RISCV::PseudoFROUND_H_INX:
19453 CmpOpc = RISCV::FLT_H_INX;
19454 F2IOpc = RISCV::FCVT_W_H_INX;
19455 I2FOpc = RISCV::FCVT_H_W_INX;
19456 FSGNJOpc = RISCV::FSGNJ_H_INX;
19457 FSGNJXOpc = RISCV::FSGNJX_H_INX;
19458 RC = &RISCV::GPRF16RegClass;
19460 case RISCV::PseudoFROUND_S:
19461 CmpOpc = RISCV::FLT_S;
19462 F2IOpc = RISCV::FCVT_W_S;
19463 I2FOpc = RISCV::FCVT_S_W;
19464 FSGNJOpc = RISCV::FSGNJ_S;
19465 FSGNJXOpc = RISCV::FSGNJX_S;
19466 RC = &RISCV::FPR32RegClass;
19468 case RISCV::PseudoFROUND_S_INX:
19469 CmpOpc = RISCV::FLT_S_INX;
19470 F2IOpc = RISCV::FCVT_W_S_INX;
19471 I2FOpc = RISCV::FCVT_S_W_INX;
19472 FSGNJOpc = RISCV::FSGNJ_S_INX;
19473 FSGNJXOpc = RISCV::FSGNJX_S_INX;
19474 RC = &RISCV::GPRF32RegClass;
19476 case RISCV::PseudoFROUND_D:
19478 CmpOpc = RISCV::FLT_D;
19479 F2IOpc = RISCV::FCVT_L_D;
19480 I2FOpc = RISCV::FCVT_D_L;
19481 FSGNJOpc = RISCV::FSGNJ_D;
19482 FSGNJXOpc = RISCV::FSGNJX_D;
19483 RC = &RISCV::FPR64RegClass;
19485 case RISCV::PseudoFROUND_D_INX:
19487 CmpOpc = RISCV::FLT_D_INX;
19488 F2IOpc = RISCV::FCVT_L_D_INX;
19489 I2FOpc = RISCV::FCVT_D_L_INX;
19490 FSGNJOpc = RISCV::FSGNJ_D_INX;
19491 FSGNJXOpc = RISCV::FSGNJX_D_INX;
19492 RC = &RISCV::GPRRegClass;
19504 F->insert(
I, CvtMBB);
19505 F->insert(
I, DoneMBB);
19516 Register DstReg =
MI.getOperand(0).getReg();
19517 Register SrcReg =
MI.getOperand(1).getReg();
19518 Register MaxReg =
MI.getOperand(2).getReg();
19519 int64_t FRM =
MI.getOperand(3).getImm();
19524 Register FabsReg =
MRI.createVirtualRegister(RC);
19528 Register CmpReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
19543 Register F2IReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
19565 MI.eraseFromParent();
19572 switch (
MI.getOpcode()) {
19575 case RISCV::ReadCounterWide:
19577 "ReadCounterWide is only to be used on riscv32");
19579 case RISCV::Select_GPR_Using_CC_GPR:
19580 case RISCV::Select_GPR_Using_CC_Imm:
19581 case RISCV::Select_FPR16_Using_CC_GPR:
19582 case RISCV::Select_FPR16INX_Using_CC_GPR:
19583 case RISCV::Select_FPR32_Using_CC_GPR:
19584 case RISCV::Select_FPR32INX_Using_CC_GPR:
19585 case RISCV::Select_FPR64_Using_CC_GPR:
19586 case RISCV::Select_FPR64INX_Using_CC_GPR:
19587 case RISCV::Select_FPR64IN32X_Using_CC_GPR:
19589 case RISCV::BuildPairF64Pseudo:
19591 case RISCV::SplitF64Pseudo:
19593 case RISCV::PseudoQuietFLE_H:
19595 case RISCV::PseudoQuietFLE_H_INX:
19596 return emitQuietFCMP(
MI, BB, RISCV::FLE_H_INX, RISCV::FEQ_H_INX, Subtarget);
19597 case RISCV::PseudoQuietFLT_H:
19599 case RISCV::PseudoQuietFLT_H_INX:
19600 return emitQuietFCMP(
MI, BB, RISCV::FLT_H_INX, RISCV::FEQ_H_INX, Subtarget);
19601 case RISCV::PseudoQuietFLE_S:
19603 case RISCV::PseudoQuietFLE_S_INX:
19604 return emitQuietFCMP(
MI, BB, RISCV::FLE_S_INX, RISCV::FEQ_S_INX, Subtarget);
19605 case RISCV::PseudoQuietFLT_S:
19607 case RISCV::PseudoQuietFLT_S_INX:
19608 return emitQuietFCMP(
MI, BB, RISCV::FLT_S_INX, RISCV::FEQ_S_INX, Subtarget);
19609 case RISCV::PseudoQuietFLE_D:
19611 case RISCV::PseudoQuietFLE_D_INX:
19612 return emitQuietFCMP(
MI, BB, RISCV::FLE_D_INX, RISCV::FEQ_D_INX, Subtarget);
19613 case RISCV::PseudoQuietFLE_D_IN32X:
19616 case RISCV::PseudoQuietFLT_D:
19618 case RISCV::PseudoQuietFLT_D_INX:
19619 return emitQuietFCMP(
MI, BB, RISCV::FLT_D_INX, RISCV::FEQ_D_INX, Subtarget);
19620 case RISCV::PseudoQuietFLT_D_IN32X:
19624 case RISCV::PseudoVFROUND_NOEXCEPT_V_M1_MASK:
19626 case RISCV::PseudoVFROUND_NOEXCEPT_V_M2_MASK:
19628 case RISCV::PseudoVFROUND_NOEXCEPT_V_M4_MASK:
19630 case RISCV::PseudoVFROUND_NOEXCEPT_V_M8_MASK:
19632 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF2_MASK:
19634 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF4_MASK:
19636 case RISCV::PseudoFROUND_H:
19637 case RISCV::PseudoFROUND_H_INX:
19638 case RISCV::PseudoFROUND_S:
19639 case RISCV::PseudoFROUND_S_INX:
19640 case RISCV::PseudoFROUND_D:
19641 case RISCV::PseudoFROUND_D_INX:
19642 case RISCV::PseudoFROUND_D_IN32X:
19644 case TargetOpcode::STATEPOINT:
19650 MI.addOperand(*
MI.getMF(),
19656 case TargetOpcode::STACKMAP:
19657 case TargetOpcode::PATCHPOINT:
19660 "supported on 64-bit targets");
19678 if (
MI.readsRegister(RISCV::FRM,
nullptr))
19684void RISCVTargetLowering::analyzeInputArgs(
19688 unsigned NumArgs = Ins.size();
19691 for (
unsigned i = 0; i != NumArgs; ++i) {
19692 MVT ArgVT = Ins[i].VT;
19695 Type *ArgTy =
nullptr;
19698 else if (Ins[i].isOrigArg())
19699 ArgTy = FType->
getParamType(Ins[i].getOrigArgIndex());
19702 true, IsRet, ArgTy)) {
19703 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type "
19710void RISCVTargetLowering::analyzeOutputArgs(
19714 unsigned NumArgs = Outs.
size();
19716 for (
unsigned i = 0; i != NumArgs; i++) {
19717 MVT ArgVT = Outs[i].VT;
19719 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
19722 Outs[i].IsFixed, IsRet, OrigTy)) {
19723 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type "
19774 if (In.isOrigArg()) {
19779 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
19780 (
BitWidth < 32 && In.Flags.isZExt())) {
19802 if (LocVT == MVT::i64 && VA.
getValVT() == MVT::f32)
19851 ExtType,
DL, LocVT, Chain, FIN,
19868 Register LoVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
19881 Register HiVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
19896 switch (CallConv) {
19906 if (Subtarget.hasStdExtE())
19910 "(Zdinx/D) instruction set extensions");
19914 if (Func.hasFnAttribute(
"interrupt")) {
19915 if (!Func.arg_empty())
19917 "Functions with the interrupt attribute cannot have arguments!");
19922 if (!(Kind ==
"user" || Kind ==
"supervisor" || Kind ==
"machine"))
19924 "Function interrupt attribute argument not supported!");
19929 unsigned XLenInBytes = Subtarget.
getXLen() / 8;
19931 std::vector<SDValue> OutChains;
19940 analyzeInputArgs(MF, CCInfo, Ins,
false,
19944 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
19965 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
19966 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
19968 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
19970 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
19999 int VarArgsSaveSize = XLenInBytes * (ArgRegs.
size() -
Idx);
20004 if (VarArgsSaveSize == 0) {
20008 int VaArgOffset = -VarArgsSaveSize;
20016 XLenInBytes, VaArgOffset -
static_cast<int>(XLenInBytes),
true);
20017 VarArgsSaveSize += XLenInBytes;
20024 for (
unsigned I =
Idx;
I < ArgRegs.
size(); ++
I) {
20029 Chain,
DL, ArgValue, FIN,
20031 OutChains.push_back(Store);
20045 if (!OutChains.empty()) {
20046 OutChains.push_back(Chain);
20056bool RISCVTargetLowering::isEligibleForTailCallOptimization(
20060 auto CalleeCC = CLI.CallConv;
20061 auto &Outs = CLI.Outs;
20063 auto CallerCC = Caller.getCallingConv();
20070 if (Caller.hasFnAttribute(
"interrupt"))
20085 for (
auto &VA : ArgLocs)
20091 auto IsCallerStructRet = Caller.hasStructRetAttr();
20092 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
20093 if (IsCallerStructRet || IsCalleeStructRet)
20098 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
20099 if (CalleeCC != CallerCC) {
20100 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
20101 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
20108 for (
auto &Arg : Outs)
20109 if (Arg.Flags.isByVal())
20144 if (Subtarget.hasStdExtE())
20148 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
20154 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
20160 "site marked musttail");
20167 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
20169 if (!Flags.isByVal())
20173 unsigned Size = Flags.getByValSize();
20174 Align Alignment = Flags.getNonZeroByValAlign();
20181 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
20183 false,
nullptr, IsTailCall,
20195 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
20198 SDValue ArgValue = OutVals[OutIdx];
20218 if (!StackPtr.getNode())
20230 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
20248 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
20249 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
20255 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
20256 SDValue PartValue = OutVals[OutIdx + 1];
20257 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
20269 int FI = cast<FrameIndexSDNode>(SpillSlot)->getIndex();
20271 DAG.
getStore(Chain,
DL, ArgValue, SpillSlot,
20273 for (
const auto &Part : Parts) {
20274 SDValue PartValue = Part.first;
20275 SDValue PartOffset = Part.second;
20282 ArgValue = SpillSlot;
20288 if (Flags.isByVal())
20289 ArgValue = ByValArgs[j++];
20296 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
20297 "for passing parameters");
20300 if (!StackPtr.getNode())
20314 if (!MemOpChains.
empty())
20320 for (
auto &Reg : RegsToPass) {
20321 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
20328 validateCCReservedRegs(RegsToPass, MF);
20332 "Return address register required, but has been reserved."});
20337 bool CalleeIsLargeExternalSymbol =
false;
20339 if (
auto *S = dyn_cast<GlobalAddressSDNode>(Callee))
20341 else if (
auto *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
20343 CalleeIsLargeExternalSymbol =
true;
20359 for (
auto &Reg : RegsToPass)
20364 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
20365 assert(Mask &&
"Missing call preserved mask for calling convention");
20373 "Unexpected CFI type for a direct call");
20381 bool NeedSWGuarded =
false;
20383 Subtarget.hasStdExtZicfilp() &&
20385 NeedSWGuarded =
true;
20399 Chain = DAG.
getNode(CallOpc,
DL, NodeTys, Ops);
20412 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_RISCV);
20415 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
20416 auto &VA = RVLocs[i];
20424 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
20425 assert(VA.needsCustom());
20445 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
20447 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
20448 MVT VT = Outs[i].VT;
20451 true,
true,
nullptr))
20483 for (
unsigned i = 0, e = RVLocs.size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
20484 SDValue Val = OutVals[OutIdx];
20493 DAG.
getVTList(MVT::i32, MVT::i32), Val);
20497 Register RegHi = RVLocs[++i].getLocReg();
20503 "Return value register required, but has been reserved."});
20519 "Return value register required, but has been reserved."});
20541 if (Func.hasFnAttribute(
"interrupt")) {
20542 if (!Func.getReturnType()->isVoidTy())
20544 "Functions with the interrupt attribute must have void return type!");
20550 if (Kind ==
"supervisor")
20556 return DAG.
getNode(RetOpc,
DL, MVT::Other, RetOps);
20559void RISCVTargetLowering::validateCCReservedRegs(
20560 const SmallVectorImpl<std::pair<llvm::Register, llvm::SDValue>> &Regs,
20569 F,
"Argument register required, but has been reserved."});
20575 if (
N->getNumValues() != 1)
20577 if (!
N->hasNUsesOfValue(1, 0))
20580 SDNode *Copy = *
N->user_begin();
20594 if (Copy->getOperand(Copy->getNumOperands() - 1).getValueType() == MVT::Glue)
20598 bool HasRet =
false;
20599 for (
SDNode *Node : Copy->users()) {
20607 Chain = Copy->getOperand(0);
20616#define NODE_NAME_CASE(NODE) \
20617 case RISCVISD::NODE: \
20618 return "RISCVISD::" #NODE;
20879#undef NODE_NAME_CASE
20886 if (Constraint.
size() == 1) {
20887 switch (Constraint[0]) {
20904 if (Constraint ==
"vr" || Constraint ==
"vd" || Constraint ==
"vm")
20906 if (Constraint ==
"cr" || Constraint ==
"cf")
20912std::pair<unsigned, const TargetRegisterClass *>
20918 if (Constraint.
size() == 1) {
20919 switch (Constraint[0]) {
20924 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
20925 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
20926 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
20927 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
20928 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
20929 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
20930 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
20932 if (VT == MVT::f16) {
20933 if (Subtarget.hasStdExtZfhmin())
20934 return std::make_pair(0U, &RISCV::FPR16RegClass);
20935 if (Subtarget.hasStdExtZhinxmin())
20936 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
20937 }
else if (VT == MVT::f32) {
20938 if (Subtarget.hasStdExtF())
20939 return std::make_pair(0U, &RISCV::FPR32RegClass);
20940 if (Subtarget.hasStdExtZfinx())
20941 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
20942 }
else if (VT == MVT::f64) {
20943 if (Subtarget.hasStdExtD())
20944 return std::make_pair(0U, &RISCV::FPR64RegClass);
20945 if (Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
20946 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
20947 if (Subtarget.hasStdExtZdinx() && Subtarget.
is64Bit())
20948 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
20952 if (VT == MVT::f64 && !Subtarget.
is64Bit() && Subtarget.hasStdExtZdinx())
20953 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
20954 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
20958 }
else if (Constraint ==
"vr") {
20959 for (
const auto *RC :
20960 {&RISCV::VRRegClass, &RISCV::VRM2RegClass, &RISCV::VRM4RegClass,
20961 &RISCV::VRM8RegClass, &RISCV::VRN2M1RegClass, &RISCV::VRN3M1RegClass,
20962 &RISCV::VRN4M1RegClass, &RISCV::VRN5M1RegClass,
20963 &RISCV::VRN6M1RegClass, &RISCV::VRN7M1RegClass,
20964 &RISCV::VRN8M1RegClass, &RISCV::VRN2M2RegClass,
20965 &RISCV::VRN3M2RegClass, &RISCV::VRN4M2RegClass,
20966 &RISCV::VRN2M4RegClass}) {
20968 return std::make_pair(0U, RC);
20970 }
else if (Constraint ==
"vd") {
20971 for (
const auto *RC :
20972 {&RISCV::VRNoV0RegClass, &RISCV::VRM2NoV0RegClass,
20973 &RISCV::VRM4NoV0RegClass, &RISCV::VRM8NoV0RegClass,
20974 &RISCV::VRN2M1NoV0RegClass, &RISCV::VRN3M1NoV0RegClass,
20975 &RISCV::VRN4M1NoV0RegClass, &RISCV::VRN5M1NoV0RegClass,
20976 &RISCV::VRN6M1NoV0RegClass, &RISCV::VRN7M1NoV0RegClass,
20977 &RISCV::VRN8M1NoV0RegClass, &RISCV::VRN2M2NoV0RegClass,
20978 &RISCV::VRN3M2NoV0RegClass, &RISCV::VRN4M2NoV0RegClass,
20979 &RISCV::VRN2M4NoV0RegClass}) {
20981 return std::make_pair(0U, RC);
20983 }
else if (Constraint ==
"vm") {
20984 if (
TRI->isTypeLegalForClass(RISCV::VMV0RegClass, VT.
SimpleTy))
20985 return std::make_pair(0U, &RISCV::VMV0RegClass);
20986 }
else if (Constraint ==
"cr") {
20987 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
20988 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
20989 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
20990 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
20991 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
20992 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
20994 return std::make_pair(0U, &RISCV::GPRCRegClass);
20995 }
else if (Constraint ==
"cf") {
20996 if (VT == MVT::f16) {
20997 if (Subtarget.hasStdExtZfhmin())
20998 return std::make_pair(0U, &RISCV::FPR16CRegClass);
20999 if (Subtarget.hasStdExtZhinxmin())
21000 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
21001 }
else if (VT == MVT::f32) {
21002 if (Subtarget.hasStdExtF())
21003 return std::make_pair(0U, &RISCV::FPR32CRegClass);
21004 if (Subtarget.hasStdExtZfinx())
21005 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
21006 }
else if (VT == MVT::f64) {
21007 if (Subtarget.hasStdExtD())
21008 return std::make_pair(0U, &RISCV::FPR64CRegClass);
21009 if (Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
21010 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
21011 if (Subtarget.hasStdExtZdinx() && Subtarget.
is64Bit())
21012 return std::make_pair(0U, &RISCV::GPRCRegClass);
21021 .
Case(
"{zero}", RISCV::X0)
21022 .
Case(
"{ra}", RISCV::X1)
21023 .
Case(
"{sp}", RISCV::X2)
21024 .
Case(
"{gp}", RISCV::X3)
21025 .
Case(
"{tp}", RISCV::X4)
21026 .
Case(
"{t0}", RISCV::X5)
21027 .
Case(
"{t1}", RISCV::X6)
21028 .
Case(
"{t2}", RISCV::X7)
21029 .
Cases(
"{s0}",
"{fp}", RISCV::X8)
21030 .
Case(
"{s1}", RISCV::X9)
21031 .
Case(
"{a0}", RISCV::X10)
21032 .
Case(
"{a1}", RISCV::X11)
21033 .
Case(
"{a2}", RISCV::X12)
21034 .
Case(
"{a3}", RISCV::X13)
21035 .
Case(
"{a4}", RISCV::X14)
21036 .
Case(
"{a5}", RISCV::X15)
21037 .
Case(
"{a6}", RISCV::X16)
21038 .
Case(
"{a7}", RISCV::X17)
21039 .
Case(
"{s2}", RISCV::X18)
21040 .
Case(
"{s3}", RISCV::X19)
21041 .
Case(
"{s4}", RISCV::X20)
21042 .
Case(
"{s5}", RISCV::X21)
21043 .
Case(
"{s6}", RISCV::X22)
21044 .
Case(
"{s7}", RISCV::X23)
21045 .
Case(
"{s8}", RISCV::X24)
21046 .
Case(
"{s9}", RISCV::X25)
21047 .
Case(
"{s10}", RISCV::X26)
21048 .
Case(
"{s11}", RISCV::X27)
21049 .
Case(
"{t3}", RISCV::X28)
21050 .
Case(
"{t4}", RISCV::X29)
21051 .
Case(
"{t5}", RISCV::X30)
21052 .
Case(
"{t6}", RISCV::X31)
21054 if (XRegFromAlias != RISCV::NoRegister)
21055 return std::make_pair(XRegFromAlias, &RISCV::GPRRegClass);
21064 if (Subtarget.hasStdExtF()) {
21066 .
Cases(
"{f0}",
"{ft0}", RISCV::F0_F)
21067 .
Cases(
"{f1}",
"{ft1}", RISCV::F1_F)
21068 .
Cases(
"{f2}",
"{ft2}", RISCV::F2_F)
21069 .
Cases(
"{f3}",
"{ft3}", RISCV::F3_F)
21070 .
Cases(
"{f4}",
"{ft4}", RISCV::F4_F)
21071 .
Cases(
"{f5}",
"{ft5}", RISCV::F5_F)
21072 .
Cases(
"{f6}",
"{ft6}", RISCV::F6_F)
21073 .
Cases(
"{f7}",
"{ft7}", RISCV::F7_F)
21074 .
Cases(
"{f8}",
"{fs0}", RISCV::F8_F)
21075 .
Cases(
"{f9}",
"{fs1}", RISCV::F9_F)
21076 .
Cases(
"{f10}",
"{fa0}", RISCV::F10_F)
21077 .
Cases(
"{f11}",
"{fa1}", RISCV::F11_F)
21078 .
Cases(
"{f12}",
"{fa2}", RISCV::F12_F)
21079 .
Cases(
"{f13}",
"{fa3}", RISCV::F13_F)
21080 .
Cases(
"{f14}",
"{fa4}", RISCV::F14_F)
21081 .
Cases(
"{f15}",
"{fa5}", RISCV::F15_F)
21082 .
Cases(
"{f16}",
"{fa6}", RISCV::F16_F)
21083 .
Cases(
"{f17}",
"{fa7}", RISCV::F17_F)
21084 .
Cases(
"{f18}",
"{fs2}", RISCV::F18_F)
21085 .
Cases(
"{f19}",
"{fs3}", RISCV::F19_F)
21086 .
Cases(
"{f20}",
"{fs4}", RISCV::F20_F)
21087 .
Cases(
"{f21}",
"{fs5}", RISCV::F21_F)
21088 .
Cases(
"{f22}",
"{fs6}", RISCV::F22_F)
21089 .
Cases(
"{f23}",
"{fs7}", RISCV::F23_F)
21090 .
Cases(
"{f24}",
"{fs8}", RISCV::F24_F)
21091 .
Cases(
"{f25}",
"{fs9}", RISCV::F25_F)
21092 .
Cases(
"{f26}",
"{fs10}", RISCV::F26_F)
21093 .
Cases(
"{f27}",
"{fs11}", RISCV::F27_F)
21094 .
Cases(
"{f28}",
"{ft8}", RISCV::F28_F)
21095 .
Cases(
"{f29}",
"{ft9}", RISCV::F29_F)
21096 .
Cases(
"{f30}",
"{ft10}", RISCV::F30_F)
21097 .
Cases(
"{f31}",
"{ft11}", RISCV::F31_F)
21099 if (FReg != RISCV::NoRegister) {
21100 assert(RISCV::F0_F <= FReg && FReg <= RISCV::F31_F &&
"Unknown fp-reg");
21101 if (Subtarget.hasStdExtD() && (VT == MVT::f64 || VT == MVT::Other)) {
21102 unsigned RegNo = FReg - RISCV::F0_F;
21103 unsigned DReg = RISCV::F0_D + RegNo;
21104 return std::make_pair(DReg, &RISCV::FPR64RegClass);
21106 if (VT == MVT::f32 || VT == MVT::Other)
21107 return std::make_pair(FReg, &RISCV::FPR32RegClass);
21108 if (Subtarget.hasStdExtZfhmin() && VT == MVT::f16) {
21109 unsigned RegNo = FReg - RISCV::F0_F;
21110 unsigned HReg = RISCV::F0_H + RegNo;
21111 return std::make_pair(HReg, &RISCV::FPR16RegClass);
21118 .
Case(
"{v0}", RISCV::V0)
21119 .
Case(
"{v1}", RISCV::V1)
21120 .
Case(
"{v2}", RISCV::V2)
21121 .
Case(
"{v3}", RISCV::V3)
21122 .
Case(
"{v4}", RISCV::V4)
21123 .
Case(
"{v5}", RISCV::V5)
21124 .
Case(
"{v6}", RISCV::V6)
21125 .
Case(
"{v7}", RISCV::V7)
21126 .
Case(
"{v8}", RISCV::V8)
21127 .
Case(
"{v9}", RISCV::V9)
21128 .
Case(
"{v10}", RISCV::V10)
21129 .
Case(
"{v11}", RISCV::V11)
21130 .
Case(
"{v12}", RISCV::V12)
21131 .
Case(
"{v13}", RISCV::V13)
21132 .
Case(
"{v14}", RISCV::V14)
21133 .
Case(
"{v15}", RISCV::V15)
21134 .
Case(
"{v16}", RISCV::V16)
21135 .
Case(
"{v17}", RISCV::V17)
21136 .
Case(
"{v18}", RISCV::V18)
21137 .
Case(
"{v19}", RISCV::V19)
21138 .
Case(
"{v20}", RISCV::V20)
21139 .
Case(
"{v21}", RISCV::V21)
21140 .
Case(
"{v22}", RISCV::V22)
21141 .
Case(
"{v23}", RISCV::V23)
21142 .
Case(
"{v24}", RISCV::V24)
21143 .
Case(
"{v25}", RISCV::V25)
21144 .
Case(
"{v26}", RISCV::V26)
21145 .
Case(
"{v27}", RISCV::V27)
21146 .
Case(
"{v28}", RISCV::V28)
21147 .
Case(
"{v29}", RISCV::V29)
21148 .
Case(
"{v30}", RISCV::V30)
21149 .
Case(
"{v31}", RISCV::V31)
21151 if (VReg != RISCV::NoRegister) {
21152 if (
TRI->isTypeLegalForClass(RISCV::VMRegClass, VT.
SimpleTy))
21153 return std::make_pair(VReg, &RISCV::VMRegClass);
21154 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, VT.
SimpleTy))
21155 return std::make_pair(VReg, &RISCV::VRRegClass);
21156 for (
const auto *RC :
21157 {&RISCV::VRM2RegClass, &RISCV::VRM4RegClass, &RISCV::VRM8RegClass}) {
21158 if (
TRI->isTypeLegalForClass(*RC, VT.
SimpleTy)) {
21159 VReg =
TRI->getMatchingSuperReg(VReg, RISCV::sub_vrm1_0, RC);
21160 return std::make_pair(VReg, RC);
21166 std::pair<Register, const TargetRegisterClass *> Res =
21172 if (Res.second == &RISCV::GPRF16RegClass ||
21173 Res.second == &RISCV::GPRF32RegClass ||
21174 Res.second == &RISCV::GPRPairRegClass)
21175 return std::make_pair(Res.first, &RISCV::GPRRegClass);
21183 if (ConstraintCode.
size() == 1) {
21184 switch (ConstraintCode[0]) {
21199 if (Constraint.
size() == 1) {
21200 switch (Constraint[0]) {
21203 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
21205 if (isInt<12>(CVal))
21218 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
21220 if (isUInt<5>(CVal))
21238 if (Subtarget.hasStdExtZtso()) {
21254 if (Subtarget.hasStdExtZtso()) {
21262 if (Subtarget.enableTrailingSeqCstFence() && isa<StoreInst>(Inst) &&
21281 if (Subtarget.hasForcedAtomics())
21286 if (Subtarget.hasStdExtZacas() &&
21287 (
Size >= 32 || Subtarget.hasStdExtZabha()))
21293 if (
Size < 32 && !Subtarget.hasStdExtZabha())
21306 return Intrinsic::riscv_masked_atomicrmw_xchg_i32;
21308 return Intrinsic::riscv_masked_atomicrmw_add_i32;
21310 return Intrinsic::riscv_masked_atomicrmw_sub_i32;
21312 return Intrinsic::riscv_masked_atomicrmw_nand_i32;
21314 return Intrinsic::riscv_masked_atomicrmw_max_i32;
21316 return Intrinsic::riscv_masked_atomicrmw_min_i32;
21318 return Intrinsic::riscv_masked_atomicrmw_umax_i32;
21320 return Intrinsic::riscv_masked_atomicrmw_umin_i32;
21329 return Intrinsic::riscv_masked_atomicrmw_xchg_i64;
21331 return Intrinsic::riscv_masked_atomicrmw_add_i64;
21333 return Intrinsic::riscv_masked_atomicrmw_sub_i64;
21335 return Intrinsic::riscv_masked_atomicrmw_nand_i64;
21337 return Intrinsic::riscv_masked_atomicrmw_max_i64;
21339 return Intrinsic::riscv_masked_atomicrmw_min_i64;
21341 return Intrinsic::riscv_masked_atomicrmw_umax_i64;
21343 return Intrinsic::riscv_masked_atomicrmw_umin_i64;
21369 unsigned XLen = Subtarget.
getXLen();
21393 unsigned ValWidth =
21398 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
21401 Builder.
CreateCall(LrwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
21413 if (Subtarget.hasForcedAtomics())
21417 if (!(Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas()) &&
21426 unsigned XLen = Subtarget.
getXLen();
21428 Intrinsic::ID CmpXchgIntrID = Intrinsic::riscv_masked_cmpxchg_i32;
21433 CmpXchgIntrID = Intrinsic::riscv_masked_cmpxchg_i64;
21437 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, Ordering});
21444 EVT DataVT)
const {
21460 return Subtarget.hasStdExtZfhmin();
21462 return Subtarget.hasStdExtF();
21464 return Subtarget.hasStdExtD();
21496 "RVVBitsPerBlock changed, audit needed");
21505 if (!Subtarget.hasVendorXTHeadMemIdx())
21511 Base =
Op->getOperand(0);
21513 int64_t RHSC =
RHS->getSExtValue();
21519 bool isLegalIndexedOffset =
false;
21520 for (
unsigned i = 0; i < 4; i++)
21521 if (isInt<5>(RHSC >> i) && ((RHSC % (1LL << i)) == 0)) {
21522 isLegalIndexedOffset =
true;
21526 if (!isLegalIndexedOffset)
21543 VT = LD->getMemoryVT();
21544 Ptr = LD->getBasePtr();
21545 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
21546 VT = ST->getMemoryVT();
21547 Ptr = ST->getBasePtr();
21563 if (Subtarget.hasVendorXCVmem() && !Subtarget.
is64Bit()) {
21568 Base = LS->getBasePtr();
21572 if (
Base ==
Op->getOperand(0))
21574 else if (
Base ==
Op->getOperand(1))
21586 VT = LD->getMemoryVT();
21587 Ptr = LD->getBasePtr();
21588 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
21589 VT = ST->getMemoryVT();
21590 Ptr = ST->getBasePtr();
21633 const Constant *PersonalityFn)
const {
21638 const Constant *PersonalityFn)
const {
21653 bool IsSigned)
const {
21668 const bool HasZmmul = Subtarget.hasStdExtZmmul();
21672 auto *ConstNode = cast<ConstantSDNode>(
C);
21673 const APInt &Imm = ConstNode->getAPIntValue();
21676 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
21677 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
21681 if (Subtarget.hasStdExtZba() && !Imm.isSignedIntN(12) &&
21682 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
21683 (Imm - 8).isPowerOf2()))
21688 if (!Imm.isSignedIntN(12) && Imm.countr_zero() < 12 &&
21689 ConstNode->hasOneUse()) {
21690 APInt ImmS = Imm.ashr(Imm.countr_zero());
21691 if ((ImmS + 1).isPowerOf2() || (ImmS - 1).isPowerOf2() ||
21692 (1 - ImmS).isPowerOf2())
21715 if (C1.
isSignedIntN(12) && !(C1 * C2).isSignedIntN(12))
21724 unsigned *
Fast)
const {
21727 *
Fast = Subtarget.enableUnalignedScalarMem();
21728 return Subtarget.enableUnalignedScalarMem();
21744 *
Fast = Subtarget.enableUnalignedVectorMem();
21745 return Subtarget.enableUnalignedVectorMem();
21754 if (FuncAttributes.
hasFnAttr(Attribute::NoImplicitFloat))
21766 if (
Op.size() < MinVLenInBytes)
21781 MVT PreferredVT = (
Op.isMemset() && !
Op.isZeroMemset()) ? MVT::i8 : ELenVT;
21785 if (PreferredVT != MVT::i8 && !Subtarget.enableUnalignedVectorMem()) {
21787 if (
Op.isFixedDstAlign())
21788 RequiredAlign = std::min(RequiredAlign,
Op.getDstAlign());
21790 RequiredAlign = std::min(RequiredAlign,
Op.getSrcAlign());
21798 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID>
CC)
const {
21799 bool IsABIRegCopy =
CC.has_value();
21802 MVT PairVT = Subtarget.
is64Bit() ? MVT::i128 : MVT::i64;
21803 if ((ValueVT == PairVT ||
21804 (!Subtarget.
is64Bit() && Subtarget.hasStdExtZdinx() &&
21805 ValueVT == MVT::f64)) &&
21806 NumParts == 1 && PartVT == MVT::Untyped) {
21809 if (ValueVT == MVT::f64)
21818 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
21819 PartVT == MVT::f32) {
21834 [[maybe_unused]]
unsigned ValLMUL =
21838 [[maybe_unused]]
unsigned PartLMUL =
21841 assert(ValNF == PartNF && ValLMUL == PartLMUL &&
21842 "RISC-V vector tuple type only accepts same register class type "
21858 if (PartVTBitSize % ValueVTBitSize == 0) {
21859 assert(PartVTBitSize >= ValueVTBitSize);
21866 if (ValueEltVT != PartEltVT) {
21867 if (PartVTBitSize > ValueVTBitSize) {
21869 assert(Count != 0 &&
"The number of element should not be zero.");
21870 EVT SameEltTypeVT =
21892 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID>
CC)
const {
21893 bool IsABIRegCopy =
CC.has_value();
21895 MVT PairVT = Subtarget.
is64Bit() ? MVT::i128 : MVT::i64;
21896 if ((ValueVT == PairVT ||
21897 (!Subtarget.
is64Bit() && Subtarget.hasStdExtZdinx() &&
21898 ValueVT == MVT::f64)) &&
21899 NumParts == 1 && PartVT == MVT::Untyped) {
21910 if (ValueVT == MVT::f64)
21915 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
21916 PartVT == MVT::f32) {
21933 if (PartVTBitSize % ValueVTBitSize == 0) {
21934 assert(PartVTBitSize >= ValueVTBitSize);
21935 EVT SameEltTypeVT = ValueVT;
21942 if (ValueEltVT != PartEltVT) {
21944 assert(Count != 0 &&
"The number of element should not be zero.");
21961 bool OptSize = Attr.
hasFnAttr(Attribute::MinSize);
21968 unsigned Opc =
N->getOpcode();
21996 if (M->getStackProtectorGuard() ==
"tls") {
21998 int Offset = M->getStackProtectorGuardOffset();
22006 VectorType *VTy,
unsigned Factor,
Align Alignment,
unsigned AddrSpace,
22020 if (
auto *FVTy = dyn_cast<FixedVectorType>(VTy)) {
22025 if (FVTy->getNumElements() < 2)
22040 return Factor * LMUL <= 8;
22044 Align Alignment)
const {
22056 if (!Subtarget.enableUnalignedVectorMem() &&
22064 Intrinsic::riscv_seg2_load, Intrinsic::riscv_seg3_load,
22065 Intrinsic::riscv_seg4_load, Intrinsic::riscv_seg5_load,
22066 Intrinsic::riscv_seg6_load, Intrinsic::riscv_seg7_load,
22067 Intrinsic::riscv_seg8_load};
22088 auto *VTy = cast<FixedVectorType>(Shuffles[0]->
getType());
22100 unsigned ScalarSizeInBytes = VTy->getScalarSizeInBits() / 8;
22101 Value *Stride = ConstantInt::get(XLenTy, Factor * ScalarSizeInBytes);
22102 Value *
Offset = ConstantInt::get(XLenTy, Indices[0] * ScalarSizeInBytes);
22109 {VTy, BasePtr->getType(), Stride->
getType()},
22110 {BasePtr, Stride, Mask, VL});
22113 Shuffles[0]->replaceAllUsesWith(CI);
22117 Value *VL = ConstantInt::get(XLenTy, VTy->getNumElements());
22123 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
22125 Shuffles[i]->replaceAllUsesWith(SubVec);
22132 Intrinsic::riscv_seg2_store, Intrinsic::riscv_seg3_store,
22133 Intrinsic::riscv_seg4_store, Intrinsic::riscv_seg5_store,
22134 Intrinsic::riscv_seg6_store, Intrinsic::riscv_seg7_store,
22135 Intrinsic::riscv_seg8_store};
22155 unsigned Factor)
const {
22158 auto *ShuffleVTy = cast<FixedVectorType>(SVI->
getType());
22161 ShuffleVTy->getNumElements() / Factor);
22163 SI->getPointerAddressSpace(),
22164 SI->getDataLayout()))
22175 unsigned ScalarSizeInBytes = ShuffleVTy->getScalarSizeInBits() / 8;
22177 auto *DataVTy = cast<FixedVectorType>(
Data->getType());
22178 Value *Stride = ConstantInt::get(XLenTy, Factor * ScalarSizeInBytes);
22179 Value *
Offset = ConstantInt::get(XLenTy, Index * ScalarSizeInBytes);
22185 Intrinsic::experimental_vp_strided_store,
22186 {
Data->getType(), BasePtr->getType(), Stride->
getType()},
22187 {
Data, BasePtr, Stride, Mask, VL});
22196 {VTy, SI->getPointerOperandType(), XLenTy});
22200 for (
unsigned i = 0; i < Factor; i++) {
22209 Value *VL = ConstantInt::get(XLenTy, VTy->getNumElements());
22210 Ops.
append({SI->getPointerOperand(), VL});
22227 const unsigned Factor = 2;
22239 if (
auto *FVTy = dyn_cast<FixedVectorType>(ResVTy)) {
22240 Value *VL = ConstantInt::get(XLenTy, FVTy->getNumElements());
22247 Intrinsic::riscv_vlseg2, Intrinsic::riscv_vlseg3,
22248 Intrinsic::riscv_vlseg4, Intrinsic::riscv_vlseg5,
22249 Intrinsic::riscv_vlseg6, Intrinsic::riscv_vlseg7,
22250 Intrinsic::riscv_vlseg8};
22257 NumElts * SEW / 8),
22263 IntrIds[Factor - 2], {VecTupTy, XLenTy},
22265 ConstantInt::get(XLenTy,
Log2_64(SEW))});
22269 for (
unsigned i = 0; i < Factor; ++i) {
22271 Intrinsic::riscv_tuple_extract, {ResVTy, VecTupTy},
22289 if (
II->getIntrinsicID() != Intrinsic::vector_interleave2)
22292 const unsigned Factor = 2;
22294 VectorType *InVTy = cast<VectorType>(
II->getArgOperand(0)->getType());
22298 SI->getPointerAddressSpace(),
DL))
22303 if (
auto *FVTy = dyn_cast<FixedVectorType>(InVTy)) {
22304 Value *VL = ConstantInt::get(XLenTy, FVTy->getNumElements());
22306 {InVTy, SI->getPointerOperandType(), XLenTy},
22307 {
II->getArgOperand(0),
II->getArgOperand(1),
22308 SI->getPointerOperand(), VL});
22311 Intrinsic::riscv_vsseg2, Intrinsic::riscv_vsseg3,
22312 Intrinsic::riscv_vsseg4, Intrinsic::riscv_vsseg5,
22313 Intrinsic::riscv_vsseg6, Intrinsic::riscv_vsseg7,
22314 Intrinsic::riscv_vsseg8};
22319 SI->getContext(),
"riscv.vector.tuple",
22321 NumElts * SEW / 8),
22325 SI->getModule(), IntrIds[Factor - 2], {VecTupTy, XLenTy});
22330 for (
unsigned i = 0; i < Factor; ++i)
22332 Intrinsic::riscv_tuple_insert, {VecTupTy, InVTy},
22333 {StoredVal, II->getArgOperand(i), Builder.getInt32(i)});
22335 Builder.
CreateCall(VssegNFunc, {StoredVal, SI->getPointerOperand(), VL,
22336 ConstantInt::get(XLenTy,
Log2_64(SEW))});
22347 "Invalid call instruction for a KCFI check");
22349 MBBI->getOpcode()));
22352 Target.setIsRenamable(
false);
22360#define GET_REGISTER_MATCHER
22361#include "RISCVGenAsmMatcher.inc"
22367 if (Reg == RISCV::NoRegister)
22369 if (Reg == RISCV::NoRegister)
22381 const MDNode *NontemporalInfo =
I.getMetadata(LLVMContext::MD_nontemporal);
22383 if (NontemporalInfo ==
nullptr)
22391 int NontemporalLevel = 5;
22392 const MDNode *RISCVNontemporalInfo =
22393 I.getMetadata(
"riscv-nontemporal-domain");
22394 if (RISCVNontemporalInfo !=
nullptr)
22397 cast<ConstantAsMetadata>(RISCVNontemporalInfo->
getOperand(0))
22401 assert((1 <= NontemporalLevel && NontemporalLevel <= 5) &&
22402 "RISC-V target doesn't support this non-temporal domain.");
22404 NontemporalLevel -= 2;
22406 if (NontemporalLevel & 0b1)
22408 if (NontemporalLevel & 0b10)
22421 return TargetFlags;
22431 return isTypeLegal(VT) && Subtarget.hasStdExtZvbb();
22434 return Subtarget.hasStdExtZbb() &&
22445 if (Subtarget.hasStdExtZalasr()) {
22446 if (Subtarget.hasStdExtZtso()) {
22451 auto *LI = dyn_cast<LoadInst>(
I);
22452 auto *SI = dyn_cast<StoreInst>(
I);
22462 return isa<LoadInst>(
I) || isa<StoreInst>(
I);
22469 return isa<LoadInst>(
I) || isa<StoreInst>(
I);
22476 if (
Op == Instruction::Add ||
Op == Instruction::Sub ||
22477 Op == Instruction::And ||
Op == Instruction::Or ||
22478 Op == Instruction::Xor ||
Op == Instruction::InsertElement ||
22479 Op == Instruction::ShuffleVector ||
Op == Instruction::Load ||
22480 Op == Instruction::Freeze ||
Op == Instruction::Store)
22488 !isa<ReturnInst>(&Inst))
22491 if (
const AllocaInst *AI = dyn_cast<AllocaInst>(&Inst)) {
22492 if (AI->getAllocatedType()->isScalableTy())
22500RISCVTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
22508 if (!Subtarget.hasShortForwardBranchOpt())
22510 EVT VT =
N->getValueType(0);
22511 if (!(VT == MVT::i32 || (VT == MVT::i64 && Subtarget.
is64Bit())))
22515 if (Divisor.
sgt(2048) || Divisor.
slt(-2048))
22520bool RISCVTargetLowering::shouldFoldSelectWithSingleBitTest(
22521 EVT VT,
const APInt &AndMask)
const {
22522 if (Subtarget.hasStdExtZicond() || Subtarget.hasVendorXVentanaCondOps())
22523 return !Subtarget.hasStdExtZbs() && AndMask.
ugt(1024);
22527unsigned RISCVTargetLowering::getMinimumJumpTableEntries()
const {
22535 if (Subtarget.hasStdExtZicfilp()) {
22559std::pair<const TargetRegisterClass *, uint8_t>
22579#define GET_RISCVVIntrinsicsTable_IMPL
22580#include "RISCVGenSearchableTables.inc"
22595 Align StackAlign)
const {
22599 unsigned StackProbeSize =
22603 return StackProbeSize ? StackProbeSize : StackAlign.
value();
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 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 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 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
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.
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
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 isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
bool hasAndNotCompare(SDValue Y) const override
Return true if the target should transform: (X & Y) == Y —> (~X & Y) == 0 (X & Y) !...
bool shouldScalarizeBinop(SDValue VecOp) const override
Try to convert an extract element of a vector binary operation into an extract element followed by a ...
bool lowerInterleaveIntrinsicToStore(IntrinsicInst *II, StoreInst *SI, SmallVectorImpl< Instruction * > &DeadInsts) const override
Lower an interleave intrinsic to a target specific store intrinsic.
bool isDesirableToCommuteWithShift(const SDNode *N, CombineLevel Level) const override
Return true if it is profitable to move this shift by a constant amount through its operand,...
bool areTwoSDNodeTargetMMOFlagsMergeable(const MemSDNode &NodeX, const MemSDNode &NodeY) const override
Return true if it is valid to merge the TargetMMOFlags in two SDNodes.
bool hasBitTest(SDValue X, SDValue Y) const override
Return true if the target has a bit-test instruction: (X & (1 << Y)) ==/!= 0 This knowledge can be us...
static unsigned computeVLMAX(unsigned VectorBits, unsigned EltSize, unsigned MinSize)
bool shouldExpandCttzElements(EVT VT) const override
Return true if the @llvm.experimental.cttz.elts intrinsic should be expanded using generic code in Se...
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
Value * emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, AtomicCmpXchgInst *CI, Value *AlignedAddr, Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const override
Perform a masked cmpxchg using a target-specific intrinsic.
bool isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize) const override
Returns true if the target can instruction select the specified FP immediate natively.
InstructionCost getLMULCost(MVT VT) const
Return the cost of LMUL for linear operations.
unsigned getJumpTableEncoding() const override
Return the entry encoding for a jump table in the current function.
bool isMulAddWithConstProfitable(SDValue AddNode, SDValue ConstNode) const override
Return true if it may be profitable to transform (mul (add x, c1), c2) -> (add (mul x,...
InstructionCost getVSlideVICost(MVT VT) const
Return the cost of a vslidedown.vi or vslideup.vi instruction for the type VT.
bool fallBackToDAGISel(const Instruction &Inst) const override
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, LLVMContext &Context) const override
This hook should be implemented to check whether the return values described by the Outs array can fi...
bool lowerInterleavedLoad(LoadInst *LI, ArrayRef< ShuffleVectorInst * > Shuffles, ArrayRef< unsigned > Indices, unsigned Factor) const override
Lower an interleaved load into a vlsegN intrinsic.
bool isCtpopFast(EVT VT) const override
Return true if ctpop instruction is fast.
unsigned ComputeNumSignBitsForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
This method can be implemented by targets that want to expose additional information about sign bits ...
MVT getContainerForFixedLengthVector(MVT VT) const
static unsigned getRegClassIDForVecVT(MVT VT)
Register getExceptionPointerRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
TargetLowering::AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return true if EXTRACT_SUBVECTOR is cheap for extracting this result type from this source type with ...
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
MachineMemOperand::Flags getTargetMMOFlags(const Instruction &I) const override
This callback is used to inspect load/store instructions and add target-specific MachineMemOperand fl...
SDValue computeVLMax(MVT VecVT, const SDLoc &DL, SelectionDAG &DAG) const
bool signExtendConstant(const ConstantInt *CI) const override
Return true if this constant should be sign extended when promoting to a larger type.
bool lowerDeinterleaveIntrinsicToLoad(IntrinsicInst *II, LoadInst *LI, SmallVectorImpl< Instruction * > &DeadInsts) const override
Lower a deinterleave intrinsic to a target specific load intrinsic.
bool shouldTransformSignedTruncationCheck(EVT XVT, unsigned KeptBits) const override
Should we tranform the IR-optimal check for whether given truncation down into KeptBits would be trun...
bool shouldProduceAndByConstByHoistingConstFromShiftsLHSOfAnd(SDValue X, ConstantSDNode *XC, ConstantSDNode *CC, SDValue Y, unsigned OldShiftOpcode, unsigned NewShiftOpcode, SelectionDAG &DAG) const override
Given the pattern (X & (C l>>/<< Y)) ==/!= 0 return true if it should be transformed into: ((X <</l>>...
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
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.
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.
@ 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.
ElementCount getVectorElementCount() const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
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.
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)