39#include "llvm/IR/IntrinsicsRISCV.h"
54#define DEBUG_TYPE "riscv-lower"
60 cl::desc(
"Give the maximum size (in number of nodes) of the web of "
61 "instructions that we will consider for VW expansion"),
66 cl::desc(
"Allow the formation of VW_W operations (e.g., "
67 "VWADD_W) with splat constants"),
72 cl::desc(
"Set the minimum number of repetitions of a divisor to allow "
73 "transformation to multiplications by the reciprocal"),
78 cl::desc(
"Give the maximum number of instructions that we will "
79 "use for creating a floating-point immediate value"),
90 !Subtarget.hasStdExtF()) {
91 errs() <<
"Hard-float 'f' ABI can't be used for a target that "
92 "doesn't support the F instruction set extension (ignoring "
96 !Subtarget.hasStdExtD()) {
97 errs() <<
"Hard-float 'd' ABI can't be used for a target that "
98 "doesn't support the D instruction set extension (ignoring "
122 if (Subtarget.hasStdExtZfhmin())
124 if (Subtarget.hasStdExtZfbfmin())
126 if (Subtarget.hasStdExtF())
128 if (Subtarget.hasStdExtD())
130 if (Subtarget.hasStdExtZhinxmin())
132 if (Subtarget.hasStdExtZfinx())
134 if (Subtarget.hasStdExtZdinx()) {
142 MVT::nxv1i1, MVT::nxv2i1, MVT::nxv4i1, MVT::nxv8i1,
143 MVT::nxv16i1, MVT::nxv32i1, MVT::nxv64i1};
145 MVT::nxv1i8, MVT::nxv2i8, MVT::nxv4i8, MVT::nxv8i8, MVT::nxv16i8,
146 MVT::nxv32i8, MVT::nxv64i8, MVT::nxv1i16, MVT::nxv2i16, MVT::nxv4i16,
147 MVT::nxv8i16, MVT::nxv16i16, MVT::nxv32i16, MVT::nxv1i32, MVT::nxv2i32,
148 MVT::nxv4i32, MVT::nxv8i32, MVT::nxv16i32, MVT::nxv1i64, MVT::nxv2i64,
149 MVT::nxv4i64, MVT::nxv8i64};
151 MVT::nxv1f16, MVT::nxv2f16, MVT::nxv4f16,
152 MVT::nxv8f16, MVT::nxv16f16, MVT::nxv32f16};
154 MVT::nxv1bf16, MVT::nxv2bf16, MVT::nxv4bf16,
155 MVT::nxv8bf16, MVT::nxv16bf16, MVT::nxv32bf16};
157 MVT::nxv1f32, MVT::nxv2f32, MVT::nxv4f32, MVT::nxv8f32, MVT::nxv16f32};
159 MVT::nxv1f64, MVT::nxv2f64, MVT::nxv4f64, MVT::nxv8f64};
161 MVT::riscv_nxv1i8x2, MVT::riscv_nxv1i8x3, MVT::riscv_nxv1i8x4,
162 MVT::riscv_nxv1i8x5, MVT::riscv_nxv1i8x6, MVT::riscv_nxv1i8x7,
163 MVT::riscv_nxv1i8x8, MVT::riscv_nxv2i8x2, MVT::riscv_nxv2i8x3,
164 MVT::riscv_nxv2i8x4, MVT::riscv_nxv2i8x5, MVT::riscv_nxv2i8x6,
165 MVT::riscv_nxv2i8x7, MVT::riscv_nxv2i8x8, MVT::riscv_nxv4i8x2,
166 MVT::riscv_nxv4i8x3, MVT::riscv_nxv4i8x4, MVT::riscv_nxv4i8x5,
167 MVT::riscv_nxv4i8x6, MVT::riscv_nxv4i8x7, MVT::riscv_nxv4i8x8,
168 MVT::riscv_nxv8i8x2, MVT::riscv_nxv8i8x3, MVT::riscv_nxv8i8x4,
169 MVT::riscv_nxv8i8x5, MVT::riscv_nxv8i8x6, MVT::riscv_nxv8i8x7,
170 MVT::riscv_nxv8i8x8, MVT::riscv_nxv16i8x2, MVT::riscv_nxv16i8x3,
171 MVT::riscv_nxv16i8x4, MVT::riscv_nxv32i8x2};
174 auto addRegClassForRVV = [
this](
MVT VT) {
178 if (VT.getVectorMinNumElements() < MinElts)
181 unsigned Size = VT.getSizeInBits().getKnownMinValue();
184 RC = &RISCV::VRRegClass;
186 RC = &RISCV::VRM2RegClass;
188 RC = &RISCV::VRM4RegClass;
190 RC = &RISCV::VRM8RegClass;
197 for (
MVT VT : BoolVecVTs)
198 addRegClassForRVV(VT);
199 for (
MVT VT : IntVecVTs) {
200 if (VT.getVectorElementType() == MVT::i64 &&
203 addRegClassForRVV(VT);
207 for (
MVT VT : F16VecVTs)
208 addRegClassForRVV(VT);
211 for (
MVT VT : BF16VecVTs)
212 addRegClassForRVV(VT);
215 for (
MVT VT : F32VecVTs)
216 addRegClassForRVV(VT);
219 for (
MVT VT : F64VecVTs)
220 addRegClassForRVV(VT);
223 auto addRegClassForFixedVectors = [
this](
MVT VT) {
230 if (useRVVForFixedLengthVectorVT(VT))
231 addRegClassForFixedVectors(VT);
234 if (useRVVForFixedLengthVectorVT(VT))
235 addRegClassForFixedVectors(VT);
295 if (!(Subtarget.hasVendorXCValu() && !Subtarget.
is64Bit())) {
305 if (!Subtarget.hasVendorXTHeadBb())
310 if (!Subtarget.hasStdExtZbb() && !Subtarget.hasVendorXTHeadBb() &&
311 !(Subtarget.hasVendorXCValu() && !Subtarget.
is64Bit()))
321 if (!Subtarget.hasStdExtZbb())
327 if (!Subtarget.hasStdExtZmmul()) {
329 }
else if (Subtarget.
is64Bit()) {
336 if (!Subtarget.hasStdExtM()) {
339 }
else if (Subtarget.
is64Bit()) {
341 {MVT::i8, MVT::i16, MVT::i32},
Custom);
351 if (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) {
354 }
else if (Subtarget.hasVendorXTHeadBb()) {
358 }
else if (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit()) {
367 (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb() ||
368 Subtarget.hasVendorXTHeadBb())
372 if (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit()) {
380 if (Subtarget.hasStdExtZbb() ||
381 (Subtarget.hasVendorXCValu() && !Subtarget.
is64Bit())) {
386 if (Subtarget.hasStdExtZbb() ||
387 (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit())) {
394 if (Subtarget.hasStdExtZbb() || Subtarget.hasVendorXTHeadBb() ||
395 (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit())) {
404 if (Subtarget.hasVendorXCValu() && !Subtarget.
is64Bit()) {
406 }
else if (Subtarget.hasShortForwardBranchOpt()) {
409 }
else if (Subtarget.
is64Bit()) {
415 else if (!Subtarget.hasVendorXTHeadCondMov())
418 static const unsigned FPLegalNodeTypes[] = {
432 static const unsigned FPOpToExpand[] = {
436 static const unsigned FPRndMode[] = {
440 static const unsigned ZfhminZfbfminPromoteOps[] = {
451 if (Subtarget.hasStdExtZfbfmin()) {
474 if (Subtarget.hasStdExtZfa())
501 Subtarget.hasStdExtZfh() && Subtarget.hasStdExtZfa() ?
Legal :
Promote);
543 if (Subtarget.hasStdExtZfa()) {
561 if (Subtarget.hasStdExtZfa()) {
643 if (Subtarget.hasStdExtZicbop()) {
647 if (Subtarget.hasStdExtA()) {
649 if (Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas())
653 }
else if (Subtarget.hasForcedAtomics()) {
677 {MVT::i8, MVT::i16},
Custom);
688 static const unsigned IntegerVPOps[] = {
689 ISD::VP_ADD, ISD::VP_SUB, ISD::VP_MUL,
690 ISD::VP_SDIV, ISD::VP_UDIV, ISD::VP_SREM,
691 ISD::VP_UREM, ISD::VP_AND, ISD::VP_OR,
692 ISD::VP_XOR, ISD::VP_SRA, ISD::VP_SRL,
693 ISD::VP_SHL, ISD::VP_REDUCE_ADD, ISD::VP_REDUCE_AND,
694 ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR, ISD::VP_REDUCE_SMAX,
695 ISD::VP_REDUCE_SMIN, ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN,
696 ISD::VP_MERGE, ISD::VP_SELECT, ISD::VP_FP_TO_SINT,
697 ISD::VP_FP_TO_UINT, ISD::VP_SETCC, ISD::VP_SIGN_EXTEND,
698 ISD::VP_ZERO_EXTEND, ISD::VP_TRUNCATE, ISD::VP_SMIN,
699 ISD::VP_SMAX, ISD::VP_UMIN, ISD::VP_UMAX,
700 ISD::VP_ABS, ISD::EXPERIMENTAL_VP_REVERSE, ISD::EXPERIMENTAL_VP_SPLICE,
701 ISD::VP_SADDSAT, ISD::VP_UADDSAT, ISD::VP_SSUBSAT,
702 ISD::VP_USUBSAT, ISD::VP_CTTZ_ELTS, ISD::VP_CTTZ_ELTS_ZERO_UNDEF,
703 ISD::EXPERIMENTAL_VP_SPLAT};
705 static const unsigned FloatingPointVPOps[] = {
706 ISD::VP_FADD, ISD::VP_FSUB, ISD::VP_FMUL,
707 ISD::VP_FDIV, ISD::VP_FNEG, ISD::VP_FABS,
708 ISD::VP_FMA, ISD::VP_REDUCE_FADD, ISD::VP_REDUCE_SEQ_FADD,
709 ISD::VP_REDUCE_FMIN, ISD::VP_REDUCE_FMAX, ISD::VP_MERGE,
710 ISD::VP_SELECT, ISD::VP_SINT_TO_FP, ISD::VP_UINT_TO_FP,
711 ISD::VP_SETCC, ISD::VP_FP_ROUND, ISD::VP_FP_EXTEND,
712 ISD::VP_SQRT, ISD::VP_FMINNUM, ISD::VP_FMAXNUM,
713 ISD::VP_FCEIL, ISD::VP_FFLOOR, ISD::VP_FROUND,
714 ISD::VP_FROUNDEVEN, ISD::VP_FCOPYSIGN, ISD::VP_FROUNDTOZERO,
715 ISD::VP_FRINT, ISD::VP_FNEARBYINT, ISD::VP_IS_FPCLASS,
716 ISD::VP_FMINIMUM, ISD::VP_FMAXIMUM, ISD::VP_LRINT,
717 ISD::VP_LLRINT, ISD::EXPERIMENTAL_VP_REVERSE,
718 ISD::EXPERIMENTAL_VP_SPLICE, ISD::VP_REDUCE_FMINIMUM,
719 ISD::VP_REDUCE_FMAXIMUM, ISD::EXPERIMENTAL_VP_SPLAT};
721 static const unsigned IntegerVecReduceOps[] = {
726 static const unsigned FloatingPointVecReduceOps[] = {
730 static const unsigned FloatingPointLibCallOps[] = {
743 ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR,
744 ISD::VP_REDUCE_SMAX, ISD::VP_REDUCE_SMIN,
745 ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN},
749 for (
MVT VT : BoolVecVTs) {
779 {ISD::VP_REDUCE_AND, ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR}, VT,
803 ISD::VP_TRUNCATE, ISD::VP_SETCC},
819 for (
MVT VT : IntVecVTs) {
830 if (VT.getVectorElementType() == MVT::i64 && !Subtarget.hasStdExtV())
880 {ISD::VP_LOAD, ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
881 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER, ISD::VP_SCATTER},
905 if (Subtarget.hasStdExtZvkb()) {
913 if (Subtarget.hasStdExtZvbb()) {
917 ISD::VP_CTTZ_ZERO_UNDEF, ISD::VP_CTPOP},
923 ISD::VP_CTTZ_ZERO_UNDEF, ISD::VP_CTPOP},
932 ISD::VP_CTLZ_ZERO_UNDEF, ISD::VP_CTTZ_ZERO_UNDEF},
940 for (
MVT VT : VecTupleVTs) {
961 static const unsigned ZvfhminZvfbfminPromoteOps[] = {
971 static const unsigned ZvfhminZvfbfminPromoteVPOps[] = {
986 ISD::VP_FROUNDTOZERO,
992 ISD::VP_REDUCE_FMINIMUM,
993 ISD::VP_REDUCE_FMAXIMUM};
996 const auto SetCommonVFPActions = [&](
MVT VT) {
1031 {ISD::VP_LOAD, ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1032 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER, ISD::VP_SCATTER},
1065 const auto SetCommonVFPExtLoadTruncStoreActions =
1067 for (
auto SmallVT : SmallerVTs) {
1075 const auto SetCommonPromoteToF32Actions = [&](
MVT VT) {
1100 ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1101 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1124 for (
MVT VT : F16VecVTs) {
1127 SetCommonVFPActions(VT);
1130 for (
MVT VT : F16VecVTs) {
1133 SetCommonPromoteToF32Actions(VT);
1138 for (
MVT VT : BF16VecVTs) {
1141 SetCommonPromoteToF32Actions(VT);
1146 for (
MVT VT : F32VecVTs) {
1149 SetCommonVFPActions(VT);
1150 SetCommonVFPExtLoadTruncStoreActions(VT, F16VecVTs);
1151 SetCommonVFPExtLoadTruncStoreActions(VT, BF16VecVTs);
1156 for (
MVT VT : F64VecVTs) {
1159 SetCommonVFPActions(VT);
1160 SetCommonVFPExtLoadTruncStoreActions(VT, F16VecVTs);
1161 SetCommonVFPExtLoadTruncStoreActions(VT, BF16VecVTs);
1162 SetCommonVFPExtLoadTruncStoreActions(VT, F32VecVTs);
1168 if (!useRVVForFixedLengthVectorVT(VT))
1217 {ISD::VP_REDUCE_AND, ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR}, VT,
1244 ISD::VP_SETCC, ISD::VP_TRUNCATE},
1268 ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1269 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1306 if (Subtarget.hasStdExtZvkb())
1309 if (Subtarget.hasStdExtZvbb()) {
1333 if (!useRVVForFixedLengthVectorVT(VT))
1357 ISD::VP_SCATTER, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1358 ISD::EXPERIMENTAL_VP_STRIDED_STORE},
1374 if (Subtarget.hasStdExtZfhmin()) {
1398 if (Subtarget.hasStdExtZfbfmin()) {
1458 if (Subtarget.hasStdExtZfbfmin())
1467 if (Subtarget.hasStdExtA())
1470 if (Subtarget.hasForcedAtomics()) {
1480 if (Subtarget.hasVendorXTHeadMemIdx()) {
1496 if (Subtarget.hasVendorXCVmem() && !Subtarget.
is64Bit()) {
1522 if (Subtarget.hasStdExtZbb())
1525 if ((Subtarget.hasStdExtZbs() && Subtarget.
is64Bit()) ||
1529 if (Subtarget.hasStdExtZbkb())
1538 ISD::VP_GATHER, ISD::VP_SCATTER,
ISD::SRA,
1541 ISD::VP_STORE, ISD::VP_TRUNCATE, ISD::EXPERIMENTAL_VP_REVERSE,
1547 if (Subtarget.hasVendorXTHeadMemPair())
1590MVT RISCVTargetLowering::getVPExplicitVectorLengthTy()
const {
1595bool RISCVTargetLowering::shouldExpandGetVectorLength(
EVT TripCountVT,
1597 bool IsScalable)
const {
1604 if (TripCountVT != MVT::i32 && TripCountVT != Subtarget.
getXLenVT())
1629 unsigned Intrinsic)
const {
1630 auto &
DL =
I.getDataLayout();
1632 auto SetRVVLoadStoreInfo = [&](
unsigned PtrOp,
bool IsStore,
1633 bool IsUnitStrided,
bool UsePtrVal =
false) {
1638 Info.ptrVal =
I.getArgOperand(PtrOp);
1640 Info.fallbackAddressSpace =
1641 I.getArgOperand(PtrOp)->getType()->getPointerAddressSpace();
1645 MemTy =
I.getArgOperand(0)->getType();
1648 MemTy =
I.getType();
1658 if (cast<TargetExtType>(MemTy)->
getName() ==
"riscv.vector.tuple")
1661 1 << cast<ConstantInt>(
I.getArgOperand(
I.arg_size() - 1))
1663 Info.align =
DL.getABITypeAlign(MemTy);
1673 if (
I.hasMetadata(LLVMContext::MD_nontemporal))
1677 switch (Intrinsic) {
1680 case Intrinsic::riscv_masked_atomicrmw_xchg_i32:
1681 case Intrinsic::riscv_masked_atomicrmw_add_i32:
1682 case Intrinsic::riscv_masked_atomicrmw_sub_i32:
1683 case Intrinsic::riscv_masked_atomicrmw_nand_i32:
1684 case Intrinsic::riscv_masked_atomicrmw_max_i32:
1685 case Intrinsic::riscv_masked_atomicrmw_min_i32:
1686 case Intrinsic::riscv_masked_atomicrmw_umax_i32:
1687 case Intrinsic::riscv_masked_atomicrmw_umin_i32:
1688 case Intrinsic::riscv_masked_cmpxchg_i32:
1690 Info.memVT = MVT::i32;
1691 Info.ptrVal =
I.getArgOperand(0);
1697 case Intrinsic::riscv_seg2_load:
1698 case Intrinsic::riscv_seg3_load:
1699 case Intrinsic::riscv_seg4_load:
1700 case Intrinsic::riscv_seg5_load:
1701 case Intrinsic::riscv_seg6_load:
1702 case Intrinsic::riscv_seg7_load:
1703 case Intrinsic::riscv_seg8_load:
1704 return SetRVVLoadStoreInfo( 0,
false,
1706 case Intrinsic::riscv_seg2_store:
1707 case Intrinsic::riscv_seg3_store:
1708 case Intrinsic::riscv_seg4_store:
1709 case Intrinsic::riscv_seg5_store:
1710 case Intrinsic::riscv_seg6_store:
1711 case Intrinsic::riscv_seg7_store:
1712 case Intrinsic::riscv_seg8_store:
1714 return SetRVVLoadStoreInfo(
I.arg_size() - 2,
1717 case Intrinsic::riscv_vle:
1718 case Intrinsic::riscv_vle_mask:
1719 case Intrinsic::riscv_vleff:
1720 case Intrinsic::riscv_vleff_mask:
1721 return SetRVVLoadStoreInfo( 1,
1725 case Intrinsic::riscv_vse:
1726 case Intrinsic::riscv_vse_mask:
1727 return SetRVVLoadStoreInfo( 1,
1731 case Intrinsic::riscv_vlse:
1732 case Intrinsic::riscv_vlse_mask:
1733 case Intrinsic::riscv_vloxei:
1734 case Intrinsic::riscv_vloxei_mask:
1735 case Intrinsic::riscv_vluxei:
1736 case Intrinsic::riscv_vluxei_mask:
1737 return SetRVVLoadStoreInfo( 1,
1740 case Intrinsic::riscv_vsse:
1741 case Intrinsic::riscv_vsse_mask:
1742 case Intrinsic::riscv_vsoxei:
1743 case Intrinsic::riscv_vsoxei_mask:
1744 case Intrinsic::riscv_vsuxei:
1745 case Intrinsic::riscv_vsuxei_mask:
1746 return SetRVVLoadStoreInfo( 1,
1749 case Intrinsic::riscv_vlseg2:
1750 case Intrinsic::riscv_vlseg3:
1751 case Intrinsic::riscv_vlseg4:
1752 case Intrinsic::riscv_vlseg5:
1753 case Intrinsic::riscv_vlseg6:
1754 case Intrinsic::riscv_vlseg7:
1755 case Intrinsic::riscv_vlseg8:
1756 case Intrinsic::riscv_vlseg2ff:
1757 case Intrinsic::riscv_vlseg3ff:
1758 case Intrinsic::riscv_vlseg4ff:
1759 case Intrinsic::riscv_vlseg5ff:
1760 case Intrinsic::riscv_vlseg6ff:
1761 case Intrinsic::riscv_vlseg7ff:
1762 case Intrinsic::riscv_vlseg8ff:
1763 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1766 case Intrinsic::riscv_vlseg2_mask:
1767 case Intrinsic::riscv_vlseg3_mask:
1768 case Intrinsic::riscv_vlseg4_mask:
1769 case Intrinsic::riscv_vlseg5_mask:
1770 case Intrinsic::riscv_vlseg6_mask:
1771 case Intrinsic::riscv_vlseg7_mask:
1772 case Intrinsic::riscv_vlseg8_mask:
1773 case Intrinsic::riscv_vlseg2ff_mask:
1774 case Intrinsic::riscv_vlseg3ff_mask:
1775 case Intrinsic::riscv_vlseg4ff_mask:
1776 case Intrinsic::riscv_vlseg5ff_mask:
1777 case Intrinsic::riscv_vlseg6ff_mask:
1778 case Intrinsic::riscv_vlseg7ff_mask:
1779 case Intrinsic::riscv_vlseg8ff_mask:
1780 return SetRVVLoadStoreInfo(
I.arg_size() - 5,
1783 case Intrinsic::riscv_vlsseg2:
1784 case Intrinsic::riscv_vlsseg3:
1785 case Intrinsic::riscv_vlsseg4:
1786 case Intrinsic::riscv_vlsseg5:
1787 case Intrinsic::riscv_vlsseg6:
1788 case Intrinsic::riscv_vlsseg7:
1789 case Intrinsic::riscv_vlsseg8:
1790 case Intrinsic::riscv_vloxseg2:
1791 case Intrinsic::riscv_vloxseg3:
1792 case Intrinsic::riscv_vloxseg4:
1793 case Intrinsic::riscv_vloxseg5:
1794 case Intrinsic::riscv_vloxseg6:
1795 case Intrinsic::riscv_vloxseg7:
1796 case Intrinsic::riscv_vloxseg8:
1797 case Intrinsic::riscv_vluxseg2:
1798 case Intrinsic::riscv_vluxseg3:
1799 case Intrinsic::riscv_vluxseg4:
1800 case Intrinsic::riscv_vluxseg5:
1801 case Intrinsic::riscv_vluxseg6:
1802 case Intrinsic::riscv_vluxseg7:
1803 case Intrinsic::riscv_vluxseg8:
1804 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
1807 case Intrinsic::riscv_vlsseg2_mask:
1808 case Intrinsic::riscv_vlsseg3_mask:
1809 case Intrinsic::riscv_vlsseg4_mask:
1810 case Intrinsic::riscv_vlsseg5_mask:
1811 case Intrinsic::riscv_vlsseg6_mask:
1812 case Intrinsic::riscv_vlsseg7_mask:
1813 case Intrinsic::riscv_vlsseg8_mask:
1814 case Intrinsic::riscv_vloxseg2_mask:
1815 case Intrinsic::riscv_vloxseg3_mask:
1816 case Intrinsic::riscv_vloxseg4_mask:
1817 case Intrinsic::riscv_vloxseg5_mask:
1818 case Intrinsic::riscv_vloxseg6_mask:
1819 case Intrinsic::riscv_vloxseg7_mask:
1820 case Intrinsic::riscv_vloxseg8_mask:
1821 case Intrinsic::riscv_vluxseg2_mask:
1822 case Intrinsic::riscv_vluxseg3_mask:
1823 case Intrinsic::riscv_vluxseg4_mask:
1824 case Intrinsic::riscv_vluxseg5_mask:
1825 case Intrinsic::riscv_vluxseg6_mask:
1826 case Intrinsic::riscv_vluxseg7_mask:
1827 case Intrinsic::riscv_vluxseg8_mask:
1828 return SetRVVLoadStoreInfo(
I.arg_size() - 6,
1831 case Intrinsic::riscv_vsseg2:
1832 case Intrinsic::riscv_vsseg3:
1833 case Intrinsic::riscv_vsseg4:
1834 case Intrinsic::riscv_vsseg5:
1835 case Intrinsic::riscv_vsseg6:
1836 case Intrinsic::riscv_vsseg7:
1837 case Intrinsic::riscv_vsseg8:
1838 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1841 case Intrinsic::riscv_vsseg2_mask:
1842 case Intrinsic::riscv_vsseg3_mask:
1843 case Intrinsic::riscv_vsseg4_mask:
1844 case Intrinsic::riscv_vsseg5_mask:
1845 case Intrinsic::riscv_vsseg6_mask:
1846 case Intrinsic::riscv_vsseg7_mask:
1847 case Intrinsic::riscv_vsseg8_mask:
1848 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
1851 case Intrinsic::riscv_vssseg2:
1852 case Intrinsic::riscv_vssseg3:
1853 case Intrinsic::riscv_vssseg4:
1854 case Intrinsic::riscv_vssseg5:
1855 case Intrinsic::riscv_vssseg6:
1856 case Intrinsic::riscv_vssseg7:
1857 case Intrinsic::riscv_vssseg8:
1858 case Intrinsic::riscv_vsoxseg2:
1859 case Intrinsic::riscv_vsoxseg3:
1860 case Intrinsic::riscv_vsoxseg4:
1861 case Intrinsic::riscv_vsoxseg5:
1862 case Intrinsic::riscv_vsoxseg6:
1863 case Intrinsic::riscv_vsoxseg7:
1864 case Intrinsic::riscv_vsoxseg8:
1865 case Intrinsic::riscv_vsuxseg2:
1866 case Intrinsic::riscv_vsuxseg3:
1867 case Intrinsic::riscv_vsuxseg4:
1868 case Intrinsic::riscv_vsuxseg5:
1869 case Intrinsic::riscv_vsuxseg6:
1870 case Intrinsic::riscv_vsuxseg7:
1871 case Intrinsic::riscv_vsuxseg8:
1872 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
1875 case Intrinsic::riscv_vssseg2_mask:
1876 case Intrinsic::riscv_vssseg3_mask:
1877 case Intrinsic::riscv_vssseg4_mask:
1878 case Intrinsic::riscv_vssseg5_mask:
1879 case Intrinsic::riscv_vssseg6_mask:
1880 case Intrinsic::riscv_vssseg7_mask:
1881 case Intrinsic::riscv_vssseg8_mask:
1882 case Intrinsic::riscv_vsoxseg2_mask:
1883 case Intrinsic::riscv_vsoxseg3_mask:
1884 case Intrinsic::riscv_vsoxseg4_mask:
1885 case Intrinsic::riscv_vsoxseg5_mask:
1886 case Intrinsic::riscv_vsoxseg6_mask:
1887 case Intrinsic::riscv_vsoxseg7_mask:
1888 case Intrinsic::riscv_vsoxseg8_mask:
1889 case Intrinsic::riscv_vsuxseg2_mask:
1890 case Intrinsic::riscv_vsuxseg3_mask:
1891 case Intrinsic::riscv_vsuxseg4_mask:
1892 case Intrinsic::riscv_vsuxseg5_mask:
1893 case Intrinsic::riscv_vsuxseg6_mask:
1894 case Intrinsic::riscv_vsuxseg7_mask:
1895 case Intrinsic::riscv_vsuxseg8_mask:
1896 return SetRVVLoadStoreInfo(
I.arg_size() - 5,
1937 return isInt<12>(Imm);
1941 return isInt<12>(Imm);
1954 return (SrcBits == 64 && DestBits == 32);
1965 return (SrcBits == 64 && DestBits == 32);
1976 if (SrcBits == DestBits * 2) {
1987 if (
auto *LD = dyn_cast<LoadSDNode>(Val)) {
1988 EVT MemVT = LD->getMemoryVT();
1989 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
1999 return Subtarget.
is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
2007 return Subtarget.hasStdExtZbb() ||
2008 (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit());
2012 return Subtarget.hasStdExtZbb() || Subtarget.hasVendorXTHeadBb() ||
2013 (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit());
2024 if (!Subtarget.hasStdExtZbs() && !Subtarget.hasVendorXTHeadBs())
2029 return !Mask->getValue().isSignedIntN(12) && Mask->getValue().isPowerOf2();
2033 EVT VT =
Y.getValueType();
2039 return (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
2040 (!isa<ConstantSDNode>(
Y) || cast<ConstantSDNode>(
Y)->isOpaque());
2045 if (Subtarget.hasStdExtZbs())
2046 return X.getValueType().isScalarInteger();
2047 auto *
C = dyn_cast<ConstantSDNode>(
Y);
2049 if (Subtarget.hasVendorXTHeadBs())
2050 return C !=
nullptr;
2052 return C &&
C->getAPIntValue().ule(10);
2072 if (BitSize > Subtarget.
getXLen())
2076 int64_t Val = Imm.getSExtValue();
2084 if (!Subtarget.enableUnalignedScalarMem())
2100 unsigned OldShiftOpcode,
unsigned NewShiftOpcode,
2107 if (XC && OldShiftOpcode ==
ISD::SRL && XC->isOne())
2111 if (NewShiftOpcode ==
ISD::SRL &&
CC->isOne())
2155 if (!Subtarget.hasStdExtZfa())
2158 bool IsSupportedVT =
false;
2159 if (VT == MVT::f16) {
2160 IsSupportedVT = Subtarget.hasStdExtZfh() || Subtarget.hasStdExtZvfh();
2161 }
else if (VT == MVT::f32) {
2162 IsSupportedVT =
true;
2163 }
else if (VT == MVT::f64) {
2164 assert(Subtarget.hasStdExtD() &&
"Expect D extension");
2165 IsSupportedVT =
true;
2175 bool ForCodeSize)
const {
2176 bool IsLegalVT =
false;
2179 else if (VT == MVT::f32)
2181 else if (VT == MVT::f64)
2183 else if (VT == MVT::bf16)
2184 IsLegalVT = Subtarget.hasStdExtZfbfmin();
2196 return Imm.isZero();
2200 if (Imm.isNegZero())
2205 const int FmvCost = Subtarget.hasStdExtZfinx() ? 0 : 1;
2208 Subtarget.
getXLen(), Subtarget);
2214 unsigned Index)
const {
2227 if (EltVT == MVT::i1)
2240 if (Index + ResElts <= MinVLMAX && Index < 31)
2249 return (ResElts * 2) == SrcElts && (Index == 0 || Index == ResElts);
2268 std::optional<MVT> RegisterVT)
const {
2270 if (VT == (Subtarget.
is64Bit() ? MVT::i128 : MVT::i64) && RegisterVT &&
2271 *RegisterVT == MVT::Untyped)
2291 unsigned &NumIntermediates,
MVT &RegisterVT)
const {
2293 Context,
CC, VT, IntermediateVT, NumIntermediates, RegisterVT);
2308 isa<ConstantSDNode>(
LHS.getOperand(1))) {
2314 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
2327 if (
auto *RHSC = dyn_cast<ConstantSDNode>(
RHS)) {
2328 int64_t
C = RHSC->getSExtValue();
2366 if (VT.
SimpleTy >= MVT::riscv_nxv1i8x2 &&
2367 VT.
SimpleTy <= MVT::riscv_nxv1i8x8)
2369 if (VT.
SimpleTy >= MVT::riscv_nxv2i8x2 &&
2370 VT.
SimpleTy <= MVT::riscv_nxv2i8x8)
2372 if (VT.
SimpleTy >= MVT::riscv_nxv4i8x2 &&
2373 VT.
SimpleTy <= MVT::riscv_nxv4i8x8)
2375 if (VT.
SimpleTy >= MVT::riscv_nxv8i8x2 &&
2376 VT.
SimpleTy <= MVT::riscv_nxv8i8x8)
2378 if (VT.
SimpleTy >= MVT::riscv_nxv16i8x2 &&
2379 VT.
SimpleTy <= MVT::riscv_nxv16i8x4)
2381 if (VT.
SimpleTy == MVT::riscv_nxv32i8x2)
2391 switch (KnownSize) {
2419 return RISCV::VRRegClassID;
2421 return RISCV::VRM2RegClassID;
2423 return RISCV::VRM4RegClassID;
2425 return RISCV::VRM8RegClassID;
2435 static_assert(RISCV::sub_vrm1_7 == RISCV::sub_vrm1_0 + 7,
2436 "Unexpected subreg numbering");
2437 return RISCV::sub_vrm1_0 + Index;
2440 static_assert(RISCV::sub_vrm2_3 == RISCV::sub_vrm2_0 + 3,
2441 "Unexpected subreg numbering");
2442 return RISCV::sub_vrm2_0 + Index;
2445 static_assert(RISCV::sub_vrm4_1 == RISCV::sub_vrm4_0 + 1,
2446 "Unexpected subreg numbering");
2447 return RISCV::sub_vrm4_0 + Index;
2455 unsigned RegsPerField =
2458 switch (RegsPerField) {
2461 return RISCV::VRN2M1RegClassID;
2463 return RISCV::VRN3M1RegClassID;
2465 return RISCV::VRN4M1RegClassID;
2467 return RISCV::VRN5M1RegClassID;
2469 return RISCV::VRN6M1RegClassID;
2471 return RISCV::VRN7M1RegClassID;
2473 return RISCV::VRN8M1RegClassID;
2477 return RISCV::VRN2M2RegClassID;
2479 return RISCV::VRN3M2RegClassID;
2481 return RISCV::VRN4M2RegClassID;
2485 return RISCV::VRN2M4RegClassID;
2493 return RISCV::VRRegClassID;
2502std::pair<unsigned, unsigned>
2504 MVT VecVT,
MVT SubVecVT,
unsigned InsertExtractIdx,
2506 static_assert((RISCV::VRM8RegClassID > RISCV::VRM4RegClassID &&
2507 RISCV::VRM4RegClassID > RISCV::VRM2RegClassID &&
2508 RISCV::VRM2RegClassID > RISCV::VRRegClassID),
2509 "Register classes not ordered");
2516 if (VecRegClassID == SubRegClassID)
2517 return {RISCV::NoSubRegister, 0};
2520 "Only allow scalable vector subvector.");
2522 "Invalid vector tuple insert/extract for vector and subvector with "
2533 unsigned SubRegIdx = RISCV::NoSubRegister;
2534 for (
const unsigned RCID :
2535 {RISCV::VRM4RegClassID, RISCV::VRM2RegClassID, RISCV::VRRegClassID})
2536 if (VecRegClassID > RCID && SubRegClassID <= RCID) {
2540 SubRegIdx =
TRI->composeSubRegIndices(SubRegIdx,
2545 return {SubRegIdx, InsertExtractIdx};
2550bool RISCVTargetLowering::mergeStoresAfterLegalization(
EVT VT)
const {
2581unsigned RISCVTargetLowering::combineRepeatedFPDivisors()
const {
2588 "Unexpected opcode");
2590 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
2592 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
2595 return Op.getOperand(
II->VLOperand + 1 + HasChain);
2669bool RISCVTargetLowering::useRVVForFixedLengthVectorVT(
MVT VT)
const {
2670 return ::useRVVForFixedLengthVectorVT(VT, Subtarget);
2679 "Expected legal fixed length vector!");
2682 unsigned MaxELen = Subtarget.
getELen();
2716 return ::getContainerForFixedLengthVector(*
this, VT,
getSubtarget());
2723 "Expected to convert into a scalable vector!");
2724 assert(V.getValueType().isFixedLengthVector() &&
2725 "Expected a fixed length vector operand!");
2735 "Expected to convert into a fixed length vector!");
2736 assert(V.getValueType().isScalableVector() &&
2737 "Expected a scalable vector operand!");
2760static std::pair<SDValue, SDValue>
2769static std::pair<SDValue, SDValue>
2782static std::pair<SDValue, SDValue>
2799std::pair<unsigned, unsigned>
2815 return std::make_pair(MinVLMAX, MaxVLMAX);
2827 EVT VT,
unsigned DefinedValues)
const {
2841 std::tie(LMul, Fractional) =
2844 Cost = LMul <= DLenFactor ? (DLenFactor / LMul) : 1;
2846 Cost = (LMul * DLenFactor);
2889 Op.getValueType() == MVT::bf16) {
2890 bool IsStrict =
Op->isStrictFPOpcode();
2895 {Op.getOperand(0), Op.getOperand(1)});
2897 {
Op.getValueType(), MVT::Other},
2903 DAG.
getNode(
Op.getOpcode(),
DL, MVT::f32,
Op.getOperand(0)),
2918 MVT DstVT =
Op.getSimpleValueType();
2919 EVT SatVT = cast<VTSDNode>(
Op.getOperand(1))->getVT();
2927 Src.getValueType() == MVT::bf16) {
2934 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
2942 Opc,
DL, DstVT, Src,
2956 MVT SrcVT = Src.getSimpleValueType();
2962 if (SatVT != DstEltVT)
2965 MVT DstContainerVT = DstVT;
2966 MVT SrcContainerVT = SrcVT;
2972 "Expected same element count");
2981 {Src, Src, DAG.getCondCode(ISD::SETNE),
2982 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
2986 if (DstEltSize > (2 * SrcEltSize)) {
2992 MVT CvtContainerVT = DstContainerVT;
2993 MVT CvtEltVT = DstEltVT;
2994 if (SrcEltSize > (2 * DstEltSize)) {
3003 while (CvtContainerVT != DstContainerVT) {
3009 Res = DAG.
getNode(ClipOpc,
DL, CvtContainerVT, Res, Mask, VL);
3016 Res, DAG.
getUNDEF(DstContainerVT), VL);
3026 bool IsStrict =
Op->isStrictFPOpcode();
3027 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
3037 {
Op.getOperand(0), SrcVal});
3038 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
3039 {Ext.getValue(1), Ext.getValue(0)});
3053 case ISD::VP_FROUNDEVEN:
3057 case ISD::VP_FROUNDTOZERO:
3061 case ISD::VP_FFLOOR:
3069 case ISD::VP_FROUND:
3086 MVT VT =
Op.getSimpleValueType();
3093 MVT ContainerVT = VT;
3100 if (
Op->isVPOpcode()) {
3101 Mask =
Op.getOperand(1);
3105 VL =
Op.getOperand(2);
3127 DAG.
getUNDEF(ContainerVT), MaxValNode, VL);
3141 switch (
Op.getOpcode()) {
3149 case ISD::VP_FFLOOR:
3152 case ISD::VP_FROUND:
3153 case ISD::VP_FROUNDEVEN:
3154 case ISD::VP_FROUNDTOZERO: {
3166 case ISD::VP_FNEARBYINT:
3179 Src, Src, Mask, VL);
3194 MVT VT =
Op.getSimpleValueType();
3198 MVT ContainerVT = VT;
3210 MVT MaskVT = Mask.getSimpleValueType();
3213 {Chain, Src, Src, DAG.getCondCode(ISD::SETUNE),
3214 DAG.getUNDEF(MaskVT), Mask, VL});
3218 {Chain, Src, Src, Src, Unorder, VL});
3219 Chain = Src.getValue(1);
3235 DAG.
getUNDEF(ContainerVT), MaxValNode, VL);
3247 switch (
Op.getOpcode()) {
3258 {Chain, Src, Mask, DAG.getTargetConstant(FRM, DL, XLenVT), VL});
3264 DAG.
getVTList(IntVT, MVT::Other), Chain, Src, Mask, VL);
3268 DAG.
getVTList(ContainerVT, MVT::Other), Chain, Src,
3277 DAG.
getVTList(ContainerVT, MVT::Other), Chain,
3278 Truncated, Mask, VL);
3284 Src, Src, Mask, VL);
3294 MVT VT =
Op.getSimpleValueType();
3322 MVT VT =
Op.getSimpleValueType();
3327 MVT ContainerVT = VT;
3372 "Unexpected vector MVT");
3400 return std::nullopt;
3418 unsigned EltSizeInBits) {
3421 return std::nullopt;
3422 bool IsInteger =
Op.getValueType().isInteger();
3424 std::optional<unsigned> SeqStepDenom;
3425 std::optional<APInt> SeqStepNum;
3426 std::optional<APInt> SeqAddend;
3427 std::optional<std::pair<APInt, unsigned>> PrevElt;
3428 assert(EltSizeInBits >=
Op.getValueType().getScalarSizeInBits());
3433 const unsigned OpSize =
Op.getScalarValueSizeInBits();
3435 if (Elt.isUndef()) {
3436 Elts[
Idx] = std::nullopt;
3440 Elts[
Idx] = Elt->getAsAPIntVal().trunc(OpSize).zext(EltSizeInBits);
3445 return std::nullopt;
3446 Elts[
Idx] = *ExactInteger;
3459 unsigned IdxDiff =
Idx - PrevElt->second;
3460 APInt ValDiff = *Elt - PrevElt->first;
3468 int64_t Remainder = ValDiff.
srem(IdxDiff);
3473 return std::nullopt;
3474 ValDiff = ValDiff.
sdiv(IdxDiff);
3479 SeqStepNum = ValDiff;
3480 else if (ValDiff != SeqStepNum)
3481 return std::nullopt;
3484 SeqStepDenom = IdxDiff;
3485 else if (IdxDiff != *SeqStepDenom)
3486 return std::nullopt;
3490 if (!PrevElt || PrevElt->first != *Elt)
3491 PrevElt = std::make_pair(*Elt,
Idx);
3495 if (!SeqStepNum || !SeqStepDenom)
3496 return std::nullopt;
3504 (
APInt(EltSizeInBits,
Idx,
false,
true) *
3506 .sdiv(*SeqStepDenom);
3508 APInt Addend = *Elt - ExpectedVal;
3511 else if (Addend != SeqAddend)
3512 return std::nullopt;
3515 assert(SeqAddend &&
"Must have an addend if we have a step");
3517 return VIDSequence{SeqStepNum->getSExtValue(), *SeqStepDenom,
3518 SeqAddend->getSExtValue()};
3533 MVT SrcVT = Src.getSimpleValueType();
3543 auto *CIdx = dyn_cast<ConstantSDNode>(
Idx);
3549 MVT ContainerVT = VT;
3553 MVT SrcContainerVT = SrcVT;
3588 MVT VT =
Op.getSimpleValueType();
3600 unsigned MostCommonCount = 0;
3602 unsigned NumUndefElts =
3610 unsigned NumScalarLoads = 0;
3616 unsigned &Count = ValueCounts[V];
3618 if (
auto *CFP = dyn_cast<ConstantFPSDNode>(V))
3619 NumScalarLoads += !CFP->isExactlyValue(+0.0);
3624 if (++Count >= MostCommonCount) {
3626 MostCommonCount = Count;
3630 assert(DominantValue &&
"Not expecting an all-undef BUILD_VECTOR");
3631 unsigned NumDefElts = NumElts - NumUndefElts;
3632 unsigned DominantValueCountThreshold = NumDefElts <= 2 ? 0 : NumDefElts - 2;
3638 ((MostCommonCount > DominantValueCountThreshold) ||
3651 !LastOp.isUndef() && ValueCounts[LastOp] == 1 &&
3652 LastOp != DominantValue) {
3661 Processed.insert(LastOp);
3666 const SDValue &V = OpIdx.value();
3667 if (V.isUndef() || !Processed.insert(V).second)
3669 if (ValueCounts[V] == 1) {
3678 return DAG.getConstant(V == V1, DL, XLenVT);
3694 MVT VT =
Op.getSimpleValueType();
3724 unsigned NumViaIntegerBits = std::clamp(NumElts, 8u, Subtarget.
getXLen());
3725 NumViaIntegerBits = std::min(NumViaIntegerBits, Subtarget.
getELen());
3733 unsigned IntegerViaVecElts =
divideCeil(NumElts, NumViaIntegerBits);
3734 MVT IntegerViaVecVT =
3739 unsigned BitPos = 0, IntegerEltIdx = 0;
3742 for (
unsigned I = 0;
I < NumElts;) {
3744 bool BitValue = !V.isUndef() && V->getAsZExtVal();
3745 Bits |= ((
uint64_t)BitValue << BitPos);
3751 if (
I % NumViaIntegerBits == 0 ||
I == NumElts) {
3752 if (NumViaIntegerBits <= 32)
3753 Bits = SignExtend64<32>(Bits);
3755 Elts[IntegerEltIdx] = Elt;
3764 if (NumElts < NumViaIntegerBits) {
3768 assert(IntegerViaVecVT == MVT::v1i8 &&
"Unexpected mask vector type");
3796 int64_t StepNumerator = SimpleVID->StepNumerator;
3797 unsigned StepDenominator = SimpleVID->StepDenominator;
3798 int64_t Addend = SimpleVID->Addend;
3800 assert(StepNumerator != 0 &&
"Invalid step");
3801 bool Negate =
false;
3802 int64_t SplatStepVal = StepNumerator;
3806 if (StepNumerator != 1 && StepNumerator !=
INT64_MIN &&
3808 Negate = StepNumerator < 0;
3810 SplatStepVal =
Log2_64(std::abs(StepNumerator));
3817 if (((StepOpcode ==
ISD::MUL && isInt<12>(SplatStepVal)) ||
3818 (StepOpcode ==
ISD::SHL && isUInt<5>(SplatStepVal))) &&
3820 (SplatStepVal >= 0 || StepDenominator == 1) && isInt<5>(Addend)) {
3823 MVT VIDContainerVT =
3831 if ((StepOpcode ==
ISD::MUL && SplatStepVal != 1) ||
3832 (StepOpcode ==
ISD::SHL && SplatStepVal != 0)) {
3834 VID = DAG.
getNode(StepOpcode,
DL, VIDVT, VID, SplatStep);
3836 if (StepDenominator != 1) {
3841 if (Addend != 0 || Negate) {
3860 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32) &&
3861 "Unexpected sequence type");
3865 unsigned ViaVecLen =
3869 uint64_t EltMask = maskTrailingOnes<uint64_t>(EltBitSize);
3872 for (
const auto &OpIdx :
enumerate(
Op->op_values())) {
3873 const auto &SeqV = OpIdx.value();
3874 if (!SeqV.isUndef())
3876 ((SeqV->getAsZExtVal() & EltMask) << (OpIdx.index() * EltBitSize));
3882 if (ViaIntVT == MVT::i32)
3883 SplatValue = SignExtend64<32>(SplatValue);
3905 const auto *BV = cast<BuildVectorSDNode>(
Op);
3908 BV->getRepeatedSequence(Sequence) &&
3909 (Sequence.size() * EltBitSize) <= Subtarget.
getELen()) {
3910 unsigned SeqLen = Sequence.size();
3912 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32 ||
3913 ViaIntVT == MVT::i64) &&
3914 "Unexpected sequence type");
3919 const unsigned RequiredVL = NumElts / SeqLen;
3920 const unsigned ViaVecLen =
3922 NumElts : RequiredVL;
3925 unsigned EltIdx = 0;
3926 uint64_t EltMask = maskTrailingOnes<uint64_t>(EltBitSize);
3930 for (
const auto &SeqV : Sequence) {
3931 if (!SeqV.isUndef())
3933 ((SeqV->getAsZExtVal() & EltMask) << (EltIdx * EltBitSize));
3940 if (ViaIntVT == MVT::i32)
3941 SplatValue = SignExtend64<32>(SplatValue);
3947 (!Subtarget.
is64Bit() && ViaIntVT == MVT::i64)) &&
3948 "Unexpected bitcast sequence");
3949 if (ViaIntVT.
bitsLE(XLenVT) || isInt<32>(SplatValue)) {
3952 MVT ViaContainerVT =
3959 if (ViaVecLen != RequiredVL)
3979 Source, DAG, Subtarget);
3999 return RISCV::PACKH;
4001 return Subtarget.
is64Bit() ? RISCV::PACKW : RISCV::PACK;
4016 MVT VT =
Op.getSimpleValueType();
4024 if (!Subtarget.hasStdExtZbb() || !Subtarget.hasStdExtZba())
4029 if (ElemSizeInBits >= std::min(Subtarget.
getELen(), Subtarget.
getXLen()) ||
4043 if (Subtarget.hasStdExtZbkb())
4048 ElemDL, XLenVT,
A,
B),
4060 NewOperands.
reserve(NumElts / 2);
4062 NewOperands.
push_back(pack(
Op.getOperand(i),
Op.getOperand(i + 1)));
4072 MVT VT =
Op.getSimpleValueType();
4083 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) || EltVT == MVT::bf16) {
4088 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4089 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin())) {
4092 if (
auto *
C = dyn_cast<ConstantFPSDNode>(Elem)) {
4176 auto OneVRegOfOps =
ArrayRef(BuildVectorOps).
slice(i, ElemsPerVReg);
4180 unsigned InsertIdx = (i / ElemsPerVReg) * NumOpElts;
4203 unsigned NumUndefElts =
4205 unsigned NumDefElts = NumElts - NumUndefElts;
4206 if (NumDefElts >= 8 && NumDefElts > NumElts / 2 &&
4213 for (
unsigned i = 0; i < NumElts; i++) {
4215 if (i < NumElts / 2) {
4222 bool SelectMaskVal = (i < NumElts / 2);
4225 assert(SubVecAOps.
size() == NumElts && SubVecBOps.
size() == NumElts &&
4226 MaskVals.
size() == NumElts);
4261 unsigned UndefCount = 0;
4268 LinearBudget -= PerSlideCost;
4271 LinearBudget -= PerSlideCost;
4274 LinearBudget -= PerSlideCost;
4277 if (LinearBudget < 0)
4282 "Illegal type which will result in reserved encoding");
4307 Vec,
Offset, Mask, VL, Policy);
4320 Vec,
Offset, Mask, VL, Policy);
4330 if (isa<ConstantSDNode>(
Lo) && isa<ConstantSDNode>(
Hi)) {
4331 int32_t LoC = cast<ConstantSDNode>(
Lo)->getSExtValue();
4332 int32_t HiC = cast<ConstantSDNode>(
Hi)->getSExtValue();
4335 if ((LoC >> 31) == HiC)
4346 (isa<RegisterSDNode>(VL) &&
4347 cast<RegisterSDNode>(VL)->
getReg() == RISCV::X0))
4349 else if (isa<ConstantSDNode>(VL) && isUInt<4>(VL->
getAsZExtVal()))
4364 isa<ConstantSDNode>(
Hi.getOperand(1)) &&
4365 Hi.getConstantOperandVal(1) == 31)
4384 assert(Scalar.getValueType() == MVT::i64 &&
"Unexpected VT!");
4396 bool HasPassthru = Passthru && !Passthru.
isUndef();
4397 if (!HasPassthru && !Passthru)
4404 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
4405 EltVT == MVT::bf16) {
4406 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4407 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
4421 if (Scalar.getValueType().bitsLE(XLenVT)) {
4428 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4432 assert(XLenVT == MVT::i32 && Scalar.getValueType() == MVT::i64 &&
4433 "Unexpected scalar for splat lowering!");
4457 SDValue ExtractedVal = Scalar.getOperand(0);
4462 MVT ExtractedContainerVT = ExtractedVT;
4465 DAG, ExtractedContainerVT, Subtarget);
4467 ExtractedVal, DAG, Subtarget);
4469 if (ExtractedContainerVT.
bitsLE(VT))
4484 if (!Scalar.getValueType().bitsLE(XLenVT))
4487 VT,
DL, DAG, Subtarget);
4495 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4515 if (Src != V2.getOperand(0))
4520 if (!Src.getValueType().isFixedLengthVector() ||
4521 Src.getValueType().getVectorNumElements() != (NumElts * 2))
4526 V2.getConstantOperandVal(1) != NumElts)
4544 int Size = Mask.size();
4546 assert(
Size == (
int)NumElts &&
"Unexpected mask size");
4552 EvenSrc = StartIndexes[0];
4553 OddSrc = StartIndexes[1];
4556 if (EvenSrc != 0 && OddSrc != 0)
4566 int HalfNumElts = NumElts / 2;
4567 return ((EvenSrc % HalfNumElts) == 0) && ((OddSrc % HalfNumElts) == 0);
4583 int Size = Mask.size();
4595 for (
int i = 0; i !=
Size; ++i) {
4601 int StartIdx = i - (M %
Size);
4609 int CandidateRotation = StartIdx < 0 ? -StartIdx :
Size - StartIdx;
4612 Rotation = CandidateRotation;
4613 else if (Rotation != CandidateRotation)
4618 int MaskSrc = M <
Size ? 0 : 1;
4623 int &TargetSrc = StartIdx < 0 ? HiSrc : LoSrc;
4628 TargetSrc = MaskSrc;
4629 else if (TargetSrc != MaskSrc)
4636 assert(Rotation != 0 &&
"Failed to locate a viable rotation!");
4637 assert((LoSrc >= 0 || HiSrc >= 0) &&
4638 "Failed to find a rotated input vector!");
4652 ElementCount SrcEC = Src.getValueType().getVectorElementCount();
4659 unsigned Shift = Index * EltBits;
4686 auto findNonEXTRACT_SUBVECTORParent =
4687 [](
SDValue Parent) -> std::pair<SDValue, uint64_t> {
4692 Parent.getOperand(0).getSimpleValueType().isFixedLengthVector()) {
4693 Offset += Parent.getConstantOperandVal(1);
4694 Parent = Parent.getOperand(0);
4696 return std::make_pair(Parent,
Offset);
4699 auto [V1Src, V1IndexOffset] = findNonEXTRACT_SUBVECTORParent(V1);
4700 auto [V2Src, V2IndexOffset] = findNonEXTRACT_SUBVECTORParent(V2);
4709 for (
size_t i = 0; i != NewMask.
size(); ++i) {
4710 if (NewMask[i] == -1)
4713 if (
static_cast<size_t>(NewMask[i]) < NewMask.
size()) {
4714 NewMask[i] = NewMask[i] + V1IndexOffset;
4718 NewMask[i] = NewMask[i] - NewMask.
size() + V2IndexOffset;
4724 if (NewMask[0] <= 0)
4728 for (
unsigned i = 1; i != NewMask.
size(); ++i)
4729 if (NewMask[i - 1] + 1 != NewMask[i])
4733 MVT SrcVT = Src.getSimpleValueType();
4764 int NumSubElts, Index;
4769 bool OpsSwapped = Mask[Index] < (int)NumElts;
4770 SDValue InPlace = OpsSwapped ? V2 : V1;
4771 SDValue ToInsert = OpsSwapped ? V1 : V2;
4781 if (NumSubElts + Index >= (
int)NumElts)
4795 Res =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, InPlace, ToInsert,
4807 bool OpsSwapped =
false;
4808 if (!isa<BuildVectorSDNode>(V1)) {
4809 if (!isa<BuildVectorSDNode>(V2))
4814 SDValue Splat = cast<BuildVectorSDNode>(V1)->getSplatValue();
4822 const unsigned E = Mask.size() - ((
Offset > 0) ?
Offset : 0);
4823 for (
unsigned i = S; i != E; ++i)
4824 if (Mask[i] >= 0 && (
unsigned)Mask[i] !=
Base + i +
Offset)
4830 bool IsVSlidedown = isSlideMask(Mask, OpsSwapped ? 0 : NumElts, 1);
4831 if (!IsVSlidedown && !isSlideMask(Mask, OpsSwapped ? 0 : NumElts, -1))
4834 const int InsertIdx = Mask[IsVSlidedown ? (NumElts - 1) : 0];
4836 if (InsertIdx < 0 || InsertIdx / NumElts != (
unsigned)OpsSwapped)
4859 auto OpCode = IsVSlidedown ?
4864 auto Vec = DAG.
getNode(OpCode,
DL, ContainerVT,
4867 Splat, TrueMask, VL);
4878 for (
unsigned i = 0; i < Mask.size(); i++)
4879 LaneIsUndef[i % Factor] &= (Mask[i] == -1);
4882 for (
unsigned i = 0; i < Factor; i++) {
4893 for (
unsigned i = 0; i < Mask.size() / Factor; i++) {
4894 unsigned j = i * Factor + Index;
4895 if (Mask[j] != -1 && (
unsigned)Mask[j] != i)
4908 MVT VT = V.getSimpleValueType();
4923 EC.multiplyCoefficientBy(Factor));
4942 MVT VecContainerVT = VecVT;
4959 MVT WideContainerVT = WideVT;
4965 EvenV = DAG.
getBitcast(VecContainerVT, EvenV);
4972 if (Subtarget.hasStdExtZvbb()) {
4977 OffsetVec, Passthru, Mask, VL);
4979 Interleaved, EvenV, Passthru, Mask, VL);
4987 OddV, Passthru, Mask, VL);
4993 OddV, AllOnesVec, Passthru, Mask, VL);
5001 Interleaved, OddsMul, Passthru, Mask, VL);
5008 Interleaved = DAG.
getBitcast(ResultContainerVT, Interleaved);
5054 if (ViaEltSize > NumElts)
5063 if (ViaEltSize > NumElts)
5069 if (ViaEltSize > NumElts)
5078 MVT &RotateVT,
unsigned &RotateAmt) {
5084 unsigned NumSubElts;
5086 NumElts, NumSubElts, RotateAmt))
5089 NumElts / NumSubElts);
5157 unsigned NumOfSrcRegs = NumElts / NumOpElts;
5158 unsigned NumOfDestRegs = NumElts / NumOpElts;
5167 Mask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs,
5168 [&]() {
Operands.emplace_back(); },
5169 [&](
ArrayRef<int> SrcSubMask,
unsigned SrcVecIdx,
unsigned DstVecIdx) {
5170 Operands.emplace_back().emplace_back(
5171 SrcVecIdx, UINT_MAX,
5174 [&](
ArrayRef<int> SrcSubMask,
unsigned Idx1,
unsigned Idx2,
bool NewReg) {
5180 assert(
Operands.size() == NumOfDestRegs &&
"Whole vector must be processed");
5185 unsigned NumShuffles = std::accumulate(
5192 for (const auto &P : Data) {
5193 unsigned Idx2 = std::get<1>(P);
5194 ArrayRef<int> Mask = std::get<2>(P);
5195 if (Idx2 != UINT_MAX)
5197 else if (ShuffleVectorInst::isIdentityMask(Mask, Mask.size()))
5202 if ((NumOfDestRegs > 2 && NumShuffles > NumOfDestRegs) ||
5203 (NumOfDestRegs <= 2 && NumShuffles >= 4))
5205 auto ExtractValue = [&, &DAG = DAG](
SDValue SrcVec,
unsigned ExtractIdx) {
5207 DAG.getVectorIdxConstant(ExtractIdx,
DL));
5211 auto PerformShuffle = [&, &DAG = DAG](
SDValue SubVec1,
SDValue SubVec2,
5213 SDValue SubVec = DAG.getVectorShuffle(OneRegVT,
DL, SubVec1, SubVec2, Mask);
5216 SDValue Vec = DAG.getUNDEF(ContainerVT);
5221 for (
unsigned I : seq<unsigned>(
Data.size())) {
5222 const auto &[Idx1, Idx2,
_] =
Data[
I];
5230 V = ExtractValue(Idx1 >= NumOfSrcRegs ? V2 : V1,
5231 (Idx1 % NumOfSrcRegs) * NumOpElts);
5232 if (Idx2 != UINT_MAX) {
5235 V = ExtractValue(Idx2 >= NumOfSrcRegs ? V2 : V1,
5236 (Idx2 % NumOfSrcRegs) * NumOpElts);
5240 for (
const auto &[Idx1, Idx2, Mask] :
Data) {
5242 SDValue V2 = Idx2 == UINT_MAX ? V1 : Values.
at(Idx2);
5243 V = PerformShuffle(V1, V2, Mask);
5247 unsigned InsertIdx =
I * NumOpElts;
5250 DAG.getVectorIdxConstant(InsertIdx,
DL));
5260 bool SawUndef =
false;
5261 for (
unsigned i = 0; i < Mask.size(); i++) {
5262 if (Mask[i] == -1) {
5268 if (i > (
unsigned)Mask[i])
5270 if (Mask[i] <=
Last)
5301 for (
int Idx : Mask) {
5304 unsigned SrcIdx =
Idx % Mask.size();
5306 if (Srcs[SrcIdx] == -1)
5309 else if (Srcs[SrcIdx] != Src)
5315 for (
int Lane : Srcs) {
5328 for (
unsigned I = 0;
I < Mask.size();
I++) {
5332 NewMask[
I] = Mask[
I] % Mask.size();
5345 if ((M / Span) != (
int)(
I / Span))
5347 int SpanIdx =
I % Span;
5349 if (LowSpan[SpanIdx] == -1)
5360 [&](
const auto &
Idx) {
return Idx == -1 ||
Idx < Span; });
5371 MVT VT =
Op.getSimpleValueType();
5379 if (ElementSize > 32)
5402 MVT VT =
Op.getSimpleValueType();
5417 V2 = V2.isUndef() ? DAG.
getUNDEF(WidenVT)
5441 V.getOperand(0).getSimpleValueType().getVectorNumElements();
5442 V = V.getOperand(
Offset / OpElements);
5448 auto *Ld = cast<LoadSDNode>(V);
5458 SDValue Ops[] = {Ld->getChain(),
5472 MVT SplatVT = ContainerVT;
5475 if (SVT == MVT::bf16 ||
5476 (SVT == MVT::f16 && !Subtarget.hasStdExtZfh())) {
5485 V = DAG.
getLoad(SVT,
DL, Ld->getChain(), NewAddr,
5486 Ld->getPointerInfo().getWithOffset(
Offset),
5487 Ld->getOriginalAlign(),
5491 Ld->getPointerInfo().getWithOffset(
Offset), SVT,
5492 Ld->getOriginalAlign(),
5493 Ld->getMemOperand()->getFlags());
5505 assert(Lane < (
int)NumElts &&
"Unexpected lane!");
5508 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
5530 if (Subtarget.hasStdExtZvkb())
5541 LoV = LoSrc == 0 ? V1 : V2;
5545 HiV = HiSrc == 0 ? V1 : V2;
5551 unsigned InvRotate = NumElts - Rotation;
5561 Res =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, Res, LoV,
5579 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
5580 for (
unsigned Factor = 2; Factor <= MaxFactor; Factor <<= 1) {
5596 int EvenSrc, OddSrc;
5604 bool LaneIsUndef[2] = {
true,
true};
5605 for (
unsigned i = 0; i < Mask.size(); i++)
5606 LaneIsUndef[i % 2] &= (Mask[i] == -1);
5608 int Size = Mask.size();
5610 if (LaneIsUndef[0]) {
5613 assert(EvenSrc >= 0 &&
"Undef source?");
5614 EvenV = (EvenSrc /
Size) == 0 ? V1 : V2;
5619 if (LaneIsUndef[1]) {
5622 assert(OddSrc >= 0 &&
"Undef source?");
5623 OddV = (OddSrc /
Size) == 0 ? V1 : V2;
5633 assert(!V1.
isUndef() &&
"Unexpected shuffle canonicalization");
5645 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
5646 for (
unsigned Factor = 4; Factor <= MaxFactor; Factor <<= 1) {
5662 if (NumElts > MinVLMAX) {
5663 unsigned MaxIdx = 0;
5667 MaxIdx = std::max(std::max((
unsigned)
I, (
unsigned)M), MaxIdx);
5669 unsigned NewNumElts =
5671 if (NewNumElts != NumElts) {
5676 Mask.take_front(NewNumElts));
5694 for (
auto Idx : Mask) {
5707 any_of(Mask, [&](
const auto &
Idx) {
return Idx > 255; })) {
5736 MVT IndexContainerVT =
5741 for (
int MaskIndex : Mask) {
5742 bool IsLHSIndex = MaskIndex < (int)NumElts && MaskIndex >= 0;
5761 auto [InnerTrueMask, InnerVL] =
5766 Gather = DAG.
getUNDEF(ContainerVT);
5767 for (
int i = 0; i <
N; i++) {
5773 DAG.
getNode(GatherVVOpc,
DL, M1VT, SubV1, SubIndex,
5774 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
5786 auto [InnerTrueMask, InnerVL] =
5791 Gather = DAG.
getUNDEF(ContainerVT);
5797 for (
int i = 0; i <
N; i++) {
5800 DAG.
getUNDEF(IndexContainerVT), LHSIndices,
5801 SlideAmt, TrueMask, VL);
5806 DAG.
getNode(GatherVVOpc,
DL, M1VT, SubV1, SubIndex,
5807 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
5814 Gather = DAG.
getNode(GatherVVOpc,
DL, ContainerVT, V1, LHSIndices,
5815 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
5826 for (
int MaskIndex : Mask) {
5827 bool IsLHSOrUndefIndex = MaskIndex < (int)NumElts;
5828 ShuffleMaskLHS.
push_back(IsLHSOrUndefIndex && MaskIndex >= 0
5830 ShuffleMaskRHS.
push_back(IsLHSOrUndefIndex ? -1 : (MaskIndex - NumElts));
5861 for (
int MaskIndex : Mask) {
5862 bool SelectMaskVal = (MaskIndex < (int)NumElts) ^ !SwapOps;
5866 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
5884 const unsigned NumElts = M.size();
5900RISCVTargetLowering::lowerCTLZ_CTTZ_ZERO_UNDEF(
SDValue Op,
5902 MVT VT =
Op.getSimpleValueType();
5906 MVT ContainerVT = VT;
5909 if (
Op->isVPOpcode()) {
5910 Mask =
Op.getOperand(1);
5914 VL =
Op.getOperand(2);
5920 MVT FloatEltVT = (EltSize >= 32) ? MVT::f64 : MVT::f32;
5922 FloatEltVT = MVT::f32;
5929 "Expected legal float type!");
5936 }
else if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF) {
5939 Src = DAG.
getNode(ISD::VP_AND,
DL, VT, Src, Neg, Mask, VL);
5944 if (FloatVT.
bitsGT(VT)) {
5945 if (
Op->isVPOpcode())
5946 FloatVal = DAG.
getNode(ISD::VP_UINT_TO_FP,
DL, FloatVT, Src, Mask, VL);
5955 if (!
Op->isVPOpcode())
5959 MVT ContainerFloatVT =
5962 Src, Mask, RTZRM, VL);
5969 unsigned ShiftAmt = FloatEltVT == MVT::f64 ? 52 : 23;
5973 if (
Op->isVPOpcode()) {
5982 else if (IntVT.
bitsGT(VT))
5987 unsigned ExponentBias = FloatEltVT == MVT::f64 ? 1023 : 127;
5992 if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF)
5993 return DAG.
getNode(ISD::VP_SUB,
DL, VT, Exp,
5998 unsigned Adjust = ExponentBias + (EltSize - 1);
6000 if (
Op->isVPOpcode())
6010 else if (
Op.getOpcode() == ISD::VP_CTLZ)
6011 Res = DAG.
getNode(ISD::VP_UMIN,
DL, VT, Res,
6021 MVT SrcVT =
Source.getSimpleValueType();
6030 SrcVT = ContainerVT;
6043 if (
Op->getOpcode() == ISD::VP_CTTZ_ELTS_ZERO_UNDEF)
6060 auto *
Load = cast<LoadSDNode>(
Op);
6061 assert(Load &&
Load->getMemoryVT().isVector() &&
"Expected vector load");
6064 Load->getMemoryVT(),
6065 *
Load->getMemOperand()))
6069 MVT VT =
Op.getSimpleValueType();
6071 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
6072 "Unexpected unaligned RVV load type");
6076 "Expecting equally-sized RVV vector types to be legal");
6078 Load->getPointerInfo(),
Load->getOriginalAlign(),
6079 Load->getMemOperand()->getFlags());
6089 auto *
Store = cast<StoreSDNode>(
Op);
6090 assert(Store &&
Store->getValue().getValueType().isVector() &&
6091 "Expected vector store");
6094 Store->getMemoryVT(),
6095 *
Store->getMemOperand()))
6102 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
6103 "Unexpected unaligned RVV store type");
6107 "Expecting equally-sized RVV vector types to be legal");
6108 StoredVal = DAG.
getBitcast(NewVT, StoredVal);
6110 Store->getPointerInfo(),
Store->getOriginalAlign(),
6111 Store->getMemOperand()->getFlags());
6116 assert(
Op.getValueType() == MVT::i64 &&
"Unexpected VT");
6118 int64_t Imm = cast<ConstantSDNode>(
Op)->getSExtValue();
6145 unsigned ShiftAmt, AddOpc;
6156 MVT VT =
Op.getSimpleValueType();
6157 const APFloat &
Imm = cast<ConstantFPSDNode>(
Op)->getValueAPF();
6160 bool Negate =
false;
6164 if (Index < 0 &&
Imm.isNegative()) {
6192 if (Subtarget.hasStdExtZtso()) {
6216 MVT VT =
Op.getSimpleValueType();
6218 unsigned Check =
Op.getConstantOperandVal(1);
6219 unsigned TDCMask = 0;
6247 MVT VT0 =
Op.getOperand(0).getSimpleValueType();
6252 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6254 VL =
Op.getOperand(3);
6257 VL,
Op->getFlags());
6272 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6274 MVT MaskContainerVT =
6277 VL =
Op.getOperand(3);
6282 Mask, VL,
Op->getFlags());
6285 DAG.
getUNDEF(ContainerDstVT), TDCMaskV, VL);
6290 DAG.
getUNDEF(ContainerVT), Mask, VL});
6294 TDCMaskV, DAG.
getUNDEF(ContainerDstVT), Mask, VL);
6298 DAG.
getUNDEF(ContainerDstVT), SplatZero, VL);
6302 DAG.
getUNDEF(ContainerVT), Mask, VL});
6318 MVT VT =
Op.getSimpleValueType();
6345 return DAG.
getNode(Opc,
DL, VT, NewX, NewY);
6352 MVT ContainerVT = VT;
6360 if (
Op->isVPOpcode()) {
6361 Mask =
Op.getOperand(2);
6365 VL =
Op.getOperand(3);
6373 {X, X, DAG.getCondCode(ISD::SETOEQ),
6374 DAG.getUNDEF(ContainerVT), Mask, VL});
6382 {Y, Y, DAG.getCondCode(ISD::SETOEQ),
6383 DAG.getUNDEF(ContainerVT), Mask, VL});
6393 DAG.
getUNDEF(ContainerVT), Mask, VL);
6403 "Wrong opcode for lowering FABS or FNEG.");
6406 MVT VT =
Op.getSimpleValueType();
6407 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
6414 Mask = Mask.sext(Subtarget.
getXLen());
6427 MVT VT =
Op.getSimpleValueType();
6428 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
6438 if (SignSize == Subtarget.
getXLen()) {
6440 }
else if (SignSize == 16) {
6442 }
else if (SignSize == 32) {
6444 }
else if (SignSize == 64) {
6445 assert(XLenVT == MVT::i32 &&
"Unexpected type");
6455 if (ShiftAmount > 0) {
6458 }
else if (ShiftAmount < 0) {
6484#define OP_CASE(NODE) \
6486 return RISCVISD::NODE##_VL;
6487#define VP_CASE(NODE) \
6488 case ISD::VP_##NODE: \
6489 return RISCVISD::NODE##_VL;
6491 switch (
Op.getOpcode()) {
6569 case ISD::VP_CTLZ_ZERO_UNDEF:
6572 case ISD::VP_CTTZ_ZERO_UNDEF:
6581 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
6586 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
6591 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
6594 case ISD::VP_SELECT:
6603 case ISD::VP_SIGN_EXTEND:
6605 case ISD::VP_ZERO_EXTEND:
6607 case ISD::VP_FP_TO_SINT:
6609 case ISD::VP_FP_TO_UINT:
6612 case ISD::VP_FMINNUM:
6615 case ISD::VP_FMAXNUM:
6620 case ISD::VP_LLRINT:
6632 "not a RISC-V target specific op");
6636 "adding target specific op should update this function");
6656 "not a RISC-V target specific op");
6660 "adding target specific op should update this function");
6673 if (
Op.getValueType() == MVT::nxv32f16 &&
6677 if (
Op.getValueType() == MVT::nxv32bf16)
6690 if (!
Op.getOperand(j).getValueType().isVector()) {
6691 LoOperands[j] =
Op.getOperand(j);
6692 HiOperands[j] =
Op.getOperand(j);
6695 std::tie(LoOperands[j], HiOperands[j]) =
6700 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
6702 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
6717 std::tie(LoOperands[j], HiOperands[j]) =
6721 if (!
Op.getOperand(j).getValueType().isVector()) {
6722 LoOperands[j] =
Op.getOperand(j);
6723 HiOperands[j] =
Op.getOperand(j);
6726 std::tie(LoOperands[j], HiOperands[j]) =
6731 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
6733 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
6743 auto [EVLLo, EVLHi] =
6744 DAG.
SplitEVL(
Op.getOperand(3),
Op.getOperand(1).getValueType(),
DL);
6748 {Op.getOperand(0), Lo, MaskLo, EVLLo},
Op->getFlags());
6750 {ResLo, Hi, MaskHi, EVLHi},
Op->getFlags());
6768 if (!
Op.getOperand(j).getValueType().isVector()) {
6769 LoOperands[j] =
Op.getOperand(j);
6770 HiOperands[j] =
Op.getOperand(j);
6773 std::tie(LoOperands[j], HiOperands[j]) =
6778 DAG.
getNode(
Op.getOpcode(),
DL, LoVTs, LoOperands,
Op->getFlags());
6781 DAG.
getNode(
Op.getOpcode(),
DL, HiVTs, HiOperands,
Op->getFlags());
6790 switch (
Op.getOpcode()) {
6796 return lowerGlobalAddress(
Op, DAG);
6798 return lowerBlockAddress(
Op, DAG);
6800 return lowerConstantPool(
Op, DAG);
6802 return lowerJumpTable(
Op, DAG);
6804 return lowerGlobalTLSAddress(
Op, DAG);
6808 return lowerConstantFP(
Op, DAG);
6810 return lowerSELECT(
Op, DAG);
6812 return lowerBRCOND(
Op, DAG);
6814 return lowerVASTART(
Op, DAG);
6816 return lowerFRAMEADDR(
Op, DAG);
6818 return lowerRETURNADDR(
Op, DAG);
6820 return lowerShiftLeftParts(
Op, DAG);
6822 return lowerShiftRightParts(
Op, DAG,
true);
6824 return lowerShiftRightParts(
Op, DAG,
false);
6827 if (
Op.getValueType().isFixedLengthVector()) {
6828 assert(Subtarget.hasStdExtZvkb());
6829 return lowerToScalableOp(
Op, DAG);
6831 assert(Subtarget.hasVendorXTHeadBb() &&
6832 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
6833 "Unexpected custom legalization");
6835 if (!isa<ConstantSDNode>(
Op.getOperand(1)))
6840 EVT VT =
Op.getValueType();
6844 if (Op0VT == MVT::i16 &&
6846 (VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
6850 if (VT == MVT::f32 && Op0VT == MVT::i32 && Subtarget.
is64Bit() &&
6855 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.
is64Bit() &&
6871 "Unexpected types");
6905 return LowerINTRINSIC_WO_CHAIN(
Op, DAG);
6907 return LowerINTRINSIC_W_CHAIN(
Op, DAG);
6909 return LowerINTRINSIC_VOID(
Op, DAG);
6911 return LowerIS_FPCLASS(
Op, DAG);
6913 MVT VT =
Op.getSimpleValueType();
6915 assert(Subtarget.hasStdExtZvbb());
6916 return lowerToScalableOp(
Op, DAG);
6919 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected custom legalization");
6929 if (!
Op.getSimpleValueType().isVector())
6931 return lowerVectorTruncLike(
Op, DAG);
6934 if (
Op.getOperand(0).getValueType().isVector() &&
6935 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
6936 return lowerVectorMaskExt(
Op, DAG, 1);
6939 if (
Op.getOperand(0).getValueType().isVector() &&
6940 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
6941 return lowerVectorMaskExt(
Op, DAG, -1);
6944 return lowerSPLAT_VECTOR_PARTS(
Op, DAG);
6946 return lowerINSERT_VECTOR_ELT(
Op, DAG);
6948 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
6950 MVT VT =
Op.getSimpleValueType();
6958 MVT ContainerVT = VT;
6966 DAG.
getUNDEF(ContainerVT), Scalar, VL);
6970 DAG.
getUNDEF(ContainerVT), Scalar, VL);
6978 MVT VT =
Op.getSimpleValueType();
6998 }
else if ((Val % 8) == 0) {
7014 if (
Op.getValueType() == MVT::f16 && Subtarget.
is64Bit() &&
7015 Op.getOperand(1).getValueType() == MVT::i32) {
7032 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
7035 return lowerStrictFPExtendOrRoundLike(
Op, DAG);
7038 if (
Op.getValueType().isVector() &&
7039 ((
Op.getValueType().getScalarType() == MVT::f16 &&
7042 Op.getValueType().getScalarType() == MVT::bf16)) {
7058 Op1.getValueType().isVector() &&
7059 ((Op1.getValueType().getScalarType() == MVT::f16 &&
7062 Op1.getValueType().getScalarType() == MVT::bf16)) {
7068 Op1.getValueType().getVectorElementCount());
7071 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), WidenVec);
7081 MVT VT =
Op.getSimpleValueType();
7084 bool IsStrict =
Op->isStrictFPOpcode();
7085 SDValue Src =
Op.getOperand(0 + IsStrict);
7086 MVT SrcVT = Src.getSimpleValueType();
7097 "Unexpected vector element types");
7101 if (EltSize > (2 * SrcEltSize)) {
7113 Op.getOperand(0), Ext);
7117 assert(SrcEltVT == MVT::f16 &&
"Unexpected FP_TO_[US]INT lowering");
7122 auto [FExt, Chain] =
7124 return DAG.
getNode(
Op.getOpcode(),
DL,
Op->getVTList(), Chain, FExt);
7131 if (SrcEltSize > (2 * EltSize)) {
7134 assert(EltVT == MVT::f16 &&
"Unexpected [US]_TO_FP lowering");
7139 Op.getOperand(0), Src);
7154 Op.getOperand(0), Src);
7168 unsigned RVVOpc = 0;
7169 switch (
Op.getOpcode()) {
7201 "Expected same element count");
7208 Op.getOperand(0), Src, Mask, VL);
7212 Src = DAG.
getNode(RVVOpc,
DL, ContainerVT, Src, Mask, VL);
7227 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
7234 MVT VT =
Op.getSimpleValueType();
7254 bool IsStrict =
Op->isStrictFPOpcode();
7255 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7259 std::tie(Res, Chain) =
7260 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
7275 bool IsStrict =
Op->isStrictFPOpcode();
7276 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7282 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
7283 CallOptions,
DL, Chain);
7300 if (
Op.getValueType().isVector())
7305 assert(
Op.getOperand(0).getValueType() == MVT::f16 &&
7306 "Unexpected custom legalisation");
7309 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), Ext);
7315 assert(
Op.getOperand(1).getValueType() == MVT::f16 &&
7316 "Unexpected custom legalisation");
7319 {
Op.getOperand(0),
Op.getOperand(1)});
7320 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
7321 {Ext.getValue(1), Ext.getValue(0)});
7328 return lowerVECREDUCE(
Op, DAG);
7332 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7333 return lowerVectorMaskVecReduction(
Op, DAG,
false);
7334 return lowerVECREDUCE(
Op, DAG);
7341 return lowerFPVECREDUCE(
Op, DAG);
7342 case ISD::VP_REDUCE_ADD:
7343 case ISD::VP_REDUCE_UMAX:
7344 case ISD::VP_REDUCE_SMAX:
7345 case ISD::VP_REDUCE_UMIN:
7346 case ISD::VP_REDUCE_SMIN:
7347 case ISD::VP_REDUCE_FADD:
7348 case ISD::VP_REDUCE_SEQ_FADD:
7349 case ISD::VP_REDUCE_FMIN:
7350 case ISD::VP_REDUCE_FMAX:
7351 case ISD::VP_REDUCE_FMINIMUM:
7352 case ISD::VP_REDUCE_FMAXIMUM:
7355 return lowerVPREDUCE(
Op, DAG);
7356 case ISD::VP_REDUCE_AND:
7357 case ISD::VP_REDUCE_OR:
7358 case ISD::VP_REDUCE_XOR:
7359 if (
Op.getOperand(1).getValueType().getVectorElementType() == MVT::i1)
7360 return lowerVectorMaskVecReduction(
Op, DAG,
true);
7361 return lowerVPREDUCE(
Op, DAG);
7362 case ISD::VP_CTTZ_ELTS:
7363 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
7364 return lowerVPCttzElements(
Op, DAG);
7368 DAG.
getUNDEF(ContainerVT), DAG, Subtarget);
7371 return lowerINSERT_SUBVECTOR(
Op, DAG);
7373 return lowerEXTRACT_SUBVECTOR(
Op, DAG);
7375 return lowerVECTOR_DEINTERLEAVE(
Op, DAG);
7377 return lowerVECTOR_INTERLEAVE(
Op, DAG);
7379 return lowerSTEP_VECTOR(
Op, DAG);
7381 return lowerVECTOR_REVERSE(
Op, DAG);
7383 return lowerVECTOR_SPLICE(
Op, DAG);
7387 MVT VT =
Op.getSimpleValueType();
7389 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
7390 EltVT == MVT::bf16) {
7393 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
7394 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
7404 if (EltVT == MVT::i1)
7405 return lowerVectorMaskSplat(
Op, DAG);
7414 MVT VT =
Op.getSimpleValueType();
7415 MVT ContainerVT = VT;
7433 Op->ops().take_front(HalfNumOps));
7435 Op->ops().drop_front(HalfNumOps));
7439 unsigned NumOpElts =
7440 Op.getOperand(0).getSimpleValueType().getVectorMinNumElements();
7443 SDValue SubVec = OpIdx.value();
7454 auto *Load = cast<LoadSDNode>(
Op);
7455 EVT VecTy = Load->getMemoryVT();
7462 unsigned NumElts = Sz / (NF * 8);
7463 int Log2LMUL =
Log2_64(NumElts) - 3;
7466 Flag.setNoUnsignedWrap(
true);
7468 SDValue BasePtr = Load->getBasePtr();
7476 for (
unsigned i = 0; i < NF; ++i) {
7489 if (
auto V = expandUnalignedRVVLoad(
Op, DAG))
7491 if (
Op.getValueType().isFixedLengthVector())
7492 return lowerFixedLengthVectorLoadToRVV(
Op, DAG);
7496 auto *Store = cast<StoreSDNode>(
Op);
7497 SDValue StoredVal = Store->getValue();
7505 unsigned NumElts = Sz / (NF * 8);
7506 int Log2LMUL =
Log2_64(NumElts) - 3;
7509 Flag.setNoUnsignedWrap(
true);
7511 SDValue Chain = Store->getChain();
7512 SDValue BasePtr = Store->getBasePtr();
7519 for (
unsigned i = 0; i < NF; ++i) {
7523 Ret = DAG.
getStore(Chain,
DL, Extract, BasePtr,
7525 Store->getOriginalAlign(),
7526 Store->getMemOperand()->getFlags());
7527 Chain = Ret.getValue(0);
7533 if (
auto V = expandUnalignedRVVStore(
Op, DAG))
7535 if (
Op.getOperand(1).getValueType().isFixedLengthVector())
7536 return lowerFixedLengthVectorStoreToRVV(
Op, DAG);
7541 return lowerMaskedLoad(
Op, DAG);
7544 return lowerMaskedStore(
Op, DAG);
7546 return lowerVectorCompress(
Op, DAG);
7555 EVT VT =
Op.getValueType();
7566 MVT OpVT =
Op.getOperand(0).getSimpleValueType();
7568 MVT VT =
Op.getSimpleValueType();
7573 "Unexpected CondCode");
7581 if (isa<ConstantSDNode>(
RHS)) {
7582 int64_t Imm = cast<ConstantSDNode>(
RHS)->getSExtValue();
7583 if (Imm != 0 && isInt<12>((
uint64_t)Imm + 1)) {
7605 return lowerFixedLengthVectorSetccToRVV(
Op, DAG);
7621 return lowerToScalableOp(
Op, DAG);
7625 if (
Op.getSimpleValueType().isFixedLengthVector())
7626 return lowerToScalableOp(
Op, DAG);
7628 assert(
Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.
is64Bit() &&
7629 "Unexpected custom legalisation");
7633 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
7659 return lowerToScalableOp(
Op, DAG);
7663 EVT VT =
Op->getValueType(0);
7678 return lowerABS(
Op, DAG);
7683 if (Subtarget.hasStdExtZvbb())
7684 return lowerToScalableOp(
Op, DAG);
7686 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
7688 return lowerFixedLengthVectorSelectToRVV(
Op, DAG);
7690 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
7694 return lowerFixedLengthVectorFCOPYSIGNToRVV(
Op, DAG);
7703 return lowerToScalableOp(
Op, DAG);
7706 return lowerVectorStrictFSetcc(
Op, DAG);
7716 case ISD::VP_GATHER:
7717 return lowerMaskedGather(
Op, DAG);
7719 case ISD::VP_SCATTER:
7720 return lowerMaskedScatter(
Op, DAG);
7722 return lowerGET_ROUNDING(
Op, DAG);
7724 return lowerSET_ROUNDING(
Op, DAG);
7726 return lowerEH_DWARF_CFA(
Op, DAG);
7728 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7729 return lowerVPMergeMask(
Op, DAG);
7731 case ISD::VP_SELECT:
7739 case ISD::VP_UADDSAT:
7740 case ISD::VP_USUBSAT:
7741 case ISD::VP_SADDSAT:
7742 case ISD::VP_SSUBSAT:
7744 case ISD::VP_LLRINT:
7745 return lowerVPOp(
Op, DAG);
7749 return lowerLogicVPOp(
Op, DAG);
7758 case ISD::VP_FMINNUM:
7759 case ISD::VP_FMAXNUM:
7760 case ISD::VP_FCOPYSIGN:
7767 return lowerVPOp(
Op, DAG);
7768 case ISD::VP_IS_FPCLASS:
7769 return LowerIS_FPCLASS(
Op, DAG);
7770 case ISD::VP_SIGN_EXTEND:
7771 case ISD::VP_ZERO_EXTEND:
7772 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
7773 return lowerVPExtMaskOp(
Op, DAG);
7774 return lowerVPOp(
Op, DAG);
7775 case ISD::VP_TRUNCATE:
7776 return lowerVectorTruncLike(
Op, DAG);
7777 case ISD::VP_FP_EXTEND:
7778 case ISD::VP_FP_ROUND:
7779 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
7780 case ISD::VP_SINT_TO_FP:
7781 case ISD::VP_UINT_TO_FP:
7782 if (
Op.getValueType().isVector() &&
7783 ((
Op.getValueType().getScalarType() == MVT::f16 &&
7786 Op.getValueType().getScalarType() == MVT::bf16)) {
7799 case ISD::VP_FP_TO_SINT:
7800 case ISD::VP_FP_TO_UINT:
7802 Op1.getValueType().isVector() &&
7803 ((Op1.getValueType().getScalarType() == MVT::f16 &&
7806 Op1.getValueType().getScalarType() == MVT::bf16)) {
7812 Op1.getValueType().getVectorElementCount());
7816 {WidenVec, Op.getOperand(1), Op.getOperand(2)});
7818 return lowerVPFPIntConvOp(
Op, DAG);
7822 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
7823 return lowerVPSetCCMaskOp(
Op, DAG);
7829 case ISD::VP_BITREVERSE:
7831 return lowerVPOp(
Op, DAG);
7833 case ISD::VP_CTLZ_ZERO_UNDEF:
7834 if (Subtarget.hasStdExtZvbb())
7835 return lowerVPOp(
Op, DAG);
7836 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
7838 case ISD::VP_CTTZ_ZERO_UNDEF:
7839 if (Subtarget.hasStdExtZvbb())
7840 return lowerVPOp(
Op, DAG);
7841 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
7843 return lowerVPOp(
Op, DAG);
7844 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
7845 return lowerVPStridedLoad(
Op, DAG);
7846 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
7847 return lowerVPStridedStore(
Op, DAG);
7849 case ISD::VP_FFLOOR:
7851 case ISD::VP_FNEARBYINT:
7852 case ISD::VP_FROUND:
7853 case ISD::VP_FROUNDEVEN:
7854 case ISD::VP_FROUNDTOZERO:
7858 case ISD::VP_FMAXIMUM:
7859 case ISD::VP_FMINIMUM:
7863 case ISD::EXPERIMENTAL_VP_SPLICE:
7864 return lowerVPSpliceExperimental(
Op, DAG);
7865 case ISD::EXPERIMENTAL_VP_REVERSE:
7866 return lowerVPReverseExperimental(
Op, DAG);
7867 case ISD::EXPERIMENTAL_VP_SPLAT:
7868 return lowerVPSplatExperimental(
Op, DAG);
7871 "llvm.clear_cache only needs custom lower on Linux targets");
7874 return emitFlushICache(DAG,
Op.getOperand(0),
Op.getOperand(1),
7875 Op.getOperand(2), Flags,
DL);
7878 return lowerDYNAMIC_STACKALLOC(
Op, DAG);
7880 return lowerINIT_TRAMPOLINE(
Op, DAG);
7882 return lowerADJUST_TRAMPOLINE(
Op, DAG);
7889 MakeLibCallOptions CallOptions;
7890 std::pair<SDValue, SDValue> CallResult =
7891 makeLibCall(DAG, RTLIB::RISCV_FLUSH_ICACHE, MVT::isVoid,
7892 {Start,
End, Flags}, CallOptions,
DL, InChain);
7895 return CallResult.second;
7908 std::unique_ptr<MCCodeEmitter> CodeEmitter(
7915 const Value *TrmpAddr = cast<SrcValueSDNode>(
Op.getOperand(4))->getValue();
7927 constexpr unsigned StaticChainOffset = 16;
7928 constexpr unsigned FunctionAddressOffset = 24;
7932 auto GetEncoding = [&](
const MCInst &MC) {
7935 CodeEmitter->encodeInstruction(MC, CB, Fixups, *STI);
7945 GetEncoding(
MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X7).addImm(0)),
7950 MCInstBuilder(RISCV::LD).addReg(RISCV::X5).addReg(RISCV::X7).addImm(
7951 FunctionAddressOffset)),
7955 MCInstBuilder(RISCV::LD).addReg(RISCV::X7).addReg(RISCV::X7).addImm(
7956 StaticChainOffset)),
7975 SDValue FunctionAddress =
Op.getOperand(2);
7979 struct OffsetValuePair {
7983 } OffsetValues[] = {
7984 {StaticChainOffset, StaticChain},
7985 {FunctionAddressOffset, FunctionAddress},
7990 DAG.
getConstant(OffsetValue.Offset, dl, MVT::i64));
7991 OffsetValue.Addr =
Addr;
7992 OutChains[
Idx + 4] =
8001 SDValue EndOfTrmp = OffsetValues[0].Addr;
8015 return Op.getOperand(0);
8032 N->getOffset(), Flags);
8061template <
class NodeTy>
8063 bool IsLocal,
bool IsExternWeak)
const {
8073 if (IsLocal && !Subtarget.allowTaggedGlobals())
8143 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
8152 return getAddr(
N, DAG);
8159 return getAddr(
N, DAG);
8166 return getAddr(
N, DAG);
8171 bool UseGOT)
const {
8235 Args.push_back(Entry);
8268 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
8282 Addr = getStaticTLSAddr(
N, DAG,
false);
8285 Addr = getStaticTLSAddr(
N, DAG,
true);
8290 : getDynamicTLSAddr(
N, DAG);
8307 if (
LHS == LHS2 &&
RHS == RHS2) {
8312 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
8320 return std::nullopt;
8328 MVT VT =
N->getSimpleValueType(0);
8358 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV)) {
8361 if (~TrueVal == FalseVal) {
8401 if (Subtarget.hasShortForwardBranchOpt())
8404 unsigned SelOpNo = 0;
8414 unsigned ConstSelOpNo = 1;
8415 unsigned OtherSelOpNo = 2;
8416 if (!dyn_cast<ConstantSDNode>(Sel->
getOperand(ConstSelOpNo))) {
8421 ConstantSDNode *ConstSelOpNode = dyn_cast<ConstantSDNode>(ConstSelOp);
8422 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
8426 ConstantSDNode *ConstBinOpNode = dyn_cast<ConstantSDNode>(ConstBinOp);
8427 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
8433 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
8435 std::swap(NewConstOps[0], NewConstOps[1]);
8447 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
8449 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
8452 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
8453 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
8462 MVT VT =
Op.getSimpleValueType();
8476 if ((Subtarget.hasStdExtZicond() || Subtarget.hasVendorXVentanaCondOps()) &&
8504 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV)) {
8516 int64_t TrueImm =
TrueVal.getSExtValue();
8517 int64_t FalseImm =
FalseVal.getSExtValue();
8520 if (isInt<12>(TrueImm) && isInt<12>(FalseImm) &&
8521 isInt<12>(TrueImm - FalseImm)) {
8535 TrueVal, Subtarget.
getXLen(), Subtarget,
true);
8537 FalseVal, Subtarget.
getXLen(), Subtarget,
true);
8538 bool IsCZERO_NEZ = TrueValCost <= FalseValCost;
8540 IsCZERO_NEZ ? FalseVal - TrueVal : TrueVal - FalseVal,
DL, VT);
8545 DL, VT, LHSVal, CondV);
8561 if (
Op.hasOneUse()) {
8562 unsigned UseOpc =
Op->user_begin()->getOpcode();
8571 return lowerSELECT(NewSel, DAG);
8600 SDValue Ops[] = {CondV,
Zero, SetNE, TrueV, FalseV};
8621 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV) &&
8625 if (TrueVal - 1 == FalseVal)
8627 if (TrueVal + 1 == FalseVal)
8634 RHS == TrueV && LHS == FalseV) {
8651 if (isa<ConstantSDNode>(TrueV) && !isa<ConstantSDNode>(FalseV)) {
8677 LHS, RHS, TargetCC,
Op.getOperand(2));
8695 const Value *SV = cast<SrcValueSDNode>(
Op.getOperand(2))->getValue();
8707 int XLenInBytes = Subtarget.
getXLen() / 8;
8709 EVT VT =
Op.getValueType();
8712 unsigned Depth =
Op.getConstantOperandVal(0);
8714 int Offset = -(XLenInBytes * 2);
8731 int XLenInBytes = Subtarget.
getXLen() / 8;
8736 EVT VT =
Op.getValueType();
8738 unsigned Depth =
Op.getConstantOperandVal(0);
8740 int Off = -XLenInBytes;
8741 SDValue FrameAddr = lowerFRAMEADDR(
Op, DAG);
8760 EVT VT =
Lo.getValueType();
8799 EVT VT =
Lo.getValueType();
8850 MVT VT =
Op.getSimpleValueType();
8876 MVT VecVT =
Op.getSimpleValueType();
8878 "Unexpected SPLAT_VECTOR_PARTS lowering");
8884 MVT ContainerVT = VecVT;
8904 int64_t ExtTrueVal)
const {
8906 MVT VecVT =
Op.getSimpleValueType();
8909 assert(Src.getValueType().isVector() &&
8910 Src.getValueType().getVectorElementType() == MVT::i1);
8931 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
8933 DAG.
getUNDEF(ContainerVT), SplatTrueVal, VL);
8936 SplatZero, DAG.
getUNDEF(ContainerVT), VL);
8941SDValue RISCVTargetLowering::lowerFixedLengthVectorExtendToRVV(
8943 MVT ExtVT =
Op.getSimpleValueType();
8947 MVT VT =
Op.getOperand(0).getSimpleValueType();
8973 bool IsVPTrunc =
Op.getOpcode() == ISD::VP_TRUNCATE;
8975 EVT MaskVT =
Op.getValueType();
8978 "Unexpected type for vector mask lowering");
8980 MVT VecVT = Src.getSimpleValueType();
8984 VL =
Op.getOperand(2);
8987 MVT ContainerVT = VecVT;
8993 MVT MaskContainerVT =
9000 std::tie(Mask, VL) =
9008 DAG.
getUNDEF(ContainerVT), SplatOne, VL);
9010 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
9014 DAG.
getUNDEF(ContainerVT), Mask, VL);
9017 DAG.
getUNDEF(MaskContainerVT), Mask, VL});
9025 unsigned Opc =
Op.getOpcode();
9026 bool IsVPTrunc = Opc == ISD::VP_TRUNCATE;
9029 MVT VT =
Op.getSimpleValueType();
9031 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
9035 return lowerVectorMaskTruncLike(
Op, DAG);
9043 MVT SrcVT = Src.getSimpleValueType();
9048 "Unexpected vector truncate lowering");
9050 MVT ContainerVT = SrcVT;
9054 VL =
Op.getOperand(2);
9067 std::tie(Mask, VL) =
9083 }
while (SrcEltVT != DstEltVT);
9092RISCVTargetLowering::lowerStrictFPExtendOrRoundLike(
SDValue Op,
9097 MVT VT =
Op.getSimpleValueType();
9098 MVT SrcVT = Src.getSimpleValueType();
9099 MVT ContainerVT = VT;
9122 Chain, Src, Mask, VL);
9123 Chain = Src.getValue(1);
9130 Chain, Src, Mask, VL);
9141RISCVTargetLowering::lowerVectorFPExtendOrRoundLike(
SDValue Op,
9144 Op.getOpcode() == ISD::VP_FP_ROUND ||
Op.getOpcode() == ISD::VP_FP_EXTEND;
9151 MVT VT =
Op.getSimpleValueType();
9153 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
9156 MVT SrcVT = Src.getSimpleValueType();
9158 bool IsDirectExtend =
9166 bool IsDirectConv = IsDirectExtend || IsDirectTrunc;
9173 MVT ContainerVT = VT;
9177 VL =
Op.getOperand(2);
9191 std::tie(Mask, VL) =
9197 Src = DAG.
getNode(ConvOpc,
DL, ContainerVT, Src, Mask, VL);
9203 unsigned InterConvOpc =
9208 DAG.
getNode(InterConvOpc,
DL, InterVT, Src, Mask, VL);
9210 DAG.
getNode(ConvOpc,
DL, ContainerVT, IntermediateConv, Mask, VL);
9221static std::optional<MVT>
9227 const unsigned MinVLMAX = VectorBitsMin / EltSize;
9229 if (MaxIdx < MinVLMAX)
9231 else if (MaxIdx < MinVLMAX * 2)
9233 else if (MaxIdx < MinVLMAX * 4)
9238 return std::nullopt;
9251 MVT VecVT =
Op.getSimpleValueType();
9268 ValVT == MVT::bf16) {
9277 MVT ContainerVT = VecVT;
9286 MVT OrigContainerVT = ContainerVT;
9289 if (
auto *IdxC = dyn_cast<ConstantSDNode>(
Idx)) {
9290 const unsigned OrigIdx = IdxC->getZExtValue();
9293 DL, DAG, Subtarget)) {
9294 ContainerVT = *ShrunkVT;
9303 VLEN && ContainerVT.
bitsGT(M1VT)) {
9306 unsigned RemIdx = OrigIdx % ElemsPerVReg;
9307 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
9308 unsigned ExtractIdx =
9325 if (!IsLegalInsert && isa<ConstantSDNode>(Val)) {
9326 const auto *CVal = cast<ConstantSDNode>(Val);
9327 if (isInt<32>(CVal->getSExtValue())) {
9328 IsLegalInsert =
true;
9337 if (IsLegalInsert) {
9343 Vec = DAG.
getNode(Opc,
DL, ContainerVT, Vec, Val, VL);
9359 std::tie(ValLo, ValHi) = DAG.
SplitScalar(Val,
DL, MVT::i32, MVT::i32);
9360 MVT I32ContainerVT =
9371 Vec, Vec, ValLo, I32Mask, InsertI64VL);
9376 Tail, ValInVec, ValHi, I32Mask, InsertI64VL);
9378 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
9383 ValInVec, AlignedIdx);
9393 DAG.
getUNDEF(I32ContainerVT), ValLo,
9394 I32Mask, InsertI64VL);
9396 DAG.
getUNDEF(I32ContainerVT), ValInVec, ValHi,
9397 I32Mask, InsertI64VL);
9399 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
9412 Idx, Mask, InsertVL, Policy);
9416 Slideup, AlignedIdx);
9431 EVT EltVT =
Op.getValueType();
9438 MVT ContainerVT = VecVT;
9454 unsigned WidenVecLen;
9457 unsigned MaxEEW = Subtarget.
getELen();
9462 "the number of elements should be power of 2");
9466 ExtractBitIdx =
Idx;
9468 WideEltVT = LargestEltVT;
9471 ExtractElementIdx = DAG.
getNode(
9482 Vec, ExtractElementIdx);
9498 EltVT == MVT::bf16) {
9508 MVT ContainerVT = VecVT;
9519 if (
auto *IdxC = dyn_cast<ConstantSDNode>(
Idx);
9520 IdxC && VLen && VecVT.
getSizeInBits().getKnownMinValue() > *VLen) {
9522 unsigned OrigIdx = IdxC->getZExtValue();
9525 unsigned RemIdx = OrigIdx % ElemsPerVReg;
9526 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
9527 unsigned ExtractIdx =
9537 std::optional<uint64_t> MaxIdx;
9540 if (
auto *IdxC = dyn_cast<ConstantSDNode>(
Idx))
9541 MaxIdx = IdxC->getZExtValue();
9543 if (
auto SmallerVT =
9545 ContainerVT = *SmallerVT;
9592 "Unexpected opcode");
9599 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
9604 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
9605 if (!
II || !
II->hasScalarOperand())
9608 unsigned SplatOp =
II->ScalarOperand + 1 + HasChain;
9621 if (OpVT.
bitsLT(XLenVT)) {
9628 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
9638 assert(
II->ScalarOperand > 0 &&
"Unexpected splat operand!");
9639 MVT VT =
Op.getOperand(SplatOp - 1).getSimpleValueType();
9642 assert(XLenVT == MVT::i32 && OpVT == MVT::i64 &&
9653 case Intrinsic::riscv_vslide1up:
9654 case Intrinsic::riscv_vslide1down:
9655 case Intrinsic::riscv_vslide1up_mask:
9656 case Intrinsic::riscv_vslide1down_mask: {
9659 bool IsMasked = NumOps == 7;
9665 std::tie(ScalarLo, ScalarHi) =
9673 if (isa<ConstantSDNode>(AVL)) {
9674 const auto [MinVLMAX, MaxVLMAX] =
9678 if (AVLInt <= MinVLMAX) {
9680 }
else if (AVLInt >= 2 * MaxVLMAX) {
9714 if (IntNo == Intrinsic::riscv_vslide1up ||
9715 IntNo == Intrinsic::riscv_vslide1up_mask) {
9717 ScalarHi, I32Mask, I32VL);
9719 ScalarLo, I32Mask, I32VL);
9722 ScalarLo, I32Mask, I32VL);
9724 ScalarHi, I32Mask, I32VL);
9773 const unsigned ElementWidth = 8;
9778 [[maybe_unused]]
unsigned MinVF =
9781 [[maybe_unused]]
unsigned VF =
N->getConstantOperandVal(2);
9785 bool Fractional = VF < LMul1VF;
9786 unsigned LMulVal = Fractional ? LMul1VF / VF : VF / LMul1VF;
9807 MVT ContainerVT = OpVT;
9834 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
9838 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
9839 if (!
II || !
II->hasScalarOperand())
9842 unsigned SplatOp =
II->ScalarOperand + 1;
9855 if (OpVT.
bitsLT(XLenVT)) {
9858 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
9869 EVT ValType = V.getValueType();
9870 if (ValType.isVector() && ValType.isFloatingPoint()) {
9873 ValType.getVectorElementCount());
9876 if (ValType.isFixedLengthVector()) {
9878 DAG, V.getSimpleValueType(), Subtarget);
9894 unsigned IntNo =
Op.getConstantOperandVal(0);
9901 case Intrinsic::riscv_tuple_insert: {
9909 case Intrinsic::riscv_tuple_extract: {
9916 case Intrinsic::thread_pointer: {
9920 case Intrinsic::riscv_orc_b:
9921 case Intrinsic::riscv_brev8:
9922 case Intrinsic::riscv_sha256sig0:
9923 case Intrinsic::riscv_sha256sig1:
9924 case Intrinsic::riscv_sha256sum0:
9925 case Intrinsic::riscv_sha256sum1:
9926 case Intrinsic::riscv_sm3p0:
9927 case Intrinsic::riscv_sm3p1: {
9940 return DAG.
getNode(Opc,
DL, XLenVT,
Op.getOperand(1));
9942 case Intrinsic::riscv_sm4ks:
9943 case Intrinsic::riscv_sm4ed: {
9947 return DAG.
getNode(Opc,
DL, XLenVT,
Op.getOperand(1),
Op.getOperand(2),
9950 case Intrinsic::riscv_zip:
9951 case Intrinsic::riscv_unzip: {
9954 return DAG.
getNode(Opc,
DL, XLenVT,
Op.getOperand(1));
9956 case Intrinsic::riscv_mopr:
9960 case Intrinsic::riscv_moprr: {
9962 Op.getOperand(2),
Op.getOperand(3));
9964 case Intrinsic::riscv_clmul:
9967 case Intrinsic::riscv_clmulh:
9968 case Intrinsic::riscv_clmulr: {
9971 return DAG.
getNode(Opc,
DL, XLenVT,
Op.getOperand(1),
Op.getOperand(2));
9973 case Intrinsic::experimental_get_vector_length:
9975 case Intrinsic::experimental_cttz_elts:
9977 case Intrinsic::riscv_vmv_x_s: {
9981 case Intrinsic::riscv_vfmv_f_s:
9984 case Intrinsic::riscv_vmv_v_x:
9986 Op.getOperand(3),
Op.getSimpleValueType(),
DL, DAG,
9988 case Intrinsic::riscv_vfmv_v_f:
9990 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
9991 case Intrinsic::riscv_vmv_s_x: {
9994 if (
Scalar.getValueType().bitsLE(XLenVT)) {
9997 Op.getOperand(1), Scalar,
Op.getOperand(3));
10000 assert(
Scalar.getValueType() == MVT::i64 &&
"Unexpected scalar VT!");
10017 MVT VT =
Op.getSimpleValueType();
10022 if (
Op.getOperand(1).isUndef())
10023 return SplattedVal;
10038 case Intrinsic::riscv_vfmv_s_f:
10040 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
10042 case Intrinsic::riscv_vaesdf_vv:
10043 case Intrinsic::riscv_vaesdf_vs:
10044 case Intrinsic::riscv_vaesdm_vv:
10045 case Intrinsic::riscv_vaesdm_vs:
10046 case Intrinsic::riscv_vaesef_vv:
10047 case Intrinsic::riscv_vaesef_vs:
10048 case Intrinsic::riscv_vaesem_vv:
10049 case Intrinsic::riscv_vaesem_vs:
10050 case Intrinsic::riscv_vaeskf1:
10051 case Intrinsic::riscv_vaeskf2:
10052 case Intrinsic::riscv_vaesz_vs:
10053 case Intrinsic::riscv_vsm4k:
10054 case Intrinsic::riscv_vsm4r_vv:
10055 case Intrinsic::riscv_vsm4r_vs: {
10056 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
10057 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
10058 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
10063 case Intrinsic::riscv_vsm3c:
10064 case Intrinsic::riscv_vsm3me: {
10065 if (!
isValidEGW(8,
Op.getSimpleValueType(), Subtarget) ||
10066 !
isValidEGW(8,
Op->getOperand(1).getSimpleValueType(), Subtarget))
10071 case Intrinsic::riscv_vsha2ch:
10072 case Intrinsic::riscv_vsha2cl:
10073 case Intrinsic::riscv_vsha2ms: {
10074 if (
Op->getSimpleValueType(0).getScalarSizeInBits() == 64 &&
10075 !Subtarget.hasStdExtZvknhb())
10077 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
10078 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
10079 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
10083 case Intrinsic::riscv_sf_vc_v_x:
10084 case Intrinsic::riscv_sf_vc_v_i:
10085 case Intrinsic::riscv_sf_vc_v_xv:
10086 case Intrinsic::riscv_sf_vc_v_iv:
10087 case Intrinsic::riscv_sf_vc_v_vv:
10088 case Intrinsic::riscv_sf_vc_v_fv:
10089 case Intrinsic::riscv_sf_vc_v_xvv:
10090 case Intrinsic::riscv_sf_vc_v_ivv:
10091 case Intrinsic::riscv_sf_vc_v_vvv:
10092 case Intrinsic::riscv_sf_vc_v_fvv:
10093 case Intrinsic::riscv_sf_vc_v_xvw:
10094 case Intrinsic::riscv_sf_vc_v_ivw:
10095 case Intrinsic::riscv_sf_vc_v_vvw:
10096 case Intrinsic::riscv_sf_vc_v_fvw: {
10097 MVT VT =
Op.getSimpleValueType();
10134 MVT VT =
Op.getSimpleValueType();
10138 if (VT.isFloatingPoint()) {
10143 if (VT.isFixedLengthVector())
10153 if (VT.isFixedLengthVector())
10155 if (VT.isFloatingPoint())
10174 unsigned IntNo =
Op.getConstantOperandVal(1);
10178 case Intrinsic::riscv_seg2_load:
10179 case Intrinsic::riscv_seg3_load:
10180 case Intrinsic::riscv_seg4_load:
10181 case Intrinsic::riscv_seg5_load:
10182 case Intrinsic::riscv_seg6_load:
10183 case Intrinsic::riscv_seg7_load:
10184 case Intrinsic::riscv_seg8_load: {
10187 Intrinsic::riscv_vlseg2, Intrinsic::riscv_vlseg3,
10188 Intrinsic::riscv_vlseg4, Intrinsic::riscv_vlseg5,
10189 Intrinsic::riscv_vlseg6, Intrinsic::riscv_vlseg7,
10190 Intrinsic::riscv_vlseg8};
10191 unsigned NF =
Op->getNumValues() - 1;
10192 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
10194 MVT VT =
Op->getSimpleValueType(0);
10202 auto *
Load = cast<MemIntrinsicSDNode>(
Op);
10214 Load->getMemoryVT(),
Load->getMemOperand());
10216 for (
unsigned int RetIdx = 0; RetIdx < NF; RetIdx++) {
10225 case Intrinsic::riscv_sf_vc_v_x_se:
10227 case Intrinsic::riscv_sf_vc_v_i_se:
10229 case Intrinsic::riscv_sf_vc_v_xv_se:
10231 case Intrinsic::riscv_sf_vc_v_iv_se:
10233 case Intrinsic::riscv_sf_vc_v_vv_se:
10235 case Intrinsic::riscv_sf_vc_v_fv_se:
10237 case Intrinsic::riscv_sf_vc_v_xvv_se:
10239 case Intrinsic::riscv_sf_vc_v_ivv_se:
10241 case Intrinsic::riscv_sf_vc_v_vvv_se:
10243 case Intrinsic::riscv_sf_vc_v_fvv_se:
10245 case Intrinsic::riscv_sf_vc_v_xvw_se:
10247 case Intrinsic::riscv_sf_vc_v_ivw_se:
10249 case Intrinsic::riscv_sf_vc_v_vvw_se:
10251 case Intrinsic::riscv_sf_vc_v_fvw_se:
10260 unsigned IntNo =
Op.getConstantOperandVal(1);
10264 case Intrinsic::riscv_seg2_store:
10265 case Intrinsic::riscv_seg3_store:
10266 case Intrinsic::riscv_seg4_store:
10267 case Intrinsic::riscv_seg5_store:
10268 case Intrinsic::riscv_seg6_store:
10269 case Intrinsic::riscv_seg7_store:
10270 case Intrinsic::riscv_seg8_store: {
10273 Intrinsic::riscv_vsseg2, Intrinsic::riscv_vsseg3,
10274 Intrinsic::riscv_vsseg4, Intrinsic::riscv_vsseg5,
10275 Intrinsic::riscv_vsseg6, Intrinsic::riscv_vsseg7,
10276 Intrinsic::riscv_vsseg8};
10279 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
10281 MVT VT =
Op->getOperand(2).getSimpleValueType();
10291 auto *FixedIntrinsic = cast<MemIntrinsicSDNode>(
Op);
10294 for (
unsigned i = 0; i < NF; i++)
10298 ContainerVT, FixedIntrinsic->getOperand(2 + i), DAG, Subtarget),
10302 FixedIntrinsic->getChain(),
10311 FixedIntrinsic->getMemoryVT(), FixedIntrinsic->getMemOperand());
10313 case Intrinsic::riscv_sf_vc_xv_se:
10315 case Intrinsic::riscv_sf_vc_iv_se:
10317 case Intrinsic::riscv_sf_vc_vv_se:
10319 case Intrinsic::riscv_sf_vc_fv_se:
10321 case Intrinsic::riscv_sf_vc_xvv_se:
10323 case Intrinsic::riscv_sf_vc_ivv_se:
10325 case Intrinsic::riscv_sf_vc_vvv_se:
10327 case Intrinsic::riscv_sf_vc_fvv_se:
10329 case Intrinsic::riscv_sf_vc_xvw_se:
10331 case Intrinsic::riscv_sf_vc_ivw_se:
10333 case Intrinsic::riscv_sf_vc_vvw_se:
10335 case Intrinsic::riscv_sf_vc_fvw_se:
10343 switch (ISDOpcode) {
10346 case ISD::VP_REDUCE_ADD:
10349 case ISD::VP_REDUCE_UMAX:
10352 case ISD::VP_REDUCE_SMAX:
10355 case ISD::VP_REDUCE_UMIN:
10358 case ISD::VP_REDUCE_SMIN:
10361 case ISD::VP_REDUCE_AND:
10364 case ISD::VP_REDUCE_OR:
10367 case ISD::VP_REDUCE_XOR:
10370 case ISD::VP_REDUCE_FADD:
10372 case ISD::VP_REDUCE_SEQ_FADD:
10374 case ISD::VP_REDUCE_FMAX:
10375 case ISD::VP_REDUCE_FMAXIMUM:
10377 case ISD::VP_REDUCE_FMIN:
10378 case ISD::VP_REDUCE_FMINIMUM:
10388 SDValue Vec =
Op.getOperand(IsVP ? 1 : 0);
10393 Op.getOpcode() == ISD::VP_REDUCE_AND ||
10394 Op.getOpcode() == ISD::VP_REDUCE_OR ||
10395 Op.getOpcode() == ISD::VP_REDUCE_XOR) &&
10396 "Unexpected reduction lowering");
10400 MVT ContainerVT = VecVT;
10408 Mask =
Op.getOperand(2);
10409 VL =
Op.getOperand(3);
10411 std::tie(Mask, VL) =
10416 switch (
Op.getOpcode()) {
10420 case ISD::VP_REDUCE_AND: {
10432 case ISD::VP_REDUCE_OR:
10438 case ISD::VP_REDUCE_XOR: {
10462 return DAG.
getNode(BaseOpc,
DL,
Op.getValueType(), SetCC,
Op.getOperand(0));
10466 auto *RegisterAVL = dyn_cast<RegisterSDNode>(AVL);
10467 auto *ImmAVL = dyn_cast<ConstantSDNode>(AVL);
10468 return (RegisterAVL && RegisterAVL->getReg() == RISCV::X0) ||
10469 (ImmAVL && ImmAVL->getZExtValue() >= 1);
10485 auto InnerVT = VecVT.
bitsLE(M1VT) ? VecVT : M1VT;
10489 auto InnerVL = NonZeroAVL ? VL : DAG.
getConstant(1,
DL, XLenVT);
10492 if (M1VT != InnerVT)
10498 SDValue Ops[] = {PassThru, Vec, InitialValue, Mask, VL, Policy};
10517 VecEVT =
Lo.getValueType();
10530 MVT ContainerVT = VecVT;
10550 Mask, VL,
DL, DAG, Subtarget);
10556static std::tuple<unsigned, SDValue, SDValue>
10560 auto Flags =
Op->getFlags();
10561 unsigned Opcode =
Op.getOpcode();
10585 return std::make_tuple(RVVOpc,
Op.getOperand(0), Front);
10593 MVT VecEltVT =
Op.getSimpleValueType();
10595 unsigned RVVOpcode;
10596 SDValue VectorVal, ScalarVal;
10597 std::tie(RVVOpcode, VectorVal, ScalarVal) =
10601 MVT ContainerVT = VecVT;
10607 MVT ResVT =
Op.getSimpleValueType();
10610 VL,
DL, DAG, Subtarget);
10615 if (
Op->getFlags().hasNoNaNs())
10621 {VectorVal, VectorVal, DAG.getCondCode(ISD::SETNE),
10622 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
10628 DL, ResVT, NoNaNs, Res,
10635 unsigned Opc =
Op.getOpcode();
10658 Vec, Mask, VL,
DL, DAG, Subtarget);
10659 if ((Opc != ISD::VP_REDUCE_FMINIMUM && Opc != ISD::VP_REDUCE_FMAXIMUM) ||
10660 Op->getFlags().hasNoNaNs())
10677 DL, ResVT, NoNaNs, Res,
10690 unsigned OrigIdx =
Op.getConstantOperandVal(2);
10693 if (OrigIdx == 0 && Vec.
isUndef())
10704 assert(OrigIdx % 8 == 0 &&
"Invalid index");
10707 "Unexpected mask vector lowering");
10739 MVT ContainerVT = VecVT;
10746 DAG.
getUNDEF(ContainerVT), SubVec,
10763 if (OrigIdx == 0) {
10768 SubVec =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, Vec, SubVec,
10769 SlideupAmt, Mask, VL, Policy);
10777 MVT ContainerVecVT = VecVT;
10783 MVT ContainerSubVecVT = SubVecVT;
10789 unsigned SubRegIdx;
10799 ContainerVecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
10800 SubRegIdx = Decompose.first;
10802 (OrigIdx % Vscale));
10806 ContainerVecVT, ContainerSubVecVT, OrigIdx,
TRI);
10807 SubRegIdx = Decompose.first;
10814 bool ExactlyVecRegSized =
10816 .isKnownMultipleOf(Subtarget.
expandVScale(VecRegSize));
10831 if (RemIdx.
isZero() && (ExactlyVecRegSized || Vec.
isUndef())) {
10835 if (SubRegIdx == RISCV::NoSubRegister) {
10858 MVT InterSubVT = ContainerVecVT;
10859 SDValue AlignedExtract = Vec;
10899 SubVec =
getVSlideup(DAG, Subtarget,
DL, InterSubVT, AlignedExtract, SubVec,
10900 SlideupAmt, Mask, VL, Policy);
10905 if (ContainerVecVT.
bitsGT(InterSubVT))
10914 return DAG.
getBitcast(
Op.getSimpleValueType(), SubVec);
10920 MVT SubVecVT =
Op.getSimpleValueType();
10925 unsigned OrigIdx =
Op.getConstantOperandVal(1);
10941 assert(OrigIdx % 8 == 0 &&
"Invalid index");
10944 "Unexpected mask vector lowering");
10978 MVT ContainerVT = VecVT;
10986 if (
auto ShrunkVT =
10988 ContainerVT = *ShrunkVT;
11001 DAG.
getUNDEF(ContainerVT), Vec, SlidedownAmt, Mask, VL);
11013 MVT ContainerSubVecVT = SubVecVT;
11017 unsigned SubRegIdx;
11027 VecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
11028 SubRegIdx = Decompose.first;
11030 (OrigIdx % Vscale));
11034 VecVT, ContainerSubVecVT, OrigIdx,
TRI);
11035 SubRegIdx = Decompose.first;
11062 MVT InterSubVT = VecVT;
11067 assert(SubRegIdx != RISCV::NoSubRegister);
11087 Vec, SlidedownAmt, Mask, VL);
11096 return DAG.
getBitcast(
Op.getSimpleValueType(), Slidedown);
11103 MVT VT =
N.getSimpleValueType();
11107 assert(
Op.getSimpleValueType() == VT &&
11108 "Operands and result must be same type");
11112 unsigned NumVals =
N->getNumValues();
11115 NumVals,
N.getValueType().changeVectorElementType(MVT::i8)));
11118 for (
unsigned I = 0;
I < NumVals;
I++) {
11124 if (TruncVals.
size() > 1)
11126 return TruncVals.
front();
11132 MVT VecVT =
Op.getSimpleValueType();
11134 const unsigned Factor =
Op->getNumValues();
11145 for (
unsigned i = 0U; i < Factor; ++i)
11154 for (
unsigned i = 0U; i < Factor; ++i)
11164 for (
unsigned i = 0; i != Factor; ++i) {
11167 Ops[i * 2 + 1] = OpHi;
11175 ArrayRef(Ops).slice(Factor, Factor));
11178 for (
unsigned i = 0; i != Factor; ++i)
11214 EvenSplat = DAG.
getBitcast(MVT::nxv64i1, EvenSplat);
11219 OddSplat = DAG.
getBitcast(MVT::nxv64i1, OddSplat);
11225 EvenMask, DAG.
getUNDEF(ConcatVT));
11261 Intrinsic::riscv_vlseg2, Intrinsic::riscv_vlseg3, Intrinsic::riscv_vlseg4,
11262 Intrinsic::riscv_vlseg5, Intrinsic::riscv_vlseg6, Intrinsic::riscv_vlseg7,
11263 Intrinsic::riscv_vlseg8};
11284 for (
unsigned i = 0U; i < Factor; ++i)
11294 MVT VecVT =
Op.getSimpleValueType();
11307 for (
unsigned i = 0U; i < Factor; ++i)
11315 for (
unsigned i = 0U; i < Factor; ++i)
11328 for (
unsigned i = 0; i != Factor; ++i) {
11331 Ops[i + Factor] = OpHi;
11337 ArrayRef(Ops).take_front(Factor)),
11339 ArrayRef(Ops).drop_front(Factor))};
11342 for (
unsigned i = 0; i != Factor; ++i) {
11343 unsigned IdxLo = 2 * i;
11344 unsigned IdxHi = 2 * i + 1;
11346 Res[IdxLo / Factor].getValue(IdxLo % Factor),
11347 Res[IdxHi / Factor].getValue(IdxHi % Factor));
11371 Intrinsic::riscv_vsseg2, Intrinsic::riscv_vsseg3,
11372 Intrinsic::riscv_vsseg4, Intrinsic::riscv_vsseg5,
11373 Intrinsic::riscv_vsseg6, Intrinsic::riscv_vsseg7,
11374 Intrinsic::riscv_vsseg8,
11382 for (
unsigned i = 0; i < Factor; i++)
11405 for (
unsigned i = 0; i != Factor; ++i) {
11409 Loads[i] = DAG.
getLoad(VecVT,
DL, Chain, StackPtr, PtrInfo);
11426 Op.getOperand(0),
Op.getOperand(1));
11474 MVT VT =
Op.getSimpleValueType();
11479 uint64_t StepValImm =
Op.getConstantOperandVal(0);
11480 if (StepValImm != 1) {
11489 VL, VT,
DL, DAG, Subtarget);
11504 MVT VecVT =
Op.getSimpleValueType();
11513 MVT ContainerVT = VecVT;
11567 unsigned MaxVLMAX =
11577 if (MaxVLMAX > 256 && EltSize == 8) {
11606 assert(isUInt<16>(MaxVLMAX - 1));
11632 DAG.
getUNDEF(ContainerVT), Mask, VL);
11644 MVT VecVT =
Op.getSimpleValueType();
11648 int64_t ImmValue = cast<ConstantSDNode>(
Op.getOperand(2))->getSExtValue();
11649 SDValue DownOffset, UpOffset;
11650 if (ImmValue >= 0) {
11666 DownOffset, TrueMask, UpOffset);
11667 return getVSlideup(DAG, Subtarget,
DL, VecVT, SlideDown, V2, UpOffset,
11673RISCVTargetLowering::lowerFixedLengthVectorLoadToRVV(
SDValue Op,
11676 auto *
Load = cast<LoadSDNode>(
Op);
11679 Load->getMemoryVT(),
11680 *
Load->getMemOperand()) &&
11681 "Expecting a correctly-aligned load");
11683 MVT VT =
Op.getSimpleValueType();
11689 const auto [MinVLMAX, MaxVLMAX] =
11692 getLMUL1VT(ContainerVT).bitsLE(ContainerVT)) {
11706 IsMaskOp ? Intrinsic::riscv_vlm : Intrinsic::riscv_vle,
DL, XLenVT);
11709 Ops.push_back(DAG.
getUNDEF(ContainerVT));
11710 Ops.push_back(
Load->getBasePtr());
11715 Load->getMemoryVT(),
Load->getMemOperand());
11722RISCVTargetLowering::lowerFixedLengthVectorStoreToRVV(
SDValue Op,
11725 auto *
Store = cast<StoreSDNode>(
Op);
11728 Store->getMemoryVT(),
11729 *
Store->getMemOperand()) &&
11730 "Expecting a correctly-aligned store");
11751 const auto [MinVLMAX, MaxVLMAX] =
11754 getLMUL1VT(ContainerVT).bitsLE(ContainerVT)) {
11765 IsMaskOp ? Intrinsic::riscv_vsm : Intrinsic::riscv_vse,
DL, XLenVT);
11768 {Store->getChain(), IntID, NewValue, Store->getBasePtr(), VL},
11769 Store->getMemoryVT(),
Store->getMemOperand());
11775 MVT VT =
Op.getSimpleValueType();
11777 const auto *MemSD = cast<MemSDNode>(
Op);
11778 EVT MemVT = MemSD->getMemoryVT();
11780 SDValue Chain = MemSD->getChain();
11784 bool IsExpandingLoad =
false;
11785 if (
const auto *VPLoad = dyn_cast<VPLoadSDNode>(
Op)) {
11786 Mask = VPLoad->getMask();
11788 VL = VPLoad->getVectorLength();
11790 const auto *MLoad = cast<MaskedLoadSDNode>(
Op);
11791 Mask = MLoad->getMask();
11792 PassThru = MLoad->getPassThru();
11793 IsExpandingLoad = MLoad->isExpandingLoad();
11800 MVT ContainerVT = VT;
11814 if (!IsUnmasked && IsExpandingLoad) {
11821 unsigned IntID = IsUnmasked || IsExpandingLoad ? Intrinsic::riscv_vle
11822 : Intrinsic::riscv_vle_mask;
11824 if (IntID == Intrinsic::riscv_vle)
11825 Ops.push_back(DAG.
getUNDEF(ContainerVT));
11827 Ops.push_back(PassThru);
11828 Ops.push_back(BasePtr);
11829 if (IntID == Intrinsic::riscv_vle_mask)
11830 Ops.push_back(Mask);
11832 if (IntID == Intrinsic::riscv_vle_mask)
11839 Chain =
Result.getValue(1);
11841 MVT IndexVT = ContainerVT;
11846 bool UseVRGATHEREI16 =
false;
11854 UseVRGATHEREI16 =
true;
11860 DAG.
getUNDEF(IndexVT), Mask, ExpandingVL);
11864 DL, ContainerVT, Result, Iota, PassThru, Mask, ExpandingVL);
11877 const auto *MemSD = cast<MemSDNode>(
Op);
11878 EVT MemVT = MemSD->getMemoryVT();
11880 SDValue Chain = MemSD->getChain();
11884 bool IsCompressingStore =
false;
11885 if (
const auto *VPStore = dyn_cast<VPStoreSDNode>(
Op)) {
11886 Val = VPStore->getValue();
11887 Mask = VPStore->getMask();
11888 VL = VPStore->getVectorLength();
11890 const auto *MStore = cast<MaskedStoreSDNode>(
Op);
11891 Val = MStore->getValue();
11892 Mask = MStore->getMask();
11893 IsCompressingStore = MStore->isCompressingStore();
11902 MVT ContainerVT = VT;
11907 if (!IsUnmasked || IsCompressingStore) {
11916 if (IsCompressingStore) {
11919 DAG.
getUNDEF(ContainerVT), Val, Mask, VL);
11926 IsUnmasked ? Intrinsic::riscv_vse : Intrinsic::riscv_vse_mask;
11928 Ops.push_back(Val);
11929 Ops.push_back(BasePtr);
11931 Ops.push_back(Mask);
11935 DAG.
getVTList(MVT::Other), Ops, MemVT, MMO);
11947 MVT ContainerVT = VT;
11960 Passthru, Val, Mask, VL);
11969RISCVTargetLowering::lowerFixedLengthVectorSetccToRVV(
SDValue Op,
11971 MVT InVT =
Op.getOperand(0).getSimpleValueType();
11974 MVT VT =
Op.getSimpleValueType();
11988 {Op1, Op2,
Op.getOperand(2), DAG.
getUNDEF(MaskVT), Mask, VL});
11995 unsigned Opc =
Op.getOpcode();
12002 MVT VT =
Op.getSimpleValueType();
12035 MVT ContainerInVT = InVT;
12054 {Chain, Op1, Op1, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
12058 {Chain, Op2, Op2, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
12066 {Chain, Op1, Op2, CC, Mask, Mask, VL});
12071 {Chain, Op1, Op2, CC, DAG.getUNDEF(MaskVT), Mask, VL});
12084 MVT VT =
Op.getSimpleValueType();
12088 "Unexpected type for ISD::ABS");
12090 MVT ContainerVT = VT;
12097 if (
Op->getOpcode() == ISD::VP_ABS) {
12098 Mask =
Op->getOperand(1);
12102 VL =
Op->getOperand(2);
12110 DAG.
getUNDEF(ContainerVT), Mask, VL);
12112 DAG.
getUNDEF(ContainerVT), Mask, VL);
12119SDValue RISCVTargetLowering::lowerFixedLengthVectorFCOPYSIGNToRVV(
12122 MVT VT =
Op.getSimpleValueType();
12126 "Can only handle COPYSIGN with matching types.");
12135 Sign, DAG.
getUNDEF(ContainerVT), Mask, VL);
12140SDValue RISCVTargetLowering::lowerFixedLengthVectorSelectToRVV(
12142 MVT VT =
Op.getSimpleValueType();
12145 MVT I1ContainerVT =
12159 Op2, DAG.
getUNDEF(ContainerVT), VL);
12170 MVT VT =
Op.getSimpleValueType();
12175 for (
const SDValue &V :
Op->op_values()) {
12176 assert(!isa<VTSDNode>(V) &&
"Unexpected VTSDNode node!");
12179 if (!
V.getValueType().isVector()) {
12185 assert(useRVVForFixedLengthVectorVT(
V.getSimpleValueType()) &&
12186 "Only fixed length vectors are supported!");
12200 if (
Op->isStrictFPOpcode()) {
12209 DAG.
getNode(NewOpc,
DL, ContainerVT, Ops,
Op->getFlags());
12223 MVT VT =
Op.getSimpleValueType();
12226 MVT ContainerVT = VT;
12232 assert(!isa<VTSDNode>(V) &&
"Unexpected VTSDNode node!");
12235 if (HasPassthruOp) {
12238 if (*MaskIdx == OpIdx.index())
12242 if (
Op.getOpcode() == ISD::VP_MERGE) {
12246 assert(
Op.getOpcode() == ISD::VP_SELECT);
12258 if (!
V.getValueType().isFixedLengthVector()) {
12263 MVT OpVT =
V.getSimpleValueType();
12265 assert(useRVVForFixedLengthVectorVT(OpVT) &&
12266 "Only fixed length vectors are supported!");
12271 return DAG.
getNode(RISCVISDOpc,
DL, VT, Ops,
Op->getFlags());
12281 MVT VT =
Op.getSimpleValueType();
12287 MVT ContainerVT = VT;
12297 DAG.
getUNDEF(ContainerVT), Zero, VL);
12300 Op.getOpcode() == ISD::VP_ZERO_EXTEND ? 1 : -1,
DL, XLenVT);
12302 DAG.
getUNDEF(ContainerVT), SplatValue, VL);
12305 ZeroSplat, DAG.
getUNDEF(ContainerVT), VL);
12314 MVT VT =
Op.getSimpleValueType();
12318 ISD::CondCode Condition = cast<CondCodeSDNode>(
Op.getOperand(2))->get();
12322 MVT ContainerVT = VT;
12332 switch (Condition) {
12400 MVT DstVT =
Op.getSimpleValueType();
12401 MVT SrcVT = Src.getSimpleValueType();
12414 if (DstEltSize >= SrcEltSize) {
12423 if (SrcEltSize == 1) {
12434 ZeroSplat, DAG.
getUNDEF(IntVT), VL);
12435 }
else if (DstEltSize > (2 * SrcEltSize)) {
12439 Src = DAG.
getNode(RISCVISDExtOpc,
DL, IntVT, Src, Mask, VL);
12445 "Wrong input/output vector types");
12448 if (DstEltSize > (2 * SrcEltSize)) {
12464 MVT InterimFVT = DstVT;
12465 if (SrcEltSize > (2 * DstEltSize)) {
12466 assert(SrcEltSize == (4 * DstEltSize) &&
"Unexpected types!");
12473 if (InterimFVT != DstVT) {
12479 "Wrong input/output vector types");
12483 if (DstEltSize == 1) {
12486 assert(SrcEltSize >= 16 &&
"Unexpected FP type!");
12496 DAG.
getUNDEF(InterimIVT), SplatZero, VL);
12506 while (InterimIVT != DstVT) {
12518 MVT VT =
Op.getSimpleValueType();
12527 MVT VT =
Op.getSimpleValueType();
12541 MVT ContainerVT = VT;
12562 SplatZero, DAG.
getUNDEF(PromotedVT), VL);
12565 SplatOne, SplatZero, DAG.
getUNDEF(PromotedVT), VLMax);
12569 TrueVal, FalseVal, FalseVal, VL);
12584RISCVTargetLowering::lowerVPSpliceExperimental(
SDValue Op,
12596 MVT VT =
Op.getSimpleValueType();
12597 MVT ContainerVT = VT;
12607 if (IsMaskVector) {
12618 SplatZeroOp1, DAG.
getUNDEF(ContainerVT), EVL1);
12627 SplatZeroOp2, DAG.
getUNDEF(ContainerVT), EVL2);
12630 int64_t ImmValue = cast<ConstantSDNode>(
Offset)->getSExtValue();
12631 SDValue DownOffset, UpOffset;
12632 if (ImmValue >= 0) {
12646 Op1, DownOffset, Mask, UpOffset);
12650 if (IsMaskVector) {
12654 {Result, DAG.getConstant(0, DL, ContainerVT),
12655 DAG.getCondCode(ISD::SETNE), DAG.getUNDEF(getMaskTypeFor(ContainerVT)),
12670 MVT VT =
Op.getSimpleValueType();
12672 MVT ContainerVT = VT;
12688RISCVTargetLowering::lowerVPReverseExperimental(
SDValue Op,
12691 MVT VT =
Op.getSimpleValueType();
12698 MVT ContainerVT = VT;
12706 MVT GatherVT = ContainerVT;
12710 if (IsMaskVector) {
12721 SplatZero, DAG.
getUNDEF(IndicesVT), EVL);
12727 unsigned MaxVLMAX =
12736 if (MaxVLMAX > 256 && EltSize == 8) {
12764 DAG.
getUNDEF(GatherVT), Result, Diff, Mask, EVL);
12766 if (IsMaskVector) {
12789 DAG.
getUNDEF(IndicesVT), VecLen, EVL);
12791 DAG.
getUNDEF(IndicesVT), Mask, EVL);
12793 DAG.
getUNDEF(GatherVT), Mask, EVL);
12795 if (IsMaskVector) {
12810 MVT VT =
Op.getSimpleValueType();
12812 return lowerVPOp(
Op, DAG);
12819 MVT ContainerVT = VT;
12838 MVT VT =
Op.getSimpleValueType();
12839 MVT ContainerVT = VT;
12845 auto *VPNode = cast<VPStridedLoadSDNode>(
Op);
12851 : Intrinsic::riscv_vlse_mask,
12854 DAG.
getUNDEF(ContainerVT), VPNode->getBasePtr(),
12855 VPNode->getStride()};
12863 Ops.
push_back(VPNode->getVectorLength());
12871 VPNode->getMemoryVT(), VPNode->getMemOperand());
12885 auto *VPNode = cast<VPStridedStoreSDNode>(
Op);
12886 SDValue StoreVal = VPNode->getValue();
12888 MVT ContainerVT = VT;
12899 : Intrinsic::riscv_vsse_mask,
12902 VPNode->getBasePtr(), VPNode->getStride()};
12910 Ops.
push_back(VPNode->getVectorLength());
12913 Ops, VPNode->getMemoryVT(),
12914 VPNode->getMemOperand());
12926 MVT VT =
Op.getSimpleValueType();
12928 const auto *MemSD = cast<MemSDNode>(
Op.getNode());
12929 EVT MemVT = MemSD->getMemoryVT();
12931 SDValue Chain = MemSD->getChain();
12937 if (
auto *VPGN = dyn_cast<VPGatherSDNode>(
Op.getNode())) {
12938 Index = VPGN->getIndex();
12939 Mask = VPGN->getMask();
12941 VL = VPGN->getVectorLength();
12946 auto *MGN = cast<MaskedGatherSDNode>(
Op.getNode());
12947 Index = MGN->getIndex();
12948 Mask = MGN->getMask();
12949 PassThru = MGN->getPassThru();
12953 MVT IndexVT =
Index.getSimpleValueType();
12957 "Unexpected VTs!");
12958 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
12961 "Unexpected extending MGATHER/VP_GATHER");
12967 MVT ContainerVT = VT;
12991 IsUnmasked ? Intrinsic::riscv_vluxei : Intrinsic::riscv_vluxei_mask;
13008 Chain =
Result.getValue(1);
13025 const auto *MemSD = cast<MemSDNode>(
Op.getNode());
13026 EVT MemVT = MemSD->getMemoryVT();
13028 SDValue Chain = MemSD->getChain();
13031 [[maybe_unused]]
bool IsTruncatingStore =
false;
13034 if (
auto *VPSN = dyn_cast<VPScatterSDNode>(
Op.getNode())) {
13035 Index = VPSN->getIndex();
13036 Mask = VPSN->getMask();
13037 Val = VPSN->getValue();
13038 VL = VPSN->getVectorLength();
13040 IsTruncatingStore =
false;
13043 auto *MSN = cast<MaskedScatterSDNode>(
Op.getNode());
13044 Index = MSN->getIndex();
13045 Mask = MSN->getMask();
13046 Val = MSN->getValue();
13047 IsTruncatingStore = MSN->isTruncatingStore();
13051 MVT IndexVT =
Index.getSimpleValueType();
13055 "Unexpected VTs!");
13056 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
13059 assert(!IsTruncatingStore &&
"Unexpected truncating MSCATTER/VP_SCATTER");
13065 MVT ContainerVT = VT;
13089 IsUnmasked ? Intrinsic::riscv_vsoxei : Intrinsic::riscv_vsoxei_mask;
13099 DAG.
getVTList(MVT::Other), Ops, MemVT, MMO);
13115 static const int Table =
13144 static const unsigned Table =
13167 bool isRISCV64 = Subtarget.
is64Bit();
13231 switch (
N->getOpcode()) {
13233 llvm_unreachable(
"Don't know how to custom type legalize this operation!");
13239 "Unexpected custom legalisation");
13240 bool IsStrict =
N->isStrictFPOpcode();
13243 SDValue Op0 = IsStrict ?
N->getOperand(1) :
N->getOperand(0);
13261 Opc,
DL, VTs, Chain, Op0,
13295 std::tie(Result, Chain) =
13296 makeLibCall(DAG, LC,
N->getValueType(0), Op0, CallOptions,
DL, Chain);
13324 Op0.
getValueType() == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
13335 assert(!Subtarget.
is64Bit() &&
"READCYCLECOUNTER/READSTEADYCOUNTER only "
13336 "has custom type legalization on riscv32");
13338 SDValue LoCounter, HiCounter;
13349 N->getOperand(0), LoCounter, HiCounter);
13373 unsigned Size =
N->getSimpleValueType(0).getSizeInBits();
13374 unsigned XLen = Subtarget.
getXLen();
13377 assert(
Size == (XLen * 2) &&
"Unexpected custom legalisation");
13385 if (LHSIsU == RHSIsU)
13402 if (RHSIsU && LHSIsS && !RHSIsS)
13404 else if (LHSIsU && RHSIsS && !LHSIsS)
13414 "Unexpected custom legalisation");
13421 "Unexpected custom legalisation");
13424 if (
N->getOpcode() ==
ISD::SHL && Subtarget.hasStdExtZbs() &&
13450 "Unexpected custom legalisation");
13451 assert((Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb() ||
13452 Subtarget.hasVendorXTHeadBb()) &&
13453 "Unexpected custom legalization");
13454 if (!isa<ConstantSDNode>(
N->getOperand(1)) &&
13455 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()))
13464 "Unexpected custom legalisation");
13478 MVT VT =
N->getSimpleValueType(0);
13479 assert((VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32) &&
13480 Subtarget.
is64Bit() && Subtarget.hasStdExtM() &&
13481 "Unexpected custom legalisation");
13493 if (VT != MVT::i32)
13502 "Unexpected custom legalisation");
13506 if (!isa<ConstantSDNode>(
N->getOperand(1)))
13523 EVT OType =
N->getValueType(1);
13536 "Unexpected custom legalisation");
13553 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1), Res,
13557 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1),
N->getOperand(0),
13575 !Subtarget.hasStdExtZbb() &&
"Unexpected custom legalisation");
13584 "Unexpected custom legalisation");
13590 "Unexpected custom legalisation");
13592 if (Subtarget.hasStdExtZbb()) {
13626 EVT VT =
N->getValueType(0);
13631 if (VT == MVT::i16 &&
13633 (Op0VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
13636 }
else if (VT == MVT::i32 && Op0VT == MVT::f32 && Subtarget.
is64Bit() &&
13641 }
else if (VT == MVT::i64 && Op0VT == MVT::f64 && !Subtarget.
is64Bit() &&
13644 DAG.
getVTList(MVT::i32, MVT::i32), Op0);
13665 MVT VT =
N->getSimpleValueType(0);
13667 assert((VT == MVT::i16 || (VT == MVT::i32 && Subtarget.
is64Bit())) &&
13668 "Unexpected custom legalisation");
13671 "Unexpected extension");
13697 assert(!Subtarget.
is64Bit() &&
N->getValueType(0) == MVT::i64 &&
13699 "Unexpected EXTRACT_VECTOR_ELT legalization");
13702 MVT ContainerVT = VecVT;
13730 DAG.
getUNDEF(ContainerVT), Mask, VL);
13738 unsigned IntNo =
N->getConstantOperandVal(0);
13742 "Don't know how to custom type legalize this intrinsic!");
13743 case Intrinsic::experimental_get_vector_length: {
13748 case Intrinsic::experimental_cttz_elts: {
13754 case Intrinsic::riscv_orc_b:
13755 case Intrinsic::riscv_brev8:
13756 case Intrinsic::riscv_sha256sig0:
13757 case Intrinsic::riscv_sha256sig1:
13758 case Intrinsic::riscv_sha256sum0:
13759 case Intrinsic::riscv_sha256sum1:
13760 case Intrinsic::riscv_sm3p0:
13761 case Intrinsic::riscv_sm3p1: {
13762 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
13782 case Intrinsic::riscv_sm4ks:
13783 case Intrinsic::riscv_sm4ed: {
13791 DAG.
getNode(Opc,
DL, MVT::i64, NewOp0, NewOp1,
N->getOperand(3));
13795 case Intrinsic::riscv_mopr: {
13796 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
13806 case Intrinsic::riscv_moprr: {
13807 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
13819 case Intrinsic::riscv_clmul: {
13820 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
13831 case Intrinsic::riscv_clmulh:
13832 case Intrinsic::riscv_clmulr: {
13833 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
13861 case Intrinsic::riscv_vmv_x_s: {
13862 EVT VT =
N->getValueType(0);
13864 if (VT.
bitsLT(XLenVT)) {
13873 "Unexpected custom legalization");
13911 case ISD::VP_REDUCE_ADD:
13912 case ISD::VP_REDUCE_AND:
13913 case ISD::VP_REDUCE_OR:
13914 case ISD::VP_REDUCE_XOR:
13915 case ISD::VP_REDUCE_SMAX:
13916 case ISD::VP_REDUCE_UMAX:
13917 case ISD::VP_REDUCE_SMIN:
13918 case ISD::VP_REDUCE_UMIN:
13982 const EVT VT =
N->getValueType(0);
13983 const unsigned Opc =
N->getOpcode();
13990 (Opc !=
ISD::FADD || !
N->getFlags().hasAllowReassociation()))
13995 "Inconsistent mappings");
14006 !isa<ConstantSDNode>(
RHS.getOperand(1)))
14009 uint64_t RHSIdx = cast<ConstantSDNode>(
RHS.getOperand(1))->getLimitedValue();
14024 LHS.getOperand(0) == SrcVec && isa<ConstantSDNode>(
LHS.getOperand(1))) {
14026 cast<ConstantSDNode>(
LHS.getOperand(1))->getLimitedValue();
14027 if (0 == std::min(LHSIdx, RHSIdx) && 1 == std::max(LHSIdx, RHSIdx)) {
14031 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
N->getFlags());
14038 if (
LHS.getOpcode() != ReduceOpc)
14053 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
14054 ReduceVec->
getFlags() &
N->getFlags());
14064 auto BinOpToRVVReduce = [](
unsigned Opc) {
14093 auto IsReduction = [&BinOpToRVVReduce](
SDValue V,
unsigned Opc) {
14096 V.getOperand(0).getOpcode() == BinOpToRVVReduce(Opc);
14099 unsigned Opc =
N->getOpcode();
14100 unsigned ReduceIdx;
14101 if (IsReduction(
N->getOperand(0), Opc))
14103 else if (IsReduction(
N->getOperand(1), Opc))
14109 if (Opc ==
ISD::FADD && !
N->getFlags().hasAllowReassociation())
14112 SDValue Extract =
N->getOperand(ReduceIdx);
14144 SDValue NewStart =
N->getOperand(1 - ReduceIdx);
14171 if (!Subtarget.hasStdExtZba())
14175 EVT VT =
N->getValueType(0);
14187 auto *N0C = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
14188 auto *N1C = dyn_cast<ConstantSDNode>(N1->
getOperand(1));
14191 int64_t C0 = N0C->getSExtValue();
14192 int64_t C1 = N1C->getSExtValue();
14193 if (C0 <= 0 || C1 <= 0)
14197 int64_t Bits = std::min(C0, C1);
14198 int64_t Diff = std::abs(C0 - C1);
14199 if (Diff != 1 && Diff != 2 && Diff != 3)
14226 EVT VT =
N->getValueType(0);
14234 if ((!Subtarget.hasStdExtZicond() &&
14235 !Subtarget.hasVendorXVentanaCondOps()) ||
14257 bool SwapSelectOps;
14263 SwapSelectOps =
false;
14264 NonConstantVal = FalseVal;
14266 SwapSelectOps =
true;
14267 NonConstantVal = TrueVal;
14273 FalseVal = DAG.
getNode(
N->getOpcode(),
SDLoc(
N), VT, OtherOp, NonConstantVal);
14321 EVT VT =
N->getValueType(0);
14329 auto *N0C = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
14330 auto *N1C = dyn_cast<ConstantSDNode>(
N->getOperand(1));
14336 if (!N0C->hasOneUse())
14338 int64_t C0 = N0C->getSExtValue();
14339 int64_t C1 = N1C->getSExtValue();
14341 if (C0 == -1 || C0 == 0 || C0 == 1 || isInt<12>(C1))
14344 if ((C1 / C0) != 0 && isInt<12>(C1 / C0) && isInt<12>(C1 % C0) &&
14345 !isInt<12>(C0 * (C1 / C0))) {
14348 }
else if ((C1 / C0 + 1) != 0 && isInt<12>(C1 / C0 + 1) &&
14349 isInt<12>(C1 % C0 - C0) && !isInt<12>(C0 * (C1 / C0 + 1))) {
14352 }
else if ((C1 / C0 - 1) != 0 && isInt<12>(C1 / C0 - 1) &&
14353 isInt<12>(C1 % C0 + C0) && !isInt<12>(C0 * (C1 / C0 - 1))) {
14380 EVT VT =
N->getValueType(0);
14411 unsigned OuterExtend =
14415 OuterExtend,
SDLoc(
N), VT,
14423 EVT VT =
N->getValueType(0);
14471 EVT VT =
N->getValueType(0);
14475 auto *N0C = dyn_cast<ConstantSDNode>(N0);
14481 APInt ImmValMinus1 = N0C->getAPIntValue() - 1;
14491 if (!isIntEqualitySetCC(CCVal) || !SetCCOpVT.
isInteger())
14514 if (!Subtarget.hasStdExtZbb())
14517 EVT VT =
N->getValueType(0);
14519 if (VT != Subtarget.
getXLenVT() && VT != MVT::i32 && VT != MVT::i16)
14528 auto *ShAmtCLeft = dyn_cast<ConstantSDNode>(N0.
getOperand(1));
14531 unsigned ShiftedAmount = 8 - ShAmtCLeft->getZExtValue();
14533 if (ShiftedAmount >= 8)
14537 SDValue RightShiftOperand = N1;
14539 if (ShiftedAmount != 0) {
14542 auto *ShAmtCRight = dyn_cast<ConstantSDNode>(N1.
getOperand(1));
14543 if (!ShAmtCRight || ShAmtCRight->getZExtValue() != ShiftedAmount)
14552 if (LeftShiftOperand != RightShiftOperand)
14556 Mask <<= ShiftedAmount;
14570 EVT VT =
N->getValueType(0);
14601 bool IsAnd =
N->getOpcode() ==
ISD::AND;
14625 EVT VT =
N->getValueType(0);
14649 EVT VT =
N->getValueType(0);
14676 if (CondLHS != True)
14683 if (!CondRHSC || CondRHSC->
getAPIntValue() != (1ULL << ScalarBits))
14695 if (!FalseRHSC || !FalseRHSC->
isZero())
14715 EVT VT =
N->getValueType(0);
14722 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() && VT == MVT::i1 &&
14749 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
14801 EVT VT =
N->getValueType(0);
14847 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
14872 auto *ConstN00 = dyn_cast<ConstantSDNode>(N0.
getOperand(0));
14877 const APInt &Imm = ConstN00->getAPIntValue();
14878 if ((Imm + 1).isSignedIntN(12))
14899 EVT VT =
N->getValueType(0);
14911 const bool HasShlAdd =
14912 Subtarget.hasStdExtZba() || Subtarget.hasVendorXTHeadBa();
14926 for (
uint64_t Divisor : {3, 5, 9}) {
14927 if (MulAmt % Divisor != 0)
14929 uint64_t MulAmt2 = MulAmt / Divisor;
14936 if (
X.getOpcode() ==
ISD::AND && isa<ConstantSDNode>(
X.getOperand(1)) &&
14937 X.getConstantOperandVal(1) == UINT64_C(0xffffffff)) {
14954 if (MulAmt2 == 3 || MulAmt2 == 5 || MulAmt2 == 9) {
14970 if (ScaleShift >= 1 && ScaleShift < 4) {
14971 unsigned ShiftAmt =
Log2_64((MulAmt & (MulAmt - 1)));
14985 for (
uint64_t Divisor : {3, 5, 9}) {
14990 if ((
C >> TZ) == Divisor && (TZ == 1 || TZ == 2 || TZ == 3)) {
15001 if (MulAmt > 2 &&
isPowerOf2_64((MulAmt - 1) & (MulAmt - 2))) {
15003 if (ScaleShift >= 1 && ScaleShift < 4) {
15004 unsigned ShiftAmt =
Log2_64(((MulAmt - 1) & (MulAmt - 2)));
15030 uint64_t MulAmtLowBit = MulAmt & (-MulAmt);
15032 uint64_t ShiftAmt1 = MulAmt + MulAmtLowBit;
15043 for (
uint64_t Divisor : {3, 5, 9}) {
15044 if (MulAmt % Divisor != 0)
15046 uint64_t MulAmt2 = MulAmt / Divisor;
15049 for (
uint64_t Divisor2 : {3, 5, 9}) {
15050 if (MulAmt2 % Divisor2 != 0)
15052 uint64_t MulAmt3 = MulAmt2 / Divisor2;
15075 EVT VT =
N->getValueType(0);
15082 if (
N->getOperand(0).getOpcode() !=
ISD::AND ||
15083 N->getOperand(0).getOperand(0).getOpcode() !=
ISD::SRL)
15096 if (!V1.
isMask(HalfSize) || V2 != (1ULL | 1ULL << HalfSize) ||
15097 V3 != (HalfSize - 1))
15113 EVT VT =
N->getValueType(0);
15121 unsigned AddSubOpc;
15127 auto IsAddSubWith1 = [&](
SDValue V) ->
bool {
15128 AddSubOpc = V->getOpcode();
15130 SDValue Opnd = V->getOperand(1);
15131 MulOper = V->getOperand(0);
15140 if (IsAddSubWith1(N0)) {
15142 return DAG.
getNode(AddSubOpc,
DL, VT, N1, MulVal);
15145 if (IsAddSubWith1(N1)) {
15147 return DAG.
getNode(AddSubOpc,
DL, VT, N0, MulVal);
15162 if (isIndexTypeSigned(IndexType))
15165 if (!
N->hasOneUse())
15168 EVT VT =
N.getValueType();
15207 EVT SrcVT = Src.getValueType();
15211 NewElen = std::max(NewElen, 8U);
15234 EVT VT =
N->getValueType(0);
15237 if (OpVT != MVT::i64 || !Subtarget.
is64Bit())
15241 auto *N1C = dyn_cast<ConstantSDNode>(N1);
15253 if (!isIntEqualitySetCC(
Cond))
15262 const APInt &C1 = N1C->getAPIntValue();
15280 EVT VT =
N->getValueType(0);
15281 EVT SrcVT = cast<VTSDNode>(
N->getOperand(1))->
getVT();
15282 unsigned Opc = Src.getOpcode();
15287 Subtarget.hasStdExtZfhmin())
15289 Src.getOperand(0));
15293 VT == MVT::i64 && !isa<ConstantSDNode>(Src.getOperand(1)) &&
15296 Src.getOperand(1));
15304struct CombineResult;
15306enum ExtKind :
uint8_t { ZExt = 1 << 0, SExt = 1 << 1, FPExt = 1 << 2 };
15333struct NodeExtensionHelper {
15342 bool SupportsFPExt;
15345 bool EnforceOneUse;
15360 return OrigOperand;
15371 unsigned getExtOpc(ExtKind SupportsExt)
const {
15372 switch (SupportsExt) {
15373 case ExtKind::SExt:
15375 case ExtKind::ZExt:
15377 case ExtKind::FPExt:
15388 std::optional<ExtKind> SupportsExt)
const {
15389 if (!SupportsExt.has_value())
15390 return OrigOperand;
15392 MVT NarrowVT = getNarrowType(Root, *SupportsExt);
15396 if (
Source.getValueType() == NarrowVT)
15400 if (
Source.getValueType().getVectorElementType() == MVT::bf16) {
15406 unsigned ExtOpc = getExtOpc(*SupportsExt);
15410 auto [
Mask, VL] = getMaskAndVL(Root, DAG, Subtarget);
15417 return DAG.
getNode(ExtOpc,
DL, NarrowVT, Source, Mask, VL);
15429 DAG.
getUNDEF(NarrowVT), Source, VL);
15442 static MVT getNarrowType(
const SDNode *Root, ExtKind SupportsExt) {
15448 MVT EltVT = SupportsExt == ExtKind::FPExt
15450 :
MVT::getIntegerVT(NarrowSize);
15452 assert((
int)NarrowSize >= (SupportsExt == ExtKind::FPExt ? 16 : 8) &&
15453 "Trying to extend something we can't represent");
15460 static unsigned getSExtOpcode(
unsigned Opcode) {
15483 static unsigned getZExtOpcode(
unsigned Opcode) {
15509 static unsigned getFPExtOpcode(
unsigned Opcode) {
15534 static unsigned getSUOpcode(
unsigned Opcode) {
15536 "SU is only supported for MUL");
15542 static unsigned getWOpcode(
unsigned Opcode, ExtKind SupportsExt) {
15562 using CombineToTry = std::function<std::optional<CombineResult>(
15563 SDNode * ,
const NodeExtensionHelper & ,
15568 bool needToPromoteOtherUsers()
const {
return EnforceOneUse; }
15572 unsigned Opc = OrigOperand.
getOpcode();
15576 "Unexpected Opcode");
15589 unsigned ScalarBits =
Op.getValueSizeInBits();
15591 if (ScalarBits < EltBits) {
15594 !Subtarget.
is64Bit() &&
"Unexpected splat");
15596 SupportsSExt =
true;
15600 SupportsZExt =
true;
15602 EnforceOneUse =
false;
15606 unsigned NarrowSize = EltBits / 2;
15609 if (NarrowSize < 8)
15613 SupportsSExt =
true;
15617 SupportsZExt =
true;
15619 EnforceOneUse =
false;
15622 bool isSupportedFPExtend(
SDNode *Root,
MVT NarrowEltVT,
15629 if (NarrowEltVT == MVT::bf16 && (!Subtarget.hasStdExtZvfbfwma() ||
15639 SupportsZExt =
false;
15640 SupportsSExt =
false;
15641 SupportsFPExt =
false;
15642 EnforceOneUse =
true;
15643 unsigned Opc = OrigOperand.
getOpcode();
15665 SupportsZExt =
true;
15668 SupportsSExt =
true;
15673 if (!isSupportedFPExtend(Root, NarrowEltVT, Subtarget))
15675 SupportsFPExt =
true;
15680 fillUpExtensionSupportForSplat(Root, DAG, Subtarget);
15692 if (!isSupportedFPExtend(Root,
Op.getOperand(0).getSimpleValueType(),
15697 unsigned ScalarBits =
Op.getOperand(0).getValueSizeInBits();
15698 if (NarrowSize != ScalarBits)
15701 SupportsFPExt =
true;
15710 static bool isSupportedRoot(
const SDNode *Root,
15739 Subtarget.hasStdExtZvbb();
15741 return Subtarget.hasStdExtZvbb();
15755 assert(isSupportedRoot(Root, Subtarget) &&
15756 "Trying to build an helper with an "
15757 "unsupported root");
15758 assert(OperandIdx < 2 &&
"Requesting something else than LHS or RHS");
15774 if (OperandIdx == 1) {
15783 EnforceOneUse =
false;
15788 fillUpExtensionSupport(Root, DAG, Subtarget);
15794 static std::pair<SDValue, SDValue>
15797 assert(isSupportedRoot(Root, Subtarget) &&
"Unexpected root");
15816 switch (
N->getOpcode()) {
15858struct CombineResult {
15860 unsigned TargetOpcode;
15862 std::optional<ExtKind> LHSExt;
15863 std::optional<ExtKind> RHSExt;
15867 NodeExtensionHelper
LHS;
15869 NodeExtensionHelper
RHS;
15871 CombineResult(
unsigned TargetOpcode,
SDNode *Root,
15872 const NodeExtensionHelper &
LHS, std::optional<ExtKind> LHSExt,
15873 const NodeExtensionHelper &
RHS, std::optional<ExtKind> RHSExt)
15874 : TargetOpcode(TargetOpcode), LHSExt(LHSExt), RHSExt(RHSExt), Root(Root),
15883 std::tie(Mask, VL) =
15884 NodeExtensionHelper::getMaskAndVL(Root, DAG, Subtarget);
15898 LHS.getOrCreateExtendedOp(Root, DAG, Subtarget, LHSExt),
15899 RHS.getOrCreateExtendedOp(Root, DAG, Subtarget, RHSExt),
15900 Passthru, Mask, VL);
15914static std::optional<CombineResult>
15915canFoldToVWWithSameExtensionImpl(
SDNode *Root,
const NodeExtensionHelper &LHS,
15916 const NodeExtensionHelper &RHS,
15919 if ((AllowExtMask & ExtKind::ZExt) &&
LHS.SupportsZExt &&
RHS.SupportsZExt)
15920 return CombineResult(NodeExtensionHelper::getZExtOpcode(Root->
getOpcode()),
15921 Root, LHS, {ExtKind::ZExt}, RHS,
15923 if ((AllowExtMask & ExtKind::SExt) &&
LHS.SupportsSExt &&
RHS.SupportsSExt)
15924 return CombineResult(NodeExtensionHelper::getSExtOpcode(Root->
getOpcode()),
15925 Root, LHS, {ExtKind::SExt}, RHS,
15927 if ((AllowExtMask & ExtKind::FPExt) &&
LHS.SupportsFPExt &&
RHS.SupportsFPExt)
15928 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
15929 Root, LHS, {ExtKind::FPExt}, RHS,
15931 return std::nullopt;
15940static std::optional<CombineResult>
15941canFoldToVWWithSameExtension(
SDNode *Root,
const NodeExtensionHelper &LHS,
15944 return canFoldToVWWithSameExtensionImpl(
15945 Root, LHS, RHS, ExtKind::ZExt | ExtKind::SExt | ExtKind::FPExt, DAG,
15953static std::optional<CombineResult>
15954canFoldToVW_W(
SDNode *Root,
const NodeExtensionHelper &LHS,
15957 if (
RHS.SupportsFPExt)
15958 return CombineResult(
15959 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::FPExt),
15960 Root, LHS, std::nullopt, RHS, {ExtKind::FPExt});
15967 return CombineResult(
15968 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::ZExt), Root,
15969 LHS, std::nullopt, RHS, {ExtKind::ZExt});
15971 return CombineResult(
15972 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::SExt), Root,
15973 LHS, std::nullopt, RHS, {ExtKind::SExt});
15974 return std::nullopt;
15981static std::optional<CombineResult>
15982canFoldToVWWithSEXT(
SDNode *Root,
const NodeExtensionHelper &LHS,
15985 return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::SExt, DAG,
15993static std::optional<CombineResult>
15994canFoldToVWWithZEXT(
SDNode *Root,
const NodeExtensionHelper &LHS,
15997 return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::ZExt, DAG,
16005static std::optional<CombineResult>
16006canFoldToVWWithFPEXT(
SDNode *Root,
const NodeExtensionHelper &LHS,
16009 return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::FPExt, DAG,
16017static std::optional<CombineResult>
16018canFoldToVW_SU(
SDNode *Root,
const NodeExtensionHelper &LHS,
16022 if (!
LHS.SupportsSExt || !
RHS.SupportsZExt)
16023 return std::nullopt;
16024 return CombineResult(NodeExtensionHelper::getSUOpcode(Root->
getOpcode()),
16025 Root, LHS, {ExtKind::SExt}, RHS,
16030NodeExtensionHelper::getSupportedFoldings(
const SDNode *Root) {
16041 Strategies.
push_back(canFoldToVWWithSameExtension);
16050 Strategies.
push_back(canFoldToVWWithSameExtension);
16055 Strategies.
push_back(canFoldToVWWithSameExtension);
16062 Strategies.
push_back(canFoldToVWWithZEXT);
16067 Strategies.
push_back(canFoldToVWWithSEXT);
16072 Strategies.
push_back(canFoldToVWWithZEXT);
16077 Strategies.
push_back(canFoldToVWWithFPEXT);
16106 if (!NodeExtensionHelper::isSupportedRoot(
N, Subtarget))
16112 Inserted.insert(
N);
16115 while (!Worklist.
empty()) {
16118 NodeExtensionHelper
LHS(Root, 0, DAG, Subtarget);
16119 NodeExtensionHelper
RHS(Root, 1, DAG, Subtarget);
16120 auto AppendUsersIfNeeded = [&Worklist, &Subtarget,
16121 &Inserted](
const NodeExtensionHelper &
Op) {
16122 if (
Op.needToPromoteOtherUsers()) {
16125 if (!NodeExtensionHelper::isSupportedRoot(TheUser, Subtarget))
16130 if (Inserted.insert(TheUser).second)
16143 NodeExtensionHelper::getSupportedFoldings(Root);
16145 assert(!FoldingStrategies.
empty() &&
"Nothing to be folded");
16146 bool Matched =
false;
16147 for (
int Attempt = 0;
16148 (Attempt != 1 + NodeExtensionHelper::isCommutative(Root)) && !Matched;
16151 for (NodeExtensionHelper::CombineToTry FoldingStrategy :
16152 FoldingStrategies) {
16153 std::optional<CombineResult> Res =
16154 FoldingStrategy(Root,
LHS,
RHS, DAG, Subtarget);
16161 if (Res->LHSExt.has_value())
16162 if (!AppendUsersIfNeeded(
LHS))
16164 if (Res->RHSExt.has_value())
16165 if (!AppendUsersIfNeeded(
RHS))
16177 SDValue InputRootReplacement;
16184 for (CombineResult Res : CombinesToApply) {
16185 SDValue NewValue = Res.materialize(DAG, Subtarget);
16186 if (!InputRootReplacement) {
16188 "First element is expected to be the current node");
16189 InputRootReplacement = NewValue;
16194 for (std::pair<SDValue, SDValue> OldNewValues : ValuesToReplace) {
16198 return InputRootReplacement;
16205 unsigned Opc =
N->getOpcode();
16210 SDValue MergeOp =
N->getOperand(1);
16211 unsigned MergeOpc = MergeOp.
getOpcode();
16222 SDValue Passthru =
N->getOperand(2);
16236 Z = Z.getOperand(1);
16242 {Y, X, Y, MergeOp->getOperand(0), N->getOperand(4)},
16249 [[maybe_unused]]
unsigned Opc =
N->getOpcode();
16278 EVT NewMemVT = (MemVT == MVT::i32) ? MVT::i64 : MVT::i128;
16284 auto Ext = cast<LoadSDNode>(LSNode1)->getExtensionType();
16286 if (MemVT == MVT::i32)
16292 Opcode,
SDLoc(LSNode1), DAG.
getVTList({XLenVT, XLenVT, MVT::Other}),
16327 if (!Subtarget.hasVendorXTHeadMemPair())
16339 auto ExtractBaseAndOffset = [](
SDValue Ptr) -> std::pair<SDValue, uint64_t> {
16341 if (
auto *C1 = dyn_cast<ConstantSDNode>(
Ptr->getOperand(1)))
16342 return {
Ptr->getOperand(0), C1->getZExtValue()};
16346 auto [Base1, Offset1] = ExtractBaseAndOffset(LSNode1->
getOperand(OpNum));
16367 auto [Base2, Offset2] = ExtractBaseAndOffset(LSNode2->
getOperand(OpNum));
16370 if (Base1 != Base2)
16374 bool Valid =
false;
16375 if (MemVT == MVT::i32) {
16377 if ((Offset1 + 4 == Offset2) && isShiftedUInt<2, 3>(Offset1))
16379 }
else if (MemVT == MVT::i64) {
16381 if ((Offset1 + 8 == Offset2) && isShiftedUInt<2, 4>(Offset1))
16415 if (Src->isStrictFPOpcode())
16423 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
16433 EVT VT =
N->getValueType(0);
16436 MVT SrcVT = Src.getSimpleValueType();
16437 MVT SrcContainerVT = SrcVT;
16439 SDValue XVal = Src.getOperand(0);
16466 FpToInt = DAG.
getNode(Opc,
DL, ContainerVT, XVal, Mask, VL);
16470 FpToInt = DAG.
getNode(Opc,
DL, ContainerVT, XVal, Mask,
16483 if (VT != MVT::i32 && VT != XLenVT)
16513 EVT DstVT =
N->getValueType(0);
16514 if (DstVT != XLenVT)
16520 if (Src->isStrictFPOpcode())
16528 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
16531 EVT SatVT = cast<VTSDNode>(
N->getOperand(1))->getVT();
16540 if (SatVT == DstVT)
16542 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
16548 Src = Src.getOperand(0);
16569 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected extension");
16575 EVT VT =
N->getValueType(0);
16590 auto *VPLoad = dyn_cast<VPLoadSDNode>(
N->getOperand(0));
16594 EVT LoadVT = VPLoad->getValueType(0);
16598 N->getOperand(2) != VPLoad->getVectorLength() ||
16599 !
N->getOperand(0).hasOneUse())
16606 SDValue LoadMask = VPLoad->getMask();
16611 if (LoadMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
16613 LoadMask.
getOperand(2) != VPLoad->getVectorLength())
16621 SDValue NumElem = VPLoad->getVectorLength();
16622 uint64_t ElemWidthByte = VPLoad->getValueType(0).getScalarSizeInBits() / 8;
16634 PtrInfo, VPLoad->getMemOperand()->getFlags(),
16638 LoadVT,
DL, VPLoad->getChain(),
Base, Stride, LoadMask,
16639 VPLoad->getVectorLength(), MMO, VPLoad->isExpandingLoad());
16651 auto *VPStore = cast<VPStoreSDNode>(
N);
16653 if (VPStore->getValue().getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE)
16656 SDValue VPReverse = VPStore->getValue();
16662 VPStore->getVectorLength() != VPReverse.
getOperand(2) ||
16666 SDValue StoreMask = VPStore->getMask();
16671 if (StoreMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
16673 StoreMask.
getOperand(2) != VPStore->getVectorLength())
16681 SDValue NumElem = VPStore->getVectorLength();
16695 PtrInfo, VPStore->getMemOperand()->getFlags(),
16700 VPStore->getOffset(), Stride, StoreMask, VPStore->getVectorLength(),
16701 VPStore->getMemoryVT(), MMO, VPStore->getAddressingMode(),
16702 VPStore->isTruncatingStore(), VPStore->isCompressingStore());
16714 EVT VT =
N->getValueType(0);
16726 if (In.getOpcode() != ISD::VP_SRL || In.getOperand(2) != Mask ||
16727 In.getOperand(3) != VL)
16736 if (
LHS.getOpcode() != ISD::VP_ADD ||
LHS.getOperand(2) != Mask ||
16737 LHS.getOperand(3) != VL)
16744 if (V.getOpcode() != ISD::VP_ADD || V.getOperand(2) != Mask ||
16745 V.getOperand(3) != VL)
16757 if (!FindAdd(LHS0, LHS1) && !FindAdd(LHS1, LHS0))
16771 if (
Op.getOpcode() != ISD::VP_ZERO_EXTEND ||
Op.getOperand(1) != Mask ||
16772 Op.getOperand(2) != VL)
16782 Operands[0].getOperand(0), Mask, VL);
16784 Operands[1].getOperand(0), Mask, VL);
16789 {NewOp0, NewOp1, DAG.
getUNDEF(VT), Mask, VL});
16838 unsigned Offset = IsStrict ? 1 : 0;
16845 auto invertIfNegative = [&Mask, &VL](
SDValue &V) {
16847 V.getOperand(2) == VL) {
16849 V = V.getOperand(0);
16856 bool NegA = invertIfNegative(
A);
16857 bool NegB = invertIfNegative(
B);
16858 bool NegC = invertIfNegative(
C);
16861 if (!NegA && !NegB && !NegC)
16867 {N->getOperand(0), A, B, C, Mask, VL});
16891 EVT VT =
N->getValueType(0);
16896 if (!isa<ConstantSDNode>(
N->getOperand(1)))
16898 uint64_t ShAmt =
N->getConstantOperandVal(1);
16906 cast<VTSDNode>(N0.
getOperand(1))->getVT().getSizeInBits();
16911 if (LShAmt < ExtSize) {
16924 if (ShAmt > 32 || VT != MVT::i64)
16940 AddC = dyn_cast<ConstantSDNode>(N0.
getOperand(IsAdd ? 1 : 0));
16953 !isa<ConstantSDNode>(U->getOperand(1)) ||
16954 U->getConstantOperandVal(1) > 32)
17009 if (!
Cond.hasOneUse())
17028 EVT VT =
Cond.getValueType();
17073 LHS =
LHS.getOperand(0);
17083 LHS.getOperand(0).getValueType() == Subtarget.
getXLenVT()) {
17087 CCVal = cast<CondCodeSDNode>(
LHS.getOperand(2))->get();
17091 RHS =
LHS.getOperand(1);
17092 LHS =
LHS.getOperand(0);
17101 RHS =
LHS.getOperand(1);
17102 LHS =
LHS.getOperand(0);
17118 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
17159 bool Commutative =
true;
17160 unsigned Opc = TrueVal.getOpcode();
17168 Commutative =
false;
17176 if (!TrueVal.hasOneUse() || isa<ConstantSDNode>(FalseVal))
17180 if (FalseVal == TrueVal.getOperand(0))
17182 else if (Commutative && FalseVal == TrueVal.getOperand(1))
17187 EVT VT =
N->getValueType(0);
17189 SDValue OtherOp = TrueVal.getOperand(1 - OpToFold);
17195 assert(IdentityOperand &&
"No identity operand!");
17200 DAG.
getSelect(
DL, OtherOpVT,
N->getOperand(0), OtherOp, IdentityOperand);
17201 return DAG.
getNode(TrueVal.getOpcode(),
DL, VT, FalseVal, NewSel);
17222 CountZeroes =
N->getOperand(2);
17223 ValOnZero =
N->getOperand(1);
17225 CountZeroes =
N->getOperand(1);
17226 ValOnZero =
N->getOperand(2);
17245 if (
Cond->getOperand(0) != CountZeroesArgument)
17261 CountZeroes, BitWidthMinusOne);
17271 EVT VT =
N->getValueType(0);
17272 EVT CondVT =
Cond.getValueType();
17280 (Subtarget.hasStdExtZicond() || Subtarget.hasVendorXVentanaCondOps())) {
17286 const APInt &MaskVal =
LHS.getConstantOperandAPInt(1);
17297 if (!TrueVal.hasOneUse() || !FalseVal.hasOneUse())
17301 if (TrueVal.getOpcode() ==
ISD::SUB && FalseVal.getOpcode() ==
ISD::ADD) {
17309 SDValue A = FalseVal.getOperand(0);
17310 SDValue B = FalseVal.getOperand(1);
17312 return ((TrueVal.getOperand(0) ==
A && TrueVal.getOperand(1) ==
B) ||
17313 (TrueVal.getOperand(1) ==
A && TrueVal.getOperand(0) ==
B));
17321 EVT VT =
N->getValueType(0);
17323 SDValue TrueVal =
N->getOperand(1);
17324 SDValue FalseVal =
N->getOperand(2);
17330 SDValue Sub = SwapCC ? TrueVal : FalseVal;
17354 SDValue TrueVal =
N->getOperand(1);
17355 SDValue FalseVal =
N->getOperand(2);
17370 EVT VT =
N->getValueType(0);
17377 const unsigned Opcode =
N->op_begin()->getNode()->getOpcode();
17392 if (
Op.isUndef()) {
17405 if (
Op.getOpcode() != Opcode || !
Op.hasOneUse())
17409 if (!isa<ConstantSDNode>(
Op.getOperand(1)) &&
17410 !isa<ConstantFPSDNode>(
Op.getOperand(1)))
17414 if (
Op.getOperand(0).getValueType() !=
Op.getOperand(1).getValueType())
17442 const unsigned InVecOpcode = InVec->
getOpcode();
17452 if (!isa<ConstantSDNode>(InValRHS) && !isa<ConstantFPSDNode>(InValRHS))
17459 InVecLHS, InValLHS, EltNo);
17461 InVecRHS, InValRHS, EltNo);
17470 auto *IndexC = dyn_cast<ConstantSDNode>(EltNo);
17473 unsigned Elt = IndexC->getZExtValue();
17481 unsigned ConcatOpIdx = Elt / ConcatNumElts;
17484 ConcatOp, InVal, NewIdx);
17488 ConcatOps[ConcatOpIdx] = ConcatOp;
17500 EVT VT =
N->getValueType(0);
17510 auto *BaseLd = dyn_cast<LoadSDNode>(
N->getOperand(0));
17512 !
SDValue(BaseLd, 0).hasOneUse())
17515 EVT BaseLdVT = BaseLd->getValueType(0);
17522 auto *Ld = dyn_cast<LoadSDNode>(
Op);
17523 if (!Ld || !Ld->isSimple() || !
Op.hasOneUse() ||
17525 Ld->getValueType(0) != BaseLdVT)
17534 using PtrDiff = std::pair<std::variant<int64_t, SDValue>,
bool>;
17536 LoadSDNode *Ld2) -> std::optional<PtrDiff> {
17541 if (BIO1.equalBaseIndex(BIO2, DAG))
17546 SDValue P2 = Ld2->getBasePtr();
17549 if (P1.getOpcode() ==
ISD::ADD && P1.getOperand(0) == P2)
17550 return {{P1.getOperand(1),
true}};
17552 return std::nullopt;
17556 auto BaseDiff = GetPtrDiff(Lds[0], Lds[1]);
17561 for (
auto *It = Lds.
begin() + 1; It != Lds.
end() - 1; It++)
17562 if (GetPtrDiff(*It, *std::next(It)) != BaseDiff)
17570 unsigned WideScalarBitWidth =
17583 auto [StrideVariant, MustNegateStride] = *BaseDiff;
17585 std::holds_alternative<SDValue>(StrideVariant)
17586 ? std::get<SDValue>(StrideVariant)
17589 if (MustNegateStride)
17597 if (
auto *ConstStride = dyn_cast<ConstantSDNode>(Stride);
17598 ConstStride && ConstStride->getSExtValue() >= 0)
17602 ConstStride->getSExtValue() * (
N->getNumOperands() - 1);
17608 BaseLd->getPointerInfo(), BaseLd->getMemOperand()->getFlags(), MemSize,
17612 WideVecVT,
DL, BaseLd->getChain(), BaseLd->getBasePtr(), Stride,
17626 EVT VT =
N->getValueType(0);
17638 SDValue Sub = SwapCC ? V1 : V2;
17643 for (
int MaskIndex : Mask) {
17644 bool SelectMaskVal = (MaskIndex < (int)NumElts);
17647 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
17685 if (
N->getValueType(0).isFixedLengthVector())
17688 SDValue Addend =
N->getOperand(0);
17692 SDValue AddPassthruOp =
N->getOperand(2);
17693 if (!AddPassthruOp.
isUndef())
17697 auto IsVWMulOpc = [](
unsigned Opc) {
17716 if (!MulPassthruOp.
isUndef())
17726 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
17727 }(
N, DAG, Subtarget);
17732 if (AddMask != MulMask || AddVL != MulVL)
17737 "Unexpected opcode after VWMACC_VL");
17739 "Unexpected opcode after VWMACC_VL!");
17741 "Unexpected opcode after VWMUL_VL!");
17743 "Unexpected opcode after VWMUL_VL!");
17746 EVT VT =
N->getValueType(0);
17762 const EVT IndexVT = Index.getValueType();
17766 if (!isIndexTypeSigned(IndexType))
17798 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
17801 if (Index->getOperand(i)->isUndef())
17803 uint64_t C = Index->getConstantOperandVal(i);
17804 if (
C % ElementSize != 0)
17806 C =
C / ElementSize;
17810 ActiveLanes.
set(
C);
17812 return ActiveLanes.
all();
17830 if (NumElems % 2 != 0)
17834 const unsigned WiderElementSize = ElementSize * 2;
17835 if (WiderElementSize > ST.getELen()/8)
17838 if (!ST.enableUnalignedVectorMem() && BaseAlign < WiderElementSize)
17841 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
17844 if (Index->getOperand(i)->isUndef())
17848 uint64_t C = Index->getConstantOperandVal(i);
17850 if (
C % WiderElementSize != 0)
17855 if (
C !=
Last + ElementSize)
17872 (isa<RegisterSDNode>(VL) &&
17873 cast<RegisterSDNode>(VL)->getReg() == RISCV::X0);
17875 Mask.getOperand(0) != VL)
17878 auto IsTruncNode = [&](
SDValue V) {
17880 V.getOperand(1) == Mask && V.getOperand(2) == VL;
17887 while (IsTruncNode(
Op)) {
17888 if (!
Op.hasOneUse())
17890 Op =
Op.getOperand(0);
17925 MVT VT =
N->getSimpleValueType(0);
17930 auto MatchMinMax = [&VL, &Mask](
SDValue V,
unsigned Opc,
unsigned OpcVL,
17932 if (V.getOpcode() != Opc &&
17933 !(V.getOpcode() == OpcVL && V.getOperand(2).isUndef() &&
17934 V.getOperand(3) == Mask && V.getOperand(4) == VL))
17942 Op.getOperand(1).getValueType().isFixedLengthVector() &&
17944 Op.getOperand(1).getOperand(0).getValueType() ==
Op.getValueType() &&
17946 Op =
Op.getOperand(1).getOperand(0);
17949 return V.getOperand(0);
17952 Op.getOperand(2) == VL) {
17953 if (
auto *Op1 = dyn_cast<ConstantSDNode>(
Op.getOperand(1))) {
17955 Op1->getAPIntValue().sextOrTrunc(
Op.getScalarValueSizeInBits());
17956 return V.getOperand(0);
17965 auto DetectUSatPattern = [&](
SDValue V) {
17990 V.getOperand(1), DAG.
getUNDEF(V.getValueType()),
17996 auto DetectSSatPattern = [&](
SDValue V) {
17998 unsigned NumSrcBits = V.getScalarValueSizeInBits();
18006 if (HiC == SignedMax && LoC == SignedMin)
18012 if (HiC == SignedMax && LoC == SignedMin)
18022 Src.getOperand(1) == Mask && Src.getOperand(2) == VL &&
18024 Src = Src.getOperand(0);
18028 if ((Val = DetectUSatPattern(Src)))
18030 else if ((Val = DetectSSatPattern(Src)))
18040 Val = DAG.
getNode(ClipOpc,
DL, ValVT, Val, Mask, VL);
18041 }
while (ValVT != VT);
18055 EVT VT =
N->getValueType(0);
18063 Src = Src.getOperand(0);
18068 Src = Src.getOperand(0);
18069 EVT SrcEVT = Src.getValueType();
18109 switch (
LHS.getOpcode()) {
18129 ShAmtInt =
RHS.getConstantOperandVal(1);
18142 if (ShAmtInt >= NarrowBits)
18144 MVT VT =
N->getSimpleValueType(0);
18151 switch (
N->getOpcode()) {
18157 Passthru =
N->getOperand(2);
18158 Mask =
N->getOperand(3);
18159 VL =
N->getOperand(4);
18164 return DAG.
getNode(Opcode,
DL, VT, NarrowOp,
18166 Passthru, Mask, VL);
18178 auto SimplifyDemandedLowBitsHelper = [&](
unsigned OpNo,
unsigned LowBits) {
18189 switch (
N->getOpcode()) {
18209 APInt V =
C->getValueAPF().bitcastToAPInt();
18244 if (SimplifyDemandedLowBitsHelper(0, 32) ||
18245 SimplifyDemandedLowBitsHelper(1, 5))
18253 if (SimplifyDemandedLowBitsHelper(0, 32))
18270 MVT VT =
N->getSimpleValueType(0);
18273 if (
auto *CFP = dyn_cast<ConstantFPSDNode>(Op0)) {
18286 "Unexpected value type!");
18291 cast<LoadSDNode>(Op0)->isSimple()) {
18293 auto *LN0 = cast<LoadSDNode>(Op0);
18296 LN0->getBasePtr(), IVT, LN0->getMemOperand());
18320 EVT VT =
N->getValueType(0);
18373 if (!
C || !
C->getValueAPF().isExactlyValue(+1.0))
18375 EVT VT =
N->getValueType(0);
18404 if (
N->getValueType(0) == MVT::i64 && Subtarget.
is64Bit()) {
18409 Src.getOperand(0));
18414 Src.getOperand(0), Src.getOperand(1));
18426 case ISD::VP_TRUNCATE:
18439 unsigned Opc =
N->getOpcode();
18454 return DAG.
getNode(InvOpc,
SDLoc(
N),
N->getValueType(0), Val, NewCond);
18464 N->getValueType(0), Val,
Cond.getOperand(0));
18475 SDValue FalseV =
N->getOperand(4);
18477 EVT VT =
N->getValueType(0);
18480 if (TrueV == FalseV)
18485 if (!Subtarget.hasShortForwardBranchOpt() && isa<ConstantSDNode>(TrueV) &&
18491 int64_t TrueSImm = cast<ConstantSDNode>(TrueV)->getSExtValue();
18492 int64_t FalseSImm = cast<ConstantSDNode>(FalseV)->getSExtValue();
18495 if (isInt<12>(TrueSImm) && isInt<12>(FalseSImm) &&
18496 isInt<12>(TrueSImm - FalseSImm)) {
18512 {LHS, RHS, CC, TrueV, FalseV});
18579 N->getOperand(0),
LHS,
RHS,
CC,
N->getOperand(4));
18592 EVT VT =
N->getValueType(0);
18616 const auto *MGN = cast<MaskedGatherSDNode>(
N);
18617 const EVT VT =
N->getValueType(0);
18618 SDValue Index = MGN->getIndex();
18619 SDValue ScaleOp = MGN->getScale();
18621 assert(!MGN->isIndexScaled() &&
18622 "Scaled gather/scatter should not be formed");
18627 N->getVTList(), MGN->getMemoryVT(),
DL,
18628 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
18629 MGN->getBasePtr(), Index, ScaleOp},
18630 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
18634 N->getVTList(), MGN->getMemoryVT(),
DL,
18635 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
18636 MGN->getBasePtr(), Index, ScaleOp},
18637 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
18643 if (std::optional<VIDSequence> SimpleVID =
18645 SimpleVID && SimpleVID->StepDenominator == 1) {
18646 const int64_t StepNumerator = SimpleVID->StepNumerator;
18647 const int64_t Addend = SimpleVID->Addend;
18654 assert(MGN->getBasePtr()->getValueType(0) == PtrVT);
18662 VT,
DL, MGN->getChain(), BasePtr,
18664 EVL, MGN->getMemOperand());
18666 StridedLoad, MGN->getPassThru(), EVL);
18676 MGN->getBasePtr(), DAG.
getUNDEF(XLenVT),
18678 MGN->getMemoryVT(), MGN->getMemOperand(),
18687 MGN->getMemOperand()->getBaseAlign(), Subtarget)) {
18689 for (
unsigned i = 0; i < Index->getNumOperands(); i += 2)
18690 NewIndices.
push_back(Index.getOperand(i));
18691 EVT IndexVT = Index.getValueType()
18692 .getHalfNumVectorElementsVT(*DAG.
getContext());
18698 assert(EltCnt.isKnownEven() &&
"Splitting vector, but not in half!");
18700 EltCnt.divideCoefficientBy(2));
18703 EltCnt.divideCoefficientBy(2));
18708 {MGN->getChain(), Passthru, Mask, MGN->getBasePtr(),
18717 const auto *MSN = cast<MaskedScatterSDNode>(
N);
18718 SDValue Index = MSN->getIndex();
18719 SDValue ScaleOp = MSN->getScale();
18721 assert(!MSN->isIndexScaled() &&
18722 "Scaled gather/scatter should not be formed");
18727 N->getVTList(), MSN->getMemoryVT(),
DL,
18728 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
18730 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
18734 N->getVTList(), MSN->getMemoryVT(),
DL,
18735 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
18737 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
18739 EVT VT = MSN->getValue()->getValueType(0);
18741 if (!MSN->isTruncatingStore() &&
18745 return DAG.
getMaskedStore(MSN->getChain(),
DL, Shuffle, MSN->getBasePtr(),
18746 DAG.
getUNDEF(XLenVT), MSN->getMask(),
18747 MSN->getMemoryVT(), MSN->getMemOperand(),
18752 case ISD::VP_GATHER: {
18753 const auto *VPGN = cast<VPGatherSDNode>(
N);
18754 SDValue Index = VPGN->getIndex();
18755 SDValue ScaleOp = VPGN->getScale();
18757 assert(!VPGN->isIndexScaled() &&
18758 "Scaled gather/scatter should not be formed");
18763 {VPGN->getChain(), VPGN->getBasePtr(), Index,
18764 ScaleOp, VPGN->getMask(),
18765 VPGN->getVectorLength()},
18766 VPGN->getMemOperand(), IndexType);
18770 {VPGN->getChain(), VPGN->getBasePtr(), Index,
18771 ScaleOp, VPGN->getMask(),
18772 VPGN->getVectorLength()},
18773 VPGN->getMemOperand(), IndexType);
18777 case ISD::VP_SCATTER: {
18778 const auto *VPSN = cast<VPScatterSDNode>(
N);
18779 SDValue Index = VPSN->getIndex();
18780 SDValue ScaleOp = VPSN->getScale();
18782 assert(!VPSN->isIndexScaled() &&
18783 "Scaled gather/scatter should not be formed");
18788 {VPSN->getChain(), VPSN->getValue(),
18789 VPSN->getBasePtr(), Index, ScaleOp,
18790 VPSN->getMask(), VPSN->getVectorLength()},
18791 VPSN->getMemOperand(), IndexType);
18795 {VPSN->getChain(), VPSN->getValue(),
18796 VPSN->getBasePtr(), Index, ScaleOp,
18797 VPSN->getMask(), VPSN->getVectorLength()},
18798 VPSN->getMemOperand(), IndexType);
18812 EVT VT =
N->getValueType(0);
18815 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt,
18816 N->getOperand(2),
N->getOperand(3),
N->getOperand(4));
18834 EVT VT =
N->getValueType(0);
18838 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt);
18878 auto *Store = cast<StoreSDNode>(
N);
18879 SDValue Chain = Store->getChain();
18880 EVT MemVT = Store->getMemoryVT();
18881 SDValue Val = Store->getValue();
18884 bool IsScalarizable =
18886 Store->isSimple() &&
18916 NewVT, *Store->getMemOperand())) {
18918 return DAG.
getStore(Chain,
DL, NewV, Store->getBasePtr(),
18919 Store->getPointerInfo(), Store->getOriginalAlign(),
18920 Store->getMemOperand()->getFlags());
18928 if (
auto *L = dyn_cast<LoadSDNode>(Val);
18930 L->hasNUsesOfValue(1, 0) && L->hasNUsesOfValue(1, 1) &&
18932 L->getMemoryVT() == MemVT) {
18935 NewVT, *Store->getMemOperand()) &&
18937 NewVT, *L->getMemOperand())) {
18939 L->getPointerInfo(), L->getOriginalAlign(),
18940 L->getMemOperand()->getFlags());
18941 return DAG.
getStore(Chain,
DL, NewL, Store->getBasePtr(),
18942 Store->getPointerInfo(), Store->getOriginalAlign(),
18943 Store->getMemOperand()->getFlags());
18955 MVT VecVT = Src.getSimpleValueType();
18962 Store->getChain(),
DL, Src, Store->getBasePtr(), Store->getOffset(),
18965 Store->getMemOperand(), Store->getAddressingMode(),
18966 Store->isTruncatingStore(),
false);
18973 EVT VT =
N->getValueType(0);
18999 const MVT VT =
N->getSimpleValueType(0);
19000 SDValue Passthru =
N->getOperand(0);
19001 SDValue Scalar =
N->getOperand(1);
19010 const MVT VT =
N->getSimpleValueType(0);
19011 SDValue Passthru =
N->getOperand(0);
19012 SDValue Scalar =
N->getOperand(1);
19017 unsigned ScalarSize = Scalar.getValueSizeInBits();
19019 if (ScalarSize > EltWidth && Passthru.
isUndef())
19020 if (SimplifyDemandedLowBitsHelper(1, EltWidth))
19027 (!Const || Const->isZero() ||
19028 !Const->getAPIntValue().sextOrTrunc(EltWidth).isSignedIntN(5)))
19038 if (
N->getOperand(0).isUndef() &&
19041 Src.getOperand(0).getValueType().isScalableVector()) {
19042 EVT VT =
N->getValueType(0);
19043 EVT SrcVT = Src.getOperand(0).getValueType();
19047 return Src.getOperand(0);
19053 const MVT VT =
N->getSimpleValueType(0);
19054 SDValue Passthru =
N->getOperand(0);
19055 SDValue Scalar =
N->getOperand(1);
19059 Scalar.getOperand(0).getValueType() ==
N->getValueType(0))
19060 return Scalar.getOperand(0);
19069 DAG.
getNode(
N->getOpcode(),
DL, M1VT, M1Passthru, Scalar, VL);
19079 Const && !Const->isZero() && isInt<5>(Const->getSExtValue()) &&
19087 MVT VecVT =
N->getOperand(0).getSimpleValueType();
19089 if (M1VT.
bitsLT(VecVT)) {
19100 unsigned IntNo =
N->getConstantOperandVal(IntOpNo);
19105 case Intrinsic::riscv_vcpop:
19106 case Intrinsic::riscv_vcpop_mask:
19107 case Intrinsic::riscv_vfirst:
19108 case Intrinsic::riscv_vfirst_mask: {
19110 if (IntNo == Intrinsic::riscv_vcpop_mask ||
19111 IntNo == Intrinsic::riscv_vfirst_mask)
19112 VL =
N->getOperand(3);
19117 EVT VT =
N->getValueType(0);
19118 if (IntNo == Intrinsic::riscv_vfirst ||
19119 IntNo == Intrinsic::riscv_vfirst_mask)
19125 case ISD::EXPERIMENTAL_VP_REVERSE:
19127 case ISD::VP_STORE:
19132 EVT VT =
N->getValueType(0);
19143 for (
unsigned i = 0; i < NF; ++i)
19150 if ((SrcVT == MVT::v1i1 || SrcVT == MVT::v2i1 || SrcVT == MVT::v4i1) &&
19173 EVT XVT,
unsigned KeptBits)
const {
19178 if (XVT != MVT::i32 && XVT != MVT::i64)
19182 if (KeptBits == 32 || KeptBits == 64)
19186 return Subtarget.hasStdExtZbb() &&
19187 ((KeptBits == 8 && XVT == MVT::i64 && !Subtarget.
is64Bit()) ||
19195 "Expected shift op");
19213 if (!isa<StoreSDNode>(
Use) && !isa<LoadSDNode>(
Use))
19222 return isUsedByLdSt(N0.
getNode(),
N);
19224 auto *C1 = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
19225 auto *C2 = dyn_cast<ConstantSDNode>(
N->getOperand(1));
19228 if (Subtarget.hasStdExtZba() && C2 && C2->getZExtValue() >= 1 &&
19229 C2->getZExtValue() <= 3 &&
N->hasOneUse() &&
19230 N->user_begin()->getOpcode() ==
ISD::ADD &&
19231 !isUsedByLdSt(*
N->user_begin(),
nullptr) &&
19232 !isa<ConstantSDNode>(
N->user_begin()->getOperand(1)))
19236 const APInt &C1Int = C1->getAPIntValue();
19237 APInt ShiftedC1Int = C1Int << C2->getAPIntValue();
19263 if (C1Cost < ShiftedC1Cost)
19286 EVT VT =
Op.getValueType();
19290 unsigned Opcode =
Op.getOpcode();
19298 const APInt &Mask =
C->getAPIntValue();
19307 auto IsLegalMask = [ShrunkMask, ExpandedMask](
const APInt &Mask) ->
bool {
19308 return ShrunkMask.
isSubsetOf(Mask) && Mask.isSubsetOf(ExpandedMask);
19310 auto UseMask = [Mask,
Op, &TLO](
const APInt &NewMask) ->
bool {
19311 if (NewMask == Mask)
19316 Op.getOperand(0), NewC);
19329 APInt NewMask =
APInt(Mask.getBitWidth(), 0xffff);
19330 if (IsLegalMask(NewMask))
19331 return UseMask(NewMask);
19334 if (VT == MVT::i64) {
19336 if (IsLegalMask(NewMask))
19337 return UseMask(NewMask);
19352 APInt NewMask = ShrunkMask;
19353 if (MinSignedBits <= 12)
19355 else if (!
C->isOpaque() && MinSignedBits <= 32 && !ShrunkMask.
isSignedIntN(32))
19361 assert(IsLegalMask(NewMask));
19362 return UseMask(NewMask);
19366 static const uint64_t GREVMasks[] = {
19367 0x5555555555555555ULL, 0x3333333333333333ULL, 0x0F0F0F0F0F0F0F0FULL,
19368 0x00FF00FF00FF00FFULL, 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL};
19370 for (
unsigned Stage = 0; Stage != 6; ++Stage) {
19371 unsigned Shift = 1 << Stage;
19372 if (ShAmt & Shift) {
19374 uint64_t Res = ((x & Mask) << Shift) | ((x >> Shift) & Mask);
19386 const APInt &DemandedElts,
19388 unsigned Depth)
const {
19390 unsigned Opc =
Op.getOpcode();
19395 "Should use MaskedValueIsZero if you don't know whether Op"
19396 " is a target node!");
19479 assert(MinVLenB > 0 &&
"READ_VLENB without vector extension enabled?");
19482 if (MaxVLenB == MinVLenB)
19499 case Intrinsic::riscv_vsetvli:
19500 case Intrinsic::riscv_vsetvlimax: {
19501 bool HasAVL = IntNo == Intrinsic::riscv_vsetvli;
19502 unsigned VSEW =
Op.getConstantOperandVal(HasAVL + 1);
19508 MaxVL = (Fractional) ? MaxVL / LMul : MaxVL * LMul;
19511 if (HasAVL && isa<ConstantSDNode>(
Op.getOperand(1)))
19512 MaxVL = std::min(MaxVL,
Op.getConstantOperandVal(1));
19514 unsigned KnownZeroFirstBit =
Log2_32(MaxVL) + 1;
19527 unsigned Depth)
const {
19528 switch (
Op.getOpcode()) {
19534 if (Tmp == 1)
return 1;
19537 return std::min(Tmp, Tmp2);
19549 if (Tmp < 33)
return 1;
19574 unsigned XLen = Subtarget.
getXLen();
19575 unsigned EltBits =
Op.getOperand(0).getScalarValueSizeInBits();
19576 if (EltBits <= XLen)
19577 return XLen - EltBits + 1;
19581 unsigned IntNo =
Op.getConstantOperandVal(1);
19585 case Intrinsic::riscv_masked_atomicrmw_xchg_i64:
19586 case Intrinsic::riscv_masked_atomicrmw_add_i64:
19587 case Intrinsic::riscv_masked_atomicrmw_sub_i64:
19588 case Intrinsic::riscv_masked_atomicrmw_nand_i64:
19589 case Intrinsic::riscv_masked_atomicrmw_max_i64:
19590 case Intrinsic::riscv_masked_atomicrmw_min_i64:
19591 case Intrinsic::riscv_masked_atomicrmw_umax_i64:
19592 case Intrinsic::riscv_masked_atomicrmw_umin_i64:
19593 case Intrinsic::riscv_masked_cmpxchg_i64:
19601 assert(Subtarget.hasStdExtA());
19616 switch (
Op.getOpcode()) {
19622 return !
Op.getValueType().isInteger();
19630 assert(Ld &&
"Unexpected null LoadSDNode");
19638 auto *CNode = dyn_cast<ConstantPoolSDNode>(
Ptr);
19639 if (!CNode || CNode->isMachineConstantPoolEntry() ||
19640 CNode->getOffset() != 0)
19648 auto *CNode = GetSupportedConstantPool(
Ptr);
19649 if (!CNode || CNode->getTargetFlags() != 0)
19652 return CNode->getConstVal();
19660 auto *CNodeLo = GetSupportedConstantPool(
Ptr.getOperand(1));
19661 auto *CNodeHi = GetSupportedConstantPool(
Ptr.getOperand(0).getOperand(0));
19667 if (CNodeLo->getConstVal() != CNodeHi->getConstVal())
19670 return CNodeLo->getConstVal();
19675 assert(
MI.getOpcode() == RISCV::ReadCounterWide &&
"Unexpected instruction");
19707 Register ReadAgainReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
19710 int64_t LoCounter =
MI.getOperand(2).getImm();
19711 int64_t HiCounter =
MI.getOperand(3).getImm();
19721 BuildMI(LoopMBB,
DL,
TII->get(RISCV::CSRRS), ReadAgainReg)
19733 MI.eraseFromParent();
19741 assert(
MI.getOpcode() == RISCV::SplitF64Pseudo &&
"Unexpected instruction");
19749 Register SrcReg =
MI.getOperand(2).getReg();
19769 MI.eraseFromParent();
19776 assert(
MI.getOpcode() == RISCV::BuildPairF64Pseudo &&
19777 "Unexpected instruction");
19783 Register DstReg =
MI.getOperand(0).getReg();
19806 MI.eraseFromParent();
19811 switch (
MI.getOpcode()) {
19814 case RISCV::Select_GPR_Using_CC_GPR:
19815 case RISCV::Select_GPR_Using_CC_Imm:
19816 case RISCV::Select_FPR16_Using_CC_GPR:
19817 case RISCV::Select_FPR16INX_Using_CC_GPR:
19818 case RISCV::Select_FPR32_Using_CC_GPR:
19819 case RISCV::Select_FPR32INX_Using_CC_GPR:
19820 case RISCV::Select_FPR64_Using_CC_GPR:
19821 case RISCV::Select_FPR64INX_Using_CC_GPR:
19822 case RISCV::Select_FPR64IN32X_Using_CC_GPR:
19828 unsigned RelOpcode,
unsigned EqOpcode,
19831 Register DstReg =
MI.getOperand(0).getReg();
19832 Register Src1Reg =
MI.getOperand(1).getReg();
19833 Register Src2Reg =
MI.getOperand(2).getReg();
19835 Register SavedFFlags =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
19859 MI.eraseFromParent();
19910 F->insert(It, FirstMBB);
19911 F->insert(It, SecondMBB);
19912 F->insert(It, SinkMBB);
19961 First.eraseFromParent();
20000 if ((
MI.getOpcode() != RISCV::Select_GPR_Using_CC_GPR &&
20001 MI.getOpcode() != RISCV::Select_GPR_Using_CC_Imm) &&
20002 Next != BB->
end() && Next->getOpcode() ==
MI.getOpcode() &&
20003 Next->getOperand(5).getReg() ==
MI.getOperand(0).getReg() &&
20004 Next->getOperand(5).isKill())
20009 if (
MI.getOperand(2).isReg())
20010 RHS =
MI.getOperand(2).getReg();
20015 SelectDests.
insert(
MI.getOperand(0).getReg());
20019 SequenceMBBI != E; ++SequenceMBBI) {
20020 if (SequenceMBBI->isDebugInstr())
20023 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
20024 !SequenceMBBI->getOperand(2).isReg() ||
20025 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
20026 SequenceMBBI->getOperand(3).getImm() !=
CC ||
20027 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
20028 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
20030 LastSelectPseudo = &*SequenceMBBI;
20032 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
20035 if (SequenceMBBI->hasUnmodeledSideEffects() ||
20036 SequenceMBBI->mayLoadOrStore() ||
20037 SequenceMBBI->usesCustomInsertionHook())
20040 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
20055 F->insert(
I, IfFalseMBB);
20056 F->insert(
I, TailMBB);
20059 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
20065 TailMBB->
push_back(DebugInstr->removeFromParent());
20069 TailMBB->
splice(TailMBB->
end(), HeadMBB,
20079 if (
MI.getOperand(2).isImm())
20082 .
addImm(
MI.getOperand(2).getImm())
20094 auto SelectMBBI =
MI.getIterator();
20095 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
20097 while (SelectMBBI != SelectEnd) {
20098 auto Next = std::next(SelectMBBI);
20102 TII.get(RISCV::PHI), SelectMBBI->getOperand(0).getReg())
20103 .
addReg(SelectMBBI->getOperand(4).getReg())
20105 .
addReg(SelectMBBI->getOperand(5).getReg())
20120 RISCVVInversePseudosTable::getBaseInfo(MCOpcode, LMul, SEW);
20121 assert(
Inverse &&
"Unexpected LMUL and SEW pair for instruction");
20123 RISCV::lookupMaskedIntrinsicByUnmasked(
Inverse->Pseudo);
20124 assert(
Masked &&
"Could not find masked instruction for LMUL and SEW pair");
20130 unsigned CVTXOpc) {
20136 Register SavedFFLAGS =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
20149 .
add(
MI.getOperand(1))
20150 .
add(
MI.getOperand(2))
20151 .
add(
MI.getOperand(3))
20153 .
add(
MI.getOperand(4))
20154 .
add(
MI.getOperand(5))
20155 .
add(
MI.getOperand(6))
20170 .
add(
MI.getOperand(0))
20171 .
add(
MI.getOperand(1))
20173 .
add(
MI.getOperand(3))
20175 .
add(
MI.getOperand(4))
20176 .
add(
MI.getOperand(5))
20177 .
add(
MI.getOperand(6))
20187 MI.eraseFromParent();
20193 unsigned CmpOpc, F2IOpc, I2FOpc, FSGNJOpc, FSGNJXOpc;
20195 switch (
MI.getOpcode()) {
20198 case RISCV::PseudoFROUND_H:
20199 CmpOpc = RISCV::FLT_H;
20200 F2IOpc = RISCV::FCVT_W_H;
20201 I2FOpc = RISCV::FCVT_H_W;
20202 FSGNJOpc = RISCV::FSGNJ_H;
20203 FSGNJXOpc = RISCV::FSGNJX_H;
20204 RC = &RISCV::FPR16RegClass;
20206 case RISCV::PseudoFROUND_H_INX:
20207 CmpOpc = RISCV::FLT_H_INX;
20208 F2IOpc = RISCV::FCVT_W_H_INX;
20209 I2FOpc = RISCV::FCVT_H_W_INX;
20210 FSGNJOpc = RISCV::FSGNJ_H_INX;
20211 FSGNJXOpc = RISCV::FSGNJX_H_INX;
20212 RC = &RISCV::GPRF16RegClass;
20214 case RISCV::PseudoFROUND_S:
20215 CmpOpc = RISCV::FLT_S;
20216 F2IOpc = RISCV::FCVT_W_S;
20217 I2FOpc = RISCV::FCVT_S_W;
20218 FSGNJOpc = RISCV::FSGNJ_S;
20219 FSGNJXOpc = RISCV::FSGNJX_S;
20220 RC = &RISCV::FPR32RegClass;
20222 case RISCV::PseudoFROUND_S_INX:
20223 CmpOpc = RISCV::FLT_S_INX;
20224 F2IOpc = RISCV::FCVT_W_S_INX;
20225 I2FOpc = RISCV::FCVT_S_W_INX;
20226 FSGNJOpc = RISCV::FSGNJ_S_INX;
20227 FSGNJXOpc = RISCV::FSGNJX_S_INX;
20228 RC = &RISCV::GPRF32RegClass;
20230 case RISCV::PseudoFROUND_D:
20232 CmpOpc = RISCV::FLT_D;
20233 F2IOpc = RISCV::FCVT_L_D;
20234 I2FOpc = RISCV::FCVT_D_L;
20235 FSGNJOpc = RISCV::FSGNJ_D;
20236 FSGNJXOpc = RISCV::FSGNJX_D;
20237 RC = &RISCV::FPR64RegClass;
20239 case RISCV::PseudoFROUND_D_INX:
20241 CmpOpc = RISCV::FLT_D_INX;
20242 F2IOpc = RISCV::FCVT_L_D_INX;
20243 I2FOpc = RISCV::FCVT_D_L_INX;
20244 FSGNJOpc = RISCV::FSGNJ_D_INX;
20245 FSGNJXOpc = RISCV::FSGNJX_D_INX;
20246 RC = &RISCV::GPRRegClass;
20258 F->insert(
I, CvtMBB);
20259 F->insert(
I, DoneMBB);
20270 Register DstReg =
MI.getOperand(0).getReg();
20271 Register SrcReg =
MI.getOperand(1).getReg();
20272 Register MaxReg =
MI.getOperand(2).getReg();
20273 int64_t FRM =
MI.getOperand(3).getImm();
20278 Register FabsReg =
MRI.createVirtualRegister(RC);
20282 Register CmpReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
20297 Register F2IReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
20319 MI.eraseFromParent();
20326 switch (
MI.getOpcode()) {
20329 case RISCV::ReadCounterWide:
20331 "ReadCounterWide is only to be used on riscv32");
20333 case RISCV::Select_GPR_Using_CC_GPR:
20334 case RISCV::Select_GPR_Using_CC_Imm:
20335 case RISCV::Select_FPR16_Using_CC_GPR:
20336 case RISCV::Select_FPR16INX_Using_CC_GPR:
20337 case RISCV::Select_FPR32_Using_CC_GPR:
20338 case RISCV::Select_FPR32INX_Using_CC_GPR:
20339 case RISCV::Select_FPR64_Using_CC_GPR:
20340 case RISCV::Select_FPR64INX_Using_CC_GPR:
20341 case RISCV::Select_FPR64IN32X_Using_CC_GPR:
20343 case RISCV::BuildPairF64Pseudo:
20345 case RISCV::SplitF64Pseudo:
20347 case RISCV::PseudoQuietFLE_H:
20349 case RISCV::PseudoQuietFLE_H_INX:
20350 return emitQuietFCMP(
MI, BB, RISCV::FLE_H_INX, RISCV::FEQ_H_INX, Subtarget);
20351 case RISCV::PseudoQuietFLT_H:
20353 case RISCV::PseudoQuietFLT_H_INX:
20354 return emitQuietFCMP(
MI, BB, RISCV::FLT_H_INX, RISCV::FEQ_H_INX, Subtarget);
20355 case RISCV::PseudoQuietFLE_S:
20357 case RISCV::PseudoQuietFLE_S_INX:
20358 return emitQuietFCMP(
MI, BB, RISCV::FLE_S_INX, RISCV::FEQ_S_INX, Subtarget);
20359 case RISCV::PseudoQuietFLT_S:
20361 case RISCV::PseudoQuietFLT_S_INX:
20362 return emitQuietFCMP(
MI, BB, RISCV::FLT_S_INX, RISCV::FEQ_S_INX, Subtarget);
20363 case RISCV::PseudoQuietFLE_D:
20365 case RISCV::PseudoQuietFLE_D_INX:
20366 return emitQuietFCMP(
MI, BB, RISCV::FLE_D_INX, RISCV::FEQ_D_INX, Subtarget);
20367 case RISCV::PseudoQuietFLE_D_IN32X:
20370 case RISCV::PseudoQuietFLT_D:
20372 case RISCV::PseudoQuietFLT_D_INX:
20373 return emitQuietFCMP(
MI, BB, RISCV::FLT_D_INX, RISCV::FEQ_D_INX, Subtarget);
20374 case RISCV::PseudoQuietFLT_D_IN32X:
20378 case RISCV::PseudoVFROUND_NOEXCEPT_V_M1_MASK:
20380 case RISCV::PseudoVFROUND_NOEXCEPT_V_M2_MASK:
20382 case RISCV::PseudoVFROUND_NOEXCEPT_V_M4_MASK:
20384 case RISCV::PseudoVFROUND_NOEXCEPT_V_M8_MASK:
20386 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF2_MASK:
20388 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF4_MASK:
20390 case RISCV::PseudoFROUND_H:
20391 case RISCV::PseudoFROUND_H_INX:
20392 case RISCV::PseudoFROUND_S:
20393 case RISCV::PseudoFROUND_S_INX:
20394 case RISCV::PseudoFROUND_D:
20395 case RISCV::PseudoFROUND_D_INX:
20396 case RISCV::PseudoFROUND_D_IN32X:
20398 case RISCV::PROBED_STACKALLOC_DYN:
20400 case TargetOpcode::STATEPOINT:
20406 MI.addOperand(*
MI.getMF(),
20412 case TargetOpcode::STACKMAP:
20413 case TargetOpcode::PATCHPOINT:
20416 "supported on 64-bit targets");
20424 int Idx = RISCV::getNamedOperandIdx(
MI.getOpcode(), RISCV::OpName::frm);
20434 if (
MI.readsRegister(RISCV::FRM,
nullptr))
20440void RISCVTargetLowering::analyzeInputArgs(
20444 unsigned NumArgs = Ins.size();
20447 for (
unsigned i = 0; i != NumArgs; ++i) {
20448 MVT ArgVT = Ins[i].VT;
20451 Type *ArgTy =
nullptr;
20454 else if (Ins[i].isOrigArg())
20455 ArgTy = FType->
getParamType(Ins[i].getOrigArgIndex());
20458 true, IsRet, ArgTy)) {
20459 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type "
20466void RISCVTargetLowering::analyzeOutputArgs(
20470 unsigned NumArgs = Outs.
size();
20472 for (
unsigned i = 0; i != NumArgs; i++) {
20473 MVT ArgVT = Outs[i].VT;
20475 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
20478 Outs[i].IsFixed, IsRet, OrigTy)) {
20479 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type "
20530 if (In.isOrigArg()) {
20535 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
20536 (
BitWidth < 32 && In.Flags.isZExt())) {
20558 if (LocVT == MVT::i64 && VA.
getValVT() == MVT::f32)
20607 ExtType,
DL, LocVT, Chain, FIN,
20624 Register LoVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
20637 Register HiVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
20652 switch (CallConv) {
20662 if (Subtarget.hasStdExtE())
20666 "(Zdinx/D) instruction set extensions");
20670 if (Func.hasFnAttribute(
"interrupt")) {
20671 if (!Func.arg_empty())
20673 "Functions with the interrupt attribute cannot have arguments!");
20678 if (!(Kind ==
"user" || Kind ==
"supervisor" || Kind ==
"machine"))
20680 "Function interrupt attribute argument not supported!");
20685 unsigned XLenInBytes = Subtarget.
getXLen() / 8;
20687 std::vector<SDValue> OutChains;
20696 analyzeInputArgs(MF, CCInfo, Ins,
false,
20700 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
20721 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
20722 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
20724 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
20726 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
20755 int VarArgsSaveSize = XLenInBytes * (ArgRegs.
size() -
Idx);
20760 if (VarArgsSaveSize == 0) {
20764 int VaArgOffset = -VarArgsSaveSize;
20772 XLenInBytes, VaArgOffset -
static_cast<int>(XLenInBytes),
true);
20773 VarArgsSaveSize += XLenInBytes;
20780 for (
unsigned I =
Idx;
I < ArgRegs.
size(); ++
I) {
20785 Chain,
DL, ArgValue, FIN,
20787 OutChains.push_back(Store);
20801 if (!OutChains.empty()) {
20802 OutChains.push_back(Chain);
20812bool RISCVTargetLowering::isEligibleForTailCallOptimization(
20816 auto CalleeCC = CLI.CallConv;
20817 auto &Outs = CLI.Outs;
20819 auto CallerCC = Caller.getCallingConv();
20826 if (Caller.hasFnAttribute(
"interrupt"))
20841 for (
auto &VA : ArgLocs)
20847 auto IsCallerStructRet = Caller.hasStructRetAttr();
20848 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
20849 if (IsCallerStructRet || IsCalleeStructRet)
20854 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
20855 if (CalleeCC != CallerCC) {
20856 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
20857 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
20864 for (
auto &Arg : Outs)
20865 if (Arg.Flags.isByVal())
20900 if (Subtarget.hasStdExtE())
20904 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
20910 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
20916 "site marked musttail");
20923 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
20925 if (!Flags.isByVal())
20929 unsigned Size = Flags.getByValSize();
20930 Align Alignment = Flags.getNonZeroByValAlign();
20937 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
20939 false,
nullptr, IsTailCall,
20951 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
20954 SDValue ArgValue = OutVals[OutIdx];
20974 if (!StackPtr.getNode())
20986 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
21004 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
21005 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
21011 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
21012 SDValue PartValue = OutVals[OutIdx + 1];
21013 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
21025 int FI = cast<FrameIndexSDNode>(SpillSlot)->getIndex();
21027 DAG.
getStore(Chain,
DL, ArgValue, SpillSlot,
21029 for (
const auto &Part : Parts) {
21030 SDValue PartValue = Part.first;
21031 SDValue PartOffset = Part.second;
21038 ArgValue = SpillSlot;
21044 if (Flags.isByVal())
21045 ArgValue = ByValArgs[j++];
21052 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
21053 "for passing parameters");
21056 if (!StackPtr.getNode())
21070 if (!MemOpChains.
empty())
21076 for (
auto &Reg : RegsToPass) {
21077 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
21084 validateCCReservedRegs(RegsToPass, MF);
21088 "Return address register required, but has been reserved."});
21093 bool CalleeIsLargeExternalSymbol =
false;
21095 if (
auto *S = dyn_cast<GlobalAddressSDNode>(Callee))
21097 else if (
auto *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
21099 CalleeIsLargeExternalSymbol =
true;
21115 for (
auto &Reg : RegsToPass)
21120 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
21121 assert(Mask &&
"Missing call preserved mask for calling convention");
21129 "Unexpected CFI type for a direct call");
21137 bool NeedSWGuarded =
false;
21139 Subtarget.hasStdExtZicfilp() &&
21141 NeedSWGuarded =
true;
21155 Chain = DAG.
getNode(CallOpc,
DL, NodeTys, Ops);
21168 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_RISCV);
21171 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
21172 auto &VA = RVLocs[i];
21180 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
21181 assert(VA.needsCustom());
21202 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
21204 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
21205 MVT VT = Outs[i].VT;
21208 true,
true,
nullptr))
21240 for (
unsigned i = 0, e = RVLocs.size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
21241 SDValue Val = OutVals[OutIdx];
21250 DAG.
getVTList(MVT::i32, MVT::i32), Val);
21254 Register RegHi = RVLocs[++i].getLocReg();
21260 "Return value register required, but has been reserved."});
21276 "Return value register required, but has been reserved."});
21298 if (Func.hasFnAttribute(
"interrupt")) {
21299 if (!Func.getReturnType()->isVoidTy())
21301 "Functions with the interrupt attribute must have void return type!");
21307 if (Kind ==
"supervisor")
21313 return DAG.
getNode(RetOpc,
DL, MVT::Other, RetOps);
21316void RISCVTargetLowering::validateCCReservedRegs(
21317 const SmallVectorImpl<std::pair<llvm::Register, llvm::SDValue>> &Regs,
21326 F,
"Argument register required, but has been reserved."});
21332 if (
N->getNumValues() != 1)
21334 if (!
N->hasNUsesOfValue(1, 0))
21337 SDNode *Copy = *
N->user_begin();
21351 if (Copy->getOperand(Copy->getNumOperands() - 1).getValueType() == MVT::Glue)
21355 bool HasRet =
false;
21356 for (
SDNode *Node : Copy->users()) {
21364 Chain = Copy->getOperand(0);
21373#define NODE_NAME_CASE(NODE) \
21374 case RISCVISD::NODE: \
21375 return "RISCVISD::" #NODE;
21637#undef NODE_NAME_CASE
21644 if (Constraint.
size() == 1) {
21645 switch (Constraint[0]) {
21662 if (Constraint ==
"vr" || Constraint ==
"vd" || Constraint ==
"vm")
21664 if (Constraint ==
"cr" || Constraint ==
"cR" || Constraint ==
"cf")
21670std::pair<unsigned, const TargetRegisterClass *>
21676 if (Constraint.
size() == 1) {
21677 switch (Constraint[0]) {
21682 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
21683 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
21684 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
21685 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
21686 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
21687 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
21688 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
21690 if (VT == MVT::f16) {
21691 if (Subtarget.hasStdExtZfhmin())
21692 return std::make_pair(0U, &RISCV::FPR16RegClass);
21693 if (Subtarget.hasStdExtZhinxmin())
21694 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
21695 }
else if (VT == MVT::f32) {
21696 if (Subtarget.hasStdExtF())
21697 return std::make_pair(0U, &RISCV::FPR32RegClass);
21698 if (Subtarget.hasStdExtZfinx())
21699 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
21700 }
else if (VT == MVT::f64) {
21701 if (Subtarget.hasStdExtD())
21702 return std::make_pair(0U, &RISCV::FPR64RegClass);
21703 if (Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
21704 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
21705 if (Subtarget.hasStdExtZdinx() && Subtarget.
is64Bit())
21706 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
21710 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
21714 }
else if (Constraint ==
"vr") {
21715 for (
const auto *RC :
21716 {&RISCV::VRRegClass, &RISCV::VRM2RegClass, &RISCV::VRM4RegClass,
21717 &RISCV::VRM8RegClass, &RISCV::VRN2M1RegClass, &RISCV::VRN3M1RegClass,
21718 &RISCV::VRN4M1RegClass, &RISCV::VRN5M1RegClass,
21719 &RISCV::VRN6M1RegClass, &RISCV::VRN7M1RegClass,
21720 &RISCV::VRN8M1RegClass, &RISCV::VRN2M2RegClass,
21721 &RISCV::VRN3M2RegClass, &RISCV::VRN4M2RegClass,
21722 &RISCV::VRN2M4RegClass}) {
21724 return std::make_pair(0U, RC);
21726 }
else if (Constraint ==
"vd") {
21727 for (
const auto *RC :
21728 {&RISCV::VRNoV0RegClass, &RISCV::VRM2NoV0RegClass,
21729 &RISCV::VRM4NoV0RegClass, &RISCV::VRM8NoV0RegClass,
21730 &RISCV::VRN2M1NoV0RegClass, &RISCV::VRN3M1NoV0RegClass,
21731 &RISCV::VRN4M1NoV0RegClass, &RISCV::VRN5M1NoV0RegClass,
21732 &RISCV::VRN6M1NoV0RegClass, &RISCV::VRN7M1NoV0RegClass,
21733 &RISCV::VRN8M1NoV0RegClass, &RISCV::VRN2M2NoV0RegClass,
21734 &RISCV::VRN3M2NoV0RegClass, &RISCV::VRN4M2NoV0RegClass,
21735 &RISCV::VRN2M4NoV0RegClass}) {
21737 return std::make_pair(0U, RC);
21739 }
else if (Constraint ==
"vm") {
21740 if (
TRI->isTypeLegalForClass(RISCV::VMV0RegClass, VT.
SimpleTy))
21741 return std::make_pair(0U, &RISCV::VMV0RegClass);
21742 }
else if (Constraint ==
"cr") {
21743 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
21744 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
21745 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
21746 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
21747 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
21748 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
21750 return std::make_pair(0U, &RISCV::GPRCRegClass);
21751 }
else if (Constraint ==
"cR") {
21752 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
21753 }
else if (Constraint ==
"cf") {
21754 if (VT == MVT::f16) {
21755 if (Subtarget.hasStdExtZfhmin())
21756 return std::make_pair(0U, &RISCV::FPR16CRegClass);
21757 if (Subtarget.hasStdExtZhinxmin())
21758 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
21759 }
else if (VT == MVT::f32) {
21760 if (Subtarget.hasStdExtF())
21761 return std::make_pair(0U, &RISCV::FPR32CRegClass);
21762 if (Subtarget.hasStdExtZfinx())
21763 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
21764 }
else if (VT == MVT::f64) {
21765 if (Subtarget.hasStdExtD())
21766 return std::make_pair(0U, &RISCV::FPR64CRegClass);
21767 if (Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
21768 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
21769 if (Subtarget.hasStdExtZdinx() && Subtarget.
is64Bit())
21770 return std::make_pair(0U, &RISCV::GPRCRegClass);
21779 .
Case(
"{zero}", RISCV::X0)
21780 .
Case(
"{ra}", RISCV::X1)
21781 .
Case(
"{sp}", RISCV::X2)
21782 .
Case(
"{gp}", RISCV::X3)
21783 .
Case(
"{tp}", RISCV::X4)
21784 .
Case(
"{t0}", RISCV::X5)
21785 .
Case(
"{t1}", RISCV::X6)
21786 .
Case(
"{t2}", RISCV::X7)
21787 .
Cases(
"{s0}",
"{fp}", RISCV::X8)
21788 .
Case(
"{s1}", RISCV::X9)
21789 .
Case(
"{a0}", RISCV::X10)
21790 .
Case(
"{a1}", RISCV::X11)
21791 .
Case(
"{a2}", RISCV::X12)
21792 .
Case(
"{a3}", RISCV::X13)
21793 .
Case(
"{a4}", RISCV::X14)
21794 .
Case(
"{a5}", RISCV::X15)
21795 .
Case(
"{a6}", RISCV::X16)
21796 .
Case(
"{a7}", RISCV::X17)
21797 .
Case(
"{s2}", RISCV::X18)
21798 .
Case(
"{s3}", RISCV::X19)
21799 .
Case(
"{s4}", RISCV::X20)
21800 .
Case(
"{s5}", RISCV::X21)
21801 .
Case(
"{s6}", RISCV::X22)
21802 .
Case(
"{s7}", RISCV::X23)
21803 .
Case(
"{s8}", RISCV::X24)
21804 .
Case(
"{s9}", RISCV::X25)
21805 .
Case(
"{s10}", RISCV::X26)
21806 .
Case(
"{s11}", RISCV::X27)
21807 .
Case(
"{t3}", RISCV::X28)
21808 .
Case(
"{t4}", RISCV::X29)
21809 .
Case(
"{t5}", RISCV::X30)
21810 .
Case(
"{t6}", RISCV::X31)
21812 if (XRegFromAlias != RISCV::NoRegister)
21813 return std::make_pair(XRegFromAlias, &RISCV::GPRRegClass);
21822 if (Subtarget.hasStdExtF()) {
21824 .
Cases(
"{f0}",
"{ft0}", RISCV::F0_F)
21825 .
Cases(
"{f1}",
"{ft1}", RISCV::F1_F)
21826 .
Cases(
"{f2}",
"{ft2}", RISCV::F2_F)
21827 .
Cases(
"{f3}",
"{ft3}", RISCV::F3_F)
21828 .
Cases(
"{f4}",
"{ft4}", RISCV::F4_F)
21829 .
Cases(
"{f5}",
"{ft5}", RISCV::F5_F)
21830 .
Cases(
"{f6}",
"{ft6}", RISCV::F6_F)
21831 .
Cases(
"{f7}",
"{ft7}", RISCV::F7_F)
21832 .
Cases(
"{f8}",
"{fs0}", RISCV::F8_F)
21833 .
Cases(
"{f9}",
"{fs1}", RISCV::F9_F)
21834 .
Cases(
"{f10}",
"{fa0}", RISCV::F10_F)
21835 .
Cases(
"{f11}",
"{fa1}", RISCV::F11_F)
21836 .
Cases(
"{f12}",
"{fa2}", RISCV::F12_F)
21837 .
Cases(
"{f13}",
"{fa3}", RISCV::F13_F)
21838 .
Cases(
"{f14}",
"{fa4}", RISCV::F14_F)
21839 .
Cases(
"{f15}",
"{fa5}", RISCV::F15_F)
21840 .
Cases(
"{f16}",
"{fa6}", RISCV::F16_F)
21841 .
Cases(
"{f17}",
"{fa7}", RISCV::F17_F)
21842 .
Cases(
"{f18}",
"{fs2}", RISCV::F18_F)
21843 .
Cases(
"{f19}",
"{fs3}", RISCV::F19_F)
21844 .
Cases(
"{f20}",
"{fs4}", RISCV::F20_F)
21845 .
Cases(
"{f21}",
"{fs5}", RISCV::F21_F)
21846 .
Cases(
"{f22}",
"{fs6}", RISCV::F22_F)
21847 .
Cases(
"{f23}",
"{fs7}", RISCV::F23_F)
21848 .
Cases(
"{f24}",
"{fs8}", RISCV::F24_F)
21849 .
Cases(
"{f25}",
"{fs9}", RISCV::F25_F)
21850 .
Cases(
"{f26}",
"{fs10}", RISCV::F26_F)
21851 .
Cases(
"{f27}",
"{fs11}", RISCV::F27_F)
21852 .
Cases(
"{f28}",
"{ft8}", RISCV::F28_F)
21853 .
Cases(
"{f29}",
"{ft9}", RISCV::F29_F)
21854 .
Cases(
"{f30}",
"{ft10}", RISCV::F30_F)
21855 .
Cases(
"{f31}",
"{ft11}", RISCV::F31_F)
21857 if (FReg != RISCV::NoRegister) {
21858 assert(RISCV::F0_F <= FReg && FReg <= RISCV::F31_F &&
"Unknown fp-reg");
21859 if (Subtarget.hasStdExtD() && (VT == MVT::f64 || VT == MVT::Other)) {
21860 unsigned RegNo = FReg - RISCV::F0_F;
21861 unsigned DReg = RISCV::F0_D + RegNo;
21862 return std::make_pair(DReg, &RISCV::FPR64RegClass);
21864 if (VT == MVT::f32 || VT == MVT::Other)
21865 return std::make_pair(FReg, &RISCV::FPR32RegClass);
21866 if (Subtarget.hasStdExtZfhmin() && VT == MVT::f16) {
21867 unsigned RegNo = FReg - RISCV::F0_F;
21868 unsigned HReg = RISCV::F0_H + RegNo;
21869 return std::make_pair(HReg, &RISCV::FPR16RegClass);
21876 .
Case(
"{v0}", RISCV::V0)
21877 .
Case(
"{v1}", RISCV::V1)
21878 .
Case(
"{v2}", RISCV::V2)
21879 .
Case(
"{v3}", RISCV::V3)
21880 .
Case(
"{v4}", RISCV::V4)
21881 .
Case(
"{v5}", RISCV::V5)
21882 .
Case(
"{v6}", RISCV::V6)
21883 .
Case(
"{v7}", RISCV::V7)
21884 .
Case(
"{v8}", RISCV::V8)
21885 .
Case(
"{v9}", RISCV::V9)
21886 .
Case(
"{v10}", RISCV::V10)
21887 .
Case(
"{v11}", RISCV::V11)
21888 .
Case(
"{v12}", RISCV::V12)
21889 .
Case(
"{v13}", RISCV::V13)
21890 .
Case(
"{v14}", RISCV::V14)
21891 .
Case(
"{v15}", RISCV::V15)
21892 .
Case(
"{v16}", RISCV::V16)
21893 .
Case(
"{v17}", RISCV::V17)
21894 .
Case(
"{v18}", RISCV::V18)
21895 .
Case(
"{v19}", RISCV::V19)
21896 .
Case(
"{v20}", RISCV::V20)
21897 .
Case(
"{v21}", RISCV::V21)
21898 .
Case(
"{v22}", RISCV::V22)
21899 .
Case(
"{v23}", RISCV::V23)
21900 .
Case(
"{v24}", RISCV::V24)
21901 .
Case(
"{v25}", RISCV::V25)
21902 .
Case(
"{v26}", RISCV::V26)
21903 .
Case(
"{v27}", RISCV::V27)
21904 .
Case(
"{v28}", RISCV::V28)
21905 .
Case(
"{v29}", RISCV::V29)
21906 .
Case(
"{v30}", RISCV::V30)
21907 .
Case(
"{v31}", RISCV::V31)
21909 if (VReg != RISCV::NoRegister) {
21910 if (
TRI->isTypeLegalForClass(RISCV::VMRegClass, VT.
SimpleTy))
21911 return std::make_pair(VReg, &RISCV::VMRegClass);
21912 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, VT.
SimpleTy))
21913 return std::make_pair(VReg, &RISCV::VRRegClass);
21914 for (
const auto *RC :
21915 {&RISCV::VRM2RegClass, &RISCV::VRM4RegClass, &RISCV::VRM8RegClass}) {
21916 if (
TRI->isTypeLegalForClass(*RC, VT.
SimpleTy)) {
21917 VReg =
TRI->getMatchingSuperReg(VReg, RISCV::sub_vrm1_0, RC);
21918 return std::make_pair(VReg, RC);
21924 std::pair<Register, const TargetRegisterClass *> Res =
21930 if (Res.second == &RISCV::GPRF16RegClass ||
21931 Res.second == &RISCV::GPRF32RegClass ||
21932 Res.second == &RISCV::GPRPairRegClass)
21933 return std::make_pair(Res.first, &RISCV::GPRRegClass);
21941 if (ConstraintCode.
size() == 1) {
21942 switch (ConstraintCode[0]) {
21957 if (Constraint.
size() == 1) {
21958 switch (Constraint[0]) {
21961 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
21963 if (isInt<12>(CVal))
21976 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
21978 if (isUInt<5>(CVal))
21996 if (Subtarget.hasStdExtZtso()) {
22012 if (Subtarget.hasStdExtZtso()) {
22020 if (Subtarget.enableTrailingSeqCstFence() && isa<StoreInst>(Inst) &&
22039 if (Subtarget.hasForcedAtomics())
22044 if (Subtarget.hasStdExtZacas() &&
22045 (
Size >= 32 || Subtarget.hasStdExtZabha()))
22051 if (
Size < 32 && !Subtarget.hasStdExtZabha())
22064 return Intrinsic::riscv_masked_atomicrmw_xchg_i32;
22066 return Intrinsic::riscv_masked_atomicrmw_add_i32;
22068 return Intrinsic::riscv_masked_atomicrmw_sub_i32;
22070 return Intrinsic::riscv_masked_atomicrmw_nand_i32;
22072 return Intrinsic::riscv_masked_atomicrmw_max_i32;
22074 return Intrinsic::riscv_masked_atomicrmw_min_i32;
22076 return Intrinsic::riscv_masked_atomicrmw_umax_i32;
22078 return Intrinsic::riscv_masked_atomicrmw_umin_i32;
22087 return Intrinsic::riscv_masked_atomicrmw_xchg_i64;
22089 return Intrinsic::riscv_masked_atomicrmw_add_i64;
22091 return Intrinsic::riscv_masked_atomicrmw_sub_i64;
22093 return Intrinsic::riscv_masked_atomicrmw_nand_i64;
22095 return Intrinsic::riscv_masked_atomicrmw_max_i64;
22097 return Intrinsic::riscv_masked_atomicrmw_min_i64;
22099 return Intrinsic::riscv_masked_atomicrmw_umax_i64;
22101 return Intrinsic::riscv_masked_atomicrmw_umin_i64;
22127 unsigned XLen = Subtarget.
getXLen();
22151 unsigned ValWidth =
22156 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
22159 Builder.
CreateCall(LrwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
22171 if (Subtarget.hasForcedAtomics())
22175 if (!(Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas()) &&
22184 unsigned XLen = Subtarget.
getXLen();
22186 Intrinsic::ID CmpXchgIntrID = Intrinsic::riscv_masked_cmpxchg_i32;
22191 CmpXchgIntrID = Intrinsic::riscv_masked_cmpxchg_i64;
22195 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, Ordering});
22202 EVT DataVT)
const {
22218 return Subtarget.hasStdExtZfhmin();
22220 return Subtarget.hasStdExtF();
22222 return Subtarget.hasStdExtD();
22254 "RVVBitsPerBlock changed, audit needed");
22263 if (!Subtarget.hasVendorXTHeadMemIdx())
22269 Base =
Op->getOperand(0);
22271 int64_t RHSC =
RHS->getSExtValue();
22277 bool isLegalIndexedOffset =
false;
22278 for (
unsigned i = 0; i < 4; i++)
22279 if (isInt<5>(RHSC >> i) && ((RHSC % (1LL << i)) == 0)) {
22280 isLegalIndexedOffset =
true;
22284 if (!isLegalIndexedOffset)
22301 VT = LD->getMemoryVT();
22302 Ptr = LD->getBasePtr();
22303 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
22304 VT = ST->getMemoryVT();
22305 Ptr = ST->getBasePtr();
22321 if (Subtarget.hasVendorXCVmem() && !Subtarget.
is64Bit()) {
22326 Base = LS->getBasePtr();
22330 if (
Base ==
Op->getOperand(0))
22332 else if (
Base ==
Op->getOperand(1))
22344 VT = LD->getMemoryVT();
22345 Ptr = LD->getBasePtr();
22346 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
22347 VT = ST->getMemoryVT();
22348 Ptr = ST->getBasePtr();
22391 const Constant *PersonalityFn)
const {
22396 const Constant *PersonalityFn)
const {
22411 bool IsSigned)
const {
22426 const bool HasZmmul = Subtarget.hasStdExtZmmul();
22430 auto *ConstNode = cast<ConstantSDNode>(
C);
22431 const APInt &Imm = ConstNode->getAPIntValue();
22434 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
22435 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
22439 if (Subtarget.hasStdExtZba() && !Imm.isSignedIntN(12) &&
22440 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
22441 (Imm - 8).isPowerOf2()))
22446 if (!Imm.isSignedIntN(12) && Imm.countr_zero() < 12 &&
22447 ConstNode->hasOneUse()) {
22448 APInt ImmS = Imm.ashr(Imm.countr_zero());
22449 if ((ImmS + 1).isPowerOf2() || (ImmS - 1).isPowerOf2() ||
22450 (1 - ImmS).isPowerOf2())
22473 if (C1.
isSignedIntN(12) && !(C1 * C2).isSignedIntN(12))
22482 unsigned *
Fast)
const {
22485 *
Fast = Subtarget.enableUnalignedScalarMem();
22486 return Subtarget.enableUnalignedScalarMem();
22502 *
Fast = Subtarget.enableUnalignedVectorMem();
22503 return Subtarget.enableUnalignedVectorMem();
22512 if (FuncAttributes.
hasFnAttr(Attribute::NoImplicitFloat))
22524 if (
Op.size() < MinVLenInBytes)
22539 MVT PreferredVT = (
Op.isMemset() && !
Op.isZeroMemset()) ? MVT::i8 : ELenVT;
22543 if (PreferredVT != MVT::i8 && !Subtarget.enableUnalignedVectorMem()) {
22545 if (
Op.isFixedDstAlign())
22546 RequiredAlign = std::min(RequiredAlign,
Op.getDstAlign());
22548 RequiredAlign = std::min(RequiredAlign,
Op.getSrcAlign());
22556 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID>
CC)
const {
22557 bool IsABIRegCopy =
CC.has_value();
22560 MVT PairVT = Subtarget.
is64Bit() ? MVT::i128 : MVT::i64;
22561 if ((ValueVT == PairVT ||
22562 (!Subtarget.
is64Bit() && Subtarget.hasStdExtZdinx() &&
22563 ValueVT == MVT::f64)) &&
22564 NumParts == 1 && PartVT == MVT::Untyped) {
22567 if (ValueVT == MVT::f64)
22576 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
22577 PartVT == MVT::f32) {
22592 [[maybe_unused]]
unsigned ValLMUL =
22596 [[maybe_unused]]
unsigned PartLMUL =
22599 assert(ValNF == PartNF && ValLMUL == PartLMUL &&
22600 "RISC-V vector tuple type only accepts same register class type "
22616 if (PartVTBitSize % ValueVTBitSize == 0) {
22617 assert(PartVTBitSize >= ValueVTBitSize);
22624 if (ValueEltVT != PartEltVT) {
22625 if (PartVTBitSize > ValueVTBitSize) {
22627 assert(Count != 0 &&
"The number of element should not be zero.");
22628 EVT SameEltTypeVT =
22650 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID>
CC)
const {
22651 bool IsABIRegCopy =
CC.has_value();
22653 MVT PairVT = Subtarget.
is64Bit() ? MVT::i128 : MVT::i64;
22654 if ((ValueVT == PairVT ||
22655 (!Subtarget.
is64Bit() && Subtarget.hasStdExtZdinx() &&
22656 ValueVT == MVT::f64)) &&
22657 NumParts == 1 && PartVT == MVT::Untyped) {
22668 if (ValueVT == MVT::f64)
22673 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
22674 PartVT == MVT::f32) {
22691 if (PartVTBitSize % ValueVTBitSize == 0) {
22692 assert(PartVTBitSize >= ValueVTBitSize);
22693 EVT SameEltTypeVT = ValueVT;
22700 if (ValueEltVT != PartEltVT) {
22702 assert(Count != 0 &&
"The number of element should not be zero.");
22719 bool OptSize = Attr.
hasFnAttr(Attribute::MinSize);
22726 unsigned Opc =
N->getOpcode();
22754 if (M->getStackProtectorGuard() ==
"tls") {
22756 int Offset = M->getStackProtectorGuardOffset();
22764 VectorType *VTy,
unsigned Factor,
Align Alignment,
unsigned AddrSpace,
22778 if (
auto *FVTy = dyn_cast<FixedVectorType>(VTy)) {
22783 if (FVTy->getNumElements() < 2)
22798 return Factor * LMUL <= 8;
22802 Align Alignment)
const {
22814 if (!Subtarget.enableUnalignedVectorMem() &&
22822 Intrinsic::riscv_seg2_load, Intrinsic::riscv_seg3_load,
22823 Intrinsic::riscv_seg4_load, Intrinsic::riscv_seg5_load,
22824 Intrinsic::riscv_seg6_load, Intrinsic::riscv_seg7_load,
22825 Intrinsic::riscv_seg8_load};
22846 auto *VTy = cast<FixedVectorType>(Shuffles[0]->
getType());
22858 unsigned ScalarSizeInBytes = VTy->getScalarSizeInBits() / 8;
22859 Value *Stride = ConstantInt::get(XLenTy, Factor * ScalarSizeInBytes);
22860 Value *
Offset = ConstantInt::get(XLenTy, Indices[0] * ScalarSizeInBytes);
22867 {VTy, BasePtr->getType(), Stride->
getType()},
22868 {BasePtr, Stride, Mask, VL});
22871 Shuffles[0]->replaceAllUsesWith(CI);
22875 Value *VL = ConstantInt::get(XLenTy, VTy->getNumElements());
22881 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
22883 Shuffles[i]->replaceAllUsesWith(SubVec);
22890 Intrinsic::riscv_seg2_store, Intrinsic::riscv_seg3_store,
22891 Intrinsic::riscv_seg4_store, Intrinsic::riscv_seg5_store,
22892 Intrinsic::riscv_seg6_store, Intrinsic::riscv_seg7_store,
22893 Intrinsic::riscv_seg8_store};
22913 unsigned Factor)
const {
22916 auto *ShuffleVTy = cast<FixedVectorType>(SVI->
getType());
22919 ShuffleVTy->getNumElements() / Factor);
22921 SI->getPointerAddressSpace(),
22922 SI->getDataLayout()))
22933 unsigned ScalarSizeInBytes = ShuffleVTy->getScalarSizeInBits() / 8;
22935 auto *DataVTy = cast<FixedVectorType>(
Data->getType());
22936 Value *Stride = ConstantInt::get(XLenTy, Factor * ScalarSizeInBytes);
22937 Value *
Offset = ConstantInt::get(XLenTy, Index * ScalarSizeInBytes);
22943 Intrinsic::experimental_vp_strided_store,
22944 {
Data->getType(), BasePtr->getType(), Stride->
getType()},
22945 {
Data, BasePtr, Stride, Mask, VL});
22954 {VTy, SI->getPointerOperandType(), XLenTy});
22958 for (
unsigned i = 0; i < Factor; i++) {
22967 Value *VL = ConstantInt::get(XLenTy, VTy->getNumElements());
22968 Ops.
append({SI->getPointerOperand(), VL});
22977 unsigned Factor = DeinterleaveValues.
size();
22984 auto *ResVTy = cast<VectorType>(DeinterleaveValues[0]->
getType());
22995 if (
auto *FVTy = dyn_cast<FixedVectorType>(ResVTy)) {
22996 Value *VL = ConstantInt::get(XLenTy, FVTy->getNumElements());
23003 Intrinsic::riscv_vlseg2, Intrinsic::riscv_vlseg3,
23004 Intrinsic::riscv_vlseg4, Intrinsic::riscv_vlseg5,
23005 Intrinsic::riscv_vlseg6, Intrinsic::riscv_vlseg7,
23006 Intrinsic::riscv_vlseg8};
23008 unsigned SEW =
DL.getTypeSizeInBits(ResVTy->getElementType());
23009 unsigned NumElts = ResVTy->getElementCount().getKnownMinValue();
23013 NumElts * SEW / 8),
23019 IntrIds[Factor - 2], {VecTupTy, XLenTy},
23021 ConstantInt::get(XLenTy,
Log2_64(SEW))});
23025 for (
unsigned i = 0; i < Factor; ++i) {
23027 Intrinsic::riscv_tuple_extract, {ResVTy, VecTupTy},
23033 for (
auto [
Idx, DIV] :
enumerate(DeinterleaveValues)) {
23046 unsigned Factor = InterleaveValues.
size();
23053 auto *InVTy = cast<VectorType>(InterleaveValues[0]->
getType());
23057 SI->getPointerAddressSpace(),
DL))
23062 if (
auto *FVTy = dyn_cast<FixedVectorType>(InVTy)) {
23065 {InVTy, SI->getPointerOperandType(), XLenTy});
23068 InterleaveValues.
end());
23069 Value *VL = ConstantInt::get(XLenTy, FVTy->getNumElements());
23070 Ops.
append({SI->getPointerOperand(), VL});
23075 Intrinsic::riscv_vsseg2, Intrinsic::riscv_vsseg3,
23076 Intrinsic::riscv_vsseg4, Intrinsic::riscv_vsseg5,
23077 Intrinsic::riscv_vsseg6, Intrinsic::riscv_vsseg7,
23078 Intrinsic::riscv_vsseg8};
23080 unsigned SEW =
DL.getTypeSizeInBits(InVTy->getElementType());
23081 unsigned NumElts = InVTy->getElementCount().getKnownMinValue();
23083 SI->getContext(),
"riscv.vector.tuple",
23085 NumElts * SEW / 8),
23089 SI->getModule(), IntrIds[Factor - 2], {VecTupTy, XLenTy});
23094 for (
unsigned i = 0; i < Factor; ++i)
23096 Intrinsic::riscv_tuple_insert, {VecTupTy, InVTy},
23097 {StoredVal, InterleaveValues[i], Builder.getInt32(i)});
23099 Builder.
CreateCall(VssegNFunc, {StoredVal, SI->getPointerOperand(), VL,
23100 ConstantInt::get(XLenTy,
Log2_64(SEW))});
23116 using namespace PatternMatch;
23154 assert(Mask &&
"Expect a valid mask");
23155 assert(Load->getIntrinsicID() == Intrinsic::vp_load &&
23156 "Unexpected intrinsic");
23158 const unsigned Factor = DeinterleaveResults.
size();
23160 auto *WideVTy = dyn_cast<ScalableVectorType>(Load->getType());
23165 unsigned WideNumElements = WideVTy->getElementCount().getKnownMinValue();
23166 assert(WideNumElements % Factor == 0 &&
23167 "ElementCount of a wide load must be divisible by interleave factor");
23170 WideVTy->isScalableTy());
23171 auto &
DL = Load->getModule()->getDataLayout();
23172 Align Alignment = Load->getParamAlign(0).value_or(
23173 DL.getABITypeAlign(WideVTy->getElementType()));
23175 VTy, Factor, Alignment,
23176 Load->getArgOperand(0)->getType()->getPointerAddressSpace(),
DL))
23180 Value *WideEVL = Load->getArgOperand(2);
23183 if (!
isMultipleOfN(WideEVL, Load->getDataLayout(), Factor))
23192 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
23193 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
23194 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
23195 Intrinsic::riscv_vlseg8_mask,
23198 unsigned SEW =
DL.getTypeSizeInBits(VTy->getElementType());
23199 unsigned NumElts = VTy->getElementCount().getKnownMinValue();
23201 Load->getContext(),
"riscv.vector.tuple",
23203 NumElts * SEW / 8),
23209 Load->getModule(), IntrMaskIds[Factor - 2],
23210 {VecTupTy, Mask->getType(), EVL->getType()});
23214 Load->getArgOperand(0),
23218 ConstantInt::get(XLenTy,
Log2_64(SEW))};
23226 Load->getModule(), Intrinsic::riscv_tuple_extract, {VTy, VecTupTy});
23227 for (
unsigned i = 0; i < Factor; ++i) {
23228 Value *VecExtract =
23233 for (
auto [
Idx, DIO] :
enumerate(DeinterleaveResults)) {
23267 assert(Mask &&
"Expect a valid mask");
23268 assert(Store->getIntrinsicID() == Intrinsic::vp_store &&
23269 "Unexpected intrinsic");
23271 const unsigned Factor = InterleaveOperands.
size();
23273 auto *VTy = dyn_cast<ScalableVectorType>(InterleaveOperands[0]->
getType());
23279 Align Alignment = Store->getParamAlign(1).value_or(
23280 DL.getABITypeAlign(VTy->getElementType()));
23282 VTy, Factor, Alignment,
23283 Store->getArgOperand(1)->getType()->getPointerAddressSpace(),
DL))
23287 Value *WideEVL = Store->getArgOperand(3);
23290 if (!
isMultipleOfN(WideEVL, Store->getDataLayout(), Factor))
23299 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
23300 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
23301 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
23302 Intrinsic::riscv_vsseg8_mask,
23305 unsigned SEW =
DL.getTypeSizeInBits(VTy->getElementType());
23306 unsigned NumElts = VTy->getElementCount().getKnownMinValue();
23308 Store->getContext(),
"riscv.vector.tuple",
23310 NumElts * SEW / 8),
23314 Store->getModule(), Intrinsic::riscv_tuple_insert, {VecTupTy, VTy});
23316 for (
unsigned i = 0; i < Factor; ++i)
23318 VecInsertFunc, {StoredVal, InterleaveOperands[i], Builder.getInt32(i)});
23321 Store->getModule(), IntrMaskIds[Factor - 2],
23322 {VecTupTy, Mask->getType(), EVL->getType()});
23324 Value *
Operands[] = {StoredVal, Store->getArgOperand(1), Mask, EVL,
23325 ConstantInt::get(XLenTy,
Log2_64(SEW))};
23336 "Invalid call instruction for a KCFI check");
23338 MBBI->getOpcode()));
23341 Target.setIsRenamable(
false);
23349#define GET_REGISTER_MATCHER
23350#include "RISCVGenAsmMatcher.inc"
23356 if (Reg == RISCV::NoRegister)
23358 if (Reg == RISCV::NoRegister)
23370 const MDNode *NontemporalInfo =
I.getMetadata(LLVMContext::MD_nontemporal);
23372 if (NontemporalInfo ==
nullptr)
23380 int NontemporalLevel = 5;
23381 const MDNode *RISCVNontemporalInfo =
23382 I.getMetadata(
"riscv-nontemporal-domain");
23383 if (RISCVNontemporalInfo !=
nullptr)
23386 cast<ConstantAsMetadata>(RISCVNontemporalInfo->
getOperand(0))
23390 assert((1 <= NontemporalLevel && NontemporalLevel <= 5) &&
23391 "RISC-V target doesn't support this non-temporal domain.");
23393 NontemporalLevel -= 2;
23395 if (NontemporalLevel & 0b1)
23397 if (NontemporalLevel & 0b10)
23410 return TargetFlags;
23420 return isTypeLegal(VT) && Subtarget.hasStdExtZvbb();
23423 return Subtarget.hasStdExtZbb() &&
23434 if (Subtarget.hasStdExtZalasr()) {
23435 if (Subtarget.hasStdExtZtso()) {
23440 auto *LI = dyn_cast<LoadInst>(
I);
23441 auto *SI = dyn_cast<StoreInst>(
I);
23451 return isa<LoadInst>(
I) || isa<StoreInst>(
I);
23458 return isa<LoadInst>(
I) || isa<StoreInst>(
I);
23465 if (
Op == Instruction::Add ||
Op == Instruction::Sub ||
23466 Op == Instruction::And ||
Op == Instruction::Or ||
23467 Op == Instruction::Xor ||
Op == Instruction::InsertElement ||
23468 Op == Instruction::ShuffleVector ||
Op == Instruction::Load ||
23469 Op == Instruction::Freeze ||
Op == Instruction::Store)
23477 !isa<ReturnInst>(&Inst))
23480 if (
const AllocaInst *AI = dyn_cast<AllocaInst>(&Inst)) {
23481 if (AI->getAllocatedType()->isScalableTy())
23489RISCVTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
23497 if (!Subtarget.hasShortForwardBranchOpt())
23499 EVT VT =
N->getValueType(0);
23500 if (!(VT == MVT::i32 || (VT == MVT::i64 && Subtarget.
is64Bit())))
23504 if (Divisor.
sgt(2048) || Divisor.
slt(-2048))
23509bool RISCVTargetLowering::shouldFoldSelectWithSingleBitTest(
23510 EVT VT,
const APInt &AndMask)
const {
23511 if (Subtarget.hasStdExtZicond() || Subtarget.hasVendorXVentanaCondOps())
23512 return !Subtarget.hasStdExtZbs() && AndMask.
ugt(1024);
23516unsigned RISCVTargetLowering::getMinimumJumpTableEntries()
const {
23524 if (Subtarget.hasStdExtZicfilp()) {
23548std::pair<const TargetRegisterClass *, uint8_t>
23568#define GET_RISCVVIntrinsicsTable_IMPL
23569#include "RISCVGenSearchableTables.inc"
23584 Align StackAlign)
const {
23588 unsigned StackProbeSize =
23592 return StackProbeSize ? StackProbeSize : StackAlign.
value();
23607 cast<ConstantSDNode>(
Op.getOperand(2))->getMaybeAlignValue();
23609 EVT VT =
Op.getValueType();
23630 Register TargetReg =
MI.getOperand(1).getReg();
23633 bool IsRV64 = Subtarget.
is64Bit();
23641 MF.
insert(MBBInsertPoint, LoopTestMBB);
23643 MF.
insert(MBBInsertPoint, ExitMBB);
23659 TII->get(IsRV64 ? RISCV::SD : RISCV::SW))
23682 MI.eraseFromParent();
23684 return ExitMBB->
begin()->getParent();
unsigned const MachineRegisterInfo * MRI
static MCRegister MatchRegisterName(StringRef Name)
static EVT getContainerForFixedLengthVector(SelectionDAG &DAG, EVT VT)
static SDValue performSHLCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
If the operand is a bitwise AND with a constant RHS, and the shift has a constant RHS and is the only...
static SDValue performORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const AArch64Subtarget *Subtarget, const AArch64TargetLowering &TLI)
static SDValue performANDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue tryWidenMaskForShuffle(SDValue Op, SelectionDAG &DAG)
static SDValue performSETCCCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
static SDValue convertToScalableVector(SelectionDAG &DAG, EVT VT, SDValue V)
static SDValue convertFromScalableVector(SelectionDAG &DAG, EVT VT, SDValue V)
#define NODE_NAME_CASE(node)
static bool isConstant(const MachineInstr &MI)
AMDGPU Register Bank Select
static bool isZeroOrAllOnes(SDValue N, bool AllOnes)
static SDValue combineSelectAndUseCommutative(SDNode *N, bool AllOnes, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp, TargetLowering::DAGCombinerInfo &DCI, bool AllOnes=false)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static MCRegister MatchRegisterAltName(StringRef Name)
Maps from the set of all alternative registernames to a register number.
Function Alias Analysis Results
static SDValue getTargetNode(GlobalAddressSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, unsigned Flags)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Analysis containing CSE Info
static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static MachineBasicBlock * emitSelectPseudo(MachineInstr &MI, MachineBasicBlock *BB, unsigned Opcode)
static SDValue unpackFromRegLoc(const CSKYSubtarget &Subtarget, SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
const HexagonInstrInfo * TII
This file defines an InstructionCost class that is used when calculating the cost of an instruction,...
static Align getPrefTypeAlign(EVT VT, SelectionDAG &DAG)
static SDValue customLegalizeToWOpWithSExt(SDNode *N, SelectionDAG &DAG)
static SDValue customLegalizeToWOp(SDNode *N, SelectionDAG &DAG, int NumOp, unsigned ExtOpc=ISD::ANY_EXTEND)
static Intrinsic::ID getIntrinsicForMaskedAtomicRMWBinOp(unsigned GRLen, AtomicRMWInst::BinOp BinOp)
loop Loop Strength Reduction
static bool isSplat(Value *V)
Return true if V is a splat of a value (which is used when multiplying a matrix with a scalar).
mir Rename Register Operands
unsigned const TargetRegisterInfo * TRI
This file provides utility analysis objects describing memory locations.
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const MipsSubtarget &Subtarget)
static SDValue performSUBCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const MipsSubtarget &Subtarget)
static SDValue performSELECTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const MipsSubtarget &Subtarget)
static SDValue performMULCombine(SDNode *N, SelectionDAG &DAG, const TargetLowering::DAGCombinerInfo &DCI, const MipsSETargetLowering *TL, const MipsSubtarget &Subtarget)
static SDValue performXORCombine(SDNode *N, SelectionDAG &DAG, const MipsSubtarget &Subtarget)
static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG)
static SDValue performSRACombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const MipsSubtarget &Subtarget)
uint64_t IntrinsicInst * II
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
static CodeModel::Model getCodeModel(const PPCSubtarget &S, const TargetMachine &TM, const MachineOperand &MO)
static StringRef getName(Value *V)
static constexpr MCPhysReg SPReg
static StringRef getExtensionType(StringRef Ext)
static SDValue performCONCAT_VECTORSCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue SplitVectorReductionOp(SDValue Op, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static MachineBasicBlock * emitBuildPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const RISCVSubtarget &Subtarget)
static MachineBasicBlock * emitQuietFCMP(MachineInstr &MI, MachineBasicBlock *BB, unsigned RelOpcode, unsigned EqOpcode, const RISCVSubtarget &Subtarget)
static int isElementRotate(int &LoSrc, int &HiSrc, ArrayRef< int > Mask)
Match shuffles that concatenate two vectors, rotate the concatenation, and then extract the original ...
static bool isLowSourceShuffle(ArrayRef< int > Mask, int Span)
Is this mask only using elements from the first span of the input?
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 bool isMultipleOfN(const Value *V, const DataLayout &DL, unsigned N)
static std::optional< APInt > getExactInteger(const APFloat &APF, uint32_t BitWidth)
static SDValue performVP_TRUNCATECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isInterleaveShuffle(ArrayRef< int > Mask, MVT VT, int &EvenSrc, int &OddSrc, const RISCVSubtarget &Subtarget)
Is this shuffle interleaving contiguous elements from one vector into the even elements and contiguou...
static bool narrowIndex(SDValue &N, ISD::MemIndexType IndexType, SelectionDAG &DAG)
According to the property that indexed load/store instructions zero-extend their indices,...
static unsigned getPACKOpcode(unsigned DestBW, const RISCVSubtarget &Subtarget)
static void promoteVCIXScalar(const SDValue &Op, SmallVectorImpl< SDValue > &Operands, SelectionDAG &DAG)
static SDValue splatSplitI64WithVL(const SDLoc &DL, MVT VT, SDValue Passthru, SDValue Scalar, SDValue VL, SelectionDAG &DAG)
static SDValue splatPartsI64WithVL(const SDLoc &DL, MVT VT, SDValue Passthru, SDValue Lo, SDValue Hi, SDValue VL, SelectionDAG &DAG)
static SDValue getWideningInterleave(SDValue EvenV, SDValue OddV, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue getAllOnesMask(MVT VecVT, SDValue VL, const SDLoc &DL, SelectionDAG &DAG)
Creates an all ones mask suitable for masking a vector of type VecTy with vector length VL.
static cl::opt< int > FPImmCost(DEBUG_TYPE "-fpimm-cost", cl::Hidden, cl::desc("Give the maximum number of instructions that we will " "use for creating a floating-point immediate value"), cl::init(2))
static SDValue lowerScalarSplat(SDValue Passthru, SDValue Scalar, SDValue VL, MVT VT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static const RISCV::RISCVMaskedPseudoInfo * lookupMaskedIntrinsic(uint16_t MCOpcode, RISCVII::VLMUL LMul, unsigned SEW)
static SDValue expandMul(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue performVWADDSUBW_VLCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static bool matchIndexAsWiderOp(EVT VT, SDValue Index, SDValue Mask, Align BaseAlign, const RISCVSubtarget &ST)
Match the index of a gather or scatter operation as an operation with twice the element width and hal...
static bool isLegalBitRotate(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, MVT &RotateVT, unsigned &RotateAmt)
static SDValue combineOp_VLToVWOp_VL(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
Combine a binary or FMA operation to its equivalent VW or VW_W form.
static SDValue combineVFMADD_VLWithVFNEG_VL(SDNode *N, SelectionDAG &DAG)
static SDValue combineOrOfCZERO(SDNode *N, SDValue N0, SDValue N1, SelectionDAG &DAG)
static SDValue useInversedSetcc(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerDisjointIndicesShuffle(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Given a shuffle where the indices are disjoint between the two sources, e.g.:
static SDValue combineVWADDSUBWSelect(SDNode *N, SelectionDAG &DAG)
static MachineBasicBlock * EmitLoweredCascadedSelect(MachineInstr &First, MachineInstr &Second, MachineBasicBlock *ThisMBB, const RISCVSubtarget &Subtarget)
static SDValue performINSERT_VECTOR_ELTCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue lowerFABSorFNEG(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerFMAXIMUM_FMINIMUM(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue SplitStrictFPVectorOp(SDValue Op, SelectionDAG &DAG)
static SDValue tryDemorganOfBooleanCondition(SDValue Cond, SelectionDAG &DAG)
static SDValue performMemPairCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue combineDeMorganOfBoolean(SDNode *N, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLEAsVSlidedown(const SDLoc &DL, MVT VT, SDValue V1, SDValue V2, ArrayRef< int > Mask, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
static unsigned getRVVReductionOp(unsigned ISDOpcode)
static SDValue combineSubShiftToOrcB(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::optional< bool > matchSetCC(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue Val)
static SDValue lowerShuffleViaVRegSplitting(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue getVCIXISDNodeVOID(SDValue &Op, SelectionDAG &DAG, unsigned Type)
static SDValue lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static cl::opt< unsigned > NumRepeatedDivisors(DEBUG_TYPE "-fp-repeated-divisors", cl::Hidden, cl::desc("Set the minimum number of repetitions of a divisor to allow " "transformation to multiplications by the reciprocal"), cl::init(2))
static SDValue foldSelectOfCTTZOrCTLZ(SDNode *N, SelectionDAG &DAG)
static SDValue lowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue foldBinOpIntoSelectIfProfitable(SDNode *BO, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue combineVectorMulToSraBitcast(SDNode *N, SelectionDAG &DAG)
static bool isLocalRepeatingShuffle(ArrayRef< int > Mask, int Span)
Is this mask local (i.e.
static SDValue combineScalarCTPOPToVCPOP(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool hasMaskOp(unsigned Opcode)
Return true if a RISC-V target specified op has a mask operand.
static bool legalizeScatterGatherIndexType(SDLoc DL, SDValue &Index, ISD::MemIndexType &IndexType, RISCVTargetLowering::DAGCombinerInfo &DCI)
static SDValue combineSelectToBinOp(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isSpreadMask(ArrayRef< int > Mask, unsigned Factor, unsigned &Index)
static unsigned getRISCVVLOp(SDValue Op)
Get a RISC-V target specified VL op for a given SDNode.
static unsigned getVecReduceOpcode(unsigned Opc)
Given a binary operator, return the associative generic ISD::VECREDUCE_OP which corresponds to it.
static std::pair< SDValue, SDValue > getDefaultVLOps(uint64_t NumElts, MVT ContainerVT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isPromotedOpNeedingSplit(SDValue Op, const RISCVSubtarget &Subtarget)
static SDValue performFP_TO_INT_SATCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue lowerReductionSeq(unsigned RVVOpcode, MVT ResVT, SDValue StartValue, SDValue Vec, SDValue Mask, SDValue VL, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Helper to lower a reduction sequence of the form: scalar = reduce_op vec, scalar_start.
static SDValue performVP_REVERSECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerGetVectorLength(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::pair< SDValue, SDValue > getDefaultScalableVLOps(MVT VecVT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue getVLOperand(SDValue Op)
static SDValue performVECTOR_SHUFFLECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue performVP_STORECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static MachineBasicBlock * emitFROUND(MachineInstr &MI, MachineBasicBlock *MBB, const RISCVSubtarget &Subtarget)
static SDValue getLargeExternalSymbol(ExternalSymbolSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG)
static SDValue lowerCttzElts(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerVectorIntrinsicScalars(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue performSIGN_EXTEND_INREGCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerVectorXRINT(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static cl::opt< unsigned > ExtensionMaxWebSize(DEBUG_TYPE "-ext-max-web-size", cl::Hidden, cl::desc("Give the maximum size (in number of nodes) of the web of " "instructions that we will consider for VW expansion"), cl::init(18))
static SDValue getDeinterleaveShiftAndTrunc(const SDLoc &DL, MVT VT, SDValue Src, unsigned Factor, unsigned Index, SelectionDAG &DAG)
static SDValue combineBinOpOfZExt(SDNode *N, SelectionDAG &DAG)
static bool matchSelectAddSub(SDValue TrueVal, SDValue FalseVal, bool &SwapCC)
static bool isSelectPseudo(MachineInstr &MI)
static std::optional< MVT > getSmallestVTForIndex(MVT VecVT, unsigned MaxIdx, SDLoc DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool useRVVForFixedLengthVectorVT(MVT VT, const RISCVSubtarget &Subtarget)
static Value * useTpOffset(IRBuilderBase &IRB, unsigned Offset)
static SDValue combineAddOfBooleanXor(SDNode *N, SelectionDAG &DAG)
static SDValue combineTruncOfSraSext(SDNode *N, SelectionDAG &DAG)
static SDValue getSingleShuffleSrc(MVT VT, MVT ContainerVT, SDValue V1, SDValue V2)
static MachineBasicBlock * emitSplitF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const RISCVSubtarget &Subtarget)
static MachineBasicBlock * emitVFROUND_NOEXCEPT_MASK(MachineInstr &MI, MachineBasicBlock *BB, unsigned CVTXOpc)
static SDValue SplitVectorOp(SDValue Op, SelectionDAG &DAG)
static unsigned negateFMAOpcode(unsigned Opcode, bool NegMul, bool NegAcc)
static SDValue lowerScalarInsert(SDValue Scalar, SDValue VL, MVT VT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue transformAddShlImm(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue tryFoldSelectIntoOp(SDNode *N, SelectionDAG &DAG, SDValue TrueVal, SDValue FalseVal, bool Swapped)
static SDValue lowerBitreverseShuffle(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerConstant(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool matchIndexAsShuffle(EVT VT, SDValue Index, SDValue Mask, SmallVector< int > &ShuffleMask)
Match the index vector of a scatter or gather node as the shuffle mask which performs the rearrangeme...
static SDValue performVFMADD_VLCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue combineBinOpToReduce(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue SplitVPOp(SDValue Op, SelectionDAG &DAG)
static SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static void processVCIXOperands(SDValue &OrigOp, SmallVectorImpl< SDValue > &Operands, SelectionDAG &DAG)
static SDValue widenVectorOpsToi8(SDValue N, const SDLoc &DL, SelectionDAG &DAG)
static SDValue lowerINT_TO_FP(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerVectorFTRUNC_FCEIL_FFLOOR_FROUND(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerFTRUNC_FCEIL_FFLOOR_FROUND(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::optional< VIDSequence > isSimpleVIDSequence(SDValue Op, unsigned EltSizeInBits)
static SDValue getVSlideup(SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const SDLoc &DL, EVT VT, SDValue Passthru, SDValue Op, SDValue Offset, SDValue Mask, SDValue VL, unsigned Policy=RISCVII::TAIL_UNDISTURBED_MASK_UNDISTURBED)
static uint64_t computeGREVOrGORC(uint64_t x, unsigned ShAmt, bool IsGORC)
static SDValue lowerVECTOR_SHUFFLEAsRotate(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static RISCVFPRndMode::RoundingMode matchRoundingOp(unsigned Opc)
static SDValue lowerVectorStrictFTRUNC_FCEIL_FFLOOR_FROUND(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue combineTruncSelectToSMaxUSat(SDNode *N, SelectionDAG &DAG)
static SDValue performBITREVERSECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue transformAddImmMulImm(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue combineSubOfBoolean(SDNode *N, SelectionDAG &DAG)
static SDValue matchSplatAsGather(SDValue SplatVal, MVT VT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isValidEGW(int EGS, EVT VT, const RISCVSubtarget &Subtarget)
static bool combine_CC(SDValue &LHS, SDValue &RHS, SDValue &CC, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isNonZeroAVL(SDValue AVL)
static SDValue lowerFP_TO_INT(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLEAsVSlideup(const SDLoc &DL, MVT VT, SDValue V1, SDValue V2, ArrayRef< int > Mask, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
static SDValue getVCIXISDNodeWCHAIN(SDValue &Op, SelectionDAG &DAG, unsigned Type)
static SDValue getLargeGlobalAddress(GlobalAddressSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG)
static MachineBasicBlock * emitReadCounterWidePseudo(MachineInstr &MI, MachineBasicBlock *BB)
static SDValue getWideningSpread(SDValue V, unsigned Factor, unsigned Index, const SDLoc &DL, SelectionDAG &DAG)
static cl::opt< bool > AllowSplatInVW_W(DEBUG_TYPE "-form-vw-w-with-splat", cl::Hidden, cl::desc("Allow the formation of VW_W operations (e.g., " "VWADD_W) with splat constants"), cl::init(false))
static SDValue unpackF64OnRV32DSoftABI(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const CCValAssign &HiVA, const SDLoc &DL)
static SDValue tryMemPairCombine(SelectionDAG &DAG, LSBaseSDNode *LSNode1, LSBaseSDNode *LSNode2, SDValue BasePtr, uint64_t Imm)
static std::tuple< unsigned, SDValue, SDValue > getRVVFPReductionOpAndOperands(SDValue Op, SelectionDAG &DAG, EVT EltVT, const RISCVSubtarget &Subtarget)
static SDValue performFP_TO_INTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue combineBinOpOfExtractToReduceTree(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Perform two related transforms whose purpose is to incrementally recognize an explode_vector followed...
static SDValue lowerBuildVectorViaPacking(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Double the element size of the build vector to reduce the number of vslide1down in the build vector c...
static SDValue performTRUNCATECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerBuildVectorViaDominantValues(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Try and optimize BUILD_VECTORs with "dominant values" - these are values which constitute a large pro...
static bool isCompressMask(ArrayRef< int > Mask)
static void translateSetCCForBranch(const SDLoc &DL, SDValue &LHS, SDValue &RHS, ISD::CondCode &CC, SelectionDAG &DAG)
static SDValue combineToVWMACC(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue performBUILD_VECTORCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
If we have a build_vector where each lane is binop X, C, where C is a constant (but not necessarily t...
static const Intrinsic::ID FixedVssegIntrIds[]
static SDValue getVSlidedown(SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const SDLoc &DL, EVT VT, SDValue Passthru, SDValue Op, SDValue Offset, SDValue Mask, SDValue VL, unsigned Policy=RISCVII::TAIL_UNDISTURBED_MASK_UNDISTURBED)
static LLT getMaskTypeFor(LLT VecTy)
Return the type of the mask type suitable for masking the provided vector type.
static unsigned getRISCVWOpcode(unsigned Opcode)
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static Type * getValueType(Value *V)
Returns the type of the given value/instruction V.
static bool isCommutative(Instruction *I)
This file defines the SmallSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static SymbolRef::Type getType(const Symbol *Sym)
static constexpr int Concat[]
opStatus convertFromAPInt(const APInt &Input, bool IsSigned, roundingMode RM)
opStatus convertToInteger(MutableArrayRef< integerPart > Input, unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const
static APFloat getNaN(const fltSemantics &Sem, bool Negative=false, uint64_t payload=0)
Factory for NaN values.
Class for arbitrary precision integers.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
uint64_t getZExtValue() const
Get zero extended value.
void setBitsFrom(unsigned loBit)
Set the top bits starting from loBit.
unsigned getActiveBits() const
Compute the number of active bits in the value.
APInt trunc(unsigned width) const
Truncate to new width.
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
bool sgt(const APInt &RHS) const
Signed greater than comparison.
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
bool ugt(const APInt &RHS) const
Unsigned greater than comparison.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
bool isNegative() const
Determine sign of this APInt.
APInt sdiv(const APInt &RHS) const
Signed division function for APInt.
void clearAllBits()
Set every bit to 0.
bool isSignedIntN(unsigned N) const
Check if this APInt has an N-bits signed integer value.
static APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
unsigned getSignificantBits() const
Get the minimum bit size for this signed APInt.
void insertBits(const APInt &SubBits, unsigned bitPosition)
Insert the bits from a smaller APInt starting at bitPosition.
APInt srem(const APInt &RHS) const
Function for signed remainder operation.
bool isMask(unsigned numBits) const
bool isNonNegative() const
Determine if this APInt Value is non-negative (>= 0)
APInt sext(unsigned width) const
Sign extend to a new width.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
bool slt(const APInt &RHS) const
Signed less than comparison.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
void setLowBits(unsigned loBits)
Set the bottom loBits bits.
APInt extractBits(unsigned numBits, unsigned bitPosition) const
Return an APInt with the extracted bits [bitPosition,bitPosition+numBits).
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)
Constructs an APInt value that has a contiguous range of bits set.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
int64_t getSExtValue() const
Get sign extended value.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
An arbitrary precision integer that knows its signedness.
an instruction to allocate memory on the stack
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.
An instruction that atomically checks whether a specified value is in a memory location,...
Value * getCompareOperand()
an instruction that atomically reads a memory location, combines it with another value,...
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ USubCond
Subtract only if no unsigned overflow.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ UMax
*p = old >unsigned v ? old : v
@ UDecWrap
Decrement one until a minimum value or zero.
bool isFloatingPointOperation() const
BinOp getOperation() const
AtomicOrdering getOrdering() const
Returns the ordering constraint of this rmw instruction.
bool hasFnAttr(Attribute::AttrKind Kind) const
Return true if the attribute exists for the function.
StringRef getValueAsString() const
Return the attribute's value as a string.
static Attribute getWithAlignment(LLVMContext &Context, Align Alignment)
Return a uniquified Attribute object that has the specific alignment set.
static BaseIndexOffset match(const SDNode *N, const SelectionDAG &DAG)
Parses tree in N for base, index, offset addresses.
LLVM Basic Block Representation.
const Module * getModule() const
Return the module owning the function this basic block belongs to, or nullptr if the function does no...
bool test(unsigned Idx) const
bool all() const
all - Returns true if all bits are set.
CCState - This class holds information needed while lowering arguments and return values.
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
void AnalyzeCallOperands(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeCallOperands - Analyze the outgoing arguments to a call, incorporating info about the passed v...
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
bool isMustTailCall() const
Tests if this call site must be tail call optimized.
bool isIndirectCall() const
Return true if the callsite is an indirect call.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
This class represents a function call, abstracting a target machine's calling convention.
bool isExactlyValue(double V) const
We don't rely on operator== working on double values, as it returns true for things that are clearly ...
This is the shared class of boolean and integer constants.
bool isMinusOne() const
This function will return true iff every bit in this constant is set to true.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
This is an important base class in LLVM.
static Constant * getAllOnesValue(Type *Ty)
This class represents an Operation in the Expression.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
unsigned getPointerSizeInBits(unsigned AS=0) const
Layout pointer size, in bits FIXME: The defaults need to be removed once all of the backends/clients ...
Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
const ValueT & at(const_arg_type_t< KeyT > Val) const
at - Return the entry for the specified key, or abort if no such entry exists.
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)
Tagged union holding either a T or a Error.
static FixedVectorType * get(Type *ElementType, unsigned NumElts)
Class to represent function types.
Type * getParamType(unsigned i) const
Parameter type accessors.
Type * getReturnType() const
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
uint64_t getFnAttributeAsParsedInteger(StringRef Kind, uint64_t Default=0) const
For a string attribute Kind, parse attribute as an integer.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
AttributeList getAttributes() const
Return the attribute list for this Function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Argument * getArg(unsigned i) const
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Helper struct to store a base, index and offset that forms an address.
int64_t getOffset() const
bool hasExternalWeakLinkage() const
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
Store the specified register of the given register class to the specified stack frame index.
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
Load the specified register of the given register class from the specified stack frame index.
Common base class shared among various IRBuilders.
Value * CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
FenceInst * CreateFence(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System, const Twine &Name="")
Value * CreateSExt(Value *V, Type *DestTy, const Twine &Name="")
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Value * CreatePtrAdd(Value *Ptr, Value *Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
BasicBlock * GetInsertBlock() const
IntegerType * getInt64Ty()
Fetch the type representing a 64-bit integer.
Value * CreateUDiv(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Value * getAllOnesMask(ElementCount NumElts)
Return an all true boolean vector (mask) with NumElts lanes.
CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
Value * CreateNot(Value *V, const Twine &Name="")
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
ConstantInt * getIntN(unsigned N, uint64_t C)
Get a constant N-bit value, zero extended or truncated from a 64-bit value.
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
AtomicRMWInst * CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr, Value *Val, MaybeAlign Align, AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
static InstructionCost getInvalid(CostType Val=0)
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Class to represent integer types.
This is an important class for using LLVM in a threaded context.
void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
Base class for LoadSDNode and StoreSDNode.
bool isIndexed() const
Return true if this is a pre/post inc/dec load/store.
An instruction for reading from memory.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
Value * getPointerOperand()
Type * getPointerOperandType() const
Align getAlign() const
Return the alignment of the access that is being performed.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
static constexpr LocationSize beforeOrAfterPointer()
Any location before or after the base pointer (but still within the underlying object).
Context object for machine code objects.
Base class for the full range of assembler expressions which are needed for parsing.
Instances of this class represent a single low-level machine instruction.
MCContext & getContext() const
Generic base class for all target subtargets.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
const MDOperand & getOperand(unsigned I) const
static MVT getFloatingPointVT(unsigned BitWidth)
static auto integer_fixedlen_vector_valuetypes()
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
bool isRISCVVectorTuple() const
Return true if this is a RISCV vector tuple type where the runtime length is machine dependent.
uint64_t getScalarSizeInBits() const
MVT changeVectorElementType(MVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
bool bitsLE(MVT VT) const
Return true if this has no more bits than VT.
unsigned getVectorNumElements() const
static MVT getRISCVVectorTupleVT(unsigned Sz, unsigned NFields)
bool isVector() const
Return true if this is a vector value type.
bool isInteger() const
Return true if this is an integer or a vector integer type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
static MVT getScalableVectorVT(MVT VT, unsigned NumElements)
unsigned getRISCVVectorTupleNumFields() const
Given a RISC-V vector tuple type, return the num_fields.
MVT changeTypeToInteger()
Return the type converted to an equivalently sized integer or vector with integer element type.
static MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
bool bitsLT(MVT VT) const
Return true if this has less bits than VT.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
const fltSemantics & getFltSemantics() const
Returns an APFloat semantics tag appropriate for the value type.
bool bitsGT(MVT VT) const
Return true if this has more bits than VT.
bool isFixedLengthVector() const
ElementCount getVectorElementCount() const
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool bitsGE(MVT VT) const
Return true if this has no less bits than VT.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
bool isValid() const
Return true if this is a valid simple valuetype.
static MVT getIntegerVT(unsigned BitWidth)
MVT getDoubleNumVectorElementsVT() const
MVT getHalfNumVectorElementsVT() const
Return a VT for a vector type with the same element type but half the number of elements.
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
static auto integer_scalable_vector_valuetypes()
MVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
static auto fp_fixedlen_vector_valuetypes()
void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
void push_back(MachineInstr *MI)
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any debug instructions.
Instructions::iterator instr_iterator
instr_iterator instr_end()
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
void collectDebugValues(SmallVectorImpl< MachineInstr * > &DbgValues)
Scan instructions immediately following MI and collect any matching DBG_VALUEs.
void setFlag(MIFlag Flag)
Set a MI flag.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
@ EK_Custom32
EK_Custom32 - Each entry is a 32-bit value that is custom lowered by the TargetLowering::LowerCustomJ...
A description of a memory reference used in the backend.
const MDNode * getRanges() const
Return the range tag for the memory reference.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MONonTemporal
The memory access is non-temporal.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
const MachinePointerInfo & getPointerInfo() const
Flags getFlags() const
Return the raw flags of the source value,.
AAMDNodes getAAInfo() const
Return the AA tags for the memory reference.
Align getBaseAlign() const
Return the minimum known alignment in bytes of the base address, without the offset.
MachineOperand class - Representation of each machine instruction operand.
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
void addLiveIn(MCRegister Reg, Register vreg=Register())
addLiveIn - Add the specified register as a live-in.
This is an abstract virtual class for memory operations.
bool isSimple() const
Returns true if the memory operation is neither atomic or volatile.
MachineMemOperand * getMemOperand() const
Return a MachineMemOperand object describing the memory reference performed by operation.
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
A Module instance is used to store all the information related to an LLVM module.
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A RISCV-specific constant pool value.
static RISCVConstantPoolValue * Create(const GlobalValue *GV)
RISCVMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private RISCV-...
void setVarArgsFrameIndex(int Index)
int getVarArgsFrameIndex() const
void setVarArgsSaveSize(int Size)
void addSExt32Register(Register Reg)
RISCVABI::ABI getTargetABI() const
unsigned getMinimumJumpTableEntries() const
bool hasStdExtCOrZca() const
unsigned getMaxLMULForFixedLengthVectors() const
bool hasVInstructionsI64() const
bool hasVInstructionsF64() const
unsigned getMaxStoresPerMemcpy(bool OptSize) const
bool hasStdExtDOrZdinx() const
unsigned getMaxLoadsPerMemcmp(bool OptSize) const
bool hasStdExtZfhOrZhinx() const
unsigned getRealMinVLen() const
unsigned getMaxStoresPerMemset(bool OptSize) const
Quantity expandVScale(Quantity X) const
If the ElementCount or TypeSize X is scalable and VScale (VLEN) is exactly known, returns X converted...
bool useRVVForFixedLengthVectors() const
bool isTargetFuchsia() const
bool hasVInstructionsBF16Minimal() const
unsigned getDLenFactor() const
unsigned getMaxStoresPerMemmove(bool OptSize) const
bool hasVInstructionsF16Minimal() const
unsigned getMaxGluedStoresPerMemcpy() const
bool hasConditionalMoveFusion() const
bool hasVInstructionsF16() const
unsigned getMaxBuildIntsCost() const
bool useCCMovInsn() const
Align getPrefLoopAlignment() const
bool hasVInstructions() const
bool isRegisterReservedByUser(Register i) const override
std::optional< unsigned > getRealVLen() const
bool hasOptimizedSegmentLoadStore(unsigned NF) const
bool useConstantPoolForLargeInts() const
Align getPrefFunctionAlignment() const
bool hasStdExtZfhminOrZhinxmin() const
unsigned getRealMaxVLen() const
const RISCVRegisterInfo * getRegisterInfo() const override
const RISCVInstrInfo * getInstrInfo() const override
const RISCVTargetLowering * getTargetLowering() const override
bool hasVInstructionsF32() const
bool isTargetAndroid() const
bool hasStdExtFOrZfinx() const
const RISCVFrameLowering * getFrameLowering() const override
static std::pair< unsigned, unsigned > computeVLMAXBounds(MVT ContainerVT, const RISCVSubtarget &Subtarget)
static std::pair< unsigned, unsigned > decomposeSubvectorInsertExtractToSubRegs(MVT VecVT, MVT SubVecVT, unsigned InsertExtractIdx, const RISCVRegisterInfo *TRI)
InstructionCost getVRGatherVVCost(MVT VT) const
Return the cost of a vrgather.vv instruction for the type VT.
bool getIndexedAddressParts(SDNode *Op, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const
static unsigned getSubregIndexByMVT(MVT VT, unsigned Index)
Value * getIRStackGuard(IRBuilderBase &IRB) const override
If the target has a standard location for the stack protector cookie, returns the address of that loc...
bool shouldConvertFpToSat(unsigned Op, EVT FPVT, EVT VT) const override
Should we generate fp_to_si_sat and fp_to_ui_sat from type FPVT to type VT from min(max(fptoi)) satur...
InlineAsm::ConstraintCode getInlineAsmMemConstraint(StringRef ConstraintCode) const override
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
bool shouldFoldSelectWithIdentityConstant(unsigned BinOpcode, EVT VT) const override
Return true if pulling a binary operation into a select with an identity constant is profitable.
bool mayBeEmittedAsTailCall(const CallInst *CI) const override
Return true if the target may be able emit the call instruction as a tail call.
RISCVTargetLowering(const TargetMachine &TM, const RISCVSubtarget &STI)
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
Instruction * emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
Inserts in the IR a target-specific intrinsic specifying a fence.
bool isTruncateFree(Type *SrcTy, Type *DstTy) const override
Return true if it's free to truncate a value of type FromTy to type ToTy.
bool lowerInterleaveIntrinsicToStore(StoreInst *SI, ArrayRef< Value * > InterleaveValues) const override
Lower an interleave intrinsic to a target specific store intrinsic.
bool shouldRemoveExtendFromGSIndex(SDValue Extend, EVT DataVT) const override
Value * emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI, Value *AlignedAddr, Value *Incr, Value *Mask, Value *ShiftAmt, AtomicOrdering Ord) const override
Perform a masked atomicrmw using a target-specific intrinsic.
EVT getOptimalMemOpType(const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const override
Returns true if the target allows unaligned memory accesses of the specified type.
const Constant * getTargetConstantFromLoad(LoadSDNode *LD) const override
This method returns the constant pool value that will be loaded by LD.
const RISCVSubtarget & getSubtarget() const
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
bool preferScalarizeSplat(SDNode *N) const override
const char * getTargetNodeName(unsigned Opcode) const override
This method returns the name of a target specific DAG node.
bool shouldExtendTypeInLibCall(EVT Type) const override
Returns true if arguments should be extended in lib calls.
bool isLegalAddImmediate(int64_t Imm) const override
Return true if the specified immediate is legal add immediate, that is the target has add instruction...
bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const override
Returns true if arguments should be sign-extended in lib calls.
const MCExpr * LowerCustomJumpTableEntry(const MachineJumpTableInfo *MJTI, const MachineBasicBlock *MBB, unsigned uid, MCContext &Ctx) const override
InstructionCost getVRGatherVICost(MVT VT) const
Return the cost of a vrgather.vi (or vx) instruction for the type VT.
bool shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const override
Return true if it is beneficial to convert a load of a constant to just the constant itself.
bool targetShrinkDemandedConstant(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, TargetLoweringOpt &TLO) const override
bool shouldExpandBuildVectorWithShuffles(EVT VT, unsigned DefinedValues) const override
MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Return the register type for a given MVT, ensuring vectors are treated as a series of gpr sized integ...
bool decomposeMulByConstant(LLVMContext &Context, EVT VT, SDValue C) const override
Return true if it is profitable to transform an integer multiplication-by-constant into simpler opera...
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, LLVMContext &Context, const Type *RetTy) const override
This hook should be implemented to check whether the return values described by the Outs array can fi...
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
bool hasAndNotCompare(SDValue Y) const override
Return true if the target should transform: (X & Y) == Y —> (~X & Y) == 0 (X & Y) !...
bool shouldScalarizeBinop(SDValue VecOp) const override
Try to convert an extract element of a vector binary operation into an extract element followed by a ...
bool isDesirableToCommuteWithShift(const SDNode *N, CombineLevel Level) const override
Return true if it is profitable to move this shift by a constant amount through its operand,...
bool areTwoSDNodeTargetMMOFlagsMergeable(const MemSDNode &NodeX, const MemSDNode &NodeY) const override
Return true if it is valid to merge the TargetMMOFlags in two SDNodes.
bool hasBitTest(SDValue X, SDValue Y) const override
Return true if the target has a bit-test instruction: (X & (1 << Y)) ==/!= 0 This knowledge can be us...
static unsigned computeVLMAX(unsigned VectorBits, unsigned EltSize, unsigned MinSize)
bool shouldExpandCttzElements(EVT VT) const override
Return true if the @llvm.experimental.cttz.elts intrinsic should be expanded using generic code in Se...
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
Value * emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, AtomicCmpXchgInst *CI, Value *AlignedAddr, Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const override
Perform a masked cmpxchg using a target-specific intrinsic.
bool isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize) const override
Returns true if the target can instruction select the specified FP immediate natively.
InstructionCost getLMULCost(MVT VT) const
Return the cost of LMUL for linear operations.
unsigned getJumpTableEncoding() const override
Return the entry encoding for a jump table in the current function.
bool isMulAddWithConstProfitable(SDValue AddNode, SDValue ConstNode) const override
Return true if it may be profitable to transform (mul (add x, c1), c2) -> (add (mul x,...
InstructionCost getVSlideVICost(MVT VT) const
Return the cost of a vslidedown.vi or vslideup.vi instruction for the type VT.
bool fallBackToDAGISel(const Instruction &Inst) const override
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
bool lowerInterleavedLoad(LoadInst *LI, ArrayRef< ShuffleVectorInst * > Shuffles, ArrayRef< unsigned > Indices, unsigned Factor) const override
Lower an interleaved load into a vlsegN intrinsic.
bool isCtpopFast(EVT VT) const override
Return true if ctpop instruction is fast.
unsigned ComputeNumSignBitsForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
This method can be implemented by targets that want to expose additional information about sign bits ...
MVT getContainerForFixedLengthVector(MVT VT) const
static unsigned getRegClassIDForVecVT(MVT VT)
Register getExceptionPointerRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
TargetLowering::AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return true if EXTRACT_SUBVECTOR is cheap for extracting this result type from this source type with ...
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
MachineBasicBlock * emitDynamicProbedAlloc(MachineInstr &MI, MachineBasicBlock *MBB) const
MachineMemOperand::Flags getTargetMMOFlags(const Instruction &I) const override
This callback is used to inspect load/store instructions and add target-specific MachineMemOperand fl...
SDValue computeVLMax(MVT VecVT, const SDLoc &DL, SelectionDAG &DAG) const
bool signExtendConstant(const ConstantInt *CI) const override
Return true if this constant should be sign extended when promoting to a larger type.
bool shouldTransformSignedTruncationCheck(EVT XVT, unsigned KeptBits) const override
Should we tranform the IR-optimal check for whether given truncation down into KeptBits would be trun...
bool shouldProduceAndByConstByHoistingConstFromShiftsLHSOfAnd(SDValue X, ConstantSDNode *XC, ConstantSDNode *CC, SDValue Y, unsigned OldShiftOpcode, unsigned NewShiftOpcode, SelectionDAG &DAG) const override
Given the pattern (X & (C l>>/<< Y)) ==/!= 0 return true if it should be transformed into: ((X <</l>>...
bool hasInlineStackProbe(const MachineFunction &MF) const override
True if stack clash protection is enabled for this functions.
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Returns the register with the specified architectural or ABI name.
InstructionCost getVSlideVXCost(MVT VT) const
Return the cost of a vslidedown.vx or vslideup.vx instruction for the type VT.
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
static unsigned getRegClassIDForLMUL(RISCVII::VLMUL LMul)
bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override
Return true if result of the specified node is used by a return node only.
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const override
Return true if an FMA operation is faster than a pair of fmul and fadd instructions.
TargetLowering::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *CI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
bool lowerDeinterleavedIntrinsicToVPLoad(VPIntrinsic *Load, Value *Mask, ArrayRef< Value * > DeinterleaveRes) const override
Lower an interleaved vp.load into a vlsegN intrinsic.
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
bool lowerInterleavedIntrinsicToVPStore(VPIntrinsic *Store, Value *Mask, ArrayRef< Value * > InterleaveOps) const override
Lower an interleaved vp.store into a vssegN intrinsic.
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
Lower the specified operand into the Ops vector.
bool splitValueIntoRegisterParts(SelectionDAG &DAG, const SDLoc &DL, SDValue Val, SDValue *Parts, unsigned NumParts, MVT PartVT, std::optional< CallingConv::ID > CC) const override
Target-specific splitting of values into parts that fit a register storing a legal type.
Instruction * emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Return the number of registers for a given MVT, ensuring vectors are treated as a series of gpr sized...
ConstraintType getConstraintType(StringRef Constraint) const override
getConstraintType - Given a constraint letter, return the type of constraint it is for this target.
MachineInstr * EmitKCFICheck(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator &MBBI, const TargetInstrInfo *TII) const override
bool isLegalInterleavedAccessType(VectorType *VTy, unsigned Factor, Align Alignment, unsigned AddrSpace, const DataLayout &) const
Returns whether or not generating a interleaved load/store intrinsic for this type will be legal.
bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool PoisonOnly, bool ConsiderFlags, unsigned Depth) const override
Return true if Op can create undef or poison from non-undef & non-poison operands.
bool isIntDivCheap(EVT VT, AttributeList Attr) const override
Return true if integer divide is usually cheaper than a sequence of several shifts,...
SDValue expandIndirectJTBranch(const SDLoc &dl, SDValue Value, SDValue Addr, int JTI, SelectionDAG &DAG) const override
Expands target specific indirect branch for the case of JumpTable expansion.
bool lowerDeinterleaveIntrinsicToLoad(LoadInst *LI, ArrayRef< Value * > DeinterleaveValues) const override
Lower a deinterleave intrinsic to a target specific load intrinsic.
unsigned getNumRegisters(LLVMContext &Context, EVT VT, std::optional< MVT > RegisterVT=std::nullopt) const override
Return the number of registers for a given MVT, for inline assembly.
bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
Returns true by value, base pointer and offset pointer and addressing mode by reference if this node ...
bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
Returns true by value, base pointer and offset pointer and addressing mode by reference if the node's...
SDValue joinRegisterPartsIntoValue(SelectionDAG &DAG, const SDLoc &DL, const SDValue *Parts, unsigned NumParts, MVT PartVT, EVT ValueVT, std::optional< CallingConv::ID > CC) const override
Target-specific combining of register parts into its original value.
bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const override
Return if the target supports combining a chain like:
bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override
Return true if sign-extension from FromTy to ToTy is cheaper than zero-extension.
bool isLegalStridedLoadStore(EVT DataType, Align Alignment) const
Return true if a stride load store of the given result type and alignment is legal.
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
unsigned getStackProbeSize(const MachineFunction &MF, Align StackAlign) const
bool shouldInsertFencesForAtomic(const Instruction *I) const override
Whether AtomicExpandPass should automatically insert fences and reduce ordering for this atomic.
Wrapper class representing virtual and physical registers.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
ArrayRef< SDUse > ops() const
const APInt & getAsAPIntVal() const
Helper method returns the APInt value of a ConstantSDNode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
iterator_range< use_iterator > uses()
SDNodeFlags getFlags() const
MVT getSimpleValueType(unsigned ResNo) const
Return the type of a specified result as a simple type.
static bool hasPredecessorHelper(const SDNode *N, SmallPtrSetImpl< const SDNode * > &Visited, SmallVectorImpl< const SDNode * > &Worklist, unsigned int MaxSteps=0, bool TopologicalPrune=false)
Returns true if N is a predecessor of any node in Worklist.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
const SDValue & getOperand(unsigned Num) const
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
void setCFIType(uint32_t Type)
bool isUndef() const
Return true if the type of the node type undefined.
iterator_range< user_iterator > users()
op_iterator op_end() const
op_iterator op_begin() const
Represents a use of a SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
const APInt & getConstantOperandAPInt(unsigned i) const
uint64_t getScalarValueSizeInBits() const
uint64_t getConstantOperandVal(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getOpcode() const
unsigned getNumOperands() const
static ScalableVectorType * get(Type *ElementType, unsigned MinNumElts)
virtual bool isTargetStrictFPOpcode(unsigned Opcode) const
Returns true if a node with the given target-specific opcode has strict floating-point semantics.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
Align getReducedAlign(EVT VT, bool UseABI)
In most cases this function returns the ABI alignment for a given type, except for illegal vector typ...
SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
unsigned ComputeMaxSignificantBits(SDValue Op, unsigned Depth=0) const
Get the upper bound on bit size for this Value Op as a signed integer.
SDValue getMaskedGather(SDVTList VTs, EVT MemVT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType, ISD::LoadExtType ExtTy)
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL)
SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
SDValue getNeutralElement(unsigned Opcode, const SDLoc &DL, EVT VT, SDNodeFlags Flags)
Get the (commutative) neutral element for the given opcode, if it exists.
SDValue getVScale(const SDLoc &DL, EVT VT, APInt MulImm, bool ConstantFold=true)
Return a node that represents the runtime scaling 'MulImm * RuntimeVL'.
SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
SDValue getStridedLoadVP(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, const SDLoc &DL, SDValue Chain, SDValue Ptr, SDValue Offset, SDValue Stride, SDValue Mask, SDValue EVL, EVT MemVT, MachineMemOperand *MMO, bool IsExpanding=false)
SDValue makeEquivalentMemoryOrdering(SDValue OldChain, SDValue NewMemOpChain)
If an existing load has uses of its chain, create a token factor node with that chain and the new mem...
SDValue getJumpTableDebugInfo(int JTI, SDValue Chain, const SDLoc &DL)
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false)
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
bool isSafeToSpeculativelyExecute(unsigned Opcode) const
Some opcodes may create immediate undefined behavior when used with some values (integer division-by-...
SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
SDValue getRegister(Register Reg, EVT VT)
SDValue getElementCount(const SDLoc &DL, EVT VT, ElementCount EC, bool ConstantFold=true)
SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
SDValue getStepVector(const SDLoc &DL, EVT ResVT, const APInt &StepVal)
Returns a vector of type ResVT whose elements contain the linear sequence <0, Step,...
SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
bool shouldOptForSize() const
std::pair< SDValue, SDValue > SplitVectorOperand(const SDNode *N, unsigned OpNo)
Split the node's operand with EXTRACT_SUBVECTOR and return the low/high part.
SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
SDValue getVPZExtOrTrunc(const SDLoc &DL, EVT VT, SDValue Op, SDValue Mask, SDValue EVL)
Convert a vector-predicated Op, which must be an integer vector, to the vector-type VT,...
const TargetLowering & getTargetLoweringInfo() const
SDValue getStridedStoreVP(SDValue Chain, const SDLoc &DL, SDValue Val, SDValue Ptr, SDValue Offset, SDValue Stride, SDValue Mask, SDValue EVL, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
bool NewNodesMustHaveLegalTypes
When true, additional steps are taken to ensure that getConstant() and similar functions return DAG n...
std::pair< EVT, EVT > GetSplitDestVTs(const EVT &VT) const
Compute the VTs needed for the low/hi parts of a type which is split (or expanded) into two not neces...
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getGatherVP(SDVTList VTs, EVT VT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType)
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
bool isSplatValue(SDValue V, const APInt &DemandedElts, APInt &UndefElts, unsigned Depth=0) const
Test whether V has a splatted value for all the demanded elements.
SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
const SelectionDAGTargetInfo & getSelectionDAGInfo() const
SDValue getStoreVP(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, SDValue Offset, SDValue Mask, SDValue EVL, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags=SDNodeFlags())
Returns sum of the base pointer and offset.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue getSplatVector(EVT VT, const SDLoc &DL, SDValue Op)
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
bool SignBitIsZero(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero.
SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDValue > Ops, SDNodeFlags Flags=SDNodeFlags())
SDValue getMaskedStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Base, SDValue Offset, SDValue Mask, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
std::pair< SDValue, SDValue > getStrictFPExtendOrRound(SDValue Op, SDValue Chain, const SDLoc &DL, EVT VT)
Convert Op, which must be a STRICT operation of float type, to the float type VT, by either extending...
std::pair< SDValue, SDValue > SplitEVL(SDValue N, EVT VecVT, const SDLoc &DL)
Split the explicit vector length parameter of a VP operation.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond)
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
SDValue getScatterVP(SDVTList VTs, EVT VT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType)
SDValue getValueType(EVT)
SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getFPExtendOrRound(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of float type, to the float type VT, by either extending or rounding (by tr...
bool isKnownNeverNaN(SDValue Op, bool SNaN=false, unsigned Depth=0) const
Test whether the given SDValue (or all elements of it, if it is a vector) is known to never be NaN.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
SDValue getBoolConstant(bool V, const SDLoc &DL, EVT VT, EVT OpVT)
Create a true or false constant of type VT using the target's BooleanContent for type OpVT.
SDValue getTargetBlockAddress(const BlockAddress *BA, EVT VT, int64_t Offset=0, unsigned TargetFlags=0)
SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
SDValue getRegisterMask(const uint32_t *RegMask)
SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
SDValue getCondCode(ISD::CondCode Cond)
bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
LLVMContext * getContext() const
SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=0, const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Base, SDValue Offset, SDValue Mask, SDValue Src0, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, ISD::LoadExtType, bool IsExpanding=false)
SDValue getSplat(EVT VT, const SDLoc &DL, SDValue Op)
Returns a node representing a splat of one value into all lanes of the provided vector type.
std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a logical NOT operation as (XOR Val, BooleanOne).
SDValue getMaskedScatter(SDVTList VTs, EVT MemVT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType, bool IsTruncating=false)
This instruction constructs a fixed permutation of two input vectors.
static bool isSelectMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from its source vectors without lane crossings.
static bool isBitRotateMask(ArrayRef< int > Mask, unsigned EltSizeInBits, unsigned MinSubElts, unsigned MaxSubElts, unsigned &NumSubElts, unsigned &RotateAmt)
Checks if the shuffle is a bit rotation of the first operand across multiple subelements,...
VectorType * getType() const
Overload to return most specific vector type.
static void getShuffleMask(const Constant *Mask, SmallVectorImpl< int > &Result)
Convert the input shuffle mask operand to a vector of integers.
static bool isDeInterleaveMaskOfFactor(ArrayRef< int > Mask, unsigned Factor, unsigned &Index)
Check if the mask is a DE-interleave mask of the given factor Factor like: <Index,...
static bool isIdentityMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector without lane crossin...
static bool isReverseMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask swaps the order of elements from exactly one source vector.
static bool isInsertSubvectorMask(ArrayRef< int > Mask, int NumSrcElts, int &NumSubElts, int &Index)
Return true if this shuffle mask is an insert subvector mask.
static bool isInterleaveMask(ArrayRef< int > Mask, unsigned Factor, unsigned NumInputElts, SmallVectorImpl< unsigned > &StartIndexes)
Return true if the mask interleaves one or more input vectors together.
This SDNode is used to implement the code generator support for the llvm IR shufflevector instruction...
int getSplatIndex() const
ArrayRef< int > getMask() const
static bool isSplatMask(ArrayRef< int > Mask)
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
pointer data()
Return a pointer to the vector's buffer, even if empty().
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
This class is used to represent ISD::STORE nodes.
StringRef - Represent a constant reference to a string, i.e.
constexpr size_t size() const
size - Get the string size.
std::string lower() const
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, T Value)
static StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
static TargetExtType * get(LLVMContext &Context, StringRef Name, ArrayRef< Type * > Types={}, ArrayRef< unsigned > Ints={})
Return a target extension type having the specified name and optional type and integer parameters.
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
TargetInstrInfo - Interface to description of machine instruction set.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
bool PredictableSelectIsExpensive
Tells the code generator that select is more expensive than a branch if the branch is usually predict...
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
unsigned MaxStoresPerMemcpyOptSize
Likewise for functions with the OptSize attribute.
MachineBasicBlock * emitPatchPoint(MachineInstr &MI, MachineBasicBlock *MBB) const
Replace/modify any TargetFrameIndex operands with a targte-dependent sequence of memory operands that...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
const TargetMachine & getTargetMachine() const
unsigned MaxLoadsPerMemcmp
Specify maximum number of load instructions per memcmp call.
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
unsigned MaxGluedStoresPerMemcpy
Specify max number of store instructions to glue in inlined memcpy.
virtual bool isZExtFree(Type *FromTy, Type *ToTy) const
Return true if any actual instruction that defines a value of type FromTy implicitly zero-extends the...
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
void setOperationPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
Convenience method to set an operation to Promote and specify the type in a single call.
unsigned getMinCmpXchgSizeInBits() const
Returns the size of the smallest cmpxchg or ll/sc instruction the backend supports.
virtual unsigned getNumRegisters(LLVMContext &Context, EVT VT, std::optional< MVT > RegisterVT=std::nullopt) const
Return the number of registers that this ValueType will eventually require.
void setIndexedLoadAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed load does or does not work with the specified type and indicate w...
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
virtual unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
bool isOperationCustom(unsigned Op, EVT VT) const
Return true if the operation uses custom lowering, regardless of whether the type is legal or not.
unsigned MaxStoresPerMemsetOptSize
Likewise for functions with the OptSize attribute.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
unsigned MaxStoresPerMemmove
Specify maximum number of store instructions per memmove call.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
virtual bool isTruncateFree(Type *FromTy, Type *ToTy) const
Return true if it's free to truncate a value of type FromTy to type ToTy.
unsigned MaxStoresPerMemmoveOptSize
Likewise for functions with the OptSize attribute.
virtual bool shouldFoldSelectWithSingleBitTest(EVT VT, const APInt &AndMask) const
virtual Value * getIRStackGuard(IRBuilderBase &IRB) const
If the target has a standard location for the stack protector guard, returns the address of that loca...
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
bool EnableExtLdPromotion
void setIndexedStoreAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed store does or does not work with the specified type and indicate ...
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setLibcallName(RTLIB::Libcall Call, const char *Name)
Rename the default libcall routine name for the specified libcall.
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
bool isOperationLegal(unsigned Op, EVT VT) const
Return true if the specified operation is legal on this target.
unsigned MaxStoresPerMemset
Specify maximum number of store instructions per memset call.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
unsigned MaxLoadsPerMemcmpOptSize
Likewise for functions with the OptSize attribute.
virtual bool isBinOp(unsigned Opcode) const
Return true if the node is a math/logic binary operator.
void setMinCmpXchgSizeInBits(unsigned SizeInBits)
Sets the minimum cmpxchg or ll/sc size supported by the backend.
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
void setCondCodeAction(ArrayRef< ISD::CondCode > CCs, MVT VT, LegalizeAction Action)
Indicate that the specified condition code is or isn't supported on the target and indicate what to d...
virtual std::pair< const TargetRegisterClass *, uint8_t > findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const
Return the largest legal super-reg register class of the register class for the specified type and it...
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
std::vector< ArgListEntry > ArgListTy
bool allowsMemoryAccessForAlignment(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
This function returns true if the memory access is aligned or if the target allows this specific unal...
unsigned MaxStoresPerMemcpy
Specify maximum number of store instructions per memcpy call.
bool isOperationLegalOrCustomOrPromote(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
SDValue expandAddSubSat(SDNode *Node, SelectionDAG &DAG) const
Method for building the DAG expansion of ISD::[US][ADD|SUB]SAT.
SDValue buildSDIVPow2WithCMov(SDNode *N, const APInt &Divisor, SelectionDAG &DAG, SmallVectorImpl< SDNode * > &Created) const
Build sdiv by power-of-2 with conditional move instructions Ref: "Hacker's Delight" by Henry Warren 1...
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
virtual SDValue expandIndirectJTBranch(const SDLoc &dl, SDValue Value, SDValue Addr, int JTI, SelectionDAG &DAG) const
Expands target specific indirect branch for the case of JumpTable expansion.
virtual InlineAsm::ConstraintCode getInlineAsmMemConstraint(StringRef ConstraintCode) const
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
virtual SDValue LowerToTLSEmulatedModel(const GlobalAddressSDNode *GA, SelectionDAG &DAG) const
Lower TLS global address SDNode for target independent emulated TLS model.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
bool isPositionIndependent() const
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
bool verifyReturnAddressArgumentIsConstant(SDValue Op, SelectionDAG &DAG) const
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
virtual unsigned getJumpTableEncoding() const
Return the entry encoding for a jump table in the current function.
virtual bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool PoisonOnly, bool ConsiderFlags, unsigned Depth) const
Return true if Op can create undef or poison from non-undef & non-poison operands.
Primary interface to the complete machine description for the target machine.
TLSModel::Model getTLSModel(const GlobalValue *GV) const
Returns the TLS model which should be used for the given global variable.
const Triple & getTargetTriple() const
bool useTLSDESC() const
Returns true if this target uses TLS Descriptors.
const MCSubtargetInfo * getMCSubtargetInfo() const
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
virtual TargetLoweringObjectFile * getObjFileLowering() const
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual bool isRegisterReservedByUser(Register R) const
virtual const TargetInstrInfo * getInstrInfo() const
Target - Wrapper for Target specific information.
bool isOSBinFormatCOFF() const
Tests whether the OS uses the COFF binary format.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
The instances of the Type class are immutable: once they are created, they are never changed.
unsigned getIntegerBitWidth() const
Type * getStructElementType(unsigned N) const
static IntegerType * getIntNTy(LLVMContext &C, unsigned N)
bool isStructTy() const
True if this is an instance of StructType.
bool isTargetExtTy() const
Return true if this is a target extension type.
bool isScalableTy(SmallPtrSetImpl< const Type * > &Visited) const
Return true if this is a type whose size is a known multiple of vscale.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
static IntegerType * getInt8Ty(LLVMContext &C)
bool isIntegerTy() const
True if this is an instance of IntegerType.
TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
A Use represents the edge between a Value definition and its users.
User * getUser() const
Returns the User that contains this Use.
unsigned getOperandNo() const
Return the operand # of this use in its User.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
This is the common base class for vector predication intrinsics.
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.
static VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
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.
bool match(Val *V, const Pattern &P)
class_match< ConstantInt > m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
BinaryOp_match< LHS, RHS, Instruction::Mul, true > m_c_Mul(const LHS &L, const RHS &R)
Matches a Mul with LHS and RHS in either order.
@ 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
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)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
static const MachineMemOperand::Flags MONontemporalBit1
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
MCCodeEmitter * createRISCVMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
static const MachineMemOperand::Flags MONontemporalBit0
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
bool widenShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Try to transform a shuffle mask by replacing elements with the scaled index for an equivalent mask of...
Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
bool isNullOrNullSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndefs=false)
Return true if the value is a constant 0 integer or a splatted vector of a constant 0 integer (with n...
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
bool isReleaseOrStronger(AtomicOrdering AO)
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
bool CC_RISCV_FastCC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed, bool IsRet, Type *OrigTy)
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
bool isOneOrOneSplat(SDValue V, bool AllowUndefs=false)
Return true if the value is a constant 1 integer or a splatted vector of a constant 1 integer (with n...
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
auto drop_end(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the last N elements excluded.
AtomicOrdering
Atomic ordering for LLVM's memory model.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
void narrowShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Replace each shuffle mask index with the scaled sequential indices for an equivalent mask of narrowed...
@ Xor
Bitwise or logical XOR of integers.
@ And
Bitwise or logical AND of integers.
@ SMin
Signed integer min implemented in terms of select(cmp()).
unsigned getKillRegState(bool B)
void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, unsigned Depth=0, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
DWARFExpression::Operation Op
RoundingMode
Rounding mode.
@ TowardZero
roundTowardZero.
@ NearestTiesToEven
roundTiesToEven.
@ TowardPositive
roundTowardPositive.
@ NearestTiesToAway
roundTiesToAway.
@ TowardNegative
roundTowardNegative.
ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
bool isAcquireOrStronger(AtomicOrdering AO)
constexpr unsigned BitWidth
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
bool RISCVCCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed, bool IsRet, Type *OrigTy)
RISCVCCAssignFn - This target-specific function extends the default CCValAssign with additional infor...
bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
void processShuffleMasks(ArrayRef< int > Mask, unsigned NumOfSrcRegs, unsigned NumOfDestRegs, unsigned NumOfUsedRegs, function_ref< void()> NoInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned)> SingleInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned, bool)> ManyInputsAction)
Splits and processes shuffle mask depending on the number of input and output registers.
unsigned Log2(Align A)
Returns the log2 of the alignment.
bool CC_RISCV(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed, bool IsRet, Type *OrigTy)
llvm::SmallVector< int, 16 > createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs)
Create a sequential shuffle mask.
bool isNeutralConstant(unsigned Opc, SDNodeFlags Flags, SDValue V, unsigned OperandNo)
Returns true if V is a neutral element of Opc with Flags.
bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This is used by foldLoadsRecursive() to capture a Root Load node which is of type or(load,...
static constexpr roundingMode rmNearestTiesToEven
static unsigned int semanticsPrecision(const fltSemantics &)
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint64_t value() const
This is a hole in the type system and should not be abused.
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
uint64_t getScalarStoreSize() const
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
bool isByteSized() const
Return true if the bit size is a multiple of 8.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
unsigned getRISCVVectorTupleNumFields() const
Given a RISCV vector tuple type, return the num_fields.
uint64_t getScalarSizeInBits() const
EVT getHalfSizedIntegerVT(LLVMContext &Context) const
Finds the smallest simple value type that is greater than or equal to half the width of this EVT.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
bool isRISCVVectorTuple() const
Return true if this is a vector value type.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isFixedLengthVector() const
EVT getRoundIntegerType(LLVMContext &Context) const
Rounds the bit-width of the given integer EVT up to the nearest power of two (and at least to eight),...
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
bool bitsGE(EVT VT) const
Return true if this has no less bits than VT.
Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
EVT changeVectorElementType(EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
bool isInteger() const
Return true if this is an integer or a vector integer type.
unsigned countMinTrailingZeros() const
Returns the minimum number of trailing zero bits.
static KnownBits urem(const KnownBits &LHS, const KnownBits &RHS)
Compute known bits for urem(LHS, RHS).
bool isUnknown() const
Returns true if we don't know any bits.
unsigned countMaxTrailingZeros() const
Returns the maximum number of trailing zero bits possible.
KnownBits trunc(unsigned BitWidth) const
Return known bits for a truncation of the value we're tracking.
unsigned getBitWidth() const
Get the bit width of this value.
KnownBits zext(unsigned BitWidth) const
Return known bits for a zero extension of the value we're tracking.
void resetAll()
Resets the known state of all bits.
unsigned countMaxActiveBits() const
Returns the maximum number of bits needed to represent all possible unsigned values with these known ...
KnownBits intersectWith(const KnownBits &RHS) const
Returns KnownBits information that is known to be true for both this and RHS.
KnownBits sext(unsigned BitWidth) const
Return known bits for a sign extension of the value we're tracking.
static KnownBits udiv(const KnownBits &LHS, const KnownBits &RHS, bool Exact=false)
Compute known bits for udiv(LHS, RHS).
unsigned countMaxLeadingZeros() const
Returns the maximum number of leading zero bits possible.
static KnownBits shl(const KnownBits &LHS, const KnownBits &RHS, bool NUW=false, bool NSW=false, bool ShAmtNonZero=false)
Compute known bits for shl(LHS, RHS).
This class contains a discriminated union of information about pointers in memory operands,...
static MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const
static MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
BitVector getReservedRegs(const MachineFunction &MF) const override
Register getFrameRegister(const MachineFunction &MF) const override
These are IR-level optimization flags that may be propagated to SDNodes.
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This structure contains all information that is necessary for lowering calls.
SmallVector< ISD::InputArg, 32 > Ins
const ConstantInt * CFIType
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
bool isAfterLegalizeDAG() const
void AddToWorklist(SDNode *N)
bool isCalledByLegalizer() const
bool recursivelyDeleteUnusedNodes(SDNode *N)
bool isBeforeLegalize() const
SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
This structure is used to pass arguments to makeLibCall function.
MakeLibCallOptions & setTypeListBeforeSoften(ArrayRef< EVT > OpsVT, EVT RetVT, bool Value=true)
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...
bool CombineTo(SDValue O, SDValue N)