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 = NormalizedVF / NumOpElts;
5131 unsigned NumOfDestRegs = NormalizedVF / NumOpElts;
5138 unsigned RegCnt = 0;
5139 unsigned PrevCnt = 0;
5141 Mask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs,
5146 [&, &DAG = DAG](
ArrayRef<int> SrcSubMask,
unsigned SrcVecIdx,
5147 unsigned DstVecIdx) {
5148 SDValue SrcVec = SrcVecIdx >= NumOfSrcRegs ? V2 : V1;
5149 unsigned ExtractIdx = (SrcVecIdx % NumOfSrcRegs) * NumOpElts;
5158 [&, &DAG = DAG](
ArrayRef<int> SrcSubMask,
unsigned Idx1,
unsigned Idx2) {
5159 if (PrevCnt + 1 == RegCnt)
5161 SDValue SubVec1 = SubRegs[PrevCnt + 1];
5163 SDValue SrcVec = Idx1 >= NumOfSrcRegs ? V2 : V1;
5164 unsigned ExtractIdx = (Idx1 % NumOfSrcRegs) * NumOpElts;
5169 SDValue SrcVec = Idx2 >= NumOfSrcRegs ? V2 : V1;
5170 unsigned ExtractIdx = (Idx2 % NumOfSrcRegs) * NumOpElts;
5177 SubRegs[PrevCnt + 1] = SubVec1;
5179 assert(RegCnt == NumOfDestRegs &&
"Whole vector must be processed");
5184 unsigned InsertIdx =
I * NumOpElts;
5197 bool SawUndef =
false;
5198 for (
unsigned i = 0; i < Mask.size(); i++) {
5199 if (Mask[i] == -1) {
5205 if (i > (
unsigned)Mask[i])
5207 if (Mask[i] <=
Last)
5238 for (
int Idx : Mask) {
5241 unsigned SrcIdx =
Idx % Mask.size();
5243 if (Srcs[SrcIdx] == -1)
5246 else if (Srcs[SrcIdx] != Src)
5252 for (
int Lane : Srcs) {
5265 for (
unsigned I = 0;
I < Mask.size();
I++) {
5269 NewMask[
I] = Mask[
I] % Mask.size();
5281 MVT VT =
Op.getSimpleValueType();
5296 V2 = V2.isUndef() ? DAG.
getUNDEF(WidenVT)
5320 V.getOperand(0).getSimpleValueType().getVectorNumElements();
5321 V = V.getOperand(
Offset / OpElements);
5327 auto *Ld = cast<LoadSDNode>(V);
5337 SDValue Ops[] = {Ld->getChain(),
5351 MVT SplatVT = ContainerVT;
5354 if (SVT == MVT::bf16 ||
5355 (SVT == MVT::f16 && !Subtarget.hasStdExtZfh())) {
5364 V = DAG.
getLoad(SVT,
DL, Ld->getChain(), NewAddr,
5365 Ld->getPointerInfo().getWithOffset(
Offset),
5366 Ld->getOriginalAlign(),
5370 Ld->getPointerInfo().getWithOffset(
Offset), SVT,
5371 Ld->getOriginalAlign(),
5372 Ld->getMemOperand()->getFlags());
5384 assert(Lane < (
int)NumElts &&
"Unexpected lane!");
5387 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
5409 if (Subtarget.hasStdExtZvkb())
5420 LoV = LoSrc == 0 ? V1 : V2;
5424 HiV = HiSrc == 0 ? V1 : V2;
5430 unsigned InvRotate = NumElts - Rotation;
5440 Res =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, Res, LoV,
5458 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
5459 for (
unsigned Factor = 2; Factor <= MaxFactor; Factor <<= 1) {
5475 int EvenSrc, OddSrc;
5483 bool LaneIsUndef[2] = {
true,
true};
5484 for (
unsigned i = 0; i < Mask.size(); i++)
5485 LaneIsUndef[i % 2] &= (Mask[i] == -1);
5487 int Size = Mask.size();
5489 if (LaneIsUndef[0]) {
5492 assert(EvenSrc >= 0 &&
"Undef source?");
5493 EvenV = (EvenSrc /
Size) == 0 ? V1 : V2;
5498 if (LaneIsUndef[1]) {
5501 assert(OddSrc >= 0 &&
"Undef source?");
5502 OddV = (OddSrc /
Size) == 0 ? V1 : V2;
5512 assert(!V1.
isUndef() &&
"Unexpected shuffle canonicalization");
5527 for (
auto Idx : Mask) {
5543 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
5544 for (
unsigned Factor = 4; Factor <= MaxFactor; Factor <<= 1) {
5557 any_of(Mask, [&](
const auto &
Idx) {
return Idx > 255; })) {
5586 MVT IndexContainerVT =
5591 for (
int MaskIndex : Mask) {
5592 bool IsLHSIndex = MaskIndex < (int)NumElts && MaskIndex >= 0;
5601 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
5611 for (
int MaskIndex : Mask) {
5612 bool IsLHSOrUndefIndex = MaskIndex < (int)NumElts;
5613 ShuffleMaskLHS.
push_back(IsLHSOrUndefIndex && MaskIndex >= 0
5615 ShuffleMaskRHS.
push_back(IsLHSOrUndefIndex ? -1 : (MaskIndex - NumElts));
5641 for (
int MaskIndex : Mask) {
5642 bool SelectMaskVal = (MaskIndex < (int)NumElts) ^ !SwapOps;
5646 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
5678RISCVTargetLowering::lowerCTLZ_CTTZ_ZERO_UNDEF(
SDValue Op,
5680 MVT VT =
Op.getSimpleValueType();
5684 MVT ContainerVT = VT;
5687 if (
Op->isVPOpcode()) {
5688 Mask =
Op.getOperand(1);
5692 VL =
Op.getOperand(2);
5698 MVT FloatEltVT = (EltSize >= 32) ? MVT::f64 : MVT::f32;
5700 FloatEltVT = MVT::f32;
5707 "Expected legal float type!");
5714 }
else if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF) {
5717 Src = DAG.
getNode(ISD::VP_AND,
DL, VT, Src, Neg, Mask, VL);
5722 if (FloatVT.
bitsGT(VT)) {
5723 if (
Op->isVPOpcode())
5724 FloatVal = DAG.
getNode(ISD::VP_UINT_TO_FP,
DL, FloatVT, Src, Mask, VL);
5733 if (!
Op->isVPOpcode())
5737 MVT ContainerFloatVT =
5740 Src, Mask, RTZRM, VL);
5747 unsigned ShiftAmt = FloatEltVT == MVT::f64 ? 52 : 23;
5751 if (
Op->isVPOpcode()) {
5760 else if (IntVT.
bitsGT(VT))
5765 unsigned ExponentBias = FloatEltVT == MVT::f64 ? 1023 : 127;
5770 if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF)
5771 return DAG.
getNode(ISD::VP_SUB,
DL, VT, Exp,
5776 unsigned Adjust = ExponentBias + (EltSize - 1);
5778 if (
Op->isVPOpcode())
5788 else if (
Op.getOpcode() == ISD::VP_CTLZ)
5789 Res = DAG.
getNode(ISD::VP_UMIN,
DL, VT, Res,
5799 MVT SrcVT =
Source.getSimpleValueType();
5808 SrcVT = ContainerVT;
5821 if (
Op->getOpcode() == ISD::VP_CTTZ_ELTS_ZERO_UNDEF)
5838 auto *
Load = cast<LoadSDNode>(
Op);
5839 assert(Load &&
Load->getMemoryVT().isVector() &&
"Expected vector load");
5842 Load->getMemoryVT(),
5843 *
Load->getMemOperand()))
5847 MVT VT =
Op.getSimpleValueType();
5849 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
5850 "Unexpected unaligned RVV load type");
5854 "Expecting equally-sized RVV vector types to be legal");
5856 Load->getPointerInfo(),
Load->getOriginalAlign(),
5857 Load->getMemOperand()->getFlags());
5867 auto *
Store = cast<StoreSDNode>(
Op);
5868 assert(Store &&
Store->getValue().getValueType().isVector() &&
5869 "Expected vector store");
5872 Store->getMemoryVT(),
5873 *
Store->getMemOperand()))
5880 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
5881 "Unexpected unaligned RVV store type");
5885 "Expecting equally-sized RVV vector types to be legal");
5886 StoredVal = DAG.
getBitcast(NewVT, StoredVal);
5888 Store->getPointerInfo(),
Store->getOriginalAlign(),
5889 Store->getMemOperand()->getFlags());
5894 assert(
Op.getValueType() == MVT::i64 &&
"Unexpected VT");
5896 int64_t Imm = cast<ConstantSDNode>(
Op)->getSExtValue();
5923 unsigned ShiftAmt, AddOpc;
5934 MVT VT =
Op.getSimpleValueType();
5935 const APFloat &
Imm = cast<ConstantFPSDNode>(
Op)->getValueAPF();
5938 bool Negate =
false;
5942 if (Index < 0 &&
Imm.isNegative()) {
5970 if (Subtarget.hasStdExtZtso()) {
5994 MVT VT =
Op.getSimpleValueType();
5996 unsigned Check =
Op.getConstantOperandVal(1);
5997 unsigned TDCMask = 0;
6025 MVT VT0 =
Op.getOperand(0).getSimpleValueType();
6030 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6032 VL =
Op.getOperand(3);
6035 VL,
Op->getFlags());
6050 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6052 MVT MaskContainerVT =
6055 VL =
Op.getOperand(3);
6060 Mask, VL,
Op->getFlags());
6063 DAG.
getUNDEF(ContainerDstVT), TDCMaskV, VL);
6068 DAG.
getUNDEF(ContainerVT), Mask, VL});
6072 TDCMaskV, DAG.
getUNDEF(ContainerDstVT), Mask, VL);
6076 DAG.
getUNDEF(ContainerDstVT), SplatZero, VL);
6080 DAG.
getUNDEF(ContainerVT), Mask, VL});
6096 MVT VT =
Op.getSimpleValueType();
6123 return DAG.
getNode(Opc,
DL, VT, NewX, NewY);
6130 MVT ContainerVT = VT;
6138 if (
Op->isVPOpcode()) {
6139 Mask =
Op.getOperand(2);
6143 VL =
Op.getOperand(3);
6151 {X, X, DAG.getCondCode(ISD::SETOEQ),
6152 DAG.getUNDEF(ContainerVT), Mask, VL});
6160 {Y, Y, DAG.getCondCode(ISD::SETOEQ),
6161 DAG.getUNDEF(ContainerVT), Mask, VL});
6171 DAG.
getUNDEF(ContainerVT), Mask, VL);
6181 "Wrong opcode for lowering FABS or FNEG.");
6184 MVT VT =
Op.getSimpleValueType();
6185 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
6192 Mask = Mask.sext(Subtarget.
getXLen());
6205 MVT VT =
Op.getSimpleValueType();
6206 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
6216 if (SignSize == Subtarget.
getXLen()) {
6218 }
else if (SignSize == 16) {
6220 }
else if (SignSize == 32) {
6222 }
else if (SignSize == 64) {
6223 assert(XLenVT == MVT::i32 &&
"Unexpected type");
6233 if (ShiftAmount > 0) {
6236 }
else if (ShiftAmount < 0) {
6262#define OP_CASE(NODE) \
6264 return RISCVISD::NODE##_VL;
6265#define VP_CASE(NODE) \
6266 case ISD::VP_##NODE: \
6267 return RISCVISD::NODE##_VL;
6269 switch (
Op.getOpcode()) {
6347 case ISD::VP_CTLZ_ZERO_UNDEF:
6350 case ISD::VP_CTTZ_ZERO_UNDEF:
6359 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
6364 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
6369 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
6372 case ISD::VP_SELECT:
6381 case ISD::VP_SIGN_EXTEND:
6383 case ISD::VP_ZERO_EXTEND:
6385 case ISD::VP_FP_TO_SINT:
6387 case ISD::VP_FP_TO_UINT:
6390 case ISD::VP_FMINNUM:
6393 case ISD::VP_FMAXNUM:
6398 case ISD::VP_LLRINT:
6410 "not a RISC-V target specific op");
6414 "adding target specific op should update this function");
6434 "not a RISC-V target specific op");
6438 "adding target specific op should update this function");
6451 if (
Op.getValueType() == MVT::nxv32f16 &&
6455 if (
Op.getValueType() == MVT::nxv32bf16)
6468 if (!
Op.getOperand(j).getValueType().isVector()) {
6469 LoOperands[j] =
Op.getOperand(j);
6470 HiOperands[j] =
Op.getOperand(j);
6473 std::tie(LoOperands[j], HiOperands[j]) =
6478 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
6480 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
6495 std::tie(LoOperands[j], HiOperands[j]) =
6499 if (!
Op.getOperand(j).getValueType().isVector()) {
6500 LoOperands[j] =
Op.getOperand(j);
6501 HiOperands[j] =
Op.getOperand(j);
6504 std::tie(LoOperands[j], HiOperands[j]) =
6509 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
6511 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
6521 auto [EVLLo, EVLHi] =
6522 DAG.
SplitEVL(
Op.getOperand(3),
Op.getOperand(1).getValueType(),
DL);
6526 {Op.getOperand(0), Lo, MaskLo, EVLLo},
Op->getFlags());
6528 {ResLo, Hi, MaskHi, EVLHi},
Op->getFlags());
6546 if (!
Op.getOperand(j).getValueType().isVector()) {
6547 LoOperands[j] =
Op.getOperand(j);
6548 HiOperands[j] =
Op.getOperand(j);
6551 std::tie(LoOperands[j], HiOperands[j]) =
6556 DAG.
getNode(
Op.getOpcode(),
DL, LoVTs, LoOperands,
Op->getFlags());
6559 DAG.
getNode(
Op.getOpcode(),
DL, HiVTs, HiOperands,
Op->getFlags());
6568 switch (
Op.getOpcode()) {
6574 return lowerGlobalAddress(
Op, DAG);
6576 return lowerBlockAddress(
Op, DAG);
6578 return lowerConstantPool(
Op, DAG);
6580 return lowerJumpTable(
Op, DAG);
6582 return lowerGlobalTLSAddress(
Op, DAG);
6586 return lowerConstantFP(
Op, DAG);
6588 return lowerSELECT(
Op, DAG);
6590 return lowerBRCOND(
Op, DAG);
6592 return lowerVASTART(
Op, DAG);
6594 return lowerFRAMEADDR(
Op, DAG);
6596 return lowerRETURNADDR(
Op, DAG);
6598 return lowerShiftLeftParts(
Op, DAG);
6600 return lowerShiftRightParts(
Op, DAG,
true);
6602 return lowerShiftRightParts(
Op, DAG,
false);
6605 if (
Op.getValueType().isFixedLengthVector()) {
6606 assert(Subtarget.hasStdExtZvkb());
6607 return lowerToScalableOp(
Op, DAG);
6609 assert(Subtarget.hasVendorXTHeadBb() &&
6610 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
6611 "Unexpected custom legalization");
6613 if (!isa<ConstantSDNode>(
Op.getOperand(1)))
6618 EVT VT =
Op.getValueType();
6622 if (Op0VT == MVT::i16 &&
6624 (VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
6628 if (VT == MVT::f32 && Op0VT == MVT::i32 && Subtarget.
is64Bit() &&
6633 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.
is64Bit() &&
6649 "Unexpected types");
6683 return LowerINTRINSIC_WO_CHAIN(
Op, DAG);
6685 return LowerINTRINSIC_W_CHAIN(
Op, DAG);
6687 return LowerINTRINSIC_VOID(
Op, DAG);
6689 return LowerIS_FPCLASS(
Op, DAG);
6691 MVT VT =
Op.getSimpleValueType();
6693 assert(Subtarget.hasStdExtZvbb());
6694 return lowerToScalableOp(
Op, DAG);
6697 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected custom legalization");
6707 if (!
Op.getSimpleValueType().isVector())
6709 return lowerVectorTruncLike(
Op, DAG);
6712 if (
Op.getOperand(0).getValueType().isVector() &&
6713 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
6714 return lowerVectorMaskExt(
Op, DAG, 1);
6717 if (
Op.getOperand(0).getValueType().isVector() &&
6718 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
6719 return lowerVectorMaskExt(
Op, DAG, -1);
6722 return lowerSPLAT_VECTOR_PARTS(
Op, DAG);
6724 return lowerINSERT_VECTOR_ELT(
Op, DAG);
6726 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
6728 MVT VT =
Op.getSimpleValueType();
6736 MVT ContainerVT = VT;
6744 DAG.
getUNDEF(ContainerVT), Scalar, VL);
6748 DAG.
getUNDEF(ContainerVT), Scalar, VL);
6756 MVT VT =
Op.getSimpleValueType();
6776 }
else if ((Val % 8) == 0) {
6792 if (
Op.getValueType() == MVT::f16 && Subtarget.
is64Bit() &&
6793 Op.getOperand(1).getValueType() == MVT::i32) {
6810 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
6813 return lowerStrictFPExtendOrRoundLike(
Op, DAG);
6816 if (
Op.getValueType().isVector() &&
6817 ((
Op.getValueType().getScalarType() == MVT::f16 &&
6820 Op.getValueType().getScalarType() == MVT::bf16)) {
6836 Op1.getValueType().isVector() &&
6837 ((Op1.getValueType().getScalarType() == MVT::f16 &&
6840 Op1.getValueType().getScalarType() == MVT::bf16)) {
6846 Op1.getValueType().getVectorElementCount());
6849 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), WidenVec);
6859 MVT VT =
Op.getSimpleValueType();
6862 bool IsStrict =
Op->isStrictFPOpcode();
6863 SDValue Src =
Op.getOperand(0 + IsStrict);
6864 MVT SrcVT = Src.getSimpleValueType();
6875 "Unexpected vector element types");
6879 if (EltSize > (2 * SrcEltSize)) {
6891 Op.getOperand(0), Ext);
6895 assert(SrcEltVT == MVT::f16 &&
"Unexpected FP_TO_[US]INT lowering");
6900 auto [FExt, Chain] =
6902 return DAG.
getNode(
Op.getOpcode(),
DL,
Op->getVTList(), Chain, FExt);
6909 if (SrcEltSize > (2 * EltSize)) {
6912 assert(EltVT == MVT::f16 &&
"Unexpected [US]_TO_FP lowering");
6917 Op.getOperand(0), Src);
6932 Op.getOperand(0), Src);
6946 unsigned RVVOpc = 0;
6947 switch (
Op.getOpcode()) {
6979 "Expected same element count");
6986 Op.getOperand(0), Src, Mask, VL);
6990 Src = DAG.
getNode(RVVOpc,
DL, ContainerVT, Src, Mask, VL);
7005 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
7012 MVT VT =
Op.getSimpleValueType();
7032 bool IsStrict =
Op->isStrictFPOpcode();
7033 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7037 std::tie(Res, Chain) =
7038 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
7053 bool IsStrict =
Op->isStrictFPOpcode();
7054 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7060 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
7061 CallOptions,
DL, Chain);
7078 if (
Op.getValueType().isVector())
7083 assert(
Op.getOperand(0).getValueType() == MVT::f16 &&
7084 "Unexpected custom legalisation");
7087 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), Ext);
7093 assert(
Op.getOperand(1).getValueType() == MVT::f16 &&
7094 "Unexpected custom legalisation");
7097 {
Op.getOperand(0),
Op.getOperand(1)});
7098 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
7099 {Ext.getValue(1), Ext.getValue(0)});
7106 return lowerVECREDUCE(
Op, DAG);
7110 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7111 return lowerVectorMaskVecReduction(
Op, DAG,
false);
7112 return lowerVECREDUCE(
Op, DAG);
7119 return lowerFPVECREDUCE(
Op, DAG);
7120 case ISD::VP_REDUCE_ADD:
7121 case ISD::VP_REDUCE_UMAX:
7122 case ISD::VP_REDUCE_SMAX:
7123 case ISD::VP_REDUCE_UMIN:
7124 case ISD::VP_REDUCE_SMIN:
7125 case ISD::VP_REDUCE_FADD:
7126 case ISD::VP_REDUCE_SEQ_FADD:
7127 case ISD::VP_REDUCE_FMIN:
7128 case ISD::VP_REDUCE_FMAX:
7129 case ISD::VP_REDUCE_FMINIMUM:
7130 case ISD::VP_REDUCE_FMAXIMUM:
7133 return lowerVPREDUCE(
Op, DAG);
7134 case ISD::VP_REDUCE_AND:
7135 case ISD::VP_REDUCE_OR:
7136 case ISD::VP_REDUCE_XOR:
7137 if (
Op.getOperand(1).getValueType().getVectorElementType() == MVT::i1)
7138 return lowerVectorMaskVecReduction(
Op, DAG,
true);
7139 return lowerVPREDUCE(
Op, DAG);
7140 case ISD::VP_CTTZ_ELTS:
7141 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
7142 return lowerVPCttzElements(
Op, DAG);
7146 DAG.
getUNDEF(ContainerVT), DAG, Subtarget);
7149 return lowerINSERT_SUBVECTOR(
Op, DAG);
7151 return lowerEXTRACT_SUBVECTOR(
Op, DAG);
7153 return lowerVECTOR_DEINTERLEAVE(
Op, DAG);
7155 return lowerVECTOR_INTERLEAVE(
Op, DAG);
7157 return lowerSTEP_VECTOR(
Op, DAG);
7159 return lowerVECTOR_REVERSE(
Op, DAG);
7161 return lowerVECTOR_SPLICE(
Op, DAG);
7165 MVT VT =
Op.getSimpleValueType();
7167 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
7168 EltVT == MVT::bf16) {
7171 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
7172 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
7182 if (EltVT == MVT::i1)
7183 return lowerVectorMaskSplat(
Op, DAG);
7192 MVT VT =
Op.getSimpleValueType();
7193 MVT ContainerVT = VT;
7211 Op->ops().take_front(HalfNumOps));
7213 Op->ops().drop_front(HalfNumOps));
7217 unsigned NumOpElts =
7218 Op.getOperand(0).getSimpleValueType().getVectorMinNumElements();
7221 SDValue SubVec = OpIdx.value();
7232 auto *Load = cast<LoadSDNode>(
Op);
7233 EVT VecTy = Load->getMemoryVT();
7240 unsigned NumElts = Sz / (NF * 8);
7241 int Log2LMUL =
Log2_64(NumElts) - 3;
7244 Flag.setNoUnsignedWrap(
true);
7246 SDValue BasePtr = Load->getBasePtr();
7254 for (
unsigned i = 0; i < NF; ++i) {
7267 if (
auto V = expandUnalignedRVVLoad(
Op, DAG))
7269 if (
Op.getValueType().isFixedLengthVector())
7270 return lowerFixedLengthVectorLoadToRVV(
Op, DAG);
7274 auto *Store = cast<StoreSDNode>(
Op);
7275 SDValue StoredVal = Store->getValue();
7283 unsigned NumElts = Sz / (NF * 8);
7284 int Log2LMUL =
Log2_64(NumElts) - 3;
7287 Flag.setNoUnsignedWrap(
true);
7289 SDValue Chain = Store->getChain();
7290 SDValue BasePtr = Store->getBasePtr();
7297 for (
unsigned i = 0; i < NF; ++i) {
7301 Ret = DAG.
getStore(Chain,
DL, Extract, BasePtr,
7303 Store->getOriginalAlign(),
7304 Store->getMemOperand()->getFlags());
7305 Chain = Ret.getValue(0);
7311 if (
auto V = expandUnalignedRVVStore(
Op, DAG))
7313 if (
Op.getOperand(1).getValueType().isFixedLengthVector())
7314 return lowerFixedLengthVectorStoreToRVV(
Op, DAG);
7319 return lowerMaskedLoad(
Op, DAG);
7322 return lowerMaskedStore(
Op, DAG);
7324 return lowerVectorCompress(
Op, DAG);
7333 EVT VT =
Op.getValueType();
7344 MVT OpVT =
Op.getOperand(0).getSimpleValueType();
7346 MVT VT =
Op.getSimpleValueType();
7351 "Unexpected CondCode");
7359 if (isa<ConstantSDNode>(
RHS)) {
7360 int64_t Imm = cast<ConstantSDNode>(
RHS)->getSExtValue();
7361 if (Imm != 0 && isInt<12>((
uint64_t)Imm + 1)) {
7383 return lowerFixedLengthVectorSetccToRVV(
Op, DAG);
7399 return lowerToScalableOp(
Op, DAG);
7403 if (
Op.getSimpleValueType().isFixedLengthVector())
7404 return lowerToScalableOp(
Op, DAG);
7406 assert(
Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.
is64Bit() &&
7407 "Unexpected custom legalisation");
7411 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
7437 return lowerToScalableOp(
Op, DAG);
7441 EVT VT =
Op->getValueType(0);
7456 return lowerABS(
Op, DAG);
7461 if (Subtarget.hasStdExtZvbb())
7462 return lowerToScalableOp(
Op, DAG);
7464 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
7466 return lowerFixedLengthVectorSelectToRVV(
Op, DAG);
7468 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
7472 return lowerFixedLengthVectorFCOPYSIGNToRVV(
Op, DAG);
7481 return lowerToScalableOp(
Op, DAG);
7484 return lowerVectorStrictFSetcc(
Op, DAG);
7494 case ISD::VP_GATHER:
7495 return lowerMaskedGather(
Op, DAG);
7497 case ISD::VP_SCATTER:
7498 return lowerMaskedScatter(
Op, DAG);
7500 return lowerGET_ROUNDING(
Op, DAG);
7502 return lowerSET_ROUNDING(
Op, DAG);
7504 return lowerEH_DWARF_CFA(
Op, DAG);
7506 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7507 return lowerVPMergeMask(
Op, DAG);
7509 case ISD::VP_SELECT:
7517 case ISD::VP_UADDSAT:
7518 case ISD::VP_USUBSAT:
7519 case ISD::VP_SADDSAT:
7520 case ISD::VP_SSUBSAT:
7522 case ISD::VP_LLRINT:
7523 return lowerVPOp(
Op, DAG);
7527 return lowerLogicVPOp(
Op, DAG);
7536 case ISD::VP_FMINNUM:
7537 case ISD::VP_FMAXNUM:
7538 case ISD::VP_FCOPYSIGN:
7545 return lowerVPOp(
Op, DAG);
7546 case ISD::VP_IS_FPCLASS:
7547 return LowerIS_FPCLASS(
Op, DAG);
7548 case ISD::VP_SIGN_EXTEND:
7549 case ISD::VP_ZERO_EXTEND:
7550 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
7551 return lowerVPExtMaskOp(
Op, DAG);
7552 return lowerVPOp(
Op, DAG);
7553 case ISD::VP_TRUNCATE:
7554 return lowerVectorTruncLike(
Op, DAG);
7555 case ISD::VP_FP_EXTEND:
7556 case ISD::VP_FP_ROUND:
7557 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
7558 case ISD::VP_SINT_TO_FP:
7559 case ISD::VP_UINT_TO_FP:
7560 if (
Op.getValueType().isVector() &&
7561 ((
Op.getValueType().getScalarType() == MVT::f16 &&
7564 Op.getValueType().getScalarType() == MVT::bf16)) {
7577 case ISD::VP_FP_TO_SINT:
7578 case ISD::VP_FP_TO_UINT:
7580 Op1.getValueType().isVector() &&
7581 ((Op1.getValueType().getScalarType() == MVT::f16 &&
7584 Op1.getValueType().getScalarType() == MVT::bf16)) {
7590 Op1.getValueType().getVectorElementCount());
7594 {WidenVec, Op.getOperand(1), Op.getOperand(2)});
7596 return lowerVPFPIntConvOp(
Op, DAG);
7600 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
7601 return lowerVPSetCCMaskOp(
Op, DAG);
7607 case ISD::VP_BITREVERSE:
7609 return lowerVPOp(
Op, DAG);
7611 case ISD::VP_CTLZ_ZERO_UNDEF:
7612 if (Subtarget.hasStdExtZvbb())
7613 return lowerVPOp(
Op, DAG);
7614 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
7616 case ISD::VP_CTTZ_ZERO_UNDEF:
7617 if (Subtarget.hasStdExtZvbb())
7618 return lowerVPOp(
Op, DAG);
7619 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
7621 return lowerVPOp(
Op, DAG);
7622 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
7623 return lowerVPStridedLoad(
Op, DAG);
7624 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
7625 return lowerVPStridedStore(
Op, DAG);
7627 case ISD::VP_FFLOOR:
7629 case ISD::VP_FNEARBYINT:
7630 case ISD::VP_FROUND:
7631 case ISD::VP_FROUNDEVEN:
7632 case ISD::VP_FROUNDTOZERO:
7636 case ISD::VP_FMAXIMUM:
7637 case ISD::VP_FMINIMUM:
7641 case ISD::EXPERIMENTAL_VP_SPLICE:
7642 return lowerVPSpliceExperimental(
Op, DAG);
7643 case ISD::EXPERIMENTAL_VP_REVERSE:
7644 return lowerVPReverseExperimental(
Op, DAG);
7645 case ISD::EXPERIMENTAL_VP_SPLAT:
7646 return lowerVPSplatExperimental(
Op, DAG);
7649 "llvm.clear_cache only needs custom lower on Linux targets");
7652 return emitFlushICache(DAG,
Op.getOperand(0),
Op.getOperand(1),
7653 Op.getOperand(2), Flags,
DL);
7656 return lowerINIT_TRAMPOLINE(
Op, DAG);
7658 return lowerADJUST_TRAMPOLINE(
Op, DAG);
7665 MakeLibCallOptions CallOptions;
7666 std::pair<SDValue, SDValue> CallResult =
7667 makeLibCall(DAG, RTLIB::RISCV_FLUSH_ICACHE, MVT::isVoid,
7668 {Start,
End, Flags}, CallOptions,
DL, InChain);
7671 return CallResult.second;
7684 std::unique_ptr<MCCodeEmitter> CodeEmitter(
7691 const Value *TrmpAddr = cast<SrcValueSDNode>(
Op.getOperand(4))->getValue();
7703 constexpr unsigned StaticChainOffset = 16;
7704 constexpr unsigned FunctionAddressOffset = 24;
7708 auto GetEncoding = [&](
const MCInst &MC) {
7711 CodeEmitter->encodeInstruction(MC, CB, Fixups, *STI);
7721 GetEncoding(
MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X7).addImm(0)),
7726 MCInstBuilder(RISCV::LD).addReg(RISCV::X5).addReg(RISCV::X7).addImm(
7727 FunctionAddressOffset)),
7731 MCInstBuilder(RISCV::LD).addReg(RISCV::X7).addReg(RISCV::X7).addImm(
7732 StaticChainOffset)),
7751 SDValue FunctionAddress =
Op.getOperand(2);
7755 struct OffsetValuePair {
7759 } OffsetValues[] = {
7760 {StaticChainOffset, StaticChain},
7761 {FunctionAddressOffset, FunctionAddress},
7766 DAG.
getConstant(OffsetValue.Offset, dl, MVT::i64));
7767 OffsetValue.Addr =
Addr;
7768 OutChains[
Idx + 4] =
7777 SDValue EndOfTrmp = OffsetValues[0].Addr;
7791 return Op.getOperand(0);
7808 N->getOffset(), Flags);
7837template <
class NodeTy>
7839 bool IsLocal,
bool IsExternWeak)
const {
7849 if (IsLocal && !Subtarget.allowTaggedGlobals())
7919 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
7928 return getAddr(
N, DAG);
7935 return getAddr(
N, DAG);
7942 return getAddr(
N, DAG);
7947 bool UseGOT)
const {
8011 Args.push_back(Entry);
8044 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
8058 Addr = getStaticTLSAddr(
N, DAG,
false);
8061 Addr = getStaticTLSAddr(
N, DAG,
true);
8066 : getDynamicTLSAddr(
N, DAG);
8083 if (
LHS == LHS2 &&
RHS == RHS2) {
8088 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
8096 return std::nullopt;
8104 MVT VT =
N->getSimpleValueType(0);
8134 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV)) {
8137 if (~TrueVal == FalseVal) {
8177 if (Subtarget.hasShortForwardBranchOpt())
8180 unsigned SelOpNo = 0;
8190 unsigned ConstSelOpNo = 1;
8191 unsigned OtherSelOpNo = 2;
8192 if (!dyn_cast<ConstantSDNode>(Sel->
getOperand(ConstSelOpNo))) {
8197 ConstantSDNode *ConstSelOpNode = dyn_cast<ConstantSDNode>(ConstSelOp);
8198 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
8202 ConstantSDNode *ConstBinOpNode = dyn_cast<ConstantSDNode>(ConstBinOp);
8203 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
8209 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
8211 std::swap(NewConstOps[0], NewConstOps[1]);
8223 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
8225 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
8228 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
8229 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
8238 MVT VT =
Op.getSimpleValueType();
8252 if ((Subtarget.hasStdExtZicond() || Subtarget.hasVendorXVentanaCondOps()) &&
8280 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV)) {
8284 TrueVal, Subtarget.
getXLen(), Subtarget,
true);
8286 FalseVal, Subtarget.
getXLen(), Subtarget,
true);
8287 bool IsCZERO_NEZ = TrueValCost <= FalseValCost;
8289 IsCZERO_NEZ ? FalseVal - TrueVal : TrueVal - FalseVal,
DL, VT);
8294 DL, VT, LHSVal, CondV);
8310 if (
Op.hasOneUse()) {
8311 unsigned UseOpc =
Op->user_begin()->getOpcode();
8320 return lowerSELECT(NewSel, DAG);
8349 SDValue Ops[] = {CondV,
Zero, SetNE, TrueV, FalseV};
8370 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV) &&
8374 if (TrueVal - 1 == FalseVal)
8376 if (TrueVal + 1 == FalseVal)
8383 RHS == TrueV && LHS == FalseV) {
8400 if (isa<ConstantSDNode>(TrueV) && !isa<ConstantSDNode>(FalseV)) {
8426 LHS, RHS, TargetCC,
Op.getOperand(2));
8444 const Value *SV = cast<SrcValueSDNode>(
Op.getOperand(2))->getValue();
8456 int XLenInBytes = Subtarget.
getXLen() / 8;
8458 EVT VT =
Op.getValueType();
8461 unsigned Depth =
Op.getConstantOperandVal(0);
8463 int Offset = -(XLenInBytes * 2);
8480 int XLenInBytes = Subtarget.
getXLen() / 8;
8485 EVT VT =
Op.getValueType();
8487 unsigned Depth =
Op.getConstantOperandVal(0);
8489 int Off = -XLenInBytes;
8490 SDValue FrameAddr = lowerFRAMEADDR(
Op, DAG);
8509 EVT VT =
Lo.getValueType();
8548 EVT VT =
Lo.getValueType();
8599 MVT VT =
Op.getSimpleValueType();
8625 MVT VecVT =
Op.getSimpleValueType();
8627 "Unexpected SPLAT_VECTOR_PARTS lowering");
8633 MVT ContainerVT = VecVT;
8653 int64_t ExtTrueVal)
const {
8655 MVT VecVT =
Op.getSimpleValueType();
8658 assert(Src.getValueType().isVector() &&
8659 Src.getValueType().getVectorElementType() == MVT::i1);
8680 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
8682 DAG.
getUNDEF(ContainerVT), SplatTrueVal, VL);
8685 SplatZero, DAG.
getUNDEF(ContainerVT), VL);
8690SDValue RISCVTargetLowering::lowerFixedLengthVectorExtendToRVV(
8692 MVT ExtVT =
Op.getSimpleValueType();
8696 MVT VT =
Op.getOperand(0).getSimpleValueType();
8722 bool IsVPTrunc =
Op.getOpcode() == ISD::VP_TRUNCATE;
8724 EVT MaskVT =
Op.getValueType();
8727 "Unexpected type for vector mask lowering");
8729 MVT VecVT = Src.getSimpleValueType();
8733 VL =
Op.getOperand(2);
8736 MVT ContainerVT = VecVT;
8742 MVT MaskContainerVT =
8749 std::tie(Mask, VL) =
8757 DAG.
getUNDEF(ContainerVT), SplatOne, VL);
8759 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
8763 DAG.
getUNDEF(ContainerVT), Mask, VL);
8766 DAG.
getUNDEF(MaskContainerVT), Mask, VL});
8774 unsigned Opc =
Op.getOpcode();
8775 bool IsVPTrunc = Opc == ISD::VP_TRUNCATE;
8778 MVT VT =
Op.getSimpleValueType();
8780 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
8784 return lowerVectorMaskTruncLike(
Op, DAG);
8792 MVT SrcVT = Src.getSimpleValueType();
8797 "Unexpected vector truncate lowering");
8799 MVT ContainerVT = SrcVT;
8803 VL =
Op.getOperand(2);
8816 std::tie(Mask, VL) =
8832 }
while (SrcEltVT != DstEltVT);
8841RISCVTargetLowering::lowerStrictFPExtendOrRoundLike(
SDValue Op,
8846 MVT VT =
Op.getSimpleValueType();
8847 MVT SrcVT = Src.getSimpleValueType();
8848 MVT ContainerVT = VT;
8871 Chain, Src, Mask, VL);
8872 Chain = Src.getValue(1);
8879 Chain, Src, Mask, VL);
8890RISCVTargetLowering::lowerVectorFPExtendOrRoundLike(
SDValue Op,
8893 Op.getOpcode() == ISD::VP_FP_ROUND ||
Op.getOpcode() == ISD::VP_FP_EXTEND;
8900 MVT VT =
Op.getSimpleValueType();
8902 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
8905 MVT SrcVT = Src.getSimpleValueType();
8907 bool IsDirectExtend =
8915 bool IsDirectConv = IsDirectExtend || IsDirectTrunc;
8918 MVT ContainerVT = VT;
8922 VL =
Op.getOperand(2);
8936 std::tie(Mask, VL) =
8942 Src = DAG.
getNode(ConvOpc,
DL, ContainerVT, Src, Mask, VL);
8948 unsigned InterConvOpc =
8953 DAG.
getNode(InterConvOpc,
DL, InterVT, Src, Mask, VL);
8955 DAG.
getNode(ConvOpc,
DL, ContainerVT, IntermediateConv, Mask, VL);
8966static std::optional<MVT>
8972 const unsigned MinVLMAX = VectorBitsMin / EltSize;
8974 if (MaxIdx < MinVLMAX)
8976 else if (MaxIdx < MinVLMAX * 2)
8978 else if (MaxIdx < MinVLMAX * 4)
8983 return std::nullopt;
8996 MVT VecVT =
Op.getSimpleValueType();
9013 ValVT == MVT::bf16) {
9022 MVT ContainerVT = VecVT;
9031 MVT OrigContainerVT = ContainerVT;
9034 if (
auto *IdxC = dyn_cast<ConstantSDNode>(
Idx)) {
9035 const unsigned OrigIdx = IdxC->getZExtValue();
9038 DL, DAG, Subtarget)) {
9039 ContainerVT = *ShrunkVT;
9048 VLEN && ContainerVT.
bitsGT(M1VT)) {
9051 unsigned RemIdx = OrigIdx % ElemsPerVReg;
9052 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
9053 unsigned ExtractIdx =
9070 if (!IsLegalInsert && isa<ConstantSDNode>(Val)) {
9071 const auto *CVal = cast<ConstantSDNode>(Val);
9072 if (isInt<32>(CVal->getSExtValue())) {
9073 IsLegalInsert =
true;
9082 if (IsLegalInsert) {
9088 Vec = DAG.
getNode(Opc,
DL, ContainerVT, Vec, Val, VL);
9104 std::tie(ValLo, ValHi) = DAG.
SplitScalar(Val,
DL, MVT::i32, MVT::i32);
9105 MVT I32ContainerVT =
9116 Vec, Vec, ValLo, I32Mask, InsertI64VL);
9121 Tail, ValInVec, ValHi, I32Mask, InsertI64VL);
9123 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
9128 ValInVec, AlignedIdx);
9138 DAG.
getUNDEF(I32ContainerVT), ValLo,
9139 I32Mask, InsertI64VL);
9141 DAG.
getUNDEF(I32ContainerVT), ValInVec, ValHi,
9142 I32Mask, InsertI64VL);
9144 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
9157 Idx, Mask, InsertVL, Policy);
9161 Slideup, AlignedIdx);
9176 EVT EltVT =
Op.getValueType();
9183 MVT ContainerVT = VecVT;
9199 unsigned WidenVecLen;
9202 unsigned MaxEEW = Subtarget.
getELen();
9207 "the number of elements should be power of 2");
9211 ExtractBitIdx =
Idx;
9213 WideEltVT = LargestEltVT;
9216 ExtractElementIdx = DAG.
getNode(
9227 Vec, ExtractElementIdx);
9243 EltVT == MVT::bf16) {
9253 MVT ContainerVT = VecVT;
9264 if (
auto *IdxC = dyn_cast<ConstantSDNode>(
Idx);
9265 IdxC && VLen && VecVT.
getSizeInBits().getKnownMinValue() > *VLen) {
9267 unsigned OrigIdx = IdxC->getZExtValue();
9270 unsigned RemIdx = OrigIdx % ElemsPerVReg;
9271 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
9272 unsigned ExtractIdx =
9282 std::optional<uint64_t> MaxIdx;
9285 if (
auto *IdxC = dyn_cast<ConstantSDNode>(
Idx))
9286 MaxIdx = IdxC->getZExtValue();
9288 if (
auto SmallerVT =
9290 ContainerVT = *SmallerVT;
9337 "Unexpected opcode");
9344 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
9349 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
9350 if (!
II || !
II->hasScalarOperand())
9353 unsigned SplatOp =
II->ScalarOperand + 1 + HasChain;
9366 if (OpVT.
bitsLT(XLenVT)) {
9373 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
9383 assert(
II->ScalarOperand > 0 &&
"Unexpected splat operand!");
9384 MVT VT =
Op.getOperand(SplatOp - 1).getSimpleValueType();
9387 assert(XLenVT == MVT::i32 && OpVT == MVT::i64 &&
9398 case Intrinsic::riscv_vslide1up:
9399 case Intrinsic::riscv_vslide1down:
9400 case Intrinsic::riscv_vslide1up_mask:
9401 case Intrinsic::riscv_vslide1down_mask: {
9404 bool IsMasked = NumOps == 7;
9410 std::tie(ScalarLo, ScalarHi) =
9418 if (isa<ConstantSDNode>(AVL)) {
9419 const auto [MinVLMAX, MaxVLMAX] =
9423 if (AVLInt <= MinVLMAX) {
9425 }
else if (AVLInt >= 2 * MaxVLMAX) {
9459 if (IntNo == Intrinsic::riscv_vslide1up ||
9460 IntNo == Intrinsic::riscv_vslide1up_mask) {
9462 ScalarHi, I32Mask, I32VL);
9464 ScalarLo, I32Mask, I32VL);
9467 ScalarLo, I32Mask, I32VL);
9469 ScalarHi, I32Mask, I32VL);
9518 const unsigned ElementWidth = 8;
9523 [[maybe_unused]]
unsigned MinVF =
9526 [[maybe_unused]]
unsigned VF =
N->getConstantOperandVal(2);
9530 bool Fractional = VF < LMul1VF;
9531 unsigned LMulVal = Fractional ? LMul1VF / VF : VF / LMul1VF;
9552 MVT ContainerVT = OpVT;
9579 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
9583 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
9584 if (!
II || !
II->hasScalarOperand())
9587 unsigned SplatOp =
II->ScalarOperand + 1;
9600 if (OpVT.
bitsLT(XLenVT)) {
9603 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
9614 EVT ValType = V.getValueType();
9615 if (ValType.isVector() && ValType.isFloatingPoint()) {
9618 ValType.getVectorElementCount());
9621 if (ValType.isFixedLengthVector()) {
9623 DAG, V.getSimpleValueType(), Subtarget);
9639 unsigned IntNo =
Op.getConstantOperandVal(0);
9646 case Intrinsic::riscv_tuple_insert: {
9654 case Intrinsic::riscv_tuple_extract: {
9661 case Intrinsic::thread_pointer: {
9665 case Intrinsic::riscv_orc_b:
9666 case Intrinsic::riscv_brev8:
9667 case Intrinsic::riscv_sha256sig0:
9668 case Intrinsic::riscv_sha256sig1:
9669 case Intrinsic::riscv_sha256sum0:
9670 case Intrinsic::riscv_sha256sum1:
9671 case Intrinsic::riscv_sm3p0:
9672 case Intrinsic::riscv_sm3p1: {
9685 return DAG.
getNode(Opc,
DL, XLenVT,
Op.getOperand(1));
9687 case Intrinsic::riscv_sm4ks:
9688 case Intrinsic::riscv_sm4ed: {
9692 return DAG.
getNode(Opc,
DL, XLenVT,
Op.getOperand(1),
Op.getOperand(2),
9695 case Intrinsic::riscv_zip:
9696 case Intrinsic::riscv_unzip: {
9699 return DAG.
getNode(Opc,
DL, XLenVT,
Op.getOperand(1));
9701 case Intrinsic::riscv_mopr:
9705 case Intrinsic::riscv_moprr: {
9707 Op.getOperand(2),
Op.getOperand(3));
9709 case Intrinsic::riscv_clmul:
9712 case Intrinsic::riscv_clmulh:
9713 case Intrinsic::riscv_clmulr: {
9716 return DAG.
getNode(Opc,
DL, XLenVT,
Op.getOperand(1),
Op.getOperand(2));
9718 case Intrinsic::experimental_get_vector_length:
9720 case Intrinsic::experimental_cttz_elts:
9722 case Intrinsic::riscv_vmv_x_s: {
9726 case Intrinsic::riscv_vfmv_f_s:
9729 case Intrinsic::riscv_vmv_v_x:
9731 Op.getOperand(3),
Op.getSimpleValueType(),
DL, DAG,
9733 case Intrinsic::riscv_vfmv_v_f:
9735 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
9736 case Intrinsic::riscv_vmv_s_x: {
9739 if (
Scalar.getValueType().bitsLE(XLenVT)) {
9742 Op.getOperand(1), Scalar,
Op.getOperand(3));
9745 assert(
Scalar.getValueType() == MVT::i64 &&
"Unexpected scalar VT!");
9762 MVT VT =
Op.getSimpleValueType();
9767 if (
Op.getOperand(1).isUndef())
9783 case Intrinsic::riscv_vfmv_s_f:
9785 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
9787 case Intrinsic::riscv_vaesdf_vv:
9788 case Intrinsic::riscv_vaesdf_vs:
9789 case Intrinsic::riscv_vaesdm_vv:
9790 case Intrinsic::riscv_vaesdm_vs:
9791 case Intrinsic::riscv_vaesef_vv:
9792 case Intrinsic::riscv_vaesef_vs:
9793 case Intrinsic::riscv_vaesem_vv:
9794 case Intrinsic::riscv_vaesem_vs:
9795 case Intrinsic::riscv_vaeskf1:
9796 case Intrinsic::riscv_vaeskf2:
9797 case Intrinsic::riscv_vaesz_vs:
9798 case Intrinsic::riscv_vsm4k:
9799 case Intrinsic::riscv_vsm4r_vv:
9800 case Intrinsic::riscv_vsm4r_vs: {
9801 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
9802 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
9803 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
9808 case Intrinsic::riscv_vsm3c:
9809 case Intrinsic::riscv_vsm3me: {
9810 if (!
isValidEGW(8,
Op.getSimpleValueType(), Subtarget) ||
9811 !
isValidEGW(8,
Op->getOperand(1).getSimpleValueType(), Subtarget))
9816 case Intrinsic::riscv_vsha2ch:
9817 case Intrinsic::riscv_vsha2cl:
9818 case Intrinsic::riscv_vsha2ms: {
9819 if (
Op->getSimpleValueType(0).getScalarSizeInBits() == 64 &&
9820 !Subtarget.hasStdExtZvknhb())
9822 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
9823 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
9824 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
9828 case Intrinsic::riscv_sf_vc_v_x:
9829 case Intrinsic::riscv_sf_vc_v_i:
9830 case Intrinsic::riscv_sf_vc_v_xv:
9831 case Intrinsic::riscv_sf_vc_v_iv:
9832 case Intrinsic::riscv_sf_vc_v_vv:
9833 case Intrinsic::riscv_sf_vc_v_fv:
9834 case Intrinsic::riscv_sf_vc_v_xvv:
9835 case Intrinsic::riscv_sf_vc_v_ivv:
9836 case Intrinsic::riscv_sf_vc_v_vvv:
9837 case Intrinsic::riscv_sf_vc_v_fvv:
9838 case Intrinsic::riscv_sf_vc_v_xvw:
9839 case Intrinsic::riscv_sf_vc_v_ivw:
9840 case Intrinsic::riscv_sf_vc_v_vvw:
9841 case Intrinsic::riscv_sf_vc_v_fvw: {
9842 MVT VT =
Op.getSimpleValueType();
9879 MVT VT =
Op.getSimpleValueType();
9883 if (VT.isFloatingPoint()) {
9888 if (VT.isFixedLengthVector())
9898 if (VT.isFixedLengthVector())
9900 if (VT.isFloatingPoint())
9919 unsigned IntNo =
Op.getConstantOperandVal(1);
9923 case Intrinsic::riscv_seg2_load:
9924 case Intrinsic::riscv_seg3_load:
9925 case Intrinsic::riscv_seg4_load:
9926 case Intrinsic::riscv_seg5_load:
9927 case Intrinsic::riscv_seg6_load:
9928 case Intrinsic::riscv_seg7_load:
9929 case Intrinsic::riscv_seg8_load: {
9932 Intrinsic::riscv_vlseg2, Intrinsic::riscv_vlseg3,
9933 Intrinsic::riscv_vlseg4, Intrinsic::riscv_vlseg5,
9934 Intrinsic::riscv_vlseg6, Intrinsic::riscv_vlseg7,
9935 Intrinsic::riscv_vlseg8};
9936 unsigned NF =
Op->getNumValues() - 1;
9937 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
9939 MVT VT =
Op->getSimpleValueType(0);
9947 auto *
Load = cast<MemIntrinsicSDNode>(
Op);
9959 Load->getMemoryVT(),
Load->getMemOperand());
9961 for (
unsigned int RetIdx = 0; RetIdx < NF; RetIdx++) {
9970 case Intrinsic::riscv_sf_vc_v_x_se:
9972 case Intrinsic::riscv_sf_vc_v_i_se:
9974 case Intrinsic::riscv_sf_vc_v_xv_se:
9976 case Intrinsic::riscv_sf_vc_v_iv_se:
9978 case Intrinsic::riscv_sf_vc_v_vv_se:
9980 case Intrinsic::riscv_sf_vc_v_fv_se:
9982 case Intrinsic::riscv_sf_vc_v_xvv_se:
9984 case Intrinsic::riscv_sf_vc_v_ivv_se:
9986 case Intrinsic::riscv_sf_vc_v_vvv_se:
9988 case Intrinsic::riscv_sf_vc_v_fvv_se:
9990 case Intrinsic::riscv_sf_vc_v_xvw_se:
9992 case Intrinsic::riscv_sf_vc_v_ivw_se:
9994 case Intrinsic::riscv_sf_vc_v_vvw_se:
9996 case Intrinsic::riscv_sf_vc_v_fvw_se:
10005 unsigned IntNo =
Op.getConstantOperandVal(1);
10009 case Intrinsic::riscv_seg2_store:
10010 case Intrinsic::riscv_seg3_store:
10011 case Intrinsic::riscv_seg4_store:
10012 case Intrinsic::riscv_seg5_store:
10013 case Intrinsic::riscv_seg6_store:
10014 case Intrinsic::riscv_seg7_store:
10015 case Intrinsic::riscv_seg8_store: {
10018 Intrinsic::riscv_vsseg2, Intrinsic::riscv_vsseg3,
10019 Intrinsic::riscv_vsseg4, Intrinsic::riscv_vsseg5,
10020 Intrinsic::riscv_vsseg6, Intrinsic::riscv_vsseg7,
10021 Intrinsic::riscv_vsseg8};
10024 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
10026 MVT VT =
Op->getOperand(2).getSimpleValueType();
10036 auto *FixedIntrinsic = cast<MemIntrinsicSDNode>(
Op);
10039 for (
unsigned i = 0; i < NF; i++)
10043 ContainerVT, FixedIntrinsic->getOperand(2 + i), DAG, Subtarget),
10047 FixedIntrinsic->getChain(),
10056 FixedIntrinsic->getMemoryVT(), FixedIntrinsic->getMemOperand());
10058 case Intrinsic::riscv_sf_vc_xv_se:
10060 case Intrinsic::riscv_sf_vc_iv_se:
10062 case Intrinsic::riscv_sf_vc_vv_se:
10064 case Intrinsic::riscv_sf_vc_fv_se:
10066 case Intrinsic::riscv_sf_vc_xvv_se:
10068 case Intrinsic::riscv_sf_vc_ivv_se:
10070 case Intrinsic::riscv_sf_vc_vvv_se:
10072 case Intrinsic::riscv_sf_vc_fvv_se:
10074 case Intrinsic::riscv_sf_vc_xvw_se:
10076 case Intrinsic::riscv_sf_vc_ivw_se:
10078 case Intrinsic::riscv_sf_vc_vvw_se:
10080 case Intrinsic::riscv_sf_vc_fvw_se:
10088 switch (ISDOpcode) {
10091 case ISD::VP_REDUCE_ADD:
10094 case ISD::VP_REDUCE_UMAX:
10097 case ISD::VP_REDUCE_SMAX:
10100 case ISD::VP_REDUCE_UMIN:
10103 case ISD::VP_REDUCE_SMIN:
10106 case ISD::VP_REDUCE_AND:
10109 case ISD::VP_REDUCE_OR:
10112 case ISD::VP_REDUCE_XOR:
10115 case ISD::VP_REDUCE_FADD:
10117 case ISD::VP_REDUCE_SEQ_FADD:
10119 case ISD::VP_REDUCE_FMAX:
10120 case ISD::VP_REDUCE_FMAXIMUM:
10122 case ISD::VP_REDUCE_FMIN:
10123 case ISD::VP_REDUCE_FMINIMUM:
10133 SDValue Vec =
Op.getOperand(IsVP ? 1 : 0);
10138 Op.getOpcode() == ISD::VP_REDUCE_AND ||
10139 Op.getOpcode() == ISD::VP_REDUCE_OR ||
10140 Op.getOpcode() == ISD::VP_REDUCE_XOR) &&
10141 "Unexpected reduction lowering");
10145 MVT ContainerVT = VecVT;
10153 Mask =
Op.getOperand(2);
10154 VL =
Op.getOperand(3);
10156 std::tie(Mask, VL) =
10161 switch (
Op.getOpcode()) {
10165 case ISD::VP_REDUCE_AND: {
10174 case ISD::VP_REDUCE_OR:
10180 case ISD::VP_REDUCE_XOR: {
10204 return DAG.
getNode(BaseOpc,
DL,
Op.getValueType(), SetCC,
Op.getOperand(0));
10208 auto *RegisterAVL = dyn_cast<RegisterSDNode>(AVL);
10209 auto *ImmAVL = dyn_cast<ConstantSDNode>(AVL);
10210 return (RegisterAVL && RegisterAVL->getReg() == RISCV::X0) ||
10211 (ImmAVL && ImmAVL->getZExtValue() >= 1);
10227 auto InnerVT = VecVT.
bitsLE(M1VT) ? VecVT : M1VT;
10231 auto InnerVL = NonZeroAVL ? VL : DAG.
getConstant(1,
DL, XLenVT);
10234 if (M1VT != InnerVT)
10240 SDValue Ops[] = {PassThru, Vec, InitialValue, Mask, VL, Policy};
10259 VecEVT =
Lo.getValueType();
10272 MVT ContainerVT = VecVT;
10292 Mask, VL,
DL, DAG, Subtarget);
10298static std::tuple<unsigned, SDValue, SDValue>
10302 auto Flags =
Op->getFlags();
10303 unsigned Opcode =
Op.getOpcode();
10327 return std::make_tuple(RVVOpc,
Op.getOperand(0), Front);
10335 MVT VecEltVT =
Op.getSimpleValueType();
10337 unsigned RVVOpcode;
10338 SDValue VectorVal, ScalarVal;
10339 std::tie(RVVOpcode, VectorVal, ScalarVal) =
10343 MVT ContainerVT = VecVT;
10349 MVT ResVT =
Op.getSimpleValueType();
10352 VL,
DL, DAG, Subtarget);
10357 if (
Op->getFlags().hasNoNaNs())
10363 {VectorVal, VectorVal, DAG.getCondCode(ISD::SETNE),
10364 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
10370 DL, ResVT, NoNaNs, Res,
10377 unsigned Opc =
Op.getOpcode();
10400 Vec, Mask, VL,
DL, DAG, Subtarget);
10401 if ((Opc != ISD::VP_REDUCE_FMINIMUM && Opc != ISD::VP_REDUCE_FMAXIMUM) ||
10402 Op->getFlags().hasNoNaNs())
10419 DL, ResVT, NoNaNs, Res,
10432 unsigned OrigIdx =
Op.getConstantOperandVal(2);
10435 if (OrigIdx == 0 && Vec.
isUndef())
10446 assert(OrigIdx % 8 == 0 &&
"Invalid index");
10449 "Unexpected mask vector lowering");
10481 MVT ContainerVT = VecVT;
10488 DAG.
getUNDEF(ContainerVT), SubVec,
10505 if (OrigIdx == 0) {
10510 SubVec =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, Vec, SubVec,
10511 SlideupAmt, Mask, VL, Policy);
10519 MVT ContainerVecVT = VecVT;
10525 MVT ContainerSubVecVT = SubVecVT;
10531 unsigned SubRegIdx;
10541 ContainerVecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
10542 SubRegIdx = Decompose.first;
10544 (OrigIdx % Vscale));
10548 ContainerVecVT, ContainerSubVecVT, OrigIdx,
TRI);
10549 SubRegIdx = Decompose.first;
10556 bool ExactlyVecRegSized =
10558 .isKnownMultipleOf(Subtarget.
expandVScale(VecRegSize));
10573 if (RemIdx.
isZero() && (ExactlyVecRegSized || Vec.
isUndef())) {
10577 if (SubRegIdx == RISCV::NoSubRegister) {
10600 MVT InterSubVT = ContainerVecVT;
10601 SDValue AlignedExtract = Vec;
10641 SubVec =
getVSlideup(DAG, Subtarget,
DL, InterSubVT, AlignedExtract, SubVec,
10642 SlideupAmt, Mask, VL, Policy);
10647 if (ContainerVecVT.
bitsGT(InterSubVT))
10656 return DAG.
getBitcast(
Op.getSimpleValueType(), SubVec);
10662 MVT SubVecVT =
Op.getSimpleValueType();
10667 unsigned OrigIdx =
Op.getConstantOperandVal(1);
10683 assert(OrigIdx % 8 == 0 &&
"Invalid index");
10686 "Unexpected mask vector lowering");
10720 MVT ContainerVT = VecVT;
10728 if (
auto ShrunkVT =
10730 ContainerVT = *ShrunkVT;
10743 DAG.
getUNDEF(ContainerVT), Vec, SlidedownAmt, Mask, VL);
10755 MVT ContainerSubVecVT = SubVecVT;
10759 unsigned SubRegIdx;
10769 VecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
10770 SubRegIdx = Decompose.first;
10772 (OrigIdx % Vscale));
10776 VecVT, ContainerSubVecVT, OrigIdx,
TRI);
10777 SubRegIdx = Decompose.first;
10804 MVT InterSubVT = VecVT;
10809 assert(SubRegIdx != RISCV::NoSubRegister);
10829 Vec, SlidedownAmt, Mask, VL);
10838 return DAG.
getBitcast(
Op.getSimpleValueType(), Slidedown);
10845 MVT VT =
N.getSimpleValueType();
10849 assert(
Op.getSimpleValueType() == VT &&
10850 "Operands and result must be same type");
10854 unsigned NumVals =
N->getNumValues();
10857 NumVals,
N.getValueType().changeVectorElementType(MVT::i8)));
10860 for (
unsigned I = 0;
I < NumVals;
I++) {
10866 if (TruncVals.
size() > 1)
10868 return TruncVals.
front();
10874 MVT VecVT =
Op.getSimpleValueType();
10877 "vector_interleave on non-scalable vector!");
10888 EVT SplitVT = Op0Lo.getValueType();
10891 DAG.
getVTList(SplitVT, SplitVT), Op0Lo, Op0Hi);
10893 DAG.
getVTList(SplitVT, SplitVT), Op1Lo, Op1Hi);
10907 Op.getOperand(0),
Op.getOperand(1));
10926 EvenSplat = DAG.
getBitcast(MVT::nxv64i1, EvenSplat);
10931 OddSplat = DAG.
getBitcast(MVT::nxv64i1, OddSplat);
10937 EvenMask, DAG.
getUNDEF(ConcatVT));
10953 MVT VecVT =
Op.getSimpleValueType();
10956 "vector_interleave on non-scalable vector!");
10969 EVT SplitVT = Op0Lo.getValueType();
10972 DAG.
getVTList(SplitVT, SplitVT), Op0Lo, Op1Lo);
10974 DAG.
getVTList(SplitVT, SplitVT), Op0Hi, Op1Hi);
10996 Op.getOperand(0),
Op.getOperand(1));
11044 MVT VT =
Op.getSimpleValueType();
11049 uint64_t StepValImm =
Op.getConstantOperandVal(0);
11050 if (StepValImm != 1) {
11059 VL, VT,
DL, DAG, Subtarget);
11074 MVT VecVT =
Op.getSimpleValueType();
11083 MVT ContainerVT = VecVT;
11137 unsigned MaxVLMAX =
11147 if (MaxVLMAX > 256 && EltSize == 8) {
11176 assert(isUInt<16>(MaxVLMAX - 1));
11202 DAG.
getUNDEF(ContainerVT), Mask, VL);
11214 MVT VecVT =
Op.getSimpleValueType();
11218 int64_t ImmValue = cast<ConstantSDNode>(
Op.getOperand(2))->getSExtValue();
11219 SDValue DownOffset, UpOffset;
11220 if (ImmValue >= 0) {
11236 DownOffset, TrueMask, UpOffset);
11237 return getVSlideup(DAG, Subtarget,
DL, VecVT, SlideDown, V2, UpOffset,
11243RISCVTargetLowering::lowerFixedLengthVectorLoadToRVV(
SDValue Op,
11246 auto *
Load = cast<LoadSDNode>(
Op);
11249 Load->getMemoryVT(),
11250 *
Load->getMemOperand()) &&
11251 "Expecting a correctly-aligned load");
11253 MVT VT =
Op.getSimpleValueType();
11259 const auto [MinVLMAX, MaxVLMAX] =
11262 getLMUL1VT(ContainerVT).bitsLE(ContainerVT)) {
11276 IsMaskOp ? Intrinsic::riscv_vlm : Intrinsic::riscv_vle,
DL, XLenVT);
11279 Ops.push_back(DAG.
getUNDEF(ContainerVT));
11280 Ops.push_back(
Load->getBasePtr());
11285 Load->getMemoryVT(),
Load->getMemOperand());
11292RISCVTargetLowering::lowerFixedLengthVectorStoreToRVV(
SDValue Op,
11295 auto *
Store = cast<StoreSDNode>(
Op);
11298 Store->getMemoryVT(),
11299 *
Store->getMemOperand()) &&
11300 "Expecting a correctly-aligned store");
11321 const auto [MinVLMAX, MaxVLMAX] =
11324 getLMUL1VT(ContainerVT).bitsLE(ContainerVT)) {
11335 IsMaskOp ? Intrinsic::riscv_vsm : Intrinsic::riscv_vse,
DL, XLenVT);
11338 {Store->getChain(), IntID, NewValue, Store->getBasePtr(), VL},
11339 Store->getMemoryVT(),
Store->getMemOperand());
11345 MVT VT =
Op.getSimpleValueType();
11347 const auto *MemSD = cast<MemSDNode>(
Op);
11348 EVT MemVT = MemSD->getMemoryVT();
11350 SDValue Chain = MemSD->getChain();
11354 bool IsExpandingLoad =
false;
11355 if (
const auto *VPLoad = dyn_cast<VPLoadSDNode>(
Op)) {
11356 Mask = VPLoad->getMask();
11358 VL = VPLoad->getVectorLength();
11360 const auto *MLoad = cast<MaskedLoadSDNode>(
Op);
11361 Mask = MLoad->getMask();
11362 PassThru = MLoad->getPassThru();
11363 IsExpandingLoad = MLoad->isExpandingLoad();
11370 MVT ContainerVT = VT;
11384 if (!IsUnmasked && IsExpandingLoad) {
11391 unsigned IntID = IsUnmasked || IsExpandingLoad ? Intrinsic::riscv_vle
11392 : Intrinsic::riscv_vle_mask;
11394 if (IntID == Intrinsic::riscv_vle)
11395 Ops.push_back(DAG.
getUNDEF(ContainerVT));
11397 Ops.push_back(PassThru);
11398 Ops.push_back(BasePtr);
11399 if (IntID == Intrinsic::riscv_vle_mask)
11400 Ops.push_back(Mask);
11402 if (IntID == Intrinsic::riscv_vle_mask)
11409 Chain =
Result.getValue(1);
11411 MVT IndexVT = ContainerVT;
11416 bool UseVRGATHEREI16 =
false;
11424 UseVRGATHEREI16 =
true;
11430 DAG.
getUNDEF(IndexVT), Mask, ExpandingVL);
11434 DL, ContainerVT, Result, Iota, PassThru, Mask, ExpandingVL);
11447 const auto *MemSD = cast<MemSDNode>(
Op);
11448 EVT MemVT = MemSD->getMemoryVT();
11450 SDValue Chain = MemSD->getChain();
11454 bool IsCompressingStore =
false;
11455 if (
const auto *VPStore = dyn_cast<VPStoreSDNode>(
Op)) {
11456 Val = VPStore->getValue();
11457 Mask = VPStore->getMask();
11458 VL = VPStore->getVectorLength();
11460 const auto *MStore = cast<MaskedStoreSDNode>(
Op);
11461 Val = MStore->getValue();
11462 Mask = MStore->getMask();
11463 IsCompressingStore = MStore->isCompressingStore();
11472 MVT ContainerVT = VT;
11477 if (!IsUnmasked || IsCompressingStore) {
11486 if (IsCompressingStore) {
11489 DAG.
getUNDEF(ContainerVT), Val, Mask, VL);
11496 IsUnmasked ? Intrinsic::riscv_vse : Intrinsic::riscv_vse_mask;
11498 Ops.push_back(Val);
11499 Ops.push_back(BasePtr);
11501 Ops.push_back(Mask);
11505 DAG.
getVTList(MVT::Other), Ops, MemVT, MMO);
11517 MVT ContainerVT = VT;
11530 Passthru, Val, Mask, VL);
11539RISCVTargetLowering::lowerFixedLengthVectorSetccToRVV(
SDValue Op,
11541 MVT InVT =
Op.getOperand(0).getSimpleValueType();
11544 MVT VT =
Op.getSimpleValueType();
11558 {Op1, Op2,
Op.getOperand(2), DAG.
getUNDEF(MaskVT), Mask, VL});
11565 unsigned Opc =
Op.getOpcode();
11572 MVT VT =
Op.getSimpleValueType();
11605 MVT ContainerInVT = InVT;
11624 {Chain, Op1, Op1, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
11628 {Chain, Op2, Op2, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
11636 {Chain, Op1, Op2, CC, Mask, Mask, VL});
11641 {Chain, Op1, Op2, CC, DAG.getUNDEF(MaskVT), Mask, VL});
11654 MVT VT =
Op.getSimpleValueType();
11658 "Unexpected type for ISD::ABS");
11660 MVT ContainerVT = VT;
11667 if (
Op->getOpcode() == ISD::VP_ABS) {
11668 Mask =
Op->getOperand(1);
11672 VL =
Op->getOperand(2);
11680 DAG.
getUNDEF(ContainerVT), Mask, VL);
11682 DAG.
getUNDEF(ContainerVT), Mask, VL);
11689SDValue RISCVTargetLowering::lowerFixedLengthVectorFCOPYSIGNToRVV(
11692 MVT VT =
Op.getSimpleValueType();
11696 "Can only handle COPYSIGN with matching types.");
11705 Sign, DAG.
getUNDEF(ContainerVT), Mask, VL);
11710SDValue RISCVTargetLowering::lowerFixedLengthVectorSelectToRVV(
11712 MVT VT =
Op.getSimpleValueType();
11715 MVT I1ContainerVT =
11729 Op2, DAG.
getUNDEF(ContainerVT), VL);
11740 MVT VT =
Op.getSimpleValueType();
11745 for (
const SDValue &V :
Op->op_values()) {
11746 assert(!isa<VTSDNode>(V) &&
"Unexpected VTSDNode node!");
11749 if (!
V.getValueType().isVector()) {
11755 assert(useRVVForFixedLengthVectorVT(
V.getSimpleValueType()) &&
11756 "Only fixed length vectors are supported!");
11770 if (
Op->isStrictFPOpcode()) {
11779 DAG.
getNode(NewOpc,
DL, ContainerVT, Ops,
Op->getFlags());
11793 MVT VT =
Op.getSimpleValueType();
11796 MVT ContainerVT = VT;
11802 assert(!isa<VTSDNode>(V) &&
"Unexpected VTSDNode node!");
11805 if (HasPassthruOp) {
11808 if (*MaskIdx == OpIdx.index())
11812 if (
Op.getOpcode() == ISD::VP_MERGE) {
11816 assert(
Op.getOpcode() == ISD::VP_SELECT);
11828 if (!
V.getValueType().isFixedLengthVector()) {
11833 MVT OpVT =
V.getSimpleValueType();
11835 assert(useRVVForFixedLengthVectorVT(OpVT) &&
11836 "Only fixed length vectors are supported!");
11841 return DAG.
getNode(RISCVISDOpc,
DL, VT, Ops,
Op->getFlags());
11851 MVT VT =
Op.getSimpleValueType();
11857 MVT ContainerVT = VT;
11867 DAG.
getUNDEF(ContainerVT), Zero, VL);
11870 Op.getOpcode() == ISD::VP_ZERO_EXTEND ? 1 : -1,
DL, XLenVT);
11872 DAG.
getUNDEF(ContainerVT), SplatValue, VL);
11875 ZeroSplat, DAG.
getUNDEF(ContainerVT), VL);
11884 MVT VT =
Op.getSimpleValueType();
11888 ISD::CondCode Condition = cast<CondCodeSDNode>(
Op.getOperand(2))->get();
11892 MVT ContainerVT = VT;
11902 switch (Condition) {
11970 MVT DstVT =
Op.getSimpleValueType();
11971 MVT SrcVT = Src.getSimpleValueType();
11984 if (DstEltSize >= SrcEltSize) {
11993 if (SrcEltSize == 1) {
12004 ZeroSplat, DAG.
getUNDEF(IntVT), VL);
12005 }
else if (DstEltSize > (2 * SrcEltSize)) {
12009 Src = DAG.
getNode(RISCVISDExtOpc,
DL, IntVT, Src, Mask, VL);
12015 "Wrong input/output vector types");
12018 if (DstEltSize > (2 * SrcEltSize)) {
12034 MVT InterimFVT = DstVT;
12035 if (SrcEltSize > (2 * DstEltSize)) {
12036 assert(SrcEltSize == (4 * DstEltSize) &&
"Unexpected types!");
12043 if (InterimFVT != DstVT) {
12049 "Wrong input/output vector types");
12053 if (DstEltSize == 1) {
12056 assert(SrcEltSize >= 16 &&
"Unexpected FP type!");
12066 DAG.
getUNDEF(InterimIVT), SplatZero, VL);
12076 while (InterimIVT != DstVT) {
12088 MVT VT =
Op.getSimpleValueType();
12097 MVT VT =
Op.getSimpleValueType();
12111 MVT ContainerVT = VT;
12132 SplatZero, DAG.
getUNDEF(PromotedVT), VL);
12135 SplatOne, SplatZero, DAG.
getUNDEF(PromotedVT), VLMax);
12139 TrueVal, FalseVal, FalseVal, VL);
12154RISCVTargetLowering::lowerVPSpliceExperimental(
SDValue Op,
12166 MVT VT =
Op.getSimpleValueType();
12167 MVT ContainerVT = VT;
12177 if (IsMaskVector) {
12188 SplatZeroOp1, DAG.
getUNDEF(ContainerVT), EVL1);
12197 SplatZeroOp2, DAG.
getUNDEF(ContainerVT), EVL2);
12200 int64_t ImmValue = cast<ConstantSDNode>(
Offset)->getSExtValue();
12201 SDValue DownOffset, UpOffset;
12202 if (ImmValue >= 0) {
12216 Op1, DownOffset, Mask, UpOffset);
12220 if (IsMaskVector) {
12224 {Result, DAG.getConstant(0, DL, ContainerVT),
12225 DAG.getCondCode(ISD::SETNE), DAG.getUNDEF(getMaskTypeFor(ContainerVT)),
12240 MVT VT =
Op.getSimpleValueType();
12242 MVT ContainerVT = VT;
12258RISCVTargetLowering::lowerVPReverseExperimental(
SDValue Op,
12261 MVT VT =
Op.getSimpleValueType();
12268 MVT ContainerVT = VT;
12276 MVT GatherVT = ContainerVT;
12280 if (IsMaskVector) {
12291 SplatZero, DAG.
getUNDEF(IndicesVT), EVL);
12297 unsigned MaxVLMAX =
12306 if (MaxVLMAX > 256 && EltSize == 8) {
12334 DAG.
getUNDEF(GatherVT), Result, Diff, Mask, EVL);
12336 if (IsMaskVector) {
12359 DAG.
getUNDEF(IndicesVT), VecLen, EVL);
12361 DAG.
getUNDEF(IndicesVT), Mask, EVL);
12363 DAG.
getUNDEF(GatherVT), Mask, EVL);
12365 if (IsMaskVector) {
12380 MVT VT =
Op.getSimpleValueType();
12382 return lowerVPOp(
Op, DAG);
12389 MVT ContainerVT = VT;
12408 MVT VT =
Op.getSimpleValueType();
12409 MVT ContainerVT = VT;
12415 auto *VPNode = cast<VPStridedLoadSDNode>(
Op);
12421 : Intrinsic::riscv_vlse_mask,
12424 DAG.
getUNDEF(ContainerVT), VPNode->getBasePtr(),
12425 VPNode->getStride()};
12433 Ops.
push_back(VPNode->getVectorLength());
12441 VPNode->getMemoryVT(), VPNode->getMemOperand());
12455 auto *VPNode = cast<VPStridedStoreSDNode>(
Op);
12456 SDValue StoreVal = VPNode->getValue();
12458 MVT ContainerVT = VT;
12469 : Intrinsic::riscv_vsse_mask,
12472 VPNode->getBasePtr(), VPNode->getStride()};
12480 Ops.
push_back(VPNode->getVectorLength());
12483 Ops, VPNode->getMemoryVT(),
12484 VPNode->getMemOperand());
12496 MVT VT =
Op.getSimpleValueType();
12498 const auto *MemSD = cast<MemSDNode>(
Op.getNode());
12499 EVT MemVT = MemSD->getMemoryVT();
12501 SDValue Chain = MemSD->getChain();
12507 if (
auto *VPGN = dyn_cast<VPGatherSDNode>(
Op.getNode())) {
12508 Index = VPGN->getIndex();
12509 Mask = VPGN->getMask();
12511 VL = VPGN->getVectorLength();
12516 auto *MGN = cast<MaskedGatherSDNode>(
Op.getNode());
12517 Index = MGN->getIndex();
12518 Mask = MGN->getMask();
12519 PassThru = MGN->getPassThru();
12523 MVT IndexVT =
Index.getSimpleValueType();
12527 "Unexpected VTs!");
12528 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
12531 "Unexpected extending MGATHER/VP_GATHER");
12537 MVT ContainerVT = VT;
12561 IsUnmasked ? Intrinsic::riscv_vluxei : Intrinsic::riscv_vluxei_mask;
12578 Chain =
Result.getValue(1);
12595 const auto *MemSD = cast<MemSDNode>(
Op.getNode());
12596 EVT MemVT = MemSD->getMemoryVT();
12598 SDValue Chain = MemSD->getChain();
12601 [[maybe_unused]]
bool IsTruncatingStore =
false;
12604 if (
auto *VPSN = dyn_cast<VPScatterSDNode>(
Op.getNode())) {
12605 Index = VPSN->getIndex();
12606 Mask = VPSN->getMask();
12607 Val = VPSN->getValue();
12608 VL = VPSN->getVectorLength();
12610 IsTruncatingStore =
false;
12613 auto *MSN = cast<MaskedScatterSDNode>(
Op.getNode());
12614 Index = MSN->getIndex();
12615 Mask = MSN->getMask();
12616 Val = MSN->getValue();
12617 IsTruncatingStore = MSN->isTruncatingStore();
12621 MVT IndexVT =
Index.getSimpleValueType();
12625 "Unexpected VTs!");
12626 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
12629 assert(!IsTruncatingStore &&
"Unexpected truncating MSCATTER/VP_SCATTER");
12635 MVT ContainerVT = VT;
12659 IsUnmasked ? Intrinsic::riscv_vsoxei : Intrinsic::riscv_vsoxei_mask;
12669 DAG.
getVTList(MVT::Other), Ops, MemVT, MMO);
12678 RISCVSysReg::lookupSysRegByName(
"FRM")->Encoding,
DL, XLenVT);
12686 static const int Table =
12710 RISCVSysReg::lookupSysRegByName(
"FRM")->Encoding,
DL, XLenVT);
12716 static const unsigned Table =
12739 bool isRISCV64 = Subtarget.
is64Bit();
12803 switch (
N->getOpcode()) {
12805 llvm_unreachable(
"Don't know how to custom type legalize this operation!");
12811 "Unexpected custom legalisation");
12812 bool IsStrict =
N->isStrictFPOpcode();
12815 SDValue Op0 = IsStrict ?
N->getOperand(1) :
N->getOperand(0);
12833 Opc,
DL, VTs, Chain, Op0,
12867 std::tie(Result, Chain) =
12868 makeLibCall(DAG, LC,
N->getValueType(0), Op0, CallOptions,
DL, Chain);
12896 Op0.
getValueType() == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
12907 assert(!Subtarget.
is64Bit() &&
"READCYCLECOUNTER/READSTEADYCOUNTER only "
12908 "has custom type legalization on riscv32");
12910 SDValue LoCounter, HiCounter;
12914 RISCVSysReg::lookupSysRegByName(
"CYCLE")->Encoding,
DL, XLenVT);
12916 RISCVSysReg::lookupSysRegByName(
"CYCLEH")->Encoding,
DL, XLenVT);
12919 RISCVSysReg::lookupSysRegByName(
"TIME")->Encoding,
DL, XLenVT);
12921 RISCVSysReg::lookupSysRegByName(
"TIMEH")->Encoding,
DL, XLenVT);
12925 N->getOperand(0), LoCounter, HiCounter);
12949 unsigned Size =
N->getSimpleValueType(0).getSizeInBits();
12950 unsigned XLen = Subtarget.
getXLen();
12953 assert(
Size == (XLen * 2) &&
"Unexpected custom legalisation");
12961 if (LHSIsU == RHSIsU)
12978 if (RHSIsU && LHSIsS && !RHSIsS)
12980 else if (LHSIsU && RHSIsS && !LHSIsS)
12990 "Unexpected custom legalisation");
12997 "Unexpected custom legalisation");
13000 if (
N->getOpcode() ==
ISD::SHL && Subtarget.hasStdExtZbs() &&
13026 "Unexpected custom legalisation");
13027 assert((Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb() ||
13028 Subtarget.hasVendorXTHeadBb()) &&
13029 "Unexpected custom legalization");
13030 if (!isa<ConstantSDNode>(
N->getOperand(1)) &&
13031 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()))
13040 "Unexpected custom legalisation");
13054 MVT VT =
N->getSimpleValueType(0);
13055 assert((VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32) &&
13056 Subtarget.
is64Bit() && Subtarget.hasStdExtM() &&
13057 "Unexpected custom legalisation");
13069 if (VT != MVT::i32)
13078 "Unexpected custom legalisation");
13082 if (!isa<ConstantSDNode>(
N->getOperand(1)))
13099 EVT OType =
N->getValueType(1);
13112 "Unexpected custom legalisation");
13129 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1), Res,
13133 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1),
N->getOperand(0),
13151 !Subtarget.hasStdExtZbb() &&
"Unexpected custom legalisation");
13160 "Unexpected custom legalisation");
13166 "Unexpected custom legalisation");
13168 if (Subtarget.hasStdExtZbb()) {
13202 EVT VT =
N->getValueType(0);
13207 if (VT == MVT::i16 &&
13209 (Op0VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
13212 }
else if (VT == MVT::i32 && Op0VT == MVT::f32 && Subtarget.
is64Bit() &&
13217 }
else if (VT == MVT::i64 && Op0VT == MVT::f64 && !Subtarget.
is64Bit() &&
13220 DAG.
getVTList(MVT::i32, MVT::i32), Op0);
13241 MVT VT =
N->getSimpleValueType(0);
13243 assert((VT == MVT::i16 || (VT == MVT::i32 && Subtarget.
is64Bit())) &&
13244 "Unexpected custom legalisation");
13247 "Unexpected extension");
13273 assert(!Subtarget.
is64Bit() &&
N->getValueType(0) == MVT::i64 &&
13275 "Unexpected EXTRACT_VECTOR_ELT legalization");
13278 MVT ContainerVT = VecVT;
13306 DAG.
getUNDEF(ContainerVT), Mask, VL);
13314 unsigned IntNo =
N->getConstantOperandVal(0);
13318 "Don't know how to custom type legalize this intrinsic!");
13319 case Intrinsic::experimental_get_vector_length: {
13324 case Intrinsic::experimental_cttz_elts: {
13330 case Intrinsic::riscv_orc_b:
13331 case Intrinsic::riscv_brev8:
13332 case Intrinsic::riscv_sha256sig0:
13333 case Intrinsic::riscv_sha256sig1:
13334 case Intrinsic::riscv_sha256sum0:
13335 case Intrinsic::riscv_sha256sum1:
13336 case Intrinsic::riscv_sm3p0:
13337 case Intrinsic::riscv_sm3p1: {
13338 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
13358 case Intrinsic::riscv_sm4ks:
13359 case Intrinsic::riscv_sm4ed: {
13367 DAG.
getNode(Opc,
DL, MVT::i64, NewOp0, NewOp1,
N->getOperand(3));
13371 case Intrinsic::riscv_mopr: {
13372 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
13382 case Intrinsic::riscv_moprr: {
13383 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
13395 case Intrinsic::riscv_clmul: {
13396 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
13407 case Intrinsic::riscv_clmulh:
13408 case Intrinsic::riscv_clmulr: {
13409 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
13437 case Intrinsic::riscv_vmv_x_s: {
13438 EVT VT =
N->getValueType(0);
13440 if (VT.
bitsLT(XLenVT)) {
13449 "Unexpected custom legalization");
13487 case ISD::VP_REDUCE_ADD:
13488 case ISD::VP_REDUCE_AND:
13489 case ISD::VP_REDUCE_OR:
13490 case ISD::VP_REDUCE_XOR:
13491 case ISD::VP_REDUCE_SMAX:
13492 case ISD::VP_REDUCE_UMAX:
13493 case ISD::VP_REDUCE_SMIN:
13494 case ISD::VP_REDUCE_UMIN:
13558 const EVT VT =
N->getValueType(0);
13559 const unsigned Opc =
N->getOpcode();
13566 (Opc !=
ISD::FADD || !
N->getFlags().hasAllowReassociation()))
13571 "Inconsistent mappings");
13582 !isa<ConstantSDNode>(
RHS.getOperand(1)))
13585 uint64_t RHSIdx = cast<ConstantSDNode>(
RHS.getOperand(1))->getLimitedValue();
13600 LHS.getOperand(0) == SrcVec && isa<ConstantSDNode>(
LHS.getOperand(1))) {
13602 cast<ConstantSDNode>(
LHS.getOperand(1))->getLimitedValue();
13603 if (0 == std::min(LHSIdx, RHSIdx) && 1 == std::max(LHSIdx, RHSIdx)) {
13607 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
N->getFlags());
13614 if (
LHS.getOpcode() != ReduceOpc)
13629 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
13630 ReduceVec->
getFlags() &
N->getFlags());
13640 auto BinOpToRVVReduce = [](
unsigned Opc) {
13669 auto IsReduction = [&BinOpToRVVReduce](
SDValue V,
unsigned Opc) {
13672 V.getOperand(0).getOpcode() == BinOpToRVVReduce(Opc);
13675 unsigned Opc =
N->getOpcode();
13676 unsigned ReduceIdx;
13677 if (IsReduction(
N->getOperand(0), Opc))
13679 else if (IsReduction(
N->getOperand(1), Opc))
13685 if (Opc ==
ISD::FADD && !
N->getFlags().hasAllowReassociation())
13688 SDValue Extract =
N->getOperand(ReduceIdx);
13720 SDValue NewStart =
N->getOperand(1 - ReduceIdx);
13747 if (!Subtarget.hasStdExtZba())
13751 EVT VT =
N->getValueType(0);
13763 auto *N0C = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
13764 auto *N1C = dyn_cast<ConstantSDNode>(N1->
getOperand(1));
13767 int64_t C0 = N0C->getSExtValue();
13768 int64_t C1 = N1C->getSExtValue();
13769 if (C0 <= 0 || C1 <= 0)
13773 int64_t Bits = std::min(C0, C1);
13774 int64_t Diff = std::abs(C0 - C1);
13775 if (Diff != 1 && Diff != 2 && Diff != 3)
13802 EVT VT =
N->getValueType(0);
13810 if ((!Subtarget.hasStdExtZicond() &&
13811 !Subtarget.hasVendorXVentanaCondOps()) ||
13833 bool SwapSelectOps;
13839 SwapSelectOps =
false;
13840 NonConstantVal = FalseVal;
13842 SwapSelectOps =
true;
13843 NonConstantVal = TrueVal;
13849 FalseVal = DAG.
getNode(
N->getOpcode(),
SDLoc(
N), VT, OtherOp, NonConstantVal);
13897 EVT VT =
N->getValueType(0);
13905 auto *N0C = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
13906 auto *N1C = dyn_cast<ConstantSDNode>(
N->getOperand(1));
13912 if (!N0C->hasOneUse())
13914 int64_t C0 = N0C->getSExtValue();
13915 int64_t C1 = N1C->getSExtValue();
13917 if (C0 == -1 || C0 == 0 || C0 == 1 || isInt<12>(C1))
13920 if ((C1 / C0) != 0 && isInt<12>(C1 / C0) && isInt<12>(C1 % C0) &&
13921 !isInt<12>(C0 * (C1 / C0))) {
13924 }
else if ((C1 / C0 + 1) != 0 && isInt<12>(C1 / C0 + 1) &&
13925 isInt<12>(C1 % C0 - C0) && !isInt<12>(C0 * (C1 / C0 + 1))) {
13928 }
else if ((C1 / C0 - 1) != 0 && isInt<12>(C1 / C0 - 1) &&
13929 isInt<12>(C1 % C0 + C0) && !isInt<12>(C0 * (C1 / C0 - 1))) {
13956 EVT VT =
N->getValueType(0);
13987 unsigned OuterExtend =
13991 OuterExtend,
SDLoc(
N), VT,
13999 EVT VT =
N->getValueType(0);
14047 EVT VT =
N->getValueType(0);
14051 auto *N0C = dyn_cast<ConstantSDNode>(N0);
14057 APInt ImmValMinus1 = N0C->getAPIntValue() - 1;
14067 if (!isIntEqualitySetCC(CCVal) || !SetCCOpVT.
isInteger())
14090 if (!Subtarget.hasStdExtZbb())
14093 EVT VT =
N->getValueType(0);
14095 if (VT != Subtarget.
getXLenVT() && VT != MVT::i32 && VT != MVT::i16)
14104 auto *ShAmtCLeft = dyn_cast<ConstantSDNode>(N0.
getOperand(1));
14107 unsigned ShiftedAmount = 8 - ShAmtCLeft->getZExtValue();
14109 if (ShiftedAmount >= 8)
14113 SDValue RightShiftOperand = N1;
14115 if (ShiftedAmount != 0) {
14118 auto *ShAmtCRight = dyn_cast<ConstantSDNode>(N1.
getOperand(1));
14119 if (!ShAmtCRight || ShAmtCRight->getZExtValue() != ShiftedAmount)
14128 if (LeftShiftOperand != RightShiftOperand)
14132 Mask <<= ShiftedAmount;
14146 EVT VT =
N->getValueType(0);
14177 bool IsAnd =
N->getOpcode() ==
ISD::AND;
14201 EVT VT =
N->getValueType(0);
14225 EVT VT =
N->getValueType(0);
14252 if (CondLHS != True)
14259 if (!CondRHSC || CondRHSC->
getAPIntValue() != (1ULL << ScalarBits))
14271 if (!FalseRHSC || !FalseRHSC->
isZero())
14291 EVT VT =
N->getValueType(0);
14298 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() && VT == MVT::i1 &&
14325 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
14377 EVT VT =
N->getValueType(0);
14423 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
14448 auto *ConstN00 = dyn_cast<ConstantSDNode>(N0.
getOperand(0));
14453 const APInt &Imm = ConstN00->getAPIntValue();
14454 if ((Imm + 1).isSignedIntN(12))
14475 EVT VT =
N->getValueType(0);
14487 const bool HasShlAdd =
14488 Subtarget.hasStdExtZba() || Subtarget.hasVendorXTHeadBa();
14502 for (
uint64_t Divisor : {3, 5, 9}) {
14503 if (MulAmt % Divisor != 0)
14505 uint64_t MulAmt2 = MulAmt / Divisor;
14512 if (
X.getOpcode() ==
ISD::AND && isa<ConstantSDNode>(
X.getOperand(1)) &&
14513 X.getConstantOperandVal(1) == UINT64_C(0xffffffff)) {
14530 if (MulAmt2 == 3 || MulAmt2 == 5 || MulAmt2 == 9) {
14546 if (ScaleShift >= 1 && ScaleShift < 4) {
14547 unsigned ShiftAmt =
Log2_64((MulAmt & (MulAmt - 1)));
14561 for (
uint64_t Divisor : {3, 5, 9}) {
14566 if ((
C >> TZ) == Divisor && (TZ == 1 || TZ == 2 || TZ == 3)) {
14577 if (MulAmt > 2 &&
isPowerOf2_64((MulAmt - 1) & (MulAmt - 2))) {
14579 if (ScaleShift >= 1 && ScaleShift < 4) {
14580 unsigned ShiftAmt =
Log2_64(((MulAmt - 1) & (MulAmt - 2)));
14606 uint64_t MulAmtLowBit = MulAmt & (-MulAmt);
14608 uint64_t ShiftAmt1 = MulAmt + MulAmtLowBit;
14619 for (
uint64_t Divisor : {3, 5, 9}) {
14620 if (MulAmt % Divisor != 0)
14622 uint64_t MulAmt2 = MulAmt / Divisor;
14625 for (
uint64_t Divisor2 : {3, 5, 9}) {
14626 if (MulAmt2 % Divisor2 != 0)
14628 uint64_t MulAmt3 = MulAmt2 / Divisor2;
14651 EVT VT =
N->getValueType(0);
14658 if (
N->getOperand(0).getOpcode() !=
ISD::AND ||
14659 N->getOperand(0).getOperand(0).getOpcode() !=
ISD::SRL)
14672 if (!V1.
isMask(HalfSize) || V2 != (1ULL | 1ULL << HalfSize) ||
14673 V3 != (HalfSize - 1))
14689 EVT VT =
N->getValueType(0);
14697 unsigned AddSubOpc;
14703 auto IsAddSubWith1 = [&](
SDValue V) ->
bool {
14704 AddSubOpc = V->getOpcode();
14706 SDValue Opnd = V->getOperand(1);
14707 MulOper = V->getOperand(0);
14716 if (IsAddSubWith1(N0)) {
14718 return DAG.
getNode(AddSubOpc,
DL, VT, N1, MulVal);
14721 if (IsAddSubWith1(N1)) {
14723 return DAG.
getNode(AddSubOpc,
DL, VT, N0, MulVal);
14738 if (isIndexTypeSigned(IndexType))
14741 if (!
N->hasOneUse())
14744 EVT VT =
N.getValueType();
14783 EVT SrcVT = Src.getValueType();
14787 NewElen = std::max(NewElen, 8U);
14810 EVT VT =
N->getValueType(0);
14813 if (OpVT != MVT::i64 || !Subtarget.
is64Bit())
14817 auto *N1C = dyn_cast<ConstantSDNode>(N1);
14829 if (!isIntEqualitySetCC(
Cond))
14838 const APInt &C1 = N1C->getAPIntValue();
14856 EVT VT =
N->getValueType(0);
14857 EVT SrcVT = cast<VTSDNode>(
N->getOperand(1))->
getVT();
14858 unsigned Opc = Src.getOpcode();
14863 Subtarget.hasStdExtZfhmin())
14865 Src.getOperand(0));
14869 VT == MVT::i64 && !isa<ConstantSDNode>(Src.getOperand(1)) &&
14872 Src.getOperand(1));
14880struct CombineResult;
14882enum ExtKind :
uint8_t { ZExt = 1 << 0, SExt = 1 << 1, FPExt = 1 << 2 };
14909struct NodeExtensionHelper {
14918 bool SupportsFPExt;
14921 bool EnforceOneUse;
14936 return OrigOperand;
14947 unsigned getExtOpc(ExtKind SupportsExt)
const {
14948 switch (SupportsExt) {
14949 case ExtKind::SExt:
14951 case ExtKind::ZExt:
14953 case ExtKind::FPExt:
14964 std::optional<ExtKind> SupportsExt)
const {
14965 if (!SupportsExt.has_value())
14966 return OrigOperand;
14968 MVT NarrowVT = getNarrowType(Root, *SupportsExt);
14972 if (
Source.getValueType() == NarrowVT)
14976 if (
Source.getValueType().getVectorElementType() == MVT::bf16) {
14982 unsigned ExtOpc = getExtOpc(*SupportsExt);
14986 auto [
Mask, VL] = getMaskAndVL(Root, DAG, Subtarget);
14993 return DAG.
getNode(ExtOpc,
DL, NarrowVT, Source, Mask, VL);
15005 DAG.
getUNDEF(NarrowVT), Source, VL);
15018 static MVT getNarrowType(
const SDNode *Root, ExtKind SupportsExt) {
15024 MVT EltVT = SupportsExt == ExtKind::FPExt
15026 :
MVT::getIntegerVT(NarrowSize);
15028 assert((
int)NarrowSize >= (SupportsExt == ExtKind::FPExt ? 16 : 8) &&
15029 "Trying to extend something we can't represent");
15036 static unsigned getSExtOpcode(
unsigned Opcode) {
15059 static unsigned getZExtOpcode(
unsigned Opcode) {
15085 static unsigned getFPExtOpcode(
unsigned Opcode) {
15110 static unsigned getSUOpcode(
unsigned Opcode) {
15112 "SU is only supported for MUL");
15118 static unsigned getWOpcode(
unsigned Opcode, ExtKind SupportsExt) {
15138 using CombineToTry = std::function<std::optional<CombineResult>(
15139 SDNode * ,
const NodeExtensionHelper & ,
15144 bool needToPromoteOtherUsers()
const {
return EnforceOneUse; }
15148 unsigned Opc = OrigOperand.
getOpcode();
15152 "Unexpected Opcode");
15165 unsigned ScalarBits =
Op.getValueSizeInBits();
15167 if (ScalarBits < EltBits) {
15170 !Subtarget.
is64Bit() &&
"Unexpected splat");
15172 SupportsSExt =
true;
15176 SupportsZExt =
true;
15178 EnforceOneUse =
false;
15182 unsigned NarrowSize = EltBits / 2;
15185 if (NarrowSize < 8)
15189 SupportsSExt =
true;
15193 SupportsZExt =
true;
15195 EnforceOneUse =
false;
15198 bool isSupportedFPExtend(
SDNode *Root,
MVT NarrowEltVT,
15205 if (NarrowEltVT == MVT::bf16 && (!Subtarget.hasStdExtZvfbfwma() ||
15215 SupportsZExt =
false;
15216 SupportsSExt =
false;
15217 SupportsFPExt =
false;
15218 EnforceOneUse =
true;
15219 unsigned Opc = OrigOperand.
getOpcode();
15241 SupportsZExt =
true;
15244 SupportsSExt =
true;
15249 if (!isSupportedFPExtend(Root, NarrowEltVT, Subtarget))
15251 SupportsFPExt =
true;
15256 fillUpExtensionSupportForSplat(Root, DAG, Subtarget);
15268 if (!isSupportedFPExtend(Root,
Op.getOperand(0).getSimpleValueType(),
15273 unsigned ScalarBits =
Op.getOperand(0).getValueSizeInBits();
15274 if (NarrowSize != ScalarBits)
15277 SupportsFPExt =
true;
15286 static bool isSupportedRoot(
const SDNode *Root,
15315 Subtarget.hasStdExtZvbb();
15317 return Subtarget.hasStdExtZvbb();
15331 assert(isSupportedRoot(Root, Subtarget) &&
15332 "Trying to build an helper with an "
15333 "unsupported root");
15334 assert(OperandIdx < 2 &&
"Requesting something else than LHS or RHS");
15350 if (OperandIdx == 1) {
15359 EnforceOneUse =
false;
15364 fillUpExtensionSupport(Root, DAG, Subtarget);
15370 static std::pair<SDValue, SDValue>
15373 assert(isSupportedRoot(Root, Subtarget) &&
"Unexpected root");
15392 switch (
N->getOpcode()) {
15434struct CombineResult {
15436 unsigned TargetOpcode;
15438 std::optional<ExtKind> LHSExt;
15439 std::optional<ExtKind> RHSExt;
15443 NodeExtensionHelper
LHS;
15445 NodeExtensionHelper
RHS;
15447 CombineResult(
unsigned TargetOpcode,
SDNode *Root,
15448 const NodeExtensionHelper &
LHS, std::optional<ExtKind> LHSExt,
15449 const NodeExtensionHelper &
RHS, std::optional<ExtKind> RHSExt)
15450 : TargetOpcode(TargetOpcode), LHSExt(LHSExt), RHSExt(RHSExt), Root(Root),
15459 std::tie(Mask, VL) =
15460 NodeExtensionHelper::getMaskAndVL(Root, DAG, Subtarget);
15474 LHS.getOrCreateExtendedOp(Root, DAG, Subtarget, LHSExt),
15475 RHS.getOrCreateExtendedOp(Root, DAG, Subtarget, RHSExt),
15476 Passthru, Mask, VL);
15490static std::optional<CombineResult>
15491canFoldToVWWithSameExtensionImpl(
SDNode *Root,
const NodeExtensionHelper &LHS,
15492 const NodeExtensionHelper &RHS,
15495 if ((AllowExtMask & ExtKind::ZExt) &&
LHS.SupportsZExt &&
RHS.SupportsZExt)
15496 return CombineResult(NodeExtensionHelper::getZExtOpcode(Root->
getOpcode()),
15497 Root, LHS, {ExtKind::ZExt}, RHS,
15499 if ((AllowExtMask & ExtKind::SExt) &&
LHS.SupportsSExt &&
RHS.SupportsSExt)
15500 return CombineResult(NodeExtensionHelper::getSExtOpcode(Root->
getOpcode()),
15501 Root, LHS, {ExtKind::SExt}, RHS,
15503 if ((AllowExtMask & ExtKind::FPExt) &&
LHS.SupportsFPExt &&
RHS.SupportsFPExt)
15504 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
15505 Root, LHS, {ExtKind::FPExt}, RHS,
15507 return std::nullopt;
15516static std::optional<CombineResult>
15517canFoldToVWWithSameExtension(
SDNode *Root,
const NodeExtensionHelper &LHS,
15520 return canFoldToVWWithSameExtensionImpl(
15521 Root, LHS, RHS, ExtKind::ZExt | ExtKind::SExt | ExtKind::FPExt, DAG,
15529static std::optional<CombineResult>
15530canFoldToVW_W(
SDNode *Root,
const NodeExtensionHelper &LHS,
15533 if (
RHS.SupportsFPExt)
15534 return CombineResult(
15535 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::FPExt),
15536 Root, LHS, std::nullopt, RHS, {ExtKind::FPExt});
15543 return CombineResult(
15544 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::ZExt), Root,
15545 LHS, std::nullopt, RHS, {ExtKind::ZExt});
15547 return CombineResult(
15548 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::SExt), Root,
15549 LHS, std::nullopt, RHS, {ExtKind::SExt});
15550 return std::nullopt;
15557static std::optional<CombineResult>
15558canFoldToVWWithSEXT(
SDNode *Root,
const NodeExtensionHelper &LHS,
15561 return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::SExt, DAG,
15569static std::optional<CombineResult>
15570canFoldToVWWithZEXT(
SDNode *Root,
const NodeExtensionHelper &LHS,
15573 return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::ZExt, DAG,
15581static std::optional<CombineResult>
15582canFoldToVWWithFPEXT(
SDNode *Root,
const NodeExtensionHelper &LHS,
15585 return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::FPExt, DAG,
15593static std::optional<CombineResult>
15594canFoldToVW_SU(
SDNode *Root,
const NodeExtensionHelper &LHS,
15598 if (!
LHS.SupportsSExt || !
RHS.SupportsZExt)
15599 return std::nullopt;
15600 return CombineResult(NodeExtensionHelper::getSUOpcode(Root->
getOpcode()),
15601 Root, LHS, {ExtKind::SExt}, RHS,
15606NodeExtensionHelper::getSupportedFoldings(
const SDNode *Root) {
15617 Strategies.
push_back(canFoldToVWWithSameExtension);
15626 Strategies.
push_back(canFoldToVWWithSameExtension);
15631 Strategies.
push_back(canFoldToVWWithSameExtension);
15638 Strategies.
push_back(canFoldToVWWithZEXT);
15643 Strategies.
push_back(canFoldToVWWithSEXT);
15648 Strategies.
push_back(canFoldToVWWithZEXT);
15653 Strategies.
push_back(canFoldToVWWithFPEXT);
15682 if (!NodeExtensionHelper::isSupportedRoot(
N, Subtarget))
15688 Inserted.insert(
N);
15691 while (!Worklist.
empty()) {
15694 NodeExtensionHelper
LHS(Root, 0, DAG, Subtarget);
15695 NodeExtensionHelper
RHS(Root, 1, DAG, Subtarget);
15696 auto AppendUsersIfNeeded = [&Worklist, &Subtarget,
15697 &Inserted](
const NodeExtensionHelper &
Op) {
15698 if (
Op.needToPromoteOtherUsers()) {
15701 if (!NodeExtensionHelper::isSupportedRoot(TheUser, Subtarget))
15706 if (Inserted.insert(TheUser).second)
15719 NodeExtensionHelper::getSupportedFoldings(Root);
15721 assert(!FoldingStrategies.
empty() &&
"Nothing to be folded");
15722 bool Matched =
false;
15723 for (
int Attempt = 0;
15724 (Attempt != 1 + NodeExtensionHelper::isCommutative(Root)) && !Matched;
15727 for (NodeExtensionHelper::CombineToTry FoldingStrategy :
15728 FoldingStrategies) {
15729 std::optional<CombineResult> Res =
15730 FoldingStrategy(Root,
LHS,
RHS, DAG, Subtarget);
15737 if (Res->LHSExt.has_value())
15738 if (!AppendUsersIfNeeded(
LHS))
15740 if (Res->RHSExt.has_value())
15741 if (!AppendUsersIfNeeded(
RHS))
15753 SDValue InputRootReplacement;
15760 for (CombineResult Res : CombinesToApply) {
15761 SDValue NewValue = Res.materialize(DAG, Subtarget);
15762 if (!InputRootReplacement) {
15764 "First element is expected to be the current node");
15765 InputRootReplacement = NewValue;
15770 for (std::pair<SDValue, SDValue> OldNewValues : ValuesToReplace) {
15774 return InputRootReplacement;
15781 unsigned Opc =
N->getOpcode();
15786 SDValue MergeOp =
N->getOperand(1);
15787 unsigned MergeOpc = MergeOp.
getOpcode();
15798 SDValue Passthru =
N->getOperand(2);
15812 Z = Z.getOperand(1);
15818 {Y, X, Y, MergeOp->getOperand(0), N->getOperand(4)},
15825 [[maybe_unused]]
unsigned Opc =
N->getOpcode();
15854 EVT NewMemVT = (MemVT == MVT::i32) ? MVT::i64 : MVT::i128;
15860 auto Ext = cast<LoadSDNode>(LSNode1)->getExtensionType();
15862 if (MemVT == MVT::i32)
15868 Opcode,
SDLoc(LSNode1), DAG.
getVTList({XLenVT, XLenVT, MVT::Other}),
15903 if (!Subtarget.hasVendorXTHeadMemPair())
15915 auto ExtractBaseAndOffset = [](
SDValue Ptr) -> std::pair<SDValue, uint64_t> {
15917 if (
auto *C1 = dyn_cast<ConstantSDNode>(
Ptr->getOperand(1)))
15918 return {
Ptr->getOperand(0), C1->getZExtValue()};
15922 auto [Base1, Offset1] = ExtractBaseAndOffset(LSNode1->
getOperand(OpNum));
15943 auto [Base2, Offset2] = ExtractBaseAndOffset(LSNode2->
getOperand(OpNum));
15946 if (Base1 != Base2)
15950 bool Valid =
false;
15951 if (MemVT == MVT::i32) {
15953 if ((Offset1 + 4 == Offset2) && isShiftedUInt<2, 3>(Offset1))
15955 }
else if (MemVT == MVT::i64) {
15957 if ((Offset1 + 8 == Offset2) && isShiftedUInt<2, 4>(Offset1))
15991 if (Src->isStrictFPOpcode())
15999 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
16009 EVT VT =
N->getValueType(0);
16012 MVT SrcVT = Src.getSimpleValueType();
16013 MVT SrcContainerVT = SrcVT;
16015 SDValue XVal = Src.getOperand(0);
16042 FpToInt = DAG.
getNode(Opc,
DL, ContainerVT, XVal, Mask, VL);
16046 FpToInt = DAG.
getNode(Opc,
DL, ContainerVT, XVal, Mask,
16059 if (VT != MVT::i32 && VT != XLenVT)
16089 EVT DstVT =
N->getValueType(0);
16090 if (DstVT != XLenVT)
16096 if (Src->isStrictFPOpcode())
16104 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
16107 EVT SatVT = cast<VTSDNode>(
N->getOperand(1))->getVT();
16116 if (SatVT == DstVT)
16118 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
16124 Src = Src.getOperand(0);
16145 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected extension");
16151 EVT VT =
N->getValueType(0);
16206 unsigned Offset = IsStrict ? 1 : 0;
16213 auto invertIfNegative = [&Mask, &VL](
SDValue &V) {
16215 V.getOperand(2) == VL) {
16217 V = V.getOperand(0);
16224 bool NegA = invertIfNegative(
A);
16225 bool NegB = invertIfNegative(
B);
16226 bool NegC = invertIfNegative(
C);
16229 if (!NegA && !NegB && !NegC)
16235 {N->getOperand(0), A, B, C, Mask, VL});
16259 EVT VT =
N->getValueType(0);
16264 if (!isa<ConstantSDNode>(
N->getOperand(1)))
16266 uint64_t ShAmt =
N->getConstantOperandVal(1);
16274 cast<VTSDNode>(N0.
getOperand(1))->getVT().getSizeInBits();
16279 if (LShAmt < ExtSize) {
16292 if (ShAmt > 32 || VT != MVT::i64)
16308 AddC = dyn_cast<ConstantSDNode>(N0.
getOperand(IsAdd ? 1 : 0));
16321 !isa<ConstantSDNode>(U->getOperand(1)) ||
16322 U->getConstantOperandVal(1) > 32)
16377 if (!
Cond.hasOneUse())
16396 EVT VT =
Cond.getValueType();
16441 LHS =
LHS.getOperand(0);
16451 LHS.getOperand(0).getValueType() == Subtarget.
getXLenVT()) {
16455 CCVal = cast<CondCodeSDNode>(
LHS.getOperand(2))->get();
16459 RHS =
LHS.getOperand(1);
16460 LHS =
LHS.getOperand(0);
16469 RHS =
LHS.getOperand(1);
16470 LHS =
LHS.getOperand(0);
16486 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
16527 bool Commutative =
true;
16528 unsigned Opc = TrueVal.getOpcode();
16536 Commutative =
false;
16544 if (!TrueVal.hasOneUse() || isa<ConstantSDNode>(FalseVal))
16548 if (FalseVal == TrueVal.getOperand(0))
16550 else if (Commutative && FalseVal == TrueVal.getOperand(1))
16555 EVT VT =
N->getValueType(0);
16557 SDValue OtherOp = TrueVal.getOperand(1 - OpToFold);
16563 assert(IdentityOperand &&
"No identity operand!");
16568 DAG.
getSelect(
DL, OtherOpVT,
N->getOperand(0), OtherOp, IdentityOperand);
16569 return DAG.
getNode(TrueVal.getOpcode(),
DL, VT, FalseVal, NewSel);
16590 CountZeroes =
N->getOperand(2);
16591 ValOnZero =
N->getOperand(1);
16593 CountZeroes =
N->getOperand(1);
16594 ValOnZero =
N->getOperand(2);
16613 if (
Cond->getOperand(0) != CountZeroesArgument)
16629 CountZeroes, BitWidthMinusOne);
16639 EVT VT =
N->getValueType(0);
16640 EVT CondVT =
Cond.getValueType();
16648 (Subtarget.hasStdExtZicond() || Subtarget.hasVendorXVentanaCondOps())) {
16654 const APInt &MaskVal =
LHS.getConstantOperandAPInt(1);
16675 SDValue TrueVal =
N->getOperand(1);
16676 SDValue FalseVal =
N->getOperand(2);
16691 EVT VT =
N->getValueType(0);
16698 const unsigned Opcode =
N->op_begin()->getNode()->getOpcode();
16713 if (
Op.isUndef()) {
16726 if (
Op.getOpcode() != Opcode || !
Op.hasOneUse())
16730 if (!isa<ConstantSDNode>(
Op.getOperand(1)) &&
16731 !isa<ConstantFPSDNode>(
Op.getOperand(1)))
16735 if (
Op.getOperand(0).getValueType() !=
Op.getOperand(1).getValueType())
16763 const unsigned InVecOpcode = InVec->
getOpcode();
16773 if (!isa<ConstantSDNode>(InValRHS) && !isa<ConstantFPSDNode>(InValRHS))
16780 InVecLHS, InValLHS, EltNo);
16782 InVecRHS, InValRHS, EltNo);
16791 auto *IndexC = dyn_cast<ConstantSDNode>(EltNo);
16794 unsigned Elt = IndexC->getZExtValue();
16802 unsigned ConcatOpIdx = Elt / ConcatNumElts;
16805 ConcatOp, InVal, NewIdx);
16809 ConcatOps[ConcatOpIdx] = ConcatOp;
16821 EVT VT =
N->getValueType(0);
16831 auto *BaseLd = dyn_cast<LoadSDNode>(
N->getOperand(0));
16833 !
SDValue(BaseLd, 0).hasOneUse())
16836 EVT BaseLdVT = BaseLd->getValueType(0);
16843 auto *Ld = dyn_cast<LoadSDNode>(
Op);
16844 if (!Ld || !Ld->isSimple() || !
Op.hasOneUse() ||
16846 Ld->getValueType(0) != BaseLdVT)
16855 using PtrDiff = std::pair<std::variant<int64_t, SDValue>,
bool>;
16857 LoadSDNode *Ld2) -> std::optional<PtrDiff> {
16862 if (BIO1.equalBaseIndex(BIO2, DAG))
16867 SDValue P2 = Ld2->getBasePtr();
16873 return std::nullopt;
16877 auto BaseDiff = GetPtrDiff(Lds[0], Lds[1]);
16882 for (
auto *It = Lds.
begin() + 1; It != Lds.
end() - 1; It++)
16883 if (GetPtrDiff(*It, *std::next(It)) != BaseDiff)
16891 unsigned WideScalarBitWidth =
16904 auto [StrideVariant, MustNegateStride] = *BaseDiff;
16906 std::holds_alternative<SDValue>(StrideVariant)
16907 ? std::get<SDValue>(StrideVariant)
16910 if (MustNegateStride)
16918 if (
auto *ConstStride = dyn_cast<ConstantSDNode>(Stride);
16919 ConstStride && ConstStride->getSExtValue() >= 0)
16923 ConstStride->getSExtValue() * (
N->getNumOperands() - 1);
16929 BaseLd->getPointerInfo(), BaseLd->getMemOperand()->getFlags(), MemSize,
16933 WideVecVT,
DL, BaseLd->getChain(), BaseLd->getBasePtr(), Stride,
16948 if (
N->getValueType(0).isFixedLengthVector())
16951 SDValue Addend =
N->getOperand(0);
16955 SDValue AddPassthruOp =
N->getOperand(2);
16956 if (!AddPassthruOp.
isUndef())
16960 auto IsVWMulOpc = [](
unsigned Opc) {
16979 if (!MulPassthruOp.
isUndef())
16989 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
16990 }(
N, DAG, Subtarget);
16995 if (AddMask != MulMask || AddVL != MulVL)
17000 "Unexpected opcode after VWMACC_VL");
17002 "Unexpected opcode after VWMACC_VL!");
17004 "Unexpected opcode after VWMUL_VL!");
17006 "Unexpected opcode after VWMUL_VL!");
17009 EVT VT =
N->getValueType(0);
17025 const EVT IndexVT = Index.getValueType();
17029 if (!isIndexTypeSigned(IndexType))
17061 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
17064 if (Index->getOperand(i)->isUndef())
17066 uint64_t C = Index->getConstantOperandVal(i);
17067 if (
C % ElementSize != 0)
17069 C =
C / ElementSize;
17073 ActiveLanes.
set(
C);
17075 return ActiveLanes.
all();
17093 if (NumElems % 2 != 0)
17097 const unsigned WiderElementSize = ElementSize * 2;
17098 if (WiderElementSize > ST.getELen()/8)
17101 if (!ST.enableUnalignedVectorMem() && BaseAlign < WiderElementSize)
17104 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
17107 if (Index->getOperand(i)->isUndef())
17111 uint64_t C = Index->getConstantOperandVal(i);
17113 if (
C % WiderElementSize != 0)
17118 if (
C !=
Last + ElementSize)
17135 (isa<RegisterSDNode>(VL) &&
17136 cast<RegisterSDNode>(VL)->getReg() == RISCV::X0);
17138 Mask.getOperand(0) != VL)
17141 auto IsTruncNode = [&](
SDValue V) {
17143 V.getOperand(1) == Mask && V.getOperand(2) == VL;
17150 while (IsTruncNode(
Op)) {
17151 if (!
Op.hasOneUse())
17153 Op =
Op.getOperand(0);
17188 MVT VT =
N->getSimpleValueType(0);
17193 auto MatchMinMax = [&VL, &Mask](
SDValue V,
unsigned Opc,
unsigned OpcVL,
17195 if (V.getOpcode() != Opc &&
17196 !(V.getOpcode() == OpcVL && V.getOperand(2).isUndef() &&
17197 V.getOperand(3) == Mask && V.getOperand(4) == VL))
17205 Op.getOperand(1).getValueType().isFixedLengthVector() &&
17207 Op.getOperand(1).getOperand(0).getValueType() ==
Op.getValueType() &&
17209 Op =
Op.getOperand(1).getOperand(0);
17212 return V.getOperand(0);
17215 Op.getOperand(2) == VL) {
17216 if (
auto *Op1 = dyn_cast<ConstantSDNode>(
Op.getOperand(1))) {
17218 Op1->getAPIntValue().sextOrTrunc(
Op.getScalarValueSizeInBits());
17219 return V.getOperand(0);
17228 auto DetectUSatPattern = [&](
SDValue V) {
17253 V.getOperand(1), DAG.
getUNDEF(V.getValueType()),
17259 auto DetectSSatPattern = [&](
SDValue V) {
17261 unsigned NumSrcBits = V.getScalarValueSizeInBits();
17269 if (HiC == SignedMax && LoC == SignedMin)
17275 if (HiC == SignedMax && LoC == SignedMin)
17285 Src.getOperand(1) == Mask && Src.getOperand(2) == VL &&
17287 Src = Src.getOperand(0);
17291 if ((Val = DetectUSatPattern(Src)))
17293 else if ((Val = DetectSSatPattern(Src)))
17303 Val = DAG.
getNode(ClipOpc,
DL, ValVT, Val, Mask, VL);
17304 }
while (ValVT != VT);
17318 EVT VT =
N->getValueType(0);
17326 Src = Src.getOperand(0);
17331 Src = Src.getOperand(0);
17332 EVT SrcEVT = Src.getValueType();
17364 auto SimplifyDemandedLowBitsHelper = [&](
unsigned OpNo,
unsigned LowBits) {
17375 switch (
N->getOpcode()) {
17395 APInt V =
C->getValueAPF().bitcastToAPInt();
17430 if (SimplifyDemandedLowBitsHelper(0, 32) ||
17431 SimplifyDemandedLowBitsHelper(1, 5))
17439 if (SimplifyDemandedLowBitsHelper(0, 32))
17456 MVT VT =
N->getSimpleValueType(0);
17459 if (
auto *CFP = dyn_cast<ConstantFPSDNode>(Op0)) {
17472 "Unexpected value type!");
17477 cast<LoadSDNode>(Op0)->isSimple()) {
17479 auto *LN0 = cast<LoadSDNode>(Op0);
17482 LN0->getBasePtr(), IVT, LN0->getMemOperand());
17506 EVT VT =
N->getValueType(0);
17559 if (!
C || !
C->getValueAPF().isExactlyValue(+1.0))
17561 EVT VT =
N->getValueType(0);
17590 if (
N->getValueType(0) == MVT::i64 && Subtarget.
is64Bit()) {
17595 Src.getOperand(0));
17600 Src.getOperand(0), Src.getOperand(1));
17621 unsigned Opc =
N->getOpcode();
17636 return DAG.
getNode(InvOpc,
SDLoc(
N),
N->getValueType(0), Val, NewCond);
17646 N->getValueType(0), Val,
Cond.getOperand(0));
17657 SDValue FalseV =
N->getOperand(4);
17659 EVT VT =
N->getValueType(0);
17662 if (TrueV == FalseV)
17667 if (!Subtarget.hasShortForwardBranchOpt() && isa<ConstantSDNode>(TrueV) &&
17673 int64_t TrueSImm = cast<ConstantSDNode>(TrueV)->getSExtValue();
17674 int64_t FalseSImm = cast<ConstantSDNode>(FalseV)->getSExtValue();
17677 if (isInt<12>(TrueSImm) && isInt<12>(FalseSImm) &&
17678 isInt<12>(TrueSImm - FalseSImm)) {
17694 {LHS, RHS, CC, TrueV, FalseV});
17761 N->getOperand(0),
LHS,
RHS,
CC,
N->getOperand(4));
17774 EVT VT =
N->getValueType(0);
17798 const auto *MGN = cast<MaskedGatherSDNode>(
N);
17799 const EVT VT =
N->getValueType(0);
17800 SDValue Index = MGN->getIndex();
17801 SDValue ScaleOp = MGN->getScale();
17803 assert(!MGN->isIndexScaled() &&
17804 "Scaled gather/scatter should not be formed");
17809 N->getVTList(), MGN->getMemoryVT(),
DL,
17810 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
17811 MGN->getBasePtr(), Index, ScaleOp},
17812 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
17816 N->getVTList(), MGN->getMemoryVT(),
DL,
17817 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
17818 MGN->getBasePtr(), Index, ScaleOp},
17819 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
17825 if (std::optional<VIDSequence> SimpleVID =
17827 SimpleVID && SimpleVID->StepDenominator == 1) {
17828 const int64_t StepNumerator = SimpleVID->StepNumerator;
17829 const int64_t Addend = SimpleVID->Addend;
17836 assert(MGN->getBasePtr()->getValueType(0) == PtrVT);
17844 VT,
DL, MGN->getChain(), BasePtr,
17846 EVL, MGN->getMemOperand());
17848 StridedLoad, MGN->getPassThru(), EVL);
17858 MGN->getBasePtr(), DAG.
getUNDEF(XLenVT),
17860 MGN->getMemoryVT(), MGN->getMemOperand(),
17869 MGN->getMemOperand()->getBaseAlign(), Subtarget)) {
17871 for (
unsigned i = 0; i < Index->getNumOperands(); i += 2)
17872 NewIndices.
push_back(Index.getOperand(i));
17873 EVT IndexVT = Index.getValueType()
17874 .getHalfNumVectorElementsVT(*DAG.
getContext());
17880 assert(EltCnt.isKnownEven() &&
"Splitting vector, but not in half!");
17882 EltCnt.divideCoefficientBy(2));
17885 EltCnt.divideCoefficientBy(2));
17890 {MGN->getChain(), Passthru, Mask, MGN->getBasePtr(),
17899 const auto *MSN = cast<MaskedScatterSDNode>(
N);
17900 SDValue Index = MSN->getIndex();
17901 SDValue ScaleOp = MSN->getScale();
17903 assert(!MSN->isIndexScaled() &&
17904 "Scaled gather/scatter should not be formed");
17909 N->getVTList(), MSN->getMemoryVT(),
DL,
17910 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
17912 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
17916 N->getVTList(), MSN->getMemoryVT(),
DL,
17917 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
17919 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
17921 EVT VT = MSN->getValue()->getValueType(0);
17923 if (!MSN->isTruncatingStore() &&
17927 return DAG.
getMaskedStore(MSN->getChain(),
DL, Shuffle, MSN->getBasePtr(),
17928 DAG.
getUNDEF(XLenVT), MSN->getMask(),
17929 MSN->getMemoryVT(), MSN->getMemOperand(),
17934 case ISD::VP_GATHER: {
17935 const auto *VPGN = cast<VPGatherSDNode>(
N);
17936 SDValue Index = VPGN->getIndex();
17937 SDValue ScaleOp = VPGN->getScale();
17939 assert(!VPGN->isIndexScaled() &&
17940 "Scaled gather/scatter should not be formed");
17945 {VPGN->getChain(), VPGN->getBasePtr(), Index,
17946 ScaleOp, VPGN->getMask(),
17947 VPGN->getVectorLength()},
17948 VPGN->getMemOperand(), IndexType);
17952 {VPGN->getChain(), VPGN->getBasePtr(), Index,
17953 ScaleOp, VPGN->getMask(),
17954 VPGN->getVectorLength()},
17955 VPGN->getMemOperand(), IndexType);
17959 case ISD::VP_SCATTER: {
17960 const auto *VPSN = cast<VPScatterSDNode>(
N);
17961 SDValue Index = VPSN->getIndex();
17962 SDValue ScaleOp = VPSN->getScale();
17964 assert(!VPSN->isIndexScaled() &&
17965 "Scaled gather/scatter should not be formed");
17970 {VPSN->getChain(), VPSN->getValue(),
17971 VPSN->getBasePtr(), Index, ScaleOp,
17972 VPSN->getMask(), VPSN->getVectorLength()},
17973 VPSN->getMemOperand(), IndexType);
17977 {VPSN->getChain(), VPSN->getValue(),
17978 VPSN->getBasePtr(), Index, ScaleOp,
17979 VPSN->getMask(), VPSN->getVectorLength()},
17980 VPSN->getMemOperand(), IndexType);
17994 EVT VT =
N->getValueType(0);
17997 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt,
17998 N->getOperand(2),
N->getOperand(3),
N->getOperand(4));
18016 EVT VT =
N->getValueType(0);
18020 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt);
18060 auto *Store = cast<StoreSDNode>(
N);
18061 SDValue Chain = Store->getChain();
18062 EVT MemVT = Store->getMemoryVT();
18063 SDValue Val = Store->getValue();
18066 bool IsScalarizable =
18068 Store->isSimple() &&
18098 NewVT, *Store->getMemOperand())) {
18100 return DAG.
getStore(Chain,
DL, NewV, Store->getBasePtr(),
18101 Store->getPointerInfo(), Store->getOriginalAlign(),
18102 Store->getMemOperand()->getFlags());
18110 if (
auto *L = dyn_cast<LoadSDNode>(Val);
18112 L->hasNUsesOfValue(1, 0) && L->hasNUsesOfValue(1, 1) &&
18114 L->getMemoryVT() == MemVT) {
18117 NewVT, *Store->getMemOperand()) &&
18119 NewVT, *L->getMemOperand())) {
18121 L->getPointerInfo(), L->getOriginalAlign(),
18122 L->getMemOperand()->getFlags());
18123 return DAG.
getStore(Chain,
DL, NewL, Store->getBasePtr(),
18124 Store->getPointerInfo(), Store->getOriginalAlign(),
18125 Store->getMemOperand()->getFlags());
18137 MVT VecVT = Src.getSimpleValueType();
18144 Store->getChain(),
DL, Src, Store->getBasePtr(), Store->getOffset(),
18147 Store->getMemOperand(), Store->getAddressingMode(),
18148 Store->isTruncatingStore(),
false);
18155 EVT VT =
N->getValueType(0);
18177 const MVT VT =
N->getSimpleValueType(0);
18178 SDValue Passthru =
N->getOperand(0);
18179 SDValue Scalar =
N->getOperand(1);
18188 const MVT VT =
N->getSimpleValueType(0);
18189 SDValue Passthru =
N->getOperand(0);
18190 SDValue Scalar =
N->getOperand(1);
18195 unsigned ScalarSize = Scalar.getValueSizeInBits();
18197 if (ScalarSize > EltWidth && Passthru.
isUndef())
18198 if (SimplifyDemandedLowBitsHelper(1, EltWidth))
18205 (!Const || Const->isZero() ||
18206 !Const->getAPIntValue().sextOrTrunc(EltWidth).isSignedIntN(5)))
18216 if (
N->getOperand(0).isUndef() &&
18219 Src.getOperand(0).getValueType().isScalableVector()) {
18220 EVT VT =
N->getValueType(0);
18221 EVT SrcVT = Src.getOperand(0).getValueType();
18225 return Src.getOperand(0);
18231 const MVT VT =
N->getSimpleValueType(0);
18232 SDValue Passthru =
N->getOperand(0);
18233 SDValue Scalar =
N->getOperand(1);
18237 Scalar.getOperand(0).getValueType() ==
N->getValueType(0))
18238 return Scalar.getOperand(0);
18247 DAG.
getNode(
N->getOpcode(),
DL, M1VT, M1Passthru, Scalar, VL);
18257 Const && !Const->isZero() && isInt<5>(Const->getSExtValue()) &&
18265 MVT VecVT =
N->getOperand(0).getSimpleValueType();
18267 if (M1VT.
bitsLT(VecVT)) {
18278 unsigned IntNo =
N->getConstantOperandVal(IntOpNo);
18283 case Intrinsic::riscv_vcpop:
18284 case Intrinsic::riscv_vcpop_mask:
18285 case Intrinsic::riscv_vfirst:
18286 case Intrinsic::riscv_vfirst_mask: {
18288 if (IntNo == Intrinsic::riscv_vcpop_mask ||
18289 IntNo == Intrinsic::riscv_vfirst_mask)
18290 VL =
N->getOperand(3);
18295 EVT VT =
N->getValueType(0);
18296 if (IntNo == Intrinsic::riscv_vfirst ||
18297 IntNo == Intrinsic::riscv_vfirst_mask)
18306 EVT VT =
N->getValueType(0);
18317 for (
unsigned i = 0; i < NF; ++i)
18324 if ((SrcVT == MVT::v1i1 || SrcVT == MVT::v2i1 || SrcVT == MVT::v4i1) &&
18347 EVT XVT,
unsigned KeptBits)
const {
18352 if (XVT != MVT::i32 && XVT != MVT::i64)
18356 if (KeptBits == 32 || KeptBits == 64)
18360 return Subtarget.hasStdExtZbb() &&
18361 ((KeptBits == 8 && XVT == MVT::i64 && !Subtarget.
is64Bit()) ||
18369 "Expected shift op");
18387 if (!isa<StoreSDNode>(
Use) && !isa<LoadSDNode>(
Use))
18396 return isUsedByLdSt(N0.
getNode(),
N);
18398 auto *C1 = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
18399 auto *C2 = dyn_cast<ConstantSDNode>(
N->getOperand(1));
18401 const APInt &C1Int = C1->getAPIntValue();
18402 APInt ShiftedC1Int = C1Int << C2->getAPIntValue();
18428 if (C1Cost < ShiftedC1Cost)
18451 EVT VT =
Op.getValueType();
18455 unsigned Opcode =
Op.getOpcode();
18463 const APInt &Mask =
C->getAPIntValue();
18472 auto IsLegalMask = [ShrunkMask, ExpandedMask](
const APInt &Mask) ->
bool {
18473 return ShrunkMask.
isSubsetOf(Mask) && Mask.isSubsetOf(ExpandedMask);
18475 auto UseMask = [Mask,
Op, &TLO](
const APInt &NewMask) ->
bool {
18476 if (NewMask == Mask)
18481 Op.getOperand(0), NewC);
18494 APInt NewMask =
APInt(Mask.getBitWidth(), 0xffff);
18495 if (IsLegalMask(NewMask))
18496 return UseMask(NewMask);
18499 if (VT == MVT::i64) {
18501 if (IsLegalMask(NewMask))
18502 return UseMask(NewMask);
18517 APInt NewMask = ShrunkMask;
18518 if (MinSignedBits <= 12)
18520 else if (!
C->isOpaque() && MinSignedBits <= 32 && !ShrunkMask.
isSignedIntN(32))
18526 assert(IsLegalMask(NewMask));
18527 return UseMask(NewMask);
18531 static const uint64_t GREVMasks[] = {
18532 0x5555555555555555ULL, 0x3333333333333333ULL, 0x0F0F0F0F0F0F0F0FULL,
18533 0x00FF00FF00FF00FFULL, 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL};
18535 for (
unsigned Stage = 0; Stage != 6; ++Stage) {
18536 unsigned Shift = 1 << Stage;
18537 if (ShAmt & Shift) {
18539 uint64_t Res = ((x & Mask) << Shift) | ((x >> Shift) & Mask);
18551 const APInt &DemandedElts,
18553 unsigned Depth)
const {
18555 unsigned Opc =
Op.getOpcode();
18560 "Should use MaskedValueIsZero if you don't know whether Op"
18561 " is a target node!");
18644 assert(MinVLenB > 0 &&
"READ_VLENB without vector extension enabled?");
18647 if (MaxVLenB == MinVLenB)
18664 case Intrinsic::riscv_vsetvli:
18665 case Intrinsic::riscv_vsetvlimax: {
18666 bool HasAVL = IntNo == Intrinsic::riscv_vsetvli;
18667 unsigned VSEW =
Op.getConstantOperandVal(HasAVL + 1);
18673 MaxVL = (Fractional) ? MaxVL / LMul : MaxVL * LMul;
18676 if (HasAVL && isa<ConstantSDNode>(
Op.getOperand(1)))
18677 MaxVL = std::min(MaxVL,
Op.getConstantOperandVal(1));
18679 unsigned KnownZeroFirstBit =
Log2_32(MaxVL) + 1;
18692 unsigned Depth)
const {
18693 switch (
Op.getOpcode()) {
18699 if (Tmp == 1)
return 1;
18702 return std::min(Tmp, Tmp2);
18714 if (Tmp < 33)
return 1;
18739 unsigned XLen = Subtarget.
getXLen();
18740 unsigned EltBits =
Op.getOperand(0).getScalarValueSizeInBits();
18741 if (EltBits <= XLen)
18742 return XLen - EltBits + 1;
18746 unsigned IntNo =
Op.getConstantOperandVal(1);
18750 case Intrinsic::riscv_masked_atomicrmw_xchg_i64:
18751 case Intrinsic::riscv_masked_atomicrmw_add_i64:
18752 case Intrinsic::riscv_masked_atomicrmw_sub_i64:
18753 case Intrinsic::riscv_masked_atomicrmw_nand_i64:
18754 case Intrinsic::riscv_masked_atomicrmw_max_i64:
18755 case Intrinsic::riscv_masked_atomicrmw_min_i64:
18756 case Intrinsic::riscv_masked_atomicrmw_umax_i64:
18757 case Intrinsic::riscv_masked_atomicrmw_umin_i64:
18758 case Intrinsic::riscv_masked_cmpxchg_i64:
18766 assert(Subtarget.hasStdExtA());
18781 switch (
Op.getOpcode()) {
18787 return !
Op.getValueType().isInteger();
18795 assert(Ld &&
"Unexpected null LoadSDNode");
18803 auto *CNode = dyn_cast<ConstantPoolSDNode>(
Ptr);
18804 if (!CNode || CNode->isMachineConstantPoolEntry() ||
18805 CNode->getOffset() != 0)
18813 auto *CNode = GetSupportedConstantPool(
Ptr);
18814 if (!CNode || CNode->getTargetFlags() != 0)
18817 return CNode->getConstVal();
18825 auto *CNodeLo = GetSupportedConstantPool(
Ptr.getOperand(1));
18826 auto *CNodeHi = GetSupportedConstantPool(
Ptr.getOperand(0).getOperand(0));
18832 if (CNodeLo->getConstVal() != CNodeHi->getConstVal())
18835 return CNodeLo->getConstVal();
18840 assert(
MI.getOpcode() == RISCV::ReadCounterWide &&
"Unexpected instruction");
18872 Register ReadAgainReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
18875 int64_t LoCounter =
MI.getOperand(2).getImm();
18876 int64_t HiCounter =
MI.getOperand(3).getImm();
18886 BuildMI(LoopMBB,
DL,
TII->get(RISCV::CSRRS), ReadAgainReg)
18898 MI.eraseFromParent();
18906 assert(
MI.getOpcode() == RISCV::SplitF64Pseudo &&
"Unexpected instruction");
18914 Register SrcReg =
MI.getOperand(2).getReg();
18934 MI.eraseFromParent();
18941 assert(
MI.getOpcode() == RISCV::BuildPairF64Pseudo &&
18942 "Unexpected instruction");
18948 Register DstReg =
MI.getOperand(0).getReg();
18971 MI.eraseFromParent();
18976 switch (
MI.getOpcode()) {
18979 case RISCV::Select_GPR_Using_CC_GPR:
18980 case RISCV::Select_GPR_Using_CC_Imm:
18981 case RISCV::Select_FPR16_Using_CC_GPR:
18982 case RISCV::Select_FPR16INX_Using_CC_GPR:
18983 case RISCV::Select_FPR32_Using_CC_GPR:
18984 case RISCV::Select_FPR32INX_Using_CC_GPR:
18985 case RISCV::Select_FPR64_Using_CC_GPR:
18986 case RISCV::Select_FPR64INX_Using_CC_GPR:
18987 case RISCV::Select_FPR64IN32X_Using_CC_GPR:
18993 unsigned RelOpcode,
unsigned EqOpcode,
18996 Register DstReg =
MI.getOperand(0).getReg();
18997 Register Src1Reg =
MI.getOperand(1).getReg();
18998 Register Src2Reg =
MI.getOperand(2).getReg();
19000 Register SavedFFlags =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
19024 MI.eraseFromParent();
19075 F->insert(It, FirstMBB);
19076 F->insert(It, SecondMBB);
19077 F->insert(It, SinkMBB);
19126 First.eraseFromParent();
19165 if ((
MI.getOpcode() != RISCV::Select_GPR_Using_CC_GPR &&
19166 MI.getOpcode() != RISCV::Select_GPR_Using_CC_Imm) &&
19167 Next != BB->
end() && Next->getOpcode() ==
MI.getOpcode() &&
19168 Next->getOperand(5).getReg() ==
MI.getOperand(0).getReg() &&
19169 Next->getOperand(5).isKill())
19174 if (
MI.getOperand(2).isReg())
19175 RHS =
MI.getOperand(2).getReg();
19180 SelectDests.
insert(
MI.getOperand(0).getReg());
19184 SequenceMBBI != E; ++SequenceMBBI) {
19185 if (SequenceMBBI->isDebugInstr())
19188 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
19189 !SequenceMBBI->getOperand(2).isReg() ||
19190 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
19191 SequenceMBBI->getOperand(3).getImm() !=
CC ||
19192 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
19193 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
19195 LastSelectPseudo = &*SequenceMBBI;
19197 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
19200 if (SequenceMBBI->hasUnmodeledSideEffects() ||
19201 SequenceMBBI->mayLoadOrStore() ||
19202 SequenceMBBI->usesCustomInsertionHook())
19205 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
19220 F->insert(
I, IfFalseMBB);
19221 F->insert(
I, TailMBB);
19224 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
19230 TailMBB->
push_back(DebugInstr->removeFromParent());
19234 TailMBB->
splice(TailMBB->
end(), HeadMBB,
19244 if (
MI.getOperand(2).isImm())
19247 .
addImm(
MI.getOperand(2).getImm())
19259 auto SelectMBBI =
MI.getIterator();
19260 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
19262 while (SelectMBBI != SelectEnd) {
19263 auto Next = std::next(SelectMBBI);
19267 TII.get(RISCV::PHI), SelectMBBI->getOperand(0).getReg())
19268 .
addReg(SelectMBBI->getOperand(4).getReg())
19270 .
addReg(SelectMBBI->getOperand(5).getReg())
19285 RISCVVInversePseudosTable::getBaseInfo(MCOpcode, LMul, SEW);
19286 assert(
Inverse &&
"Unexpected LMUL and SEW pair for instruction");
19288 RISCV::lookupMaskedIntrinsicByUnmasked(
Inverse->Pseudo);
19289 assert(
Masked &&
"Could not find masked instruction for LMUL and SEW pair");
19295 unsigned CVTXOpc) {
19301 Register SavedFFLAGS =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
19314 .
add(
MI.getOperand(1))
19315 .
add(
MI.getOperand(2))
19316 .
add(
MI.getOperand(3))
19318 .
add(
MI.getOperand(4))
19319 .
add(
MI.getOperand(5))
19320 .
add(
MI.getOperand(6))
19335 .
add(
MI.getOperand(0))
19336 .
add(
MI.getOperand(1))
19338 .
add(
MI.getOperand(3))
19340 .
add(
MI.getOperand(4))
19341 .
add(
MI.getOperand(5))
19342 .
add(
MI.getOperand(6))
19352 MI.eraseFromParent();
19358 unsigned CmpOpc, F2IOpc, I2FOpc, FSGNJOpc, FSGNJXOpc;
19360 switch (
MI.getOpcode()) {
19363 case RISCV::PseudoFROUND_H:
19364 CmpOpc = RISCV::FLT_H;
19365 F2IOpc = RISCV::FCVT_W_H;
19366 I2FOpc = RISCV::FCVT_H_W;
19367 FSGNJOpc = RISCV::FSGNJ_H;
19368 FSGNJXOpc = RISCV::FSGNJX_H;
19369 RC = &RISCV::FPR16RegClass;
19371 case RISCV::PseudoFROUND_H_INX:
19372 CmpOpc = RISCV::FLT_H_INX;
19373 F2IOpc = RISCV::FCVT_W_H_INX;
19374 I2FOpc = RISCV::FCVT_H_W_INX;
19375 FSGNJOpc = RISCV::FSGNJ_H_INX;
19376 FSGNJXOpc = RISCV::FSGNJX_H_INX;
19377 RC = &RISCV::GPRF16RegClass;
19379 case RISCV::PseudoFROUND_S:
19380 CmpOpc = RISCV::FLT_S;
19381 F2IOpc = RISCV::FCVT_W_S;
19382 I2FOpc = RISCV::FCVT_S_W;
19383 FSGNJOpc = RISCV::FSGNJ_S;
19384 FSGNJXOpc = RISCV::FSGNJX_S;
19385 RC = &RISCV::FPR32RegClass;
19387 case RISCV::PseudoFROUND_S_INX:
19388 CmpOpc = RISCV::FLT_S_INX;
19389 F2IOpc = RISCV::FCVT_W_S_INX;
19390 I2FOpc = RISCV::FCVT_S_W_INX;
19391 FSGNJOpc = RISCV::FSGNJ_S_INX;
19392 FSGNJXOpc = RISCV::FSGNJX_S_INX;
19393 RC = &RISCV::GPRF32RegClass;
19395 case RISCV::PseudoFROUND_D:
19397 CmpOpc = RISCV::FLT_D;
19398 F2IOpc = RISCV::FCVT_L_D;
19399 I2FOpc = RISCV::FCVT_D_L;
19400 FSGNJOpc = RISCV::FSGNJ_D;
19401 FSGNJXOpc = RISCV::FSGNJX_D;
19402 RC = &RISCV::FPR64RegClass;
19404 case RISCV::PseudoFROUND_D_INX:
19406 CmpOpc = RISCV::FLT_D_INX;
19407 F2IOpc = RISCV::FCVT_L_D_INX;
19408 I2FOpc = RISCV::FCVT_D_L_INX;
19409 FSGNJOpc = RISCV::FSGNJ_D_INX;
19410 FSGNJXOpc = RISCV::FSGNJX_D_INX;
19411 RC = &RISCV::GPRRegClass;
19423 F->insert(
I, CvtMBB);
19424 F->insert(
I, DoneMBB);
19435 Register DstReg =
MI.getOperand(0).getReg();
19436 Register SrcReg =
MI.getOperand(1).getReg();
19437 Register MaxReg =
MI.getOperand(2).getReg();
19438 int64_t FRM =
MI.getOperand(3).getImm();
19443 Register FabsReg =
MRI.createVirtualRegister(RC);
19447 Register CmpReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
19462 Register F2IReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
19484 MI.eraseFromParent();
19491 switch (
MI.getOpcode()) {
19494 case RISCV::ReadCounterWide:
19496 "ReadCounterWide is only to be used on riscv32");
19498 case RISCV::Select_GPR_Using_CC_GPR:
19499 case RISCV::Select_GPR_Using_CC_Imm:
19500 case RISCV::Select_FPR16_Using_CC_GPR:
19501 case RISCV::Select_FPR16INX_Using_CC_GPR:
19502 case RISCV::Select_FPR32_Using_CC_GPR:
19503 case RISCV::Select_FPR32INX_Using_CC_GPR:
19504 case RISCV::Select_FPR64_Using_CC_GPR:
19505 case RISCV::Select_FPR64INX_Using_CC_GPR:
19506 case RISCV::Select_FPR64IN32X_Using_CC_GPR:
19508 case RISCV::BuildPairF64Pseudo:
19510 case RISCV::SplitF64Pseudo:
19512 case RISCV::PseudoQuietFLE_H:
19514 case RISCV::PseudoQuietFLE_H_INX:
19515 return emitQuietFCMP(
MI, BB, RISCV::FLE_H_INX, RISCV::FEQ_H_INX, Subtarget);
19516 case RISCV::PseudoQuietFLT_H:
19518 case RISCV::PseudoQuietFLT_H_INX:
19519 return emitQuietFCMP(
MI, BB, RISCV::FLT_H_INX, RISCV::FEQ_H_INX, Subtarget);
19520 case RISCV::PseudoQuietFLE_S:
19522 case RISCV::PseudoQuietFLE_S_INX:
19523 return emitQuietFCMP(
MI, BB, RISCV::FLE_S_INX, RISCV::FEQ_S_INX, Subtarget);
19524 case RISCV::PseudoQuietFLT_S:
19526 case RISCV::PseudoQuietFLT_S_INX:
19527 return emitQuietFCMP(
MI, BB, RISCV::FLT_S_INX, RISCV::FEQ_S_INX, Subtarget);
19528 case RISCV::PseudoQuietFLE_D:
19530 case RISCV::PseudoQuietFLE_D_INX:
19531 return emitQuietFCMP(
MI, BB, RISCV::FLE_D_INX, RISCV::FEQ_D_INX, Subtarget);
19532 case RISCV::PseudoQuietFLE_D_IN32X:
19535 case RISCV::PseudoQuietFLT_D:
19537 case RISCV::PseudoQuietFLT_D_INX:
19538 return emitQuietFCMP(
MI, BB, RISCV::FLT_D_INX, RISCV::FEQ_D_INX, Subtarget);
19539 case RISCV::PseudoQuietFLT_D_IN32X:
19543 case RISCV::PseudoVFROUND_NOEXCEPT_V_M1_MASK:
19545 case RISCV::PseudoVFROUND_NOEXCEPT_V_M2_MASK:
19547 case RISCV::PseudoVFROUND_NOEXCEPT_V_M4_MASK:
19549 case RISCV::PseudoVFROUND_NOEXCEPT_V_M8_MASK:
19551 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF2_MASK:
19553 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF4_MASK:
19555 case RISCV::PseudoFROUND_H:
19556 case RISCV::PseudoFROUND_H_INX:
19557 case RISCV::PseudoFROUND_S:
19558 case RISCV::PseudoFROUND_S_INX:
19559 case RISCV::PseudoFROUND_D:
19560 case RISCV::PseudoFROUND_D_INX:
19561 case RISCV::PseudoFROUND_D_IN32X:
19563 case TargetOpcode::STATEPOINT:
19569 MI.addOperand(*
MI.getMF(),
19575 case TargetOpcode::STACKMAP:
19576 case TargetOpcode::PATCHPOINT:
19579 "supported on 64-bit targets");
19597 if (
MI.readsRegister(RISCV::FRM,
nullptr))
19603void RISCVTargetLowering::analyzeInputArgs(
19607 unsigned NumArgs = Ins.size();
19610 for (
unsigned i = 0; i != NumArgs; ++i) {
19611 MVT ArgVT = Ins[i].VT;
19614 Type *ArgTy =
nullptr;
19617 else if (Ins[i].isOrigArg())
19618 ArgTy = FType->
getParamType(Ins[i].getOrigArgIndex());
19621 true, IsRet, ArgTy)) {
19622 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type "
19629void RISCVTargetLowering::analyzeOutputArgs(
19633 unsigned NumArgs = Outs.
size();
19635 for (
unsigned i = 0; i != NumArgs; i++) {
19636 MVT ArgVT = Outs[i].VT;
19638 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
19641 Outs[i].IsFixed, IsRet, OrigTy)) {
19642 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type "
19693 if (In.isOrigArg()) {
19698 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
19699 (
BitWidth < 32 && In.Flags.isZExt())) {
19721 if (LocVT == MVT::i64 && VA.
getValVT() == MVT::f32)
19770 ExtType,
DL, LocVT, Chain, FIN,
19787 Register LoVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
19800 Register HiVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
19815 switch (CallConv) {
19825 if (Subtarget.hasStdExtE())
19829 "(Zdinx/D) instruction set extensions");
19833 if (Func.hasFnAttribute(
"interrupt")) {
19834 if (!Func.arg_empty())
19836 "Functions with the interrupt attribute cannot have arguments!");
19841 if (!(Kind ==
"user" || Kind ==
"supervisor" || Kind ==
"machine"))
19843 "Function interrupt attribute argument not supported!");
19848 unsigned XLenInBytes = Subtarget.
getXLen() / 8;
19850 std::vector<SDValue> OutChains;
19859 analyzeInputArgs(MF, CCInfo, Ins,
false,
19863 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
19884 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
19885 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
19887 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
19889 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
19918 int VarArgsSaveSize = XLenInBytes * (ArgRegs.
size() -
Idx);
19923 if (VarArgsSaveSize == 0) {
19927 int VaArgOffset = -VarArgsSaveSize;
19935 XLenInBytes, VaArgOffset -
static_cast<int>(XLenInBytes),
true);
19936 VarArgsSaveSize += XLenInBytes;
19943 for (
unsigned I =
Idx;
I < ArgRegs.
size(); ++
I) {
19948 Chain,
DL, ArgValue, FIN,
19950 OutChains.push_back(Store);
19964 if (!OutChains.empty()) {
19965 OutChains.push_back(Chain);
19975bool RISCVTargetLowering::isEligibleForTailCallOptimization(
19979 auto CalleeCC = CLI.CallConv;
19980 auto &Outs = CLI.Outs;
19982 auto CallerCC = Caller.getCallingConv();
19989 if (Caller.hasFnAttribute(
"interrupt"))
20004 for (
auto &VA : ArgLocs)
20010 auto IsCallerStructRet = Caller.hasStructRetAttr();
20011 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
20012 if (IsCallerStructRet || IsCalleeStructRet)
20017 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
20018 if (CalleeCC != CallerCC) {
20019 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
20020 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
20027 for (
auto &Arg : Outs)
20028 if (Arg.Flags.isByVal())
20063 if (Subtarget.hasStdExtE())
20067 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
20073 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
20079 "site marked musttail");
20086 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
20088 if (!Flags.isByVal())
20092 unsigned Size = Flags.getByValSize();
20093 Align Alignment = Flags.getNonZeroByValAlign();
20100 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
20102 false,
nullptr, IsTailCall,
20114 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
20117 SDValue ArgValue = OutVals[OutIdx];
20137 if (!StackPtr.getNode())
20149 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
20167 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
20168 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
20174 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
20175 SDValue PartValue = OutVals[OutIdx + 1];
20176 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
20188 int FI = cast<FrameIndexSDNode>(SpillSlot)->getIndex();
20190 DAG.
getStore(Chain,
DL, ArgValue, SpillSlot,
20192 for (
const auto &Part : Parts) {
20193 SDValue PartValue = Part.first;
20194 SDValue PartOffset = Part.second;
20201 ArgValue = SpillSlot;
20207 if (Flags.isByVal())
20208 ArgValue = ByValArgs[j++];
20215 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
20216 "for passing parameters");
20219 if (!StackPtr.getNode())
20233 if (!MemOpChains.
empty())
20239 for (
auto &Reg : RegsToPass) {
20240 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
20247 validateCCReservedRegs(RegsToPass, MF);
20251 "Return address register required, but has been reserved."});
20256 bool CalleeIsLargeExternalSymbol =
false;
20258 if (
auto *S = dyn_cast<GlobalAddressSDNode>(Callee))
20260 else if (
auto *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
20262 CalleeIsLargeExternalSymbol =
true;
20278 for (
auto &Reg : RegsToPass)
20284 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
20285 assert(Mask &&
"Missing call preserved mask for calling convention");
20294 "Unexpected CFI type for a direct call");
20302 bool NeedSWGuarded =
false;
20304 Subtarget.hasStdExtZicfilp() &&
20306 NeedSWGuarded =
true;
20320 Chain = DAG.
getNode(CallOpc,
DL, NodeTys, Ops);
20333 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_RISCV);
20336 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
20337 auto &VA = RVLocs[i];
20345 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
20346 assert(VA.needsCustom());
20366 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
20368 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
20369 MVT VT = Outs[i].VT;
20372 true,
true,
nullptr))
20404 for (
unsigned i = 0, e = RVLocs.size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
20405 SDValue Val = OutVals[OutIdx];
20414 DAG.
getVTList(MVT::i32, MVT::i32), Val);
20418 Register RegHi = RVLocs[++i].getLocReg();
20424 "Return value register required, but has been reserved."});
20440 "Return value register required, but has been reserved."});
20462 if (Func.hasFnAttribute(
"interrupt")) {
20463 if (!Func.getReturnType()->isVoidTy())
20465 "Functions with the interrupt attribute must have void return type!");
20471 if (Kind ==
"supervisor")
20477 return DAG.
getNode(RetOpc,
DL, MVT::Other, RetOps);
20480void RISCVTargetLowering::validateCCReservedRegs(
20481 const SmallVectorImpl<std::pair<llvm::Register, llvm::SDValue>> &Regs,
20490 F,
"Argument register required, but has been reserved."});
20496 if (
N->getNumValues() != 1)
20498 if (!
N->hasNUsesOfValue(1, 0))
20501 SDNode *Copy = *
N->user_begin();
20515 if (Copy->getOperand(Copy->getNumOperands() - 1).getValueType() == MVT::Glue)
20519 bool HasRet =
false;
20520 for (
SDNode *Node : Copy->users()) {
20528 Chain = Copy->getOperand(0);
20537#define NODE_NAME_CASE(NODE) \
20538 case RISCVISD::NODE: \
20539 return "RISCVISD::" #NODE;
20800#undef NODE_NAME_CASE
20807 if (Constraint.
size() == 1) {
20808 switch (Constraint[0]) {
20825 if (Constraint ==
"vr" || Constraint ==
"vd" || Constraint ==
"vm")
20827 if (Constraint ==
"cr" || Constraint ==
"cf")
20833std::pair<unsigned, const TargetRegisterClass *>
20839 if (Constraint.
size() == 1) {
20840 switch (Constraint[0]) {
20845 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
20846 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
20847 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
20848 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
20849 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
20850 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
20851 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
20853 if (VT == MVT::f16) {
20854 if (Subtarget.hasStdExtZfhmin())
20855 return std::make_pair(0U, &RISCV::FPR16RegClass);
20856 if (Subtarget.hasStdExtZhinxmin())
20857 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
20858 }
else if (VT == MVT::f32) {
20859 if (Subtarget.hasStdExtF())
20860 return std::make_pair(0U, &RISCV::FPR32RegClass);
20861 if (Subtarget.hasStdExtZfinx())
20862 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
20863 }
else if (VT == MVT::f64) {
20864 if (Subtarget.hasStdExtD())
20865 return std::make_pair(0U, &RISCV::FPR64RegClass);
20866 if (Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
20867 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
20868 if (Subtarget.hasStdExtZdinx() && Subtarget.
is64Bit())
20869 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
20873 if (VT == MVT::f64 && !Subtarget.
is64Bit() && Subtarget.hasStdExtZdinx())
20874 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
20875 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
20879 }
else if (Constraint ==
"vr") {
20880 for (
const auto *RC :
20881 {&RISCV::VRRegClass, &RISCV::VRM2RegClass, &RISCV::VRM4RegClass,
20882 &RISCV::VRM8RegClass, &RISCV::VRN2M1RegClass, &RISCV::VRN3M1RegClass,
20883 &RISCV::VRN4M1RegClass, &RISCV::VRN5M1RegClass,
20884 &RISCV::VRN6M1RegClass, &RISCV::VRN7M1RegClass,
20885 &RISCV::VRN8M1RegClass, &RISCV::VRN2M2RegClass,
20886 &RISCV::VRN3M2RegClass, &RISCV::VRN4M2RegClass,
20887 &RISCV::VRN2M4RegClass}) {
20889 return std::make_pair(0U, RC);
20891 }
else if (Constraint ==
"vd") {
20892 for (
const auto *RC :
20893 {&RISCV::VRNoV0RegClass, &RISCV::VRM2NoV0RegClass,
20894 &RISCV::VRM4NoV0RegClass, &RISCV::VRM8NoV0RegClass,
20895 &RISCV::VRN2M1NoV0RegClass, &RISCV::VRN3M1NoV0RegClass,
20896 &RISCV::VRN4M1NoV0RegClass, &RISCV::VRN5M1NoV0RegClass,
20897 &RISCV::VRN6M1NoV0RegClass, &RISCV::VRN7M1NoV0RegClass,
20898 &RISCV::VRN8M1NoV0RegClass, &RISCV::VRN2M2NoV0RegClass,
20899 &RISCV::VRN3M2NoV0RegClass, &RISCV::VRN4M2NoV0RegClass,
20900 &RISCV::VRN2M4NoV0RegClass}) {
20902 return std::make_pair(0U, RC);
20904 }
else if (Constraint ==
"vm") {
20905 if (
TRI->isTypeLegalForClass(RISCV::VMV0RegClass, VT.
SimpleTy))
20906 return std::make_pair(0U, &RISCV::VMV0RegClass);
20907 }
else if (Constraint ==
"cr") {
20908 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
20909 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
20910 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
20911 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
20912 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
20913 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
20915 return std::make_pair(0U, &RISCV::GPRCRegClass);
20916 }
else if (Constraint ==
"cf") {
20917 if (VT == MVT::f16) {
20918 if (Subtarget.hasStdExtZfhmin())
20919 return std::make_pair(0U, &RISCV::FPR16CRegClass);
20920 if (Subtarget.hasStdExtZhinxmin())
20921 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
20922 }
else if (VT == MVT::f32) {
20923 if (Subtarget.hasStdExtF())
20924 return std::make_pair(0U, &RISCV::FPR32CRegClass);
20925 if (Subtarget.hasStdExtZfinx())
20926 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
20927 }
else if (VT == MVT::f64) {
20928 if (Subtarget.hasStdExtD())
20929 return std::make_pair(0U, &RISCV::FPR64CRegClass);
20930 if (Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
20931 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
20932 if (Subtarget.hasStdExtZdinx() && Subtarget.
is64Bit())
20933 return std::make_pair(0U, &RISCV::GPRCRegClass);
20942 .
Case(
"{zero}", RISCV::X0)
20943 .
Case(
"{ra}", RISCV::X1)
20944 .
Case(
"{sp}", RISCV::X2)
20945 .
Case(
"{gp}", RISCV::X3)
20946 .
Case(
"{tp}", RISCV::X4)
20947 .
Case(
"{t0}", RISCV::X5)
20948 .
Case(
"{t1}", RISCV::X6)
20949 .
Case(
"{t2}", RISCV::X7)
20950 .
Cases(
"{s0}",
"{fp}", RISCV::X8)
20951 .
Case(
"{s1}", RISCV::X9)
20952 .
Case(
"{a0}", RISCV::X10)
20953 .
Case(
"{a1}", RISCV::X11)
20954 .
Case(
"{a2}", RISCV::X12)
20955 .
Case(
"{a3}", RISCV::X13)
20956 .
Case(
"{a4}", RISCV::X14)
20957 .
Case(
"{a5}", RISCV::X15)
20958 .
Case(
"{a6}", RISCV::X16)
20959 .
Case(
"{a7}", RISCV::X17)
20960 .
Case(
"{s2}", RISCV::X18)
20961 .
Case(
"{s3}", RISCV::X19)
20962 .
Case(
"{s4}", RISCV::X20)
20963 .
Case(
"{s5}", RISCV::X21)
20964 .
Case(
"{s6}", RISCV::X22)
20965 .
Case(
"{s7}", RISCV::X23)
20966 .
Case(
"{s8}", RISCV::X24)
20967 .
Case(
"{s9}", RISCV::X25)
20968 .
Case(
"{s10}", RISCV::X26)
20969 .
Case(
"{s11}", RISCV::X27)
20970 .
Case(
"{t3}", RISCV::X28)
20971 .
Case(
"{t4}", RISCV::X29)
20972 .
Case(
"{t5}", RISCV::X30)
20973 .
Case(
"{t6}", RISCV::X31)
20975 if (XRegFromAlias != RISCV::NoRegister)
20976 return std::make_pair(XRegFromAlias, &RISCV::GPRRegClass);
20985 if (Subtarget.hasStdExtF()) {
20987 .
Cases(
"{f0}",
"{ft0}", RISCV::F0_F)
20988 .
Cases(
"{f1}",
"{ft1}", RISCV::F1_F)
20989 .
Cases(
"{f2}",
"{ft2}", RISCV::F2_F)
20990 .
Cases(
"{f3}",
"{ft3}", RISCV::F3_F)
20991 .
Cases(
"{f4}",
"{ft4}", RISCV::F4_F)
20992 .
Cases(
"{f5}",
"{ft5}", RISCV::F5_F)
20993 .
Cases(
"{f6}",
"{ft6}", RISCV::F6_F)
20994 .
Cases(
"{f7}",
"{ft7}", RISCV::F7_F)
20995 .
Cases(
"{f8}",
"{fs0}", RISCV::F8_F)
20996 .
Cases(
"{f9}",
"{fs1}", RISCV::F9_F)
20997 .
Cases(
"{f10}",
"{fa0}", RISCV::F10_F)
20998 .
Cases(
"{f11}",
"{fa1}", RISCV::F11_F)
20999 .
Cases(
"{f12}",
"{fa2}", RISCV::F12_F)
21000 .
Cases(
"{f13}",
"{fa3}", RISCV::F13_F)
21001 .
Cases(
"{f14}",
"{fa4}", RISCV::F14_F)
21002 .
Cases(
"{f15}",
"{fa5}", RISCV::F15_F)
21003 .
Cases(
"{f16}",
"{fa6}", RISCV::F16_F)
21004 .
Cases(
"{f17}",
"{fa7}", RISCV::F17_F)
21005 .
Cases(
"{f18}",
"{fs2}", RISCV::F18_F)
21006 .
Cases(
"{f19}",
"{fs3}", RISCV::F19_F)
21007 .
Cases(
"{f20}",
"{fs4}", RISCV::F20_F)
21008 .
Cases(
"{f21}",
"{fs5}", RISCV::F21_F)
21009 .
Cases(
"{f22}",
"{fs6}", RISCV::F22_F)
21010 .
Cases(
"{f23}",
"{fs7}", RISCV::F23_F)
21011 .
Cases(
"{f24}",
"{fs8}", RISCV::F24_F)
21012 .
Cases(
"{f25}",
"{fs9}", RISCV::F25_F)
21013 .
Cases(
"{f26}",
"{fs10}", RISCV::F26_F)
21014 .
Cases(
"{f27}",
"{fs11}", RISCV::F27_F)
21015 .
Cases(
"{f28}",
"{ft8}", RISCV::F28_F)
21016 .
Cases(
"{f29}",
"{ft9}", RISCV::F29_F)
21017 .
Cases(
"{f30}",
"{ft10}", RISCV::F30_F)
21018 .
Cases(
"{f31}",
"{ft11}", RISCV::F31_F)
21020 if (FReg != RISCV::NoRegister) {
21021 assert(RISCV::F0_F <= FReg && FReg <= RISCV::F31_F &&
"Unknown fp-reg");
21022 if (Subtarget.hasStdExtD() && (VT == MVT::f64 || VT == MVT::Other)) {
21023 unsigned RegNo = FReg - RISCV::F0_F;
21024 unsigned DReg = RISCV::F0_D + RegNo;
21025 return std::make_pair(DReg, &RISCV::FPR64RegClass);
21027 if (VT == MVT::f32 || VT == MVT::Other)
21028 return std::make_pair(FReg, &RISCV::FPR32RegClass);
21029 if (Subtarget.hasStdExtZfhmin() && VT == MVT::f16) {
21030 unsigned RegNo = FReg - RISCV::F0_F;
21031 unsigned HReg = RISCV::F0_H + RegNo;
21032 return std::make_pair(HReg, &RISCV::FPR16RegClass);
21039 .
Case(
"{v0}", RISCV::V0)
21040 .
Case(
"{v1}", RISCV::V1)
21041 .
Case(
"{v2}", RISCV::V2)
21042 .
Case(
"{v3}", RISCV::V3)
21043 .
Case(
"{v4}", RISCV::V4)
21044 .
Case(
"{v5}", RISCV::V5)
21045 .
Case(
"{v6}", RISCV::V6)
21046 .
Case(
"{v7}", RISCV::V7)
21047 .
Case(
"{v8}", RISCV::V8)
21048 .
Case(
"{v9}", RISCV::V9)
21049 .
Case(
"{v10}", RISCV::V10)
21050 .
Case(
"{v11}", RISCV::V11)
21051 .
Case(
"{v12}", RISCV::V12)
21052 .
Case(
"{v13}", RISCV::V13)
21053 .
Case(
"{v14}", RISCV::V14)
21054 .
Case(
"{v15}", RISCV::V15)
21055 .
Case(
"{v16}", RISCV::V16)
21056 .
Case(
"{v17}", RISCV::V17)
21057 .
Case(
"{v18}", RISCV::V18)
21058 .
Case(
"{v19}", RISCV::V19)
21059 .
Case(
"{v20}", RISCV::V20)
21060 .
Case(
"{v21}", RISCV::V21)
21061 .
Case(
"{v22}", RISCV::V22)
21062 .
Case(
"{v23}", RISCV::V23)
21063 .
Case(
"{v24}", RISCV::V24)
21064 .
Case(
"{v25}", RISCV::V25)
21065 .
Case(
"{v26}", RISCV::V26)
21066 .
Case(
"{v27}", RISCV::V27)
21067 .
Case(
"{v28}", RISCV::V28)
21068 .
Case(
"{v29}", RISCV::V29)
21069 .
Case(
"{v30}", RISCV::V30)
21070 .
Case(
"{v31}", RISCV::V31)
21072 if (VReg != RISCV::NoRegister) {
21073 if (
TRI->isTypeLegalForClass(RISCV::VMRegClass, VT.
SimpleTy))
21074 return std::make_pair(VReg, &RISCV::VMRegClass);
21075 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, VT.
SimpleTy))
21076 return std::make_pair(VReg, &RISCV::VRRegClass);
21077 for (
const auto *RC :
21078 {&RISCV::VRM2RegClass, &RISCV::VRM4RegClass, &RISCV::VRM8RegClass}) {
21079 if (
TRI->isTypeLegalForClass(*RC, VT.
SimpleTy)) {
21080 VReg =
TRI->getMatchingSuperReg(VReg, RISCV::sub_vrm1_0, RC);
21081 return std::make_pair(VReg, RC);
21087 std::pair<Register, const TargetRegisterClass *> Res =
21093 if (Res.second == &RISCV::GPRF16RegClass ||
21094 Res.second == &RISCV::GPRF32RegClass ||
21095 Res.second == &RISCV::GPRPairRegClass)
21096 return std::make_pair(Res.first, &RISCV::GPRRegClass);
21104 if (ConstraintCode.
size() == 1) {
21105 switch (ConstraintCode[0]) {
21120 if (Constraint.
size() == 1) {
21121 switch (Constraint[0]) {
21124 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
21126 if (isInt<12>(CVal))
21139 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
21141 if (isUInt<5>(CVal))
21159 if (Subtarget.hasStdExtZtso()) {
21175 if (Subtarget.hasStdExtZtso()) {
21183 if (Subtarget.enableTrailingSeqCstFence() && isa<StoreInst>(Inst) &&
21202 if (Subtarget.hasForcedAtomics())
21207 if (Subtarget.hasStdExtZacas() &&
21208 (
Size >= 32 || Subtarget.hasStdExtZabha()))
21214 if (
Size < 32 && !Subtarget.hasStdExtZabha())
21227 return Intrinsic::riscv_masked_atomicrmw_xchg_i32;
21229 return Intrinsic::riscv_masked_atomicrmw_add_i32;
21231 return Intrinsic::riscv_masked_atomicrmw_sub_i32;
21233 return Intrinsic::riscv_masked_atomicrmw_nand_i32;
21235 return Intrinsic::riscv_masked_atomicrmw_max_i32;
21237 return Intrinsic::riscv_masked_atomicrmw_min_i32;
21239 return Intrinsic::riscv_masked_atomicrmw_umax_i32;
21241 return Intrinsic::riscv_masked_atomicrmw_umin_i32;
21250 return Intrinsic::riscv_masked_atomicrmw_xchg_i64;
21252 return Intrinsic::riscv_masked_atomicrmw_add_i64;
21254 return Intrinsic::riscv_masked_atomicrmw_sub_i64;
21256 return Intrinsic::riscv_masked_atomicrmw_nand_i64;
21258 return Intrinsic::riscv_masked_atomicrmw_max_i64;
21260 return Intrinsic::riscv_masked_atomicrmw_min_i64;
21262 return Intrinsic::riscv_masked_atomicrmw_umax_i64;
21264 return Intrinsic::riscv_masked_atomicrmw_umin_i64;
21290 unsigned XLen = Subtarget.
getXLen();
21314 unsigned ValWidth =
21319 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
21322 Builder.
CreateCall(LrwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
21334 if (Subtarget.hasForcedAtomics())
21338 if (!(Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas()) &&
21347 unsigned XLen = Subtarget.
getXLen();
21349 Intrinsic::ID CmpXchgIntrID = Intrinsic::riscv_masked_cmpxchg_i32;
21354 CmpXchgIntrID = Intrinsic::riscv_masked_cmpxchg_i64;
21358 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, Ordering});
21365 EVT DataVT)
const {
21381 return Subtarget.hasStdExtZfhmin();
21383 return Subtarget.hasStdExtF();
21385 return Subtarget.hasStdExtD();
21417 "RVVBitsPerBlock changed, audit needed");
21426 if (!Subtarget.hasVendorXTHeadMemIdx())
21432 Base =
Op->getOperand(0);
21434 int64_t RHSC =
RHS->getSExtValue();
21440 bool isLegalIndexedOffset =
false;
21441 for (
unsigned i = 0; i < 4; i++)
21442 if (isInt<5>(RHSC >> i) && ((RHSC % (1LL << i)) == 0)) {
21443 isLegalIndexedOffset =
true;
21447 if (!isLegalIndexedOffset)
21464 VT = LD->getMemoryVT();
21465 Ptr = LD->getBasePtr();
21466 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
21467 VT = ST->getMemoryVT();
21468 Ptr = ST->getBasePtr();
21484 if (Subtarget.hasVendorXCVmem() && !Subtarget.
is64Bit()) {
21489 Base = LS->getBasePtr();
21493 if (
Base ==
Op->getOperand(0))
21495 else if (
Base ==
Op->getOperand(1))
21507 VT = LD->getMemoryVT();
21508 Ptr = LD->getBasePtr();
21509 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
21510 VT = ST->getMemoryVT();
21511 Ptr = ST->getBasePtr();
21554 const Constant *PersonalityFn)
const {
21559 const Constant *PersonalityFn)
const {
21574 bool IsSigned)
const {
21589 const bool HasZmmul = Subtarget.hasStdExtZmmul();
21593 auto *ConstNode = cast<ConstantSDNode>(
C);
21594 const APInt &Imm = ConstNode->getAPIntValue();
21597 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
21598 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
21602 if (Subtarget.hasStdExtZba() && !Imm.isSignedIntN(12) &&
21603 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
21604 (Imm - 8).isPowerOf2()))
21609 if (!Imm.isSignedIntN(12) && Imm.countr_zero() < 12 &&
21610 ConstNode->hasOneUse()) {
21611 APInt ImmS = Imm.ashr(Imm.countr_zero());
21612 if ((ImmS + 1).isPowerOf2() || (ImmS - 1).isPowerOf2() ||
21613 (1 - ImmS).isPowerOf2())
21636 if (C1.
isSignedIntN(12) && !(C1 * C2).isSignedIntN(12))
21645 unsigned *
Fast)
const {
21648 *
Fast = Subtarget.enableUnalignedScalarMem();
21649 return Subtarget.enableUnalignedScalarMem();
21665 *
Fast = Subtarget.enableUnalignedVectorMem();
21666 return Subtarget.enableUnalignedVectorMem();
21675 if (FuncAttributes.
hasFnAttr(Attribute::NoImplicitFloat))
21687 if (
Op.size() < MinVLenInBytes)
21702 MVT PreferredVT = (
Op.isMemset() && !
Op.isZeroMemset()) ? MVT::i8 : ELenVT;
21706 if (PreferredVT != MVT::i8 && !Subtarget.enableUnalignedVectorMem()) {
21708 if (
Op.isFixedDstAlign())
21709 RequiredAlign = std::min(RequiredAlign,
Op.getDstAlign());
21711 RequiredAlign = std::min(RequiredAlign,
Op.getSrcAlign());
21719 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID>
CC)
const {
21720 bool IsABIRegCopy =
CC.has_value();
21723 MVT PairVT = Subtarget.
is64Bit() ? MVT::i128 : MVT::i64;
21724 if ((ValueVT == PairVT ||
21725 (!Subtarget.
is64Bit() && Subtarget.hasStdExtZdinx() &&
21726 ValueVT == MVT::f64)) &&
21727 NumParts == 1 && PartVT == MVT::Untyped) {
21730 if (ValueVT == MVT::f64)
21739 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
21740 PartVT == MVT::f32) {
21755 [[maybe_unused]]
unsigned ValLMUL =
21759 [[maybe_unused]]
unsigned PartLMUL =
21762 assert(ValNF == PartNF && ValLMUL == PartLMUL &&
21763 "RISC-V vector tuple type only accepts same register class type "
21779 if (PartVTBitSize % ValueVTBitSize == 0) {
21780 assert(PartVTBitSize >= ValueVTBitSize);
21787 if (ValueEltVT != PartEltVT) {
21788 if (PartVTBitSize > ValueVTBitSize) {
21790 assert(Count != 0 &&
"The number of element should not be zero.");
21791 EVT SameEltTypeVT =
21813 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID>
CC)
const {
21814 bool IsABIRegCopy =
CC.has_value();
21816 MVT PairVT = Subtarget.
is64Bit() ? MVT::i128 : MVT::i64;
21817 if ((ValueVT == PairVT ||
21818 (!Subtarget.
is64Bit() && Subtarget.hasStdExtZdinx() &&
21819 ValueVT == MVT::f64)) &&
21820 NumParts == 1 && PartVT == MVT::Untyped) {
21831 if (ValueVT == MVT::f64)
21836 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
21837 PartVT == MVT::f32) {
21854 if (PartVTBitSize % ValueVTBitSize == 0) {
21855 assert(PartVTBitSize >= ValueVTBitSize);
21856 EVT SameEltTypeVT = ValueVT;
21863 if (ValueEltVT != PartEltVT) {
21865 assert(Count != 0 &&
"The number of element should not be zero.");
21882 bool OptSize = Attr.
hasFnAttr(Attribute::MinSize);
21889 unsigned Opc =
N->getOpcode();
21917 if (M->getStackProtectorGuard() ==
"tls") {
21919 int Offset = M->getStackProtectorGuardOffset();
21927 VectorType *VTy,
unsigned Factor,
Align Alignment,
unsigned AddrSpace,
21941 if (
auto *FVTy = dyn_cast<FixedVectorType>(VTy)) {
21946 if (FVTy->getNumElements() < 2)
21961 return Factor * LMUL <= 8;
21965 Align Alignment)
const {
21977 if (!Subtarget.enableUnalignedVectorMem() &&
21985 Intrinsic::riscv_seg2_load, Intrinsic::riscv_seg3_load,
21986 Intrinsic::riscv_seg4_load, Intrinsic::riscv_seg5_load,
21987 Intrinsic::riscv_seg6_load, Intrinsic::riscv_seg7_load,
21988 Intrinsic::riscv_seg8_load};
22009 auto *VTy = cast<FixedVectorType>(Shuffles[0]->
getType());
22021 unsigned ScalarSizeInBytes = VTy->getScalarSizeInBits() / 8;
22022 Value *Stride = ConstantInt::get(XLenTy, Factor * ScalarSizeInBytes);
22023 Value *
Offset = ConstantInt::get(XLenTy, Indices[0] * ScalarSizeInBytes);
22030 {VTy, BasePtr->getType(), Stride->
getType()},
22031 {BasePtr, Stride, Mask, VL});
22034 Shuffles[0]->replaceAllUsesWith(CI);
22038 Value *VL = ConstantInt::get(XLenTy, VTy->getNumElements());
22044 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
22046 Shuffles[i]->replaceAllUsesWith(SubVec);
22053 Intrinsic::riscv_seg2_store, Intrinsic::riscv_seg3_store,
22054 Intrinsic::riscv_seg4_store, Intrinsic::riscv_seg5_store,
22055 Intrinsic::riscv_seg6_store, Intrinsic::riscv_seg7_store,
22056 Intrinsic::riscv_seg8_store};
22076 unsigned Factor)
const {
22079 auto *ShuffleVTy = cast<FixedVectorType>(SVI->
getType());
22082 ShuffleVTy->getNumElements() / Factor);
22084 SI->getPointerAddressSpace(),
22085 SI->getDataLayout()))
22096 unsigned ScalarSizeInBytes = ShuffleVTy->getScalarSizeInBits() / 8;
22098 auto *DataVTy = cast<FixedVectorType>(
Data->getType());
22099 Value *Stride = ConstantInt::get(XLenTy, Factor * ScalarSizeInBytes);
22100 Value *
Offset = ConstantInt::get(XLenTy, Index * ScalarSizeInBytes);
22106 Intrinsic::experimental_vp_strided_store,
22107 {
Data->getType(), BasePtr->getType(), Stride->
getType()},
22108 {
Data, BasePtr, Stride, Mask, VL});
22117 {VTy, SI->getPointerOperandType(), XLenTy});
22121 for (
unsigned i = 0; i < Factor; i++) {
22130 Value *VL = ConstantInt::get(XLenTy, VTy->getNumElements());
22131 Ops.
append({SI->getPointerOperand(), VL});
22148 const unsigned Factor = 2;
22160 if (
auto *FVTy = dyn_cast<FixedVectorType>(ResVTy)) {
22161 Value *VL = ConstantInt::get(XLenTy, FVTy->getNumElements());
22168 Intrinsic::riscv_vlseg2, Intrinsic::riscv_vlseg3,
22169 Intrinsic::riscv_vlseg4, Intrinsic::riscv_vlseg5,
22170 Intrinsic::riscv_vlseg6, Intrinsic::riscv_vlseg7,
22171 Intrinsic::riscv_vlseg8};
22178 NumElts * SEW / 8),
22184 IntrIds[Factor - 2], {VecTupTy, XLenTy},
22186 ConstantInt::get(XLenTy,
Log2_64(SEW))});
22190 for (
unsigned i = 0; i < Factor; ++i) {
22192 Intrinsic::riscv_tuple_extract, {ResVTy, VecTupTy},
22210 if (
II->getIntrinsicID() != Intrinsic::vector_interleave2)
22213 const unsigned Factor = 2;
22215 VectorType *InVTy = cast<VectorType>(
II->getArgOperand(0)->getType());
22219 SI->getPointerAddressSpace(),
DL))
22224 if (
auto *FVTy = dyn_cast<FixedVectorType>(InVTy)) {
22225 Value *VL = ConstantInt::get(XLenTy, FVTy->getNumElements());
22227 {InVTy, SI->getPointerOperandType(), XLenTy},
22228 {
II->getArgOperand(0),
II->getArgOperand(1),
22229 SI->getPointerOperand(), VL});
22232 Intrinsic::riscv_vsseg2, Intrinsic::riscv_vsseg3,
22233 Intrinsic::riscv_vsseg4, Intrinsic::riscv_vsseg5,
22234 Intrinsic::riscv_vsseg6, Intrinsic::riscv_vsseg7,
22235 Intrinsic::riscv_vsseg8};
22240 SI->getContext(),
"riscv.vector.tuple",
22242 NumElts * SEW / 8),
22246 SI->getModule(), IntrIds[Factor - 2], {VecTupTy, XLenTy});
22251 for (
unsigned i = 0; i < Factor; ++i)
22253 Intrinsic::riscv_tuple_insert, {VecTupTy, InVTy},
22254 {StoredVal, II->getArgOperand(i), Builder.getInt32(i)});
22256 Builder.
CreateCall(VssegNFunc, {StoredVal, SI->getPointerOperand(), VL,
22257 ConstantInt::get(XLenTy,
Log2_64(SEW))});
22268 "Invalid call instruction for a KCFI check");
22270 MBBI->getOpcode()));
22273 Target.setIsRenamable(
false);
22281#define GET_REGISTER_MATCHER
22282#include "RISCVGenAsmMatcher.inc"
22288 if (Reg == RISCV::NoRegister)
22290 if (Reg == RISCV::NoRegister)
22302 const MDNode *NontemporalInfo =
I.getMetadata(LLVMContext::MD_nontemporal);
22304 if (NontemporalInfo ==
nullptr)
22312 int NontemporalLevel = 5;
22313 const MDNode *RISCVNontemporalInfo =
22314 I.getMetadata(
"riscv-nontemporal-domain");
22315 if (RISCVNontemporalInfo !=
nullptr)
22318 cast<ConstantAsMetadata>(RISCVNontemporalInfo->
getOperand(0))
22322 assert((1 <= NontemporalLevel && NontemporalLevel <= 5) &&
22323 "RISC-V target doesn't support this non-temporal domain.");
22325 NontemporalLevel -= 2;
22327 if (NontemporalLevel & 0b1)
22329 if (NontemporalLevel & 0b10)
22342 return TargetFlags;
22352 return isTypeLegal(VT) && Subtarget.hasStdExtZvbb();
22355 return Subtarget.hasStdExtZbb() &&
22366 if (Subtarget.hasStdExtZalasr()) {
22367 if (Subtarget.hasStdExtZtso()) {
22372 auto *LI = dyn_cast<LoadInst>(
I);
22373 auto *SI = dyn_cast<StoreInst>(
I);
22383 return isa<LoadInst>(
I) || isa<StoreInst>(
I);
22390 return isa<LoadInst>(
I) || isa<StoreInst>(
I);
22397 if (
Op == Instruction::Add ||
Op == Instruction::Sub ||
22398 Op == Instruction::And ||
Op == Instruction::Or ||
22399 Op == Instruction::Xor ||
Op == Instruction::InsertElement ||
22400 Op == Instruction::ShuffleVector ||
Op == Instruction::Load ||
22401 Op == Instruction::Freeze ||
Op == Instruction::Store)
22409 !isa<ReturnInst>(&Inst))
22412 if (
const AllocaInst *AI = dyn_cast<AllocaInst>(&Inst)) {
22413 if (AI->getAllocatedType()->isScalableTy())
22421RISCVTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
22429 if (!Subtarget.hasShortForwardBranchOpt())
22431 EVT VT =
N->getValueType(0);
22432 if (!(VT == MVT::i32 || (VT == MVT::i64 && Subtarget.
is64Bit())))
22436 if (Divisor.
sgt(2048) || Divisor.
slt(-2048))
22441bool RISCVTargetLowering::shouldFoldSelectWithSingleBitTest(
22442 EVT VT,
const APInt &AndMask)
const {
22443 if (Subtarget.hasStdExtZicond() || Subtarget.hasVendorXVentanaCondOps())
22444 return !Subtarget.hasStdExtZbs() && AndMask.
ugt(1024);
22448unsigned RISCVTargetLowering::getMinimumJumpTableEntries()
const {
22456 if (Subtarget.hasStdExtZicfilp()) {
22480std::pair<const TargetRegisterClass *, uint8_t>
22500#define GET_RISCVVIntrinsicsTable_IMPL
22501#include "RISCVGenSearchableTables.inc"
22516 Align StackAlign)
const {
22520 unsigned StackProbeSize =
22524 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 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.
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="")
CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, Instruction *FMFSource=nullptr, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
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.
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.)
Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
bool isNullOrNullSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndefs=false)
Return true if the value is a constant 0 integer or a splatted vector of a constant 0 integer (with n...
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
bool isReleaseOrStronger(AtomicOrdering AO)
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
bool CC_RISCV_FastCC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed, bool IsRet, Type *OrigTy)
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
bool isOneOrOneSplat(SDValue V, bool AllowUndefs=false)
Return true if the value is a constant 1 integer or a splatted vector of a constant 1 integer (with n...
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
AtomicOrdering
Atomic ordering for LLVM's memory model.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
void 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)> ManyInputsAction)
Splits and processes shuffle mask depending on the number of input and output registers.
@ 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.
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)