41#include "llvm/IR/IntrinsicsRISCV.h"
55#define DEBUG_TYPE "riscv-lower"
61 cl::desc(
"Give the maximum size (in number of nodes) of the web of "
62 "instructions that we will consider for VW expansion"),
67 cl::desc(
"Allow the formation of VW_W operations (e.g., "
68 "VWADD_W) with splat constants"),
73 cl::desc(
"Set the minimum number of repetitions of a divisor to allow "
74 "transformation to multiplications by the reciprocal"),
79 cl::desc(
"Give the maximum number of instructions that we will "
80 "use for creating a floating-point immediate value"),
85 cl::desc(
"Swap add and addi in cases where the add may "
86 "be combined with a shift"),
97 !Subtarget.hasStdExtF()) {
98 errs() <<
"Hard-float 'f' ABI can't be used for a target that "
99 "doesn't support the F instruction set extension (ignoring "
103 !Subtarget.hasStdExtD()) {
104 errs() <<
"Hard-float 'd' ABI can't be used for a target that "
105 "doesn't support the D instruction set extension (ignoring "
129 if (Subtarget.hasStdExtZfhmin())
131 if (Subtarget.hasStdExtZfbfmin() || Subtarget.hasVendorXAndesBFHCvt())
133 if (Subtarget.hasStdExtF())
135 if (Subtarget.hasStdExtD())
137 if (Subtarget.hasStdExtZhinxmin())
139 if (Subtarget.hasStdExtZfinx())
141 if (Subtarget.hasStdExtZdinx()) {
149 MVT::nxv1i1, MVT::nxv2i1, MVT::nxv4i1, MVT::nxv8i1,
150 MVT::nxv16i1, MVT::nxv32i1, MVT::nxv64i1};
152 MVT::nxv1i8, MVT::nxv2i8, MVT::nxv4i8, MVT::nxv8i8, MVT::nxv16i8,
153 MVT::nxv32i8, MVT::nxv64i8, MVT::nxv1i16, MVT::nxv2i16, MVT::nxv4i16,
154 MVT::nxv8i16, MVT::nxv16i16, MVT::nxv32i16, MVT::nxv1i32, MVT::nxv2i32,
155 MVT::nxv4i32, MVT::nxv8i32, MVT::nxv16i32, MVT::nxv1i64, MVT::nxv2i64,
156 MVT::nxv4i64, MVT::nxv8i64};
158 MVT::nxv1f16, MVT::nxv2f16, MVT::nxv4f16,
159 MVT::nxv8f16, MVT::nxv16f16, MVT::nxv32f16};
161 MVT::nxv1bf16, MVT::nxv2bf16, MVT::nxv4bf16,
162 MVT::nxv8bf16, MVT::nxv16bf16, MVT::nxv32bf16};
164 MVT::nxv1f32, MVT::nxv2f32, MVT::nxv4f32, MVT::nxv8f32, MVT::nxv16f32};
166 MVT::nxv1f64, MVT::nxv2f64, MVT::nxv4f64, MVT::nxv8f64};
168 MVT::riscv_nxv1i8x2, MVT::riscv_nxv1i8x3, MVT::riscv_nxv1i8x4,
169 MVT::riscv_nxv1i8x5, MVT::riscv_nxv1i8x6, MVT::riscv_nxv1i8x7,
170 MVT::riscv_nxv1i8x8, MVT::riscv_nxv2i8x2, MVT::riscv_nxv2i8x3,
171 MVT::riscv_nxv2i8x4, MVT::riscv_nxv2i8x5, MVT::riscv_nxv2i8x6,
172 MVT::riscv_nxv2i8x7, MVT::riscv_nxv2i8x8, MVT::riscv_nxv4i8x2,
173 MVT::riscv_nxv4i8x3, MVT::riscv_nxv4i8x4, MVT::riscv_nxv4i8x5,
174 MVT::riscv_nxv4i8x6, MVT::riscv_nxv4i8x7, MVT::riscv_nxv4i8x8,
175 MVT::riscv_nxv8i8x2, MVT::riscv_nxv8i8x3, MVT::riscv_nxv8i8x4,
176 MVT::riscv_nxv8i8x5, MVT::riscv_nxv8i8x6, MVT::riscv_nxv8i8x7,
177 MVT::riscv_nxv8i8x8, MVT::riscv_nxv16i8x2, MVT::riscv_nxv16i8x3,
178 MVT::riscv_nxv16i8x4, MVT::riscv_nxv32i8x2};
181 auto addRegClassForRVV = [
this](
MVT VT) {
185 if (VT.getVectorMinNumElements() < MinElts)
188 unsigned Size = VT.getSizeInBits().getKnownMinValue();
191 RC = &RISCV::VRRegClass;
193 RC = &RISCV::VRM2RegClass;
195 RC = &RISCV::VRM4RegClass;
197 RC = &RISCV::VRM8RegClass;
204 for (
MVT VT : BoolVecVTs)
205 addRegClassForRVV(VT);
206 for (
MVT VT : IntVecVTs) {
207 if (VT.getVectorElementType() == MVT::i64 &&
210 addRegClassForRVV(VT);
214 Subtarget.hasVendorXAndesVPackFPH())
215 for (
MVT VT : F16VecVTs)
216 addRegClassForRVV(VT);
219 Subtarget.hasVendorXAndesVBFHCvt())
220 for (
MVT VT : BF16VecVTs)
221 addRegClassForRVV(VT);
224 for (
MVT VT : F32VecVTs)
225 addRegClassForRVV(VT);
228 for (
MVT VT : F64VecVTs)
229 addRegClassForRVV(VT);
232 auto addRegClassForFixedVectors = [
this](
MVT VT) {
239 if (useRVVForFixedLengthVectorVT(VT))
240 addRegClassForFixedVectors(VT);
243 if (useRVVForFixedLengthVectorVT(VT))
244 addRegClassForFixedVectors(VT);
304 if (!(Subtarget.hasVendorXCValu() && !Subtarget.
is64Bit())) {
314 if (!Subtarget.hasVendorXTHeadBb() && !Subtarget.hasVendorXqcibm() &&
315 !Subtarget.hasVendorXAndesPerf())
320 if (!Subtarget.hasStdExtZbb() && !Subtarget.hasVendorXTHeadBb() &&
321 !Subtarget.hasVendorXqcibm() && !Subtarget.hasVendorXAndesPerf() &&
322 !(Subtarget.hasVendorXCValu() && !Subtarget.
is64Bit()))
325 if (Subtarget.hasStdExtZilsd() && !Subtarget.
is64Bit()) {
337 if (!Subtarget.hasStdExtZbb())
343 if (!Subtarget.hasStdExtZmmul()) {
345 }
else if (Subtarget.
is64Bit()) {
352 if (!Subtarget.hasStdExtM()) {
355 }
else if (Subtarget.
is64Bit()) {
357 {MVT::i8, MVT::i16, MVT::i32},
Custom);
367 if (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) {
370 }
else if (Subtarget.hasVendorXTHeadBb()) {
374 }
else if (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit()) {
383 (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb() ||
384 Subtarget.hasVendorXTHeadBb())
388 if ((Subtarget.hasVendorXCVbitmanip() || Subtarget.hasVendorXqcibm()) &&
395 if (Subtarget.hasStdExtZbkb())
399 if (Subtarget.hasStdExtZbb() ||
400 (Subtarget.hasVendorXCValu() && !Subtarget.
is64Bit())) {
405 if (Subtarget.hasStdExtZbb() ||
406 (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit())) {
420 if (Subtarget.hasStdExtZbb() || Subtarget.hasVendorXTHeadBb() ||
421 (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit())) {
430 if (Subtarget.hasVendorXCValu() && !Subtarget.
is64Bit()) {
432 }
else if (Subtarget.hasShortForwardBranchOpt()) {
435 }
else if (Subtarget.
is64Bit()) {
439 if (!Subtarget.
useCCMovInsn() && !Subtarget.hasVendorXTHeadCondMov() &&
440 !Subtarget.hasVendorXqcicm() && !Subtarget.hasVendorXqcics())
443 if (Subtarget.hasVendorXqcia() && !Subtarget.
is64Bit()) {
452 static const unsigned FPLegalNodeTypes[] = {
466 static const unsigned FPOpToExpand[] = {
470 static const unsigned FPRndMode[] = {
474 static const unsigned ZfhminZfbfminPromoteOps[] = {
485 if (Subtarget.hasStdExtZfbfmin()) {
508 if (Subtarget.hasStdExtZfa())
535 Subtarget.hasStdExtZfh() && Subtarget.hasStdExtZfa() ?
Legal :
Promote);
577 if (Subtarget.hasStdExtZfa()) {
595 if (Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
601 if (Subtarget.hasStdExtZfa()) {
689 if (Subtarget.hasVendorXMIPSCBOP())
691 else if (Subtarget.hasStdExtZicbop())
694 if (Subtarget.hasStdExtA()) {
696 if (Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas())
700 }
else if (Subtarget.hasForcedAtomics()) {
724 {MVT::i8, MVT::i16},
Custom);
735 static const unsigned IntegerVPOps[] = {
736 ISD::VP_ADD, ISD::VP_SUB, ISD::VP_MUL,
737 ISD::VP_SDIV, ISD::VP_UDIV, ISD::VP_SREM,
738 ISD::VP_UREM, ISD::VP_AND, ISD::VP_OR,
739 ISD::VP_XOR, ISD::VP_SRA, ISD::VP_SRL,
740 ISD::VP_SHL, ISD::VP_REDUCE_ADD, ISD::VP_REDUCE_AND,
741 ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR, ISD::VP_REDUCE_SMAX,
742 ISD::VP_REDUCE_SMIN, ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN,
743 ISD::VP_MERGE, ISD::VP_SELECT, ISD::VP_FP_TO_SINT,
744 ISD::VP_FP_TO_UINT, ISD::VP_SETCC, ISD::VP_SIGN_EXTEND,
745 ISD::VP_ZERO_EXTEND, ISD::VP_TRUNCATE, ISD::VP_SMIN,
746 ISD::VP_SMAX, ISD::VP_UMIN, ISD::VP_UMAX,
747 ISD::VP_ABS, ISD::EXPERIMENTAL_VP_REVERSE, ISD::EXPERIMENTAL_VP_SPLICE,
748 ISD::VP_SADDSAT, ISD::VP_UADDSAT, ISD::VP_SSUBSAT,
749 ISD::VP_USUBSAT, ISD::VP_CTTZ_ELTS, ISD::VP_CTTZ_ELTS_ZERO_UNDEF,
750 ISD::EXPERIMENTAL_VP_SPLAT};
752 static const unsigned FloatingPointVPOps[] = {
753 ISD::VP_FADD, ISD::VP_FSUB, ISD::VP_FMUL,
754 ISD::VP_FDIV, ISD::VP_FNEG, ISD::VP_FABS,
755 ISD::VP_FMA, ISD::VP_REDUCE_FADD, ISD::VP_REDUCE_SEQ_FADD,
756 ISD::VP_REDUCE_FMIN, ISD::VP_REDUCE_FMAX, ISD::VP_MERGE,
757 ISD::VP_SELECT, ISD::VP_SINT_TO_FP, ISD::VP_UINT_TO_FP,
758 ISD::VP_SETCC, ISD::VP_FP_ROUND, ISD::VP_FP_EXTEND,
759 ISD::VP_SQRT, ISD::VP_FMINNUM, ISD::VP_FMAXNUM,
760 ISD::VP_FCEIL, ISD::VP_FFLOOR, ISD::VP_FROUND,
761 ISD::VP_FROUNDEVEN, ISD::VP_FCOPYSIGN, ISD::VP_FROUNDTOZERO,
762 ISD::VP_FRINT, ISD::VP_FNEARBYINT, ISD::VP_IS_FPCLASS,
763 ISD::VP_FMINIMUM, ISD::VP_FMAXIMUM, ISD::VP_LRINT,
764 ISD::VP_LLRINT, ISD::VP_REDUCE_FMINIMUM,
765 ISD::VP_REDUCE_FMAXIMUM, ISD::EXPERIMENTAL_VP_SPLAT};
767 static const unsigned IntegerVecReduceOps[] = {
772 static const unsigned FloatingPointVecReduceOps[] = {
776 static const unsigned FloatingPointLibCallOps[] = {
789 ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR,
790 ISD::VP_REDUCE_SMAX, ISD::VP_REDUCE_SMIN,
791 ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN},
795 for (
MVT VT : BoolVecVTs) {
825 {ISD::VP_REDUCE_AND, ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR}, VT,
849 ISD::VP_TRUNCATE, ISD::VP_SETCC},
866 for (
MVT VT : IntVecVTs) {
877 if (VT.getVectorElementType() == MVT::i64 && !Subtarget.hasStdExtV())
927 {ISD::VP_LOAD, ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
928 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER, ISD::VP_SCATTER},
953 if (Subtarget.hasStdExtZvkb()) {
961 if (Subtarget.hasStdExtZvbb()) {
965 ISD::VP_CTTZ_ZERO_UNDEF, ISD::VP_CTPOP},
971 ISD::VP_CTTZ_ZERO_UNDEF, ISD::VP_CTPOP},
980 ISD::VP_CTLZ_ZERO_UNDEF, ISD::VP_CTTZ_ZERO_UNDEF},
988 for (
MVT VT : VecTupleVTs) {
1009 static const unsigned ZvfhminZvfbfminPromoteOps[] = {
1043 static const unsigned ZvfhminZvfbfminPromoteVPOps[] = {
1049 ISD::VP_REDUCE_FMIN,
1050 ISD::VP_REDUCE_FMAX,
1058 ISD::VP_FROUNDTOZERO,
1064 ISD::VP_REDUCE_FMINIMUM,
1065 ISD::VP_REDUCE_FMAXIMUM};
1068 const auto SetCommonVFPActions = [&](
MVT VT) {
1106 {ISD::VP_LOAD, ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1107 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER, ISD::VP_SCATTER},
1143 const auto SetCommonVFPExtLoadTruncStoreActions =
1145 for (
auto SmallVT : SmallerVTs) {
1153 const auto SetCommonPromoteToF32Actions = [&](
MVT VT) {
1182 ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1183 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1207 for (
MVT VT : F16VecVTs) {
1210 SetCommonVFPActions(VT);
1213 for (
MVT VT : F16VecVTs) {
1216 SetCommonPromoteToF32Actions(VT);
1221 for (
MVT VT : BF16VecVTs) {
1224 SetCommonPromoteToF32Actions(VT);
1229 for (
MVT VT : F32VecVTs) {
1232 SetCommonVFPActions(VT);
1233 SetCommonVFPExtLoadTruncStoreActions(VT, F16VecVTs);
1234 SetCommonVFPExtLoadTruncStoreActions(VT, BF16VecVTs);
1239 for (
MVT VT : F64VecVTs) {
1242 SetCommonVFPActions(VT);
1243 SetCommonVFPExtLoadTruncStoreActions(VT, F16VecVTs);
1244 SetCommonVFPExtLoadTruncStoreActions(VT, BF16VecVTs);
1245 SetCommonVFPExtLoadTruncStoreActions(VT, F32VecVTs);
1251 if (!useRVVForFixedLengthVectorVT(VT))
1300 {ISD::VP_REDUCE_AND, ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR}, VT,
1327 ISD::VP_SETCC, ISD::VP_TRUNCATE},
1354 ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1355 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1393 if (Subtarget.hasStdExtZvkb())
1396 if (Subtarget.hasStdExtZvbb()) {
1420 if (!useRVVForFixedLengthVectorVT(VT))
1446 ISD::VP_SCATTER, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1447 ISD::EXPERIMENTAL_VP_STRIDED_STORE},
1466 if (Subtarget.hasStdExtZfhmin()) {
1492 if (Subtarget.hasStdExtZfbfmin()) {
1555 if (Subtarget.hasStdExtZfbfmin())
1564 if (Subtarget.hasStdExtA())
1567 if (Subtarget.hasForcedAtomics()) {
1577 if (Subtarget.hasVendorXTHeadMemIdx()) {
1593 if (Subtarget.hasVendorXCVmem() && !Subtarget.
is64Bit()) {
1604 if (Subtarget.hasStdExtZvqdotq() && Subtarget.
getELen() >= 64) {
1616 if (VT.getVectorElementType() != MVT::i32 ||
1617 !useRVVForFixedLengthVectorVT(VT))
1627 if (Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh()) {
1633 const Align FunctionAlignment(Subtarget.hasStdExtZca() ? 2 : 4);
1648 if (Subtarget.hasStdExtZbb())
1651 if ((Subtarget.hasStdExtZbs() && Subtarget.
is64Bit()) ||
1655 if (Subtarget.hasStdExtZbkb())
1664 ISD::VP_GATHER, ISD::VP_SCATTER,
ISD::SRA,
1667 ISD::VP_STORE, ISD::VP_TRUNCATE, ISD::EXPERIMENTAL_VP_REVERSE,
1673 if (Subtarget.hasVendorXTHeadMemPair())
1713MVT RISCVTargetLowering::getVPExplicitVectorLengthTy()
const {
1718bool RISCVTargetLowering::shouldExpandGetVectorLength(
EVT TripCountVT,
1720 bool IsScalable)
const {
1727 if (TripCountVT != MVT::i32 && TripCountVT != Subtarget.
getXLenVT())
1752 unsigned Intrinsic)
const {
1753 auto &
DL =
I.getDataLayout();
1755 auto SetRVVLoadStoreInfo = [&](
unsigned PtrOp,
bool IsStore,
1756 bool IsUnitStrided,
bool UsePtrVal =
false) {
1761 Info.ptrVal =
I.getArgOperand(PtrOp);
1763 Info.fallbackAddressSpace =
1764 I.getArgOperand(PtrOp)->getType()->getPointerAddressSpace();
1768 MemTy =
I.getArgOperand(0)->getType();
1771 MemTy =
I.getType();
1781 if (cast<TargetExtType>(MemTy)->
getName() ==
"riscv.vector.tuple")
1784 1 << cast<ConstantInt>(
I.getArgOperand(
I.arg_size() - 1))
1786 Info.align =
DL.getABITypeAlign(MemTy);
1796 if (
I.hasMetadata(LLVMContext::MD_nontemporal))
1800 switch (Intrinsic) {
1803 case Intrinsic::riscv_masked_atomicrmw_xchg:
1804 case Intrinsic::riscv_masked_atomicrmw_add:
1805 case Intrinsic::riscv_masked_atomicrmw_sub:
1806 case Intrinsic::riscv_masked_atomicrmw_nand:
1807 case Intrinsic::riscv_masked_atomicrmw_max:
1808 case Intrinsic::riscv_masked_atomicrmw_min:
1809 case Intrinsic::riscv_masked_atomicrmw_umax:
1810 case Intrinsic::riscv_masked_atomicrmw_umin:
1811 case Intrinsic::riscv_masked_cmpxchg:
1818 Info.memVT = MVT::i32;
1819 Info.ptrVal =
I.getArgOperand(0);
1825 case Intrinsic::riscv_seg2_load_mask:
1826 case Intrinsic::riscv_seg3_load_mask:
1827 case Intrinsic::riscv_seg4_load_mask:
1828 case Intrinsic::riscv_seg5_load_mask:
1829 case Intrinsic::riscv_seg6_load_mask:
1830 case Intrinsic::riscv_seg7_load_mask:
1831 case Intrinsic::riscv_seg8_load_mask:
1832 case Intrinsic::riscv_sseg2_load_mask:
1833 case Intrinsic::riscv_sseg3_load_mask:
1834 case Intrinsic::riscv_sseg4_load_mask:
1835 case Intrinsic::riscv_sseg5_load_mask:
1836 case Intrinsic::riscv_sseg6_load_mask:
1837 case Intrinsic::riscv_sseg7_load_mask:
1838 case Intrinsic::riscv_sseg8_load_mask:
1839 return SetRVVLoadStoreInfo( 0,
false,
1841 case Intrinsic::riscv_seg2_store_mask:
1842 case Intrinsic::riscv_seg3_store_mask:
1843 case Intrinsic::riscv_seg4_store_mask:
1844 case Intrinsic::riscv_seg5_store_mask:
1845 case Intrinsic::riscv_seg6_store_mask:
1846 case Intrinsic::riscv_seg7_store_mask:
1847 case Intrinsic::riscv_seg8_store_mask:
1849 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1852 case Intrinsic::riscv_sseg2_store_mask:
1853 case Intrinsic::riscv_sseg3_store_mask:
1854 case Intrinsic::riscv_sseg4_store_mask:
1855 case Intrinsic::riscv_sseg5_store_mask:
1856 case Intrinsic::riscv_sseg6_store_mask:
1857 case Intrinsic::riscv_sseg7_store_mask:
1858 case Intrinsic::riscv_sseg8_store_mask:
1860 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
1863 case Intrinsic::riscv_vlm:
1864 return SetRVVLoadStoreInfo( 0,
1868 case Intrinsic::riscv_vle:
1869 case Intrinsic::riscv_vle_mask:
1870 case Intrinsic::riscv_vleff:
1871 case Intrinsic::riscv_vleff_mask:
1872 return SetRVVLoadStoreInfo( 1,
1876 case Intrinsic::riscv_vsm:
1877 case Intrinsic::riscv_vse:
1878 case Intrinsic::riscv_vse_mask:
1879 return SetRVVLoadStoreInfo( 1,
1883 case Intrinsic::riscv_vlse:
1884 case Intrinsic::riscv_vlse_mask:
1885 case Intrinsic::riscv_vloxei:
1886 case Intrinsic::riscv_vloxei_mask:
1887 case Intrinsic::riscv_vluxei:
1888 case Intrinsic::riscv_vluxei_mask:
1889 return SetRVVLoadStoreInfo( 1,
1892 case Intrinsic::riscv_vsse:
1893 case Intrinsic::riscv_vsse_mask:
1894 case Intrinsic::riscv_vsoxei:
1895 case Intrinsic::riscv_vsoxei_mask:
1896 case Intrinsic::riscv_vsuxei:
1897 case Intrinsic::riscv_vsuxei_mask:
1898 return SetRVVLoadStoreInfo( 1,
1901 case Intrinsic::riscv_vlseg2:
1902 case Intrinsic::riscv_vlseg3:
1903 case Intrinsic::riscv_vlseg4:
1904 case Intrinsic::riscv_vlseg5:
1905 case Intrinsic::riscv_vlseg6:
1906 case Intrinsic::riscv_vlseg7:
1907 case Intrinsic::riscv_vlseg8:
1908 case Intrinsic::riscv_vlseg2ff:
1909 case Intrinsic::riscv_vlseg3ff:
1910 case Intrinsic::riscv_vlseg4ff:
1911 case Intrinsic::riscv_vlseg5ff:
1912 case Intrinsic::riscv_vlseg6ff:
1913 case Intrinsic::riscv_vlseg7ff:
1914 case Intrinsic::riscv_vlseg8ff:
1915 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1918 case Intrinsic::riscv_vlseg2_mask:
1919 case Intrinsic::riscv_vlseg3_mask:
1920 case Intrinsic::riscv_vlseg4_mask:
1921 case Intrinsic::riscv_vlseg5_mask:
1922 case Intrinsic::riscv_vlseg6_mask:
1923 case Intrinsic::riscv_vlseg7_mask:
1924 case Intrinsic::riscv_vlseg8_mask:
1925 case Intrinsic::riscv_vlseg2ff_mask:
1926 case Intrinsic::riscv_vlseg3ff_mask:
1927 case Intrinsic::riscv_vlseg4ff_mask:
1928 case Intrinsic::riscv_vlseg5ff_mask:
1929 case Intrinsic::riscv_vlseg6ff_mask:
1930 case Intrinsic::riscv_vlseg7ff_mask:
1931 case Intrinsic::riscv_vlseg8ff_mask:
1932 return SetRVVLoadStoreInfo(
I.arg_size() - 5,
1935 case Intrinsic::riscv_vlsseg2:
1936 case Intrinsic::riscv_vlsseg3:
1937 case Intrinsic::riscv_vlsseg4:
1938 case Intrinsic::riscv_vlsseg5:
1939 case Intrinsic::riscv_vlsseg6:
1940 case Intrinsic::riscv_vlsseg7:
1941 case Intrinsic::riscv_vlsseg8:
1942 case Intrinsic::riscv_vloxseg2:
1943 case Intrinsic::riscv_vloxseg3:
1944 case Intrinsic::riscv_vloxseg4:
1945 case Intrinsic::riscv_vloxseg5:
1946 case Intrinsic::riscv_vloxseg6:
1947 case Intrinsic::riscv_vloxseg7:
1948 case Intrinsic::riscv_vloxseg8:
1949 case Intrinsic::riscv_vluxseg2:
1950 case Intrinsic::riscv_vluxseg3:
1951 case Intrinsic::riscv_vluxseg4:
1952 case Intrinsic::riscv_vluxseg5:
1953 case Intrinsic::riscv_vluxseg6:
1954 case Intrinsic::riscv_vluxseg7:
1955 case Intrinsic::riscv_vluxseg8:
1956 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
1959 case Intrinsic::riscv_vlsseg2_mask:
1960 case Intrinsic::riscv_vlsseg3_mask:
1961 case Intrinsic::riscv_vlsseg4_mask:
1962 case Intrinsic::riscv_vlsseg5_mask:
1963 case Intrinsic::riscv_vlsseg6_mask:
1964 case Intrinsic::riscv_vlsseg7_mask:
1965 case Intrinsic::riscv_vlsseg8_mask:
1966 case Intrinsic::riscv_vloxseg2_mask:
1967 case Intrinsic::riscv_vloxseg3_mask:
1968 case Intrinsic::riscv_vloxseg4_mask:
1969 case Intrinsic::riscv_vloxseg5_mask:
1970 case Intrinsic::riscv_vloxseg6_mask:
1971 case Intrinsic::riscv_vloxseg7_mask:
1972 case Intrinsic::riscv_vloxseg8_mask:
1973 case Intrinsic::riscv_vluxseg2_mask:
1974 case Intrinsic::riscv_vluxseg3_mask:
1975 case Intrinsic::riscv_vluxseg4_mask:
1976 case Intrinsic::riscv_vluxseg5_mask:
1977 case Intrinsic::riscv_vluxseg6_mask:
1978 case Intrinsic::riscv_vluxseg7_mask:
1979 case Intrinsic::riscv_vluxseg8_mask:
1980 return SetRVVLoadStoreInfo(
I.arg_size() - 6,
1983 case Intrinsic::riscv_vsseg2:
1984 case Intrinsic::riscv_vsseg3:
1985 case Intrinsic::riscv_vsseg4:
1986 case Intrinsic::riscv_vsseg5:
1987 case Intrinsic::riscv_vsseg6:
1988 case Intrinsic::riscv_vsseg7:
1989 case Intrinsic::riscv_vsseg8:
1990 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1993 case Intrinsic::riscv_vsseg2_mask:
1994 case Intrinsic::riscv_vsseg3_mask:
1995 case Intrinsic::riscv_vsseg4_mask:
1996 case Intrinsic::riscv_vsseg5_mask:
1997 case Intrinsic::riscv_vsseg6_mask:
1998 case Intrinsic::riscv_vsseg7_mask:
1999 case Intrinsic::riscv_vsseg8_mask:
2000 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
2003 case Intrinsic::riscv_vssseg2:
2004 case Intrinsic::riscv_vssseg3:
2005 case Intrinsic::riscv_vssseg4:
2006 case Intrinsic::riscv_vssseg5:
2007 case Intrinsic::riscv_vssseg6:
2008 case Intrinsic::riscv_vssseg7:
2009 case Intrinsic::riscv_vssseg8:
2010 case Intrinsic::riscv_vsoxseg2:
2011 case Intrinsic::riscv_vsoxseg3:
2012 case Intrinsic::riscv_vsoxseg4:
2013 case Intrinsic::riscv_vsoxseg5:
2014 case Intrinsic::riscv_vsoxseg6:
2015 case Intrinsic::riscv_vsoxseg7:
2016 case Intrinsic::riscv_vsoxseg8:
2017 case Intrinsic::riscv_vsuxseg2:
2018 case Intrinsic::riscv_vsuxseg3:
2019 case Intrinsic::riscv_vsuxseg4:
2020 case Intrinsic::riscv_vsuxseg5:
2021 case Intrinsic::riscv_vsuxseg6:
2022 case Intrinsic::riscv_vsuxseg7:
2023 case Intrinsic::riscv_vsuxseg8:
2024 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
2027 case Intrinsic::riscv_vssseg2_mask:
2028 case Intrinsic::riscv_vssseg3_mask:
2029 case Intrinsic::riscv_vssseg4_mask:
2030 case Intrinsic::riscv_vssseg5_mask:
2031 case Intrinsic::riscv_vssseg6_mask:
2032 case Intrinsic::riscv_vssseg7_mask:
2033 case Intrinsic::riscv_vssseg8_mask:
2034 case Intrinsic::riscv_vsoxseg2_mask:
2035 case Intrinsic::riscv_vsoxseg3_mask:
2036 case Intrinsic::riscv_vsoxseg4_mask:
2037 case Intrinsic::riscv_vsoxseg5_mask:
2038 case Intrinsic::riscv_vsoxseg6_mask:
2039 case Intrinsic::riscv_vsoxseg7_mask:
2040 case Intrinsic::riscv_vsoxseg8_mask:
2041 case Intrinsic::riscv_vsuxseg2_mask:
2042 case Intrinsic::riscv_vsuxseg3_mask:
2043 case Intrinsic::riscv_vsuxseg4_mask:
2044 case Intrinsic::riscv_vsuxseg5_mask:
2045 case Intrinsic::riscv_vsuxseg6_mask:
2046 case Intrinsic::riscv_vsuxseg7_mask:
2047 case Intrinsic::riscv_vsuxseg8_mask:
2048 return SetRVVLoadStoreInfo(
I.arg_size() - 5,
2089 return isInt<12>(Imm);
2093 return isInt<12>(Imm);
2106 return (SrcBits == 64 && DestBits == 32);
2117 return (SrcBits == 64 && DestBits == 32);
2128 if (SrcBits == DestBits * 2) {
2139 if (
auto *LD = dyn_cast<LoadSDNode>(Val)) {
2140 EVT MemVT = LD->getMemoryVT();
2141 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
2151 return Subtarget.
is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
2159 return Subtarget.hasStdExtZbb() ||
2160 (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit());
2164 return Subtarget.hasStdExtZbb() || Subtarget.hasVendorXTHeadBb() ||
2165 (Subtarget.hasVendorXCVbitmanip() && !Subtarget.
is64Bit());
2176 if (!Subtarget.hasStdExtZbs() && !Subtarget.hasVendorXTHeadBs())
2181 return !Mask->getValue().isSignedIntN(12) && Mask->getValue().isPowerOf2();
2185 EVT VT =
Y.getValueType();
2190 return (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
2191 (!isa<ConstantSDNode>(
Y) || cast<ConstantSDNode>(
Y)->isOpaque());
2195 EVT VT =
Y.getValueType();
2200 return Subtarget.hasStdExtZvkb();
2205 if (Subtarget.hasStdExtZbs())
2206 return X.getValueType().isScalarInteger();
2207 auto *
C = dyn_cast<ConstantSDNode>(
Y);
2209 if (Subtarget.hasVendorXTHeadBs())
2210 return C !=
nullptr;
2212 return C &&
C->getAPIntValue().ule(10);
2216 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
2236 if (BitSize > Subtarget.
getXLen())
2240 int64_t Val = Imm.getSExtValue();
2248 if (!Subtarget.enableUnalignedScalarMem())
2264 unsigned OldShiftOpcode,
unsigned NewShiftOpcode,
2271 if (XC && OldShiftOpcode ==
ISD::SRL && XC->isOne())
2319 if (!Subtarget.hasStdExtZfa())
2322 bool IsSupportedVT =
false;
2323 if (VT == MVT::f16) {
2324 IsSupportedVT = Subtarget.hasStdExtZfh() || Subtarget.hasStdExtZvfh();
2325 }
else if (VT == MVT::f32) {
2326 IsSupportedVT =
true;
2327 }
else if (VT == MVT::f64) {
2328 assert(Subtarget.hasStdExtD() &&
"Expect D extension");
2329 IsSupportedVT =
true;
2339 bool ForCodeSize)
const {
2340 bool IsLegalVT =
false;
2343 else if (VT == MVT::f32)
2345 else if (VT == MVT::f64)
2347 else if (VT == MVT::bf16)
2348 IsLegalVT = Subtarget.hasStdExtZfbfmin();
2364 return Imm.isZero();
2368 if (Imm.isNegZero())
2373 const int FmvCost = Subtarget.hasStdExtZfinx() ? 0 : 1;
2376 Subtarget.
getXLen(), Subtarget);
2382 unsigned Index)
const {
2399 if (EltVT == MVT::i1)
2412 if (Index + ResElts <= MinVLMAX && Index < 31)
2421 return (ResElts * 2) == SrcElts && (Index == 0 || Index == ResElts);
2440 std::optional<MVT> RegisterVT)
const {
2442 if (VT == (Subtarget.
is64Bit() ? MVT::i128 : MVT::i64) && RegisterVT &&
2443 *RegisterVT == MVT::Untyped)
2463 unsigned &NumIntermediates,
MVT &RegisterVT)
const {
2465 Context, CC, VT, IntermediateVT, NumIntermediates, RegisterVT);
2481 isa<ConstantSDNode>(
LHS.getOperand(1)) &&
2483 !Subtarget.hasVendorXAndesPerf()) {
2489 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
2502 if (
auto *RHSC = dyn_cast<ConstantSDNode>(
RHS)) {
2503 int64_t
C = RHSC->getSExtValue();
2513 if (Subtarget.hasVendorXqcibi() &&
C !=
INT64_MAX && isInt<16>(
C + 1)) {
2531 if (Subtarget.hasVendorXqcibi() &&
C !=
INT64_MAX && isUInt<16>(
C + 1)) {
2558 if (VT.
SimpleTy >= MVT::riscv_nxv1i8x2 &&
2559 VT.
SimpleTy <= MVT::riscv_nxv1i8x8)
2561 if (VT.
SimpleTy >= MVT::riscv_nxv2i8x2 &&
2562 VT.
SimpleTy <= MVT::riscv_nxv2i8x8)
2564 if (VT.
SimpleTy >= MVT::riscv_nxv4i8x2 &&
2565 VT.
SimpleTy <= MVT::riscv_nxv4i8x8)
2567 if (VT.
SimpleTy >= MVT::riscv_nxv8i8x2 &&
2568 VT.
SimpleTy <= MVT::riscv_nxv8i8x8)
2570 if (VT.
SimpleTy >= MVT::riscv_nxv16i8x2 &&
2571 VT.
SimpleTy <= MVT::riscv_nxv16i8x4)
2573 if (VT.
SimpleTy == MVT::riscv_nxv32i8x2)
2583 switch (KnownSize) {
2611 return RISCV::VRRegClassID;
2613 return RISCV::VRM2RegClassID;
2615 return RISCV::VRM4RegClassID;
2617 return RISCV::VRM8RegClassID;
2625 static_assert(RISCV::sub_vrm1_7 == RISCV::sub_vrm1_0 + 7,
2626 "Unexpected subreg numbering");
2627 return RISCV::sub_vrm1_0 + Index;
2630 static_assert(RISCV::sub_vrm2_3 == RISCV::sub_vrm2_0 + 3,
2631 "Unexpected subreg numbering");
2632 return RISCV::sub_vrm2_0 + Index;
2635 static_assert(RISCV::sub_vrm4_1 == RISCV::sub_vrm4_0 + 1,
2636 "Unexpected subreg numbering");
2637 return RISCV::sub_vrm4_0 + Index;
2645 unsigned RegsPerField =
2648 switch (RegsPerField) {
2651 return RISCV::VRN2M1RegClassID;
2653 return RISCV::VRN3M1RegClassID;
2655 return RISCV::VRN4M1RegClassID;
2657 return RISCV::VRN5M1RegClassID;
2659 return RISCV::VRN6M1RegClassID;
2661 return RISCV::VRN7M1RegClassID;
2663 return RISCV::VRN8M1RegClassID;
2667 return RISCV::VRN2M2RegClassID;
2669 return RISCV::VRN3M2RegClassID;
2671 return RISCV::VRN4M2RegClassID;
2675 return RISCV::VRN2M4RegClassID;
2683 return RISCV::VRRegClassID;
2692std::pair<unsigned, unsigned>
2694 MVT VecVT,
MVT SubVecVT,
unsigned InsertExtractIdx,
2696 static_assert((RISCV::VRM8RegClassID > RISCV::VRM4RegClassID &&
2697 RISCV::VRM4RegClassID > RISCV::VRM2RegClassID &&
2698 RISCV::VRM2RegClassID > RISCV::VRRegClassID),
2699 "Register classes not ordered");
2706 if (VecRegClassID == SubRegClassID)
2707 return {RISCV::NoSubRegister, 0};
2710 "Only allow scalable vector subvector.");
2712 "Invalid vector tuple insert/extract for vector and subvector with "
2723 unsigned SubRegIdx = RISCV::NoSubRegister;
2724 for (
const unsigned RCID :
2725 {RISCV::VRM4RegClassID, RISCV::VRM2RegClassID, RISCV::VRRegClassID})
2726 if (VecRegClassID > RCID && SubRegClassID <= RCID) {
2730 SubRegIdx =
TRI->composeSubRegIndices(SubRegIdx,
2735 return {SubRegIdx, InsertExtractIdx};
2740bool RISCVTargetLowering::mergeStoresAfterLegalization(
EVT VT)
const {
2771unsigned RISCVTargetLowering::combineRepeatedFPDivisors()
const {
2778 "Unexpected opcode");
2780 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
2782 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
2785 return Op.getOperand(
II->VLOperand + 1 + HasChain);
2859bool RISCVTargetLowering::useRVVForFixedLengthVectorVT(
MVT VT)
const {
2860 return ::useRVVForFixedLengthVectorVT(VT, Subtarget);
2869 "Expected legal fixed length vector!");
2872 unsigned MaxELen = Subtarget.
getELen();
2906 return ::getContainerForFixedLengthVector(*
this, VT,
getSubtarget());
2913 "Expected to convert into a scalable vector!");
2914 assert(V.getValueType().isFixedLengthVector() &&
2915 "Expected a fixed length vector operand!");
2924 "Expected to convert into a fixed length vector!");
2925 assert(V.getValueType().isScalableVector() &&
2926 "Expected a scalable vector operand!");
2945 return DAG.
getNode(RISCVISD::VMSET_VL,
DL, MaskVT, VL);
2948static std::pair<SDValue, SDValue>
2957static std::pair<SDValue, SDValue>
2970static std::pair<SDValue, SDValue>
2987std::pair<unsigned, unsigned>
3003 return std::make_pair(MinVLMAX, MaxVLMAX);
3015 EVT VT,
unsigned DefinedValues)
const {
3029 std::tie(LMul, Fractional) =
3032 Cost = LMul <= DLenFactor ? (DLenFactor / LMul) : 1;
3034 Cost = (LMul * DLenFactor);
3048 bool Log2CostModel =
3050 if (Log2CostModel && LMULCost.isValid()) {
3051 unsigned Log =
Log2_64(LMULCost.getValue());
3053 return LMULCost * Log;
3055 return LMULCost * LMULCost;
3086 Op.getValueType() == MVT::bf16) {
3087 bool IsStrict =
Op->isStrictFPOpcode();
3092 {Op.getOperand(0), Op.getOperand(1)});
3094 {
Op.getValueType(), MVT::Other},
3100 DAG.
getNode(
Op.getOpcode(),
DL, MVT::f32,
Op.getOperand(0)),
3115 MVT DstVT =
Op.getSimpleValueType();
3116 EVT SatVT = cast<VTSDNode>(
Op.getOperand(1))->getVT();
3124 Src.getValueType() == MVT::bf16) {
3130 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
3131 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
3132 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
3139 Opc,
DL, DstVT, Src,
3142 if (
Opc == RISCVISD::FCVT_WU_RV64)
3153 MVT SrcVT = Src.getSimpleValueType();
3159 if (SatVT != DstEltVT)
3162 MVT DstContainerVT = DstVT;
3163 MVT SrcContainerVT = SrcVT;
3169 "Expected same element count");
3178 {Src, Src, DAG.getCondCode(ISD::SETNE),
3179 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
3183 if (DstEltSize > (2 * SrcEltSize)) {
3186 Src = DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, InterVT, Src, Mask, VL);
3189 MVT CvtContainerVT = DstContainerVT;
3190 MVT CvtEltVT = DstEltVT;
3191 if (SrcEltSize > (2 * DstEltSize)) {
3197 IsSigned ? RISCVISD::VFCVT_RTZ_X_F_VL : RISCVISD::VFCVT_RTZ_XU_F_VL;
3200 while (CvtContainerVT != DstContainerVT) {
3204 unsigned ClipOpc = IsSigned ? RISCVISD::TRUNCATE_VECTOR_VL_SSAT
3205 : RISCVISD::TRUNCATE_VECTOR_VL_USAT;
3206 Res = DAG.
getNode(ClipOpc,
DL, CvtContainerVT, Res, Mask, VL);
3210 RISCVISD::VMV_V_X_VL,
DL, DstContainerVT, DAG.
getUNDEF(DstContainerVT),
3212 Res = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, DstContainerVT, IsNan, SplatZero,
3213 Res, DAG.
getUNDEF(DstContainerVT), VL);
3223 bool IsStrict =
Op->isStrictFPOpcode();
3224 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
3234 {
Op.getOperand(0), SrcVal});
3235 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
3236 {Ext.getValue(1), Ext.getValue(0)});
3250 case ISD::VP_FROUNDEVEN:
3254 case ISD::VP_FROUNDTOZERO:
3258 case ISD::VP_FFLOOR:
3270 case ISD::VP_FROUND:
3280 case ISD::VP_LLRINT:
3294 MVT VT =
Op.getSimpleValueType();
3304 MVT ContainerVT = VT;
3311 if (
Op->isVPOpcode()) {
3312 Mask =
Op.getOperand(1);
3316 VL =
Op.getOperand(2);
3322 SDValue Abs = DAG.
getNode(RISCVISD::FABS_VL,
DL, ContainerVT, Src, Mask, VL);
3335 DAG.
getUNDEF(ContainerVT), MaxValNode, VL);
3340 DAG.
getNode(RISCVISD::SETCC_VL,
DL, SetccVT,
3349 switch (
Op.getOpcode()) {
3357 case ISD::VP_FFLOOR:
3360 case ISD::VP_FROUND:
3361 case ISD::VP_FROUNDEVEN:
3362 case ISD::VP_FROUNDTOZERO: {
3365 Truncated = DAG.
getNode(RISCVISD::VFCVT_RM_X_F_VL,
DL, IntVT, Src, Mask,
3370 Truncated = DAG.
getNode(RISCVISD::VFCVT_RTZ_X_F_VL,
DL, IntVT, Src,
3374 case ISD::VP_FNEARBYINT:
3375 Truncated = DAG.
getNode(RISCVISD::VFROUND_NOEXCEPT_VL,
DL, ContainerVT, Src,
3381 if (Truncated.
getOpcode() != RISCVISD::VFROUND_NOEXCEPT_VL)
3382 Truncated = DAG.
getNode(RISCVISD::SINT_TO_FP_VL,
DL, ContainerVT, Truncated,
3386 Truncated = DAG.
getNode(RISCVISD::FCOPYSIGN_VL,
DL, ContainerVT, Truncated,
3387 Src, Src, Mask, VL);
3402 MVT VT =
Op.getSimpleValueType();
3406 MVT ContainerVT = VT;
3418 MVT MaskVT = Mask.getSimpleValueType();
3421 {Chain, Src, Src, DAG.getCondCode(ISD::SETUNE),
3422 DAG.getUNDEF(MaskVT), Mask, VL});
3424 Src = DAG.
getNode(RISCVISD::STRICT_FADD_VL,
DL,
3426 {Chain, Src, Src, Src, Unorder, VL});
3427 Chain = Src.getValue(1);
3430 SDValue Abs = DAG.
getNode(RISCVISD::FABS_VL,
DL, ContainerVT, Src, Mask, VL);
3443 DAG.
getUNDEF(ContainerVT), MaxValNode, VL);
3447 RISCVISD::SETCC_VL,
DL, MaskVT,
3455 switch (
Op.getOpcode()) {
3465 RISCVISD::STRICT_VFCVT_RM_X_F_VL,
DL, DAG.
getVTList(IntVT, MVT::Other),
3466 {Chain, Src, Mask, DAG.getTargetConstant(FRM, DL, XLenVT), VL});
3471 DAG.
getNode(RISCVISD::STRICT_VFCVT_RTZ_X_F_VL,
DL,
3472 DAG.
getVTList(IntVT, MVT::Other), Chain, Src, Mask, VL);
3475 Truncated = DAG.
getNode(RISCVISD::STRICT_VFROUND_NOEXCEPT_VL,
DL,
3476 DAG.
getVTList(ContainerVT, MVT::Other), Chain, Src,
3484 Truncated = DAG.
getNode(RISCVISD::STRICT_SINT_TO_FP_VL,
DL,
3485 DAG.
getVTList(ContainerVT, MVT::Other), Chain,
3486 Truncated, Mask, VL);
3491 Truncated = DAG.
getNode(RISCVISD::FCOPYSIGN_VL,
DL, ContainerVT, Truncated,
3492 Src, Src, Mask, VL);
3502 MVT VT =
Op.getSimpleValueType();
3523 return DAG.
getNode(RISCVISD::FROUND,
DL, VT, Src, MaxValNode,
3531 MVT DstVT =
Op.getSimpleValueType();
3533 MVT SrcVT = Src.getSimpleValueType();
3538 MVT DstContainerVT = DstVT;
3539 MVT SrcContainerVT = SrcVT;
3551 if (SrcElemType == MVT::f16 || SrcElemType == MVT::bf16) {
3553 Src = DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, F32VT, Src, Mask, VL);
3557 DAG.
getNode(RISCVISD::VFCVT_RM_X_F_VL,
DL, DstContainerVT, Src, Mask,
3577 return DAG.
getNode(RISCVISD::VSLIDEDOWN_VL,
DL, VT, Ops);
3589 return DAG.
getNode(RISCVISD::VSLIDEUP_VL,
DL, VT, Ops);
3614 return std::nullopt;
3632 unsigned EltSizeInBits) {
3635 return std::nullopt;
3636 bool IsInteger =
Op.getValueType().isInteger();
3638 std::optional<unsigned> SeqStepDenom;
3639 std::optional<APInt> SeqStepNum;
3640 std::optional<APInt> SeqAddend;
3641 std::optional<std::pair<APInt, unsigned>> PrevElt;
3642 assert(EltSizeInBits >=
Op.getValueType().getScalarSizeInBits());
3647 const unsigned OpSize =
Op.getScalarValueSizeInBits();
3649 if (Elt.isUndef()) {
3650 Elts[
Idx] = std::nullopt;
3654 Elts[
Idx] = Elt->getAsAPIntVal().trunc(OpSize).zext(EltSizeInBits);
3659 return std::nullopt;
3660 Elts[
Idx] = *ExactInteger;
3673 unsigned IdxDiff =
Idx - PrevElt->second;
3674 APInt ValDiff = *Elt - PrevElt->first;
3682 int64_t Remainder = ValDiff.
srem(IdxDiff);
3687 return std::nullopt;
3688 ValDiff = ValDiff.
sdiv(IdxDiff);
3693 SeqStepNum = ValDiff;
3694 else if (ValDiff != SeqStepNum)
3695 return std::nullopt;
3698 SeqStepDenom = IdxDiff;
3699 else if (IdxDiff != *SeqStepDenom)
3700 return std::nullopt;
3704 if (!PrevElt || PrevElt->first != *Elt)
3705 PrevElt = std::make_pair(*Elt,
Idx);
3709 if (!SeqStepNum || !SeqStepDenom)
3710 return std::nullopt;
3718 (
APInt(EltSizeInBits,
Idx,
false,
true) *
3720 .sdiv(*SeqStepDenom);
3722 APInt Addend = *Elt - ExpectedVal;
3725 else if (Addend != SeqAddend)
3726 return std::nullopt;
3729 assert(SeqAddend &&
"Must have an addend if we have a step");
3731 return VIDSequence{SeqStepNum->getSExtValue(), *SeqStepDenom,
3732 SeqAddend->getSExtValue()};
3747 MVT SrcVT = Src.getSimpleValueType();
3758 auto *CIdx = dyn_cast<ConstantSDNode>(
Idx);
3764 MVT ContainerVT = VT;
3768 MVT SrcContainerVT = SrcVT;
3783 SDValue Gather = DAG.
getNode(RISCVISD::VRGATHER_VX_VL,
DL, ContainerVT, Src,
3792 MVT VT =
Op.getSimpleValueType();
3801 int64_t StepNumerator = SimpleVID->StepNumerator;
3802 unsigned StepDenominator = SimpleVID->StepDenominator;
3803 int64_t Addend = SimpleVID->Addend;
3805 assert(StepNumerator != 0 &&
"Invalid step");
3806 bool Negate =
false;
3807 int64_t SplatStepVal = StepNumerator;
3811 if (StepNumerator != 1 && StepNumerator !=
INT64_MIN &&
3813 Negate = StepNumerator < 0;
3815 SplatStepVal =
Log2_64(std::abs(StepNumerator));
3822 if (((StepOpcode ==
ISD::MUL && isInt<12>(SplatStepVal)) ||
3823 (StepOpcode ==
ISD::SHL && isUInt<5>(SplatStepVal))) &&
3825 (SplatStepVal >= 0 || StepDenominator == 1) && isInt<32>(Addend)) {
3828 MVT VIDContainerVT =
3836 if ((StepOpcode ==
ISD::MUL && SplatStepVal != 1) ||
3837 (StepOpcode ==
ISD::SHL && SplatStepVal != 0)) {
3839 VID = DAG.
getNode(StepOpcode,
DL, VIDVT, VID, SplatStep);
3841 if (StepDenominator != 1) {
3846 if (Addend != 0 || Negate) {
3872 MVT VT =
Op.getSimpleValueType();
3884 unsigned MostCommonCount = 0;
3886 unsigned NumUndefElts =
3894 unsigned NumScalarLoads = 0;
3900 unsigned &Count = ValueCounts[V];
3902 if (
auto *CFP = dyn_cast<ConstantFPSDNode>(V))
3903 NumScalarLoads += !CFP->isExactlyValue(+0.0);
3908 if (++Count >= MostCommonCount) {
3910 MostCommonCount = Count;
3914 assert(DominantValue &&
"Not expecting an all-undef BUILD_VECTOR");
3915 unsigned NumDefElts = NumElts - NumUndefElts;
3916 unsigned DominantValueCountThreshold = NumDefElts <= 2 ? 0 : NumDefElts - 2;
3922 ((MostCommonCount > DominantValueCountThreshold) ||
3935 !LastOp.isUndef() && ValueCounts[LastOp] == 1 &&
3936 LastOp != DominantValue) {
3939 VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1DOWN_VL : RISCVISD::VSLIDE1DOWN_VL;
3945 Processed.insert(LastOp);
3951 if (V.isUndef() || !Processed.insert(V).second)
3953 if (ValueCounts[V] == 1) {
3961 return DAG.getConstant(V == V1, DL, XLenVT);
3977 MVT VT =
Op.getSimpleValueType();
4007 unsigned NumViaIntegerBits = std::clamp(NumElts, 8u, Subtarget.
getXLen());
4008 NumViaIntegerBits = std::min(NumViaIntegerBits, Subtarget.
getELen());
4016 unsigned IntegerViaVecElts =
divideCeil(NumElts, NumViaIntegerBits);
4017 MVT IntegerViaVecVT =
4022 unsigned BitPos = 0, IntegerEltIdx = 0;
4025 for (
unsigned I = 0;
I < NumElts;) {
4027 bool BitValue = !V.isUndef() && V->getAsZExtVal();
4028 Bits |= ((
uint64_t)BitValue << BitPos);
4034 if (
I % NumViaIntegerBits == 0 ||
I == NumElts) {
4035 if (NumViaIntegerBits <= 32)
4036 Bits = SignExtend64<32>(Bits);
4038 Elts[IntegerEltIdx] = Elt;
4047 if (NumElts < NumViaIntegerBits) {
4051 assert(IntegerViaVecVT == MVT::v1i8 &&
"Unexpected mask vector type");
4066 : RISCVISD::VMV_V_X_VL;
4086 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32) &&
4087 "Unexpected sequence type");
4091 unsigned ViaVecLen =
4095 uint64_t EltMask = maskTrailingOnes<uint64_t>(EltBitSize);
4099 const auto &SeqV =
OpIdx.value();
4100 if (!SeqV.isUndef())
4102 ((SeqV->getAsZExtVal() & EltMask) << (
OpIdx.index() * EltBitSize));
4108 if (ViaIntVT == MVT::i32)
4109 SplatValue = SignExtend64<32>(SplatValue);
4128 const auto *BV = cast<BuildVectorSDNode>(
Op);
4131 BV->getRepeatedSequence(Sequence) &&
4132 (Sequence.size() * EltBitSize) <= Subtarget.
getELen()) {
4133 unsigned SeqLen = Sequence.size();
4135 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32 ||
4136 ViaIntVT == MVT::i64) &&
4137 "Unexpected sequence type");
4142 const unsigned RequiredVL = NumElts / SeqLen;
4143 const unsigned ViaVecLen =
4145 NumElts : RequiredVL;
4148 unsigned EltIdx = 0;
4149 uint64_t EltMask = maskTrailingOnes<uint64_t>(EltBitSize);
4153 for (
const auto &SeqV : Sequence) {
4154 if (!SeqV.isUndef())
4156 ((SeqV->getAsZExtVal() & EltMask) << (EltIdx * EltBitSize));
4163 if (ViaIntVT == MVT::i32)
4164 SplatValue = SignExtend64<32>(SplatValue);
4170 (!Subtarget.
is64Bit() && ViaIntVT == MVT::i64)) &&
4171 "Unexpected bitcast sequence");
4172 if (ViaIntVT.
bitsLE(XLenVT) || isInt<32>(SplatValue)) {
4175 MVT ViaContainerVT =
4178 DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ViaContainerVT,
4182 if (ViaVecLen != RequiredVL)
4201 Source, DAG, Subtarget);
4202 SDValue Res = DAG.
getNode(RISCVISD::VSEXT_VL,
DL, ContainerVT, Source, Mask, VL);
4221 return RISCV::PACKH;
4223 return Subtarget.
is64Bit() ? RISCV::PACKW : RISCV::PACK;
4238 MVT VT =
Op.getSimpleValueType();
4246 if (!Subtarget.hasStdExtZbb() || !Subtarget.hasStdExtZba())
4251 if (ElemSizeInBits >= std::min(Subtarget.
getELen(), Subtarget.
getXLen()) ||
4265 if (Subtarget.hasStdExtZbkb())
4270 ElemDL, XLenVT,
A,
B),
4282 NewOperands.
reserve(NumElts / 2);
4284 NewOperands.
push_back(pack(
Op.getOperand(i),
Op.getOperand(i + 1)));
4294 MVT VT =
Op.getSimpleValueType();
4305 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) || EltVT == MVT::bf16) {
4310 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4311 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin())) {
4314 if (
auto *
C = dyn_cast<ConstantFPSDNode>(Elem)) {
4321 NewOps[
I] = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Elem);
4371 [](
const SDUse &U) { return U.get().isUndef(); })) {
4412 auto OneVRegOfOps =
ArrayRef(BuildVectorOps).
slice(i, ElemsPerVReg);
4416 unsigned InsertIdx = (i / ElemsPerVReg) * NumOpElts;
4438 unsigned NumUndefElts =
4440 unsigned NumDefElts = NumElts - NumUndefElts;
4441 if (NumDefElts >= 8 && NumDefElts > NumElts / 2 &&
4450 if (
Idx < NumElts / 2) {
4457 bool SelectMaskVal = (
Idx < NumElts / 2);
4460 assert(SubVecAOps.
size() == NumElts && SubVecBOps.
size() == NumElts &&
4461 MaskVals.
size() == NumElts);
4496 unsigned UndefCount = 0;
4503 LinearBudget -= PerSlideCost;
4506 LinearBudget -= PerSlideCost;
4509 LinearBudget -= PerSlideCost;
4512 if (LinearBudget < 0)
4517 "Illegal type which will result in reserved encoding");
4533 bool SlideUp =
false;
4548 using namespace SDPatternMatch;
4599 Vec = getVSlide(ContainerVT, DAG.
getUNDEF(ContainerVT), Vec,
Offset, Mask,
4606 Opcode = SlideUp ? RISCVISD::VFSLIDE1UP_VL : RISCVISD::VFSLIDE1DOWN_VL;
4608 Opcode = SlideUp ? RISCVISD::VSLIDE1UP_VL : RISCVISD::VSLIDE1DOWN_VL;
4617 Vec = getVSlide(ContainerVT, DAG.
getUNDEF(ContainerVT), Vec,
Offset, Mask,
4628 if (isa<ConstantSDNode>(
Lo) && isa<ConstantSDNode>(
Hi)) {
4629 int32_t LoC = cast<ConstantSDNode>(
Lo)->getSExtValue();
4630 int32_t HiC = cast<ConstantSDNode>(
Hi)->getSExtValue();
4633 if ((LoC >> 31) == HiC)
4634 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4640 if (isa<ConstantSDNode>(VL) && isUInt<4>(VL->
getAsZExtVal()))
4646 auto InterVec = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, InterVT,
4654 isa<ConstantSDNode>(
Hi.getOperand(1)) &&
4655 Hi.getConstantOperandVal(1) == 31)
4656 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4661 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4664 return DAG.
getNode(RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL,
DL, VT, Passthru,
Lo,
4674 assert(Scalar.getValueType() == MVT::i64 &&
"Unexpected VT!");
4686 bool HasPassthru = Passthru && !Passthru.
isUndef();
4687 if (!HasPassthru && !Passthru)
4694 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
4695 EltVT == MVT::bf16) {
4696 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4697 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
4698 Scalar = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Scalar);
4707 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL, VT, Passthru, Scalar, VL);
4711 if (Scalar.getValueType().bitsLE(XLenVT)) {
4718 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4719 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru, Scalar, VL);
4722 assert(XLenVT == MVT::i32 && Scalar.getValueType() == MVT::i64 &&
4723 "Unexpected scalar for splat lowering!");
4726 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, VT, Passthru,
4747 SDValue ExtractedVal = Scalar.getOperand(0);
4752 MVT ExtractedContainerVT = ExtractedVT;
4755 DAG, ExtractedContainerVT, Subtarget);
4757 ExtractedVal, DAG, Subtarget);
4759 if (ExtractedContainerVT.
bitsLE(VT))
4771 if (!Scalar.getValueType().bitsLE(XLenVT))
4774 VT,
DL, DAG, Subtarget);
4782 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4823 Src && Src.getValueType().getVectorNumElements() == (NumElts * 2))
4840 !Subtarget.hasVendorXRivosVizip())
4843 int Size = Mask.size();
4845 assert(
Size == (
int)NumElts &&
"Unexpected mask size");
4851 EvenSrc = StartIndexes[0];
4852 OddSrc = StartIndexes[1];
4855 if (EvenSrc != 0 && OddSrc != 0)
4865 int HalfNumElts = NumElts / 2;
4866 return ((EvenSrc % HalfNumElts) == 0) && ((OddSrc % HalfNumElts) == 0);
4871 std::array<std::pair<int, int>, 2> &SrcInfo) {
4876 if (SrcInfo[0].second == 0 && SrcInfo[1].second == 0)
4880 if ((SrcInfo[0].second > 0 && SrcInfo[1].second < 0) ||
4881 SrcInfo[1].second == 0)
4883 assert(SrcInfo[0].first != -1 &&
"Must find one slide");
4891 if (SrcInfo[1].first == -1)
4893 return SrcInfo[0].second < 0 && SrcInfo[1].second > 0 &&
4894 SrcInfo[1].second - SrcInfo[0].second == (int)NumElts;
4899 bool RequiredPolarity) {
4900 int NumElts = Mask.size();
4904 int Src = M >= NumElts;
4905 int Diff = (int)
Idx - (M % NumElts);
4906 bool C = Src == SrcInfo[1].first && Diff == SrcInfo[1].second;
4907 assert(
C != (Src == SrcInfo[0].first && Diff == SrcInfo[0].second) &&
4908 "Must match exactly one of the two slides");
4909 if (RequiredPolarity != (
C == (
Idx / Factor) % 2))
4920static bool isZipEven(
const std::array<std::pair<int, int>, 2> &SrcInfo,
4922 Factor = SrcInfo[1].second;
4924 Mask.size() % Factor == 0 &&
4935static bool isZipOdd(
const std::array<std::pair<int, int>, 2> &SrcInfo,
4937 Factor = -SrcInfo[1].second;
4939 Mask.size() % Factor == 0 &&
4952 ElementCount SrcEC = Src.getValueType().getVectorElementCount();
4959 unsigned Shift = Index * EltBits;
4984 std::optional<int> SplatIdx;
4986 if (M == -1 ||
I == (
unsigned)M)
4988 if (SplatIdx && *SplatIdx != M)
4997 for (
int MaskIndex : Mask) {
4998 bool SelectMaskVal = MaskIndex == *SplatIdx;
5001 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
5026 auto findNonEXTRACT_SUBVECTORParent =
5027 [](
SDValue Parent) -> std::pair<SDValue, uint64_t> {
5032 Parent.getOperand(0).getSimpleValueType().isFixedLengthVector()) {
5033 Offset += Parent.getConstantOperandVal(1);
5034 Parent = Parent.getOperand(0);
5036 return std::make_pair(Parent,
Offset);
5039 auto [V1Src, V1IndexOffset] = findNonEXTRACT_SUBVECTORParent(V1);
5040 auto [V2Src, V2IndexOffset] = findNonEXTRACT_SUBVECTORParent(V2);
5049 for (
size_t i = 0; i != NewMask.
size(); ++i) {
5050 if (NewMask[i] == -1)
5053 if (
static_cast<size_t>(NewMask[i]) < NewMask.
size()) {
5054 NewMask[i] = NewMask[i] + V1IndexOffset;
5058 NewMask[i] = NewMask[i] - NewMask.
size() + V2IndexOffset;
5064 if (NewMask[0] <= 0)
5068 for (
unsigned i = 1; i != NewMask.
size(); ++i)
5069 if (NewMask[i - 1] + 1 != NewMask[i])
5073 MVT SrcVT = Src.getSimpleValueType();
5102 int NumSubElts, Index;
5107 bool OpsSwapped = Mask[Index] < (int)NumElts;
5108 SDValue InPlace = OpsSwapped ? V2 : V1;
5109 SDValue ToInsert = OpsSwapped ? V1 : V2;
5120 if (NumSubElts + Index >= (
int)NumElts)
5131 Res = DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, ContainerVT, InPlace, ToInsert,
5134 Res =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, InPlace, ToInsert,
5146 bool OpsSwapped =
false;
5147 if (!isa<BuildVectorSDNode>(V1)) {
5148 if (!isa<BuildVectorSDNode>(V2))
5153 SDValue Splat = cast<BuildVectorSDNode>(V1)->getSplatValue();
5161 const unsigned E = Mask.size() - ((
Offset > 0) ?
Offset : 0);
5162 for (
unsigned i = S; i != E; ++i)
5163 if (Mask[i] >= 0 && (
unsigned)Mask[i] !=
Base + i +
Offset)
5169 bool IsVSlidedown = isSlideMask(Mask, OpsSwapped ? 0 : NumElts, 1);
5170 if (!IsVSlidedown && !isSlideMask(Mask, OpsSwapped ? 0 : NumElts, -1))
5173 const int InsertIdx = Mask[IsVSlidedown ? (NumElts - 1) : 0];
5175 if (InsertIdx < 0 || InsertIdx / NumElts != (
unsigned)OpsSwapped)
5192 IsVSlidedown ? RISCVISD::VSLIDE1DOWN_VL : RISCVISD::VSLIDE1UP_VL,
DL,
5198 auto OpCode = IsVSlidedown ?
5199 (VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1DOWN_VL : RISCVISD::VSLIDE1DOWN_VL) :
5200 (VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1UP_VL : RISCVISD::VSLIDE1UP_VL);
5203 auto Vec = DAG.
getNode(OpCode,
DL, ContainerVT,
5206 Splat, TrueMask, VL);
5218 for (
unsigned i = 0; i < Mask.size(); i++)
5219 LaneIsUndef[i % Factor] &= (Mask[i] == -1);
5222 for (
unsigned i = 0; i < Factor; i++) {
5233 for (
unsigned i = 0; i < Mask.size() / Factor; i++) {
5234 unsigned j = i * Factor + Index;
5235 if (Mask[j] != -1 && (
unsigned)Mask[j] != i)
5244 assert(RISCVISD::RI_VZIPEVEN_VL ==
Opc || RISCVISD::RI_VZIPODD_VL ==
Opc ||
5245 RISCVISD::RI_VZIP2A_VL ==
Opc || RISCVISD::RI_VZIP2B_VL ==
Opc ||
5246 RISCVISD::RI_VUNZIP2A_VL ==
Opc || RISCVISD::RI_VUNZIP2B_VL ==
Opc);
5254 MVT ContainerVT = IntVT;
5261 MVT InnerVT = ContainerVT;
5265 (RISCVISD::RI_VUNZIP2A_VL ==
Opc || RISCVISD::RI_VUNZIP2B_VL ==
Opc)) {
5277 if (InnerVT.
bitsLT(ContainerVT))
5292 MVT VT = V.getSimpleValueType();
5307 EC.multiplyCoefficientBy(Factor));
5326 MVT VecContainerVT = VecVT;
5343 MVT WideContainerVT = WideVT;
5349 EvenV = DAG.
getBitcast(VecContainerVT, EvenV);
5356 if (Subtarget.hasStdExtZvbb()) {
5360 Interleaved = DAG.
getNode(RISCVISD::VWSLL_VL,
DL, WideContainerVT, OddV,
5361 OffsetVec, Passthru, Mask, VL);
5362 Interleaved = DAG.
getNode(RISCVISD::VWADDU_W_VL,
DL, WideContainerVT,
5363 Interleaved, EvenV, Passthru, Mask, VL);
5370 Interleaved = DAG.
getNode(RISCVISD::VWADDU_VL,
DL, WideContainerVT, EvenV,
5371 OddV, Passthru, Mask, VL);
5377 OddV, AllOnesVec, Passthru, Mask, VL);
5384 Interleaved = DAG.
getNode(RISCVISD::ADD_VL,
DL, WideContainerVT,
5385 Interleaved, OddsMul, Passthru, Mask, VL);
5392 Interleaved = DAG.
getBitcast(ResultContainerVT, Interleaved);
5438 if (ViaEltSize > NumElts)
5446 if (ViaEltSize > NumElts)
5452 if (ViaEltSize > NumElts)
5459 MVT &RotateVT,
unsigned &RotateAmt) {
5462 unsigned NumSubElts;
5464 NumElts, NumSubElts, RotateAmt))
5467 NumElts / NumSubElts);
5535 unsigned NumOfSrcRegs = NumElts / NumOpElts;
5536 unsigned NumOfDestRegs = NumElts / NumOpElts;
5545 Mask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs,
5546 [&]() {
Operands.emplace_back(); },
5547 [&](
ArrayRef<int> SrcSubMask,
unsigned SrcVecIdx,
unsigned DstVecIdx) {
5548 Operands.emplace_back().emplace_back(SrcVecIdx, UINT_MAX,
5551 [&](
ArrayRef<int> SrcSubMask,
unsigned Idx1,
unsigned Idx2,
bool NewReg) {
5556 assert(
Operands.size() == NumOfDestRegs &&
"Whole vector must be processed");
5561 unsigned NumShuffles = std::accumulate(
5568 for (const auto &P : Data) {
5569 unsigned Idx2 = std::get<1>(P);
5570 ArrayRef<int> Mask = std::get<2>(P);
5571 if (Idx2 != UINT_MAX)
5573 else if (ShuffleVectorInst::isIdentityMask(Mask, Mask.size()))
5578 if ((NumOfDestRegs > 2 && NumShuffles > NumOfDestRegs) ||
5579 (NumOfDestRegs <= 2 && NumShuffles >= 4))
5581 auto ExtractValue = [&, &DAG = DAG](
SDValue SrcVec,
unsigned ExtractIdx) {
5582 SDValue SubVec = DAG.getExtractSubvector(
DL, M1VT, SrcVec, ExtractIdx);
5586 auto PerformShuffle = [&, &DAG = DAG](
SDValue SubVec1,
SDValue SubVec2,
5588 SDValue SubVec = DAG.getVectorShuffle(OneRegVT,
DL, SubVec1, SubVec2, Mask);
5591 SDValue Vec = DAG.getUNDEF(ContainerVT);
5596 for (
unsigned I : seq<unsigned>(
Data.size())) {
5597 const auto &[Idx1, Idx2,
_] =
Data[
I];
5605 V = ExtractValue(Idx1 >= NumOfSrcRegs ? V2 : V1,
5606 (Idx1 % NumOfSrcRegs) * NumOpElts);
5607 if (Idx2 != UINT_MAX) {
5610 V = ExtractValue(Idx2 >= NumOfSrcRegs ? V2 : V1,
5611 (Idx2 % NumOfSrcRegs) * NumOpElts);
5615 for (
const auto &[Idx1, Idx2, Mask] :
Data) {
5617 SDValue V2 = Idx2 == UINT_MAX ? V1 : Values.
at(Idx2);
5618 V = PerformShuffle(V1, V2, Mask);
5622 unsigned InsertIdx =
I * NumOpElts;
5624 Vec = DAG.getInsertSubvector(
DL, Vec, V, InsertIdx);
5634 bool SawUndef =
false;
5642 if (
Idx > (
unsigned)M)
5675 for (
int Idx : Mask) {
5678 unsigned SrcIdx =
Idx % Mask.size();
5680 if (Srcs[SrcIdx] == -1)
5683 else if (Srcs[SrcIdx] != Src)
5689 for (
int Lane : Srcs) {
5702 for (
unsigned I = 0;
I < Mask.size();
I++) {
5706 NewMask[
I] = Mask[
I] % Mask.size();
5720 if ((M / Span) != (
int)(
I / Span))
5722 int SpanIdx =
I % Span;
5732 return all_of(Mask, [&](
const auto &
Idx) {
return Idx == -1 ||
Idx < Span; });
5744 int SpanIdx =
I % Span;
5745 if (Mask[SpanIdx] != M)
5759 MVT VT =
Op.getSimpleValueType();
5767 if (ElementSize > 32)
5790 MVT VT =
Op.getSimpleValueType();
5818 auto [TrueMask, VL] = TrueMaskVL;
5833 V.getOperand(0).getSimpleValueType().getVectorNumElements();
5834 V = V.getOperand(
Offset / OpElements);
5840 auto *Ld = cast<LoadSDNode>(V);
5850 SDValue Ops[] = {Ld->getChain(),
5864 MVT SplatVT = ContainerVT;
5867 if (SVT == MVT::bf16 ||
5868 (SVT == MVT::f16 && !Subtarget.hasStdExtZfh())) {
5877 V = DAG.
getLoad(SVT,
DL, Ld->getChain(), NewAddr,
5878 Ld->getPointerInfo().getWithOffset(
Offset),
5879 Ld->getBaseAlign(), Ld->getMemOperand()->
getFlags());
5882 Ld->getPointerInfo().getWithOffset(
Offset), SVT,
5884 Ld->getMemOperand()->getFlags());
5888 : RISCVISD::VMV_V_X_VL;
5896 assert(Lane < (
int)NumElts &&
"Unexpected lane!");
5899 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
5921 if (Subtarget.hasStdExtZvkb())
5937 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
5938 for (
unsigned Factor = 2; Factor <= MaxFactor; Factor <<= 1) {
5945 [&Mask](
int Idx) {
return Idx < (int)Mask.size(); }) &&
5947 return Idx >= (int)Mask.size();
5977 if (Subtarget.hasVendorXRivosVizip() &&
5981 Index == 0 ? RISCVISD::RI_VUNZIP2A_VL : RISCVISD::RI_VUNZIP2B_VL;
5997 [&Mask](
int Idx) {
return Idx < (int)Mask.size(); }) &&
5999 [&Mask](
int Idx) {
return Idx >= (int)Mask.size(); })) {
6003 if (NumElts < MinVLMAX) {
6027 int EvenSrc, OddSrc;
6037 bool LaneIsUndef[2] = {
true,
true};
6039 LaneIsUndef[
Idx % 2] &= (M == -1);
6041 int Size = Mask.size();
6043 if (LaneIsUndef[0]) {
6046 assert(EvenSrc >= 0 &&
"Undef source?");
6047 EvenV = (EvenSrc /
Size) == 0 ? V1 : V2;
6051 if (LaneIsUndef[1]) {
6054 assert(OddSrc >= 0 &&
"Undef source?");
6055 OddV = (OddSrc /
Size) == 0 ? V1 : V2;
6061 if (Subtarget.hasVendorXRivosVizip()) {
6064 return lowerVZIP(RISCVISD::RI_VZIP2A_VL, EvenV, OddV,
DL, DAG, Subtarget);
6075 std::array<std::pair<int, int>, 2> SrcInfo;
6082 auto GetSourceFor = [&](
const std::pair<int, int> &
Info) {
6083 int SrcIdx =
Info.first;
6084 assert(SrcIdx == 0 || SrcIdx == 1);
6085 SDValue &Src = Sources[SrcIdx];
6087 SDValue SrcV = SrcIdx == 0 ? V1 : V2;
6092 auto GetSlide = [&](
const std::pair<int, int> &Src,
SDValue Mask,
6094 auto [TrueMask, VL] = TrueMaskVL;
6095 SDValue SrcV = GetSourceFor(Src);
6096 int SlideAmt = Src.second;
6097 if (SlideAmt == 0) {
6099 assert(Mask == TrueMask);
6106 return getVSlideup(DAG, Subtarget,
DL, ContainerVT, Passthru, SrcV,
6111 if (SrcInfo[1].first == -1) {
6113 Res = GetSlide(SrcInfo[0], TrueMask, Res);
6117 if (Subtarget.hasVendorXRivosVizip()) {
6118 bool TryWiden =
false;
6122 SDValue Src1 = SrcInfo[0].first == 0 ? V1 : V2;
6123 SDValue Src2 = SrcInfo[1].first == 0 ? V1 : V2;
6124 return lowerVZIP(RISCVISD::RI_VZIPEVEN_VL, Src1, Src2,
DL, DAG,
6129 if (
isZipOdd(SrcInfo, Mask, Factor)) {
6131 SDValue Src1 = SrcInfo[1].first == 0 ? V1 : V2;
6132 SDValue Src2 = SrcInfo[0].first == 0 ? V1 : V2;
6133 return lowerVZIP(RISCVISD::RI_VZIPODD_VL, Src1, Src2,
DL, DAG,
6153 (SrcInfo[1].second > 0 &&
Idx < (
unsigned)SrcInfo[1].second)) {
6157 int Src = M >= (int)NumElts;
6158 int Diff = (int)
Idx - (M % NumElts);
6159 bool C = Src == SrcInfo[1].first && Diff == SrcInfo[1].second;
6160 assert(
C ^ (Src == SrcInfo[0].first && Diff == SrcInfo[0].second) &&
6161 "Must match exactly one of the two slides");
6164 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
6171 Res = GetSlide(SrcInfo[0], TrueMask, Res);
6172 Res = GetSlide(SrcInfo[1], SelectMask, Res);
6177 assert(!V1.
isUndef() &&
"Unexpected shuffle canonicalization");
6192 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
6193 for (
unsigned Factor = 4; Factor <= MaxFactor; Factor <<= 1) {
6208 if (NumElts > MinVLMAX) {
6209 unsigned MaxIdx = 0;
6213 MaxIdx = std::max(std::max((
unsigned)
I, (
unsigned)M), MaxIdx);
6215 unsigned NewNumElts =
6217 if (NewNumElts != NumElts) {
6221 Mask.take_front(NewNumElts));
6238 for (
auto Idx : Mask) {
6251 any_of(Mask, [&](
const auto &
Idx) {
return Idx > 255; })) {
6261 unsigned GatherVVOpc = RISCVISD::VRGATHER_VV_VL;
6267 GatherVVOpc = RISCVISD::VRGATHEREI16_VV_VL;
6276 GatherVVOpc = RISCVISD::VRGATHEREI16_VV_VL;
6280 MVT IndexContainerVT =
6285 for (
int MaskIndex : Mask) {
6286 bool IsLHSIndex = MaskIndex < (int)NumElts && MaskIndex >= 0;
6296 if (NumElts <= MinVLMAX) {
6298 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
6304 auto [InnerTrueMask, InnerVL] =
6316 for (
int i = 0; i <
N; i++) {
6320 DAG.
getNode(GatherVVOpc,
DL, M1VT, SubV1, SubIndex,
6321 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6338 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6340 for (
int i = 0; i <
N; i++)
6356 for (
int i = 0; i <
N; i++) {
6359 DAG.
getUNDEF(IndexContainerVT), LHSIndices,
6360 SlideAmt, TrueMask, VL);
6364 DAG.
getNode(GatherVVOpc,
DL, M1VT, SubV1, SubIndex,
6365 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6375 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
6385 for (
int MaskIndex : Mask) {
6386 bool IsLHSOrUndefIndex = MaskIndex < (int)NumElts;
6387 ShuffleMaskLHS.
push_back(IsLHSOrUndefIndex && MaskIndex >= 0
6389 ShuffleMaskRHS.
push_back(IsLHSOrUndefIndex ? -1 : (MaskIndex - NumElts));
6420 for (
int MaskIndex : Mask) {
6421 bool SelectMaskVal = (MaskIndex < (int)NumElts) ^ !SwapOps;
6425 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
6443 const unsigned NumElts = M.size();
6450 std::array<std::pair<int, int>, 2> SrcInfo;
6461RISCVTargetLowering::lowerCTLZ_CTTZ_ZERO_UNDEF(
SDValue Op,
6463 MVT VT =
Op.getSimpleValueType();
6467 MVT ContainerVT = VT;
6470 if (
Op->isVPOpcode()) {
6471 Mask =
Op.getOperand(1);
6475 VL =
Op.getOperand(2);
6481 MVT FloatEltVT = (EltSize >= 32) ? MVT::f64 : MVT::f32;
6483 FloatEltVT = MVT::f32;
6490 "Expected legal float type!");
6497 }
else if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF) {
6500 Src = DAG.
getNode(ISD::VP_AND,
DL, VT, Src, Neg, Mask, VL);
6505 if (FloatVT.
bitsGT(VT)) {
6506 if (
Op->isVPOpcode())
6507 FloatVal = DAG.
getNode(ISD::VP_UINT_TO_FP,
DL, FloatVT, Src, Mask, VL);
6516 if (!
Op->isVPOpcode())
6520 MVT ContainerFloatVT =
6522 FloatVal = DAG.
getNode(RISCVISD::VFCVT_RM_F_XU_VL,
DL, ContainerFloatVT,
6523 Src, Mask, RTZRM, VL);
6530 unsigned ShiftAmt = FloatEltVT == MVT::f64 ? 52 : 23;
6534 if (
Op->isVPOpcode()) {
6543 else if (IntVT.
bitsGT(VT))
6548 unsigned ExponentBias = FloatEltVT == MVT::f64 ? 1023 : 127;
6553 if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF)
6554 return DAG.
getNode(ISD::VP_SUB,
DL, VT, Exp,
6559 unsigned Adjust = ExponentBias + (EltSize - 1);
6561 if (
Op->isVPOpcode())
6571 else if (
Op.getOpcode() == ISD::VP_CTLZ)
6572 Res = DAG.
getNode(ISD::VP_UMIN,
DL, VT, Res,
6582 MVT SrcVT =
Source.getSimpleValueType();
6591 SrcVT = ContainerVT;
6603 SDValue Res = DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Source, Mask, EVL);
6604 if (
Op->getOpcode() == ISD::VP_CTTZ_ELTS_ZERO_UNDEF)
6621 auto *
Load = cast<LoadSDNode>(
Op);
6622 assert(Load &&
Load->getMemoryVT().isVector() &&
"Expected vector load");
6625 Load->getMemoryVT(),
6626 *
Load->getMemOperand()))
6630 MVT VT =
Op.getSimpleValueType();
6632 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
6633 "Unexpected unaligned RVV load type");
6637 "Expecting equally-sized RVV vector types to be legal");
6639 Load->getPointerInfo(),
Load->getBaseAlign(),
6640 Load->getMemOperand()->getFlags());
6650 auto *
Store = cast<StoreSDNode>(
Op);
6651 assert(Store &&
Store->getValue().getValueType().isVector() &&
6652 "Expected vector store");
6655 Store->getMemoryVT(),
6656 *
Store->getMemOperand()))
6663 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
6664 "Unexpected unaligned RVV store type");
6668 "Expecting equally-sized RVV vector types to be legal");
6669 StoredVal = DAG.
getBitcast(NewVT, StoredVal);
6671 Store->getPointerInfo(),
Store->getBaseAlign(),
6672 Store->getMemOperand()->getFlags());
6677 assert(
Op.getValueType() == MVT::i64 &&
"Unexpected VT");
6679 int64_t Imm = cast<ConstantSDNode>(
Op)->getSExtValue();
6706 unsigned ShiftAmt, AddOpc;
6717 MVT VT =
Op.getSimpleValueType();
6718 const APFloat &
Imm = cast<ConstantFPSDNode>(
Op)->getValueAPF();
6721 bool Negate =
false;
6725 if (Index < 0 &&
Imm.isNegative()) {
6748 unsigned IsData =
Op.getConstantOperandVal(4);
6751 if (Subtarget.hasVendorXMIPSCBOP() && !IsData)
6752 return Op.getOperand(0);
6764 if (Subtarget.hasStdExtZtso()) {
6788 MVT VT =
Op.getSimpleValueType();
6790 unsigned Check =
Op.getConstantOperandVal(1);
6791 unsigned TDCMask = 0;
6819 MVT VT0 =
Op.getOperand(0).getSimpleValueType();
6824 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6826 VL =
Op.getOperand(3);
6829 VL,
Op->getFlags());
6844 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6846 MVT MaskContainerVT =
6849 VL =
Op.getOperand(3);
6853 SDValue FPCLASS = DAG.
getNode(RISCVISD::FCLASS_VL,
DL, ContainerDstVT, Op0,
6854 Mask, VL,
Op->getFlags());
6856 TDCMaskV = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerDstVT,
6857 DAG.
getUNDEF(ContainerDstVT), TDCMaskV, VL);
6860 DAG.
getNode(RISCVISD::SETCC_VL,
DL, ContainerVT,
6862 DAG.
getUNDEF(ContainerVT), Mask, VL});
6866 TDCMaskV, DAG.
getUNDEF(ContainerDstVT), Mask, VL);
6869 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerDstVT,
6870 DAG.
getUNDEF(ContainerDstVT), SplatZero, VL);
6874 DAG.
getUNDEF(ContainerVT), Mask, VL});
6890 MVT VT =
Op.getSimpleValueType();
6924 MVT ContainerVT = VT;
6932 if (
Op->isVPOpcode()) {
6933 Mask =
Op.getOperand(2);
6937 VL =
Op.getOperand(3);
6944 SDValue XIsNonNan = DAG.
getNode(RISCVISD::SETCC_VL,
DL, Mask.getValueType(),
6945 {X, X, DAG.getCondCode(ISD::SETOEQ),
6946 DAG.getUNDEF(ContainerVT), Mask, VL});
6947 NewY = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, XIsNonNan,
Y,
X,
6953 SDValue YIsNonNan = DAG.
getNode(RISCVISD::SETCC_VL,
DL, Mask.getValueType(),
6954 {Y, Y, DAG.getCondCode(ISD::SETOEQ),
6955 DAG.getUNDEF(ContainerVT), Mask, VL});
6956 NewX = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, YIsNonNan,
X,
Y,
6962 ? RISCVISD::VFMAX_VL
6963 : RISCVISD::VFMIN_VL;
6965 DAG.
getUNDEF(ContainerVT), Mask, VL);
6975 "Wrong opcode for lowering FABS or FNEG.");
6978 MVT VT =
Op.getSimpleValueType();
6979 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
6983 DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT,
Op.getOperand(0));
6986 Mask = Mask.sext(Subtarget.
getXLen());
6991 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, Logic);
6999 MVT VT =
Op.getSimpleValueType();
7000 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
7010 if (SignSize == Subtarget.
getXLen())
7014 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Sign);
7016 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, XLenVT, Sign);
7018 assert(XLenVT == MVT::i32 &&
"Unexpected type");
7021 return DAG.
getNode(RISCVISD::SplitF64,
DL, {MVT::i32, MVT::i32}, Sign)
7051 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, CopiedSign);
7056#define OP_CASE(NODE) \
7058 return RISCVISD::NODE##_VL;
7059#define VP_CASE(NODE) \
7060 case ISD::VP_##NODE: \
7061 return RISCVISD::NODE##_VL;
7063 switch (
Op.getOpcode()) {
7142 case ISD::VP_CTLZ_ZERO_UNDEF:
7143 return RISCVISD::CTLZ_VL;
7145 case ISD::VP_CTTZ_ZERO_UNDEF:
7146 return RISCVISD::CTTZ_VL;
7149 return RISCVISD::VFMADD_VL;
7151 return RISCVISD::STRICT_VFMADD_VL;
7154 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7155 return RISCVISD::VMAND_VL;
7156 return RISCVISD::AND_VL;
7159 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7160 return RISCVISD::VMOR_VL;
7161 return RISCVISD::OR_VL;
7164 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7165 return RISCVISD::VMXOR_VL;
7166 return RISCVISD::XOR_VL;
7169 return RISCVISD::VZEXT_VL;
7171 return RISCVISD::VSEXT_VL;
7173 return RISCVISD::SETCC_VL;
7175 return RISCVISD::VMERGE_VL;
7176 case ISD::VP_SELECT:
7178 return RISCVISD::VMERGE_VL;
7180 return RISCVISD::SRA_VL;
7182 return RISCVISD::SRL_VL;
7184 return RISCVISD::FSQRT_VL;
7185 case ISD::VP_SIGN_EXTEND:
7186 return RISCVISD::VSEXT_VL;
7187 case ISD::VP_ZERO_EXTEND:
7188 return RISCVISD::VZEXT_VL;
7189 case ISD::VP_FP_TO_SINT:
7190 return RISCVISD::VFCVT_RTZ_X_F_VL;
7191 case ISD::VP_FP_TO_UINT:
7192 return RISCVISD::VFCVT_RTZ_XU_F_VL;
7195 case ISD::VP_FMINNUM:
7196 return RISCVISD::VFMIN_VL;
7199 case ISD::VP_FMAXNUM:
7200 return RISCVISD::VFMAX_VL;
7204 case ISD::VP_LLRINT:
7205 return RISCVISD::VFCVT_RM_X_F_VL;
7214 return (
Op.getValueType() == MVT::nxv32f16 &&
7217 Op.getValueType() == MVT::nxv32bf16;
7228 if (!
Op.getOperand(j).getValueType().isVector()) {
7229 LoOperands[j] =
Op.getOperand(j);
7230 HiOperands[j] =
Op.getOperand(j);
7233 std::tie(LoOperands[j], HiOperands[j]) =
7238 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
7240 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
7255 std::tie(LoOperands[j], HiOperands[j]) =
7259 if (!
Op.getOperand(j).getValueType().isVector()) {
7260 LoOperands[j] =
Op.getOperand(j);
7261 HiOperands[j] =
Op.getOperand(j);
7264 std::tie(LoOperands[j], HiOperands[j]) =
7269 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
7271 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
7281 auto [EVLLo, EVLHi] =
7282 DAG.
SplitEVL(
Op.getOperand(3),
Op.getOperand(1).getValueType(),
DL);
7286 {Op.getOperand(0), Lo, MaskLo, EVLLo},
Op->getFlags());
7288 {ResLo, Hi, MaskHi, EVLHi},
Op->getFlags());
7306 if (!
Op.getOperand(j).getValueType().isVector()) {
7307 LoOperands[j] =
Op.getOperand(j);
7308 HiOperands[j] =
Op.getOperand(j);
7311 std::tie(LoOperands[j], HiOperands[j]) =
7316 DAG.
getNode(
Op.getOpcode(),
DL, LoVTs, LoOperands,
Op->getFlags());
7319 DAG.
getNode(
Op.getOpcode(),
DL, HiVTs, HiOperands,
Op->getFlags());
7327RISCVTargetLowering::lowerXAndesBfHCvtBFloat16Load(
SDValue Op,
7329 assert(Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh() &&
7330 "Unexpected bfloat16 load lowering");
7334 EVT MemVT =
LD->getMemoryVT();
7339 LD->getMemOperand());
7347 DAG.
getNode(RISCVISD::NDS_FMV_BF16_X,
DL, MVT::bf16, OrSixteenOne);
7352RISCVTargetLowering::lowerXAndesBfHCvtBFloat16Store(
SDValue Op,
7354 assert(Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh() &&
7355 "Unexpected bfloat16 store lowering");
7362 ST->getChain(),
DL, FMV,
ST->getBasePtr(),
7364 ST->getMemOperand());
7369 switch (
Op.getOpcode()) {
7372 "Unimplemented RISCVTargetLowering::LowerOperation Case");
7378 return lowerGlobalAddress(
Op, DAG);
7380 return lowerBlockAddress(
Op, DAG);
7382 return lowerConstantPool(
Op, DAG);
7384 return lowerJumpTable(
Op, DAG);
7386 return lowerGlobalTLSAddress(
Op, DAG);
7390 return lowerConstantFP(
Op, DAG);
7392 return lowerSELECT(
Op, DAG);
7394 return lowerBRCOND(
Op, DAG);
7396 return lowerVASTART(
Op, DAG);
7398 return lowerFRAMEADDR(
Op, DAG);
7400 return lowerRETURNADDR(
Op, DAG);
7402 return lowerShiftLeftParts(
Op, DAG);
7404 return lowerShiftRightParts(
Op, DAG,
true);
7406 return lowerShiftRightParts(
Op, DAG,
false);
7409 if (
Op.getValueType().isFixedLengthVector()) {
7410 assert(Subtarget.hasStdExtZvkb());
7411 return lowerToScalableOp(
Op, DAG);
7413 assert(Subtarget.hasVendorXTHeadBb() &&
7414 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
7415 "Unexpected custom legalization");
7417 if (!isa<ConstantSDNode>(
Op.getOperand(1)))
7422 EVT VT =
Op.getValueType();
7426 if (Op0VT == MVT::i16 &&
7428 (VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
7430 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, NewOp0);
7432 if (VT == MVT::f32 && Op0VT == MVT::i32 && Subtarget.
is64Bit() &&
7435 return DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, NewOp0);
7437 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.
is64Bit() &&
7441 return DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64,
Lo,
Hi);
7453 "Unexpected types");
7485 return LowerINTRINSIC_WO_CHAIN(
Op, DAG);
7487 return LowerINTRINSIC_W_CHAIN(
Op, DAG);
7489 return LowerINTRINSIC_VOID(
Op, DAG);
7491 return LowerIS_FPCLASS(
Op, DAG);
7493 MVT VT =
Op.getSimpleValueType();
7495 assert(Subtarget.hasStdExtZvbb());
7496 return lowerToScalableOp(
Op, DAG);
7499 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected custom legalization");
7503 return DAG.
getNode(RISCVISD::BREV8,
DL, VT, BSwap);
7509 if (!
Op.getSimpleValueType().isVector())
7511 return lowerVectorTruncLike(
Op, DAG);
7514 if (
Op.getOperand(0).getValueType().isVector() &&
7515 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7516 return lowerVectorMaskExt(
Op, DAG, 1);
7517 if (
Op.getValueType().isScalableVector())
7519 return lowerToScalableOp(
Op, DAG);
7521 if (
Op.getOperand(0).getValueType().isVector() &&
7522 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7523 return lowerVectorMaskExt(
Op, DAG, -1);
7524 if (
Op.getValueType().isScalableVector())
7526 return lowerToScalableOp(
Op, DAG);
7528 return lowerSPLAT_VECTOR_PARTS(
Op, DAG);
7530 return lowerINSERT_VECTOR_ELT(
Op, DAG);
7532 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
7534 MVT VT =
Op.getSimpleValueType();
7542 MVT ContainerVT = VT;
7549 V = DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL, ContainerVT,
7550 DAG.
getUNDEF(ContainerVT), Scalar, VL);
7553 V = DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, ContainerVT,
7554 DAG.
getUNDEF(ContainerVT), Scalar, VL);
7562 MVT VT =
Op.getSimpleValueType();
7578 Flags.setExact(
true);
7581 }
else if (
Log2 > 3) {
7585 }
else if ((Val % 8) == 0) {
7592 Flags.setExact(
true);
7603 if (
Op.getValueType() == MVT::f16 && Subtarget.
is64Bit() &&
7604 Op.getOperand(1).getValueType() == MVT::i32) {
7621 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
7624 return lowerStrictFPExtendOrRoundLike(
Op, DAG);
7627 if (
Op.getValueType().isVector() &&
7628 ((
Op.getValueType().getScalarType() == MVT::f16 &&
7631 Op.getValueType().getScalarType() == MVT::bf16)) {
7647 Op1.getValueType().isVector() &&
7648 ((Op1.getValueType().getScalarType() == MVT::f16 &&
7651 Op1.getValueType().getScalarType() == MVT::bf16)) {
7657 Op1.getValueType().getVectorElementCount());
7660 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), WidenVec);
7670 MVT VT =
Op.getSimpleValueType();
7673 bool IsStrict =
Op->isStrictFPOpcode();
7674 SDValue Src =
Op.getOperand(0 + IsStrict);
7675 MVT SrcVT = Src.getSimpleValueType();
7686 "Unexpected vector element types");
7690 if (EltSize > (2 * SrcEltSize)) {
7702 Op.getOperand(0), Ext);
7706 assert(SrcEltVT == MVT::f16 &&
"Unexpected FP_TO_[US]INT lowering");
7711 auto [FExt, Chain] =
7713 return DAG.
getNode(
Op.getOpcode(),
DL,
Op->getVTList(), Chain, FExt);
7720 if (SrcEltSize > (2 * EltSize)) {
7723 assert(EltVT == MVT::f16 &&
"Unexpected [US]_TO_FP lowering");
7728 Op.getOperand(0), Src);
7743 Op.getOperand(0), Src);
7757 unsigned RVVOpc = 0;
7758 switch (
Op.getOpcode()) {
7762 RVVOpc = RISCVISD::VFCVT_RTZ_X_F_VL;
7765 RVVOpc = RISCVISD::VFCVT_RTZ_XU_F_VL;
7768 RVVOpc = RISCVISD::SINT_TO_FP_VL;
7771 RVVOpc = RISCVISD::UINT_TO_FP_VL;
7774 RVVOpc = RISCVISD::STRICT_VFCVT_RTZ_X_F_VL;
7777 RVVOpc = RISCVISD::STRICT_VFCVT_RTZ_XU_F_VL;
7780 RVVOpc = RISCVISD::STRICT_SINT_TO_FP_VL;
7783 RVVOpc = RISCVISD::STRICT_UINT_TO_FP_VL;
7790 "Expected same element count");
7797 Op.getOperand(0), Src, Mask, VL);
7801 Src = DAG.
getNode(RVVOpc,
DL, ContainerVT, Src, Mask, VL);
7816 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
7818 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Res);
7823 MVT VT =
Op.getSimpleValueType();
7829 ? DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32,
Op)
7843 bool IsStrict =
Op->isStrictFPOpcode();
7844 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7848 std::tie(Res, Chain) =
7849 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
7851 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Res);
7864 bool IsStrict =
Op->isStrictFPOpcode();
7865 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7868 ? DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, Op0)
7871 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
7872 CallOptions,
DL, Chain);
7891 if (
Op.getValueType().isVector())
7893 assert(
Op.getOperand(0).getValueType() == MVT::f16 &&
7894 "Unexpected custom legalisation");
7897 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), Ext);
7903 assert(
Op.getOperand(1).getValueType() == MVT::f16 &&
7904 "Unexpected custom legalisation");
7907 {
Op.getOperand(0),
Op.getOperand(1)});
7908 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
7909 {Ext.getValue(1), Ext.getValue(0)});
7916 return lowerVECREDUCE(
Op, DAG);
7920 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7921 return lowerVectorMaskVecReduction(
Op, DAG,
false);
7922 return lowerVECREDUCE(
Op, DAG);
7929 return lowerFPVECREDUCE(
Op, DAG);
7930 case ISD::VP_REDUCE_ADD:
7931 case ISD::VP_REDUCE_UMAX:
7932 case ISD::VP_REDUCE_SMAX:
7933 case ISD::VP_REDUCE_UMIN:
7934 case ISD::VP_REDUCE_SMIN:
7935 case ISD::VP_REDUCE_FADD:
7936 case ISD::VP_REDUCE_SEQ_FADD:
7937 case ISD::VP_REDUCE_FMIN:
7938 case ISD::VP_REDUCE_FMAX:
7939 case ISD::VP_REDUCE_FMINIMUM:
7940 case ISD::VP_REDUCE_FMAXIMUM:
7943 return lowerVPREDUCE(
Op, DAG);
7944 case ISD::VP_REDUCE_AND:
7945 case ISD::VP_REDUCE_OR:
7946 case ISD::VP_REDUCE_XOR:
7947 if (
Op.getOperand(1).getValueType().getVectorElementType() == MVT::i1)
7948 return lowerVectorMaskVecReduction(
Op, DAG,
true);
7949 return lowerVPREDUCE(
Op, DAG);
7950 case ISD::VP_CTTZ_ELTS:
7951 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
7952 return lowerVPCttzElements(
Op, DAG);
7956 DAG.
getUNDEF(ContainerVT), DAG, Subtarget);
7959 return lowerINSERT_SUBVECTOR(
Op, DAG);
7961 return lowerEXTRACT_SUBVECTOR(
Op, DAG);
7963 return lowerVECTOR_DEINTERLEAVE(
Op, DAG);
7965 return lowerVECTOR_INTERLEAVE(
Op, DAG);
7967 return lowerSTEP_VECTOR(
Op, DAG);
7969 return lowerVECTOR_REVERSE(
Op, DAG);
7971 return lowerVECTOR_SPLICE(
Op, DAG);
7973 MVT VT =
Op.getSimpleValueType();
7975 if (!Subtarget.
is64Bit() && EltVT == MVT::i64)
7980 MVT VT =
Op.getSimpleValueType();
7982 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
7983 EltVT == MVT::bf16) {
7986 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
7987 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
7997 if (EltVT == MVT::i1)
7998 return lowerVectorMaskSplat(
Op, DAG);
8007 MVT VT =
Op.getSimpleValueType();
8008 MVT ContainerVT = VT;
8026 Op->ops().take_front(HalfNumOps));
8028 Op->ops().drop_front(HalfNumOps));
8032 unsigned NumOpElts =
8033 Op.getOperand(0).getSimpleValueType().getVectorMinNumElements();
8045 auto *Load = cast<LoadSDNode>(
Op);
8046 EVT VT = Load->getValueType(0);
8047 if (VT == MVT::f64) {
8048 assert(Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
8049 !Subtarget.
is64Bit() &&
"Unexpected custom legalisation");
8053 SDValue BasePtr = Load->getBasePtr();
8054 SDValue Chain = Load->getChain();
8057 DAG.
getLoad(MVT::i32,
DL, Chain, BasePtr, Load->getPointerInfo(),
8058 Load->getBaseAlign(), Load->getMemOperand()->getFlags());
8061 MVT::i32,
DL, Chain, BasePtr, Load->getPointerInfo().getWithOffset(4),
8062 Load->getBaseAlign(), Load->getMemOperand()->getFlags());
8070 if (VT == MVT::bf16)
8071 return lowerXAndesBfHCvtBFloat16Load(
Op, DAG);
8079 unsigned NumElts = Sz / (NF * 8);
8080 int Log2LMUL =
Log2_64(NumElts) - 3;
8083 Flag.setNoUnsignedWrap(
true);
8085 SDValue BasePtr = Load->getBasePtr();
8093 for (
unsigned i = 0; i < NF; ++i) {
8098 Ret = DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VT, Ret, LoadVal,
8106 if (
auto V = expandUnalignedRVVLoad(
Op, DAG))
8108 if (
Op.getValueType().isFixedLengthVector())
8109 return lowerFixedLengthVectorLoadToRVV(
Op, DAG);
8113 auto *Store = cast<StoreSDNode>(
Op);
8114 SDValue StoredVal = Store->getValue();
8116 if (VT == MVT::f64) {
8117 assert(Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
8118 !Subtarget.
is64Bit() &&
"Unexpected custom legalisation");
8122 SDValue BasePtr = Store->getBasePtr();
8123 SDValue Chain = Store->getChain();
8125 DAG.
getVTList(MVT::i32, MVT::i32), StoredVal);
8128 Store->getPointerInfo(), Store->getBaseAlign(),
8129 Store->getMemOperand()->getFlags());
8132 Store->getPointerInfo().getWithOffset(4),
8133 Store->getBaseAlign(),
8134 Store->getMemOperand()->getFlags());
8137 if (VT == MVT::i64) {
8138 assert(Subtarget.hasStdExtZilsd() && !Subtarget.
is64Bit() &&
8139 "Unexpected custom legalisation");
8140 if (Store->isTruncatingStore())
8143 if (!Subtarget.enableUnalignedScalarMem() && Store->getAlign() < 8)
8154 {Store->getChain(), Lo, Hi, Store->getBasePtr()}, MVT::i64,
8155 Store->getMemOperand());
8158 if (VT == MVT::bf16)
8159 return lowerXAndesBfHCvtBFloat16Store(
Op, DAG);
8167 unsigned NumElts = Sz / (NF * 8);
8168 int Log2LMUL =
Log2_64(NumElts) - 3;
8171 Flag.setNoUnsignedWrap(
true);
8173 SDValue Chain = Store->getChain();
8174 SDValue BasePtr = Store->getBasePtr();
8181 for (
unsigned i = 0; i < NF; ++i) {
8183 DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL,
8186 Ret = DAG.
getStore(Chain,
DL, Extract, BasePtr,
8188 Store->getBaseAlign(),
8189 Store->getMemOperand()->getFlags());
8190 Chain = Ret.getValue(0);
8196 if (
auto V = expandUnalignedRVVStore(
Op, DAG))
8198 if (
Op.getOperand(1).getValueType().isFixedLengthVector())
8199 return lowerFixedLengthVectorStoreToRVV(
Op, DAG);
8204 return lowerMaskedLoad(
Op, DAG);
8205 case ISD::VP_LOAD_FF:
8206 return lowerLoadFF(
Op, DAG);
8209 return lowerMaskedStore(
Op, DAG);
8211 return lowerVectorCompress(
Op, DAG);
8220 EVT VT =
Op.getValueType();
8231 MVT OpVT =
Op.getOperand(0).getSimpleValueType();
8233 MVT VT =
Op.getSimpleValueType();
8238 "Unexpected CondCode");
8246 if (isa<ConstantSDNode>(
RHS)) {
8247 int64_t Imm = cast<ConstantSDNode>(
RHS)->getSExtValue();
8248 if (Imm != 0 && isInt<12>((
uint64_t)Imm + 1)) {
8277 return lowerToScalableOp(
Op, DAG);
8294 return lowerToScalableOp(
Op, DAG);
8298 if (
Op.getSimpleValueType().isFixedLengthVector())
8299 return lowerToScalableOp(
Op, DAG);
8301 assert(
Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.
is64Bit() &&
8302 "Unexpected custom legalisation");
8306 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
8334 return lowerToScalableOp(
Op, DAG);
8338 EVT VT =
Op->getValueType(0);
8353 return lowerABS(
Op, DAG);
8358 if (Subtarget.hasStdExtZvbb())
8359 return lowerToScalableOp(
Op, DAG);
8361 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8363 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
8367 return lowerToScalableOp(
Op, DAG);
8376 return lowerToScalableOp(
Op, DAG);
8379 return lowerVectorStrictFSetcc(
Op, DAG);
8389 case ISD::VP_GATHER:
8390 return lowerMaskedGather(
Op, DAG);
8392 case ISD::VP_SCATTER:
8393 return lowerMaskedScatter(
Op, DAG);
8395 return lowerGET_ROUNDING(
Op, DAG);
8397 return lowerSET_ROUNDING(
Op, DAG);
8399 return lowerGET_FPENV(
Op, DAG);
8401 return lowerSET_FPENV(
Op, DAG);
8403 return lowerRESET_FPENV(
Op, DAG);
8405 return lowerGET_FPMODE(
Op, DAG);
8407 return lowerSET_FPMODE(
Op, DAG);
8409 return lowerRESET_FPMODE(
Op, DAG);
8411 return lowerEH_DWARF_CFA(
Op, DAG);
8413 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
8414 return lowerVPMergeMask(
Op, DAG);
8416 case ISD::VP_SELECT:
8424 case ISD::VP_UADDSAT:
8425 case ISD::VP_USUBSAT:
8426 case ISD::VP_SADDSAT:
8427 case ISD::VP_SSUBSAT:
8429 case ISD::VP_LLRINT:
8430 return lowerVPOp(
Op, DAG);
8434 return lowerLogicVPOp(
Op, DAG);
8443 case ISD::VP_FMINNUM:
8444 case ISD::VP_FMAXNUM:
8445 case ISD::VP_FCOPYSIGN:
8452 return lowerVPOp(
Op, DAG);
8453 case ISD::VP_IS_FPCLASS:
8454 return LowerIS_FPCLASS(
Op, DAG);
8455 case ISD::VP_SIGN_EXTEND:
8456 case ISD::VP_ZERO_EXTEND:
8457 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
8458 return lowerVPExtMaskOp(
Op, DAG);
8459 return lowerVPOp(
Op, DAG);
8460 case ISD::VP_TRUNCATE:
8461 return lowerVectorTruncLike(
Op, DAG);
8462 case ISD::VP_FP_EXTEND:
8463 case ISD::VP_FP_ROUND:
8464 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
8465 case ISD::VP_SINT_TO_FP:
8466 case ISD::VP_UINT_TO_FP:
8467 if (
Op.getValueType().isVector() &&
8468 ((
Op.getValueType().getScalarType() == MVT::f16 &&
8471 Op.getValueType().getScalarType() == MVT::bf16)) {
8484 case ISD::VP_FP_TO_SINT:
8485 case ISD::VP_FP_TO_UINT:
8487 Op1.getValueType().isVector() &&
8488 ((Op1.getValueType().getScalarType() == MVT::f16 &&
8491 Op1.getValueType().getScalarType() == MVT::bf16)) {
8497 Op1.getValueType().getVectorElementCount());
8501 {WidenVec, Op.getOperand(1), Op.getOperand(2)});
8503 return lowerVPFPIntConvOp(
Op, DAG);
8507 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
8508 return lowerVPSetCCMaskOp(
Op, DAG);
8514 case ISD::VP_BITREVERSE:
8516 return lowerVPOp(
Op, DAG);
8518 case ISD::VP_CTLZ_ZERO_UNDEF:
8519 if (Subtarget.hasStdExtZvbb())
8520 return lowerVPOp(
Op, DAG);
8521 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8523 case ISD::VP_CTTZ_ZERO_UNDEF:
8524 if (Subtarget.hasStdExtZvbb())
8525 return lowerVPOp(
Op, DAG);
8526 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8528 return lowerVPOp(
Op, DAG);
8529 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
8530 return lowerVPStridedLoad(
Op, DAG);
8531 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
8532 return lowerVPStridedStore(
Op, DAG);
8534 case ISD::VP_FFLOOR:
8536 case ISD::VP_FNEARBYINT:
8537 case ISD::VP_FROUND:
8538 case ISD::VP_FROUNDEVEN:
8539 case ISD::VP_FROUNDTOZERO:
8543 case ISD::VP_FMAXIMUM:
8544 case ISD::VP_FMINIMUM:
8548 case ISD::EXPERIMENTAL_VP_SPLICE:
8549 return lowerVPSpliceExperimental(
Op, DAG);
8550 case ISD::EXPERIMENTAL_VP_REVERSE:
8551 return lowerVPReverseExperimental(
Op, DAG);
8552 case ISD::EXPERIMENTAL_VP_SPLAT:
8553 return lowerVPSplatExperimental(
Op, DAG);
8556 "llvm.clear_cache only needs custom lower on Linux targets");
8559 return emitFlushICache(DAG,
Op.getOperand(0),
Op.getOperand(1),
8560 Op.getOperand(2), Flags,
DL);
8563 return lowerDYNAMIC_STACKALLOC(
Op, DAG);
8565 return lowerINIT_TRAMPOLINE(
Op, DAG);
8567 return lowerADJUST_TRAMPOLINE(
Op, DAG);
8571 return lowerPARTIAL_REDUCE_MLA(
Op, DAG);
8578 MakeLibCallOptions CallOptions;
8579 std::pair<SDValue, SDValue> CallResult =
8580 makeLibCall(DAG, RTLIB::RISCV_FLUSH_ICACHE, MVT::isVoid,
8581 {Start,
End, Flags}, CallOptions,
DL, InChain);
8584 return CallResult.second;
8597 std::unique_ptr<MCCodeEmitter> CodeEmitter(
8604 const Value *TrmpAddr = cast<SrcValueSDNode>(
Op.getOperand(4))->getValue();
8625 const bool HasCFBranch =
8626 Subtarget.hasStdExtZicfilp() &&
8628 "cf-protection-branch");
8629 const unsigned StaticChainIdx = HasCFBranch ? 5 : 4;
8630 const unsigned StaticChainOffset = StaticChainIdx * 4;
8631 const unsigned FunctionAddressOffset = StaticChainOffset + 8;
8635 auto GetEncoding = [&](
const MCInst &MC) {
8638 CodeEmitter->encodeInstruction(MC, CB, Fixups, *STI);
8650 GetEncoding(
MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X7).addImm(0)),
8657 .addImm(FunctionAddressOffset)),
8663 .addImm(StaticChainOffset)),
8674 GetEncoding(
MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X0).addImm(0)),
8677 GetEncoding(
MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X28).addImm(0)),
8684 .addImm(FunctionAddressOffset - 4)),
8690 .addImm(StaticChainOffset - 4)),
8710 SDValue FunctionAddress =
Op.getOperand(2);
8714 struct OffsetValuePair {
8718 } OffsetValues[] = {
8719 {StaticChainOffset, StaticChain},
8720 {FunctionAddressOffset, FunctionAddress},
8722 for (
auto &OffsetValue : OffsetValues) {
8725 DAG.
getConstant(OffsetValue.Offset, dl, MVT::i64));
8726 OffsetValue.Addr =
Addr;
8732 assert(OutChains.
size() == StaticChainIdx + 2 &&
8733 "Size of OutChains mismatch");
8738 SDValue EndOfTrmp = OffsetValues[0].Addr;
8752 return Op.getOperand(0);
8761 MVT VT =
Op.getSimpleValueType();
8767 MVT ArgVT =
A.getSimpleValueType();
8768 assert(ArgVT ==
B.getSimpleValueType() &&
8778 MVT ContainerVT = VT;
8787 switch (
Op.getOpcode()) {
8789 Opc = RISCVISD::VQDOT_VL;
8792 Opc = RISCVISD::VQDOTU_VL;
8795 Opc = RISCVISD::VQDOTSU_VL;
8821 N->getOffset(), Flags);
8850template <
class NodeTy>
8852 bool IsLocal,
bool IsExternWeak)
const {
8862 if (IsLocal && !Subtarget.allowTaggedGlobals())
8892 return DAG.
getNode(RISCVISD::ADD_LO,
DL, Ty, MNHi, AddrLo);
8932 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
8941 return getAddr(
N, DAG);
8948 return getAddr(
N, DAG);
8955 return getAddr(
N, DAG);
8960 bool UseGOT)
const {
9001 DAG.
getNode(RISCVISD::ADD_TPREL,
DL, Ty, MNHi, TPReg, AddrAdd);
9002 return DAG.
getNode(RISCVISD::ADD_LO,
DL, Ty, MNAdd, AddrLo);
9021 Args.emplace_back(Load, CallTy);
9054 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
9068 Addr = getStaticTLSAddr(
N, DAG,
false);
9071 Addr = getStaticTLSAddr(
N, DAG,
true);
9076 : getDynamicTLSAddr(
N, DAG);
9093 if (
LHS == LHS2 &&
RHS == RHS2) {
9098 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
9106 return std::nullopt;
9114 MVT VT =
N->getSimpleValueType(0);
9144 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV)) {
9147 if (~TrueVal == FalseVal) {
9187 if (Subtarget.hasShortForwardBranchOpt())
9190 unsigned SelOpNo = 0;
9200 unsigned ConstSelOpNo = 1;
9201 unsigned OtherSelOpNo = 2;
9202 if (!isa<ConstantSDNode>(Sel->
getOperand(ConstSelOpNo))) {
9207 ConstantSDNode *ConstSelOpNode = dyn_cast<ConstantSDNode>(ConstSelOp);
9208 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
9212 ConstantSDNode *ConstBinOpNode = dyn_cast<ConstantSDNode>(ConstBinOp);
9213 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
9219 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
9221 std::swap(NewConstOps[0], NewConstOps[1]);
9233 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
9235 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
9238 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
9239 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
9248 MVT VT =
Op.getSimpleValueType();
9262 if ((Subtarget.hasStdExtZicond() || Subtarget.hasVendorXVentanaCondOps()) &&
9266 return DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV);
9269 return DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV);
9273 auto getNotOperand = [](
const SDValue &
Op) -> std::optional<const SDValue> {
9279 return std::nullopt;
9285 auto NotOperand = (TrueV.
getOperand(0) == FalseV)
9290 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, *NotOperand, CondV);
9296 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV));
9303 auto NotOperand = (FalseV.
getOperand(0) == TrueV)
9308 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, *NotOperand, CondV);
9314 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV));
9323 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV)) {
9335 int64_t TrueImm =
TrueVal.getSExtValue();
9336 int64_t FalseImm =
FalseVal.getSExtValue();
9339 if (isInt<12>(TrueImm) && isInt<12>(FalseImm) &&
9340 isInt<12>(TrueImm - FalseImm)) {
9355 if ((TrueVal - FalseVal).isPowerOf2() &&
FalseVal.isSignedIntN(12)) {
9360 if ((FalseVal - TrueVal).isPowerOf2() &&
TrueVal.isSignedIntN(12)) {
9369 Delta, Subtarget.
getXLen(), Subtarget,
true);
9371 if (Addend.isSignedIntN(12))
9374 Addend, Subtarget.
getXLen(), Subtarget,
true);
9375 return AddendCost + DeltaCost;
9377 bool IsCZERO_NEZ =
getCost(FalseVal - TrueVal, TrueVal) <=
9378 getCost(TrueVal - FalseVal, FalseVal);
9380 IsCZERO_NEZ ? FalseVal - TrueVal : TrueVal - FalseVal,
DL, VT);
9382 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9383 DL, VT, LHSVal, CondV);
9389 if (isa<ConstantSDNode>(TrueV) != isa<ConstantSDNode>(FalseV)) {
9390 bool IsCZERO_NEZ = isa<ConstantSDNode>(TrueV);
9391 SDValue ConstVal = IsCZERO_NEZ ? TrueV : FalseV;
9392 SDValue RegV = IsCZERO_NEZ ? FalseV : TrueV;
9393 int64_t RawConstVal = cast<ConstantSDNode>(ConstVal)->getSExtValue();
9395 if (RawConstVal == -0x800) {
9398 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9399 DL, VT, XorOp, CondV);
9404 if (isInt<12>(RawConstVal)) {
9407 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9408 DL, VT, SubOp, CondV);
9418 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV),
9419 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV),
9426 if (
Op.hasOneUse()) {
9427 unsigned UseOpc =
Op->user_begin()->getOpcode();
9436 return lowerSELECT(NewSel, DAG);
9465 SDValue Ops[] = {CondV,
Zero, SetNE, TrueV, FalseV};
9467 return DAG.
getNode(RISCVISD::SELECT_CC,
DL, VT, Ops);
9486 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV) &&
9490 if (TrueVal - 1 == FalseVal)
9492 if (TrueVal + 1 == FalseVal)
9499 RHS == TrueV && LHS == FalseV) {
9516 if (isa<ConstantSDNode>(TrueV) && !isa<ConstantSDNode>(FalseV)) {
9524 return DAG.
getNode(RISCVISD::SELECT_CC,
DL, VT, Ops);
9541 return DAG.
getNode(RISCVISD::BR_CC,
DL,
Op.getValueType(),
Op.getOperand(0),
9542 LHS, RHS, TargetCC,
Op.getOperand(2));
9545 return DAG.
getNode(RISCVISD::BR_CC,
DL,
Op.getValueType(),
Op.getOperand(0),
9560 const Value *SV = cast<SrcValueSDNode>(
Op.getOperand(2))->getValue();
9572 int XLenInBytes = Subtarget.
getXLen() / 8;
9574 EVT VT =
Op.getValueType();
9577 unsigned Depth =
Op.getConstantOperandVal(0);
9579 int Offset = -(XLenInBytes * 2);
9596 int XLenInBytes = Subtarget.
getXLen() / 8;
9598 EVT VT =
Op.getValueType();
9600 unsigned Depth =
Op.getConstantOperandVal(0);
9602 int Off = -XLenInBytes;
9603 SDValue FrameAddr = lowerFRAMEADDR(
Op, DAG);
9622 EVT VT =
Lo.getValueType();
9661 EVT VT =
Lo.getValueType();
9712 MVT VT =
Op.getSimpleValueType();
9717 return DAG.
getNode(RISCVISD::VMSET_VL,
DL, VT, VL);
9721 return DAG.
getNode(RISCVISD::VMCLR_VL,
DL, VT, VL);
9738 MVT VecVT =
Op.getSimpleValueType();
9740 "Unexpected SPLAT_VECTOR_PARTS lowering");
9746 MVT ContainerVT = VecVT;
9766 int64_t ExtTrueVal)
const {
9768 MVT VecVT =
Op.getSimpleValueType();
9771 assert(Src.getValueType().isVector() &&
9772 Src.getValueType().getVectorElementType() == MVT::i1);
9798 if (
Xor.getOpcode() == RISCVISD::VMXOR_VL) {
9804 CC =
Xor.getOperand(0);
9810 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9811 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
9812 SplatTrueVal = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9813 DAG.
getUNDEF(ContainerVT), SplatTrueVal, VL);
9815 DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, CC, SplatTrueVal,
9816 SplatZero, DAG.
getUNDEF(ContainerVT), VL);
9826 bool IsVPTrunc =
Op.getOpcode() == ISD::VP_TRUNCATE;
9828 EVT MaskVT =
Op.getValueType();
9831 "Unexpected type for vector mask lowering");
9833 MVT VecVT = Src.getSimpleValueType();
9837 VL =
Op.getOperand(2);
9840 MVT ContainerVT = VecVT;
9846 MVT MaskContainerVT =
9853 std::tie(Mask, VL) =
9860 SplatOne = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9861 DAG.
getUNDEF(ContainerVT), SplatOne, VL);
9862 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9863 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
9866 SDValue Trunc = DAG.
getNode(RISCVISD::AND_VL,
DL, ContainerVT, Src, SplatOne,
9867 DAG.
getUNDEF(ContainerVT), Mask, VL);
9868 Trunc = DAG.
getNode(RISCVISD::SETCC_VL,
DL, MaskContainerVT,
9870 DAG.
getUNDEF(MaskContainerVT), Mask, VL});
9878 unsigned Opc =
Op.getOpcode();
9879 bool IsVPTrunc =
Opc == ISD::VP_TRUNCATE;
9882 MVT VT =
Op.getSimpleValueType();
9884 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
9888 return lowerVectorMaskTruncLike(
Op, DAG);
9896 MVT SrcVT = Src.getSimpleValueType();
9901 "Unexpected vector truncate lowering");
9903 MVT ContainerVT = SrcVT;
9907 VL =
Op.getOperand(2);
9920 std::tie(Mask, VL) =
9926 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL_SSAT;
9928 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL_USAT;
9930 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL;
9936 }
while (SrcEltVT != DstEltVT);
9945RISCVTargetLowering::lowerStrictFPExtendOrRoundLike(
SDValue Op,
9950 MVT VT =
Op.getSimpleValueType();
9951 MVT SrcVT = Src.getSimpleValueType();
9952 MVT ContainerVT = VT;
9971 ? RISCVISD::STRICT_FP_EXTEND_VL
9972 : RISCVISD::STRICT_VFNCVT_ROD_VL;
9975 Chain, Src, Mask, VL);
9976 Chain = Src.getValue(1);
9980 ? RISCVISD::STRICT_FP_EXTEND_VL
9981 : RISCVISD::STRICT_FP_ROUND_VL;
9983 Chain, Src, Mask, VL);
9994RISCVTargetLowering::lowerVectorFPExtendOrRoundLike(
SDValue Op,
9997 Op.getOpcode() == ISD::VP_FP_ROUND ||
Op.getOpcode() == ISD::VP_FP_EXTEND;
10004 MVT VT =
Op.getSimpleValueType();
10006 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
10009 MVT SrcVT = Src.getSimpleValueType();
10011 bool IsDirectExtend =
10019 bool IsDirectConv = IsDirectExtend || IsDirectTrunc;
10026 MVT ContainerVT = VT;
10029 Mask =
Op.getOperand(1);
10030 VL =
Op.getOperand(2);
10044 std::tie(Mask, VL) =
10047 unsigned ConvOpc = IsExtend ? RISCVISD::FP_EXTEND_VL : RISCVISD::FP_ROUND_VL;
10049 if (IsDirectConv) {
10050 Src = DAG.
getNode(ConvOpc,
DL, ContainerVT, Src, Mask, VL);
10056 unsigned InterConvOpc =
10057 IsExtend ? RISCVISD::FP_EXTEND_VL : RISCVISD::VFNCVT_ROD_VL;
10061 DAG.
getNode(InterConvOpc,
DL, InterVT, Src, Mask, VL);
10063 DAG.
getNode(ConvOpc,
DL, ContainerVT, IntermediateConv, Mask, VL);
10074static std::optional<MVT>
10080 const unsigned MinVLMAX = VectorBitsMin / EltSize;
10082 if (MaxIdx < MinVLMAX)
10084 else if (MaxIdx < MinVLMAX * 2)
10087 else if (MaxIdx < MinVLMAX * 4)
10092 return std::nullopt;
10097 auto *IdxC = dyn_cast<ConstantSDNode>(
Idx);
10100 return isUInt<5>(IdxC->getZExtValue());
10112 MVT VecVT =
Op.getSimpleValueType();
10129 ValVT == MVT::bf16) {
10134 DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Val),
Idx);
10138 MVT ContainerVT = VecVT;
10148 std::optional<unsigned> AlignedIdx;
10149 if (
auto *IdxC = dyn_cast<ConstantSDNode>(
Idx)) {
10150 const unsigned OrigIdx = IdxC->getZExtValue();
10153 DL, DAG, Subtarget)) {
10154 ContainerVT = *ShrunkVT;
10165 unsigned RemIdx = OrigIdx % ElemsPerVReg;
10166 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
10169 ContainerVT = M1VT;
10181 if (!IsLegalInsert && isa<ConstantSDNode>(Val)) {
10182 const auto *CVal = cast<ConstantSDNode>(Val);
10183 if (isInt<32>(CVal->getSExtValue())) {
10184 IsLegalInsert =
true;
10193 if (IsLegalInsert) {
10195 VecVT.
isFloatingPoint() ? RISCVISD::VFMV_S_F_VL : RISCVISD::VMV_S_X_VL;
10199 Vec = DAG.
getNode(
Opc,
DL, ContainerVT, Vec, Val, VL);
10209 if (Subtarget.hasVendorXRivosVisni() && VecVT.
isInteger() &&
10214 Vec = DAG.
getNode(RISCVISD::RI_VINSERT_VL,
DL, ContainerVT, Vec, Val,
Idx,
10230 std::tie(ValLo, ValHi) = DAG.
SplitScalar(Val,
DL, MVT::i32, MVT::i32);
10231 MVT I32ContainerVT =
10241 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10242 Vec, Vec, ValLo, I32Mask, InsertI64VL);
10246 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10247 Tail, ValInVec, ValHi, I32Mask, InsertI64VL);
10249 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
10260 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10262 DAG.
getUNDEF(I32ContainerVT), ValLo,
10263 I32Mask, InsertI64VL);
10264 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10265 DAG.
getUNDEF(I32ContainerVT), ValInVec, ValHi,
10266 I32Mask, InsertI64VL);
10268 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
10281 Idx, Mask, InsertVL, Policy);
10299 EVT EltVT =
Op.getValueType();
10306 MVT ContainerVT = VecVT;
10313 DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Vec, Mask, VL);
10320 if (NumElts >= 8) {
10322 unsigned WidenVecLen;
10325 unsigned MaxEEW = Subtarget.
getELen();
10330 "the number of elements should be power of 2");
10334 ExtractBitIdx =
Idx;
10336 WideEltVT = LargestEltVT;
10339 ExtractElementIdx = DAG.
getNode(
10350 Vec, ExtractElementIdx);
10366 EltVT == MVT::bf16) {
10372 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, EltVT, IntExtract);
10376 MVT ContainerVT = VecVT;
10387 if (
auto *IdxC = dyn_cast<ConstantSDNode>(
Idx);
10388 IdxC && VLen && VecVT.
getSizeInBits().getKnownMinValue() > *VLen) {
10390 unsigned OrigIdx = IdxC->getZExtValue();
10393 unsigned RemIdx = OrigIdx % ElemsPerVReg;
10394 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
10395 unsigned ExtractIdx =
10399 ContainerVT = M1VT;
10404 std::optional<uint64_t> MaxIdx;
10407 if (
auto *IdxC = dyn_cast<ConstantSDNode>(
Idx))
10408 MaxIdx = IdxC->getZExtValue();
10410 if (
auto SmallerVT =
10412 ContainerVT = *SmallerVT;
10419 if (Subtarget.hasVendorXRivosVisni() && EltVT.
isInteger() &&
10466 "Unexpected opcode");
10473 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
10478 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
10479 if (!
II || !
II->hasScalarOperand())
10482 unsigned SplatOp =
II->ScalarOperand + 1 + HasChain;
10495 if (OpVT.
bitsLT(XLenVT)) {
10502 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
10512 assert(
II->ScalarOperand > 0 &&
"Unexpected splat operand!");
10513 MVT VT =
Op.getOperand(SplatOp - 1).getSimpleValueType();
10516 assert(XLenVT == MVT::i32 && OpVT == MVT::i64 &&
10527 case Intrinsic::riscv_vslide1up:
10528 case Intrinsic::riscv_vslide1down:
10529 case Intrinsic::riscv_vslide1up_mask:
10530 case Intrinsic::riscv_vslide1down_mask: {
10533 bool IsMasked = NumOps == 7;
10539 std::tie(ScalarLo, ScalarHi) =
10547 if (isa<ConstantSDNode>(AVL)) {
10548 const auto [MinVLMAX, MaxVLMAX] =
10552 if (AVLInt <= MinVLMAX) {
10554 }
else if (AVLInt >= 2 * MaxVLMAX) {
10588 if (IntNo == Intrinsic::riscv_vslide1up ||
10589 IntNo == Intrinsic::riscv_vslide1up_mask) {
10590 Vec = DAG.
getNode(RISCVISD::VSLIDE1UP_VL,
DL, I32VT, Passthru, Vec,
10591 ScalarHi, I32Mask, I32VL);
10592 Vec = DAG.
getNode(RISCVISD::VSLIDE1UP_VL,
DL, I32VT, Passthru, Vec,
10593 ScalarLo, I32Mask, I32VL);
10595 Vec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32VT, Passthru, Vec,
10596 ScalarLo, I32Mask, I32VL);
10597 Vec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32VT, Passthru, Vec,
10598 ScalarHi, I32Mask, I32VL);
10616 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, Mask, Vec, MaskedOff,
10620 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, Mask, Vec, MaskedOff,
10647 const unsigned ElementWidth = 8;
10652 [[maybe_unused]]
unsigned MinVF =
10655 [[maybe_unused]]
unsigned VF =
N->getConstantOperandVal(2);
10659 bool Fractional = VF < LMul1VF;
10660 unsigned LMulVal = Fractional ? LMul1VF / VF : VF / LMul1VF;
10681 MVT ContainerVT = OpVT;
10689 SDValue Res = DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Op0, Mask, VL);
10697 return DAG.
getSelect(
DL, XLenVT, Setcc, VL, Res);
10708 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
10712 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
10713 if (!
II || !
II->hasScalarOperand())
10716 unsigned SplatOp =
II->ScalarOperand + 1;
10729 if (OpVT.
bitsLT(XLenVT)) {
10732 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
10743 EVT ValType = V.getValueType();
10744 if (ValType.isVector() && ValType.isFloatingPoint()) {
10747 ValType.getVectorElementCount());
10750 if (ValType.isFixedLengthVector()) {
10752 DAG, V.getSimpleValueType(), Subtarget);
10768 unsigned IntNo =
Op.getConstantOperandVal(0);
10775 case Intrinsic::riscv_tuple_insert: {
10780 return DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL,
Op.getValueType(), Vec,
10783 case Intrinsic::riscv_tuple_extract: {
10787 return DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL,
Op.getValueType(), Vec,
10790 case Intrinsic::thread_pointer: {
10794 case Intrinsic::riscv_orc_b:
10795 case Intrinsic::riscv_brev8:
10796 case Intrinsic::riscv_sha256sig0:
10797 case Intrinsic::riscv_sha256sig1:
10798 case Intrinsic::riscv_sha256sum0:
10799 case Intrinsic::riscv_sha256sum1:
10800 case Intrinsic::riscv_sm3p0:
10801 case Intrinsic::riscv_sm3p1: {
10804 case Intrinsic::riscv_orc_b:
Opc = RISCVISD::ORC_B;
break;
10805 case Intrinsic::riscv_brev8:
Opc = RISCVISD::BREV8;
break;
10806 case Intrinsic::riscv_sha256sig0:
Opc = RISCVISD::SHA256SIG0;
break;
10807 case Intrinsic::riscv_sha256sig1:
Opc = RISCVISD::SHA256SIG1;
break;
10808 case Intrinsic::riscv_sha256sum0:
Opc = RISCVISD::SHA256SUM0;
break;
10809 case Intrinsic::riscv_sha256sum1:
Opc = RISCVISD::SHA256SUM1;
break;
10810 case Intrinsic::riscv_sm3p0:
Opc = RISCVISD::SM3P0;
break;
10811 case Intrinsic::riscv_sm3p1:
Opc = RISCVISD::SM3P1;
break;
10816 case Intrinsic::riscv_sm4ks:
10817 case Intrinsic::riscv_sm4ed: {
10819 IntNo == Intrinsic::riscv_sm4ks ? RISCVISD::SM4KS : RISCVISD::SM4ED;
10824 case Intrinsic::riscv_zip:
10825 case Intrinsic::riscv_unzip: {
10827 IntNo == Intrinsic::riscv_zip ? RISCVISD::ZIP : RISCVISD::UNZIP;
10830 case Intrinsic::riscv_mopr:
10831 return DAG.
getNode(RISCVISD::MOP_R,
DL, XLenVT,
Op.getOperand(1),
10834 case Intrinsic::riscv_moprr: {
10835 return DAG.
getNode(RISCVISD::MOP_RR,
DL, XLenVT,
Op.getOperand(1),
10836 Op.getOperand(2),
Op.getOperand(3));
10838 case Intrinsic::riscv_clmul:
10839 return DAG.
getNode(RISCVISD::CLMUL,
DL, XLenVT,
Op.getOperand(1),
10841 case Intrinsic::riscv_clmulh:
10842 case Intrinsic::riscv_clmulr: {
10844 IntNo == Intrinsic::riscv_clmulh ? RISCVISD::CLMULH : RISCVISD::CLMULR;
10847 case Intrinsic::experimental_get_vector_length:
10849 case Intrinsic::experimental_cttz_elts:
10851 case Intrinsic::riscv_vmv_x_s: {
10855 case Intrinsic::riscv_vfmv_f_s:
10857 case Intrinsic::riscv_vmv_v_x:
10859 Op.getOperand(3),
Op.getSimpleValueType(),
DL, DAG,
10861 case Intrinsic::riscv_vfmv_v_f:
10862 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL,
Op.getValueType(),
10863 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
10864 case Intrinsic::riscv_vmv_s_x: {
10867 if (Scalar.getValueType().bitsLE(XLenVT)) {
10869 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL,
Op.getValueType(),
10870 Op.getOperand(1), Scalar,
Op.getOperand(3));
10873 assert(Scalar.getValueType() == MVT::i64 &&
"Unexpected scalar VT!");
10890 MVT VT =
Op.getSimpleValueType();
10895 if (
Op.getOperand(1).isUndef())
10896 return SplattedVal;
10905 DAG.
getNode(RISCVISD::SETCC_VL,
DL, MaskVT,
10908 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, SelectCond, SplattedVal,
10911 case Intrinsic::riscv_vfmv_s_f:
10912 return DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL,
Op.getSimpleValueType(),
10913 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
10915 case Intrinsic::riscv_vaesdf_vv:
10916 case Intrinsic::riscv_vaesdf_vs:
10917 case Intrinsic::riscv_vaesdm_vv:
10918 case Intrinsic::riscv_vaesdm_vs:
10919 case Intrinsic::riscv_vaesef_vv:
10920 case Intrinsic::riscv_vaesef_vs:
10921 case Intrinsic::riscv_vaesem_vv:
10922 case Intrinsic::riscv_vaesem_vs:
10923 case Intrinsic::riscv_vaeskf1:
10924 case Intrinsic::riscv_vaeskf2:
10925 case Intrinsic::riscv_vaesz_vs:
10926 case Intrinsic::riscv_vsm4k:
10927 case Intrinsic::riscv_vsm4r_vv:
10928 case Intrinsic::riscv_vsm4r_vs: {
10929 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
10930 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
10931 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
10936 case Intrinsic::riscv_vsm3c:
10937 case Intrinsic::riscv_vsm3me: {
10938 if (!
isValidEGW(8,
Op.getSimpleValueType(), Subtarget) ||
10939 !
isValidEGW(8,
Op->getOperand(1).getSimpleValueType(), Subtarget))
10944 case Intrinsic::riscv_vsha2ch:
10945 case Intrinsic::riscv_vsha2cl:
10946 case Intrinsic::riscv_vsha2ms: {
10947 if (
Op->getSimpleValueType(0).getScalarSizeInBits() == 64 &&
10948 !Subtarget.hasStdExtZvknhb())
10950 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
10951 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
10952 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
10956 case Intrinsic::riscv_sf_vc_v_x:
10957 case Intrinsic::riscv_sf_vc_v_i:
10958 case Intrinsic::riscv_sf_vc_v_xv:
10959 case Intrinsic::riscv_sf_vc_v_iv:
10960 case Intrinsic::riscv_sf_vc_v_vv:
10961 case Intrinsic::riscv_sf_vc_v_fv:
10962 case Intrinsic::riscv_sf_vc_v_xvv:
10963 case Intrinsic::riscv_sf_vc_v_ivv:
10964 case Intrinsic::riscv_sf_vc_v_vvv:
10965 case Intrinsic::riscv_sf_vc_v_fvv:
10966 case Intrinsic::riscv_sf_vc_v_xvw:
10967 case Intrinsic::riscv_sf_vc_v_ivw:
10968 case Intrinsic::riscv_sf_vc_v_vvw:
10969 case Intrinsic::riscv_sf_vc_v_fvw: {
10970 MVT VT =
Op.getSimpleValueType();
11007 MVT VT =
Op.getSimpleValueType();
11011 if (VT.isFloatingPoint()) {
11016 if (VT.isFixedLengthVector())
11026 if (VT.isFixedLengthVector())
11028 if (VT.isFloatingPoint())
11051 case Intrinsic::riscv_seg2_load_mask:
11052 case Intrinsic::riscv_seg3_load_mask:
11053 case Intrinsic::riscv_seg4_load_mask:
11054 case Intrinsic::riscv_seg5_load_mask:
11055 case Intrinsic::riscv_seg6_load_mask:
11056 case Intrinsic::riscv_seg7_load_mask:
11057 case Intrinsic::riscv_seg8_load_mask:
11060 case Intrinsic::riscv_sseg2_load_mask:
11061 case Intrinsic::riscv_sseg3_load_mask:
11062 case Intrinsic::riscv_sseg4_load_mask:
11063 case Intrinsic::riscv_sseg5_load_mask:
11064 case Intrinsic::riscv_sseg6_load_mask:
11065 case Intrinsic::riscv_sseg7_load_mask:
11066 case Intrinsic::riscv_sseg8_load_mask:
11074 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
11075 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
11076 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
11077 Intrinsic::riscv_vlseg8_mask};
11079 Intrinsic::riscv_vlsseg2_mask, Intrinsic::riscv_vlsseg3_mask,
11080 Intrinsic::riscv_vlsseg4_mask, Intrinsic::riscv_vlsseg5_mask,
11081 Intrinsic::riscv_vlsseg6_mask, Intrinsic::riscv_vlsseg7_mask,
11082 Intrinsic::riscv_vlsseg8_mask};
11085 unsigned NF =
Op->getNumValues() - 1;
11086 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
11088 MVT VT =
Op->getSimpleValueType(0);
11098 MVT MaskVT = Mask.getSimpleValueType();
11099 MVT MaskContainerVT =
11104 IsStrided ? VlssegInts[NF - 2] : VlsegInts[NF - 2],
DL, XLenVT);
11105 auto *Load = cast<MemIntrinsicSDNode>(
Op);
11124 Load->getMemoryVT(), Load->getMemOperand());
11126 for (
unsigned int RetIdx = 0; RetIdx < NF; RetIdx++) {
11128 Result.getValue(0),
11132 Results.push_back(Result.getValue(1));
11138 unsigned IntNo =
Op.getConstantOperandVal(1);
11142 case Intrinsic::riscv_seg2_load_mask:
11143 case Intrinsic::riscv_seg3_load_mask:
11144 case Intrinsic::riscv_seg4_load_mask:
11145 case Intrinsic::riscv_seg5_load_mask:
11146 case Intrinsic::riscv_seg6_load_mask:
11147 case Intrinsic::riscv_seg7_load_mask:
11148 case Intrinsic::riscv_seg8_load_mask:
11149 case Intrinsic::riscv_sseg2_load_mask:
11150 case Intrinsic::riscv_sseg3_load_mask:
11151 case Intrinsic::riscv_sseg4_load_mask:
11152 case Intrinsic::riscv_sseg5_load_mask:
11153 case Intrinsic::riscv_sseg6_load_mask:
11154 case Intrinsic::riscv_sseg7_load_mask:
11155 case Intrinsic::riscv_sseg8_load_mask:
11158 case Intrinsic::riscv_sf_vc_v_x_se:
11160 case Intrinsic::riscv_sf_vc_v_i_se:
11162 case Intrinsic::riscv_sf_vc_v_xv_se:
11164 case Intrinsic::riscv_sf_vc_v_iv_se:
11166 case Intrinsic::riscv_sf_vc_v_vv_se:
11168 case Intrinsic::riscv_sf_vc_v_fv_se:
11170 case Intrinsic::riscv_sf_vc_v_xvv_se:
11172 case Intrinsic::riscv_sf_vc_v_ivv_se:
11174 case Intrinsic::riscv_sf_vc_v_vvv_se:
11176 case Intrinsic::riscv_sf_vc_v_fvv_se:
11178 case Intrinsic::riscv_sf_vc_v_xvw_se:
11180 case Intrinsic::riscv_sf_vc_v_ivw_se:
11182 case Intrinsic::riscv_sf_vc_v_vvw_se:
11184 case Intrinsic::riscv_sf_vc_v_fvw_se:
11197 case Intrinsic::riscv_seg2_store_mask:
11198 case Intrinsic::riscv_seg3_store_mask:
11199 case Intrinsic::riscv_seg4_store_mask:
11200 case Intrinsic::riscv_seg5_store_mask:
11201 case Intrinsic::riscv_seg6_store_mask:
11202 case Intrinsic::riscv_seg7_store_mask:
11203 case Intrinsic::riscv_seg8_store_mask:
11206 case Intrinsic::riscv_sseg2_store_mask:
11207 case Intrinsic::riscv_sseg3_store_mask:
11208 case Intrinsic::riscv_sseg4_store_mask:
11209 case Intrinsic::riscv_sseg5_store_mask:
11210 case Intrinsic::riscv_sseg6_store_mask:
11211 case Intrinsic::riscv_sseg7_store_mask:
11212 case Intrinsic::riscv_sseg8_store_mask:
11221 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
11222 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
11223 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
11224 Intrinsic::riscv_vsseg8_mask};
11226 Intrinsic::riscv_vssseg2_mask, Intrinsic::riscv_vssseg3_mask,
11227 Intrinsic::riscv_vssseg4_mask, Intrinsic::riscv_vssseg5_mask,
11228 Intrinsic::riscv_vssseg6_mask, Intrinsic::riscv_vssseg7_mask,
11229 Intrinsic::riscv_vssseg8_mask};
11234 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
11236 MVT VT =
Op->getOperand(2).getSimpleValueType();
11244 MVT MaskVT = Mask.getSimpleValueType();
11245 MVT MaskContainerVT =
11250 IsStrided ? VsssegInts[NF - 2] : VssegInts[NF - 2],
DL, XLenVT);
11253 auto *FixedIntrinsic = cast<MemIntrinsicSDNode>(
Op);
11256 for (
unsigned i = 0; i < NF; i++)
11258 RISCVISD::TUPLE_INSERT,
DL, VecTupTy, StoredVal,
11264 FixedIntrinsic->getChain(),
11278 FixedIntrinsic->getMemoryVT(), FixedIntrinsic->getMemOperand());
11283 unsigned IntNo =
Op.getConstantOperandVal(1);
11287 case Intrinsic::riscv_seg2_store_mask:
11288 case Intrinsic::riscv_seg3_store_mask:
11289 case Intrinsic::riscv_seg4_store_mask:
11290 case Intrinsic::riscv_seg5_store_mask:
11291 case Intrinsic::riscv_seg6_store_mask:
11292 case Intrinsic::riscv_seg7_store_mask:
11293 case Intrinsic::riscv_seg8_store_mask:
11294 case Intrinsic::riscv_sseg2_store_mask:
11295 case Intrinsic::riscv_sseg3_store_mask:
11296 case Intrinsic::riscv_sseg4_store_mask:
11297 case Intrinsic::riscv_sseg5_store_mask:
11298 case Intrinsic::riscv_sseg6_store_mask:
11299 case Intrinsic::riscv_sseg7_store_mask:
11300 case Intrinsic::riscv_sseg8_store_mask:
11303 case Intrinsic::riscv_sf_vc_xv_se:
11305 case Intrinsic::riscv_sf_vc_iv_se:
11307 case Intrinsic::riscv_sf_vc_vv_se:
11309 case Intrinsic::riscv_sf_vc_fv_se:
11311 case Intrinsic::riscv_sf_vc_xvv_se:
11313 case Intrinsic::riscv_sf_vc_ivv_se:
11315 case Intrinsic::riscv_sf_vc_vvv_se:
11317 case Intrinsic::riscv_sf_vc_fvv_se:
11319 case Intrinsic::riscv_sf_vc_xvw_se:
11321 case Intrinsic::riscv_sf_vc_ivw_se:
11323 case Intrinsic::riscv_sf_vc_vvw_se:
11325 case Intrinsic::riscv_sf_vc_fvw_se:
11333 switch (ISDOpcode) {
11336 case ISD::VP_REDUCE_ADD:
11338 return RISCVISD::VECREDUCE_ADD_VL;
11339 case ISD::VP_REDUCE_UMAX:
11341 return RISCVISD::VECREDUCE_UMAX_VL;
11342 case ISD::VP_REDUCE_SMAX:
11344 return RISCVISD::VECREDUCE_SMAX_VL;
11345 case ISD::VP_REDUCE_UMIN:
11347 return RISCVISD::VECREDUCE_UMIN_VL;
11348 case ISD::VP_REDUCE_SMIN:
11350 return RISCVISD::VECREDUCE_SMIN_VL;
11351 case ISD::VP_REDUCE_AND:
11353 return RISCVISD::VECREDUCE_AND_VL;
11354 case ISD::VP_REDUCE_OR:
11356 return RISCVISD::VECREDUCE_OR_VL;
11357 case ISD::VP_REDUCE_XOR:
11359 return RISCVISD::VECREDUCE_XOR_VL;
11360 case ISD::VP_REDUCE_FADD:
11361 return RISCVISD::VECREDUCE_FADD_VL;
11362 case ISD::VP_REDUCE_SEQ_FADD:
11363 return RISCVISD::VECREDUCE_SEQ_FADD_VL;
11364 case ISD::VP_REDUCE_FMAX:
11365 case ISD::VP_REDUCE_FMAXIMUM:
11366 return RISCVISD::VECREDUCE_FMAX_VL;
11367 case ISD::VP_REDUCE_FMIN:
11368 case ISD::VP_REDUCE_FMINIMUM:
11369 return RISCVISD::VECREDUCE_FMIN_VL;
11378 SDValue Vec =
Op.getOperand(IsVP ? 1 : 0);
11383 Op.getOpcode() == ISD::VP_REDUCE_AND ||
11384 Op.getOpcode() == ISD::VP_REDUCE_OR ||
11385 Op.getOpcode() == ISD::VP_REDUCE_XOR) &&
11386 "Unexpected reduction lowering");
11390 MVT ContainerVT = VecVT;
11398 Mask =
Op.getOperand(2);
11399 VL =
Op.getOperand(3);
11401 std::tie(Mask, VL) =
11406 switch (
Op.getOpcode()) {
11410 case ISD::VP_REDUCE_AND: {
11414 Vec = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Vec, TrueMask, VL);
11417 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11422 case ISD::VP_REDUCE_OR:
11424 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11428 case ISD::VP_REDUCE_XOR: {
11431 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11452 return DAG.
getNode(BaseOpc,
DL,
Op.getValueType(), SetCC,
Op.getOperand(0));
11456 auto *RegisterAVL = dyn_cast<RegisterSDNode>(AVL);
11457 auto *ImmAVL = dyn_cast<ConstantSDNode>(AVL);
11458 return (RegisterAVL && RegisterAVL->getReg() == RISCV::X0) ||
11459 (ImmAVL && ImmAVL->getZExtValue() >= 1);
11475 auto InnerVT = VecVT.
bitsLE(M1VT) ? VecVT : M1VT;
11479 auto InnerVL = NonZeroAVL ? VL : DAG.
getConstant(1,
DL, XLenVT);
11482 if (M1VT != InnerVT)
11487 SDValue Ops[] = {PassThru, Vec, InitialValue, Mask, VL, Policy};
11505 VecEVT =
Lo.getValueType();
11518 MVT ContainerVT = VecVT;
11537 Mask, VL,
DL, DAG, Subtarget);
11543static std::tuple<unsigned, SDValue, SDValue>
11547 auto Flags =
Op->getFlags();
11548 unsigned Opcode =
Op.getOpcode();
11556 return std::make_tuple(RISCVISD::VECREDUCE_FADD_VL,
Op.getOperand(0), Zero);
11559 return std::make_tuple(RISCVISD::VECREDUCE_SEQ_FADD_VL,
Op.getOperand(1),
11568 ? RISCVISD::VECREDUCE_FMIN_VL
11569 : RISCVISD::VECREDUCE_FMAX_VL;
11570 return std::make_tuple(RVVOpc,
Op.getOperand(0), Front);
11578 MVT VecEltVT =
Op.getSimpleValueType();
11580 unsigned RVVOpcode;
11581 SDValue VectorVal, ScalarVal;
11582 std::tie(RVVOpcode, VectorVal, ScalarVal) =
11586 MVT ContainerVT = VecVT;
11592 MVT ResVT =
Op.getSimpleValueType();
11595 VL,
DL, DAG, Subtarget);
11600 if (
Op->getFlags().hasNoNaNs())
11606 {VectorVal, VectorVal, DAG.getCondCode(ISD::SETNE),
11607 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
11609 SDValue CPop = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, IsNan, Mask, VL);
11613 DL, ResVT, NoNaNs, Res,
11620 unsigned Opc =
Op.getOpcode();
11643 Vec, Mask, VL,
DL, DAG, Subtarget);
11644 if ((
Opc != ISD::VP_REDUCE_FMINIMUM &&
Opc != ISD::VP_REDUCE_FMAXIMUM) ||
11645 Op->getFlags().hasNoNaNs())
11652 RISCVISD::SETCC_VL,
DL, PredVT,
11654 SDValue VCPop = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, IsNaN, Mask, VL);
11662 DL, ResVT, NoNaNs, Res,
11675 unsigned OrigIdx =
Op.getConstantOperandVal(2);
11678 if (OrigIdx == 0 && Vec.
isUndef())
11689 assert(OrigIdx % 8 == 0 &&
"Invalid index");
11692 "Unexpected mask vector lowering");
11724 MVT ContainerVT = VecVT;
11746 if (OrigIdx == 0) {
11748 DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, ContainerVT, Vec, SubVec, VL);
11751 SubVec =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, Vec, SubVec,
11752 SlideupAmt, Mask, VL, Policy);
11760 MVT ContainerVecVT = VecVT;
11766 MVT ContainerSubVecVT = SubVecVT;
11772 unsigned SubRegIdx;
11782 ContainerVecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
11783 SubRegIdx = Decompose.first;
11785 (OrigIdx % Vscale));
11789 ContainerVecVT, ContainerSubVecVT, OrigIdx,
TRI);
11790 SubRegIdx = Decompose.first;
11797 bool ExactlyVecRegSized =
11799 .isKnownMultipleOf(Subtarget.
expandVScale(VecRegSize));
11814 if (RemIdx.
isZero() && (ExactlyVecRegSized || Vec.
isUndef())) {
11818 if (SubRegIdx == RISCV::NoSubRegister) {
11840 MVT InterSubVT = ContainerVecVT;
11841 SDValue AlignedExtract = Vec;
11870 SubVec = DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, InterSubVT, AlignedExtract,
11878 SubVec =
getVSlideup(DAG, Subtarget,
DL, InterSubVT, AlignedExtract, SubVec,
11879 SlideupAmt, Mask, VL, Policy);
11884 if (ContainerVecVT.
bitsGT(InterSubVT))
11892 return DAG.
getBitcast(
Op.getSimpleValueType(), SubVec);
11898 MVT SubVecVT =
Op.getSimpleValueType();
11903 unsigned OrigIdx =
Op.getConstantOperandVal(1);
11919 assert(OrigIdx % 8 == 0 &&
"Invalid index");
11922 "Unexpected mask vector lowering");
11956 MVT ContainerVT = VecVT;
11964 if (
auto ShrunkVT =
11966 ContainerVT = *ShrunkVT;
11978 DAG.
getUNDEF(ContainerVT), Vec, SlidedownAmt, Mask, VL);
11989 MVT ContainerSubVecVT = SubVecVT;
11993 unsigned SubRegIdx;
12003 VecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
12004 SubRegIdx = Decompose.first;
12006 (OrigIdx % Vscale));
12010 VecVT, ContainerSubVecVT, OrigIdx,
TRI);
12011 SubRegIdx = Decompose.first;
12038 MVT InterSubVT = VecVT;
12043 assert(SubRegIdx != RISCV::NoSubRegister);
12062 Vec, SlidedownAmt, Mask, VL);
12070 return DAG.
getBitcast(
Op.getSimpleValueType(), Slidedown);
12077 MVT VT =
N.getSimpleValueType();
12081 assert(
Op.getSimpleValueType() == VT &&
12082 "Operands and result must be same type");
12086 unsigned NumVals =
N->getNumValues();
12089 NumVals,
N.getValueType().changeVectorElementType(MVT::i8)));
12092 for (
unsigned I = 0;
I < NumVals;
I++) {
12098 if (TruncVals.
size() > 1)
12100 return TruncVals.
front();
12106 MVT VecVT =
Op.getSimpleValueType();
12108 const unsigned Factor =
Op->getNumValues();
12119 for (
unsigned i = 0U; i < Factor; ++i)
12128 for (
unsigned i = 0U; i < Factor; ++i)
12138 for (
unsigned i = 0; i != Factor; ++i) {
12141 Ops[i * 2 + 1] = OpHi;
12149 ArrayRef(Ops).slice(Factor, Factor));
12152 for (
unsigned i = 0; i != Factor; ++i)
12159 if (Subtarget.hasVendorXRivosVizip() && Factor == 2) {
12160 MVT VT =
Op->getSimpleValueType(0);
12185 lowerVZIP(RISCVISD::RI_VUNZIP2A_VL, V1, V2,
DL, DAG, Subtarget);
12187 lowerVZIP(RISCVISD::RI_VUNZIP2B_VL, V1, V2,
DL, DAG, Subtarget);
12220 EvenSplat = DAG.
getBitcast(MVT::nxv64i1, EvenSplat);
12224 OddSplat = DAG.
getBitcast(MVT::nxv64i1, OddSplat);
12229 EvenMask, DAG.
getUNDEF(ConcatVT));
12263 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
12264 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
12265 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
12266 Intrinsic::riscv_vlseg8_mask};
12290 for (
unsigned i = 0U; i < Factor; ++i)
12291 Res[i] = DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL, VecVT, Load,
12300 MVT VecVT =
Op.getSimpleValueType();
12313 for (
unsigned i = 0U; i < Factor; ++i)
12321 for (
unsigned i = 0U; i < Factor; ++i)
12334 for (
unsigned i = 0; i != Factor; ++i) {
12337 Ops[i + Factor] = OpHi;
12343 ArrayRef(Ops).take_front(Factor)),
12345 ArrayRef(Ops).drop_front(Factor))};
12348 for (
unsigned i = 0; i != Factor; ++i) {
12349 unsigned IdxLo = 2 * i;
12350 unsigned IdxHi = 2 * i + 1;
12352 Res[IdxLo / Factor].getValue(IdxLo % Factor),
12353 Res[IdxHi / Factor].getValue(IdxHi % Factor));
12377 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
12378 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
12379 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
12380 Intrinsic::riscv_vsseg8_mask,
12388 for (
unsigned i = 0; i < Factor; i++)
12390 DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VecTupTy, StoredVal,
12413 for (
unsigned i = 0; i != Factor; ++i) {
12417 Loads[i] = DAG.
getLoad(VecVT,
DL, Chain, StackPtr, PtrInfo);
12425 if (Subtarget.hasVendorXRivosVizip() && !
Op.getOperand(0).isUndef() &&
12426 !
Op.getOperand(1).isUndef()) {
12446 Op.getOperand(0),
Op.getOperand(1));
12470 DAG.
getNode(RISCVISD::ADD_VL,
DL, IdxVT,
Idx, VLMax,
Idx, OddMask, VL);
12475 Interleaved = DAG.
getNode(RISCVISD::VRGATHEREI16_VV_VL,
DL, ConcatVT,
12492 MVT VT =
Op.getSimpleValueType();
12497 uint64_t StepValImm =
Op.getConstantOperandVal(0);
12498 if (StepValImm != 1) {
12507 VL, VT,
DL, DAG, Subtarget);
12522 MVT VecVT =
Op.getSimpleValueType();
12531 MVT ContainerVT = VecVT;
12585 unsigned MaxVLMAX =
12590 unsigned GatherOpc = RISCVISD::VRGATHER_VV_VL;
12595 if (MaxVLMAX > 256 && EltSize == 8) {
12609 LoVT.getVectorMinNumElements());
12614 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
12621 assert(isUInt<16>(MaxVLMAX - 1));
12622 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
12647 DAG.
getUNDEF(ContainerVT), Mask, VL);
12659 MVT VecVT =
Op.getSimpleValueType();
12663 int64_t ImmValue = cast<ConstantSDNode>(
Op.getOperand(2))->getSExtValue();
12664 SDValue DownOffset, UpOffset;
12665 if (ImmValue >= 0) {
12680 DAG, Subtarget,
DL, VecVT, DAG.
getUNDEF(VecVT), V1, DownOffset, TrueMask,
12681 Subtarget.hasVLDependentLatency() ? UpOffset
12683 return getVSlideup(DAG, Subtarget,
DL, VecVT, SlideDown, V2, UpOffset,
12689RISCVTargetLowering::lowerFixedLengthVectorLoadToRVV(
SDValue Op,
12692 auto *
Load = cast<LoadSDNode>(
Op);
12695 Load->getMemoryVT(),
12696 *
Load->getMemOperand()) &&
12697 "Expecting a correctly-aligned load");
12699 MVT VT =
Op.getSimpleValueType();
12705 const auto [MinVLMAX, MaxVLMAX] =
12722 IsMaskOp ? Intrinsic::riscv_vlm : Intrinsic::riscv_vle,
DL, XLenVT);
12725 Ops.push_back(DAG.
getUNDEF(ContainerVT));
12726 Ops.push_back(
Load->getBasePtr());
12731 Load->getMemoryVT(),
Load->getMemOperand());
12738RISCVTargetLowering::lowerFixedLengthVectorStoreToRVV(
SDValue Op,
12741 auto *
Store = cast<StoreSDNode>(
Op);
12744 Store->getMemoryVT(),
12745 *
Store->getMemOperand()) &&
12746 "Expecting a correctly-aligned store");
12766 const auto [MinVLMAX, MaxVLMAX] =
12780 IsMaskOp ? Intrinsic::riscv_vsm : Intrinsic::riscv_vse,
DL, XLenVT);
12783 {Store->getChain(), IntID, NewValue, Store->getBasePtr(), VL},
12784 Store->getMemoryVT(),
Store->getMemOperand());
12790 MVT VT =
Op.getSimpleValueType();
12792 const auto *MemSD = cast<MemSDNode>(
Op);
12793 EVT MemVT = MemSD->getMemoryVT();
12795 SDValue Chain = MemSD->getChain();
12799 bool IsExpandingLoad =
false;
12800 if (
const auto *VPLoad = dyn_cast<VPLoadSDNode>(
Op)) {
12801 Mask = VPLoad->getMask();
12803 VL = VPLoad->getVectorLength();
12805 const auto *MLoad = cast<MaskedLoadSDNode>(
Op);
12806 Mask = MLoad->getMask();
12807 PassThru = MLoad->getPassThru();
12808 IsExpandingLoad = MLoad->isExpandingLoad();
12815 MVT ContainerVT = VT;
12829 if (!IsUnmasked && IsExpandingLoad) {
12832 DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Mask,
12836 unsigned IntID = IsUnmasked || IsExpandingLoad ? Intrinsic::riscv_vle
12837 : Intrinsic::riscv_vle_mask;
12839 if (IntID == Intrinsic::riscv_vle)
12840 Ops.push_back(DAG.
getUNDEF(ContainerVT));
12842 Ops.push_back(PassThru);
12843 Ops.push_back(BasePtr);
12844 if (IntID == Intrinsic::riscv_vle_mask)
12845 Ops.push_back(Mask);
12847 if (IntID == Intrinsic::riscv_vle_mask)
12854 Chain =
Result.getValue(1);
12856 MVT IndexVT = ContainerVT;
12861 bool UseVRGATHEREI16 =
false;
12869 UseVRGATHEREI16 =
true;
12875 DAG.
getUNDEF(IndexVT), Mask, ExpandingVL);
12877 DAG.
getNode(UseVRGATHEREI16 ? RISCVISD::VRGATHEREI16_VV_VL
12878 : RISCVISD::VRGATHER_VV_VL,
12879 DL, ContainerVT, Result, Iota, PassThru, Mask, ExpandingVL);
12890 MVT VT =
Op->getSimpleValueType(0);
12892 const auto *VPLoadFF = cast<VPLoadFFSDNode>(
Op);
12893 EVT MemVT = VPLoadFF->getMemoryVT();
12895 SDValue Chain = VPLoadFF->getChain();
12899 SDValue VL = VPLoadFF->getVectorLength();
12903 MVT ContainerVT = VT;
12910 unsigned IntID = Intrinsic::riscv_vleff_mask;
12925 Chain =
Result.getValue(2);
12937 const auto *MemSD = cast<MemSDNode>(
Op);
12938 EVT MemVT = MemSD->getMemoryVT();
12940 SDValue Chain = MemSD->getChain();
12944 bool IsCompressingStore =
false;
12945 if (
const auto *VPStore = dyn_cast<VPStoreSDNode>(
Op)) {
12946 Val = VPStore->getValue();
12947 Mask = VPStore->getMask();
12948 VL = VPStore->getVectorLength();
12950 const auto *MStore = cast<MaskedStoreSDNode>(
Op);
12951 Val = MStore->getValue();
12952 Mask = MStore->getMask();
12953 IsCompressingStore = MStore->isCompressingStore();
12962 MVT ContainerVT = VT;
12967 if (!IsUnmasked || IsCompressingStore) {
12976 if (IsCompressingStore) {
12979 DAG.
getUNDEF(ContainerVT), Val, Mask, VL);
12981 DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Mask,
12986 IsUnmasked ? Intrinsic::riscv_vse : Intrinsic::riscv_vse_mask;
12988 Ops.push_back(Val);
12989 Ops.push_back(BasePtr);
12991 Ops.push_back(Mask);
12995 DAG.
getVTList(MVT::Other), Ops, MemVT, MMO);
13007 MVT ContainerVT = VT;
13020 Passthru, Val, Mask, VL);
13030 unsigned Opc =
Op.getOpcode();
13037 MVT VT =
Op.getSimpleValueType();
13070 MVT ContainerInVT = InVT;
13088 RISCVISD::STRICT_FSETCC_VL,
DL, DAG.
getVTList(MaskVT, MVT::Other),
13089 {Chain, Op1, Op1, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
13092 RISCVISD::STRICT_FSETCC_VL,
DL, DAG.
getVTList(MaskVT, MVT::Other),
13093 {Chain, Op2, Op2, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
13096 DAG.
getNode(RISCVISD::VMAND_VL,
DL, MaskVT, OrderMask1, OrderMask2, VL);
13099 Res = DAG.
getNode(RISCVISD::STRICT_FSETCCS_VL,
DL,
13101 {Chain, Op1, Op2, CC, Mask, Mask, VL});
13104 : RISCVISD::STRICT_FSETCCS_VL;
13106 {Chain, Op1, Op2, CC, DAG.getUNDEF(MaskVT), Mask, VL});
13119 MVT VT =
Op.getSimpleValueType();
13123 "Unexpected type for ISD::ABS");
13125 MVT ContainerVT = VT;
13132 if (
Op->getOpcode() == ISD::VP_ABS) {
13133 Mask =
Op->getOperand(1);
13137 VL =
Op->getOperand(2);
13142 RISCVISD::VMV_V_X_VL,
DL, ContainerVT, DAG.
getUNDEF(ContainerVT),
13145 DAG.
getUNDEF(ContainerVT), Mask, VL);
13147 DAG.
getUNDEF(ContainerVT), Mask, VL);
13156 const auto &TSInfo =
13160 bool HasPassthruOp = TSInfo.hasPassthruOp(NewOpc);
13161 bool HasMask = TSInfo.hasMaskOp(NewOpc);
13163 MVT VT =
Op.getSimpleValueType();
13168 for (
const SDValue &V :
Op->op_values()) {
13169 assert(!isa<VTSDNode>(V) &&
"Unexpected VTSDNode node!");
13172 if (!
V.getValueType().isVector()) {
13178 assert(useRVVForFixedLengthVectorVT(
V.getSimpleValueType()) &&
13179 "Only fixed length vectors are supported!");
13181 V.getSimpleValueType().getVectorElementType());
13195 if (
Op->isStrictFPOpcode()) {
13204 DAG.
getNode(NewOpc,
DL, ContainerVT, Ops,
Op->getFlags());
13214 const auto &TSInfo =
13218 bool HasPassthruOp = TSInfo.hasPassthruOp(RISCVISDOpc);
13221 MVT VT =
Op.getSimpleValueType();
13224 MVT ContainerVT = VT;
13230 assert(!isa<VTSDNode>(V) &&
"Unexpected VTSDNode node!");
13233 if (HasPassthruOp) {
13236 if (*MaskIdx ==
OpIdx.index())
13240 if (
Op.getOpcode() == ISD::VP_MERGE) {
13244 assert(
Op.getOpcode() == ISD::VP_SELECT);
13251 if (RISCVISDOpc == RISCVISD::VFCVT_RM_X_F_VL &&
13256 if (!
V.getValueType().isFixedLengthVector()) {
13261 MVT OpVT =
V.getSimpleValueType();
13263 assert(useRVVForFixedLengthVectorVT(OpVT) &&
13264 "Only fixed length vectors are supported!");
13269 return DAG.
getNode(RISCVISDOpc,
DL, VT, Ops,
Op->getFlags());
13279 MVT VT =
Op.getSimpleValueType();
13285 MVT ContainerVT = VT;
13295 DAG.
getUNDEF(ContainerVT), Zero, VL);
13298 Op.getOpcode() == ISD::VP_ZERO_EXTEND ? 1 : -1,
DL, XLenVT);
13300 DAG.
getUNDEF(ContainerVT), SplatValue, VL);
13303 ZeroSplat, DAG.
getUNDEF(ContainerVT), VL);
13312 MVT VT =
Op.getSimpleValueType();
13316 ISD::CondCode Condition = cast<CondCodeSDNode>(
Op.getOperand(2))->get();
13320 MVT ContainerVT = VT;
13328 SDValue AllOneMask = DAG.
getNode(RISCVISD::VMSET_VL,
DL, ContainerVT, VL);
13330 switch (Condition) {
13335 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, Op2, VL);
13340 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, Op2, VL);
13342 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, AllOneMask, VL);
13350 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, AllOneMask, VL);
13351 Result = DAG.
getNode(RISCVISD::VMAND_VL,
DL, ContainerVT, Temp, Op2, VL);
13359 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op2, AllOneMask, VL);
13360 Result = DAG.
getNode(RISCVISD::VMAND_VL,
DL, ContainerVT, Op1, Temp, VL);
13368 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, AllOneMask, VL);
13369 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, Op2, VL);
13377 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op2, AllOneMask, VL);
13378 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, Op1, VL);
13398 MVT DstVT =
Op.getSimpleValueType();
13399 MVT SrcVT = Src.getSimpleValueType();
13412 if (DstEltSize >= SrcEltSize) {
13416 unsigned RISCVISDExtOpc = RISCVISDOpc == RISCVISD::SINT_TO_FP_VL
13417 ? RISCVISD::VSEXT_VL
13418 : RISCVISD::VZEXT_VL;
13421 if (SrcEltSize == 1) {
13428 RISCVISDExtOpc == RISCVISD::VZEXT_VL ? 1 : -1,
DL, XLenVT);
13431 Src = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, IntVT, Src, OneSplat,
13432 ZeroSplat, DAG.
getUNDEF(IntVT), VL);
13433 }
else if (DstEltSize > (2 * SrcEltSize)) {
13437 Src = DAG.
getNode(RISCVISDExtOpc,
DL, IntVT, Src, Mask, VL);
13443 "Wrong input/output vector types");
13446 if (DstEltSize > (2 * SrcEltSize)) {
13451 DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, InterimFVT, Src, Mask, VL);
13462 MVT InterimFVT = DstVT;
13463 if (SrcEltSize > (2 * DstEltSize)) {
13464 assert(SrcEltSize == (4 * DstEltSize) &&
"Unexpected types!");
13471 if (InterimFVT != DstVT) {
13473 Result = DAG.
getNode(RISCVISD::FP_ROUND_VL,
DL, DstVT, Src, Mask, VL);
13477 "Wrong input/output vector types");
13481 if (DstEltSize == 1) {
13484 assert(SrcEltSize >= 16 &&
"Unexpected FP type!");
13493 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, InterimIVT,
13494 DAG.
getUNDEF(InterimIVT), SplatZero, VL);
13504 while (InterimIVT != DstVT) {
13516 MVT VT =
Op.getSimpleValueType();
13525 MVT VT =
Op.getSimpleValueType();
13539 MVT ContainerVT = VT;
13559 TrueVal = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, PromotedVT, TrueVal, SplatOne,
13560 SplatZero, DAG.
getUNDEF(PromotedVT), VL);
13563 SplatOne, SplatZero, DAG.
getUNDEF(PromotedVT), VLMax);
13567 TrueVal, FalseVal, FalseVal, VL);
13572 RISCVISD::SETCC_VL,
DL, ContainerVT,
13582RISCVTargetLowering::lowerVPSpliceExperimental(
SDValue Op,
13584 using namespace SDPatternMatch;
13596 MVT VT =
Op.getSimpleValueType();
13597 MVT ContainerVT = VT;
13607 if (IsMaskVector) {
13617 Op1 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, Op1, SplatOneOp1,
13618 SplatZeroOp1, DAG.
getUNDEF(ContainerVT), EVL1);
13626 Op2 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, Op2, SplatOneOp2,
13627 SplatZeroOp2, DAG.
getUNDEF(ContainerVT), EVL2);
13630 auto getVectorFirstEle = [](
SDValue Vec) {
13643 if (
auto FirstEle = getVectorFirstEle(
Op->getOperand(0))) {
13647 EltVT == MVT::bf16) {
13655 : RISCVISD::VSLIDE1UP_VL,
13656 DL, ContainerVT, DAG.
getUNDEF(ContainerVT), Op2,
13657 FirstEle, Mask, EVL2);
13666 int64_t ImmValue = cast<ConstantSDNode>(
Offset)->getSExtValue();
13667 SDValue DownOffset, UpOffset;
13668 if (ImmValue >= 0) {
13682 DAG.
getUNDEF(ContainerVT), Op1, DownOffset, Mask,
13683 Subtarget.hasVLDependentLatency() ? UpOffset : EVL2);
13687 if (IsMaskVector) {
13691 {Result, DAG.getConstant(0, DL, ContainerVT),
13692 DAG.getCondCode(ISD::SETNE), DAG.getUNDEF(getMaskTypeFor(ContainerVT)),
13707 MVT VT =
Op.getSimpleValueType();
13709 MVT ContainerVT = VT;
13718 if (
auto *
C = dyn_cast<ConstantSDNode>(Val)) {
13720 DAG.
getNode(
C->isZero() ? RISCVISD::VMCLR_VL : RISCVISD::VMSET_VL,
DL,
13730 DAG.
getUNDEF(ContainerVT), Mask, VL});
13743RISCVTargetLowering::lowerVPReverseExperimental(
SDValue Op,
13746 MVT VT =
Op.getSimpleValueType();
13753 MVT ContainerVT = VT;
13761 MVT GatherVT = ContainerVT;
13765 if (IsMaskVector) {
13775 Op1 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, IndicesVT, Op1, SplatOne,
13776 SplatZero, DAG.
getUNDEF(IndicesVT), EVL);
13782 unsigned MaxVLMAX =
13785 unsigned GatherOpc = RISCVISD::VRGATHER_VV_VL;
13791 if (MaxVLMAX > 256 && EltSize == 8) {
13819 DAG.
getUNDEF(GatherVT), Result, Diff, Mask, EVL);
13821 if (IsMaskVector) {
13824 DAG.
getNode(RISCVISD::SETCC_VL,
DL, ContainerVT,
13837 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
13844 DAG.
getUNDEF(IndicesVT), VecLen, EVL);
13845 SDValue VRSUB = DAG.
getNode(RISCVISD::SUB_VL,
DL, IndicesVT, VecLenSplat, VID,
13846 DAG.
getUNDEF(IndicesVT), Mask, EVL);
13848 DAG.
getUNDEF(GatherVT), Mask, EVL);
13850 if (IsMaskVector) {
13853 RISCVISD::SETCC_VL,
DL, ContainerVT,
13865 MVT VT =
Op.getSimpleValueType();
13867 return lowerVPOp(
Op, DAG);
13874 MVT ContainerVT = VT;
13893 MVT VT =
Op.getSimpleValueType();
13894 MVT ContainerVT = VT;
13900 auto *VPNode = cast<VPStridedLoadSDNode>(
Op);
13906 : Intrinsic::riscv_vlse_mask,
13909 DAG.
getUNDEF(ContainerVT), VPNode->getBasePtr(),
13910 VPNode->getStride()};
13918 Ops.
push_back(VPNode->getVectorLength());
13927 VPNode->getMemoryVT(), VPNode->getMemOperand());
13941 auto *VPNode = cast<VPStridedStoreSDNode>(
Op);
13942 SDValue StoreVal = VPNode->getValue();
13944 MVT ContainerVT = VT;
13955 : Intrinsic::riscv_vsse_mask,
13958 VPNode->getBasePtr(), VPNode->getStride()};
13966 Ops.
push_back(VPNode->getVectorLength());
13969 Ops, VPNode->getMemoryVT(),
13970 VPNode->getMemOperand());
13982 MVT VT =
Op.getSimpleValueType();
13984 const auto *MemSD = cast<MemSDNode>(
Op.getNode());
13985 EVT MemVT = MemSD->getMemoryVT();
13987 SDValue Chain = MemSD->getChain();
13993 if (
auto *VPGN = dyn_cast<VPGatherSDNode>(
Op.getNode())) {
13994 Index = VPGN->getIndex();
13995 Mask = VPGN->getMask();
13997 VL = VPGN->getVectorLength();
14002 auto *MGN = cast<MaskedGatherSDNode>(
Op.getNode());
14003 Index = MGN->getIndex();
14004 Mask = MGN->getMask();
14005 PassThru = MGN->getPassThru();
14009 MVT IndexVT =
Index.getSimpleValueType();
14013 "Unexpected VTs!");
14014 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
14017 "Unexpected extending MGATHER/VP_GATHER");
14023 MVT ContainerVT = VT;
14047 IsUnmasked ? Intrinsic::riscv_vluxei : Intrinsic::riscv_vluxei_mask;
14064 Chain =
Result.getValue(1);
14081 const auto *MemSD = cast<MemSDNode>(
Op.getNode());
14082 EVT MemVT = MemSD->getMemoryVT();
14084 SDValue Chain = MemSD->getChain();
14087 [[maybe_unused]]
bool IsTruncatingStore =
false;
14090 if (
auto *VPSN = dyn_cast<VPScatterSDNode>(
Op.getNode())) {
14091 Index = VPSN->getIndex();
14092 Mask = VPSN->getMask();
14093 Val = VPSN->getValue();
14094 VL = VPSN->getVectorLength();
14096 IsTruncatingStore =
false;
14099 auto *MSN = cast<MaskedScatterSDNode>(
Op.getNode());
14100 Index = MSN->getIndex();
14101 Mask = MSN->getMask();
14102 Val = MSN->getValue();
14103 IsTruncatingStore = MSN->isTruncatingStore();
14107 MVT IndexVT =
Index.getSimpleValueType();
14111 "Unexpected VTs!");
14112 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
14115 assert(!IsTruncatingStore &&
"Unexpected truncating MSCATTER/VP_SCATTER");
14121 MVT ContainerVT = VT;
14145 IsUnmasked ? Intrinsic::riscv_vsoxei : Intrinsic::riscv_vsoxei_mask;
14155 DAG.
getVTList(MVT::Other), Ops, MemVT, MMO);
14171 static const int Table =
14200 static const unsigned Table =
14215 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14226 return DAG.
getNode(RISCVISD::READ_CSR,
DL, VTs, Chain, SysRegNo);
14238 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14250 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14264 SDValue Result = DAG.
getNode(RISCVISD::READ_CSR,
DL, VTs, Chain, SysRegNo);
14265 Chain = Result.getValue(1);
14281 Chain = DAG.
getNode(RISCVISD::CLEAR_CSR,
DL, MVT::Other, Chain, SysRegNo,
14283 return DAG.
getNode(RISCVISD::SET_CSR,
DL, MVT::Other, Chain, SysRegNo,
14296 return DAG.
getNode(RISCVISD::CLEAR_CSR,
DL, MVT::Other, Chain, SysRegNo,
14304 bool isRISCV64 = Subtarget.
is64Bit();
14318 return RISCVISD::SLLW;
14320 return RISCVISD::SRAW;
14322 return RISCVISD::SRLW;
14324 return RISCVISD::DIVW;
14326 return RISCVISD::DIVUW;
14328 return RISCVISD::REMUW;
14330 return RISCVISD::ROLW;
14332 return RISCVISD::RORW;
14368 switch (
N->getOpcode()) {
14370 llvm_unreachable(
"Don't know how to custom type legalize this operation!");
14376 "Unexpected custom legalisation");
14377 bool IsStrict =
N->isStrictFPOpcode();
14380 SDValue Op0 = IsStrict ?
N->getOperand(1) :
N->getOperand(0);
14394 unsigned Opc = IsSigned ? RISCVISD::STRICT_FCVT_W_RV64
14395 : RISCVISD::STRICT_FCVT_WU_RV64;
14398 Opc,
DL, VTs, Chain, Op0,
14411 unsigned Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
14432 std::tie(Result, Chain) =
14433 makeLibCall(DAG, LC,
N->getValueType(0), Op0, CallOptions,
DL, Chain);
14452 DAG.
getNode(RISCVISD::FCVT_W_RV64,
DL, MVT::i64, Op0,
14460 RTLIB::Libcall LC =
14461 Op0.
getValueType() == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
14472 assert(!Subtarget.
is64Bit() &&
"READCYCLECOUNTER/READSTEADYCOUNTER only "
14473 "has custom type legalization on riscv32");
14475 SDValue LoCounter, HiCounter;
14486 N->getOperand(0), LoCounter, HiCounter);
14501 if (
N->getValueType(0) == MVT::i64) {
14502 assert(Subtarget.hasStdExtZilsd() && !Subtarget.
is64Bit() &&
14503 "Unexpected custom legalisation");
14505 if (!Subtarget.enableUnalignedScalarMem() && Ld->
getAlign() < 8)
14510 RISCVISD::LD_RV32,
DL,
14511 DAG.
getVTList({MVT::i32, MVT::i32, MVT::Other}),
14512 {Ld->getChain(), Ld->getBasePtr()}, MVT::i64, Ld->
getMemOperand());
14516 Results.append({Pair, Result.getValue(2)});
14521 "Unexpected custom legalisation");
14532 unsigned Size =
N->getSimpleValueType(0).getSizeInBits();
14533 unsigned XLen = Subtarget.
getXLen();
14536 assert(
Size == (XLen * 2) &&
"Unexpected custom legalisation");
14544 if (LHSIsU == RHSIsU)
14561 if (RHSIsU && LHSIsS && !RHSIsS)
14563 else if (LHSIsU && RHSIsS && !LHSIsS)
14573 "Unexpected custom legalisation");
14580 "Unexpected custom legalisation");
14583 if (
N->getOpcode() ==
ISD::SHL && Subtarget.hasStdExtZbs() &&
14609 "Unexpected custom legalisation");
14610 assert((Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb() ||
14611 Subtarget.hasVendorXTHeadBb()) &&
14612 "Unexpected custom legalization");
14613 if (!isa<ConstantSDNode>(
N->getOperand(1)) &&
14614 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()))
14623 "Unexpected custom legalisation");
14629 unsigned Opc = IsCTZ ? RISCVISD::CTZW : RISCVISD::CLZW;
14637 MVT VT =
N->getSimpleValueType(0);
14638 assert((VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32) &&
14639 Subtarget.
is64Bit() && Subtarget.hasStdExtM() &&
14640 "Unexpected custom legalisation");
14652 if (VT != MVT::i32)
14661 "Unexpected custom legalisation");
14665 if (!isa<ConstantSDNode>(
N->getOperand(1)))
14682 EVT OType =
N->getValueType(1);
14695 "Unexpected custom legalisation");
14712 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1), Res,
14716 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1),
N->getOperand(0),
14734 !Subtarget.hasStdExtZbb() &&
"Unexpected custom legalisation");
14743 "Unexpected custom legalisation");
14749 "Unexpected custom legalisation");
14751 if (Subtarget.hasStdExtZbb()) {
14785 EVT VT =
N->getValueType(0);
14790 if (VT == MVT::i16 &&
14792 (Op0VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
14795 }
else if (VT == MVT::i32 && Op0VT == MVT::f32 && Subtarget.
is64Bit() &&
14798 DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Op0);
14800 }
else if (VT == MVT::i64 && Op0VT == MVT::f64 && !Subtarget.
is64Bit() &&
14803 DAG.
getVTList(MVT::i32, MVT::i32), Op0);
14822 assert(
N->getValueType(0) == MVT::i8 && Subtarget.hasStdExtZbkb() &&
14823 "Unexpected custom legalisation");
14832 case RISCVISD::BREV8:
14833 case RISCVISD::ORC_B: {
14834 MVT VT =
N->getSimpleValueType(0);
14836 assert((VT == MVT::i16 || (VT == MVT::i32 && Subtarget.
is64Bit())) &&
14837 "Unexpected custom legalisation");
14838 assert(((
N->getOpcode() == RISCVISD::BREV8 && Subtarget.hasStdExtZbkb()) ||
14839 (
N->getOpcode() == RISCVISD::ORC_B && Subtarget.hasStdExtZbb())) &&
14840 "Unexpected extension");
14866 assert(!Subtarget.
is64Bit() &&
N->getValueType(0) == MVT::i64 &&
14868 "Unexpected EXTRACT_VECTOR_ELT legalization");
14871 MVT ContainerVT = VecVT;
14898 DAG.
getNode(RISCVISD::SRL_VL,
DL, ContainerVT, Vec, ThirtyTwoV,
14899 DAG.
getUNDEF(ContainerVT), Mask, VL);
14907 unsigned IntNo =
N->getConstantOperandVal(0);
14911 "Don't know how to custom type legalize this intrinsic!");
14912 case Intrinsic::experimental_get_vector_length: {
14917 case Intrinsic::experimental_cttz_elts: {
14923 case Intrinsic::riscv_orc_b:
14924 case Intrinsic::riscv_brev8:
14925 case Intrinsic::riscv_sha256sig0:
14926 case Intrinsic::riscv_sha256sig1:
14927 case Intrinsic::riscv_sha256sum0:
14928 case Intrinsic::riscv_sha256sum1:
14929 case Intrinsic::riscv_sm3p0:
14930 case Intrinsic::riscv_sm3p1: {
14931 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
14935 case Intrinsic::riscv_orc_b:
Opc = RISCVISD::ORC_B;
break;
14936 case Intrinsic::riscv_brev8:
Opc = RISCVISD::BREV8;
break;
14937 case Intrinsic::riscv_sha256sig0:
Opc = RISCVISD::SHA256SIG0;
break;
14938 case Intrinsic::riscv_sha256sig1:
Opc = RISCVISD::SHA256SIG1;
break;
14939 case Intrinsic::riscv_sha256sum0:
Opc = RISCVISD::SHA256SUM0;
break;
14940 case Intrinsic::riscv_sha256sum1:
Opc = RISCVISD::SHA256SUM1;
break;
14941 case Intrinsic::riscv_sm3p0:
Opc = RISCVISD::SM3P0;
break;
14942 case Intrinsic::riscv_sm3p1:
Opc = RISCVISD::SM3P1;
break;
14951 case Intrinsic::riscv_sm4ks:
14952 case Intrinsic::riscv_sm4ed: {
14954 IntNo == Intrinsic::riscv_sm4ks ? RISCVISD::SM4KS : RISCVISD::SM4ED;
14960 DAG.
getNode(
Opc,
DL, MVT::i64, NewOp0, NewOp1,
N->getOperand(3));
14964 case Intrinsic::riscv_mopr: {
14965 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
14970 RISCVISD::MOP_R,
DL, MVT::i64, NewOp,
14975 case Intrinsic::riscv_moprr: {
14976 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
14983 RISCVISD::MOP_RR,
DL, MVT::i64, NewOp0, NewOp1,
14988 case Intrinsic::riscv_clmul: {
14989 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
15000 case Intrinsic::riscv_clmulh:
15001 case Intrinsic::riscv_clmulr: {
15002 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
15022 unsigned Opc = IntNo == Intrinsic::riscv_clmulh ? RISCVISD::CLMULH
15023 : RISCVISD::CLMULR;
15030 case Intrinsic::riscv_vmv_x_s: {
15031 EVT VT =
N->getValueType(0);
15033 if (VT.
bitsLT(XLenVT)) {
15042 "Unexpected custom legalization");
15058 SDValue LShr32 = DAG.
getNode(RISCVISD::SRL_VL,
DL, VecVT, Vec, ThirtyTwoV,
15080 case ISD::VP_REDUCE_ADD:
15081 case ISD::VP_REDUCE_AND:
15082 case ISD::VP_REDUCE_OR:
15083 case ISD::VP_REDUCE_XOR:
15084 case ISD::VP_REDUCE_SMAX:
15085 case ISD::VP_REDUCE_UMAX:
15086 case ISD::VP_REDUCE_SMIN:
15087 case ISD::VP_REDUCE_UMIN:
15151 const EVT VT =
N->getValueType(0);
15152 const unsigned Opc =
N->getOpcode();
15159 (
Opc !=
ISD::FADD || !
N->getFlags().hasAllowReassociation()))
15164 "Inconsistent mappings");
15175 !isa<ConstantSDNode>(
RHS.getOperand(1)))
15178 uint64_t RHSIdx = cast<ConstantSDNode>(
RHS.getOperand(1))->getLimitedValue();
15193 LHS.getOperand(0) == SrcVec && isa<ConstantSDNode>(
LHS.getOperand(1))) {
15195 cast<ConstantSDNode>(
LHS.getOperand(1))->getLimitedValue();
15196 if (0 == std::min(LHSIdx, RHSIdx) && 1 == std::max(LHSIdx, RHSIdx)) {
15199 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
N->getFlags());
15206 if (
LHS.getOpcode() != ReduceOpc)
15220 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
15221 ReduceVec->
getFlags() &
N->getFlags());
15231 auto BinOpToRVVReduce = [](
unsigned Opc) {
15236 return RISCVISD::VECREDUCE_ADD_VL;
15238 return RISCVISD::VECREDUCE_UMAX_VL;
15240 return RISCVISD::VECREDUCE_SMAX_VL;
15242 return RISCVISD::VECREDUCE_UMIN_VL;
15244 return RISCVISD::VECREDUCE_SMIN_VL;
15246 return RISCVISD::VECREDUCE_AND_VL;
15248 return RISCVISD::VECREDUCE_OR_VL;
15250 return RISCVISD::VECREDUCE_XOR_VL;
15252 return RISCVISD::VECREDUCE_FADD_VL;
15254 return RISCVISD::VECREDUCE_FMAX_VL;
15256 return RISCVISD::VECREDUCE_FMIN_VL;
15260 auto IsReduction = [&BinOpToRVVReduce](
SDValue V,
unsigned Opc) {
15263 V.getOperand(0).getOpcode() == BinOpToRVVReduce(
Opc);
15266 unsigned Opc =
N->getOpcode();
15267 unsigned ReduceIdx;
15268 if (IsReduction(
N->getOperand(0),
Opc))
15270 else if (IsReduction(
N->getOperand(1),
Opc))
15276 if (
Opc ==
ISD::FADD && !
N->getFlags().hasAllowReassociation())
15279 SDValue Extract =
N->getOperand(ReduceIdx);
15292 if (ScalarV.
getOpcode() != RISCVISD::VFMV_S_F_VL &&
15293 ScalarV.
getOpcode() != RISCVISD::VMV_S_X_VL &&
15294 ScalarV.
getOpcode() != RISCVISD::VMV_V_X_VL)
15311 SDValue NewStart =
N->getOperand(1 - ReduceIdx);
15338 const bool HasStdExtZba = Subtarget.hasStdExtZba();
15339 const bool HasVendorXAndesPerf = Subtarget.hasVendorXAndesPerf();
15340 const bool HasVendorXqciac = Subtarget.hasVendorXqciac();
15342 if (!HasStdExtZba && !HasVendorXAndesPerf && !HasVendorXqciac)
15346 EVT VT =
N->getValueType(0);
15358 auto *N0C = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
15359 auto *N1C = dyn_cast<ConstantSDNode>(N1->
getOperand(1));
15362 int64_t C0 = N0C->getSExtValue();
15363 int64_t C1 = N1C->getSExtValue();
15364 if (C0 <= 0 || C1 <= 0)
15367 int64_t Diff = std::abs(C0 - C1);
15368 bool IsShXaddDiff = Diff == 1 || Diff == 2 || Diff == 3;
15369 bool HasShXadd = HasStdExtZba || HasVendorXAndesPerf;
15372 if ((!IsShXaddDiff && HasShXadd && !HasVendorXqciac) ||
15373 (IsShXaddDiff && !HasShXadd && HasVendorXqciac))
15377 if (Diff == 0 || Diff > 31)
15382 int64_t Bits = std::min(C0, C1);
15397 if (isa<ConstantSDNode>(
N->getOperand(1)))
15407 if (!sd_match(AddI,
m_Add(
m_Value(SHLVal), m_ConstInt(AddVal))))
15414 if (VShift.
slt(1) || VShift.
sgt(3))
15418 EVT VT =
N->getValueType(0);
15438 EVT VT =
N->getValueType(0);
15466 EVT VT =
N->getValueType(0);
15474 if ((!Subtarget.hasStdExtZicond() &&
15475 !Subtarget.hasVendorXVentanaCondOps()) ||
15489 Slct.
getOpcode() != RISCVISD::SELECT_CC) ||
15497 bool SwapSelectOps;
15498 unsigned OpOffset = Slct.
getOpcode() == RISCVISD::SELECT_CC ? 2 : 0;
15503 SwapSelectOps =
false;
15504 NonConstantVal = FalseVal;
15506 SwapSelectOps =
true;
15507 NonConstantVal = TrueVal;
15513 FalseVal = DAG.
getNode(
N->getOpcode(),
SDLoc(
N), VT, OtherOp, NonConstantVal);
15518 if (Slct.
getOpcode() == RISCVISD::SELECT_CC)
15561 EVT VT =
N->getValueType(0);
15569 auto *N0C = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
15570 auto *N1C = dyn_cast<ConstantSDNode>(
N->getOperand(1));
15576 if (!N0C->hasOneUse())
15578 int64_t C0 = N0C->getSExtValue();
15579 int64_t C1 = N1C->getSExtValue();
15581 if (C0 == -1 || C0 == 0 || C0 == 1 || isInt<12>(C1))
15584 if ((C1 / C0) != 0 && isInt<12>(C1 / C0) && isInt<12>(C1 % C0) &&
15585 !isInt<12>(C0 * (C1 / C0))) {
15588 }
else if ((C1 / C0 + 1) != 0 && isInt<12>(C1 / C0 + 1) &&
15589 isInt<12>(C1 % C0 - C0) && !isInt<12>(C0 * (C1 / C0 + 1))) {
15592 }
else if ((C1 / C0 - 1) != 0 && isInt<12>(C1 / C0 - 1) &&
15593 isInt<12>(C1 % C0 + C0) && !isInt<12>(C0 * (C1 / C0 - 1))) {
15620 EVT VT =
N->getValueType(0);
15651 unsigned OuterExtend =
15655 OuterExtend,
SDLoc(
N), VT,
15663 EVT VT =
N->getValueType(0);
15714 EVT VT =
N->getValueType(0);
15718 auto *N0C = dyn_cast<ConstantSDNode>(N0);
15724 APInt ImmValMinus1 = N0C->getAPIntValue() - 1;
15734 if (!isIntEqualitySetCC(CCVal) || !SetCCOpVT.
isInteger())
15757 if (!Subtarget.hasStdExtZbb())
15760 EVT VT =
N->getValueType(0);
15762 if (VT != Subtarget.
getXLenVT() && VT != MVT::i32 && VT != MVT::i16)
15771 auto *ShAmtCLeft = dyn_cast<ConstantSDNode>(N0.
getOperand(1));
15774 unsigned ShiftedAmount = 8 - ShAmtCLeft->getZExtValue();
15776 if (ShiftedAmount >= 8)
15780 SDValue RightShiftOperand = N1;
15782 if (ShiftedAmount != 0) {
15785 auto *ShAmtCRight = dyn_cast<ConstantSDNode>(N1.
getOperand(1));
15786 if (!ShAmtCRight || ShAmtCRight->getZExtValue() != ShiftedAmount)
15795 if (LeftShiftOperand != RightShiftOperand)
15799 Mask <<= ShiftedAmount;
15805 return DAG.
getNode(RISCVISD::ORC_B,
SDLoc(
N), VT, LeftShiftOperand);
15813 EVT VT =
N->getValueType(0);
15844 bool IsAnd =
N->getOpcode() ==
ISD::AND;
15868 EVT VT =
N->getValueType(0);
15892 EVT VT =
N->getValueType(0);
15919 if (CondLHS != True)
15926 if (!CondRHSC || CondRHSC->
getAPIntValue() != (1ULL << ScalarBits))
15938 if (!FalseRHSC || !FalseRHSC->
isZero())
15958 EVT VT =
N->getValueType(0);
15965 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() && VT == MVT::i1 &&
16002 using namespace SDPatternMatch;
16008 EVT VT =
N->getValueType(0);
16027 EVT WideVT =
X.getValueType();
16059 ConstantSDNode *MaskConst = dyn_cast<ConstantSDNode>(
N->getOperand(1));
16064 if (Mask != ExpectedMask)
16090 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
16128 if (N0.
getOpcode() != RISCVISD::CZERO_EQZ ||
16129 N1.
getOpcode() != RISCVISD::CZERO_NEZ ||
16147 EVT VT =
N->getValueType(0);
16194 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
16209 if (N0.
getOpcode() == RISCVISD::SLLW &&
16213 return DAG.
getNode(RISCVISD::ROLW,
DL, MVT::i64,
16219 auto *ConstN00 = dyn_cast<ConstantSDNode>(N0.
getOperand(0));
16224 const APInt &Imm = ConstN00->getAPIntValue();
16225 if ((Imm + 1).isSignedIntN(12))
16246 EVT VT =
N->getValueType(0);
16253 for (
uint64_t E = MulAmt,
I = 0; E && I < BitWidth; ++I, E >>= 1) {
16255 bool IsAdd = (E & 3) == 1;
16256 E -= IsAdd ? 1 : -1;
16260 Result = DAG.
getNode(AddSubOp,
DL, VT, Result, ShiftVal);
16270 uint64_t MulAmtLowBit = MulAmt & (-MulAmt);
16275 ShiftAmt1 = MulAmt + MulAmtLowBit;
16278 ShiftAmt1 = MulAmt - MulAmtLowBit;
16282 EVT VT =
N->getValueType(0);
16296 EVT VT =
N->getValueType(0);
16305 bool ShouldExpandMul =
16307 !Subtarget.hasStdExtZmmul();
16308 if (!ShouldExpandMul)
16317 if (Subtarget.hasVendorXqciac() && isInt<12>(CNode->
getSExtValue()))
16320 const bool HasShlAdd = Subtarget.hasStdExtZba() ||
16321 Subtarget.hasVendorXTHeadBa() ||
16322 Subtarget.hasVendorXAndesPerf();
16331 for (
uint64_t Divisor : {3, 5, 9}) {
16332 if (MulAmt % Divisor != 0)
16334 uint64_t MulAmt2 = MulAmt / Divisor;
16341 if (
X.getOpcode() ==
ISD::AND && isa<ConstantSDNode>(
X.getOperand(1)) &&
16342 X.getConstantOperandVal(1) == UINT64_C(0xffffffff)) {
16345 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, Shl,
16359 if (MulAmt2 == 3 || MulAmt2 == 5 || MulAmt2 == 9) {
16364 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, Mul359,
16375 if (ScaleShift >= 1 && ScaleShift < 4) {
16376 unsigned ShiftAmt =
Log2_64((MulAmt & (MulAmt - 1)));
16380 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT,
X,
16390 for (
uint64_t Divisor : {3, 5, 9}) {
16395 if ((
C >> TZ) == Divisor && (TZ == 1 || TZ == 2 || TZ == 3)) {
16400 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, Mul359,
16406 if (MulAmt > 2 &&
isPowerOf2_64((MulAmt - 1) & (MulAmt - 2))) {
16408 if (ScaleShift >= 1 && ScaleShift < 4) {
16409 unsigned ShiftAmt =
Log2_64(((MulAmt - 1) & (MulAmt - 2)));
16435 for (
uint64_t Divisor : {3, 5, 9}) {
16436 if (MulAmt % Divisor != 0)
16438 uint64_t MulAmt2 = MulAmt / Divisor;
16441 for (
uint64_t Divisor2 : {3, 5, 9}) {
16442 if (MulAmt2 % Divisor2 != 0)
16444 uint64_t MulAmt3 = MulAmt2 / Divisor2;
16451 RISCVISD::SHL_ADD,
DL, VT, Mul359A,
16463 if (!Subtarget.hasStdExtZmmul())
16473 EVT VT =
N->getValueType(0);
16480 if (
N->getOperand(0).getOpcode() !=
ISD::AND ||
16481 N->getOperand(0).getOperand(0).getOpcode() !=
ISD::SRL)
16494 if (!V1.
isMask(HalfSize) || V2 != (1ULL | 1ULL << HalfSize) ||
16495 V3 != (HalfSize - 1))
16511 EVT VT =
N->getValueType(0);
16519 unsigned AddSubOpc;
16525 auto IsAddSubWith1 = [&](
SDValue V) ->
bool {
16526 AddSubOpc = V->getOpcode();
16528 SDValue Opnd = V->getOperand(1);
16529 MulOper = V->getOperand(0);
16538 if (IsAddSubWith1(N0)) {
16540 return DAG.
getNode(AddSubOpc,
DL, VT, N1, MulVal);
16543 if (IsAddSubWith1(N1)) {
16545 return DAG.
getNode(AddSubOpc,
DL, VT, N0, MulVal);
16560 if (isIndexTypeSigned(IndexType))
16563 if (!
N->hasOneUse())
16566 EVT VT =
N.getValueType();
16605 EVT SrcVT = Src.getValueType();
16609 NewElen = std::max(NewElen, 8U);
16636 EVT OpVT =
X.getValueType();
16644 if (OpSize <= Subtarget.
getXLen() ||
16650 auto IsVectorBitCastCheap = [](
SDValue X) {
16652 return isa<ConstantSDNode>(
X) ||
X.getValueType().isVector() ||
16655 if (!IsVectorBitCastCheap(
X) || !IsVectorBitCastCheap(
Y))
16659 Attribute::NoImplicitFloat))
16666 unsigned VecSize = OpSize / 8;
16678 DAG.
getNode(ISD::VP_REDUCE_OR,
DL, XLenVT,
16695 EVT VT =
N->getValueType(0);
16700 if (!isIntEqualitySetCC(
Cond))
16711 const APInt &AndRHSC =
16712 cast<ConstantSDNode>(N0.
getOperand(1))->getAPIntValue();
16721 if (OpVT != MVT::i64 || !Subtarget.
is64Bit())
16725 auto *N1C = dyn_cast<ConstantSDNode>(N1);
16741 const APInt &C1 = N1C->getAPIntValue();
16759 EVT VT =
N->getValueType(0);
16760 EVT SrcVT = cast<VTSDNode>(
N->getOperand(1))->
getVT();
16761 unsigned Opc = Src.getOpcode();
16766 if (
Opc == RISCVISD::FMV_X_ANYEXTH && SrcVT.
bitsGE(MVT::i16) &&
16767 Subtarget.hasStdExtZfhmin())
16768 return DAG.
getNode(RISCVISD::FMV_X_SIGNEXTH,
DL, VT, Src.getOperand(0));
16772 VT == MVT::i64 && !isa<ConstantSDNode>(Src.getOperand(1)) &&
16774 return DAG.
getNode(RISCVISD::SLLW,
DL, VT, Src.getOperand(0),
16775 Src.getOperand(1));
16794struct CombineResult;
16828struct NodeExtensionHelper {
16837 bool SupportsFPExt;
16839 bool SupportsBF16Ext;
16842 bool EnforceOneUse;
16852 case RISCVISD::VSEXT_VL:
16853 case RISCVISD::VZEXT_VL:
16854 case RISCVISD::FP_EXTEND_VL:
16857 return OrigOperand;
16863 return OrigOperand.
getOpcode() == RISCVISD::VMV_V_X_VL ||
16868 unsigned getExtOpc(ExtKind SupportsExt)
const {
16869 switch (SupportsExt) {
16870 case ExtKind::SExt:
16871 return RISCVISD::VSEXT_VL;
16872 case ExtKind::ZExt:
16873 return RISCVISD::VZEXT_VL;
16874 case ExtKind::FPExt:
16875 case ExtKind::BF16Ext:
16876 return RISCVISD::FP_EXTEND_VL;
16886 std::optional<ExtKind> SupportsExt)
const {
16887 if (!SupportsExt.has_value())
16888 return OrigOperand;
16890 MVT NarrowVT = getNarrowType(Root, *SupportsExt);
16894 if (
Source.getValueType() == NarrowVT)
16897 unsigned ExtOpc = getExtOpc(*SupportsExt);
16901 auto [
Mask, VL] = getMaskAndVL(Root, DAG, Subtarget);
16905 case RISCVISD::VSEXT_VL:
16906 case RISCVISD::VZEXT_VL:
16907 case RISCVISD::FP_EXTEND_VL:
16908 return DAG.
getNode(ExtOpc,
DL, NarrowVT, Source, Mask, VL);
16911 case RISCVISD::VMV_V_X_VL:
16912 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, NarrowVT,
16914 case RISCVISD::VFMV_V_F_VL:
16919 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL, NarrowVT,
16920 DAG.
getUNDEF(NarrowVT), Source, VL);
16933 static MVT getNarrowType(
const SDNode *Root, ExtKind SupportsExt) {
16939 MVT EltVT = SupportsExt == ExtKind::BF16Ext ? MVT::bf16
16940 : SupportsExt == ExtKind::FPExt
16942 :
MVT::getIntegerVT(NarrowSize);
16944 assert((
int)NarrowSize >= (SupportsExt == ExtKind::FPExt ? 16 : 8) &&
16945 "Trying to extend something we can't represent");
16952 static unsigned getSExtOpcode(
unsigned Opcode) {
16955 case RISCVISD::ADD_VL:
16956 case RISCVISD::VWADD_W_VL:
16957 case RISCVISD::VWADDU_W_VL:
16959 case RISCVISD::OR_VL:
16960 return RISCVISD::VWADD_VL;
16962 case RISCVISD::SUB_VL:
16963 case RISCVISD::VWSUB_W_VL:
16964 case RISCVISD::VWSUBU_W_VL:
16965 return RISCVISD::VWSUB_VL;
16967 case RISCVISD::MUL_VL:
16968 return RISCVISD::VWMUL_VL;
16976 static unsigned getZExtOpcode(
unsigned Opcode) {
16979 case RISCVISD::ADD_VL:
16980 case RISCVISD::VWADD_W_VL:
16981 case RISCVISD::VWADDU_W_VL:
16983 case RISCVISD::OR_VL:
16984 return RISCVISD::VWADDU_VL;
16986 case RISCVISD::SUB_VL:
16987 case RISCVISD::VWSUB_W_VL:
16988 case RISCVISD::VWSUBU_W_VL:
16989 return RISCVISD::VWSUBU_VL;
16991 case RISCVISD::MUL_VL:
16992 return RISCVISD::VWMULU_VL;
16994 case RISCVISD::SHL_VL:
16995 return RISCVISD::VWSLL_VL;
17003 static unsigned getFPExtOpcode(
unsigned Opcode) {
17005 case RISCVISD::FADD_VL:
17006 case RISCVISD::VFWADD_W_VL:
17007 return RISCVISD::VFWADD_VL;
17008 case RISCVISD::FSUB_VL:
17009 case RISCVISD::VFWSUB_W_VL:
17010 return RISCVISD::VFWSUB_VL;
17011 case RISCVISD::FMUL_VL:
17012 return RISCVISD::VFWMUL_VL;
17013 case RISCVISD::VFMADD_VL:
17014 return RISCVISD::VFWMADD_VL;
17015 case RISCVISD::VFMSUB_VL:
17016 return RISCVISD::VFWMSUB_VL;
17017 case RISCVISD::VFNMADD_VL:
17018 return RISCVISD::VFWNMADD_VL;
17019 case RISCVISD::VFNMSUB_VL:
17020 return RISCVISD::VFWNMSUB_VL;
17028 static unsigned getSUOpcode(
unsigned Opcode) {
17030 "SU is only supported for MUL");
17031 return RISCVISD::VWMULSU_VL;
17036 static unsigned getWOpcode(
unsigned Opcode, ExtKind SupportsExt) {
17039 case RISCVISD::ADD_VL:
17041 case RISCVISD::OR_VL:
17042 return SupportsExt == ExtKind::SExt ? RISCVISD::VWADD_W_VL
17043 : RISCVISD::VWADDU_W_VL;
17045 case RISCVISD::SUB_VL:
17046 return SupportsExt == ExtKind::SExt ? RISCVISD::VWSUB_W_VL
17047 : RISCVISD::VWSUBU_W_VL;
17048 case RISCVISD::FADD_VL:
17049 return RISCVISD::VFWADD_W_VL;
17050 case RISCVISD::FSUB_VL:
17051 return RISCVISD::VFWSUB_W_VL;
17057 using CombineToTry = std::function<std::optional<CombineResult>(
17058 SDNode * ,
const NodeExtensionHelper & ,
17063 bool needToPromoteOtherUsers()
const {
return EnforceOneUse; }
17071 "Unexpected Opcode");
17084 unsigned ScalarBits =
Op.getValueSizeInBits();
17086 if (ScalarBits < EltBits) {
17088 assert(
Opc == RISCVISD::VMV_V_X_VL && EltBits == 64 && ScalarBits == 32 &&
17089 !Subtarget.
is64Bit() &&
"Unexpected splat");
17091 SupportsSExt =
true;
17095 SupportsZExt =
true;
17097 EnforceOneUse =
false;
17101 unsigned NarrowSize = EltBits / 2;
17104 if (NarrowSize < 8)
17108 SupportsSExt =
true;
17112 SupportsZExt =
true;
17114 EnforceOneUse =
false;
17118 return (NarrowEltVT == MVT::f32 ||
17123 return NarrowEltVT == MVT::bf16 && Subtarget.hasStdExtZvfbfwma();
17130 SupportsZExt =
false;
17131 SupportsSExt =
false;
17132 SupportsFPExt =
false;
17133 SupportsBF16Ext =
false;
17134 EnforceOneUse =
true;
17156 case RISCVISD::VZEXT_VL:
17157 SupportsZExt =
true;
17159 case RISCVISD::VSEXT_VL:
17160 SupportsSExt =
true;
17162 case RISCVISD::FP_EXTEND_VL: {
17165 if (isSupportedFPExtend(NarrowEltVT, Subtarget))
17166 SupportsFPExt =
true;
17167 if (isSupportedBF16Extend(NarrowEltVT, Subtarget))
17168 SupportsBF16Ext =
true;
17173 case RISCVISD::VMV_V_X_VL:
17174 fillUpExtensionSupportForSplat(Root, DAG, Subtarget);
17176 case RISCVISD::VFMV_V_F_VL: {
17187 unsigned ScalarBits =
Op.getOperand(0).getValueSizeInBits();
17188 if (NarrowSize != ScalarBits)
17191 if (isSupportedFPExtend(
Op.getOperand(0).getSimpleValueType(), Subtarget))
17192 SupportsFPExt =
true;
17193 if (isSupportedBF16Extend(
Op.getOperand(0).getSimpleValueType(),
17195 SupportsBF16Ext =
true;
17204 static bool isSupportedRoot(
const SDNode *Root,
17217 case RISCVISD::ADD_VL:
17218 case RISCVISD::MUL_VL:
17219 case RISCVISD::VWADD_W_VL:
17220 case RISCVISD::VWADDU_W_VL:
17221 case RISCVISD::SUB_VL:
17222 case RISCVISD::VWSUB_W_VL:
17223 case RISCVISD::VWSUBU_W_VL:
17225 case RISCVISD::FADD_VL:
17226 case RISCVISD::FSUB_VL:
17227 case RISCVISD::FMUL_VL:
17228 case RISCVISD::VFWADD_W_VL:
17229 case RISCVISD::VFWSUB_W_VL:
17231 case RISCVISD::OR_VL:
17235 Subtarget.hasStdExtZvbb();
17236 case RISCVISD::SHL_VL:
17237 return Subtarget.hasStdExtZvbb();
17238 case RISCVISD::VFMADD_VL:
17239 case RISCVISD::VFNMSUB_VL:
17240 case RISCVISD::VFNMADD_VL:
17241 case RISCVISD::VFMSUB_VL:
17251 assert(isSupportedRoot(Root, Subtarget) &&
17252 "Trying to build an helper with an "
17253 "unsupported root");
17254 assert(OperandIdx < 2 &&
"Requesting something else than LHS or RHS");
17264 case RISCVISD::VWADD_W_VL:
17265 case RISCVISD::VWADDU_W_VL:
17266 case RISCVISD::VWSUB_W_VL:
17267 case RISCVISD::VWSUBU_W_VL:
17268 case RISCVISD::VFWADD_W_VL:
17269 case RISCVISD::VFWSUB_W_VL:
17270 if (OperandIdx == 1) {
17272 Opc == RISCVISD::VWADDU_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL;
17274 Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWSUB_W_VL;
17276 Opc == RISCVISD::VFWADD_W_VL ||
Opc == RISCVISD::VFWSUB_W_VL;
17279 EnforceOneUse =
false;
17284 fillUpExtensionSupport(Root, DAG, Subtarget);
17290 static std::pair<SDValue, SDValue>
17293 assert(isSupportedRoot(Root, Subtarget) &&
"Unexpected root");
17312 switch (
N->getOpcode()) {
17316 case RISCVISD::ADD_VL:
17317 case RISCVISD::MUL_VL:
17318 case RISCVISD::OR_VL:
17319 case RISCVISD::VWADD_W_VL:
17320 case RISCVISD::VWADDU_W_VL:
17321 case RISCVISD::FADD_VL:
17322 case RISCVISD::FMUL_VL:
17323 case RISCVISD::VFWADD_W_VL:
17324 case RISCVISD::VFMADD_VL:
17325 case RISCVISD::VFNMSUB_VL:
17326 case RISCVISD::VFNMADD_VL:
17327 case RISCVISD::VFMSUB_VL:
17330 case RISCVISD::SUB_VL:
17331 case RISCVISD::VWSUB_W_VL:
17332 case RISCVISD::VWSUBU_W_VL:
17333 case RISCVISD::FSUB_VL:
17334 case RISCVISD::VFWSUB_W_VL:
17336 case RISCVISD::SHL_VL:
17355struct CombineResult {
17357 unsigned TargetOpcode;
17359 std::optional<ExtKind> LHSExt;
17360 std::optional<ExtKind> RHSExt;
17364 NodeExtensionHelper
LHS;
17366 NodeExtensionHelper
RHS;
17368 CombineResult(
unsigned TargetOpcode,
SDNode *Root,
17369 const NodeExtensionHelper &
LHS, std::optional<ExtKind> LHSExt,
17370 const NodeExtensionHelper &
RHS, std::optional<ExtKind> RHSExt)
17371 : TargetOpcode(TargetOpcode), LHSExt(LHSExt), RHSExt(RHSExt), Root(Root),
17380 std::tie(Mask, VL) =
17381 NodeExtensionHelper::getMaskAndVL(Root, DAG, Subtarget);
17395 LHS.getOrCreateExtendedOp(Root, DAG, Subtarget, LHSExt),
17396 RHS.getOrCreateExtendedOp(Root, DAG, Subtarget, RHSExt),
17397 Passthru, Mask, VL);
17411static std::optional<CombineResult>
17412canFoldToVWWithSameExtensionImpl(
SDNode *Root,
const NodeExtensionHelper &LHS,
17413 const NodeExtensionHelper &RHS,
17416 if ((AllowExtMask & ExtKind::ZExt) &&
LHS.SupportsZExt &&
RHS.SupportsZExt)
17417 return CombineResult(NodeExtensionHelper::getZExtOpcode(Root->
getOpcode()),
17418 Root, LHS, {ExtKind::ZExt}, RHS,
17420 if ((AllowExtMask & ExtKind::SExt) &&
LHS.SupportsSExt &&
RHS.SupportsSExt)
17421 return CombineResult(NodeExtensionHelper::getSExtOpcode(Root->
getOpcode()),
17422 Root, LHS, {ExtKind::SExt}, RHS,
17424 if ((AllowExtMask & ExtKind::FPExt) &&
LHS.SupportsFPExt &&
RHS.SupportsFPExt)
17425 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
17426 Root, LHS, {ExtKind::FPExt}, RHS,
17428 if ((AllowExtMask & ExtKind::BF16Ext) &&
LHS.SupportsBF16Ext &&
17429 RHS.SupportsBF16Ext)
17430 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
17431 Root, LHS, {ExtKind::BF16Ext}, RHS,
17432 {ExtKind::BF16Ext});
17433 return std::nullopt;
17442static std::optional<CombineResult>
17443canFoldToVWWithSameExtension(
SDNode *Root,
const NodeExtensionHelper &LHS,
17446 return canFoldToVWWithSameExtensionImpl(
17447 Root, LHS, RHS, ExtKind::ZExt | ExtKind::SExt | ExtKind::FPExt, DAG,
17455static std::optional<CombineResult>
17456canFoldToVW_W(
SDNode *Root,
const NodeExtensionHelper &LHS,
17459 if (
RHS.SupportsFPExt)
17460 return CombineResult(
17461 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::FPExt),
17462 Root, LHS, std::nullopt, RHS, {ExtKind::FPExt});
17469 return CombineResult(
17470 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::ZExt), Root,
17471 LHS, std::nullopt, RHS, {ExtKind::ZExt});
17473 return CombineResult(
17474 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::SExt), Root,
17475 LHS, std::nullopt, RHS, {ExtKind::SExt});
17476 return std::nullopt;
17483static std::optional<CombineResult>
17484canFoldToVWWithSEXT(
SDNode *Root,
const NodeExtensionHelper &LHS,
17487 return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::SExt, DAG,
17495static std::optional<CombineResult>
17496canFoldToVWWithZEXT(
SDNode *Root,
const NodeExtensionHelper &LHS,
17499 return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::ZExt, DAG,
17507static std::optional<CombineResult>
17508canFoldToVWWithFPEXT(
SDNode *Root,
const NodeExtensionHelper &LHS,
17511 return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::FPExt, DAG,
17519static std::optional<CombineResult>
17520canFoldToVWWithBF16EXT(
SDNode *Root,
const NodeExtensionHelper &LHS,
17523 return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::BF16Ext, DAG,
17531static std::optional<CombineResult>
17532canFoldToVW_SU(
SDNode *Root,
const NodeExtensionHelper &LHS,
17536 if (!
LHS.SupportsSExt || !
RHS.SupportsZExt)
17537 return std::nullopt;
17538 return CombineResult(NodeExtensionHelper::getSUOpcode(Root->
getOpcode()),
17539 Root, LHS, {ExtKind::SExt}, RHS,
17544NodeExtensionHelper::getSupportedFoldings(
const SDNode *Root) {
17550 case RISCVISD::ADD_VL:
17551 case RISCVISD::SUB_VL:
17552 case RISCVISD::OR_VL:
17553 case RISCVISD::FADD_VL:
17554 case RISCVISD::FSUB_VL:
17556 Strategies.
push_back(canFoldToVWWithSameExtension);
17560 case RISCVISD::FMUL_VL:
17561 case RISCVISD::VFMADD_VL:
17562 case RISCVISD::VFMSUB_VL:
17563 case RISCVISD::VFNMADD_VL:
17564 case RISCVISD::VFNMSUB_VL:
17565 Strategies.
push_back(canFoldToVWWithSameExtension);
17566 if (Root->
getOpcode() == RISCVISD::VFMADD_VL)
17567 Strategies.
push_back(canFoldToVWWithBF16EXT);
17570 case RISCVISD::MUL_VL:
17572 Strategies.
push_back(canFoldToVWWithSameExtension);
17577 case RISCVISD::SHL_VL:
17579 Strategies.
push_back(canFoldToVWWithZEXT);
17581 case RISCVISD::VWADD_W_VL:
17582 case RISCVISD::VWSUB_W_VL:
17584 Strategies.
push_back(canFoldToVWWithSEXT);
17586 case RISCVISD::VWADDU_W_VL:
17587 case RISCVISD::VWSUBU_W_VL:
17589 Strategies.
push_back(canFoldToVWWithZEXT);
17591 case RISCVISD::VFWADD_W_VL:
17592 case RISCVISD::VFWSUB_W_VL:
17594 Strategies.
push_back(canFoldToVWWithFPEXT);
17605 assert(
N->getOpcode() == RISCVISD::ADD_VL);
17608 SDValue Passthru =
N->getOperand(2);
17642 if (!NodeExtensionHelper::isSupportedRoot(
N, Subtarget))
17648 Inserted.insert(
N);
17651 while (!Worklist.
empty()) {
17654 NodeExtensionHelper
LHS(Root, 0, DAG, Subtarget);
17655 NodeExtensionHelper
RHS(Root, 1, DAG, Subtarget);
17656 auto AppendUsersIfNeeded = [&Worklist, &Subtarget,
17657 &Inserted](
const NodeExtensionHelper &
Op) {
17658 if (
Op.needToPromoteOtherUsers()) {
17661 if (!NodeExtensionHelper::isSupportedRoot(TheUser, Subtarget))
17666 if (Inserted.insert(TheUser).second)
17679 NodeExtensionHelper::getSupportedFoldings(Root);
17681 assert(!FoldingStrategies.
empty() &&
"Nothing to be folded");
17682 bool Matched =
false;
17683 for (
int Attempt = 0;
17684 (Attempt != 1 + NodeExtensionHelper::isCommutative(Root)) && !Matched;
17687 for (NodeExtensionHelper::CombineToTry FoldingStrategy :
17688 FoldingStrategies) {
17689 std::optional<CombineResult> Res =
17690 FoldingStrategy(Root,
LHS,
RHS, DAG, Subtarget);
17697 if (Res->LHSExt.has_value())
17698 if (!AppendUsersIfNeeded(
LHS))
17700 if (Res->RHSExt.has_value())
17701 if (!AppendUsersIfNeeded(
RHS))
17713 SDValue InputRootReplacement;
17720 for (CombineResult Res : CombinesToApply) {
17721 SDValue NewValue = Res.materialize(DAG, Subtarget);
17722 if (!InputRootReplacement) {
17724 "First element is expected to be the current node");
17725 InputRootReplacement = NewValue;
17730 for (std::pair<SDValue, SDValue> OldNewValues : ValuesToReplace) {
17734 return InputRootReplacement;
17741 unsigned Opc =
N->getOpcode();
17742 assert(
Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWADDU_W_VL ||
17743 Opc == RISCVISD::VWSUB_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL);
17746 SDValue MergeOp =
N->getOperand(1);
17747 unsigned MergeOpc = MergeOp.
getOpcode();
17749 if (MergeOpc != RISCVISD::VMERGE_VL && MergeOpc !=
ISD::VSELECT)
17758 SDValue Passthru =
N->getOperand(2);
17764 if (Mask.getOpcode() != RISCVISD::VMSET_VL)
17772 Z = Z.getOperand(1);
17778 {Y, X, Y, MergeOp->getOperand(0), N->getOperand(4)},
17785 [[maybe_unused]]
unsigned Opc =
N->getOpcode();
17786 assert(
Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWADDU_W_VL ||
17787 Opc == RISCVISD::VWSUB_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL);
17814 EVT NewMemVT = (MemVT == MVT::i32) ? MVT::i64 : MVT::i128;
17820 auto Ext = cast<LoadSDNode>(LSNode1)->getExtensionType();
17822 if (MemVT == MVT::i32)
17823 Opcode = (Ext ==
ISD::ZEXTLOAD) ? RISCVISD::TH_LWUD : RISCVISD::TH_LWD;
17825 Opcode = RISCVISD::TH_LDD;
17828 Opcode,
SDLoc(LSNode1), DAG.
getVTList({XLenVT, XLenVT, MVT::Other}),
17841 unsigned Opcode = (MemVT == MVT::i32) ? RISCVISD::TH_SWD : RISCVISD::TH_SDD;
17863 if (!Subtarget.hasVendorXTHeadMemPair())
17875 auto ExtractBaseAndOffset = [](
SDValue Ptr) -> std::pair<SDValue, uint64_t> {
17877 if (
auto *C1 = dyn_cast<ConstantSDNode>(
Ptr->getOperand(1)))
17878 return {
Ptr->getOperand(0), C1->getZExtValue()};
17882 auto [Base1, Offset1] = ExtractBaseAndOffset(LSNode1->
getOperand(OpNum));
17903 auto [Base2, Offset2] = ExtractBaseAndOffset(LSNode2->
getOperand(OpNum));
17906 if (Base1 != Base2)
17910 bool Valid =
false;
17911 if (MemVT == MVT::i32) {
17913 if ((Offset1 + 4 == Offset2) && isShiftedUInt<2, 3>(Offset1))
17915 }
else if (MemVT == MVT::i64) {
17917 if ((Offset1 + 8 == Offset2) && isShiftedUInt<2, 4>(Offset1))
17951 if (Src->isStrictFPOpcode())
17959 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
17969 EVT VT =
N->getValueType(0);
17972 MVT SrcVT = Src.getSimpleValueType();
17973 MVT SrcContainerVT = SrcVT;
17975 SDValue XVal = Src.getOperand(0);
18001 IsSigned ? RISCVISD::VFCVT_RTZ_X_F_VL : RISCVISD::VFCVT_RTZ_XU_F_VL;
18002 FpToInt = DAG.
getNode(
Opc,
DL, ContainerVT, XVal, Mask, VL);
18005 IsSigned ? RISCVISD::VFCVT_RM_X_F_VL : RISCVISD::VFCVT_RM_XU_F_VL;
18006 FpToInt = DAG.
getNode(
Opc,
DL, ContainerVT, XVal, Mask,
18019 if (VT != MVT::i32 && VT != XLenVT)
18024 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
18026 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
18049 EVT DstVT =
N->getValueType(0);
18050 if (DstVT != XLenVT)
18056 if (Src->isStrictFPOpcode())
18064 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
18067 EVT SatVT = cast<VTSDNode>(
N->getOperand(1))->getVT();
18076 if (SatVT == DstVT)
18077 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
18078 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
18079 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
18084 Src = Src.getOperand(0);
18092 if (
Opc == RISCVISD::FCVT_WU_RV64)
18105 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected extension");
18111 EVT VT =
N->getValueType(0);
18117 return DAG.
getNode(RISCVISD::BREV8,
DL, VT, Src.getOperand(0));
18126 auto *VPLoad = dyn_cast<VPLoadSDNode>(
N->getOperand(0));
18130 EVT LoadVT = VPLoad->getValueType(0);
18134 N->getOperand(2) != VPLoad->getVectorLength() ||
18135 !
N->getOperand(0).hasOneUse())
18142 SDValue LoadMask = VPLoad->getMask();
18147 if (LoadMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
18149 LoadMask.
getOperand(2) != VPLoad->getVectorLength())
18157 SDValue NumElem = VPLoad->getVectorLength();
18158 uint64_t ElemWidthByte = VPLoad->getValueType(0).getScalarSizeInBits() / 8;
18170 PtrInfo, VPLoad->getMemOperand()->getFlags(),
18174 LoadVT,
DL, VPLoad->getChain(),
Base, Stride, LoadMask,
18175 VPLoad->getVectorLength(), MMO, VPLoad->isExpandingLoad());
18187 auto *VPStore = cast<VPStoreSDNode>(
N);
18189 if (VPStore->getValue().getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE)
18192 SDValue VPReverse = VPStore->getValue();
18198 VPStore->getVectorLength() != VPReverse.
getOperand(2) ||
18202 SDValue StoreMask = VPStore->getMask();
18207 if (StoreMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
18209 StoreMask.
getOperand(2) != VPStore->getVectorLength())
18217 SDValue NumElem = VPStore->getVectorLength();
18231 PtrInfo, VPStore->getMemOperand()->getFlags(),
18236 VPStore->getOffset(), Stride, StoreMask, VPStore->getVectorLength(),
18237 VPStore->getMemoryVT(), MMO, VPStore->getAddressingMode(),
18238 VPStore->isTruncatingStore(), VPStore->isCompressingStore());
18250 EVT VT =
N->getValueType(0);
18262 if (In.getOpcode() != ISD::VP_SRL || In.getOperand(2) != Mask ||
18263 In.getOperand(3) != VL)
18272 if (
LHS.getOpcode() != ISD::VP_ADD ||
LHS.getOperand(2) != Mask ||
18273 LHS.getOperand(3) != VL)
18280 if (V.getOpcode() != ISD::VP_ADD || V.getOperand(2) != Mask ||
18281 V.getOperand(3) != VL)
18293 if (!FindAdd(LHS0, LHS1) && !FindAdd(LHS1, LHS0))
18307 if (
Op.getOpcode() != ISD::VP_ZERO_EXTEND ||
Op.getOperand(1) != Mask ||
18308 Op.getOperand(2) != VL)
18318 Operands[0].getOperand(0), Mask, VL);
18320 Operands[1].getOperand(0), Mask, VL);
18324 return DAG.
getNode(RISCVISD::AVGCEILU_VL,
DL, VT,
18325 {NewOp0, NewOp1, DAG.
getUNDEF(VT), Mask, VL});
18337 case RISCVISD::VFMADD_VL: Opcode = RISCVISD::VFNMSUB_VL;
break;
18338 case RISCVISD::VFNMSUB_VL: Opcode = RISCVISD::VFMADD_VL;
break;
18339 case RISCVISD::VFNMADD_VL: Opcode = RISCVISD::VFMSUB_VL;
break;
18340 case RISCVISD::VFMSUB_VL: Opcode = RISCVISD::VFNMADD_VL;
break;
18341 case RISCVISD::STRICT_VFMADD_VL: Opcode = RISCVISD::STRICT_VFNMSUB_VL;
break;
18342 case RISCVISD::STRICT_VFNMSUB_VL: Opcode = RISCVISD::STRICT_VFMADD_VL;
break;
18343 case RISCVISD::STRICT_VFNMADD_VL: Opcode = RISCVISD::STRICT_VFMSUB_VL;
break;
18344 case RISCVISD::STRICT_VFMSUB_VL: Opcode = RISCVISD::STRICT_VFNMADD_VL;
break;
18354 case RISCVISD::VFMADD_VL: Opcode = RISCVISD::VFMSUB_VL;
break;
18355 case RISCVISD::VFMSUB_VL: Opcode = RISCVISD::VFMADD_VL;
break;
18356 case RISCVISD::VFNMADD_VL: Opcode = RISCVISD::VFNMSUB_VL;
break;
18357 case RISCVISD::VFNMSUB_VL: Opcode = RISCVISD::VFNMADD_VL;
break;
18358 case RISCVISD::STRICT_VFMADD_VL: Opcode = RISCVISD::STRICT_VFMSUB_VL;
break;
18359 case RISCVISD::STRICT_VFMSUB_VL: Opcode = RISCVISD::STRICT_VFMADD_VL;
break;
18360 case RISCVISD::STRICT_VFNMADD_VL: Opcode = RISCVISD::STRICT_VFNMSUB_VL;
break;
18361 case RISCVISD::STRICT_VFNMSUB_VL: Opcode = RISCVISD::STRICT_VFNMADD_VL;
break;
18374 unsigned Offset = IsStrict ? 1 : 0;
18381 auto invertIfNegative = [&Mask, &VL](
SDValue &V) {
18382 if (V.getOpcode() == RISCVISD::FNEG_VL && V.getOperand(1) == Mask &&
18383 V.getOperand(2) == VL) {
18385 V = V.getOperand(0);
18392 bool NegA = invertIfNegative(
A);
18393 bool NegB = invertIfNegative(
B);
18394 bool NegC = invertIfNegative(
C);
18397 if (!NegA && !NegB && !NegC)
18403 {N->getOperand(0), A, B, C, Mask, VL});
18427 EVT VT =
N->getValueType(0);
18432 if (!isa<ConstantSDNode>(
N->getOperand(1)))
18434 uint64_t ShAmt =
N->getConstantOperandVal(1);
18442 cast<VTSDNode>(N0.
getOperand(1))->getVT().getSizeInBits();
18447 if (LShAmt < ExtSize) {
18460 if (ShAmt > 32 || VT != MVT::i64)
18476 AddC = dyn_cast<ConstantSDNode>(N0.
getOperand(IsAdd ? 1 : 0));
18489 !isa<ConstantSDNode>(U->getOperand(1)) ||
18490 U->getConstantOperandVal(1) > 32)
18545 if (!
Cond.hasOneUse())
18564 EVT VT =
Cond.getValueType();
18609 LHS =
LHS.getOperand(0);
18619 LHS.getOperand(0).getValueType() == Subtarget.
getXLenVT()) {
18623 CCVal = cast<CondCodeSDNode>(
LHS.getOperand(2))->get();
18627 RHS =
LHS.getOperand(1);
18628 LHS =
LHS.getOperand(0);
18637 auto isXorImmediate = [](
const SDValue &
Op) ->
bool {
18638 if (
const auto *XorCnst = dyn_cast<ConstantSDNode>(
Op))
18639 return isInt<12>(XorCnst->getSExtValue());
18643 auto singleBitOp = [&DAG](
const SDValue &VarOp,
18644 const SDValue &ConstOp) ->
bool {
18645 if (
const auto *XorCnst = dyn_cast<ConstantSDNode>(ConstOp)) {
18647 return (XorCnst->getSExtValue() == 1) &&
18652 auto onlyUsedBySelectOrBR = [](
const SDValue &
Op) ->
bool {
18653 for (
const SDNode *UserNode :
Op->users()) {
18654 const unsigned Opcode = UserNode->getOpcode();
18655 if (Opcode != RISCVISD::SELECT_CC && Opcode != RISCVISD::BR_CC)
18660 auto isFoldableXorEq = [isXorImmediate, singleBitOp, onlyUsedBySelectOrBR](
18663 (!isXorImmediate(
LHS.getOperand(1)) ||
18664 singleBitOp(
LHS.getOperand(0),
LHS.getOperand(1)) ||
18665 onlyUsedBySelectOrBR(
LHS));
18668 if (isFoldableXorEq(
LHS,
RHS)) {
18669 RHS =
LHS.getOperand(1);
18670 LHS =
LHS.getOperand(0);
18676 if (isFoldableXorEq(LHS0,
RHS) && isa<ConstantSDNode>(LHS0.
getOperand(1))) {
18696 if (Subtarget.hasVendorXAndesPerf()) {
18706 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
18749 bool Commutative =
true;
18750 unsigned Opc = TrueVal.getOpcode();
18760 Commutative =
false;
18768 if (!TrueVal.hasOneUse() || isa<ConstantSDNode>(FalseVal))
18772 if (FalseVal == TrueVal.getOperand(0))
18774 else if (Commutative && FalseVal == TrueVal.getOperand(1))
18779 EVT VT =
N->getValueType(0);
18781 SDValue OtherOp = TrueVal.getOperand(1 - OpToFold);
18787 assert(IdentityOperand &&
"No identity operand!");
18792 DAG.
getSelect(
DL, OtherOpVT,
N->getOperand(0), OtherOp, IdentityOperand);
18793 return DAG.
getNode(TrueVal.getOpcode(),
DL, VT, FalseVal, NewSel);
18814 CountZeroes =
N->getOperand(2);
18815 ValOnZero =
N->getOperand(1);
18817 CountZeroes =
N->getOperand(1);
18818 ValOnZero =
N->getOperand(2);
18837 if (
Cond->getOperand(0) != CountZeroesArgument)
18856 CountZeroes, BitWidthMinusOne);
18866 EVT VT =
N->getValueType(0);
18867 EVT CondVT =
Cond.getValueType();
18875 (Subtarget.hasStdExtZicond() || Subtarget.hasVendorXVentanaCondOps())) {
18881 const APInt &MaskVal =
LHS.getConstantOperandAPInt(1);
18892 if (!TrueVal.hasOneUse() || !FalseVal.hasOneUse())
18896 if (TrueVal.getOpcode() ==
ISD::SUB && FalseVal.getOpcode() ==
ISD::ADD) {
18904 SDValue A = FalseVal.getOperand(0);
18905 SDValue B = FalseVal.getOperand(1);
18907 return ((TrueVal.getOperand(0) ==
A && TrueVal.getOperand(1) ==
B) ||
18908 (TrueVal.getOperand(1) ==
A && TrueVal.getOperand(0) ==
B));
18916 EVT VT =
N->getValueType(0);
18918 SDValue TrueVal =
N->getOperand(1);
18919 SDValue FalseVal =
N->getOperand(2);
18949 SDValue TrueVal =
N->getOperand(1);
18950 SDValue FalseVal =
N->getOperand(2);
18965 EVT VT =
N->getValueType(0);
18972 const unsigned Opcode =
N->op_begin()->getNode()->getOpcode();
18987 if (
Op.isUndef()) {
19000 if (
Op.getOpcode() != Opcode || !
Op.hasOneUse())
19004 if (!isa<ConstantSDNode>(
Op.getOperand(1)) &&
19005 !isa<ConstantFPSDNode>(
Op.getOperand(1)))
19009 if (
Op.getOperand(0).getValueType() !=
Op.getOperand(1).getValueType())
19033 EVT AVT =
A.getValueType();
19034 EVT BVT =
B.getValueType();
19064 if (AOpt || BOpt) {
19082 EVT OpVT =
A.getValueType();
19107 EVT OpVT =
A.getOperand(0).getValueType();
19109 OpVT !=
B.getOperand(0).getValueType() ||
19138 if (!Subtarget.hasStdExtZvqdotq())
19142 EVT VT =
N->getValueType(0);
19167 const unsigned InVecOpcode = InVec->
getOpcode();
19177 if (!isa<ConstantSDNode>(InValRHS) && !isa<ConstantFPSDNode>(InValRHS))
19184 InVecLHS, InValLHS, EltNo);
19186 InVecRHS, InValRHS, EltNo);
19195 auto *IndexC = dyn_cast<ConstantSDNode>(EltNo);
19198 unsigned Elt = IndexC->getZExtValue();
19204 unsigned NewIdx = Elt % ConcatNumElts;
19206 unsigned ConcatOpIdx = Elt / ConcatNumElts;
19211 ConcatOps[ConcatOpIdx] = ConcatOp;
19223 EVT VT =
N->getValueType(0);
19233 auto *BaseLd = dyn_cast<LoadSDNode>(
N->getOperand(0));
19235 !
SDValue(BaseLd, 0).hasOneUse())
19238 EVT BaseLdVT = BaseLd->getValueType(0);
19245 auto *Ld = dyn_cast<LoadSDNode>(
Op);
19246 if (!Ld || !Ld->isSimple() || !
Op.hasOneUse() ||
19248 Ld->getValueType(0) != BaseLdVT)
19257 using PtrDiff = std::pair<std::variant<int64_t, SDValue>,
bool>;
19259 LoadSDNode *Ld2) -> std::optional<PtrDiff> {
19264 if (BIO1.equalBaseIndex(BIO2, DAG))
19269 SDValue P2 = Ld2->getBasePtr();
19272 if (P1.getOpcode() ==
ISD::ADD && P1.getOperand(0) == P2)
19273 return {{P1.getOperand(1),
true}};
19275 return std::nullopt;
19279 auto BaseDiff = GetPtrDiff(Lds[0], Lds[1]);
19284 for (
auto *It = Lds.
begin() + 1; It != Lds.
end() - 1; It++)
19285 if (GetPtrDiff(*It, *std::next(It)) != BaseDiff)
19293 unsigned WideScalarBitWidth =
19306 auto [StrideVariant, MustNegateStride] = *BaseDiff;
19308 std::holds_alternative<SDValue>(StrideVariant)
19309 ? std::get<SDValue>(StrideVariant)
19312 if (MustNegateStride)
19320 if (
auto *ConstStride = dyn_cast<ConstantSDNode>(Stride);
19321 ConstStride && ConstStride->getSExtValue() >= 0)
19325 ConstStride->getSExtValue() * (
N->getNumOperands() - 1);
19331 BaseLd->getPointerInfo(), BaseLd->getMemOperand()->getFlags(), MemSize,
19335 WideVecVT,
DL, BaseLd->getChain(), BaseLd->getBasePtr(), Stride,
19349 EVT VT =
N->getValueType(0);
19366 for (
int MaskIndex : Mask) {
19367 bool SelectMaskVal = (MaskIndex < (int)NumElts);
19370 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
19407 if (
N->getValueType(0).isFixedLengthVector())
19410 SDValue Addend =
N->getOperand(0);
19413 if (
N->getOpcode() == RISCVISD::ADD_VL) {
19414 SDValue AddPassthruOp =
N->getOperand(2);
19415 if (!AddPassthruOp.
isUndef())
19419 auto IsVWMulOpc = [](
unsigned Opc) {
19421 case RISCVISD::VWMUL_VL:
19422 case RISCVISD::VWMULU_VL:
19423 case RISCVISD::VWMULSU_VL:
19438 if (!MulPassthruOp.
isUndef())
19448 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
19449 }(
N, DAG, Subtarget);
19454 if (AddMask != MulMask || AddVL != MulVL)
19457 const auto &TSInfo =
19459 unsigned Opc = TSInfo.getMAccOpcode(MulOp.
getOpcode());
19462 EVT VT =
N->getValueType(0);
19473 if (!
N->getValueType(0).isVector())
19476 SDValue Addend =
N->getOperand(0);
19479 if (
N->getOpcode() == RISCVISD::ADD_VL) {
19480 SDValue AddPassthruOp =
N->getOperand(2);
19481 if (!AddPassthruOp.
isUndef())
19485 auto IsVqdotqOpc = [](
unsigned Opc) {
19487 case RISCVISD::VQDOT_VL:
19488 case RISCVISD::VQDOTU_VL:
19489 case RISCVISD::VQDOTSU_VL:
19509 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
19510 }(
N, DAG, Subtarget);
19513 if (AddVL != MulVL)
19516 if (AddMask.getOpcode() != RISCVISD::VMSET_VL ||
19517 AddMask.getOperand(0) != MulVL)
19522 EVT VT =
N->getValueType(0);
19523 Addend = DAG.
getNode(RISCVISD::ADD_VL,
DL, VT, Addend, AccumOp,
19524 DAG.
getUNDEF(VT), AddMask, AddVL);
19542 const EVT IndexVT = Index.getValueType();
19546 if (!isIndexTypeSigned(IndexType))
19578 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
19581 if (Index->getOperand(i)->isUndef())
19583 uint64_t C = Index->getConstantOperandVal(i);
19584 if (
C % ElementSize != 0)
19586 C =
C / ElementSize;
19590 ActiveLanes.
set(
C);
19592 return ActiveLanes.
all();
19610 if (NumElems % 2 != 0)
19614 const unsigned WiderElementSize = ElementSize * 2;
19615 if (WiderElementSize > ST.getELen()/8)
19618 if (!ST.enableUnalignedVectorMem() && BaseAlign < WiderElementSize)
19621 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
19624 if (Index->getOperand(i)->isUndef())
19628 uint64_t C = Index->getConstantOperandVal(i);
19630 if (
C % WiderElementSize != 0)
19635 if (
C !=
Last + ElementSize)
19652 (isa<RegisterSDNode>(VL) &&
19653 cast<RegisterSDNode>(VL)->getReg() == RISCV::X0);
19654 if (!IsVLMAX || Mask.getOpcode() != RISCVISD::VMSET_VL ||
19655 Mask.getOperand(0) != VL)
19658 auto IsTruncNode = [&](
SDValue V) {
19659 return V.getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL &&
19660 V.getOperand(1) == Mask && V.getOperand(2) == VL;
19667 while (IsTruncNode(
Op)) {
19668 if (!
Op.hasOneUse())
19670 Op =
Op.getOperand(0);
19703 assert(
N->getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL);
19705 MVT VT =
N->getSimpleValueType(0);
19710 auto MatchMinMax = [&VL, &Mask](
SDValue V,
unsigned Opc,
unsigned OpcVL,
19712 if (V.getOpcode() !=
Opc &&
19713 !(V.getOpcode() == OpcVL && V.getOperand(2).isUndef() &&
19714 V.getOperand(3) == Mask && V.getOperand(4) == VL))
19722 Op.getOperand(1).getValueType().isFixedLengthVector() &&
19724 Op.getOperand(1).getOperand(0).getValueType() ==
Op.getValueType() &&
19726 Op =
Op.getOperand(1).getOperand(0);
19729 return V.getOperand(0);
19731 if (
Op.getOpcode() == RISCVISD::VMV_V_X_VL &&
Op.getOperand(0).isUndef() &&
19732 Op.getOperand(2) == VL) {
19733 if (
auto *Op1 = dyn_cast<ConstantSDNode>(
Op.getOperand(1))) {
19735 Op1->getAPIntValue().sextOrTrunc(
Op.getScalarValueSizeInBits());
19736 return V.getOperand(0);
19745 auto DetectUSatPattern = [&](
SDValue V) {
19757 MatchMinMax(SMinOp,
ISD::SMAX, RISCVISD::SMAX_VL, LoC))
19766 MatchMinMax(SMaxOp,
ISD::SMIN, RISCVISD::SMIN_VL, HiC))
19769 return DAG.
getNode(RISCVISD::SMAX_VL,
DL, V.getValueType(), SMinOp,
19770 V.getOperand(1), DAG.
getUNDEF(V.getValueType()),
19776 auto DetectSSatPattern = [&](
SDValue V) {
19778 unsigned NumSrcBits = V.getScalarValueSizeInBits();
19785 MatchMinMax(SMinOp,
ISD::SMAX, RISCVISD::SMAX_VL, LoC))
19786 if (HiC == SignedMax && LoC == SignedMin)
19791 MatchMinMax(SMaxOp,
ISD::SMIN, RISCVISD::SMIN_VL, HiC))
19792 if (HiC == SignedMax && LoC == SignedMin)
19801 while (Src.getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL &&
19802 Src.getOperand(1) == Mask && Src.getOperand(2) == VL &&
19804 Src = Src.getOperand(0);
19808 if ((Val = DetectUSatPattern(Src)))
19809 ClipOpc = RISCVISD::TRUNCATE_VECTOR_VL_USAT;
19810 else if ((Val = DetectSSatPattern(Src)))
19811 ClipOpc = RISCVISD::TRUNCATE_VECTOR_VL_SSAT;
19820 Val = DAG.
getNode(ClipOpc,
DL, ValVT, Val, Mask, VL);
19821 }
while (ValVT != VT);
19839 unsigned Opc =
N->getOpcode();
19841 "Unexpected opcode");
19842 EVT VT =
N->getValueType(0);
19851 Src = Src.getOperand(0);
19855 Src = Src.getOperand(0);
19859 Src = Src.getOperand(0);
19862 EVT SrcEVT = Src.getValueType();
19884 VectorBitsMax, EltSize, MinSize);
19889 MVT ContainerVT = SrcMVT;
19920 switch (
LHS.getOpcode()) {
19922 case RISCVISD::VSEXT_VL:
19923 Opcode = RISCVISD::VWMULSU_VL;
19926 case RISCVISD::VZEXT_VL:
19927 Opcode = RISCVISD::VWMULU_VL;
19938 else if (
RHS.getOpcode() == RISCVISD::VMV_V_X_VL &&
19940 ShAmtInt =
RHS.getConstantOperandVal(1);
19953 if (ShAmtInt >= NarrowBits)
19955 MVT VT =
N->getSimpleValueType(0);
19962 switch (
N->getOpcode()) {
19967 case RISCVISD::SHL_VL:
19968 Passthru =
N->getOperand(2);
19969 Mask =
N->getOperand(3);
19970 VL =
N->getOperand(4);
19975 return DAG.
getNode(Opcode,
DL, VT, NarrowOp,
19977 Passthru, Mask, VL);
19989 auto SimplifyDemandedLowBitsHelper = [&](
unsigned OpNo,
unsigned LowBits) {
20000 switch (
N->getOpcode()) {
20003 case RISCVISD::SplitF64: {
20007 if (Op0->
getOpcode() == RISCVISD::BuildPairF64)
20020 APInt V =
C->getValueAPF().bitcastToAPInt();
20049 case RISCVISD::SLLW:
20050 case RISCVISD::SRAW:
20051 case RISCVISD::SRLW:
20052 case RISCVISD::RORW:
20053 case RISCVISD::ROLW: {
20055 if (SimplifyDemandedLowBitsHelper(0, 32) ||
20056 SimplifyDemandedLowBitsHelper(1, 5))
20061 case RISCVISD::CLZW:
20062 case RISCVISD::CTZW: {
20064 if (SimplifyDemandedLowBitsHelper(0, 32))
20068 case RISCVISD::FMV_W_X_RV64: {
20073 if (Op0.
getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64)
20077 case RISCVISD::FMV_X_ANYEXTH:
20078 case RISCVISD::FMV_X_ANYEXTW_RV64: {
20081 MVT VT =
N->getSimpleValueType(0);
20084 if (
auto *CFP = dyn_cast<ConstantFPSDNode>(Op0)) {
20092 if ((
N->getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64 &&
20093 Op0->
getOpcode() == RISCVISD::FMV_W_X_RV64) ||
20094 (
N->getOpcode() == RISCVISD::FMV_X_ANYEXTH &&
20095 Op0->
getOpcode() == RISCVISD::FMV_H_X)) {
20097 "Unexpected value type!");
20102 cast<LoadSDNode>(Op0)->isSimple()) {
20104 auto *LN0 = cast<LoadSDNode>(Op0);
20107 LN0->getBasePtr(), IVT, LN0->getMemOperand());
20120 unsigned FPBits =
N->getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64 ? 32 : 16;
20131 EVT VT =
N->getValueType(0);
20186 if (!
C || !
C->getValueAPF().isExactlyValue(+1.0))
20188 EVT VT =
N->getValueType(0);
20217 if (
N->getValueType(0) == MVT::i64 && Subtarget.
is64Bit()) {
20222 Src.getOperand(0));
20227 Src.getOperand(0), Src.getOperand(1));
20235 case RISCVISD::TRUNCATE_VECTOR_VL:
20239 case ISD::VP_TRUNCATE:
20247 case RISCVISD::CZERO_EQZ:
20248 case RISCVISD::CZERO_NEZ: {
20252 unsigned Opc =
N->getOpcode();
20255 if (
Opc == RISCVISD::CZERO_EQZ && Val ==
Cond)
20259 Opc == RISCVISD::CZERO_EQZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ;
20267 return DAG.
getNode(InvOpc,
SDLoc(
N),
N->getValueType(0), Val, NewCond);
20277 N->getValueType(0), Val,
Cond.getOperand(0));
20281 case RISCVISD::SELECT_CC: {
20288 SDValue FalseV =
N->getOperand(4);
20290 EVT VT =
N->getValueType(0);
20293 if (TrueV == FalseV)
20298 if (!Subtarget.hasShortForwardBranchOpt() && isa<ConstantSDNode>(TrueV) &&
20304 int64_t TrueSImm = cast<ConstantSDNode>(TrueV)->getSExtValue();
20305 int64_t FalseSImm = cast<ConstantSDNode>(FalseV)->getSExtValue();
20308 if (isInt<12>(TrueSImm) && isInt<12>(FalseSImm) &&
20309 isInt<12>(TrueSImm - FalseSImm)) {
20324 return DAG.
getNode(RISCVISD::SELECT_CC,
DL,
N->getValueType(0),
20325 {LHS, RHS, CC, TrueV, FalseV});
20384 case RISCVISD::BR_CC: {
20391 return DAG.
getNode(RISCVISD::BR_CC,
DL,
N->getValueType(0),
20392 N->getOperand(0),
LHS,
RHS, CC,
N->getOperand(4));
20405 EVT VT =
N->getValueType(0);
20429 const auto *MGN = cast<MaskedGatherSDNode>(
N);
20430 const EVT VT =
N->getValueType(0);
20431 SDValue Index = MGN->getIndex();
20432 SDValue ScaleOp = MGN->getScale();
20434 assert(!MGN->isIndexScaled() &&
20435 "Scaled gather/scatter should not be formed");
20440 N->getVTList(), MGN->getMemoryVT(),
DL,
20441 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
20442 MGN->getBasePtr(), Index, ScaleOp},
20443 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
20447 N->getVTList(), MGN->getMemoryVT(),
DL,
20448 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
20449 MGN->getBasePtr(), Index, ScaleOp},
20450 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
20456 if (std::optional<VIDSequence> SimpleVID =
20458 SimpleVID && SimpleVID->StepDenominator == 1) {
20459 const int64_t StepNumerator = SimpleVID->StepNumerator;
20460 const int64_t Addend = SimpleVID->Addend;
20467 assert(MGN->getBasePtr()->getValueType(0) == PtrVT);
20475 VT,
DL, MGN->getChain(), BasePtr,
20477 EVL, MGN->getMemOperand());
20479 StridedLoad, MGN->getPassThru(), EVL);
20489 MGN->getBasePtr(), DAG.
getUNDEF(XLenVT),
20491 MGN->getMemoryVT(), MGN->getMemOperand(),
20500 MGN->getMemOperand()->getBaseAlign(), Subtarget)) {
20502 for (
unsigned i = 0; i < Index->getNumOperands(); i += 2)
20503 NewIndices.
push_back(Index.getOperand(i));
20504 EVT IndexVT = Index.getValueType()
20505 .getHalfNumVectorElementsVT(*DAG.
getContext());
20511 assert(EltCnt.isKnownEven() &&
"Splitting vector, but not in half!");
20513 EltCnt.divideCoefficientBy(2));
20516 EltCnt.divideCoefficientBy(2));
20521 {MGN->getChain(), Passthru, Mask, MGN->getBasePtr(),
20530 const auto *MSN = cast<MaskedScatterSDNode>(
N);
20531 SDValue Index = MSN->getIndex();
20532 SDValue ScaleOp = MSN->getScale();
20534 assert(!MSN->isIndexScaled() &&
20535 "Scaled gather/scatter should not be formed");
20540 N->getVTList(), MSN->getMemoryVT(),
DL,
20541 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
20543 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
20547 N->getVTList(), MSN->getMemoryVT(),
DL,
20548 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
20550 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
20552 EVT VT = MSN->getValue()->getValueType(0);
20554 if (!MSN->isTruncatingStore() &&
20558 return DAG.
getMaskedStore(MSN->getChain(),
DL, Shuffle, MSN->getBasePtr(),
20559 DAG.
getUNDEF(XLenVT), MSN->getMask(),
20560 MSN->getMemoryVT(), MSN->getMemOperand(),
20565 case ISD::VP_GATHER: {
20566 const auto *VPGN = cast<VPGatherSDNode>(
N);
20567 SDValue Index = VPGN->getIndex();
20568 SDValue ScaleOp = VPGN->getScale();
20570 assert(!VPGN->isIndexScaled() &&
20571 "Scaled gather/scatter should not be formed");
20576 {VPGN->getChain(), VPGN->getBasePtr(), Index,
20577 ScaleOp, VPGN->getMask(),
20578 VPGN->getVectorLength()},
20579 VPGN->getMemOperand(), IndexType);
20583 {VPGN->getChain(), VPGN->getBasePtr(), Index,
20584 ScaleOp, VPGN->getMask(),
20585 VPGN->getVectorLength()},
20586 VPGN->getMemOperand(), IndexType);
20590 case ISD::VP_SCATTER: {
20591 const auto *VPSN = cast<VPScatterSDNode>(
N);
20592 SDValue Index = VPSN->getIndex();
20593 SDValue ScaleOp = VPSN->getScale();
20595 assert(!VPSN->isIndexScaled() &&
20596 "Scaled gather/scatter should not be formed");
20601 {VPSN->getChain(), VPSN->getValue(),
20602 VPSN->getBasePtr(), Index, ScaleOp,
20603 VPSN->getMask(), VPSN->getVectorLength()},
20604 VPSN->getMemOperand(), IndexType);
20608 {VPSN->getChain(), VPSN->getValue(),
20609 VPSN->getBasePtr(), Index, ScaleOp,
20610 VPSN->getMask(), VPSN->getVectorLength()},
20611 VPSN->getMemOperand(), IndexType);
20614 case RISCVISD::SHL_VL:
20618 case RISCVISD::SRA_VL:
20619 case RISCVISD::SRL_VL: {
20621 if (ShAmt.
getOpcode() == RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL) {
20625 EVT VT =
N->getValueType(0);
20628 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt,
20629 N->getOperand(2),
N->getOperand(3),
N->getOperand(4));
20644 if (ShAmt.
getOpcode() == RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL) {
20647 EVT VT =
N->getValueType(0);
20651 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt);
20655 case RISCVISD::ADD_VL:
20663 case RISCVISD::VWADD_W_VL:
20664 case RISCVISD::VWADDU_W_VL:
20665 case RISCVISD::VWSUB_W_VL:
20666 case RISCVISD::VWSUBU_W_VL:
20668 case RISCVISD::OR_VL:
20669 case RISCVISD::SUB_VL:
20670 case RISCVISD::MUL_VL:
20672 case RISCVISD::VFMADD_VL:
20673 case RISCVISD::VFNMADD_VL:
20674 case RISCVISD::VFMSUB_VL:
20675 case RISCVISD::VFNMSUB_VL:
20676 case RISCVISD::STRICT_VFMADD_VL:
20677 case RISCVISD::STRICT_VFNMADD_VL:
20678 case RISCVISD::STRICT_VFMSUB_VL:
20679 case RISCVISD::STRICT_VFNMSUB_VL:
20681 case RISCVISD::FADD_VL:
20682 case RISCVISD::FSUB_VL:
20683 case RISCVISD::FMUL_VL:
20684 case RISCVISD::VFWADD_W_VL:
20685 case RISCVISD::VFWSUB_W_VL:
20696 auto *Store = cast<StoreSDNode>(
N);
20697 SDValue Chain = Store->getChain();
20698 EVT MemVT = Store->getMemoryVT();
20699 SDValue Val = Store->getValue();
20702 bool IsScalarizable =
20704 Store->isSimple() &&
20734 NewVT, *Store->getMemOperand())) {
20736 return DAG.
getStore(Chain,
DL, NewV, Store->getBasePtr(),
20737 Store->getPointerInfo(), Store->getBaseAlign(),
20738 Store->getMemOperand()->getFlags());
20746 if (
auto *L = dyn_cast<LoadSDNode>(Val);
20748 L->hasNUsesOfValue(1, 0) && L->hasNUsesOfValue(1, 1) &&
20750 L->getMemoryVT() == MemVT) {
20753 NewVT, *Store->getMemOperand()) &&
20755 NewVT, *L->getMemOperand())) {
20757 L->getPointerInfo(), L->getBaseAlign(),
20758 L->getMemOperand()->getFlags());
20759 return DAG.
getStore(Chain,
DL, NewL, Store->getBasePtr(),
20760 Store->getPointerInfo(), Store->getBaseAlign(),
20761 Store->getMemOperand()->getFlags());
20768 if ((Val.
getOpcode() == RISCVISD::VMV_X_S ||
20774 MVT VecVT = Src.getSimpleValueType();
20781 Store->getChain(),
DL, Src, Store->getBasePtr(), Store->getOffset(),
20784 Store->getMemOperand(), Store->getAddressingMode(),
20785 Store->isTruncatingStore(),
false);
20792 EVT VT =
N->getValueType(0);
20817 case RISCVISD::VFMV_V_F_VL: {
20818 const MVT VT =
N->getSimpleValueType(0);
20819 SDValue Passthru =
N->getOperand(0);
20820 SDValue Scalar =
N->getOperand(1);
20825 return DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL, VT, Passthru, Scalar, VL);
20828 case RISCVISD::VMV_V_X_VL: {
20829 const MVT VT =
N->getSimpleValueType(0);
20830 SDValue Passthru =
N->getOperand(0);
20831 SDValue Scalar =
N->getOperand(1);
20836 unsigned ScalarSize = Scalar.getValueSizeInBits();
20838 if (ScalarSize > EltWidth && Passthru.
isUndef())
20839 if (SimplifyDemandedLowBitsHelper(1, EltWidth))
20846 (!Const || Const->isZero() ||
20847 !Const->getAPIntValue().sextOrTrunc(EltWidth).isSignedIntN(5)))
20848 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, VT, Passthru, Scalar, VL);
20852 case RISCVISD::VFMV_S_F_VL: {
20857 if (
N->getOperand(0).isUndef() &&
20860 Src.getOperand(0).getValueType().isScalableVector()) {
20861 EVT VT =
N->getValueType(0);
20862 SDValue EVSrc = Src.getOperand(0);
20881 case RISCVISD::VMV_S_X_VL: {
20882 const MVT VT =
N->getSimpleValueType(0);
20883 SDValue Passthru =
N->getOperand(0);
20884 SDValue Scalar =
N->getOperand(1);
20890 unsigned ScalarSize = Scalar.getValueSizeInBits();
20892 if (ScalarSize > EltWidth && SimplifyDemandedLowBitsHelper(1, EltWidth))
20895 if (Scalar.getOpcode() == RISCVISD::VMV_X_S && Passthru.
isUndef() &&
20896 Scalar.getOperand(0).getValueType() ==
N->getValueType(0))
20897 return Scalar.getOperand(0);
20904 DAG.
getNode(
N->getOpcode(),
DL, M1VT, M1Passthru, Scalar, VL);
20913 Const && !Const->isZero() && isInt<5>(Const->getSExtValue()) &&
20915 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru, Scalar, VL);
20919 case RISCVISD::VMV_X_S: {
20921 MVT VecVT =
N->getOperand(0).getSimpleValueType();
20923 if (M1VT.
bitsLT(VecVT)) {
20925 return DAG.
getNode(RISCVISD::VMV_X_S,
DL,
N->getSimpleValueType(0), Vec);
20933 unsigned IntNo =
N->getConstantOperandVal(IntOpNo);
20938 case Intrinsic::riscv_vcpop:
20939 case Intrinsic::riscv_vcpop_mask:
20940 case Intrinsic::riscv_vfirst:
20941 case Intrinsic::riscv_vfirst_mask: {
20943 if (IntNo == Intrinsic::riscv_vcpop_mask ||
20944 IntNo == Intrinsic::riscv_vfirst_mask)
20945 VL =
N->getOperand(3);
20950 EVT VT =
N->getValueType(0);
20951 if (IntNo == Intrinsic::riscv_vfirst ||
20952 IntNo == Intrinsic::riscv_vfirst_mask)
20956 case Intrinsic::riscv_vsseg2_mask:
20957 case Intrinsic::riscv_vsseg3_mask:
20958 case Intrinsic::riscv_vsseg4_mask:
20959 case Intrinsic::riscv_vsseg5_mask:
20960 case Intrinsic::riscv_vsseg6_mask:
20961 case Intrinsic::riscv_vsseg7_mask:
20962 case Intrinsic::riscv_vsseg8_mask: {
20967 Tuple.
getOpcode() != RISCVISD::TUPLE_INSERT ||
20976 "Type mismatch without bitcast?");
20977 unsigned Stride = SEW / 8 * NF;
20992 auto *OldMemSD = cast<MemIntrinsicSDNode>(
N);
21005 case ISD::EXPERIMENTAL_VP_REVERSE:
21007 case ISD::VP_STORE:
21012 EVT VT =
N->getValueType(0);
21023 for (
unsigned i = 0; i < NF; ++i)
21024 Result = DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VT, Result,
Splat,
21030 if ((SrcVT == MVT::v1i1 || SrcVT == MVT::v2i1 || SrcVT == MVT::v4i1) &&
21051 case RISCVISD::VRGATHER_VX_VL: {
21054 EVT VT =
N->getValueType(0);
21057 SDValue Passthru =
N->getOperand(2);
21064 Src = Src.getOperand(1);
21066 switch (Src.getOpcode()) {
21069 case RISCVISD::VMV_V_X_VL:
21070 case RISCVISD::VFMV_V_F_VL:
21074 if (Passthru.
isUndef() && VL == Src.getOperand(2) &&
21075 Src.getValueType() == VT)
21078 case RISCVISD::VMV_S_X_VL:
21079 case RISCVISD::VFMV_S_F_VL:
21085 VL == Src.getOperand(2)) {
21095 case RISCVISD::TUPLE_EXTRACT: {
21096 EVT VT =
N->getValueType(0);
21098 unsigned Idx =
N->getConstantOperandVal(1);
21106 case Intrinsic::riscv_vlseg2_mask:
21107 case Intrinsic::riscv_vlseg3_mask:
21108 case Intrinsic::riscv_vlseg4_mask:
21109 case Intrinsic::riscv_vlseg5_mask:
21110 case Intrinsic::riscv_vlseg6_mask:
21111 case Intrinsic::riscv_vlseg7_mask:
21112 case Intrinsic::riscv_vlseg8_mask:
21122 "Type mismatch without bitcast?");
21123 unsigned Stride = SEW / 8 * NF;
21138 auto *TupleMemSD = cast<MemIntrinsicSDNode>(Tuple);
21149 return Result.getValue(0);
21151 case RISCVISD::TUPLE_INSERT: {
21153 if (
N->getOperand(1).isUndef())
21154 return N->getOperand(0);
21163 EVT XVT,
unsigned KeptBits)
const {
21168 if (XVT != MVT::i32 && XVT != MVT::i64)
21172 if (KeptBits == 32 || KeptBits == 64)
21176 return Subtarget.hasStdExtZbb() &&
21177 ((KeptBits == 8 && XVT == MVT::i64 && !Subtarget.
is64Bit()) ||
21185 "Expected shift op");
21203 if (!isa<StoreSDNode>(
Use) && !isa<LoadSDNode>(
Use))
21212 return isUsedByLdSt(N0.
getNode(),
N);
21214 auto *C1 = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
21215 auto *C2 = dyn_cast<ConstantSDNode>(
N->getOperand(1));
21218 (Subtarget.hasStdExtZba() || Subtarget.hasVendorXAndesPerf()) && C2 &&
21219 C2->getZExtValue() >= 1 && C2->getZExtValue() <= 3;
21220 bool IsQCShlAdd = Subtarget.hasVendorXqciac() && C2 &&
21221 C2->getZExtValue() >= 4 && C2->getZExtValue() <= 31;
21224 if ((IsShXAdd || IsQCShlAdd) &&
N->hasOneUse() &&
21225 N->user_begin()->getOpcode() ==
ISD::ADD &&
21226 !isUsedByLdSt(*
N->user_begin(),
nullptr) &&
21227 !isa<ConstantSDNode>(
N->user_begin()->getOperand(1)))
21231 const APInt &C1Int = C1->getAPIntValue();
21232 APInt ShiftedC1Int = C1Int << C2->getAPIntValue();
21258 if (C1Cost < ShiftedC1Cost)
21281 EVT VT =
Op.getValueType();
21285 unsigned Opcode =
Op.getOpcode();
21293 const APInt &Mask =
C->getAPIntValue();
21302 auto IsLegalMask = [ShrunkMask, ExpandedMask](
const APInt &Mask) ->
bool {
21303 return ShrunkMask.
isSubsetOf(Mask) && Mask.isSubsetOf(ExpandedMask);
21305 auto UseMask = [Mask,
Op, &TLO](
const APInt &NewMask) ->
bool {
21306 if (NewMask == Mask)
21311 Op.getOperand(0), NewC);
21324 APInt NewMask =
APInt(Mask.getBitWidth(), 0xffff);
21325 if (IsLegalMask(NewMask))
21326 return UseMask(NewMask);
21329 if (VT == MVT::i64) {
21331 if (IsLegalMask(NewMask))
21332 return UseMask(NewMask);
21347 APInt NewMask = ShrunkMask;
21348 if (MinSignedBits <= 12)
21350 else if (!
C->isOpaque() && MinSignedBits <= 32 && !ShrunkMask.
isSignedIntN(32))
21356 assert(IsLegalMask(NewMask));
21357 return UseMask(NewMask);
21361 static const uint64_t GREVMasks[] = {
21362 0x5555555555555555ULL, 0x3333333333333333ULL, 0x0F0F0F0F0F0F0F0FULL,
21363 0x00FF00FF00FF00FFULL, 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL};
21365 for (
unsigned Stage = 0; Stage != 6; ++Stage) {
21366 unsigned Shift = 1 << Stage;
21367 if (ShAmt & Shift) {
21369 uint64_t Res = ((x & Mask) << Shift) | ((x >> Shift) & Mask);
21381 const APInt &DemandedElts,
21383 unsigned Depth)
const {
21385 unsigned Opc =
Op.getOpcode();
21390 "Should use MaskedValueIsZero if you don't know whether Op"
21391 " is a target node!");
21396 case RISCVISD::SELECT_CC: {
21407 case RISCVISD::VCPOP_VL: {
21412 case RISCVISD::CZERO_EQZ:
21413 case RISCVISD::CZERO_NEZ:
21419 case RISCVISD::REMUW: {
21429 case RISCVISD::DIVUW: {
21439 case RISCVISD::SLLW: {
21448 case RISCVISD::SRAW: {
21457 case RISCVISD::CTZW: {
21464 case RISCVISD::CLZW: {
21471 case RISCVISD::BREV8:
21472 case RISCVISD::ORC_B: {
21476 bool IsGORC =
Op.getOpcode() == RISCVISD::ORC_B;
21484 case RISCVISD::READ_VLENB: {
21489 assert(MinVLenB > 0 &&
"READ_VLENB without vector extension enabled?");
21492 if (MaxVLenB == MinVLenB)
21496 case RISCVISD::FCLASS: {
21509 case Intrinsic::riscv_vsetvli:
21510 case Intrinsic::riscv_vsetvlimax: {
21511 bool HasAVL = IntNo == Intrinsic::riscv_vsetvli;
21512 unsigned VSEW =
Op.getConstantOperandVal(HasAVL + 1);
21518 MaxVL = (Fractional) ? MaxVL / LMul : MaxVL * LMul;
21521 if (HasAVL && isa<ConstantSDNode>(
Op.getOperand(1)))
21522 MaxVL = std::min(MaxVL,
Op.getConstantOperandVal(1));
21524 unsigned KnownZeroFirstBit =
Log2_32(MaxVL) + 1;
21537 unsigned Depth)
const {
21538 switch (
Op.getOpcode()) {
21541 case RISCVISD::SELECT_CC: {
21544 if (Tmp == 1)
return 1;
21547 return std::min(Tmp, Tmp2);
21549 case RISCVISD::CZERO_EQZ:
21550 case RISCVISD::CZERO_NEZ:
21554 case RISCVISD::ABSW: {
21559 if (Tmp < 33)
return 1;
21562 case RISCVISD::SRAW: {
21569 return std::max(Tmp, 33U);
21571 case RISCVISD::SLLW:
21572 case RISCVISD::SRLW:
21573 case RISCVISD::DIVW:
21574 case RISCVISD::DIVUW:
21575 case RISCVISD::REMUW:
21576 case RISCVISD::ROLW:
21577 case RISCVISD::RORW:
21578 case RISCVISD::FCVT_W_RV64:
21579 case RISCVISD::FCVT_WU_RV64:
21580 case RISCVISD::STRICT_FCVT_W_RV64:
21581 case RISCVISD::STRICT_FCVT_WU_RV64:
21584 case RISCVISD::VMV_X_S: {
21590 unsigned XLen = Subtarget.
getXLen();
21591 unsigned EltBits =
Op.getOperand(0).getScalarValueSizeInBits();
21592 if (EltBits <= XLen)
21593 return XLen - EltBits + 1;
21597 unsigned IntNo =
Op.getConstantOperandVal(1);
21601 case Intrinsic::riscv_masked_atomicrmw_xchg:
21602 case Intrinsic::riscv_masked_atomicrmw_add:
21603 case Intrinsic::riscv_masked_atomicrmw_sub:
21604 case Intrinsic::riscv_masked_atomicrmw_nand:
21605 case Intrinsic::riscv_masked_atomicrmw_max:
21606 case Intrinsic::riscv_masked_atomicrmw_min:
21607 case Intrinsic::riscv_masked_atomicrmw_umax:
21608 case Intrinsic::riscv_masked_atomicrmw_umin:
21609 case Intrinsic::riscv_masked_cmpxchg:
21616 assert(Subtarget.hasStdExtA());
21617 return Op.getValueSizeInBits() - 31;
21629 unsigned Depth)
const {
21632 switch (
Op.getOpcode()) {
21633 case RISCVISD::BREV8:
21634 case RISCVISD::ORC_B: {
21636 bool IsGORC =
Op.getOpcode() == RISCVISD::ORC_B;
21644 OriginalDemandedElts, Known2, TLO,
Depth + 1))
21656 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
21664 switch (
Op.getOpcode()) {
21665 case RISCVISD::SLLW:
21666 case RISCVISD::SRAW:
21667 case RISCVISD::SRLW:
21668 case RISCVISD::RORW:
21669 case RISCVISD::ROLW:
21673 case RISCVISD::SELECT_CC:
21675 assert(
Op.getOperand(0).getValueType().isInteger() &&
21676 "RISCVISD::SELECT_CC only compares integers");
21685 assert(Ld &&
"Unexpected null LoadSDNode");
21693 auto *CNode = dyn_cast<ConstantPoolSDNode>(
Ptr);
21694 if (!CNode || CNode->isMachineConstantPoolEntry() ||
21695 CNode->getOffset() != 0)
21702 if (
Ptr.getOpcode() == RISCVISD::LLA) {
21703 auto *CNode = GetSupportedConstantPool(
Ptr.getOperand(0));
21704 if (!CNode || CNode->getTargetFlags() != 0)
21707 return CNode->getConstVal();
21711 if (
Ptr.getOpcode() != RISCVISD::ADD_LO ||
21712 Ptr.getOperand(0).getOpcode() != RISCVISD::HI)
21715 auto *CNodeLo = GetSupportedConstantPool(
Ptr.getOperand(1));
21716 auto *CNodeHi = GetSupportedConstantPool(
Ptr.getOperand(0).getOperand(0));
21722 if (CNodeLo->getConstVal() != CNodeHi->getConstVal())
21725 return CNodeLo->getConstVal();
21730 assert(
MI.getOpcode() == RISCV::ReadCounterWide &&
"Unexpected instruction");
21762 Register ReadAgainReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
21765 int64_t LoCounter =
MI.getOperand(2).getImm();
21766 int64_t HiCounter =
MI.getOperand(3).getImm();
21776 BuildMI(LoopMBB,
DL,
TII->get(RISCV::CSRRS), ReadAgainReg)
21788 MI.eraseFromParent();
21796 assert(
MI.getOpcode() == RISCV::SplitF64Pseudo &&
"Unexpected instruction");
21804 Register SrcReg =
MI.getOperand(2).getReg();
21824 MI.eraseFromParent();
21831 assert(
MI.getOpcode() == RISCV::BuildPairF64Pseudo &&
21832 "Unexpected instruction");
21838 Register DstReg =
MI.getOperand(0).getReg();
21861 MI.eraseFromParent();
21866 unsigned RelOpcode,
unsigned EqOpcode,
21869 Register DstReg =
MI.getOperand(0).getReg();
21870 Register Src1Reg =
MI.getOperand(1).getReg();
21871 Register Src2Reg =
MI.getOperand(2).getReg();
21873 Register SavedFFlags =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
21897 MI.eraseFromParent();
21948 F->insert(It, FirstMBB);
21949 F->insert(It, SecondMBB);
21950 F->insert(It, SinkMBB);
22000 First.eraseFromParent();
22039 if (
MI.getOpcode() != RISCV::Select_GPR_Using_CC_GPR &&
22040 MI.getOperand(1).isReg() &&
MI.getOperand(2).isReg() &&
22041 Next != BB->
end() && Next->getOpcode() ==
MI.getOpcode() &&
22042 Next->getOperand(5).getReg() ==
MI.getOperand(0).getReg() &&
22043 Next->getOperand(5).isKill())
22048 if (
MI.getOperand(2).isReg())
22049 RHS =
MI.getOperand(2).getReg();
22054 SelectDests.
insert(
MI.getOperand(0).getReg());
22058 SequenceMBBI != E; ++SequenceMBBI) {
22059 if (SequenceMBBI->isDebugInstr())
22061 if (RISCVInstrInfo::isSelectPseudo(*SequenceMBBI)) {
22062 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
22063 !SequenceMBBI->getOperand(2).isReg() ||
22064 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
22065 SequenceMBBI->getOperand(3).getImm() != CC ||
22066 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
22067 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
22069 LastSelectPseudo = &*SequenceMBBI;
22071 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
22074 if (SequenceMBBI->hasUnmodeledSideEffects() ||
22075 SequenceMBBI->mayLoadOrStore() ||
22076 SequenceMBBI->usesCustomInsertionHook())
22079 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
22094 F->insert(
I, IfFalseMBB);
22095 F->insert(
I, TailMBB);
22098 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
22104 TailMBB->
push_back(DebugInstr->removeFromParent());
22108 TailMBB->
splice(TailMBB->
end(), HeadMBB,
22118 if (
MI.getOperand(2).isImm())
22121 .
addImm(
MI.getOperand(2).getImm())
22133 auto SelectMBBI =
MI.getIterator();
22134 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
22136 while (SelectMBBI != SelectEnd) {
22137 auto Next = std::next(SelectMBBI);
22138 if (RISCVInstrInfo::isSelectPseudo(*SelectMBBI)) {
22141 TII.get(RISCV::PHI), SelectMBBI->getOperand(0).getReg())
22142 .
addReg(SelectMBBI->getOperand(4).getReg())
22144 .
addReg(SelectMBBI->getOperand(5).getReg())
22151 F->getProperties().resetNoPHIs();
22159 RISCVVInversePseudosTable::getBaseInfo(MCOpcode, LMul, SEW);
22160 assert(
Inverse &&
"Unexpected LMUL and SEW pair for instruction");
22162 RISCV::lookupMaskedIntrinsicByUnmasked(
Inverse->Pseudo);
22163 assert(
Masked &&
"Could not find masked instruction for LMUL and SEW pair");
22169 unsigned CVTXOpc) {
22175 Register SavedFFLAGS =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22188 .
add(
MI.getOperand(1))
22189 .
add(
MI.getOperand(2))
22190 .
add(
MI.getOperand(3))
22192 .
add(
MI.getOperand(4))
22193 .
add(
MI.getOperand(5))
22194 .
add(
MI.getOperand(6))
22209 .
add(
MI.getOperand(0))
22210 .
add(
MI.getOperand(1))
22212 .
add(
MI.getOperand(3))
22214 .
add(
MI.getOperand(4))
22215 .
add(
MI.getOperand(5))
22216 .
add(
MI.getOperand(6))
22226 MI.eraseFromParent();
22232 unsigned CmpOpc, F2IOpc, I2FOpc, FSGNJOpc, FSGNJXOpc;
22234 switch (
MI.getOpcode()) {
22237 case RISCV::PseudoFROUND_H:
22238 CmpOpc = RISCV::FLT_H;
22239 F2IOpc = RISCV::FCVT_W_H;
22240 I2FOpc = RISCV::FCVT_H_W;
22241 FSGNJOpc = RISCV::FSGNJ_H;
22242 FSGNJXOpc = RISCV::FSGNJX_H;
22243 RC = &RISCV::FPR16RegClass;
22245 case RISCV::PseudoFROUND_H_INX:
22246 CmpOpc = RISCV::FLT_H_INX;
22247 F2IOpc = RISCV::FCVT_W_H_INX;
22248 I2FOpc = RISCV::FCVT_H_W_INX;
22249 FSGNJOpc = RISCV::FSGNJ_H_INX;
22250 FSGNJXOpc = RISCV::FSGNJX_H_INX;
22251 RC = &RISCV::GPRF16RegClass;
22253 case RISCV::PseudoFROUND_S:
22254 CmpOpc = RISCV::FLT_S;
22255 F2IOpc = RISCV::FCVT_W_S;
22256 I2FOpc = RISCV::FCVT_S_W;
22257 FSGNJOpc = RISCV::FSGNJ_S;
22258 FSGNJXOpc = RISCV::FSGNJX_S;
22259 RC = &RISCV::FPR32RegClass;
22261 case RISCV::PseudoFROUND_S_INX:
22262 CmpOpc = RISCV::FLT_S_INX;
22263 F2IOpc = RISCV::FCVT_W_S_INX;
22264 I2FOpc = RISCV::FCVT_S_W_INX;
22265 FSGNJOpc = RISCV::FSGNJ_S_INX;
22266 FSGNJXOpc = RISCV::FSGNJX_S_INX;
22267 RC = &RISCV::GPRF32RegClass;
22269 case RISCV::PseudoFROUND_D:
22271 CmpOpc = RISCV::FLT_D;
22272 F2IOpc = RISCV::FCVT_L_D;
22273 I2FOpc = RISCV::FCVT_D_L;
22274 FSGNJOpc = RISCV::FSGNJ_D;
22275 FSGNJXOpc = RISCV::FSGNJX_D;
22276 RC = &RISCV::FPR64RegClass;
22278 case RISCV::PseudoFROUND_D_INX:
22280 CmpOpc = RISCV::FLT_D_INX;
22281 F2IOpc = RISCV::FCVT_L_D_INX;
22282 I2FOpc = RISCV::FCVT_D_L_INX;
22283 FSGNJOpc = RISCV::FSGNJ_D_INX;
22284 FSGNJXOpc = RISCV::FSGNJX_D_INX;
22285 RC = &RISCV::GPRRegClass;
22297 F->insert(
I, CvtMBB);
22298 F->insert(
I, DoneMBB);
22309 Register DstReg =
MI.getOperand(0).getReg();
22310 Register SrcReg =
MI.getOperand(1).getReg();
22311 Register MaxReg =
MI.getOperand(2).getReg();
22312 int64_t FRM =
MI.getOperand(3).getImm();
22317 Register FabsReg =
MRI.createVirtualRegister(RC);
22321 Register CmpReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22336 Register F2IReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22358 MI.eraseFromParent();
22365 switch (
MI.getOpcode()) {
22368 case RISCV::ReadCounterWide:
22370 "ReadCounterWide is only to be used on riscv32");
22372 case RISCV::Select_GPR_Using_CC_GPR:
22373 case RISCV::Select_GPR_Using_CC_SImm5_CV:
22374 case RISCV::Select_GPRNoX0_Using_CC_SImm5NonZero_QC:
22375 case RISCV::Select_GPRNoX0_Using_CC_UImm5NonZero_QC:
22376 case RISCV::Select_GPRNoX0_Using_CC_SImm16NonZero_QC:
22377 case RISCV::Select_GPRNoX0_Using_CC_UImm16NonZero_QC:
22378 case RISCV::Select_GPR_Using_CC_UImmLog2XLen_NDS:
22379 case RISCV::Select_GPR_Using_CC_UImm7_NDS:
22380 case RISCV::Select_FPR16_Using_CC_GPR:
22381 case RISCV::Select_FPR16INX_Using_CC_GPR:
22382 case RISCV::Select_FPR32_Using_CC_GPR:
22383 case RISCV::Select_FPR32INX_Using_CC_GPR:
22384 case RISCV::Select_FPR64_Using_CC_GPR:
22385 case RISCV::Select_FPR64INX_Using_CC_GPR:
22386 case RISCV::Select_FPR64IN32X_Using_CC_GPR:
22388 case RISCV::BuildPairF64Pseudo:
22390 case RISCV::SplitF64Pseudo:
22392 case RISCV::PseudoQuietFLE_H:
22394 case RISCV::PseudoQuietFLE_H_INX:
22395 return emitQuietFCMP(
MI, BB, RISCV::FLE_H_INX, RISCV::FEQ_H_INX, Subtarget);
22396 case RISCV::PseudoQuietFLT_H:
22398 case RISCV::PseudoQuietFLT_H_INX:
22399 return emitQuietFCMP(
MI, BB, RISCV::FLT_H_INX, RISCV::FEQ_H_INX, Subtarget);
22400 case RISCV::PseudoQuietFLE_S:
22402 case RISCV::PseudoQuietFLE_S_INX:
22403 return emitQuietFCMP(
MI, BB, RISCV::FLE_S_INX, RISCV::FEQ_S_INX, Subtarget);
22404 case RISCV::PseudoQuietFLT_S:
22406 case RISCV::PseudoQuietFLT_S_INX:
22407 return emitQuietFCMP(
MI, BB, RISCV::FLT_S_INX, RISCV::FEQ_S_INX, Subtarget);
22408 case RISCV::PseudoQuietFLE_D:
22410 case RISCV::PseudoQuietFLE_D_INX:
22411 return emitQuietFCMP(
MI, BB, RISCV::FLE_D_INX, RISCV::FEQ_D_INX, Subtarget);
22412 case RISCV::PseudoQuietFLE_D_IN32X:
22415 case RISCV::PseudoQuietFLT_D:
22417 case RISCV::PseudoQuietFLT_D_INX:
22418 return emitQuietFCMP(
MI, BB, RISCV::FLT_D_INX, RISCV::FEQ_D_INX, Subtarget);
22419 case RISCV::PseudoQuietFLT_D_IN32X:
22423 case RISCV::PseudoVFROUND_NOEXCEPT_V_M1_MASK:
22425 case RISCV::PseudoVFROUND_NOEXCEPT_V_M2_MASK:
22427 case RISCV::PseudoVFROUND_NOEXCEPT_V_M4_MASK:
22429 case RISCV::PseudoVFROUND_NOEXCEPT_V_M8_MASK:
22431 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF2_MASK:
22433 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF4_MASK:
22435 case RISCV::PseudoFROUND_H:
22436 case RISCV::PseudoFROUND_H_INX:
22437 case RISCV::PseudoFROUND_S:
22438 case RISCV::PseudoFROUND_S_INX:
22439 case RISCV::PseudoFROUND_D:
22440 case RISCV::PseudoFROUND_D_INX:
22441 case RISCV::PseudoFROUND_D_IN32X:
22443 case RISCV::PROBED_STACKALLOC_DYN:
22445 case TargetOpcode::STATEPOINT:
22451 MI.addOperand(*
MI.getMF(),
22457 case TargetOpcode::STACKMAP:
22458 case TargetOpcode::PATCHPOINT:
22461 "supported on 64-bit targets");
22471 if (
auto *FRMDef =
MI.findRegisterDefOperand(RISCV::FRM,
nullptr)) {
22472 FRMDef->setIsDead(
false);
22476 int Idx = RISCV::getNamedOperandIdx(
MI.getOpcode(), RISCV::OpName::frm);
22486 if (
MI.readsRegister(RISCV::FRM,
nullptr))
22492void RISCVTargetLowering::analyzeInputArgs(
22509void RISCVTargetLowering::analyzeOutputArgs(
22514 MVT ArgVT = Out.VT;
22536 return DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, Val);
22570 if (In.isOrigArg()) {
22575 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
22576 (
BitWidth < 32 && In.Flags.isZExt())) {
22597 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, LocVT, Val);
22598 if (LocVT == MVT::i64 && VA.
getValVT() == MVT::f32)
22599 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Val);
22647 ExtType,
DL, LocVT, Chain, FIN,
22664 Register LoVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
22677 Register HiVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
22681 return DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64,
Lo,
Hi);
22692 switch (CallConv) {
22701#define CC_VLS_CASE(ABI_VLEN) case CallingConv::RISCV_VLSCall_##ABI_VLEN:
22717 if (Subtarget.hasStdExtE())
22721 "(Zdinx/D) instruction set extensions");
22725 if (Func.hasFnAttribute(
"interrupt")) {
22726 if (!Func.arg_empty())
22728 "Functions with the interrupt attribute cannot have arguments!");
22739 "SiFive-CLIC-preemptible",
22740 "SiFive-CLIC-stack-swap",
22741 "SiFive-CLIC-preemptible-stack-swap",
22745 "Function interrupt attribute argument not supported!");
22747 if (Kind.starts_with(
"qci-") && !Subtarget.hasVendorXqciint())
22749 "'qci-*' interrupt kinds require Xqciint extension");
22751 if (Kind.starts_with(
"SiFive-CLIC-") && !Subtarget.hasVendorXSfmclic())
22753 "'SiFive-CLIC-*' interrupt kinds require XSfmclic extension");
22755 if (Kind ==
"rnmi" && !Subtarget.hasStdExtSmrnmi())
22758 if (Kind.starts_with(
"SiFive-CLIC-preemptible") && TFI->
hasFP(MF))
22760 "have a frame pointer");
22765 unsigned XLenInBytes = Subtarget.
getXLen() / 8;
22767 std::vector<SDValue> OutChains;
22776 analyzeInputArgs(MF, CCInfo, Ins,
false,
22780 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
22801 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
22802 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
22804 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
22806 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
22835 int VarArgsSaveSize = XLenInBytes * (ArgRegs.
size() -
Idx);
22840 if (VarArgsSaveSize == 0) {
22844 int VaArgOffset = -VarArgsSaveSize;
22852 XLenInBytes, VaArgOffset -
static_cast<int>(XLenInBytes),
true);
22853 VarArgsSaveSize += XLenInBytes;
22860 for (
unsigned I =
Idx;
I < ArgRegs.
size(); ++
I) {
22865 Chain,
DL, ArgValue, FIN,
22867 OutChains.push_back(Store);
22881 if (!OutChains.empty()) {
22882 OutChains.push_back(Chain);
22892bool RISCVTargetLowering::isEligibleForTailCallOptimization(
22896 auto CalleeCC = CLI.CallConv;
22897 auto &Outs = CLI.Outs;
22899 auto CallerCC = Caller.getCallingConv();
22906 if (Caller.hasFnAttribute(
"interrupt"))
22921 for (
auto &VA : ArgLocs)
22927 auto IsCallerStructRet = Caller.hasStructRetAttr();
22928 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
22929 if (IsCallerStructRet || IsCalleeStructRet)
22934 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
22935 if (CalleeCC != CallerCC) {
22936 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
22937 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
22944 for (
auto &Arg : Outs)
22945 if (Arg.Flags.isByVal())
22986 if (Subtarget.hasStdExtE())
22990 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
22996 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
23002 "call site marked musttail");
23009 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
23011 if (!Flags.isByVal())
23015 unsigned Size = Flags.getByValSize();
23016 Align Alignment = Flags.getNonZeroByValAlign();
23023 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
23025 false,
nullptr, IsTailCall,
23037 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
23040 SDValue ArgValue = OutVals[OutIdx];
23048 RISCVISD::SplitF64,
DL, DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
23060 if (!StackPtr.getNode())
23072 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
23090 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
23091 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
23097 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
23098 SDValue PartValue = OutVals[OutIdx + 1];
23099 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
23111 int FI = cast<FrameIndexSDNode>(SpillSlot)->getIndex();
23113 DAG.
getStore(Chain,
DL, ArgValue, SpillSlot,
23115 for (
const auto &Part : Parts) {
23116 SDValue PartValue = Part.first;
23117 SDValue PartOffset = Part.second;
23124 ArgValue = SpillSlot;
23130 if (Flags.isByVal())
23131 ArgValue = ByValArgs[j++];
23138 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
23139 "for passing parameters");
23142 if (!StackPtr.getNode())
23156 if (!MemOpChains.
empty())
23162 for (
auto &Reg : RegsToPass) {
23163 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
23170 validateCCReservedRegs(RegsToPass, MF);
23174 "Return address register required, but has been reserved."});
23179 bool CalleeIsLargeExternalSymbol =
false;
23181 if (
auto *S = dyn_cast<GlobalAddressSDNode>(Callee))
23183 else if (
auto *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
23185 CalleeIsLargeExternalSymbol =
true;
23201 for (
auto &Reg : RegsToPass)
23206 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
23207 assert(Mask &&
"Missing call preserved mask for calling convention");
23215 "Unexpected CFI type for a direct call");
23223 bool NeedSWGuarded =
false;
23225 Subtarget.hasStdExtZicfilp() &&
23227 NeedSWGuarded =
true;
23232 NeedSWGuarded ? RISCVISD::SW_GUARDED_TAIL : RISCVISD::TAIL;
23243 unsigned CallOpc = NeedSWGuarded ? RISCVISD::SW_GUARDED_CALL : RISCVISD::CALL;
23244 Chain = DAG.
getNode(CallOpc,
DL, NodeTys, Ops);
23261 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_RISCV);
23264 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
23265 auto &VA = RVLocs[i];
23273 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
23274 assert(VA.needsCustom());
23279 RetValue = DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64, RetValue,
23297 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
23298 MVT VT = Outs[i].VT;
23301 true, Outs[i].OrigTy))
23333 for (
unsigned i = 0, e = RVLocs.size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
23334 SDValue Val = OutVals[OutIdx];
23343 DAG.
getVTList(MVT::i32, MVT::i32), Val);
23347 Register RegHi = RVLocs[++i].getLocReg();
23353 "Return value register required, but has been reserved."});
23369 "Return value register required, but has been reserved."});
23388 unsigned RetOpc = RISCVISD::RET_GLUE;
23391 if (Func.hasFnAttribute(
"interrupt")) {
23392 if (!Func.getReturnType()->isVoidTy())
23394 "Functions with the interrupt attribute must have void return type!");
23400 if (Kind ==
"supervisor")
23401 RetOpc = RISCVISD::SRET_GLUE;
23402 else if (Kind ==
"rnmi") {
23403 assert(STI.hasFeature(RISCV::FeatureStdExtSmrnmi) &&
23404 "Need Smrnmi extension for rnmi");
23405 RetOpc = RISCVISD::MNRET_GLUE;
23406 }
else if (Kind ==
"qci-nest" || Kind ==
"qci-nonest") {
23407 assert(STI.hasFeature(RISCV::FeatureVendorXqciint) &&
23408 "Need Xqciint for qci-(no)nest");
23409 RetOpc = RISCVISD::QC_C_MILEAVERET_GLUE;
23411 RetOpc = RISCVISD::MRET_GLUE;
23414 return DAG.
getNode(RetOpc,
DL, MVT::Other, RetOps);
23417void RISCVTargetLowering::validateCCReservedRegs(
23418 const SmallVectorImpl<std::pair<llvm::Register, llvm::SDValue>> &Regs,
23427 F,
"Argument register required, but has been reserved."});
23433 if (
N->getNumValues() != 1)
23435 if (!
N->hasNUsesOfValue(1, 0))
23438 SDNode *Copy = *
N->user_begin();
23452 if (Copy->getOperand(Copy->getNumOperands() - 1).getValueType() == MVT::Glue)
23456 bool HasRet =
false;
23457 for (
SDNode *Node : Copy->users()) {
23458 if (Node->getOpcode() != RISCVISD::RET_GLUE)
23465 Chain = Copy->getOperand(0);
23477 if (Constraint.
size() == 1) {
23478 switch (Constraint[0]) {
23495 if (Constraint ==
"vr" || Constraint ==
"vd" || Constraint ==
"vm")
23497 if (Constraint ==
"cr" || Constraint ==
"cR" || Constraint ==
"cf")
23503std::pair<unsigned, const TargetRegisterClass *>
23509 if (Constraint.
size() == 1) {
23510 switch (Constraint[0]) {
23515 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
23516 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
23517 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
23518 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
23519 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
23520 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23521 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
23523 if (VT == MVT::f16) {
23524 if (Subtarget.hasStdExtZfhmin())
23525 return std::make_pair(0U, &RISCV::FPR16RegClass);
23526 if (Subtarget.hasStdExtZhinxmin())
23527 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
23528 }
else if (VT == MVT::f32) {
23529 if (Subtarget.hasStdExtF())
23530 return std::make_pair(0U, &RISCV::FPR32RegClass);
23531 if (Subtarget.hasStdExtZfinx())
23532 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
23533 }
else if (VT == MVT::f64) {
23534 if (Subtarget.hasStdExtD())
23535 return std::make_pair(0U, &RISCV::FPR64RegClass);
23536 if (Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
23537 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23538 if (Subtarget.hasStdExtZdinx() && Subtarget.
is64Bit())
23539 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
23543 if (((VT == MVT::i64 || VT == MVT::f64) && !Subtarget.
is64Bit()) ||
23544 (VT == MVT::i128 && Subtarget.
is64Bit()))
23545 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23550 }
else if (Constraint ==
"vr") {
23551 for (
const auto *RC :
23552 {&RISCV::VRRegClass, &RISCV::VRM2RegClass, &RISCV::VRM4RegClass,
23553 &RISCV::VRM8RegClass, &RISCV::VRN2M1RegClass, &RISCV::VRN3M1RegClass,
23554 &RISCV::VRN4M1RegClass, &RISCV::VRN5M1RegClass,
23555 &RISCV::VRN6M1RegClass, &RISCV::VRN7M1RegClass,
23556 &RISCV::VRN8M1RegClass, &RISCV::VRN2M2RegClass,
23557 &RISCV::VRN3M2RegClass, &RISCV::VRN4M2RegClass,
23558 &RISCV::VRN2M4RegClass}) {
23560 return std::make_pair(0U, RC);
23564 if (
TRI->isTypeLegalForClass(*RC, ContainerVT))
23565 return std::make_pair(0U, RC);
23568 }
else if (Constraint ==
"vd") {
23569 for (
const auto *RC :
23570 {&RISCV::VRNoV0RegClass, &RISCV::VRM2NoV0RegClass,
23571 &RISCV::VRM4NoV0RegClass, &RISCV::VRM8NoV0RegClass,
23572 &RISCV::VRN2M1NoV0RegClass, &RISCV::VRN3M1NoV0RegClass,
23573 &RISCV::VRN4M1NoV0RegClass, &RISCV::VRN5M1NoV0RegClass,
23574 &RISCV::VRN6M1NoV0RegClass, &RISCV::VRN7M1NoV0RegClass,
23575 &RISCV::VRN8M1NoV0RegClass, &RISCV::VRN2M2NoV0RegClass,
23576 &RISCV::VRN3M2NoV0RegClass, &RISCV::VRN4M2NoV0RegClass,
23577 &RISCV::VRN2M4NoV0RegClass}) {
23579 return std::make_pair(0U, RC);
23583 if (
TRI->isTypeLegalForClass(*RC, ContainerVT))
23584 return std::make_pair(0U, RC);
23587 }
else if (Constraint ==
"vm") {
23588 if (
TRI->isTypeLegalForClass(RISCV::VMV0RegClass, VT.
SimpleTy))
23589 return std::make_pair(0U, &RISCV::VMV0RegClass);
23595 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, ContainerVT))
23596 return std::make_pair(0U, &RISCV::VMV0RegClass);
23598 }
else if (Constraint ==
"cr") {
23599 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
23600 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
23601 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
23602 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
23603 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
23604 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23606 return std::make_pair(0U, &RISCV::GPRCRegClass);
23607 }
else if (Constraint ==
"cR") {
23608 if (((VT == MVT::i64 || VT == MVT::f64) && !Subtarget.
is64Bit()) ||
23609 (VT == MVT::i128 && Subtarget.
is64Bit()))
23610 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23611 }
else if (Constraint ==
"cf") {
23612 if (VT == MVT::f16) {
23613 if (Subtarget.hasStdExtZfhmin())
23614 return std::make_pair(0U, &RISCV::FPR16CRegClass);
23615 if (Subtarget.hasStdExtZhinxmin())
23616 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
23617 }
else if (VT == MVT::f32) {
23618 if (Subtarget.hasStdExtF())
23619 return std::make_pair(0U, &RISCV::FPR32CRegClass);
23620 if (Subtarget.hasStdExtZfinx())
23621 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
23622 }
else if (VT == MVT::f64) {
23623 if (Subtarget.hasStdExtD())
23624 return std::make_pair(0U, &RISCV::FPR64CRegClass);
23625 if (Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
23626 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23627 if (Subtarget.hasStdExtZdinx() && Subtarget.
is64Bit())
23628 return std::make_pair(0U, &RISCV::GPRCRegClass);
23637 .
Case(
"{zero}", RISCV::X0)
23638 .
Case(
"{ra}", RISCV::X1)
23639 .
Case(
"{sp}", RISCV::X2)
23640 .
Case(
"{gp}", RISCV::X3)
23641 .
Case(
"{tp}", RISCV::X4)
23642 .
Case(
"{t0}", RISCV::X5)
23643 .
Case(
"{t1}", RISCV::X6)
23644 .
Case(
"{t2}", RISCV::X7)
23645 .
Cases(
"{s0}",
"{fp}", RISCV::X8)
23646 .
Case(
"{s1}", RISCV::X9)
23647 .
Case(
"{a0}", RISCV::X10)
23648 .
Case(
"{a1}", RISCV::X11)
23649 .
Case(
"{a2}", RISCV::X12)
23650 .
Case(
"{a3}", RISCV::X13)
23651 .
Case(
"{a4}", RISCV::X14)
23652 .
Case(
"{a5}", RISCV::X15)
23653 .
Case(
"{a6}", RISCV::X16)
23654 .
Case(
"{a7}", RISCV::X17)
23655 .
Case(
"{s2}", RISCV::X18)
23656 .
Case(
"{s3}", RISCV::X19)
23657 .
Case(
"{s4}", RISCV::X20)
23658 .
Case(
"{s5}", RISCV::X21)
23659 .
Case(
"{s6}", RISCV::X22)
23660 .
Case(
"{s7}", RISCV::X23)
23661 .
Case(
"{s8}", RISCV::X24)
23662 .
Case(
"{s9}", RISCV::X25)
23663 .
Case(
"{s10}", RISCV::X26)
23664 .
Case(
"{s11}", RISCV::X27)
23665 .
Case(
"{t3}", RISCV::X28)
23666 .
Case(
"{t4}", RISCV::X29)
23667 .
Case(
"{t5}", RISCV::X30)
23668 .
Case(
"{t6}", RISCV::X31)
23670 if (XRegFromAlias != RISCV::NoRegister)
23671 return std::make_pair(XRegFromAlias, &RISCV::GPRRegClass);
23680 if (Subtarget.hasStdExtF()) {
23682 .
Cases(
"{f0}",
"{ft0}", RISCV::F0_F)
23683 .
Cases(
"{f1}",
"{ft1}", RISCV::F1_F)
23684 .
Cases(
"{f2}",
"{ft2}", RISCV::F2_F)
23685 .
Cases(
"{f3}",
"{ft3}", RISCV::F3_F)
23686 .
Cases(
"{f4}",
"{ft4}", RISCV::F4_F)
23687 .
Cases(
"{f5}",
"{ft5}", RISCV::F5_F)
23688 .
Cases(
"{f6}",
"{ft6}", RISCV::F6_F)
23689 .
Cases(
"{f7}",
"{ft7}", RISCV::F7_F)
23690 .
Cases(
"{f8}",
"{fs0}", RISCV::F8_F)
23691 .
Cases(
"{f9}",
"{fs1}", RISCV::F9_F)
23692 .
Cases(
"{f10}",
"{fa0}", RISCV::F10_F)
23693 .
Cases(
"{f11}",
"{fa1}", RISCV::F11_F)
23694 .
Cases(
"{f12}",
"{fa2}", RISCV::F12_F)
23695 .
Cases(
"{f13}",
"{fa3}", RISCV::F13_F)
23696 .
Cases(
"{f14}",
"{fa4}", RISCV::F14_F)
23697 .
Cases(
"{f15}",
"{fa5}", RISCV::F15_F)
23698 .
Cases(
"{f16}",
"{fa6}", RISCV::F16_F)
23699 .
Cases(
"{f17}",
"{fa7}", RISCV::F17_F)
23700 .
Cases(
"{f18}",
"{fs2}", RISCV::F18_F)
23701 .
Cases(
"{f19}",
"{fs3}", RISCV::F19_F)
23702 .
Cases(
"{f20}",
"{fs4}", RISCV::F20_F)
23703 .
Cases(
"{f21}",
"{fs5}", RISCV::F21_F)
23704 .
Cases(
"{f22}",
"{fs6}", RISCV::F22_F)
23705 .
Cases(
"{f23}",
"{fs7}", RISCV::F23_F)
23706 .
Cases(
"{f24}",
"{fs8}", RISCV::F24_F)
23707 .
Cases(
"{f25}",
"{fs9}", RISCV::F25_F)
23708 .
Cases(
"{f26}",
"{fs10}", RISCV::F26_F)
23709 .
Cases(
"{f27}",
"{fs11}", RISCV::F27_F)
23710 .
Cases(
"{f28}",
"{ft8}", RISCV::F28_F)
23711 .
Cases(
"{f29}",
"{ft9}", RISCV::F29_F)
23712 .
Cases(
"{f30}",
"{ft10}", RISCV::F30_F)
23713 .
Cases(
"{f31}",
"{ft11}", RISCV::F31_F)
23715 if (FReg != RISCV::NoRegister) {
23716 assert(RISCV::F0_F <= FReg && FReg <= RISCV::F31_F &&
"Unknown fp-reg");
23717 if (Subtarget.hasStdExtD() && (VT == MVT::f64 || VT == MVT::Other)) {
23718 unsigned RegNo = FReg - RISCV::F0_F;
23719 unsigned DReg = RISCV::F0_D + RegNo;
23720 return std::make_pair(DReg, &RISCV::FPR64RegClass);
23722 if (VT == MVT::f32 || VT == MVT::Other)
23723 return std::make_pair(FReg, &RISCV::FPR32RegClass);
23724 if (Subtarget.hasStdExtZfhmin() && VT == MVT::f16) {
23725 unsigned RegNo = FReg - RISCV::F0_F;
23726 unsigned HReg = RISCV::F0_H + RegNo;
23727 return std::make_pair(HReg, &RISCV::FPR16RegClass);
23734 .
Case(
"{v0}", RISCV::V0)
23735 .
Case(
"{v1}", RISCV::V1)
23736 .
Case(
"{v2}", RISCV::V2)
23737 .
Case(
"{v3}", RISCV::V3)
23738 .
Case(
"{v4}", RISCV::V4)
23739 .
Case(
"{v5}", RISCV::V5)
23740 .
Case(
"{v6}", RISCV::V6)
23741 .
Case(
"{v7}", RISCV::V7)
23742 .
Case(
"{v8}", RISCV::V8)
23743 .
Case(
"{v9}", RISCV::V9)
23744 .
Case(
"{v10}", RISCV::V10)
23745 .
Case(
"{v11}", RISCV::V11)
23746 .
Case(
"{v12}", RISCV::V12)
23747 .
Case(
"{v13}", RISCV::V13)
23748 .
Case(
"{v14}", RISCV::V14)
23749 .
Case(
"{v15}", RISCV::V15)
23750 .
Case(
"{v16}", RISCV::V16)
23751 .
Case(
"{v17}", RISCV::V17)
23752 .
Case(
"{v18}", RISCV::V18)
23753 .
Case(
"{v19}", RISCV::V19)
23754 .
Case(
"{v20}", RISCV::V20)
23755 .
Case(
"{v21}", RISCV::V21)
23756 .
Case(
"{v22}", RISCV::V22)
23757 .
Case(
"{v23}", RISCV::V23)
23758 .
Case(
"{v24}", RISCV::V24)
23759 .
Case(
"{v25}", RISCV::V25)
23760 .
Case(
"{v26}", RISCV::V26)
23761 .
Case(
"{v27}", RISCV::V27)
23762 .
Case(
"{v28}", RISCV::V28)
23763 .
Case(
"{v29}", RISCV::V29)
23764 .
Case(
"{v30}", RISCV::V30)
23765 .
Case(
"{v31}", RISCV::V31)
23767 if (VReg != RISCV::NoRegister) {
23768 if (
TRI->isTypeLegalForClass(RISCV::VMRegClass, VT.
SimpleTy))
23769 return std::make_pair(VReg, &RISCV::VMRegClass);
23770 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, VT.
SimpleTy))
23771 return std::make_pair(VReg, &RISCV::VRRegClass);
23772 for (
const auto *RC :
23773 {&RISCV::VRM2RegClass, &RISCV::VRM4RegClass, &RISCV::VRM8RegClass}) {
23774 if (
TRI->isTypeLegalForClass(*RC, VT.
SimpleTy)) {
23775 VReg =
TRI->getMatchingSuperReg(VReg, RISCV::sub_vrm1_0, RC);
23776 return std::make_pair(VReg, RC);
23782 std::pair<Register, const TargetRegisterClass *> Res =
23788 if (Res.second == &RISCV::GPRF16RegClass ||
23789 Res.second == &RISCV::GPRF32RegClass ||
23790 Res.second == &RISCV::GPRPairRegClass)
23791 return std::make_pair(Res.first, &RISCV::GPRRegClass);
23799 if (ConstraintCode.
size() == 1) {
23800 switch (ConstraintCode[0]) {
23815 if (Constraint.
size() == 1) {
23816 switch (Constraint[0]) {
23819 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
23821 if (isInt<12>(CVal))
23834 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
23836 if (isUInt<5>(CVal))
23854 if (Subtarget.hasStdExtZtso()) {
23870 if (Subtarget.hasStdExtZtso()) {
23878 if (Subtarget.enableTrailingSeqCstFence() && isa<StoreInst>(Inst) &&
23897 if (Subtarget.hasForcedAtomics())
23902 if (Subtarget.hasStdExtZacas() &&
23903 (
Size >= 32 || Subtarget.hasStdExtZabha()))
23909 if (
Size < 32 && !Subtarget.hasStdExtZabha())
23921 return Intrinsic::riscv_masked_atomicrmw_xchg;
23923 return Intrinsic::riscv_masked_atomicrmw_add;
23925 return Intrinsic::riscv_masked_atomicrmw_sub;
23927 return Intrinsic::riscv_masked_atomicrmw_nand;
23929 return Intrinsic::riscv_masked_atomicrmw_max;
23931 return Intrinsic::riscv_masked_atomicrmw_min;
23933 return Intrinsic::riscv_masked_atomicrmw_umax;
23935 return Intrinsic::riscv_masked_atomicrmw_umin;
23958 unsigned XLen = Subtarget.
getXLen();
23982 unsigned ValWidth =
23987 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
23990 Builder.
CreateCall(LrwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
24002 if (Subtarget.hasForcedAtomics())
24006 if (!(Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas()) &&
24015 unsigned XLen = Subtarget.
getXLen();
24017 Intrinsic::ID CmpXchgIntrID = Intrinsic::riscv_masked_cmpxchg;
24025 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, Ordering});
24032 EVT DataVT)
const {
24048 return Subtarget.hasStdExtZfhmin();
24050 return Subtarget.hasStdExtF();
24052 return Subtarget.hasStdExtD();
24084 "RVVBitsPerBlock changed, audit needed");
24093 if (!Subtarget.hasVendorXTHeadMemIdx())
24099 Base =
Op->getOperand(0);
24101 int64_t RHSC =
RHS->getSExtValue();
24107 bool isLegalIndexedOffset =
false;
24108 for (
unsigned i = 0; i < 4; i++)
24109 if (isInt<5>(RHSC >> i) && ((RHSC % (1LL << i)) == 0)) {
24110 isLegalIndexedOffset =
true;
24114 if (!isLegalIndexedOffset)
24131 VT = LD->getMemoryVT();
24132 Ptr = LD->getBasePtr();
24133 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
24134 VT = ST->getMemoryVT();
24135 Ptr = ST->getBasePtr();
24151 if (Subtarget.hasVendorXCVmem() && !Subtarget.
is64Bit()) {
24156 Base = LS->getBasePtr();
24160 if (
Base ==
Op->getOperand(0))
24162 else if (
Base ==
Op->getOperand(1))
24174 VT = LD->getMemoryVT();
24175 Ptr = LD->getBasePtr();
24176 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
24177 VT = ST->getMemoryVT();
24178 Ptr = ST->getBasePtr();
24221 const Constant *PersonalityFn)
const {
24226 const Constant *PersonalityFn)
const {
24241 bool IsSigned)
const {
24256 const bool HasZmmul = Subtarget.hasStdExtZmmul();
24260 auto *ConstNode = cast<ConstantSDNode>(
C);
24261 const APInt &Imm = ConstNode->getAPIntValue();
24264 if (Subtarget.hasVendorXqciac() && Imm.isSignedIntN(12))
24268 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
24269 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
24273 if (Subtarget.hasStdExtZba() && !Imm.isSignedIntN(12) &&
24274 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
24275 (Imm - 8).isPowerOf2()))
24280 if (!Imm.isSignedIntN(12) && Imm.countr_zero() < 12 &&
24281 ConstNode->hasOneUse()) {
24282 APInt ImmS = Imm.ashr(Imm.countr_zero());
24283 if ((ImmS + 1).isPowerOf2() || (ImmS - 1).isPowerOf2() ||
24284 (1 - ImmS).isPowerOf2())
24307 if (C1.
isSignedIntN(12) && !(C1 * C2).isSignedIntN(12))
24316 unsigned *
Fast)
const {
24319 *
Fast = Subtarget.enableUnalignedScalarMem();
24320 return Subtarget.enableUnalignedScalarMem();
24336 *
Fast = Subtarget.enableUnalignedVectorMem();
24337 return Subtarget.enableUnalignedVectorMem();
24346 if (FuncAttributes.
hasFnAttr(Attribute::NoImplicitFloat))
24358 const unsigned MinVLenInBytes =
24361 if (
Op.size() < MinVLenInBytes)
24376 MVT PreferredVT = (
Op.isMemset() && !
Op.isZeroMemset()) ? MVT::i8 : ELenVT;
24380 if (PreferredVT != MVT::i8 && !Subtarget.enableUnalignedVectorMem()) {
24382 if (
Op.isFixedDstAlign())
24383 RequiredAlign = std::min(RequiredAlign,
Op.getDstAlign());
24385 RequiredAlign = std::min(RequiredAlign,
Op.getSrcAlign());
24393 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
24394 bool IsABIRegCopy = CC.has_value();
24397 MVT PairVT = Subtarget.
is64Bit() ? MVT::i128 : MVT::i64;
24398 if ((ValueVT == PairVT ||
24399 (!Subtarget.
is64Bit() && Subtarget.hasStdExtZdinx() &&
24400 ValueVT == MVT::f64)) &&
24401 NumParts == 1 && PartVT == MVT::Untyped) {
24404 if (ValueVT == MVT::f64)
24409 Parts[0] = DAG.
getNode(RISCVISD::BuildGPRPair,
DL, PartVT,
Lo,
Hi);
24413 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
24414 PartVT == MVT::f32) {
24429 [[maybe_unused]]
unsigned ValLMUL =
24433 [[maybe_unused]]
unsigned PartLMUL =
24436 assert(ValNF == PartNF && ValLMUL == PartLMUL &&
24437 "RISC-V vector tuple type only accepts same register class type "
24458 if (PartVTBitSize % ValueVTBitSize == 0) {
24459 assert(PartVTBitSize >= ValueVTBitSize);
24466 if (ValueEltVT != PartEltVT) {
24467 if (PartVTBitSize > ValueVTBitSize) {
24469 assert(Count != 0 &&
"The number of element should not be zero.");
24470 EVT SameEltTypeVT =
24488 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
24489 bool IsABIRegCopy = CC.has_value();
24491 MVT PairVT = Subtarget.
is64Bit() ? MVT::i128 : MVT::i64;
24492 if ((ValueVT == PairVT ||
24493 (!Subtarget.
is64Bit() && Subtarget.hasStdExtZdinx() &&
24494 ValueVT == MVT::f64)) &&
24495 NumParts == 1 && PartVT == MVT::Untyped) {
24506 if (ValueVT == MVT::f64)
24511 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
24512 PartVT == MVT::f32) {
24534 if (PartVTBitSize % ValueVTBitSize == 0) {
24535 assert(PartVTBitSize >= ValueVTBitSize);
24536 EVT SameEltTypeVT = ValueVT;
24543 if (ValueEltVT != PartEltVT) {
24545 assert(Count != 0 &&
"The number of element should not be zero.");
24564 bool OptSize = Attr.
hasFnAttr(Attribute::MinSize);
24571 unsigned Opc =
N->getOpcode();
24580 M, Intrinsic::thread_pointer, IRB.
getPtrTy());
24599 if (M->getStackProtectorGuard() ==
"tls") {
24601 int Offset = M->getStackProtectorGuardOffset();
24609 Align Alignment)
const {
24621 if (!Subtarget.enableUnalignedVectorMem() &&
24633 "Invalid call instruction for a KCFI check");
24635 MBBI->getOpcode()));
24638 Target.setIsRenamable(
false);
24646#define GET_REGISTER_MATCHER
24647#include "RISCVGenAsmMatcher.inc"
24667 const MDNode *NontemporalInfo =
I.getMetadata(LLVMContext::MD_nontemporal);
24669 if (NontemporalInfo ==
nullptr)
24677 int NontemporalLevel = 5;
24678 const MDNode *RISCVNontemporalInfo =
24679 I.getMetadata(
"riscv-nontemporal-domain");
24680 if (RISCVNontemporalInfo !=
nullptr)
24683 cast<ConstantAsMetadata>(RISCVNontemporalInfo->
getOperand(0))
24687 assert((1 <= NontemporalLevel && NontemporalLevel <= 5) &&
24688 "RISC-V target doesn't support this non-temporal domain.");
24690 NontemporalLevel -= 2;
24692 if (NontemporalLevel & 0b1)
24694 if (NontemporalLevel & 0b10)
24707 return TargetFlags;
24717 return isTypeLegal(VT) && Subtarget.hasStdExtZvbb();
24720 return Subtarget.hasStdExtZbb() &&
24731 if (Subtarget.hasStdExtZalasr()) {
24732 if (Subtarget.hasStdExtZtso()) {
24737 auto *LI = dyn_cast<LoadInst>(
I);
24738 auto *SI = dyn_cast<StoreInst>(
I);
24748 return isa<LoadInst>(
I) || isa<StoreInst>(
I);
24755 return isa<LoadInst>(
I) || isa<StoreInst>(
I);
24762 if (
Op == Instruction::Add ||
Op == Instruction::Sub ||
24763 Op == Instruction::And ||
Op == Instruction::Or ||
24764 Op == Instruction::Xor ||
Op == Instruction::InsertElement ||
24765 Op == Instruction::ShuffleVector ||
Op == Instruction::Load ||
24766 Op == Instruction::Freeze ||
Op == Instruction::Store)
24774 !isa<ReturnInst>(&Inst))
24777 if (
const AllocaInst *AI = dyn_cast<AllocaInst>(&Inst)) {
24778 if (AI->getAllocatedType()->isScalableTy())
24786RISCVTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
24794 if (!Subtarget.hasShortForwardBranchOpt())
24796 EVT VT =
N->getValueType(0);
24797 if (!(VT == MVT::i32 || (VT == MVT::i64 && Subtarget.
is64Bit())))
24801 if (Divisor.
sgt(2048) || Divisor.
slt(-2048))
24806bool RISCVTargetLowering::shouldFoldSelectWithSingleBitTest(
24807 EVT VT,
const APInt &AndMask)
const {
24808 if (Subtarget.hasStdExtZicond() || Subtarget.hasVendorXVentanaCondOps())
24809 return !Subtarget.hasStdExtZbs() && AndMask.
ugt(1024);
24813unsigned RISCVTargetLowering::getMinimumJumpTableEntries()
const {
24821 if (Subtarget.hasStdExtZicfilp()) {
24828 return DAG.
getNode(RISCVISD::SW_GUARDED_BRIND, dl, MVT::Other, Chain,
Addr);
24845std::pair<const TargetRegisterClass *, uint8_t>
24865#define GET_RISCVVIntrinsicsTable_IMPL
24866#include "RISCVGenSearchableTables.inc"
24881 Align StackAlign)
const {
24885 unsigned StackProbeSize =
24889 return StackProbeSize ? StackProbeSize : StackAlign.
value();
24904 cast<ConstantSDNode>(
Op.getOperand(2))->getMaybeAlignValue();
24906 EVT VT =
Op.getValueType();
24910 Chain = SP.getValue(1);
24917 Chain = DAG.
getNode(RISCVISD::PROBED_ALLOCA, dl, MVT::Other, Chain, SP);
24927 Register TargetReg =
MI.getOperand(0).getReg();
24930 bool IsRV64 = Subtarget.
is64Bit();
24938 MF.
insert(MBBInsertPoint, LoopTestMBB);
24940 MF.
insert(MBBInsertPoint, ExitMBB);
24956 TII->get(IsRV64 ? RISCV::SD : RISCV::SW))
24979 MI.eraseFromParent();
24981 return ExitMBB->
begin()->getParent();
24986 static const MCPhysReg RCRegs[] = {RISCV::FRM, RISCV::FFLAGS};
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 LowerPREFETCH(SDValue Op, SelectionDAG &DAG)
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)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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)
static InstructionCost getCost(Instruction &Inst, TTI::TargetCostKind CostKind, TargetTransformInfo &TTI, TargetLibraryInfo &TLI)
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,...
#define CC_VLS_CASE(ABIVlen)
static SDValue combineSelectToBinOp(SDNode *N, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static Align getPrefTypeAlign(EVT VT, SelectionDAG &DAG)
static std::optional< bool > matchSetCC(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue Val)
static SDValue customLegalizeToWOpWithSExt(SDNode *N, SelectionDAG &DAG)
static SDValue foldBinOpIntoSelectIfProfitable(SDNode *BO, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue customLegalizeToWOp(SDNode *N, SelectionDAG &DAG, int NumOp, unsigned ExtOpc=ISD::ANY_EXTEND)
static bool combine_CC(SDValue &LHS, SDValue &RHS, SDValue &CC, const SDLoc &DL, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static MachineBasicBlock * emitBuildPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static Intrinsic::ID getIntrinsicForMaskedAtomicRMWBinOp(unsigned GRLen, AtomicRMWInst::BinOp BinOp)
static void translateSetCCForBranch(const SDLoc &DL, SDValue &LHS, SDValue &RHS, ISD::CondCode &CC, SelectionDAG &DAG)
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
Register const TargetRegisterInfo * TRI
This file provides utility analysis objects describing memory locations.
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)
MachineInstr unsigned OpIdx
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 * emitQuietFCMP(MachineInstr &MI, MachineBasicBlock *BB, unsigned RelOpcode, unsigned EqOpcode, const RISCVSubtarget &Subtarget)
static bool isLowSourceShuffle(ArrayRef< int > Mask, int Span)
Is this mask only using elements from the first span of the input?
static bool isZipOdd(const std::array< std::pair< int, int >, 2 > &SrcInfo, ArrayRef< int > Mask, unsigned &Factor)
Given a shuffle which can be represented as a pair of two slides, see if it is a zipodd idiom.
static SDValue lowerVZIP(unsigned Opc, SDValue Op0, SDValue Op1, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerBuildVectorOfConstants(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue performVECREDUCECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
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 SDValue combineTruncToVnclip(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::optional< APInt > getExactInteger(const APFloat &APF, uint32_t BitWidth)
static SDValue performVP_TRUNCATECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isInterleaveShuffle(ArrayRef< int > Mask, MVT VT, int &EvenSrc, int &OddSrc, const RISCVSubtarget &Subtarget)
Is this shuffle interleaving contiguous elements from one vector into the even elements and contiguou...
static bool narrowIndex(SDValue &N, ISD::MemIndexType IndexType, SelectionDAG &DAG)
According to the property that indexed load/store instructions zero-extend their indices,...
static SDValue getSingleShuffleSrc(MVT VT, SDValue V1, SDValue V2)
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 bool isLegalBitRotate(ArrayRef< int > Mask, EVT VT, const RISCVSubtarget &Subtarget, MVT &RotateVT, unsigned &RotateAmt)
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 SDValue simplifyOp_VL(SDNode *N)
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 bool isAlternating(const std::array< std::pair< int, int >, 2 > &SrcInfo, ArrayRef< int > Mask, unsigned Factor, bool RequiredPolarity)
static const RISCV::RISCVMaskedPseudoInfo * lookupMaskedIntrinsic(uint16_t MCOpcode, RISCVVType::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 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 cl::opt< bool > ReassocShlAddiAdd("reassoc-shl-addi-add", cl::Hidden, cl::desc("Swap add and addi in cases where the add may " "be combined with a shift"), cl::init(true))
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 foldReduceOperandViaVQDOT(SDValue InVec, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue reverseZExtICmpCombine(SDNode *N, 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 SDValue reduceANDOfAtomicLoad(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static unsigned getRVVReductionOp(unsigned ISDOpcode)
static SDValue combineSubShiftToOrcB(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
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 lowerFixedVectorSegLoadIntrinsics(unsigned IntNo, SDValue Op, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
static SDValue combineVectorMulToSraBitcast(SDNode *N, SelectionDAG &DAG)
static bool isLocalRepeatingShuffle(ArrayRef< int > Mask, int Span)
Is this mask local (i.e.
static bool legalizeScatterGatherIndexType(SDLoc DL, SDValue &Index, ISD::MemIndexType &IndexType, RISCVTargetLowering::DAGCombinerInfo &DCI)
static bool isSpanSplatShuffle(ArrayRef< int > Mask, int Span)
Return true for a mask which performs an arbitrary shuffle within the first span, and then repeats th...
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=RISCVVType::TAIL_UNDISTURBED_MASK_UNDISTURBED)
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 expandMulToAddOrSubOfShl(SDNode *N, SelectionDAG &DAG, uint64_t MulAmt)
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)
const uint64_t ModeMask64
static SDValue lowerVectorIntrinsicScalars(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 combineShlAddIAddImpl(SDNode *N, SDValue AddI, SDValue Other, SelectionDAG &DAG)
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 SDValue performSIGN_EXTEND_INREGCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
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 bool isValidVisniInsertExtractIndex(SDValue Idx)
static Value * useTpOffset(IRBuilderBase &IRB, unsigned Offset)
static SDValue combineAddOfBooleanXor(SDNode *N, SelectionDAG &DAG)
static SDValue getZeroPaddedAdd(const SDLoc &DL, SDValue A, SDValue B, SelectionDAG &DAG)
Given fixed length vectors A and B with equal element types, but possibly different number of element...
const uint32_t ModeMask32
static SDValue combineTruncOfSraSext(SDNode *N, SelectionDAG &DAG)
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=RISCVVType::TAIL_UNDISTURBED_MASK_UNDISTURBED)
static MachineBasicBlock * emitSplitF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const RISCVSubtarget &Subtarget)
static SDValue combineVqdotAccum(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static MachineBasicBlock * emitVFROUND_NOEXCEPT_MASK(MachineInstr &MI, MachineBasicBlock *BB, unsigned CVTXOpc)
static SDValue SplitVectorOp(SDValue Op, SelectionDAG &DAG)
static SDValue combineToVCPOP(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
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 lowerBuildVectorViaVID(SDValue Op, 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 lowerFixedVectorSegStoreIntrinsics(unsigned IntNo, SDValue Op, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
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 lowerVectorXRINT_XROUND(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
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 bool isElementRotate(const std::array< std::pair< int, int >, 2 > &SrcInfo, unsigned NumElts)
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 SDValue lowerVECTOR_SHUFFLEAsVRGatherVX(ShuffleVectorSDNode *SVN, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
Match a single source shuffle which is an identity except that some particular element is repeated.
static bool isNonZeroAVL(SDValue AVL)
static SDValue lowerFP_TO_INT(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static MVT getQDOTXResultType(MVT OpVT)
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 foldConcatVector(SDValue V1, SDValue V2)
If concat_vector(V1,V2) could be folded away to some existing vector source, return it.
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 combineShlAddIAdd(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 SDValue expandMulToNAFSequence(SDNode *N, SelectionDAG &DAG, uint64_t MulAmt)
static SDValue combineToVWMACC(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isZipEven(const std::array< std::pair< int, int >, 2 > &SrcInfo, ArrayRef< int > Mask, unsigned &Factor)
Given a shuffle which can be represented as a pair of two slides, see if it is a zipeven idiom.
static SDValue combineVectorSizedSetCCEquality(EVT VT, SDValue X, SDValue Y, ISD::CondCode CC, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Try to map an integer comparison with size > XLEN to vector instructions before type legalization spl...
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 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
Contains matchers for matching SelectionDAG nodes and values.
static bool isCommutative(Instruction *I, Value *ValWithUses)
static Type * getValueType(Value *V)
Returns the type of the given value/instruction V.
This file defines the SmallSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
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.
bool isNegatedPowerOf2() const
Check if this APInt's negated value is a power of two greater than zero.
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.
LLVM_ABI 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.
unsigned getBitWidth() const
Return the number of bits in the APInt.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
bool isNegative() const
Determine sign of this APInt.
LLVM_ABI APInt sdiv(const APInt &RHS) const
Signed division function for APInt.
void clearAllBits()
Set every bit to 0.
unsigned countr_zero() const
Count the number of trailing zero bits.
bool isSignedIntN(unsigned N) const
Check if this APInt has an N-bits signed integer value.
static LLVM_ABI 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.
LLVM_ABI void insertBits(const APInt &SubBits, unsigned bitPosition)
Insert the bits from a smaller APInt starting at bitPosition.
LLVM_ABI 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)
LLVM_ABI 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.
LLVM_ABI 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.
This is an SDNode representing atomic operations.
const SDValue & getBasePtr() const
LLVM_ABI bool hasFnAttr(Attribute::AttrKind Kind) const
Return true if the attribute exists for the function.
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
static LLVM_ABI BaseIndexOffset match(const SDNode *N, const SelectionDAG &DAG)
Parses tree in N for base, index, offset addresses.
LLVM Basic Block Representation.
LLVM_ABI 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,...
LLVM_ABI 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.
LLVM_ABI 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
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
LLVM_ABI bool isIndirectCall() const
Return true if the callsite is an indirect call.
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
int64_t getSExtValue() const
This is an important base class in LLVM.
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
The size in bits of the pointer representation in a given address space.
LLVM_ABI 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.
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
Module * getParent()
Get the module that this global value is contained inside of...
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="")
IntegerType * getIntNTy(unsigned N)
Fetch the type representing an N-bit integer.
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.
BasicBlock * GetInsertBlock() const
IntegerType * getInt64Ty()
Fetch the type representing a 64-bit integer.
LLVM_ABI 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.
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.
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)
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
static InstructionCost getInvalid(CostType Val=0)
LLVM_ABI 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.
LLVM_ABI 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.
LLVM_ABI 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.
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, SMLoc Loc=SMLoc())
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 LLVM_ABI 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.
LLVM_ABI 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()
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI 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.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI 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.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI 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 TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
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.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
LLVM_ABI void collectDebugValues(SmallVectorImpl< MachineInstr * > &DbgValues)
Scan instructions immediately following MI and collect any matching DBG_VALUEs.
void setFlag(MIFlag Flag)
Set a MI flag.
LLVM_ABI 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,...
LLVM_ABI 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.
AtomicOrdering getSuccessOrdering() const
Return the atomic ordering requirements for this memory operation.
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.
Metadata * getModuleFlag(StringRef Key) const
Return the corresponding value if Key appears in module flags, otherwise return null.
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
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
RISCVVRGatherCostModelEnum getVRGatherCostModel() 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)
ArrayRef< MCPhysReg > getRoundingControlRegisters() const override
Returns a 0 terminated array of rounding control registers that can be attached into strict FP call.
static MVT getM1VT(MVT VT)
Given a vector (either fixed or scalable), return the scalable vector corresponding to a vector regis...
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 mayBeEmittedAsTailCall(const CallInst *CI) const override
Return true if the target may be able emit the call instruction as a tail call.
RISCVTargetLowering(const TargetMachine &TM, const RISCVSubtarget &STI)
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
Instruction * emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
Inserts in the IR a target-specific intrinsic specifying a fence.
bool isTruncateFree(Type *SrcTy, Type *DstTy) const override
Return true if it's free to truncate a value of type FromTy to type ToTy.
bool shouldRemoveExtendFromGSIndex(SDValue Extend, EVT DataVT) const override
Value * emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI, Value *AlignedAddr, Value *Incr, Value *Mask, Value *ShiftAmt, AtomicOrdering Ord) const override
Perform a masked atomicrmw using a target-specific intrinsic.
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
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 getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
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.
bool hasAndNot(SDValue Y) const override
Return true if the target has a bitwise and-not operation: X = ~A & B This can be used to simplify se...
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...
bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override
Return true if result of the specified node is used by a return node only.
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const override
Return true if an FMA operation is faster than a pair of fmul and fadd instructions.
TargetLowering::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *CI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
Register getExceptionSelectorRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
unsigned getCustomCtpopCost(EVT VT, ISD::CondCode Cond) const override
Return the maximum number of "x & (x - 1)" operations that can be done instead of deferring to a cust...
void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override
This method should be implemented by targets that mark instructions with the 'hasPostISelHook' flag.
bool isShuffleMaskLegal(ArrayRef< int > M, EVT VT) const override
Return true if the given shuffle mask can be codegen'd directly, or if it should be stack expanded.
bool isCheapToSpeculateCttz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic cttz.
bool isLegalICmpImmediate(int64_t Imm) const override
Return true if the specified immediate is legal icmp immediate, that is the target has icmp instructi...
ISD::NodeType getExtendForAtomicCmpSwapArg() const override
Returns how the platform's atomic compare and swap expects its comparison value to be extended (ZERO_...
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.
int getLegalZfaFPImm(const APFloat &Imm, EVT VT) const
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
Lower the specified operand into the Ops vector.
bool splitValueIntoRegisterParts(SelectionDAG &DAG, const SDLoc &DL, SDValue Val, SDValue *Parts, unsigned NumParts, MVT PartVT, std::optional< CallingConv::ID > CC) const override
Target-specific splitting of values into parts that fit a register storing a legal type.
Instruction * emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Return the number of registers for a given MVT, ensuring vectors are treated as a series of gpr sized...
ConstraintType getConstraintType(StringRef Constraint) const override
getConstraintType - Given a constraint letter, return the type of constraint it is for this target.
MachineInstr * EmitKCFICheck(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator &MBBI, const TargetInstrInfo *TII) const override
bool 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.
static unsigned getRegClassIDForLMUL(RISCVVType::VLMUL LMul)
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.
static bool isSpreadMask(ArrayRef< int > Mask, unsigned Factor, unsigned &Index)
Match a mask which "spreads" the leading elements of a vector evenly across the result.
static RISCVVType::VLMUL getLMUL(MVT VT)
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth) const override
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
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...
bool shouldFoldSelectWithIdentityConstant(unsigned BinOpcode, EVT VT, unsigned SelectOpcode, SDValue X, SDValue Y) const override
Return true if pulling a binary operation into a select with an identity constant is profitable.
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
size_t use_size() const
Return the number of uses of this node.
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
std::optional< APInt > bitcastToAPInt() const
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
void setCFIType(uint32_t Type)
bool isUndef() const
Returns true if the node type is UNDEF or POISON.
iterator_range< user_iterator > users()
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
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...
LLVM_ABI Align getReducedAlign(EVT VT, bool UseABI)
In most cases this function returns the ABI alignment for a given type, except for illegal vector typ...
LLVM_ABI 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)
SDValue getExtractVectorElt(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Extract element at Idx from Vec.
LLVM_ABI unsigned ComputeMaxSignificantBits(SDValue Op, unsigned Depth=0) const
Get the upper bound on bit size for this Value Op as a signed integer.
LLVM_ABI 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)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL)
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI 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),...
LLVM_ABI SDValue getNeutralElement(unsigned Opcode, const SDLoc &DL, EVT VT, SDNodeFlags Flags)
Get the (commutative) neutral element for the given opcode, if it exists.
LLVM_ABI SDValue getAtomicLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT MemVT, EVT VT, SDValue Chain, SDValue Ptr, MachineMemOperand *MMO)
LLVM_ABI SDValue getVScale(const SDLoc &DL, EVT VT, APInt MulImm, bool ConstantFold=true)
Return a node that represents the runtime scaling 'MulImm * RuntimeVL'.
LLVM_ABI SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
LLVM_ABI 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)
LLVM_ABI 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...
LLVM_ABI 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-...
LLVM_ABI SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
SDValue getExtractSubvector(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Return the VT typed sub-vector of Vec at Idx.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getElementCount(const SDLoc &DL, EVT VT, ElementCount EC, bool ConstantFold=true)
LLVM_ABI 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,...
LLVM_ABI 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=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
SDValue getInsertSubvector(const SDLoc &DL, SDValue Vec, SDValue SubVec, unsigned Idx)
Insert SubVec at the Idx element of Vec.
LLVM_ABI SDValue getStepVector(const SDLoc &DL, EVT ResVT, const APInt &StepVal)
Returns a vector of type ResVT whose elements contain the linear sequence <0, Step,...
LLVM_ABI 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.
LLVM_ABI 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.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
LLVM_ABI 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
LLVM_ABI 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...
LLVM_ABI 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).
LLVM_ABI 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.
LLVM_ABI 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.
LLVM_ABI 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...
LLVM_ABI SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI 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
LLVM_ABI 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)
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI 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)
LLVM_ABI 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())
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI 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.
LLVM_ABI 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.
LLVM_ABI 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 ...
LLVM_ABI bool SignBitIsZero(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero.
SDValue getInsertVectorElt(const SDLoc &DL, SDValue Vec, SDValue Elt, unsigned Idx)
Insert Elt into Vec at offset Idx.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDValue > Ops, SDNodeFlags Flags=SDNodeFlags())
LLVM_ABI 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)
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
LLVM_ABI 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...
LLVM_ABI std::pair< SDValue, SDValue > SplitEVL(SDValue N, EVT VecVT, const SDLoc &DL)
Split the explicit vector length parameter of a VP operation.
LLVM_ABI SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either any-extending or truncat...
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getScatterVP(SDVTList VTs, EVT VT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
LLVM_ABI 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...
LLVM_ABI bool isKnownNeverNaN(SDValue Op, const APInt &DemandedElts, 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 in...
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI 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.
LLVM_ABI 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)
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI 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.
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI 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.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI 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...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
void addCallSiteInfo(const SDNode *Node, CallSiteInfo &&CallInfo)
Set CallSiteInfo to be associated with Node.
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI 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.
LLVM_ABI 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.
LLVM_ABI 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.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
LLVM_ABI SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a logical NOT operation as (XOR Val, BooleanOne).
LLVM_ABI SDValue getMaskedScatter(SDVTList VTs, EVT MemVT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType, bool IsTruncating=false)
static LLVM_ABI bool isSelectMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from its source vectors without lane crossings.
static LLVM_ABI 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,...
static LLVM_ABI bool isSingleSourceMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector.
static LLVM_ABI 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 LLVM_ABI bool isIdentityMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector without lane crossin...
static LLVM_ABI bool isReverseMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask swaps the order of elements from exactly one source vector.
static LLVM_ABI bool isInsertSubvectorMask(ArrayRef< int > Mask, int NumSrcElts, int &NumSubElts, int &Index)
Return true if this shuffle mask is an insert subvector mask.
static LLVM_ABI 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 LLVM_ABI 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.
iterator insert(iterator I, T &&Elt)
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.
This class is used to represent ISD::STORE nodes.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
StringRef - Represent a constant reference to a string, i.e.
constexpr size_t size() const
size - Get the string size.
LLVM_ABI 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)
Information about stack frame layout on the target.
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
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 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 setPartialReduceMLAAction(unsigned Opc, MVT AccVT, MVT InputVT, LegalizeAction Action)
Indicate how a PARTIAL_REDUCE_U/SMLA node with Acc type AccVT and Input type InputVT should be treate...
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.
virtual bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0) const
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
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
unsigned EmitCallGraphSection
Emit section containing call graph metadata.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual bool isRegisterReservedByUser(Register R) const
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
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.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
LLVM_ABI bool isScalableTy(SmallPtrSetImpl< const Type * > &Visited) const
Return true if this is a type whose size is a known multiple of vscale.
bool isStructTy() const
True if this is an instance of StructType.
bool isTargetExtTy() const
Return true if this is a target extension type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
bool isIntegerTy() const
True if this is an instance of IntegerType.
LLVM_ABI Type * getStructElementType(unsigned N) const
LLVM_ABI unsigned getIntegerBitWidth() const
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.
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
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.
@ PreserveMost
Used for runtime calls that preserves most registers.
@ 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.
LLVM_ABI 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.
@ SET_FPENV
Sets the current floating-point environment.
@ 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.
@ RESET_FPENV
Set floating-point environment to default state.
@ 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...
@ SET_FPMODE
Sets the current dynamic floating-point control modes.
@ 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.
@ RESET_FPMODE
Sets default dynamic floating-point control modes.
@ 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 N vectors from N input vectors, where N is the factor to...
@ 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).
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
@ 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...
@ GET_FPMODE
Reads the current dynamic floating-point control modes.
@ GET_FPENV
Gets the current floating-point environment.
@ 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 maximum on two values, following IEEE-754 definition...
@ SSHLSAT
RESULT = [US]SHLSAT(LHS, RHS) - Perform saturation left shift.
@ 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 N vectors from N input vectors, where N is the factor ...
@ 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,...
LLVM_ABI 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 isExtOpcode(unsigned Opcode)
LLVM_ABI 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...
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
LLVM_ABI std::optional< unsigned > getVPMaskIdx(unsigned Opcode)
The operand position of the vector mask.
LLVM_ABI std::optional< unsigned > getVPExplicitVectorLengthIdx(unsigned Opcode)
The operand position of the explicit vector length parameter.
LLVM_ABI 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...
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
LLVM_ABI 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,...
LLVM_ABI bool isBuildVectorAllOnes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are ~0 or undef.
LLVM_ABI 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).
LLVM_ABI 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...
LLVM_ABI 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.
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
CastInst_match< OpTy, TruncInst > m_Trunc(const OpTy &Op)
Matches Trunc.
TwoOps_match< Val_t, Idx_t, Instruction::ExtractElement > m_ExtractElt(const Val_t &Val, const Idx_t &Idx)
Matches ExtractElementInst.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
ThreeOps_match< Val_t, Elt_t, Idx_t, Instruction::InsertElement > m_InsertElt(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx)
Matches InsertElementInst.
unsigned getBrCond(CondCode CC, unsigned SelectOpc=0)
static RISCVVType::VLMUL getLMul(uint64_t TSFlags)
static int getFRMOpNum(const MCInstrDesc &Desc)
static unsigned getSEWOpNum(const MCInstrDesc &Desc)
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 VLMUL encodeLMUL(unsigned LMUL, bool Fractional)
static unsigned decodeVSEW(unsigned VSEW)
LLVM_ABI std::pair< unsigned, bool > decodeVLMUL(VLMUL VLMul)
static unsigned encodeSEW(unsigned SEW)
@ TAIL_UNDISTURBED_MASK_UNDISTURBED
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
static constexpr unsigned RVVBytesPerBlock
LLVM_ABI Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI 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.
bool sd_match(SDNode *N, const SelectionDAG *DAG, Pattern &&P)
@ 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_FastCC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
bool CC_RISCV_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static const MachineMemOperand::Flags MONontemporalBit1
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
bool isStrongerThanMonotonic(AtomicOrdering AO)
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
bool RISCVCCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
RISCVCCAssignFn - This target-specific function extends the default CCValAssign with additional infor...
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.)
LLVM_ABI 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...
LLVM_ABI Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
LLVM_ABI 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...
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
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.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
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 CC_RISCV(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
LLVM_ABI 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...
LLVM_ABI 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.
LLVM_ABI 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...
LLVM_ABI bool isMaskedSlidePair(ArrayRef< int > Mask, int NumElts, std::array< std::pair< int, int >, 2 > &SrcInfo)
Does this shuffle mask represent either one slide shuffle or a pair of two slide shuffles,...
@ Xor
Bitwise or logical XOR of integers.
@ SMin
Signed integer min implemented in terms of select(cmp()).
@ Sub
Subtraction of integers.
unsigned getKillRegState(bool B)
DWARFExpression::Operation Op
RoundingMode
Rounding mode.
@ TowardZero
roundTowardZero.
@ NearestTiesToEven
roundTiesToEven.
@ TowardPositive
roundTowardPositive.
@ NearestTiesToAway
roundTiesToAway.
@ TowardNegative
roundTowardNegative.
LLVM_ABI 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.
LLVM_ABI 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.
LLVM_ABI 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.
LLVM_ABI bool isNeutralConstant(unsigned Opc, SDNodeFlags Flags, SDValue V, unsigned OperandNo)
Returns true if V is a neutral element of Opc with Flags.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
auto mask(ShuffFunc S, unsigned Length, OptArgs... args) -> MaskT
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 LLVM_ABI 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.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
EVT changeVectorElementType(EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
bool isInteger() const
Return true if this is an integer or a vector integer type.
static LLVM_ABI KnownBits ashr(const KnownBits &LHS, const KnownBits &RHS, bool ShAmtNonZero=false, bool Exact=false)
Compute known bits for ashr(LHS, RHS).
static LLVM_ABI 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 LLVM_ABI 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 LLVM_ABI 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 LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI 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
LLVM_ABI void AddToWorklist(SDNode *N)
bool isCalledByLegalizer() const
LLVM_ABI bool recursivelyDeleteUnusedNodes(SDNode *N)
bool isBeforeLegalize() const
LLVM_ABI 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)
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...
bool CombineTo(SDValue O, SDValue N)