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");
4542 Vec,
Offset, Mask, VL, Policy);
4546 VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1DOWN_VL : RISCVISD::VSLIDE1DOWN_VL;
4555 Vec,
Offset, Mask, VL, Policy);
4565 if (isa<ConstantSDNode>(
Lo) && isa<ConstantSDNode>(
Hi)) {
4566 int32_t LoC = cast<ConstantSDNode>(
Lo)->getSExtValue();
4567 int32_t HiC = cast<ConstantSDNode>(
Hi)->getSExtValue();
4570 if ((LoC >> 31) == HiC)
4571 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4577 if (isa<ConstantSDNode>(VL) && isUInt<4>(VL->
getAsZExtVal()))
4583 auto InterVec = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, InterVT,
4591 isa<ConstantSDNode>(
Hi.getOperand(1)) &&
4592 Hi.getConstantOperandVal(1) == 31)
4593 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4598 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4601 return DAG.
getNode(RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL,
DL, VT, Passthru,
Lo,
4611 assert(Scalar.getValueType() == MVT::i64 &&
"Unexpected VT!");
4623 bool HasPassthru = Passthru && !Passthru.
isUndef();
4624 if (!HasPassthru && !Passthru)
4631 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
4632 EltVT == MVT::bf16) {
4633 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4634 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
4635 Scalar = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Scalar);
4644 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL, VT, Passthru, Scalar, VL);
4648 if (Scalar.getValueType().bitsLE(XLenVT)) {
4655 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4656 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru, Scalar, VL);
4659 assert(XLenVT == MVT::i32 && Scalar.getValueType() == MVT::i64 &&
4660 "Unexpected scalar for splat lowering!");
4663 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, VT, Passthru,
4684 SDValue ExtractedVal = Scalar.getOperand(0);
4689 MVT ExtractedContainerVT = ExtractedVT;
4692 DAG, ExtractedContainerVT, Subtarget);
4694 ExtractedVal, DAG, Subtarget);
4696 if (ExtractedContainerVT.
bitsLE(VT))
4708 if (!Scalar.getValueType().bitsLE(XLenVT))
4711 VT,
DL, DAG, Subtarget);
4719 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4760 Src && Src.getValueType().getVectorNumElements() == (NumElts * 2))
4777 !Subtarget.hasVendorXRivosVizip())
4780 int Size = Mask.size();
4782 assert(
Size == (
int)NumElts &&
"Unexpected mask size");
4788 EvenSrc = StartIndexes[0];
4789 OddSrc = StartIndexes[1];
4792 if (EvenSrc != 0 && OddSrc != 0)
4802 int HalfNumElts = NumElts / 2;
4803 return ((EvenSrc % HalfNumElts) == 0) && ((OddSrc % HalfNumElts) == 0);
4808 std::array<std::pair<int, int>, 2> &SrcInfo) {
4813 if (SrcInfo[0].second == 0 && SrcInfo[1].second == 0)
4817 if ((SrcInfo[0].second > 0 && SrcInfo[1].second < 0) ||
4818 SrcInfo[1].second == 0)
4820 assert(SrcInfo[0].first != -1 &&
"Must find one slide");
4828 if (SrcInfo[1].first == -1)
4830 return SrcInfo[0].second < 0 && SrcInfo[1].second > 0 &&
4831 SrcInfo[1].second - SrcInfo[0].second == (int)NumElts;
4836 bool RequiredPolarity) {
4837 int NumElts = Mask.size();
4841 int Src = M >= NumElts;
4842 int Diff = (int)
Idx - (M % NumElts);
4843 bool C = Src == SrcInfo[1].first && Diff == SrcInfo[1].second;
4844 assert(
C != (Src == SrcInfo[0].first && Diff == SrcInfo[0].second) &&
4845 "Must match exactly one of the two slides");
4846 if (RequiredPolarity != (
C == (
Idx / Factor) % 2))
4857static bool isZipEven(
const std::array<std::pair<int, int>, 2> &SrcInfo,
4859 Factor = SrcInfo[1].second;
4861 Mask.size() % Factor == 0 &&
4872static bool isZipOdd(
const std::array<std::pair<int, int>, 2> &SrcInfo,
4874 Factor = -SrcInfo[1].second;
4876 Mask.size() % Factor == 0 &&
4889 ElementCount SrcEC = Src.getValueType().getVectorElementCount();
4896 unsigned Shift = Index * EltBits;
4921 std::optional<int> SplatIdx;
4923 if (M == -1 ||
I == (
unsigned)M)
4925 if (SplatIdx && *SplatIdx != M)
4934 for (
int MaskIndex : Mask) {
4935 bool SelectMaskVal = MaskIndex == *SplatIdx;
4938 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
4963 auto findNonEXTRACT_SUBVECTORParent =
4964 [](
SDValue Parent) -> std::pair<SDValue, uint64_t> {
4969 Parent.getOperand(0).getSimpleValueType().isFixedLengthVector()) {
4970 Offset += Parent.getConstantOperandVal(1);
4971 Parent = Parent.getOperand(0);
4973 return std::make_pair(Parent,
Offset);
4976 auto [V1Src, V1IndexOffset] = findNonEXTRACT_SUBVECTORParent(V1);
4977 auto [V2Src, V2IndexOffset] = findNonEXTRACT_SUBVECTORParent(V2);
4986 for (
size_t i = 0; i != NewMask.
size(); ++i) {
4987 if (NewMask[i] == -1)
4990 if (
static_cast<size_t>(NewMask[i]) < NewMask.
size()) {
4991 NewMask[i] = NewMask[i] + V1IndexOffset;
4995 NewMask[i] = NewMask[i] - NewMask.
size() + V2IndexOffset;
5001 if (NewMask[0] <= 0)
5005 for (
unsigned i = 1; i != NewMask.
size(); ++i)
5006 if (NewMask[i - 1] + 1 != NewMask[i])
5010 MVT SrcVT = Src.getSimpleValueType();
5039 int NumSubElts, Index;
5044 bool OpsSwapped = Mask[Index] < (int)NumElts;
5045 SDValue InPlace = OpsSwapped ? V2 : V1;
5046 SDValue ToInsert = OpsSwapped ? V1 : V2;
5057 if (NumSubElts + Index >= (
int)NumElts)
5068 Res = DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, ContainerVT, InPlace, ToInsert,
5071 Res =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, InPlace, ToInsert,
5083 bool OpsSwapped =
false;
5084 if (!isa<BuildVectorSDNode>(V1)) {
5085 if (!isa<BuildVectorSDNode>(V2))
5090 SDValue Splat = cast<BuildVectorSDNode>(V1)->getSplatValue();
5098 const unsigned E = Mask.size() - ((
Offset > 0) ?
Offset : 0);
5099 for (
unsigned i = S; i != E; ++i)
5100 if (Mask[i] >= 0 && (
unsigned)Mask[i] !=
Base + i +
Offset)
5106 bool IsVSlidedown = isSlideMask(Mask, OpsSwapped ? 0 : NumElts, 1);
5107 if (!IsVSlidedown && !isSlideMask(Mask, OpsSwapped ? 0 : NumElts, -1))
5110 const int InsertIdx = Mask[IsVSlidedown ? (NumElts - 1) : 0];
5112 if (InsertIdx < 0 || InsertIdx / NumElts != (
unsigned)OpsSwapped)
5129 IsVSlidedown ? RISCVISD::VSLIDE1DOWN_VL : RISCVISD::VSLIDE1UP_VL,
DL,
5135 auto OpCode = IsVSlidedown ?
5136 (VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1DOWN_VL : RISCVISD::VSLIDE1DOWN_VL) :
5137 (VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1UP_VL : RISCVISD::VSLIDE1UP_VL);
5140 auto Vec = DAG.
getNode(OpCode,
DL, ContainerVT,
5143 Splat, TrueMask, VL);
5155 for (
unsigned i = 0; i < Mask.size(); i++)
5156 LaneIsUndef[i % Factor] &= (Mask[i] == -1);
5159 for (
unsigned i = 0; i < Factor; i++) {
5170 for (
unsigned i = 0; i < Mask.size() / Factor; i++) {
5171 unsigned j = i * Factor + Index;
5172 if (Mask[j] != -1 && (
unsigned)Mask[j] != i)
5181 assert(RISCVISD::RI_VZIPEVEN_VL ==
Opc || RISCVISD::RI_VZIPODD_VL ==
Opc ||
5182 RISCVISD::RI_VZIP2A_VL ==
Opc || RISCVISD::RI_VZIP2B_VL ==
Opc ||
5183 RISCVISD::RI_VUNZIP2A_VL ==
Opc || RISCVISD::RI_VUNZIP2B_VL ==
Opc);
5191 MVT ContainerVT = IntVT;
5198 MVT InnerVT = ContainerVT;
5202 (RISCVISD::RI_VUNZIP2A_VL ==
Opc || RISCVISD::RI_VUNZIP2B_VL ==
Opc)) {
5214 if (InnerVT.
bitsLT(ContainerVT))
5229 MVT VT = V.getSimpleValueType();
5244 EC.multiplyCoefficientBy(Factor));
5263 MVT VecContainerVT = VecVT;
5280 MVT WideContainerVT = WideVT;
5286 EvenV = DAG.
getBitcast(VecContainerVT, EvenV);
5293 if (Subtarget.hasStdExtZvbb()) {
5297 Interleaved = DAG.
getNode(RISCVISD::VWSLL_VL,
DL, WideContainerVT, OddV,
5298 OffsetVec, Passthru, Mask, VL);
5299 Interleaved = DAG.
getNode(RISCVISD::VWADDU_W_VL,
DL, WideContainerVT,
5300 Interleaved, EvenV, Passthru, Mask, VL);
5307 Interleaved = DAG.
getNode(RISCVISD::VWADDU_VL,
DL, WideContainerVT, EvenV,
5308 OddV, Passthru, Mask, VL);
5314 OddV, AllOnesVec, Passthru, Mask, VL);
5321 Interleaved = DAG.
getNode(RISCVISD::ADD_VL,
DL, WideContainerVT,
5322 Interleaved, OddsMul, Passthru, Mask, VL);
5329 Interleaved = DAG.
getBitcast(ResultContainerVT, Interleaved);
5375 if (ViaEltSize > NumElts)
5383 if (ViaEltSize > NumElts)
5389 if (ViaEltSize > NumElts)
5396 MVT &RotateVT,
unsigned &RotateAmt) {
5399 unsigned NumSubElts;
5401 NumElts, NumSubElts, RotateAmt))
5404 NumElts / NumSubElts);
5472 unsigned NumOfSrcRegs = NumElts / NumOpElts;
5473 unsigned NumOfDestRegs = NumElts / NumOpElts;
5482 Mask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs,
5483 [&]() {
Operands.emplace_back(); },
5484 [&](
ArrayRef<int> SrcSubMask,
unsigned SrcVecIdx,
unsigned DstVecIdx) {
5485 Operands.emplace_back().emplace_back(SrcVecIdx, UINT_MAX,
5488 [&](
ArrayRef<int> SrcSubMask,
unsigned Idx1,
unsigned Idx2,
bool NewReg) {
5493 assert(
Operands.size() == NumOfDestRegs &&
"Whole vector must be processed");
5498 unsigned NumShuffles = std::accumulate(
5505 for (const auto &P : Data) {
5506 unsigned Idx2 = std::get<1>(P);
5507 ArrayRef<int> Mask = std::get<2>(P);
5508 if (Idx2 != UINT_MAX)
5510 else if (ShuffleVectorInst::isIdentityMask(Mask, Mask.size()))
5515 if ((NumOfDestRegs > 2 && NumShuffles > NumOfDestRegs) ||
5516 (NumOfDestRegs <= 2 && NumShuffles >= 4))
5518 auto ExtractValue = [&, &DAG = DAG](
SDValue SrcVec,
unsigned ExtractIdx) {
5519 SDValue SubVec = DAG.getExtractSubvector(
DL, M1VT, SrcVec, ExtractIdx);
5523 auto PerformShuffle = [&, &DAG = DAG](
SDValue SubVec1,
SDValue SubVec2,
5525 SDValue SubVec = DAG.getVectorShuffle(OneRegVT,
DL, SubVec1, SubVec2, Mask);
5528 SDValue Vec = DAG.getUNDEF(ContainerVT);
5533 for (
unsigned I : seq<unsigned>(
Data.size())) {
5534 const auto &[Idx1, Idx2,
_] =
Data[
I];
5542 V = ExtractValue(Idx1 >= NumOfSrcRegs ? V2 : V1,
5543 (Idx1 % NumOfSrcRegs) * NumOpElts);
5544 if (Idx2 != UINT_MAX) {
5547 V = ExtractValue(Idx2 >= NumOfSrcRegs ? V2 : V1,
5548 (Idx2 % NumOfSrcRegs) * NumOpElts);
5552 for (
const auto &[Idx1, Idx2, Mask] :
Data) {
5554 SDValue V2 = Idx2 == UINT_MAX ? V1 : Values.
at(Idx2);
5555 V = PerformShuffle(V1, V2, Mask);
5559 unsigned InsertIdx =
I * NumOpElts;
5561 Vec = DAG.getInsertSubvector(
DL, Vec, V, InsertIdx);
5571 bool SawUndef =
false;
5579 if (
Idx > (
unsigned)M)
5612 for (
int Idx : Mask) {
5615 unsigned SrcIdx =
Idx % Mask.size();
5617 if (Srcs[SrcIdx] == -1)
5620 else if (Srcs[SrcIdx] != Src)
5626 for (
int Lane : Srcs) {
5639 for (
unsigned I = 0;
I < Mask.size();
I++) {
5643 NewMask[
I] = Mask[
I] % Mask.size();
5657 if ((M / Span) != (
int)(
I / Span))
5659 int SpanIdx =
I % Span;
5669 return all_of(Mask, [&](
const auto &
Idx) {
return Idx == -1 ||
Idx < Span; });
5681 int SpanIdx =
I % Span;
5682 if (Mask[SpanIdx] != M)
5696 MVT VT =
Op.getSimpleValueType();
5704 if (ElementSize > 32)
5727 MVT VT =
Op.getSimpleValueType();
5755 auto [TrueMask, VL] = TrueMaskVL;
5770 V.getOperand(0).getSimpleValueType().getVectorNumElements();
5771 V = V.getOperand(
Offset / OpElements);
5777 auto *Ld = cast<LoadSDNode>(V);
5787 SDValue Ops[] = {Ld->getChain(),
5801 MVT SplatVT = ContainerVT;
5804 if (SVT == MVT::bf16 ||
5805 (SVT == MVT::f16 && !Subtarget.hasStdExtZfh())) {
5814 V = DAG.
getLoad(SVT,
DL, Ld->getChain(), NewAddr,
5815 Ld->getPointerInfo().getWithOffset(
Offset),
5816 Ld->getBaseAlign(), Ld->getMemOperand()->
getFlags());
5819 Ld->getPointerInfo().getWithOffset(
Offset), SVT,
5821 Ld->getMemOperand()->getFlags());
5825 : RISCVISD::VMV_V_X_VL;
5833 assert(Lane < (
int)NumElts &&
"Unexpected lane!");
5836 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
5858 if (Subtarget.hasStdExtZvkb())
5874 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
5875 for (
unsigned Factor = 2; Factor <= MaxFactor; Factor <<= 1) {
5882 [&Mask](
int Idx) {
return Idx < (int)Mask.size(); }) &&
5884 return Idx >= (int)Mask.size();
5914 if (Subtarget.hasVendorXRivosVizip() &&
5918 Index == 0 ? RISCVISD::RI_VUNZIP2A_VL : RISCVISD::RI_VUNZIP2B_VL;
5934 [&Mask](
int Idx) {
return Idx < (int)Mask.size(); }) &&
5936 [&Mask](
int Idx) {
return Idx >= (int)Mask.size(); })) {
5940 if (NumElts < MinVLMAX) {
5964 int EvenSrc, OddSrc;
5974 bool LaneIsUndef[2] = {
true,
true};
5976 LaneIsUndef[
Idx % 2] &= (M == -1);
5978 int Size = Mask.size();
5980 if (LaneIsUndef[0]) {
5983 assert(EvenSrc >= 0 &&
"Undef source?");
5984 EvenV = (EvenSrc /
Size) == 0 ? V1 : V2;
5988 if (LaneIsUndef[1]) {
5991 assert(OddSrc >= 0 &&
"Undef source?");
5992 OddV = (OddSrc /
Size) == 0 ? V1 : V2;
5998 if (Subtarget.hasVendorXRivosVizip()) {
6001 return lowerVZIP(RISCVISD::RI_VZIP2A_VL, EvenV, OddV,
DL, DAG, Subtarget);
6012 std::array<std::pair<int, int>, 2> SrcInfo;
6019 auto GetSourceFor = [&](
const std::pair<int, int> &
Info) {
6020 int SrcIdx =
Info.first;
6021 assert(SrcIdx == 0 || SrcIdx == 1);
6022 SDValue &Src = Sources[SrcIdx];
6024 SDValue SrcV = SrcIdx == 0 ? V1 : V2;
6029 auto GetSlide = [&](
const std::pair<int, int> &Src,
SDValue Mask,
6031 auto [TrueMask, VL] = TrueMaskVL;
6032 SDValue SrcV = GetSourceFor(Src);
6033 int SlideAmt = Src.second;
6034 if (SlideAmt == 0) {
6036 assert(Mask == TrueMask);
6043 return getVSlideup(DAG, Subtarget,
DL, ContainerVT, Passthru, SrcV,
6048 if (SrcInfo[1].first == -1) {
6050 Res = GetSlide(SrcInfo[0], TrueMask, Res);
6054 if (Subtarget.hasVendorXRivosVizip()) {
6055 bool TryWiden =
false;
6059 SDValue Src1 = SrcInfo[0].first == 0 ? V1 : V2;
6060 SDValue Src2 = SrcInfo[1].first == 0 ? V1 : V2;
6061 return lowerVZIP(RISCVISD::RI_VZIPEVEN_VL, Src1, Src2,
DL, DAG,
6066 if (
isZipOdd(SrcInfo, Mask, Factor)) {
6068 SDValue Src1 = SrcInfo[1].first == 0 ? V1 : V2;
6069 SDValue Src2 = SrcInfo[0].first == 0 ? V1 : V2;
6070 return lowerVZIP(RISCVISD::RI_VZIPODD_VL, Src1, Src2,
DL, DAG,
6090 (SrcInfo[1].second > 0 &&
Idx < (
unsigned)SrcInfo[1].second)) {
6094 int Src = M >= (int)NumElts;
6095 int Diff = (int)
Idx - (M % NumElts);
6096 bool C = Src == SrcInfo[1].first && Diff == SrcInfo[1].second;
6097 assert(
C ^ (Src == SrcInfo[0].first && Diff == SrcInfo[0].second) &&
6098 "Must match exactly one of the two slides");
6101 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
6108 Res = GetSlide(SrcInfo[0], TrueMask, Res);
6109 Res = GetSlide(SrcInfo[1], SelectMask, Res);
6114 assert(!V1.
isUndef() &&
"Unexpected shuffle canonicalization");
6129 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
6130 for (
unsigned Factor = 4; Factor <= MaxFactor; Factor <<= 1) {
6145 if (NumElts > MinVLMAX) {
6146 unsigned MaxIdx = 0;
6150 MaxIdx = std::max(std::max((
unsigned)
I, (
unsigned)M), MaxIdx);
6152 unsigned NewNumElts =
6154 if (NewNumElts != NumElts) {
6158 Mask.take_front(NewNumElts));
6175 for (
auto Idx : Mask) {
6188 any_of(Mask, [&](
const auto &
Idx) {
return Idx > 255; })) {
6198 unsigned GatherVVOpc = RISCVISD::VRGATHER_VV_VL;
6204 GatherVVOpc = RISCVISD::VRGATHEREI16_VV_VL;
6213 GatherVVOpc = RISCVISD::VRGATHEREI16_VV_VL;
6217 MVT IndexContainerVT =
6222 for (
int MaskIndex : Mask) {
6223 bool IsLHSIndex = MaskIndex < (int)NumElts && MaskIndex >= 0;
6233 if (NumElts <= MinVLMAX) {
6235 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
6241 auto [InnerTrueMask, InnerVL] =
6253 for (
int i = 0; i <
N; i++) {
6257 DAG.
getNode(GatherVVOpc,
DL, M1VT, SubV1, SubIndex,
6258 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6275 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6277 for (
int i = 0; i <
N; i++)
6293 for (
int i = 0; i <
N; i++) {
6296 DAG.
getUNDEF(IndexContainerVT), LHSIndices,
6297 SlideAmt, TrueMask, VL);
6301 DAG.
getNode(GatherVVOpc,
DL, M1VT, SubV1, SubIndex,
6302 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6312 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
6322 for (
int MaskIndex : Mask) {
6323 bool IsLHSOrUndefIndex = MaskIndex < (int)NumElts;
6324 ShuffleMaskLHS.
push_back(IsLHSOrUndefIndex && MaskIndex >= 0
6326 ShuffleMaskRHS.
push_back(IsLHSOrUndefIndex ? -1 : (MaskIndex - NumElts));
6357 for (
int MaskIndex : Mask) {
6358 bool SelectMaskVal = (MaskIndex < (int)NumElts) ^ !SwapOps;
6362 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
6380 const unsigned NumElts = M.size();
6387 std::array<std::pair<int, int>, 2> SrcInfo;
6398RISCVTargetLowering::lowerCTLZ_CTTZ_ZERO_UNDEF(
SDValue Op,
6400 MVT VT =
Op.getSimpleValueType();
6404 MVT ContainerVT = VT;
6407 if (
Op->isVPOpcode()) {
6408 Mask =
Op.getOperand(1);
6412 VL =
Op.getOperand(2);
6418 MVT FloatEltVT = (EltSize >= 32) ? MVT::f64 : MVT::f32;
6420 FloatEltVT = MVT::f32;
6427 "Expected legal float type!");
6434 }
else if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF) {
6437 Src = DAG.
getNode(ISD::VP_AND,
DL, VT, Src, Neg, Mask, VL);
6442 if (FloatVT.
bitsGT(VT)) {
6443 if (
Op->isVPOpcode())
6444 FloatVal = DAG.
getNode(ISD::VP_UINT_TO_FP,
DL, FloatVT, Src, Mask, VL);
6453 if (!
Op->isVPOpcode())
6457 MVT ContainerFloatVT =
6459 FloatVal = DAG.
getNode(RISCVISD::VFCVT_RM_F_XU_VL,
DL, ContainerFloatVT,
6460 Src, Mask, RTZRM, VL);
6467 unsigned ShiftAmt = FloatEltVT == MVT::f64 ? 52 : 23;
6471 if (
Op->isVPOpcode()) {
6480 else if (IntVT.
bitsGT(VT))
6485 unsigned ExponentBias = FloatEltVT == MVT::f64 ? 1023 : 127;
6490 if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF)
6491 return DAG.
getNode(ISD::VP_SUB,
DL, VT, Exp,
6496 unsigned Adjust = ExponentBias + (EltSize - 1);
6498 if (
Op->isVPOpcode())
6508 else if (
Op.getOpcode() == ISD::VP_CTLZ)
6509 Res = DAG.
getNode(ISD::VP_UMIN,
DL, VT, Res,
6519 MVT SrcVT =
Source.getSimpleValueType();
6528 SrcVT = ContainerVT;
6540 SDValue Res = DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Source, Mask, EVL);
6541 if (
Op->getOpcode() == ISD::VP_CTTZ_ELTS_ZERO_UNDEF)
6558 auto *
Load = cast<LoadSDNode>(
Op);
6559 assert(Load &&
Load->getMemoryVT().isVector() &&
"Expected vector load");
6562 Load->getMemoryVT(),
6563 *
Load->getMemOperand()))
6567 MVT VT =
Op.getSimpleValueType();
6569 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
6570 "Unexpected unaligned RVV load type");
6574 "Expecting equally-sized RVV vector types to be legal");
6576 Load->getPointerInfo(),
Load->getBaseAlign(),
6577 Load->getMemOperand()->getFlags());
6587 auto *
Store = cast<StoreSDNode>(
Op);
6588 assert(Store &&
Store->getValue().getValueType().isVector() &&
6589 "Expected vector store");
6592 Store->getMemoryVT(),
6593 *
Store->getMemOperand()))
6600 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
6601 "Unexpected unaligned RVV store type");
6605 "Expecting equally-sized RVV vector types to be legal");
6606 StoredVal = DAG.
getBitcast(NewVT, StoredVal);
6608 Store->getPointerInfo(),
Store->getBaseAlign(),
6609 Store->getMemOperand()->getFlags());
6614 assert(
Op.getValueType() == MVT::i64 &&
"Unexpected VT");
6616 int64_t Imm = cast<ConstantSDNode>(
Op)->getSExtValue();
6643 unsigned ShiftAmt, AddOpc;
6654 MVT VT =
Op.getSimpleValueType();
6655 const APFloat &
Imm = cast<ConstantFPSDNode>(
Op)->getValueAPF();
6658 bool Negate =
false;
6662 if (Index < 0 &&
Imm.isNegative()) {
6685 unsigned IsData =
Op.getConstantOperandVal(4);
6688 if (Subtarget.hasVendorXMIPSCBOP() && !IsData)
6689 return Op.getOperand(0);
6701 if (Subtarget.hasStdExtZtso()) {
6725 MVT VT =
Op.getSimpleValueType();
6727 unsigned Check =
Op.getConstantOperandVal(1);
6728 unsigned TDCMask = 0;
6756 MVT VT0 =
Op.getOperand(0).getSimpleValueType();
6761 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6763 VL =
Op.getOperand(3);
6766 VL,
Op->getFlags());
6781 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6783 MVT MaskContainerVT =
6786 VL =
Op.getOperand(3);
6790 SDValue FPCLASS = DAG.
getNode(RISCVISD::FCLASS_VL,
DL, ContainerDstVT, Op0,
6791 Mask, VL,
Op->getFlags());
6793 TDCMaskV = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerDstVT,
6794 DAG.
getUNDEF(ContainerDstVT), TDCMaskV, VL);
6797 DAG.
getNode(RISCVISD::SETCC_VL,
DL, ContainerVT,
6799 DAG.
getUNDEF(ContainerVT), Mask, VL});
6803 TDCMaskV, DAG.
getUNDEF(ContainerDstVT), Mask, VL);
6806 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerDstVT,
6807 DAG.
getUNDEF(ContainerDstVT), SplatZero, VL);
6811 DAG.
getUNDEF(ContainerVT), Mask, VL});
6827 MVT VT =
Op.getSimpleValueType();
6861 MVT ContainerVT = VT;
6869 if (
Op->isVPOpcode()) {
6870 Mask =
Op.getOperand(2);
6874 VL =
Op.getOperand(3);
6881 SDValue XIsNonNan = DAG.
getNode(RISCVISD::SETCC_VL,
DL, Mask.getValueType(),
6882 {X, X, DAG.getCondCode(ISD::SETOEQ),
6883 DAG.getUNDEF(ContainerVT), Mask, VL});
6884 NewY = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, XIsNonNan,
Y,
X,
6890 SDValue YIsNonNan = DAG.
getNode(RISCVISD::SETCC_VL,
DL, Mask.getValueType(),
6891 {Y, Y, DAG.getCondCode(ISD::SETOEQ),
6892 DAG.getUNDEF(ContainerVT), Mask, VL});
6893 NewX = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, YIsNonNan,
X,
Y,
6899 ? RISCVISD::VFMAX_VL
6900 : RISCVISD::VFMIN_VL;
6902 DAG.
getUNDEF(ContainerVT), Mask, VL);
6912 "Wrong opcode for lowering FABS or FNEG.");
6915 MVT VT =
Op.getSimpleValueType();
6916 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
6920 DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT,
Op.getOperand(0));
6923 Mask = Mask.sext(Subtarget.
getXLen());
6928 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, Logic);
6936 MVT VT =
Op.getSimpleValueType();
6937 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
6947 if (SignSize == Subtarget.
getXLen())
6951 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Sign);
6953 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, XLenVT, Sign);
6955 assert(XLenVT == MVT::i32 &&
"Unexpected type");
6958 return DAG.
getNode(RISCVISD::SplitF64,
DL, {MVT::i32, MVT::i32}, Sign)
6988 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, CopiedSign);
6993#define OP_CASE(NODE) \
6995 return RISCVISD::NODE##_VL;
6996#define VP_CASE(NODE) \
6997 case ISD::VP_##NODE: \
6998 return RISCVISD::NODE##_VL;
7000 switch (
Op.getOpcode()) {
7079 case ISD::VP_CTLZ_ZERO_UNDEF:
7080 return RISCVISD::CTLZ_VL;
7082 case ISD::VP_CTTZ_ZERO_UNDEF:
7083 return RISCVISD::CTTZ_VL;
7086 return RISCVISD::VFMADD_VL;
7088 return RISCVISD::STRICT_VFMADD_VL;
7091 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7092 return RISCVISD::VMAND_VL;
7093 return RISCVISD::AND_VL;
7096 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7097 return RISCVISD::VMOR_VL;
7098 return RISCVISD::OR_VL;
7101 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7102 return RISCVISD::VMXOR_VL;
7103 return RISCVISD::XOR_VL;
7106 return RISCVISD::VZEXT_VL;
7108 return RISCVISD::VSEXT_VL;
7110 return RISCVISD::SETCC_VL;
7112 return RISCVISD::VMERGE_VL;
7113 case ISD::VP_SELECT:
7115 return RISCVISD::VMERGE_VL;
7117 return RISCVISD::SRA_VL;
7119 return RISCVISD::SRL_VL;
7121 return RISCVISD::FSQRT_VL;
7122 case ISD::VP_SIGN_EXTEND:
7123 return RISCVISD::VSEXT_VL;
7124 case ISD::VP_ZERO_EXTEND:
7125 return RISCVISD::VZEXT_VL;
7126 case ISD::VP_FP_TO_SINT:
7127 return RISCVISD::VFCVT_RTZ_X_F_VL;
7128 case ISD::VP_FP_TO_UINT:
7129 return RISCVISD::VFCVT_RTZ_XU_F_VL;
7132 case ISD::VP_FMINNUM:
7133 return RISCVISD::VFMIN_VL;
7136 case ISD::VP_FMAXNUM:
7137 return RISCVISD::VFMAX_VL;
7141 case ISD::VP_LLRINT:
7142 return RISCVISD::VFCVT_RM_X_F_VL;
7151 return (
Op.getValueType() == MVT::nxv32f16 &&
7154 Op.getValueType() == MVT::nxv32bf16;
7165 if (!
Op.getOperand(j).getValueType().isVector()) {
7166 LoOperands[j] =
Op.getOperand(j);
7167 HiOperands[j] =
Op.getOperand(j);
7170 std::tie(LoOperands[j], HiOperands[j]) =
7175 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
7177 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
7192 std::tie(LoOperands[j], HiOperands[j]) =
7196 if (!
Op.getOperand(j).getValueType().isVector()) {
7197 LoOperands[j] =
Op.getOperand(j);
7198 HiOperands[j] =
Op.getOperand(j);
7201 std::tie(LoOperands[j], HiOperands[j]) =
7206 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
7208 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
7218 auto [EVLLo, EVLHi] =
7219 DAG.
SplitEVL(
Op.getOperand(3),
Op.getOperand(1).getValueType(),
DL);
7223 {Op.getOperand(0), Lo, MaskLo, EVLLo},
Op->getFlags());
7225 {ResLo, Hi, MaskHi, EVLHi},
Op->getFlags());
7243 if (!
Op.getOperand(j).getValueType().isVector()) {
7244 LoOperands[j] =
Op.getOperand(j);
7245 HiOperands[j] =
Op.getOperand(j);
7248 std::tie(LoOperands[j], HiOperands[j]) =
7253 DAG.
getNode(
Op.getOpcode(),
DL, LoVTs, LoOperands,
Op->getFlags());
7256 DAG.
getNode(
Op.getOpcode(),
DL, HiVTs, HiOperands,
Op->getFlags());
7264RISCVTargetLowering::lowerXAndesBfHCvtBFloat16Load(
SDValue Op,
7266 assert(Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh() &&
7267 "Unexpected bfloat16 load lowering");
7271 EVT MemVT =
LD->getMemoryVT();
7276 LD->getMemOperand());
7284 DAG.
getNode(RISCVISD::NDS_FMV_BF16_X,
DL, MVT::bf16, OrSixteenOne);
7289RISCVTargetLowering::lowerXAndesBfHCvtBFloat16Store(
SDValue Op,
7291 assert(Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh() &&
7292 "Unexpected bfloat16 store lowering");
7299 ST->getChain(),
DL, FMV,
ST->getBasePtr(),
7301 ST->getMemOperand());
7306 switch (
Op.getOpcode()) {
7309 "Unimplemented RISCVTargetLowering::LowerOperation Case");
7315 return lowerGlobalAddress(
Op, DAG);
7317 return lowerBlockAddress(
Op, DAG);
7319 return lowerConstantPool(
Op, DAG);
7321 return lowerJumpTable(
Op, DAG);
7323 return lowerGlobalTLSAddress(
Op, DAG);
7327 return lowerConstantFP(
Op, DAG);
7329 return lowerSELECT(
Op, DAG);
7331 return lowerBRCOND(
Op, DAG);
7333 return lowerVASTART(
Op, DAG);
7335 return lowerFRAMEADDR(
Op, DAG);
7337 return lowerRETURNADDR(
Op, DAG);
7339 return lowerShiftLeftParts(
Op, DAG);
7341 return lowerShiftRightParts(
Op, DAG,
true);
7343 return lowerShiftRightParts(
Op, DAG,
false);
7346 if (
Op.getValueType().isFixedLengthVector()) {
7347 assert(Subtarget.hasStdExtZvkb());
7348 return lowerToScalableOp(
Op, DAG);
7350 assert(Subtarget.hasVendorXTHeadBb() &&
7351 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
7352 "Unexpected custom legalization");
7354 if (!isa<ConstantSDNode>(
Op.getOperand(1)))
7359 EVT VT =
Op.getValueType();
7363 if (Op0VT == MVT::i16 &&
7365 (VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
7367 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, NewOp0);
7369 if (VT == MVT::f32 && Op0VT == MVT::i32 && Subtarget.
is64Bit() &&
7372 return DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, NewOp0);
7374 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.
is64Bit() &&
7378 return DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64,
Lo,
Hi);
7390 "Unexpected types");
7422 return LowerINTRINSIC_WO_CHAIN(
Op, DAG);
7424 return LowerINTRINSIC_W_CHAIN(
Op, DAG);
7426 return LowerINTRINSIC_VOID(
Op, DAG);
7428 return LowerIS_FPCLASS(
Op, DAG);
7430 MVT VT =
Op.getSimpleValueType();
7432 assert(Subtarget.hasStdExtZvbb());
7433 return lowerToScalableOp(
Op, DAG);
7436 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected custom legalization");
7440 return DAG.
getNode(RISCVISD::BREV8,
DL, VT, BSwap);
7446 if (!
Op.getSimpleValueType().isVector())
7448 return lowerVectorTruncLike(
Op, DAG);
7451 if (
Op.getOperand(0).getValueType().isVector() &&
7452 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7453 return lowerVectorMaskExt(
Op, DAG, 1);
7454 if (
Op.getValueType().isScalableVector())
7456 return lowerToScalableOp(
Op, DAG);
7458 if (
Op.getOperand(0).getValueType().isVector() &&
7459 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7460 return lowerVectorMaskExt(
Op, DAG, -1);
7461 if (
Op.getValueType().isScalableVector())
7463 return lowerToScalableOp(
Op, DAG);
7465 return lowerSPLAT_VECTOR_PARTS(
Op, DAG);
7467 return lowerINSERT_VECTOR_ELT(
Op, DAG);
7469 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
7471 MVT VT =
Op.getSimpleValueType();
7479 MVT ContainerVT = VT;
7486 V = DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL, ContainerVT,
7487 DAG.
getUNDEF(ContainerVT), Scalar, VL);
7490 V = DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, ContainerVT,
7491 DAG.
getUNDEF(ContainerVT), Scalar, VL);
7499 MVT VT =
Op.getSimpleValueType();
7515 Flags.setExact(
true);
7518 }
else if (
Log2 > 3) {
7522 }
else if ((Val % 8) == 0) {
7529 Flags.setExact(
true);
7540 if (
Op.getValueType() == MVT::f16 && Subtarget.
is64Bit() &&
7541 Op.getOperand(1).getValueType() == MVT::i32) {
7558 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
7561 return lowerStrictFPExtendOrRoundLike(
Op, DAG);
7564 if (
Op.getValueType().isVector() &&
7565 ((
Op.getValueType().getScalarType() == MVT::f16 &&
7568 Op.getValueType().getScalarType() == MVT::bf16)) {
7584 Op1.getValueType().isVector() &&
7585 ((Op1.getValueType().getScalarType() == MVT::f16 &&
7588 Op1.getValueType().getScalarType() == MVT::bf16)) {
7594 Op1.getValueType().getVectorElementCount());
7597 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), WidenVec);
7607 MVT VT =
Op.getSimpleValueType();
7610 bool IsStrict =
Op->isStrictFPOpcode();
7611 SDValue Src =
Op.getOperand(0 + IsStrict);
7612 MVT SrcVT = Src.getSimpleValueType();
7623 "Unexpected vector element types");
7627 if (EltSize > (2 * SrcEltSize)) {
7639 Op.getOperand(0), Ext);
7643 assert(SrcEltVT == MVT::f16 &&
"Unexpected FP_TO_[US]INT lowering");
7648 auto [FExt, Chain] =
7650 return DAG.
getNode(
Op.getOpcode(),
DL,
Op->getVTList(), Chain, FExt);
7657 if (SrcEltSize > (2 * EltSize)) {
7660 assert(EltVT == MVT::f16 &&
"Unexpected [US]_TO_FP lowering");
7665 Op.getOperand(0), Src);
7680 Op.getOperand(0), Src);
7694 unsigned RVVOpc = 0;
7695 switch (
Op.getOpcode()) {
7699 RVVOpc = RISCVISD::VFCVT_RTZ_X_F_VL;
7702 RVVOpc = RISCVISD::VFCVT_RTZ_XU_F_VL;
7705 RVVOpc = RISCVISD::SINT_TO_FP_VL;
7708 RVVOpc = RISCVISD::UINT_TO_FP_VL;
7711 RVVOpc = RISCVISD::STRICT_VFCVT_RTZ_X_F_VL;
7714 RVVOpc = RISCVISD::STRICT_VFCVT_RTZ_XU_F_VL;
7717 RVVOpc = RISCVISD::STRICT_SINT_TO_FP_VL;
7720 RVVOpc = RISCVISD::STRICT_UINT_TO_FP_VL;
7727 "Expected same element count");
7734 Op.getOperand(0), Src, Mask, VL);
7738 Src = DAG.
getNode(RVVOpc,
DL, ContainerVT, Src, Mask, VL);
7753 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
7755 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Res);
7760 MVT VT =
Op.getSimpleValueType();
7766 ? DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32,
Op)
7780 bool IsStrict =
Op->isStrictFPOpcode();
7781 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7785 std::tie(Res, Chain) =
7786 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
7788 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Res);
7801 bool IsStrict =
Op->isStrictFPOpcode();
7802 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7805 ? DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, Op0)
7808 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
7809 CallOptions,
DL, Chain);
7828 if (
Op.getValueType().isVector())
7830 assert(
Op.getOperand(0).getValueType() == MVT::f16 &&
7831 "Unexpected custom legalisation");
7834 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), Ext);
7840 assert(
Op.getOperand(1).getValueType() == MVT::f16 &&
7841 "Unexpected custom legalisation");
7844 {
Op.getOperand(0),
Op.getOperand(1)});
7845 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
7846 {Ext.getValue(1), Ext.getValue(0)});
7853 return lowerVECREDUCE(
Op, DAG);
7857 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7858 return lowerVectorMaskVecReduction(
Op, DAG,
false);
7859 return lowerVECREDUCE(
Op, DAG);
7866 return lowerFPVECREDUCE(
Op, DAG);
7867 case ISD::VP_REDUCE_ADD:
7868 case ISD::VP_REDUCE_UMAX:
7869 case ISD::VP_REDUCE_SMAX:
7870 case ISD::VP_REDUCE_UMIN:
7871 case ISD::VP_REDUCE_SMIN:
7872 case ISD::VP_REDUCE_FADD:
7873 case ISD::VP_REDUCE_SEQ_FADD:
7874 case ISD::VP_REDUCE_FMIN:
7875 case ISD::VP_REDUCE_FMAX:
7876 case ISD::VP_REDUCE_FMINIMUM:
7877 case ISD::VP_REDUCE_FMAXIMUM:
7880 return lowerVPREDUCE(
Op, DAG);
7881 case ISD::VP_REDUCE_AND:
7882 case ISD::VP_REDUCE_OR:
7883 case ISD::VP_REDUCE_XOR:
7884 if (
Op.getOperand(1).getValueType().getVectorElementType() == MVT::i1)
7885 return lowerVectorMaskVecReduction(
Op, DAG,
true);
7886 return lowerVPREDUCE(
Op, DAG);
7887 case ISD::VP_CTTZ_ELTS:
7888 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
7889 return lowerVPCttzElements(
Op, DAG);
7893 DAG.
getUNDEF(ContainerVT), DAG, Subtarget);
7896 return lowerINSERT_SUBVECTOR(
Op, DAG);
7898 return lowerEXTRACT_SUBVECTOR(
Op, DAG);
7900 return lowerVECTOR_DEINTERLEAVE(
Op, DAG);
7902 return lowerVECTOR_INTERLEAVE(
Op, DAG);
7904 return lowerSTEP_VECTOR(
Op, DAG);
7906 return lowerVECTOR_REVERSE(
Op, DAG);
7908 return lowerVECTOR_SPLICE(
Op, DAG);
7910 MVT VT =
Op.getSimpleValueType();
7912 if (!Subtarget.
is64Bit() && EltVT == MVT::i64)
7917 MVT VT =
Op.getSimpleValueType();
7919 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
7920 EltVT == MVT::bf16) {
7923 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
7924 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
7934 if (EltVT == MVT::i1)
7935 return lowerVectorMaskSplat(
Op, DAG);
7944 MVT VT =
Op.getSimpleValueType();
7945 MVT ContainerVT = VT;
7963 Op->ops().take_front(HalfNumOps));
7965 Op->ops().drop_front(HalfNumOps));
7969 unsigned NumOpElts =
7970 Op.getOperand(0).getSimpleValueType().getVectorMinNumElements();
7982 auto *Load = cast<LoadSDNode>(
Op);
7983 EVT VT = Load->getValueType(0);
7984 if (VT == MVT::f64) {
7985 assert(Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
7986 !Subtarget.
is64Bit() &&
"Unexpected custom legalisation");
7990 SDValue BasePtr = Load->getBasePtr();
7991 SDValue Chain = Load->getChain();
7994 DAG.
getLoad(MVT::i32,
DL, Chain, BasePtr, Load->getPointerInfo(),
7995 Load->getBaseAlign(), Load->getMemOperand()->getFlags());
7998 MVT::i32,
DL, Chain, BasePtr, Load->getPointerInfo().getWithOffset(4),
7999 Load->getBaseAlign(), Load->getMemOperand()->getFlags());
8007 if (VT == MVT::bf16)
8008 return lowerXAndesBfHCvtBFloat16Load(
Op, DAG);
8016 unsigned NumElts = Sz / (NF * 8);
8017 int Log2LMUL =
Log2_64(NumElts) - 3;
8020 Flag.setNoUnsignedWrap(
true);
8022 SDValue BasePtr = Load->getBasePtr();
8030 for (
unsigned i = 0; i < NF; ++i) {
8035 Ret = DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VT, Ret, LoadVal,
8043 if (
auto V = expandUnalignedRVVLoad(
Op, DAG))
8045 if (
Op.getValueType().isFixedLengthVector())
8046 return lowerFixedLengthVectorLoadToRVV(
Op, DAG);
8050 auto *Store = cast<StoreSDNode>(
Op);
8051 SDValue StoredVal = Store->getValue();
8053 if (VT == MVT::f64) {
8054 assert(Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
8055 !Subtarget.
is64Bit() &&
"Unexpected custom legalisation");
8059 SDValue BasePtr = Store->getBasePtr();
8060 SDValue Chain = Store->getChain();
8062 DAG.
getVTList(MVT::i32, MVT::i32), StoredVal);
8065 Store->getPointerInfo(), Store->getBaseAlign(),
8066 Store->getMemOperand()->getFlags());
8069 Store->getPointerInfo().getWithOffset(4),
8070 Store->getBaseAlign(),
8071 Store->getMemOperand()->getFlags());
8074 if (VT == MVT::i64) {
8075 assert(Subtarget.hasStdExtZilsd() && !Subtarget.
is64Bit() &&
8076 "Unexpected custom legalisation");
8077 if (Store->isTruncatingStore())
8080 if (!Subtarget.enableUnalignedScalarMem() && Store->getAlign() < 8)
8091 {Store->getChain(), Lo, Hi, Store->getBasePtr()}, MVT::i64,
8092 Store->getMemOperand());
8095 if (VT == MVT::bf16)
8096 return lowerXAndesBfHCvtBFloat16Store(
Op, DAG);
8104 unsigned NumElts = Sz / (NF * 8);
8105 int Log2LMUL =
Log2_64(NumElts) - 3;
8108 Flag.setNoUnsignedWrap(
true);
8110 SDValue Chain = Store->getChain();
8111 SDValue BasePtr = Store->getBasePtr();
8118 for (
unsigned i = 0; i < NF; ++i) {
8120 DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL,
8123 Ret = DAG.
getStore(Chain,
DL, Extract, BasePtr,
8125 Store->getBaseAlign(),
8126 Store->getMemOperand()->getFlags());
8127 Chain = Ret.getValue(0);
8133 if (
auto V = expandUnalignedRVVStore(
Op, DAG))
8135 if (
Op.getOperand(1).getValueType().isFixedLengthVector())
8136 return lowerFixedLengthVectorStoreToRVV(
Op, DAG);
8141 return lowerMaskedLoad(
Op, DAG);
8142 case ISD::VP_LOAD_FF:
8143 return lowerLoadFF(
Op, DAG);
8146 return lowerMaskedStore(
Op, DAG);
8148 return lowerVectorCompress(
Op, DAG);
8157 EVT VT =
Op.getValueType();
8168 MVT OpVT =
Op.getOperand(0).getSimpleValueType();
8170 MVT VT =
Op.getSimpleValueType();
8175 "Unexpected CondCode");
8183 if (isa<ConstantSDNode>(
RHS)) {
8184 int64_t Imm = cast<ConstantSDNode>(
RHS)->getSExtValue();
8185 if (Imm != 0 && isInt<12>((
uint64_t)Imm + 1)) {
8214 return lowerToScalableOp(
Op, DAG);
8231 return lowerToScalableOp(
Op, DAG);
8235 if (
Op.getSimpleValueType().isFixedLengthVector())
8236 return lowerToScalableOp(
Op, DAG);
8238 assert(
Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.
is64Bit() &&
8239 "Unexpected custom legalisation");
8243 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
8271 return lowerToScalableOp(
Op, DAG);
8275 EVT VT =
Op->getValueType(0);
8290 return lowerABS(
Op, DAG);
8295 if (Subtarget.hasStdExtZvbb())
8296 return lowerToScalableOp(
Op, DAG);
8298 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8300 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
8304 return lowerToScalableOp(
Op, DAG);
8313 return lowerToScalableOp(
Op, DAG);
8316 return lowerVectorStrictFSetcc(
Op, DAG);
8326 case ISD::VP_GATHER:
8327 return lowerMaskedGather(
Op, DAG);
8329 case ISD::VP_SCATTER:
8330 return lowerMaskedScatter(
Op, DAG);
8332 return lowerGET_ROUNDING(
Op, DAG);
8334 return lowerSET_ROUNDING(
Op, DAG);
8336 return lowerGET_FPENV(
Op, DAG);
8338 return lowerSET_FPENV(
Op, DAG);
8340 return lowerRESET_FPENV(
Op, DAG);
8342 return lowerGET_FPMODE(
Op, DAG);
8344 return lowerSET_FPMODE(
Op, DAG);
8346 return lowerRESET_FPMODE(
Op, DAG);
8348 return lowerEH_DWARF_CFA(
Op, DAG);
8350 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
8351 return lowerVPMergeMask(
Op, DAG);
8353 case ISD::VP_SELECT:
8361 case ISD::VP_UADDSAT:
8362 case ISD::VP_USUBSAT:
8363 case ISD::VP_SADDSAT:
8364 case ISD::VP_SSUBSAT:
8366 case ISD::VP_LLRINT:
8367 return lowerVPOp(
Op, DAG);
8371 return lowerLogicVPOp(
Op, DAG);
8380 case ISD::VP_FMINNUM:
8381 case ISD::VP_FMAXNUM:
8382 case ISD::VP_FCOPYSIGN:
8389 return lowerVPOp(
Op, DAG);
8390 case ISD::VP_IS_FPCLASS:
8391 return LowerIS_FPCLASS(
Op, DAG);
8392 case ISD::VP_SIGN_EXTEND:
8393 case ISD::VP_ZERO_EXTEND:
8394 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
8395 return lowerVPExtMaskOp(
Op, DAG);
8396 return lowerVPOp(
Op, DAG);
8397 case ISD::VP_TRUNCATE:
8398 return lowerVectorTruncLike(
Op, DAG);
8399 case ISD::VP_FP_EXTEND:
8400 case ISD::VP_FP_ROUND:
8401 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
8402 case ISD::VP_SINT_TO_FP:
8403 case ISD::VP_UINT_TO_FP:
8404 if (
Op.getValueType().isVector() &&
8405 ((
Op.getValueType().getScalarType() == MVT::f16 &&
8408 Op.getValueType().getScalarType() == MVT::bf16)) {
8421 case ISD::VP_FP_TO_SINT:
8422 case ISD::VP_FP_TO_UINT:
8424 Op1.getValueType().isVector() &&
8425 ((Op1.getValueType().getScalarType() == MVT::f16 &&
8428 Op1.getValueType().getScalarType() == MVT::bf16)) {
8434 Op1.getValueType().getVectorElementCount());
8438 {WidenVec, Op.getOperand(1), Op.getOperand(2)});
8440 return lowerVPFPIntConvOp(
Op, DAG);
8444 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
8445 return lowerVPSetCCMaskOp(
Op, DAG);
8451 case ISD::VP_BITREVERSE:
8453 return lowerVPOp(
Op, DAG);
8455 case ISD::VP_CTLZ_ZERO_UNDEF:
8456 if (Subtarget.hasStdExtZvbb())
8457 return lowerVPOp(
Op, DAG);
8458 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8460 case ISD::VP_CTTZ_ZERO_UNDEF:
8461 if (Subtarget.hasStdExtZvbb())
8462 return lowerVPOp(
Op, DAG);
8463 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8465 return lowerVPOp(
Op, DAG);
8466 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
8467 return lowerVPStridedLoad(
Op, DAG);
8468 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
8469 return lowerVPStridedStore(
Op, DAG);
8471 case ISD::VP_FFLOOR:
8473 case ISD::VP_FNEARBYINT:
8474 case ISD::VP_FROUND:
8475 case ISD::VP_FROUNDEVEN:
8476 case ISD::VP_FROUNDTOZERO:
8480 case ISD::VP_FMAXIMUM:
8481 case ISD::VP_FMINIMUM:
8485 case ISD::EXPERIMENTAL_VP_SPLICE:
8486 return lowerVPSpliceExperimental(
Op, DAG);
8487 case ISD::EXPERIMENTAL_VP_REVERSE:
8488 return lowerVPReverseExperimental(
Op, DAG);
8489 case ISD::EXPERIMENTAL_VP_SPLAT:
8490 return lowerVPSplatExperimental(
Op, DAG);
8493 "llvm.clear_cache only needs custom lower on Linux targets");
8496 return emitFlushICache(DAG,
Op.getOperand(0),
Op.getOperand(1),
8497 Op.getOperand(2), Flags,
DL);
8500 return lowerDYNAMIC_STACKALLOC(
Op, DAG);
8502 return lowerINIT_TRAMPOLINE(
Op, DAG);
8504 return lowerADJUST_TRAMPOLINE(
Op, DAG);
8508 return lowerPARTIAL_REDUCE_MLA(
Op, DAG);
8515 MakeLibCallOptions CallOptions;
8516 std::pair<SDValue, SDValue> CallResult =
8517 makeLibCall(DAG, RTLIB::RISCV_FLUSH_ICACHE, MVT::isVoid,
8518 {Start,
End, Flags}, CallOptions,
DL, InChain);
8521 return CallResult.second;
8534 std::unique_ptr<MCCodeEmitter> CodeEmitter(
8541 const Value *TrmpAddr = cast<SrcValueSDNode>(
Op.getOperand(4))->getValue();
8562 const bool HasCFBranch =
8563 Subtarget.hasStdExtZicfilp() &&
8565 "cf-protection-branch");
8566 const unsigned StaticChainIdx = HasCFBranch ? 5 : 4;
8567 const unsigned StaticChainOffset = StaticChainIdx * 4;
8568 const unsigned FunctionAddressOffset = StaticChainOffset + 8;
8572 auto GetEncoding = [&](
const MCInst &MC) {
8575 CodeEmitter->encodeInstruction(MC, CB, Fixups, *STI);
8587 GetEncoding(
MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X7).addImm(0)),
8594 .addImm(FunctionAddressOffset)),
8600 .addImm(StaticChainOffset)),
8611 GetEncoding(
MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X0).addImm(0)),
8614 GetEncoding(
MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X28).addImm(0)),
8621 .addImm(FunctionAddressOffset - 4)),
8627 .addImm(StaticChainOffset - 4)),
8647 SDValue FunctionAddress =
Op.getOperand(2);
8651 struct OffsetValuePair {
8655 } OffsetValues[] = {
8656 {StaticChainOffset, StaticChain},
8657 {FunctionAddressOffset, FunctionAddress},
8659 for (
auto &OffsetValue : OffsetValues) {
8662 DAG.
getConstant(OffsetValue.Offset, dl, MVT::i64));
8663 OffsetValue.Addr =
Addr;
8669 assert(OutChains.
size() == StaticChainIdx + 2 &&
8670 "Size of OutChains mismatch");
8675 SDValue EndOfTrmp = OffsetValues[0].Addr;
8689 return Op.getOperand(0);
8698 MVT VT =
Op.getSimpleValueType();
8704 MVT ArgVT =
A.getSimpleValueType();
8705 assert(ArgVT ==
B.getSimpleValueType() &&
8715 MVT ContainerVT = VT;
8724 switch (
Op.getOpcode()) {
8726 Opc = RISCVISD::VQDOT_VL;
8729 Opc = RISCVISD::VQDOTU_VL;
8732 Opc = RISCVISD::VQDOTSU_VL;
8758 N->getOffset(), Flags);
8787template <
class NodeTy>
8789 bool IsLocal,
bool IsExternWeak)
const {
8799 if (IsLocal && !Subtarget.allowTaggedGlobals())
8829 return DAG.
getNode(RISCVISD::ADD_LO,
DL, Ty, MNHi, AddrLo);
8869 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
8878 return getAddr(
N, DAG);
8885 return getAddr(
N, DAG);
8892 return getAddr(
N, DAG);
8897 bool UseGOT)
const {
8938 DAG.
getNode(RISCVISD::ADD_TPREL,
DL, Ty, MNHi, TPReg, AddrAdd);
8939 return DAG.
getNode(RISCVISD::ADD_LO,
DL, Ty, MNAdd, AddrLo);
8958 Args.emplace_back(Load, CallTy);
8991 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
9005 Addr = getStaticTLSAddr(
N, DAG,
false);
9008 Addr = getStaticTLSAddr(
N, DAG,
true);
9013 : getDynamicTLSAddr(
N, DAG);
9030 if (
LHS == LHS2 &&
RHS == RHS2) {
9035 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
9043 return std::nullopt;
9051 MVT VT =
N->getSimpleValueType(0);
9081 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV)) {
9084 if (~TrueVal == FalseVal) {
9124 if (Subtarget.hasShortForwardBranchOpt())
9127 unsigned SelOpNo = 0;
9137 unsigned ConstSelOpNo = 1;
9138 unsigned OtherSelOpNo = 2;
9139 if (!isa<ConstantSDNode>(Sel->
getOperand(ConstSelOpNo))) {
9144 ConstantSDNode *ConstSelOpNode = dyn_cast<ConstantSDNode>(ConstSelOp);
9145 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
9149 ConstantSDNode *ConstBinOpNode = dyn_cast<ConstantSDNode>(ConstBinOp);
9150 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
9156 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
9158 std::swap(NewConstOps[0], NewConstOps[1]);
9170 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
9172 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
9175 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
9176 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
9185 MVT VT =
Op.getSimpleValueType();
9199 if ((Subtarget.hasStdExtZicond() || Subtarget.hasVendorXVentanaCondOps()) &&
9203 return DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV);
9206 return DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV);
9210 auto getNotOperand = [](
const SDValue &
Op) -> std::optional<const SDValue> {
9216 return std::nullopt;
9222 auto NotOperand = (TrueV.
getOperand(0) == FalseV)
9227 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, *NotOperand, CondV);
9233 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV));
9240 auto NotOperand = (FalseV.
getOperand(0) == TrueV)
9245 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, *NotOperand, CondV);
9251 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV));
9260 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV)) {
9272 int64_t TrueImm =
TrueVal.getSExtValue();
9273 int64_t FalseImm =
FalseVal.getSExtValue();
9276 if (isInt<12>(TrueImm) && isInt<12>(FalseImm) &&
9277 isInt<12>(TrueImm - FalseImm)) {
9292 if ((TrueVal - FalseVal).isPowerOf2() &&
FalseVal.isSignedIntN(12)) {
9297 if ((FalseVal - TrueVal).isPowerOf2() &&
TrueVal.isSignedIntN(12)) {
9306 Delta, Subtarget.
getXLen(), Subtarget,
true);
9308 if (Addend.isSignedIntN(12))
9311 Addend, Subtarget.
getXLen(), Subtarget,
true);
9312 return AddendCost + DeltaCost;
9314 bool IsCZERO_NEZ =
getCost(FalseVal - TrueVal, TrueVal) <=
9315 getCost(TrueVal - FalseVal, FalseVal);
9317 IsCZERO_NEZ ? FalseVal - TrueVal : TrueVal - FalseVal,
DL, VT);
9319 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9320 DL, VT, LHSVal, CondV);
9326 if (isa<ConstantSDNode>(TrueV) != isa<ConstantSDNode>(FalseV)) {
9327 bool IsCZERO_NEZ = isa<ConstantSDNode>(TrueV);
9328 SDValue ConstVal = IsCZERO_NEZ ? TrueV : FalseV;
9329 SDValue RegV = IsCZERO_NEZ ? FalseV : TrueV;
9330 int64_t RawConstVal = cast<ConstantSDNode>(ConstVal)->getSExtValue();
9332 if (RawConstVal == -0x800) {
9335 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9336 DL, VT, XorOp, CondV);
9341 if (isInt<12>(RawConstVal)) {
9344 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9345 DL, VT, SubOp, CondV);
9355 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV),
9356 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV),
9363 if (
Op.hasOneUse()) {
9364 unsigned UseOpc =
Op->user_begin()->getOpcode();
9373 return lowerSELECT(NewSel, DAG);
9402 SDValue Ops[] = {CondV,
Zero, SetNE, TrueV, FalseV};
9404 return DAG.
getNode(RISCVISD::SELECT_CC,
DL, VT, Ops);
9423 if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV) &&
9427 if (TrueVal - 1 == FalseVal)
9429 if (TrueVal + 1 == FalseVal)
9436 RHS == TrueV && LHS == FalseV) {
9453 if (isa<ConstantSDNode>(TrueV) && !isa<ConstantSDNode>(FalseV)) {
9461 return DAG.
getNode(RISCVISD::SELECT_CC,
DL, VT, Ops);
9478 return DAG.
getNode(RISCVISD::BR_CC,
DL,
Op.getValueType(),
Op.getOperand(0),
9479 LHS, RHS, TargetCC,
Op.getOperand(2));
9482 return DAG.
getNode(RISCVISD::BR_CC,
DL,
Op.getValueType(),
Op.getOperand(0),
9497 const Value *SV = cast<SrcValueSDNode>(
Op.getOperand(2))->getValue();
9509 int XLenInBytes = Subtarget.
getXLen() / 8;
9511 EVT VT =
Op.getValueType();
9514 unsigned Depth =
Op.getConstantOperandVal(0);
9516 int Offset = -(XLenInBytes * 2);
9533 int XLenInBytes = Subtarget.
getXLen() / 8;
9535 EVT VT =
Op.getValueType();
9537 unsigned Depth =
Op.getConstantOperandVal(0);
9539 int Off = -XLenInBytes;
9540 SDValue FrameAddr = lowerFRAMEADDR(
Op, DAG);
9559 EVT VT =
Lo.getValueType();
9598 EVT VT =
Lo.getValueType();
9649 MVT VT =
Op.getSimpleValueType();
9654 return DAG.
getNode(RISCVISD::VMSET_VL,
DL, VT, VL);
9658 return DAG.
getNode(RISCVISD::VMCLR_VL,
DL, VT, VL);
9675 MVT VecVT =
Op.getSimpleValueType();
9677 "Unexpected SPLAT_VECTOR_PARTS lowering");
9683 MVT ContainerVT = VecVT;
9703 int64_t ExtTrueVal)
const {
9705 MVT VecVT =
Op.getSimpleValueType();
9708 assert(Src.getValueType().isVector() &&
9709 Src.getValueType().getVectorElementType() == MVT::i1);
9735 if (
Xor.getOpcode() == RISCVISD::VMXOR_VL) {
9741 CC =
Xor.getOperand(0);
9747 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9748 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
9749 SplatTrueVal = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9750 DAG.
getUNDEF(ContainerVT), SplatTrueVal, VL);
9752 DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, CC, SplatTrueVal,
9753 SplatZero, DAG.
getUNDEF(ContainerVT), VL);
9763 bool IsVPTrunc =
Op.getOpcode() == ISD::VP_TRUNCATE;
9765 EVT MaskVT =
Op.getValueType();
9768 "Unexpected type for vector mask lowering");
9770 MVT VecVT = Src.getSimpleValueType();
9774 VL =
Op.getOperand(2);
9777 MVT ContainerVT = VecVT;
9783 MVT MaskContainerVT =
9790 std::tie(Mask, VL) =
9797 SplatOne = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9798 DAG.
getUNDEF(ContainerVT), SplatOne, VL);
9799 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9800 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
9803 SDValue Trunc = DAG.
getNode(RISCVISD::AND_VL,
DL, ContainerVT, Src, SplatOne,
9804 DAG.
getUNDEF(ContainerVT), Mask, VL);
9805 Trunc = DAG.
getNode(RISCVISD::SETCC_VL,
DL, MaskContainerVT,
9807 DAG.
getUNDEF(MaskContainerVT), Mask, VL});
9815 unsigned Opc =
Op.getOpcode();
9816 bool IsVPTrunc =
Opc == ISD::VP_TRUNCATE;
9819 MVT VT =
Op.getSimpleValueType();
9821 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
9825 return lowerVectorMaskTruncLike(
Op, DAG);
9833 MVT SrcVT = Src.getSimpleValueType();
9838 "Unexpected vector truncate lowering");
9840 MVT ContainerVT = SrcVT;
9844 VL =
Op.getOperand(2);
9857 std::tie(Mask, VL) =
9863 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL_SSAT;
9865 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL_USAT;
9867 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL;
9873 }
while (SrcEltVT != DstEltVT);
9882RISCVTargetLowering::lowerStrictFPExtendOrRoundLike(
SDValue Op,
9887 MVT VT =
Op.getSimpleValueType();
9888 MVT SrcVT = Src.getSimpleValueType();
9889 MVT ContainerVT = VT;
9908 ? RISCVISD::STRICT_FP_EXTEND_VL
9909 : RISCVISD::STRICT_VFNCVT_ROD_VL;
9912 Chain, Src, Mask, VL);
9913 Chain = Src.getValue(1);
9917 ? RISCVISD::STRICT_FP_EXTEND_VL
9918 : RISCVISD::STRICT_FP_ROUND_VL;
9920 Chain, Src, Mask, VL);
9931RISCVTargetLowering::lowerVectorFPExtendOrRoundLike(
SDValue Op,
9934 Op.getOpcode() == ISD::VP_FP_ROUND ||
Op.getOpcode() == ISD::VP_FP_EXTEND;
9941 MVT VT =
Op.getSimpleValueType();
9943 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
9946 MVT SrcVT = Src.getSimpleValueType();
9948 bool IsDirectExtend =
9956 bool IsDirectConv = IsDirectExtend || IsDirectTrunc;
9963 MVT ContainerVT = VT;
9967 VL =
Op.getOperand(2);
9981 std::tie(Mask, VL) =
9984 unsigned ConvOpc = IsExtend ? RISCVISD::FP_EXTEND_VL : RISCVISD::FP_ROUND_VL;
9987 Src = DAG.
getNode(ConvOpc,
DL, ContainerVT, Src, Mask, VL);
9993 unsigned InterConvOpc =
9994 IsExtend ? RISCVISD::FP_EXTEND_VL : RISCVISD::VFNCVT_ROD_VL;
9998 DAG.
getNode(InterConvOpc,
DL, InterVT, Src, Mask, VL);
10000 DAG.
getNode(ConvOpc,
DL, ContainerVT, IntermediateConv, Mask, VL);
10011static std::optional<MVT>
10017 const unsigned MinVLMAX = VectorBitsMin / EltSize;
10019 if (MaxIdx < MinVLMAX)
10021 else if (MaxIdx < MinVLMAX * 2)
10024 else if (MaxIdx < MinVLMAX * 4)
10029 return std::nullopt;
10034 auto *IdxC = dyn_cast<ConstantSDNode>(
Idx);
10037 return isUInt<5>(IdxC->getZExtValue());
10049 MVT VecVT =
Op.getSimpleValueType();
10066 ValVT == MVT::bf16) {
10071 DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Val),
Idx);
10075 MVT ContainerVT = VecVT;
10085 std::optional<unsigned> AlignedIdx;
10086 if (
auto *IdxC = dyn_cast<ConstantSDNode>(
Idx)) {
10087 const unsigned OrigIdx = IdxC->getZExtValue();
10090 DL, DAG, Subtarget)) {
10091 ContainerVT = *ShrunkVT;
10102 unsigned RemIdx = OrigIdx % ElemsPerVReg;
10103 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
10106 ContainerVT = M1VT;
10118 if (!IsLegalInsert && isa<ConstantSDNode>(Val)) {
10119 const auto *CVal = cast<ConstantSDNode>(Val);
10120 if (isInt<32>(CVal->getSExtValue())) {
10121 IsLegalInsert =
true;
10130 if (IsLegalInsert) {
10132 VecVT.
isFloatingPoint() ? RISCVISD::VFMV_S_F_VL : RISCVISD::VMV_S_X_VL;
10136 Vec = DAG.
getNode(
Opc,
DL, ContainerVT, Vec, Val, VL);
10146 if (Subtarget.hasVendorXRivosVisni() && VecVT.
isInteger() &&
10151 Vec = DAG.
getNode(RISCVISD::RI_VINSERT_VL,
DL, ContainerVT, Vec, Val,
Idx,
10167 std::tie(ValLo, ValHi) = DAG.
SplitScalar(Val,
DL, MVT::i32, MVT::i32);
10168 MVT I32ContainerVT =
10178 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10179 Vec, Vec, ValLo, I32Mask, InsertI64VL);
10183 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10184 Tail, ValInVec, ValHi, I32Mask, InsertI64VL);
10186 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
10197 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10199 DAG.
getUNDEF(I32ContainerVT), ValLo,
10200 I32Mask, InsertI64VL);
10201 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10202 DAG.
getUNDEF(I32ContainerVT), ValInVec, ValHi,
10203 I32Mask, InsertI64VL);
10205 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
10218 Idx, Mask, InsertVL, Policy);
10236 EVT EltVT =
Op.getValueType();
10243 MVT ContainerVT = VecVT;
10250 DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Vec, Mask, VL);
10257 if (NumElts >= 8) {
10259 unsigned WidenVecLen;
10262 unsigned MaxEEW = Subtarget.
getELen();
10267 "the number of elements should be power of 2");
10271 ExtractBitIdx =
Idx;
10273 WideEltVT = LargestEltVT;
10276 ExtractElementIdx = DAG.
getNode(
10287 Vec, ExtractElementIdx);
10303 EltVT == MVT::bf16) {
10309 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, EltVT, IntExtract);
10313 MVT ContainerVT = VecVT;
10324 if (
auto *IdxC = dyn_cast<ConstantSDNode>(
Idx);
10325 IdxC && VLen && VecVT.
getSizeInBits().getKnownMinValue() > *VLen) {
10327 unsigned OrigIdx = IdxC->getZExtValue();
10330 unsigned RemIdx = OrigIdx % ElemsPerVReg;
10331 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
10332 unsigned ExtractIdx =
10336 ContainerVT = M1VT;
10341 std::optional<uint64_t> MaxIdx;
10344 if (
auto *IdxC = dyn_cast<ConstantSDNode>(
Idx))
10345 MaxIdx = IdxC->getZExtValue();
10347 if (
auto SmallerVT =
10349 ContainerVT = *SmallerVT;
10356 if (Subtarget.hasVendorXRivosVisni() && EltVT.
isInteger() &&
10403 "Unexpected opcode");
10410 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
10415 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
10416 if (!
II || !
II->hasScalarOperand())
10419 unsigned SplatOp =
II->ScalarOperand + 1 + HasChain;
10432 if (OpVT.
bitsLT(XLenVT)) {
10439 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
10449 assert(
II->ScalarOperand > 0 &&
"Unexpected splat operand!");
10450 MVT VT =
Op.getOperand(SplatOp - 1).getSimpleValueType();
10453 assert(XLenVT == MVT::i32 && OpVT == MVT::i64 &&
10464 case Intrinsic::riscv_vslide1up:
10465 case Intrinsic::riscv_vslide1down:
10466 case Intrinsic::riscv_vslide1up_mask:
10467 case Intrinsic::riscv_vslide1down_mask: {
10470 bool IsMasked = NumOps == 7;
10476 std::tie(ScalarLo, ScalarHi) =
10484 if (isa<ConstantSDNode>(AVL)) {
10485 const auto [MinVLMAX, MaxVLMAX] =
10489 if (AVLInt <= MinVLMAX) {
10491 }
else if (AVLInt >= 2 * MaxVLMAX) {
10525 if (IntNo == Intrinsic::riscv_vslide1up ||
10526 IntNo == Intrinsic::riscv_vslide1up_mask) {
10527 Vec = DAG.
getNode(RISCVISD::VSLIDE1UP_VL,
DL, I32VT, Passthru, Vec,
10528 ScalarHi, I32Mask, I32VL);
10529 Vec = DAG.
getNode(RISCVISD::VSLIDE1UP_VL,
DL, I32VT, Passthru, Vec,
10530 ScalarLo, I32Mask, I32VL);
10532 Vec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32VT, Passthru, Vec,
10533 ScalarLo, I32Mask, I32VL);
10534 Vec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32VT, Passthru, Vec,
10535 ScalarHi, I32Mask, I32VL);
10553 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, Mask, Vec, MaskedOff,
10557 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, Mask, Vec, MaskedOff,
10584 const unsigned ElementWidth = 8;
10589 [[maybe_unused]]
unsigned MinVF =
10592 [[maybe_unused]]
unsigned VF =
N->getConstantOperandVal(2);
10596 bool Fractional = VF < LMul1VF;
10597 unsigned LMulVal = Fractional ? LMul1VF / VF : VF / LMul1VF;
10618 MVT ContainerVT = OpVT;
10626 SDValue Res = DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Op0, Mask, VL);
10634 return DAG.
getSelect(
DL, XLenVT, Setcc, VL, Res);
10645 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
10649 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
10650 if (!
II || !
II->hasScalarOperand())
10653 unsigned SplatOp =
II->ScalarOperand + 1;
10666 if (OpVT.
bitsLT(XLenVT)) {
10669 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
10680 EVT ValType = V.getValueType();
10681 if (ValType.isVector() && ValType.isFloatingPoint()) {
10684 ValType.getVectorElementCount());
10687 if (ValType.isFixedLengthVector()) {
10689 DAG, V.getSimpleValueType(), Subtarget);
10705 unsigned IntNo =
Op.getConstantOperandVal(0);
10712 case Intrinsic::riscv_tuple_insert: {
10717 return DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL,
Op.getValueType(), Vec,
10720 case Intrinsic::riscv_tuple_extract: {
10724 return DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL,
Op.getValueType(), Vec,
10727 case Intrinsic::thread_pointer: {
10731 case Intrinsic::riscv_orc_b:
10732 case Intrinsic::riscv_brev8:
10733 case Intrinsic::riscv_sha256sig0:
10734 case Intrinsic::riscv_sha256sig1:
10735 case Intrinsic::riscv_sha256sum0:
10736 case Intrinsic::riscv_sha256sum1:
10737 case Intrinsic::riscv_sm3p0:
10738 case Intrinsic::riscv_sm3p1: {
10741 case Intrinsic::riscv_orc_b:
Opc = RISCVISD::ORC_B;
break;
10742 case Intrinsic::riscv_brev8:
Opc = RISCVISD::BREV8;
break;
10743 case Intrinsic::riscv_sha256sig0:
Opc = RISCVISD::SHA256SIG0;
break;
10744 case Intrinsic::riscv_sha256sig1:
Opc = RISCVISD::SHA256SIG1;
break;
10745 case Intrinsic::riscv_sha256sum0:
Opc = RISCVISD::SHA256SUM0;
break;
10746 case Intrinsic::riscv_sha256sum1:
Opc = RISCVISD::SHA256SUM1;
break;
10747 case Intrinsic::riscv_sm3p0:
Opc = RISCVISD::SM3P0;
break;
10748 case Intrinsic::riscv_sm3p1:
Opc = RISCVISD::SM3P1;
break;
10753 case Intrinsic::riscv_sm4ks:
10754 case Intrinsic::riscv_sm4ed: {
10756 IntNo == Intrinsic::riscv_sm4ks ? RISCVISD::SM4KS : RISCVISD::SM4ED;
10761 case Intrinsic::riscv_zip:
10762 case Intrinsic::riscv_unzip: {
10764 IntNo == Intrinsic::riscv_zip ? RISCVISD::ZIP : RISCVISD::UNZIP;
10767 case Intrinsic::riscv_mopr:
10768 return DAG.
getNode(RISCVISD::MOP_R,
DL, XLenVT,
Op.getOperand(1),
10771 case Intrinsic::riscv_moprr: {
10772 return DAG.
getNode(RISCVISD::MOP_RR,
DL, XLenVT,
Op.getOperand(1),
10773 Op.getOperand(2),
Op.getOperand(3));
10775 case Intrinsic::riscv_clmul:
10776 return DAG.
getNode(RISCVISD::CLMUL,
DL, XLenVT,
Op.getOperand(1),
10778 case Intrinsic::riscv_clmulh:
10779 case Intrinsic::riscv_clmulr: {
10781 IntNo == Intrinsic::riscv_clmulh ? RISCVISD::CLMULH : RISCVISD::CLMULR;
10784 case Intrinsic::experimental_get_vector_length:
10786 case Intrinsic::experimental_cttz_elts:
10788 case Intrinsic::riscv_vmv_x_s: {
10792 case Intrinsic::riscv_vfmv_f_s:
10794 case Intrinsic::riscv_vmv_v_x:
10796 Op.getOperand(3),
Op.getSimpleValueType(),
DL, DAG,
10798 case Intrinsic::riscv_vfmv_v_f:
10799 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL,
Op.getValueType(),
10800 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
10801 case Intrinsic::riscv_vmv_s_x: {
10804 if (Scalar.getValueType().bitsLE(XLenVT)) {
10806 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL,
Op.getValueType(),
10807 Op.getOperand(1), Scalar,
Op.getOperand(3));
10810 assert(Scalar.getValueType() == MVT::i64 &&
"Unexpected scalar VT!");
10827 MVT VT =
Op.getSimpleValueType();
10832 if (
Op.getOperand(1).isUndef())
10833 return SplattedVal;
10842 DAG.
getNode(RISCVISD::SETCC_VL,
DL, MaskVT,
10845 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, SelectCond, SplattedVal,
10848 case Intrinsic::riscv_vfmv_s_f:
10849 return DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL,
Op.getSimpleValueType(),
10850 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
10852 case Intrinsic::riscv_vaesdf_vv:
10853 case Intrinsic::riscv_vaesdf_vs:
10854 case Intrinsic::riscv_vaesdm_vv:
10855 case Intrinsic::riscv_vaesdm_vs:
10856 case Intrinsic::riscv_vaesef_vv:
10857 case Intrinsic::riscv_vaesef_vs:
10858 case Intrinsic::riscv_vaesem_vv:
10859 case Intrinsic::riscv_vaesem_vs:
10860 case Intrinsic::riscv_vaeskf1:
10861 case Intrinsic::riscv_vaeskf2:
10862 case Intrinsic::riscv_vaesz_vs:
10863 case Intrinsic::riscv_vsm4k:
10864 case Intrinsic::riscv_vsm4r_vv:
10865 case Intrinsic::riscv_vsm4r_vs: {
10866 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
10867 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
10868 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
10873 case Intrinsic::riscv_vsm3c:
10874 case Intrinsic::riscv_vsm3me: {
10875 if (!
isValidEGW(8,
Op.getSimpleValueType(), Subtarget) ||
10876 !
isValidEGW(8,
Op->getOperand(1).getSimpleValueType(), Subtarget))
10881 case Intrinsic::riscv_vsha2ch:
10882 case Intrinsic::riscv_vsha2cl:
10883 case Intrinsic::riscv_vsha2ms: {
10884 if (
Op->getSimpleValueType(0).getScalarSizeInBits() == 64 &&
10885 !Subtarget.hasStdExtZvknhb())
10887 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
10888 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
10889 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
10893 case Intrinsic::riscv_sf_vc_v_x:
10894 case Intrinsic::riscv_sf_vc_v_i:
10895 case Intrinsic::riscv_sf_vc_v_xv:
10896 case Intrinsic::riscv_sf_vc_v_iv:
10897 case Intrinsic::riscv_sf_vc_v_vv:
10898 case Intrinsic::riscv_sf_vc_v_fv:
10899 case Intrinsic::riscv_sf_vc_v_xvv:
10900 case Intrinsic::riscv_sf_vc_v_ivv:
10901 case Intrinsic::riscv_sf_vc_v_vvv:
10902 case Intrinsic::riscv_sf_vc_v_fvv:
10903 case Intrinsic::riscv_sf_vc_v_xvw:
10904 case Intrinsic::riscv_sf_vc_v_ivw:
10905 case Intrinsic::riscv_sf_vc_v_vvw:
10906 case Intrinsic::riscv_sf_vc_v_fvw: {
10907 MVT VT =
Op.getSimpleValueType();
10944 MVT VT =
Op.getSimpleValueType();
10948 if (VT.isFloatingPoint()) {
10953 if (VT.isFixedLengthVector())
10963 if (VT.isFixedLengthVector())
10965 if (VT.isFloatingPoint())
10988 case Intrinsic::riscv_seg2_load_mask:
10989 case Intrinsic::riscv_seg3_load_mask:
10990 case Intrinsic::riscv_seg4_load_mask:
10991 case Intrinsic::riscv_seg5_load_mask:
10992 case Intrinsic::riscv_seg6_load_mask:
10993 case Intrinsic::riscv_seg7_load_mask:
10994 case Intrinsic::riscv_seg8_load_mask:
10997 case Intrinsic::riscv_sseg2_load_mask:
10998 case Intrinsic::riscv_sseg3_load_mask:
10999 case Intrinsic::riscv_sseg4_load_mask:
11000 case Intrinsic::riscv_sseg5_load_mask:
11001 case Intrinsic::riscv_sseg6_load_mask:
11002 case Intrinsic::riscv_sseg7_load_mask:
11003 case Intrinsic::riscv_sseg8_load_mask:
11011 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
11012 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
11013 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
11014 Intrinsic::riscv_vlseg8_mask};
11016 Intrinsic::riscv_vlsseg2_mask, Intrinsic::riscv_vlsseg3_mask,
11017 Intrinsic::riscv_vlsseg4_mask, Intrinsic::riscv_vlsseg5_mask,
11018 Intrinsic::riscv_vlsseg6_mask, Intrinsic::riscv_vlsseg7_mask,
11019 Intrinsic::riscv_vlsseg8_mask};
11022 unsigned NF =
Op->getNumValues() - 1;
11023 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
11025 MVT VT =
Op->getSimpleValueType(0);
11035 MVT MaskVT = Mask.getSimpleValueType();
11036 MVT MaskContainerVT =
11041 IsStrided ? VlssegInts[NF - 2] : VlsegInts[NF - 2],
DL, XLenVT);
11042 auto *Load = cast<MemIntrinsicSDNode>(
Op);
11061 Load->getMemoryVT(), Load->getMemOperand());
11063 for (
unsigned int RetIdx = 0; RetIdx < NF; RetIdx++) {
11065 Result.getValue(0),
11069 Results.push_back(Result.getValue(1));
11075 unsigned IntNo =
Op.getConstantOperandVal(1);
11079 case Intrinsic::riscv_seg2_load_mask:
11080 case Intrinsic::riscv_seg3_load_mask:
11081 case Intrinsic::riscv_seg4_load_mask:
11082 case Intrinsic::riscv_seg5_load_mask:
11083 case Intrinsic::riscv_seg6_load_mask:
11084 case Intrinsic::riscv_seg7_load_mask:
11085 case Intrinsic::riscv_seg8_load_mask:
11086 case Intrinsic::riscv_sseg2_load_mask:
11087 case Intrinsic::riscv_sseg3_load_mask:
11088 case Intrinsic::riscv_sseg4_load_mask:
11089 case Intrinsic::riscv_sseg5_load_mask:
11090 case Intrinsic::riscv_sseg6_load_mask:
11091 case Intrinsic::riscv_sseg7_load_mask:
11092 case Intrinsic::riscv_sseg8_load_mask:
11095 case Intrinsic::riscv_sf_vc_v_x_se:
11097 case Intrinsic::riscv_sf_vc_v_i_se:
11099 case Intrinsic::riscv_sf_vc_v_xv_se:
11101 case Intrinsic::riscv_sf_vc_v_iv_se:
11103 case Intrinsic::riscv_sf_vc_v_vv_se:
11105 case Intrinsic::riscv_sf_vc_v_fv_se:
11107 case Intrinsic::riscv_sf_vc_v_xvv_se:
11109 case Intrinsic::riscv_sf_vc_v_ivv_se:
11111 case Intrinsic::riscv_sf_vc_v_vvv_se:
11113 case Intrinsic::riscv_sf_vc_v_fvv_se:
11115 case Intrinsic::riscv_sf_vc_v_xvw_se:
11117 case Intrinsic::riscv_sf_vc_v_ivw_se:
11119 case Intrinsic::riscv_sf_vc_v_vvw_se:
11121 case Intrinsic::riscv_sf_vc_v_fvw_se:
11134 case Intrinsic::riscv_seg2_store_mask:
11135 case Intrinsic::riscv_seg3_store_mask:
11136 case Intrinsic::riscv_seg4_store_mask:
11137 case Intrinsic::riscv_seg5_store_mask:
11138 case Intrinsic::riscv_seg6_store_mask:
11139 case Intrinsic::riscv_seg7_store_mask:
11140 case Intrinsic::riscv_seg8_store_mask:
11143 case Intrinsic::riscv_sseg2_store_mask:
11144 case Intrinsic::riscv_sseg3_store_mask:
11145 case Intrinsic::riscv_sseg4_store_mask:
11146 case Intrinsic::riscv_sseg5_store_mask:
11147 case Intrinsic::riscv_sseg6_store_mask:
11148 case Intrinsic::riscv_sseg7_store_mask:
11149 case Intrinsic::riscv_sseg8_store_mask:
11158 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
11159 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
11160 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
11161 Intrinsic::riscv_vsseg8_mask};
11163 Intrinsic::riscv_vssseg2_mask, Intrinsic::riscv_vssseg3_mask,
11164 Intrinsic::riscv_vssseg4_mask, Intrinsic::riscv_vssseg5_mask,
11165 Intrinsic::riscv_vssseg6_mask, Intrinsic::riscv_vssseg7_mask,
11166 Intrinsic::riscv_vssseg8_mask};
11171 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
11173 MVT VT =
Op->getOperand(2).getSimpleValueType();
11181 MVT MaskVT = Mask.getSimpleValueType();
11182 MVT MaskContainerVT =
11187 IsStrided ? VsssegInts[NF - 2] : VssegInts[NF - 2],
DL, XLenVT);
11190 auto *FixedIntrinsic = cast<MemIntrinsicSDNode>(
Op);
11193 for (
unsigned i = 0; i < NF; i++)
11195 RISCVISD::TUPLE_INSERT,
DL, VecTupTy, StoredVal,
11201 FixedIntrinsic->getChain(),
11215 FixedIntrinsic->getMemoryVT(), FixedIntrinsic->getMemOperand());
11220 unsigned IntNo =
Op.getConstantOperandVal(1);
11224 case Intrinsic::riscv_seg2_store_mask:
11225 case Intrinsic::riscv_seg3_store_mask:
11226 case Intrinsic::riscv_seg4_store_mask:
11227 case Intrinsic::riscv_seg5_store_mask:
11228 case Intrinsic::riscv_seg6_store_mask:
11229 case Intrinsic::riscv_seg7_store_mask:
11230 case Intrinsic::riscv_seg8_store_mask:
11231 case Intrinsic::riscv_sseg2_store_mask:
11232 case Intrinsic::riscv_sseg3_store_mask:
11233 case Intrinsic::riscv_sseg4_store_mask:
11234 case Intrinsic::riscv_sseg5_store_mask:
11235 case Intrinsic::riscv_sseg6_store_mask:
11236 case Intrinsic::riscv_sseg7_store_mask:
11237 case Intrinsic::riscv_sseg8_store_mask:
11240 case Intrinsic::riscv_sf_vc_xv_se:
11242 case Intrinsic::riscv_sf_vc_iv_se:
11244 case Intrinsic::riscv_sf_vc_vv_se:
11246 case Intrinsic::riscv_sf_vc_fv_se:
11248 case Intrinsic::riscv_sf_vc_xvv_se:
11250 case Intrinsic::riscv_sf_vc_ivv_se:
11252 case Intrinsic::riscv_sf_vc_vvv_se:
11254 case Intrinsic::riscv_sf_vc_fvv_se:
11256 case Intrinsic::riscv_sf_vc_xvw_se:
11258 case Intrinsic::riscv_sf_vc_ivw_se:
11260 case Intrinsic::riscv_sf_vc_vvw_se:
11262 case Intrinsic::riscv_sf_vc_fvw_se:
11270 switch (ISDOpcode) {
11273 case ISD::VP_REDUCE_ADD:
11275 return RISCVISD::VECREDUCE_ADD_VL;
11276 case ISD::VP_REDUCE_UMAX:
11278 return RISCVISD::VECREDUCE_UMAX_VL;
11279 case ISD::VP_REDUCE_SMAX:
11281 return RISCVISD::VECREDUCE_SMAX_VL;
11282 case ISD::VP_REDUCE_UMIN:
11284 return RISCVISD::VECREDUCE_UMIN_VL;
11285 case ISD::VP_REDUCE_SMIN:
11287 return RISCVISD::VECREDUCE_SMIN_VL;
11288 case ISD::VP_REDUCE_AND:
11290 return RISCVISD::VECREDUCE_AND_VL;
11291 case ISD::VP_REDUCE_OR:
11293 return RISCVISD::VECREDUCE_OR_VL;
11294 case ISD::VP_REDUCE_XOR:
11296 return RISCVISD::VECREDUCE_XOR_VL;
11297 case ISD::VP_REDUCE_FADD:
11298 return RISCVISD::VECREDUCE_FADD_VL;
11299 case ISD::VP_REDUCE_SEQ_FADD:
11300 return RISCVISD::VECREDUCE_SEQ_FADD_VL;
11301 case ISD::VP_REDUCE_FMAX:
11302 case ISD::VP_REDUCE_FMAXIMUM:
11303 return RISCVISD::VECREDUCE_FMAX_VL;
11304 case ISD::VP_REDUCE_FMIN:
11305 case ISD::VP_REDUCE_FMINIMUM:
11306 return RISCVISD::VECREDUCE_FMIN_VL;
11315 SDValue Vec =
Op.getOperand(IsVP ? 1 : 0);
11320 Op.getOpcode() == ISD::VP_REDUCE_AND ||
11321 Op.getOpcode() == ISD::VP_REDUCE_OR ||
11322 Op.getOpcode() == ISD::VP_REDUCE_XOR) &&
11323 "Unexpected reduction lowering");
11327 MVT ContainerVT = VecVT;
11335 Mask =
Op.getOperand(2);
11336 VL =
Op.getOperand(3);
11338 std::tie(Mask, VL) =
11343 switch (
Op.getOpcode()) {
11347 case ISD::VP_REDUCE_AND: {
11351 Vec = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Vec, TrueMask, VL);
11354 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11359 case ISD::VP_REDUCE_OR:
11361 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11365 case ISD::VP_REDUCE_XOR: {
11368 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11389 return DAG.
getNode(BaseOpc,
DL,
Op.getValueType(), SetCC,
Op.getOperand(0));
11393 auto *RegisterAVL = dyn_cast<RegisterSDNode>(AVL);
11394 auto *ImmAVL = dyn_cast<ConstantSDNode>(AVL);
11395 return (RegisterAVL && RegisterAVL->getReg() == RISCV::X0) ||
11396 (ImmAVL && ImmAVL->getZExtValue() >= 1);
11412 auto InnerVT = VecVT.
bitsLE(M1VT) ? VecVT : M1VT;
11416 auto InnerVL = NonZeroAVL ? VL : DAG.
getConstant(1,
DL, XLenVT);
11419 if (M1VT != InnerVT)
11424 SDValue Ops[] = {PassThru, Vec, InitialValue, Mask, VL, Policy};
11442 VecEVT =
Lo.getValueType();
11455 MVT ContainerVT = VecVT;
11474 Mask, VL,
DL, DAG, Subtarget);
11480static std::tuple<unsigned, SDValue, SDValue>
11484 auto Flags =
Op->getFlags();
11485 unsigned Opcode =
Op.getOpcode();
11493 return std::make_tuple(RISCVISD::VECREDUCE_FADD_VL,
Op.getOperand(0), Zero);
11496 return std::make_tuple(RISCVISD::VECREDUCE_SEQ_FADD_VL,
Op.getOperand(1),
11505 ? RISCVISD::VECREDUCE_FMIN_VL
11506 : RISCVISD::VECREDUCE_FMAX_VL;
11507 return std::make_tuple(RVVOpc,
Op.getOperand(0), Front);
11515 MVT VecEltVT =
Op.getSimpleValueType();
11517 unsigned RVVOpcode;
11518 SDValue VectorVal, ScalarVal;
11519 std::tie(RVVOpcode, VectorVal, ScalarVal) =
11523 MVT ContainerVT = VecVT;
11529 MVT ResVT =
Op.getSimpleValueType();
11532 VL,
DL, DAG, Subtarget);
11537 if (
Op->getFlags().hasNoNaNs())
11543 {VectorVal, VectorVal, DAG.getCondCode(ISD::SETNE),
11544 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
11546 SDValue CPop = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, IsNan, Mask, VL);
11550 DL, ResVT, NoNaNs, Res,
11557 unsigned Opc =
Op.getOpcode();
11580 Vec, Mask, VL,
DL, DAG, Subtarget);
11581 if ((
Opc != ISD::VP_REDUCE_FMINIMUM &&
Opc != ISD::VP_REDUCE_FMAXIMUM) ||
11582 Op->getFlags().hasNoNaNs())
11589 RISCVISD::SETCC_VL,
DL, PredVT,
11591 SDValue VCPop = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, IsNaN, Mask, VL);
11599 DL, ResVT, NoNaNs, Res,
11612 unsigned OrigIdx =
Op.getConstantOperandVal(2);
11615 if (OrigIdx == 0 && Vec.
isUndef())
11626 assert(OrigIdx % 8 == 0 &&
"Invalid index");
11629 "Unexpected mask vector lowering");
11661 MVT ContainerVT = VecVT;
11683 if (OrigIdx == 0) {
11685 DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, ContainerVT, Vec, SubVec, VL);
11688 SubVec =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, Vec, SubVec,
11689 SlideupAmt, Mask, VL, Policy);
11697 MVT ContainerVecVT = VecVT;
11703 MVT ContainerSubVecVT = SubVecVT;
11709 unsigned SubRegIdx;
11719 ContainerVecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
11720 SubRegIdx = Decompose.first;
11722 (OrigIdx % Vscale));
11726 ContainerVecVT, ContainerSubVecVT, OrigIdx,
TRI);
11727 SubRegIdx = Decompose.first;
11734 bool ExactlyVecRegSized =
11736 .isKnownMultipleOf(Subtarget.
expandVScale(VecRegSize));
11751 if (RemIdx.
isZero() && (ExactlyVecRegSized || Vec.
isUndef())) {
11755 if (SubRegIdx == RISCV::NoSubRegister) {
11777 MVT InterSubVT = ContainerVecVT;
11778 SDValue AlignedExtract = Vec;
11807 SubVec = DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, InterSubVT, AlignedExtract,
11815 SubVec =
getVSlideup(DAG, Subtarget,
DL, InterSubVT, AlignedExtract, SubVec,
11816 SlideupAmt, Mask, VL, Policy);
11821 if (ContainerVecVT.
bitsGT(InterSubVT))
11829 return DAG.
getBitcast(
Op.getSimpleValueType(), SubVec);
11835 MVT SubVecVT =
Op.getSimpleValueType();
11840 unsigned OrigIdx =
Op.getConstantOperandVal(1);
11856 assert(OrigIdx % 8 == 0 &&
"Invalid index");
11859 "Unexpected mask vector lowering");
11893 MVT ContainerVT = VecVT;
11901 if (
auto ShrunkVT =
11903 ContainerVT = *ShrunkVT;
11915 DAG.
getUNDEF(ContainerVT), Vec, SlidedownAmt, Mask, VL);
11926 MVT ContainerSubVecVT = SubVecVT;
11930 unsigned SubRegIdx;
11940 VecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
11941 SubRegIdx = Decompose.first;
11943 (OrigIdx % Vscale));
11947 VecVT, ContainerSubVecVT, OrigIdx,
TRI);
11948 SubRegIdx = Decompose.first;
11975 MVT InterSubVT = VecVT;
11980 assert(SubRegIdx != RISCV::NoSubRegister);
11999 Vec, SlidedownAmt, Mask, VL);
12007 return DAG.
getBitcast(
Op.getSimpleValueType(), Slidedown);
12014 MVT VT =
N.getSimpleValueType();
12018 assert(
Op.getSimpleValueType() == VT &&
12019 "Operands and result must be same type");
12023 unsigned NumVals =
N->getNumValues();
12026 NumVals,
N.getValueType().changeVectorElementType(MVT::i8)));
12029 for (
unsigned I = 0;
I < NumVals;
I++) {
12035 if (TruncVals.
size() > 1)
12037 return TruncVals.
front();
12043 MVT VecVT =
Op.getSimpleValueType();
12045 const unsigned Factor =
Op->getNumValues();
12056 for (
unsigned i = 0U; i < Factor; ++i)
12065 for (
unsigned i = 0U; i < Factor; ++i)
12075 for (
unsigned i = 0; i != Factor; ++i) {
12078 Ops[i * 2 + 1] = OpHi;
12086 ArrayRef(Ops).slice(Factor, Factor));
12089 for (
unsigned i = 0; i != Factor; ++i)
12096 if (Subtarget.hasVendorXRivosVizip() && Factor == 2) {
12097 MVT VT =
Op->getSimpleValueType(0);
12122 lowerVZIP(RISCVISD::RI_VUNZIP2A_VL, V1, V2,
DL, DAG, Subtarget);
12124 lowerVZIP(RISCVISD::RI_VUNZIP2B_VL, V1, V2,
DL, DAG, Subtarget);
12157 EvenSplat = DAG.
getBitcast(MVT::nxv64i1, EvenSplat);
12161 OddSplat = DAG.
getBitcast(MVT::nxv64i1, OddSplat);
12166 EvenMask, DAG.
getUNDEF(ConcatVT));
12200 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
12201 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
12202 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
12203 Intrinsic::riscv_vlseg8_mask};
12227 for (
unsigned i = 0U; i < Factor; ++i)
12228 Res[i] = DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL, VecVT, Load,
12237 MVT VecVT =
Op.getSimpleValueType();
12250 for (
unsigned i = 0U; i < Factor; ++i)
12258 for (
unsigned i = 0U; i < Factor; ++i)
12271 for (
unsigned i = 0; i != Factor; ++i) {
12274 Ops[i + Factor] = OpHi;
12280 ArrayRef(Ops).take_front(Factor)),
12282 ArrayRef(Ops).drop_front(Factor))};
12285 for (
unsigned i = 0; i != Factor; ++i) {
12286 unsigned IdxLo = 2 * i;
12287 unsigned IdxHi = 2 * i + 1;
12289 Res[IdxLo / Factor].getValue(IdxLo % Factor),
12290 Res[IdxHi / Factor].getValue(IdxHi % Factor));
12314 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
12315 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
12316 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
12317 Intrinsic::riscv_vsseg8_mask,
12325 for (
unsigned i = 0; i < Factor; i++)
12327 DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VecTupTy, StoredVal,
12350 for (
unsigned i = 0; i != Factor; ++i) {
12354 Loads[i] = DAG.
getLoad(VecVT,
DL, Chain, StackPtr, PtrInfo);
12362 if (Subtarget.hasVendorXRivosVizip() && !
Op.getOperand(0).isUndef() &&
12363 !
Op.getOperand(1).isUndef()) {
12383 Op.getOperand(0),
Op.getOperand(1));
12407 DAG.
getNode(RISCVISD::ADD_VL,
DL, IdxVT,
Idx, VLMax,
Idx, OddMask, VL);
12412 Interleaved = DAG.
getNode(RISCVISD::VRGATHEREI16_VV_VL,
DL, ConcatVT,
12429 MVT VT =
Op.getSimpleValueType();
12434 uint64_t StepValImm =
Op.getConstantOperandVal(0);
12435 if (StepValImm != 1) {
12444 VL, VT,
DL, DAG, Subtarget);
12459 MVT VecVT =
Op.getSimpleValueType();
12468 MVT ContainerVT = VecVT;
12522 unsigned MaxVLMAX =
12527 unsigned GatherOpc = RISCVISD::VRGATHER_VV_VL;
12532 if (MaxVLMAX > 256 && EltSize == 8) {
12546 LoVT.getVectorMinNumElements());
12551 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
12558 assert(isUInt<16>(MaxVLMAX - 1));
12559 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
12584 DAG.
getUNDEF(ContainerVT), Mask, VL);
12596 MVT VecVT =
Op.getSimpleValueType();
12600 int64_t ImmValue = cast<ConstantSDNode>(
Op.getOperand(2))->getSExtValue();
12601 SDValue DownOffset, UpOffset;
12602 if (ImmValue >= 0) {
12617 DAG, Subtarget,
DL, VecVT, DAG.
getUNDEF(VecVT), V1, DownOffset, TrueMask,
12618 Subtarget.hasVLDependentLatency() ? UpOffset
12620 return getVSlideup(DAG, Subtarget,
DL, VecVT, SlideDown, V2, UpOffset,
12626RISCVTargetLowering::lowerFixedLengthVectorLoadToRVV(
SDValue Op,
12629 auto *
Load = cast<LoadSDNode>(
Op);
12632 Load->getMemoryVT(),
12633 *
Load->getMemOperand()) &&
12634 "Expecting a correctly-aligned load");
12636 MVT VT =
Op.getSimpleValueType();
12642 const auto [MinVLMAX, MaxVLMAX] =
12659 IsMaskOp ? Intrinsic::riscv_vlm : Intrinsic::riscv_vle,
DL, XLenVT);
12662 Ops.push_back(DAG.
getUNDEF(ContainerVT));
12663 Ops.push_back(
Load->getBasePtr());
12668 Load->getMemoryVT(),
Load->getMemOperand());
12675RISCVTargetLowering::lowerFixedLengthVectorStoreToRVV(
SDValue Op,
12678 auto *
Store = cast<StoreSDNode>(
Op);
12681 Store->getMemoryVT(),
12682 *
Store->getMemOperand()) &&
12683 "Expecting a correctly-aligned store");
12703 const auto [MinVLMAX, MaxVLMAX] =
12717 IsMaskOp ? Intrinsic::riscv_vsm : Intrinsic::riscv_vse,
DL, XLenVT);
12720 {Store->getChain(), IntID, NewValue, Store->getBasePtr(), VL},
12721 Store->getMemoryVT(),
Store->getMemOperand());
12727 MVT VT =
Op.getSimpleValueType();
12729 const auto *MemSD = cast<MemSDNode>(
Op);
12730 EVT MemVT = MemSD->getMemoryVT();
12732 SDValue Chain = MemSD->getChain();
12736 bool IsExpandingLoad =
false;
12737 if (
const auto *VPLoad = dyn_cast<VPLoadSDNode>(
Op)) {
12738 Mask = VPLoad->getMask();
12740 VL = VPLoad->getVectorLength();
12742 const auto *MLoad = cast<MaskedLoadSDNode>(
Op);
12743 Mask = MLoad->getMask();
12744 PassThru = MLoad->getPassThru();
12745 IsExpandingLoad = MLoad->isExpandingLoad();
12752 MVT ContainerVT = VT;
12766 if (!IsUnmasked && IsExpandingLoad) {
12769 DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Mask,
12773 unsigned IntID = IsUnmasked || IsExpandingLoad ? Intrinsic::riscv_vle
12774 : Intrinsic::riscv_vle_mask;
12776 if (IntID == Intrinsic::riscv_vle)
12777 Ops.push_back(DAG.
getUNDEF(ContainerVT));
12779 Ops.push_back(PassThru);
12780 Ops.push_back(BasePtr);
12781 if (IntID == Intrinsic::riscv_vle_mask)
12782 Ops.push_back(Mask);
12784 if (IntID == Intrinsic::riscv_vle_mask)
12791 Chain =
Result.getValue(1);
12793 MVT IndexVT = ContainerVT;
12798 bool UseVRGATHEREI16 =
false;
12806 UseVRGATHEREI16 =
true;
12812 DAG.
getUNDEF(IndexVT), Mask, ExpandingVL);
12814 DAG.
getNode(UseVRGATHEREI16 ? RISCVISD::VRGATHEREI16_VV_VL
12815 : RISCVISD::VRGATHER_VV_VL,
12816 DL, ContainerVT, Result, Iota, PassThru, Mask, ExpandingVL);
12827 MVT VT =
Op->getSimpleValueType(0);
12829 const auto *VPLoadFF = cast<VPLoadFFSDNode>(
Op);
12830 EVT MemVT = VPLoadFF->getMemoryVT();
12832 SDValue Chain = VPLoadFF->getChain();
12836 SDValue VL = VPLoadFF->getVectorLength();
12840 MVT ContainerVT = VT;
12847 unsigned IntID = Intrinsic::riscv_vleff_mask;
12862 Chain =
Result.getValue(2);
12874 const auto *MemSD = cast<MemSDNode>(
Op);
12875 EVT MemVT = MemSD->getMemoryVT();
12877 SDValue Chain = MemSD->getChain();
12881 bool IsCompressingStore =
false;
12882 if (
const auto *VPStore = dyn_cast<VPStoreSDNode>(
Op)) {
12883 Val = VPStore->getValue();
12884 Mask = VPStore->getMask();
12885 VL = VPStore->getVectorLength();
12887 const auto *MStore = cast<MaskedStoreSDNode>(
Op);
12888 Val = MStore->getValue();
12889 Mask = MStore->getMask();
12890 IsCompressingStore = MStore->isCompressingStore();
12899 MVT ContainerVT = VT;
12904 if (!IsUnmasked || IsCompressingStore) {
12913 if (IsCompressingStore) {
12916 DAG.
getUNDEF(ContainerVT), Val, Mask, VL);
12918 DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Mask,
12923 IsUnmasked ? Intrinsic::riscv_vse : Intrinsic::riscv_vse_mask;
12925 Ops.push_back(Val);
12926 Ops.push_back(BasePtr);
12928 Ops.push_back(Mask);
12932 DAG.
getVTList(MVT::Other), Ops, MemVT, MMO);
12944 MVT ContainerVT = VT;
12957 Passthru, Val, Mask, VL);
12967 unsigned Opc =
Op.getOpcode();
12974 MVT VT =
Op.getSimpleValueType();
13007 MVT ContainerInVT = InVT;
13025 RISCVISD::STRICT_FSETCC_VL,
DL, DAG.
getVTList(MaskVT, MVT::Other),
13026 {Chain, Op1, Op1, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
13029 RISCVISD::STRICT_FSETCC_VL,
DL, DAG.
getVTList(MaskVT, MVT::Other),
13030 {Chain, Op2, Op2, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
13033 DAG.
getNode(RISCVISD::VMAND_VL,
DL, MaskVT, OrderMask1, OrderMask2, VL);
13036 Res = DAG.
getNode(RISCVISD::STRICT_FSETCCS_VL,
DL,
13038 {Chain, Op1, Op2, CC, Mask, Mask, VL});
13041 : RISCVISD::STRICT_FSETCCS_VL;
13043 {Chain, Op1, Op2, CC, DAG.getUNDEF(MaskVT), Mask, VL});
13056 MVT VT =
Op.getSimpleValueType();
13060 "Unexpected type for ISD::ABS");
13062 MVT ContainerVT = VT;
13069 if (
Op->getOpcode() == ISD::VP_ABS) {
13070 Mask =
Op->getOperand(1);
13074 VL =
Op->getOperand(2);
13079 RISCVISD::VMV_V_X_VL,
DL, ContainerVT, DAG.
getUNDEF(ContainerVT),
13082 DAG.
getUNDEF(ContainerVT), Mask, VL);
13084 DAG.
getUNDEF(ContainerVT), Mask, VL);
13093 const auto &TSInfo =
13097 bool HasPassthruOp = TSInfo.hasPassthruOp(NewOpc);
13098 bool HasMask = TSInfo.hasMaskOp(NewOpc);
13100 MVT VT =
Op.getSimpleValueType();
13105 for (
const SDValue &V :
Op->op_values()) {
13106 assert(!isa<VTSDNode>(V) &&
"Unexpected VTSDNode node!");
13109 if (!
V.getValueType().isVector()) {
13115 assert(useRVVForFixedLengthVectorVT(
V.getSimpleValueType()) &&
13116 "Only fixed length vectors are supported!");
13118 V.getSimpleValueType().getVectorElementType());
13132 if (
Op->isStrictFPOpcode()) {
13141 DAG.
getNode(NewOpc,
DL, ContainerVT, Ops,
Op->getFlags());
13151 const auto &TSInfo =
13155 bool HasPassthruOp = TSInfo.hasPassthruOp(RISCVISDOpc);
13158 MVT VT =
Op.getSimpleValueType();
13161 MVT ContainerVT = VT;
13167 assert(!isa<VTSDNode>(V) &&
"Unexpected VTSDNode node!");
13170 if (HasPassthruOp) {
13173 if (*MaskIdx ==
OpIdx.index())
13177 if (
Op.getOpcode() == ISD::VP_MERGE) {
13181 assert(
Op.getOpcode() == ISD::VP_SELECT);
13188 if (RISCVISDOpc == RISCVISD::VFCVT_RM_X_F_VL &&
13193 if (!
V.getValueType().isFixedLengthVector()) {
13198 MVT OpVT =
V.getSimpleValueType();
13200 assert(useRVVForFixedLengthVectorVT(OpVT) &&
13201 "Only fixed length vectors are supported!");
13206 return DAG.
getNode(RISCVISDOpc,
DL, VT, Ops,
Op->getFlags());
13216 MVT VT =
Op.getSimpleValueType();
13222 MVT ContainerVT = VT;
13232 DAG.
getUNDEF(ContainerVT), Zero, VL);
13235 Op.getOpcode() == ISD::VP_ZERO_EXTEND ? 1 : -1,
DL, XLenVT);
13237 DAG.
getUNDEF(ContainerVT), SplatValue, VL);
13240 ZeroSplat, DAG.
getUNDEF(ContainerVT), VL);
13249 MVT VT =
Op.getSimpleValueType();
13253 ISD::CondCode Condition = cast<CondCodeSDNode>(
Op.getOperand(2))->get();
13257 MVT ContainerVT = VT;
13265 SDValue AllOneMask = DAG.
getNode(RISCVISD::VMSET_VL,
DL, ContainerVT, VL);
13267 switch (Condition) {
13272 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, Op2, VL);
13277 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, Op2, VL);
13279 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, AllOneMask, VL);
13287 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, AllOneMask, VL);
13288 Result = DAG.
getNode(RISCVISD::VMAND_VL,
DL, ContainerVT, Temp, Op2, VL);
13296 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op2, AllOneMask, VL);
13297 Result = DAG.
getNode(RISCVISD::VMAND_VL,
DL, ContainerVT, Op1, Temp, VL);
13305 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, AllOneMask, VL);
13306 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, Op2, VL);
13314 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op2, AllOneMask, VL);
13315 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, Op1, VL);
13335 MVT DstVT =
Op.getSimpleValueType();
13336 MVT SrcVT = Src.getSimpleValueType();
13349 if (DstEltSize >= SrcEltSize) {
13353 unsigned RISCVISDExtOpc = RISCVISDOpc == RISCVISD::SINT_TO_FP_VL
13354 ? RISCVISD::VSEXT_VL
13355 : RISCVISD::VZEXT_VL;
13358 if (SrcEltSize == 1) {
13365 RISCVISDExtOpc == RISCVISD::VZEXT_VL ? 1 : -1,
DL, XLenVT);
13368 Src = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, IntVT, Src, OneSplat,
13369 ZeroSplat, DAG.
getUNDEF(IntVT), VL);
13370 }
else if (DstEltSize > (2 * SrcEltSize)) {
13374 Src = DAG.
getNode(RISCVISDExtOpc,
DL, IntVT, Src, Mask, VL);
13380 "Wrong input/output vector types");
13383 if (DstEltSize > (2 * SrcEltSize)) {
13388 DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, InterimFVT, Src, Mask, VL);
13399 MVT InterimFVT = DstVT;
13400 if (SrcEltSize > (2 * DstEltSize)) {
13401 assert(SrcEltSize == (4 * DstEltSize) &&
"Unexpected types!");
13408 if (InterimFVT != DstVT) {
13410 Result = DAG.
getNode(RISCVISD::FP_ROUND_VL,
DL, DstVT, Src, Mask, VL);
13414 "Wrong input/output vector types");
13418 if (DstEltSize == 1) {
13421 assert(SrcEltSize >= 16 &&
"Unexpected FP type!");
13430 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, InterimIVT,
13431 DAG.
getUNDEF(InterimIVT), SplatZero, VL);
13441 while (InterimIVT != DstVT) {
13453 MVT VT =
Op.getSimpleValueType();
13462 MVT VT =
Op.getSimpleValueType();
13476 MVT ContainerVT = VT;
13496 TrueVal = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, PromotedVT, TrueVal, SplatOne,
13497 SplatZero, DAG.
getUNDEF(PromotedVT), VL);
13500 SplatOne, SplatZero, DAG.
getUNDEF(PromotedVT), VLMax);
13504 TrueVal, FalseVal, FalseVal, VL);
13509 RISCVISD::SETCC_VL,
DL, ContainerVT,
13519RISCVTargetLowering::lowerVPSpliceExperimental(
SDValue Op,
13521 using namespace SDPatternMatch;
13533 MVT VT =
Op.getSimpleValueType();
13534 MVT ContainerVT = VT;
13544 if (IsMaskVector) {
13554 Op1 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, Op1, SplatOneOp1,
13555 SplatZeroOp1, DAG.
getUNDEF(ContainerVT), EVL1);
13563 Op2 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, Op2, SplatOneOp2,
13564 SplatZeroOp2, DAG.
getUNDEF(ContainerVT), EVL2);
13567 auto getVectorFirstEle = [](
SDValue Vec) {
13580 if (
auto FirstEle = getVectorFirstEle(
Op->getOperand(0))) {
13584 EltVT == MVT::bf16) {
13592 : RISCVISD::VSLIDE1UP_VL,
13593 DL, ContainerVT, DAG.
getUNDEF(ContainerVT), Op2,
13594 FirstEle, Mask, EVL2);
13603 int64_t ImmValue = cast<ConstantSDNode>(
Offset)->getSExtValue();
13604 SDValue DownOffset, UpOffset;
13605 if (ImmValue >= 0) {
13619 DAG.
getUNDEF(ContainerVT), Op1, DownOffset, Mask,
13620 Subtarget.hasVLDependentLatency() ? UpOffset : EVL2);
13624 if (IsMaskVector) {
13628 {Result, DAG.getConstant(0, DL, ContainerVT),
13629 DAG.getCondCode(ISD::SETNE), DAG.getUNDEF(getMaskTypeFor(ContainerVT)),
13644 MVT VT =
Op.getSimpleValueType();
13646 MVT ContainerVT = VT;
13655 if (
auto *
C = dyn_cast<ConstantSDNode>(Val)) {
13657 DAG.
getNode(
C->isZero() ? RISCVISD::VMCLR_VL : RISCVISD::VMSET_VL,
DL,
13667 DAG.
getUNDEF(ContainerVT), Mask, VL});
13680RISCVTargetLowering::lowerVPReverseExperimental(
SDValue Op,
13683 MVT VT =
Op.getSimpleValueType();
13690 MVT ContainerVT = VT;
13698 MVT GatherVT = ContainerVT;
13702 if (IsMaskVector) {
13712 Op1 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, IndicesVT, Op1, SplatOne,
13713 SplatZero, DAG.
getUNDEF(IndicesVT), EVL);
13719 unsigned MaxVLMAX =
13722 unsigned GatherOpc = RISCVISD::VRGATHER_VV_VL;
13728 if (MaxVLMAX > 256 && EltSize == 8) {
13756 DAG.
getUNDEF(GatherVT), Result, Diff, Mask, EVL);
13758 if (IsMaskVector) {
13761 DAG.
getNode(RISCVISD::SETCC_VL,
DL, ContainerVT,
13774 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
13781 DAG.
getUNDEF(IndicesVT), VecLen, EVL);
13782 SDValue VRSUB = DAG.
getNode(RISCVISD::SUB_VL,
DL, IndicesVT, VecLenSplat, VID,
13783 DAG.
getUNDEF(IndicesVT), Mask, EVL);
13785 DAG.
getUNDEF(GatherVT), Mask, EVL);
13787 if (IsMaskVector) {
13790 RISCVISD::SETCC_VL,
DL, ContainerVT,
13802 MVT VT =
Op.getSimpleValueType();
13804 return lowerVPOp(
Op, DAG);
13811 MVT ContainerVT = VT;
13830 MVT VT =
Op.getSimpleValueType();
13831 MVT ContainerVT = VT;
13837 auto *VPNode = cast<VPStridedLoadSDNode>(
Op);
13843 : Intrinsic::riscv_vlse_mask,
13846 DAG.
getUNDEF(ContainerVT), VPNode->getBasePtr(),
13847 VPNode->getStride()};
13855 Ops.
push_back(VPNode->getVectorLength());
13864 VPNode->getMemoryVT(), VPNode->getMemOperand());
13878 auto *VPNode = cast<VPStridedStoreSDNode>(
Op);
13879 SDValue StoreVal = VPNode->getValue();
13881 MVT ContainerVT = VT;
13892 : Intrinsic::riscv_vsse_mask,
13895 VPNode->getBasePtr(), VPNode->getStride()};
13903 Ops.
push_back(VPNode->getVectorLength());
13906 Ops, VPNode->getMemoryVT(),
13907 VPNode->getMemOperand());
13919 MVT VT =
Op.getSimpleValueType();
13921 const auto *MemSD = cast<MemSDNode>(
Op.getNode());
13922 EVT MemVT = MemSD->getMemoryVT();
13924 SDValue Chain = MemSD->getChain();
13930 if (
auto *VPGN = dyn_cast<VPGatherSDNode>(
Op.getNode())) {
13931 Index = VPGN->getIndex();
13932 Mask = VPGN->getMask();
13934 VL = VPGN->getVectorLength();
13939 auto *MGN = cast<MaskedGatherSDNode>(
Op.getNode());
13940 Index = MGN->getIndex();
13941 Mask = MGN->getMask();
13942 PassThru = MGN->getPassThru();
13946 MVT IndexVT =
Index.getSimpleValueType();
13950 "Unexpected VTs!");
13951 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
13954 "Unexpected extending MGATHER/VP_GATHER");
13960 MVT ContainerVT = VT;
13984 IsUnmasked ? Intrinsic::riscv_vluxei : Intrinsic::riscv_vluxei_mask;
14001 Chain =
Result.getValue(1);
14018 const auto *MemSD = cast<MemSDNode>(
Op.getNode());
14019 EVT MemVT = MemSD->getMemoryVT();
14021 SDValue Chain = MemSD->getChain();
14024 [[maybe_unused]]
bool IsTruncatingStore =
false;
14027 if (
auto *VPSN = dyn_cast<VPScatterSDNode>(
Op.getNode())) {
14028 Index = VPSN->getIndex();
14029 Mask = VPSN->getMask();
14030 Val = VPSN->getValue();
14031 VL = VPSN->getVectorLength();
14033 IsTruncatingStore =
false;
14036 auto *MSN = cast<MaskedScatterSDNode>(
Op.getNode());
14037 Index = MSN->getIndex();
14038 Mask = MSN->getMask();
14039 Val = MSN->getValue();
14040 IsTruncatingStore = MSN->isTruncatingStore();
14044 MVT IndexVT =
Index.getSimpleValueType();
14048 "Unexpected VTs!");
14049 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
14052 assert(!IsTruncatingStore &&
"Unexpected truncating MSCATTER/VP_SCATTER");
14058 MVT ContainerVT = VT;
14082 IsUnmasked ? Intrinsic::riscv_vsoxei : Intrinsic::riscv_vsoxei_mask;
14092 DAG.
getVTList(MVT::Other), Ops, MemVT, MMO);
14108 static const int Table =
14137 static const unsigned Table =
14152 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14163 return DAG.
getNode(RISCVISD::READ_CSR,
DL, VTs, Chain, SysRegNo);
14175 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14187 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14201 SDValue Result = DAG.
getNode(RISCVISD::READ_CSR,
DL, VTs, Chain, SysRegNo);
14202 Chain = Result.getValue(1);
14218 Chain = DAG.
getNode(RISCVISD::CLEAR_CSR,
DL, MVT::Other, Chain, SysRegNo,
14220 return DAG.
getNode(RISCVISD::SET_CSR,
DL, MVT::Other, Chain, SysRegNo,
14233 return DAG.
getNode(RISCVISD::CLEAR_CSR,
DL, MVT::Other, Chain, SysRegNo,
14241 bool isRISCV64 = Subtarget.
is64Bit();
14255 return RISCVISD::SLLW;
14257 return RISCVISD::SRAW;
14259 return RISCVISD::SRLW;
14261 return RISCVISD::DIVW;
14263 return RISCVISD::DIVUW;
14265 return RISCVISD::REMUW;
14267 return RISCVISD::ROLW;
14269 return RISCVISD::RORW;
14305 switch (
N->getOpcode()) {
14307 llvm_unreachable(
"Don't know how to custom type legalize this operation!");
14313 "Unexpected custom legalisation");
14314 bool IsStrict =
N->isStrictFPOpcode();
14317 SDValue Op0 = IsStrict ?
N->getOperand(1) :
N->getOperand(0);
14331 unsigned Opc = IsSigned ? RISCVISD::STRICT_FCVT_W_RV64
14332 : RISCVISD::STRICT_FCVT_WU_RV64;
14335 Opc,
DL, VTs, Chain, Op0,
14348 unsigned Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
14369 std::tie(Result, Chain) =
14370 makeLibCall(DAG, LC,
N->getValueType(0), Op0, CallOptions,
DL, Chain);
14389 DAG.
getNode(RISCVISD::FCVT_W_RV64,
DL, MVT::i64, Op0,
14397 RTLIB::Libcall LC =
14398 Op0.
getValueType() == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
14409 assert(!Subtarget.
is64Bit() &&
"READCYCLECOUNTER/READSTEADYCOUNTER only "
14410 "has custom type legalization on riscv32");
14412 SDValue LoCounter, HiCounter;
14423 N->getOperand(0), LoCounter, HiCounter);
14438 if (
N->getValueType(0) == MVT::i64) {
14439 assert(Subtarget.hasStdExtZilsd() && !Subtarget.
is64Bit() &&
14440 "Unexpected custom legalisation");
14442 if (!Subtarget.enableUnalignedScalarMem() && Ld->
getAlign() < 8)
14447 RISCVISD::LD_RV32,
DL,
14448 DAG.
getVTList({MVT::i32, MVT::i32, MVT::Other}),
14449 {Ld->getChain(), Ld->getBasePtr()}, MVT::i64, Ld->
getMemOperand());
14453 Results.append({Pair, Result.getValue(2)});
14458 "Unexpected custom legalisation");
14469 unsigned Size =
N->getSimpleValueType(0).getSizeInBits();
14470 unsigned XLen = Subtarget.
getXLen();
14473 assert(
Size == (XLen * 2) &&
"Unexpected custom legalisation");
14481 if (LHSIsU == RHSIsU)
14498 if (RHSIsU && LHSIsS && !RHSIsS)
14500 else if (LHSIsU && RHSIsS && !LHSIsS)
14510 "Unexpected custom legalisation");
14517 "Unexpected custom legalisation");
14520 if (
N->getOpcode() ==
ISD::SHL && Subtarget.hasStdExtZbs() &&
14546 "Unexpected custom legalisation");
14547 assert((Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb() ||
14548 Subtarget.hasVendorXTHeadBb()) &&
14549 "Unexpected custom legalization");
14550 if (!isa<ConstantSDNode>(
N->getOperand(1)) &&
14551 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()))
14560 "Unexpected custom legalisation");
14566 unsigned Opc = IsCTZ ? RISCVISD::CTZW : RISCVISD::CLZW;
14574 MVT VT =
N->getSimpleValueType(0);
14575 assert((VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32) &&
14576 Subtarget.
is64Bit() && Subtarget.hasStdExtM() &&
14577 "Unexpected custom legalisation");
14589 if (VT != MVT::i32)
14598 "Unexpected custom legalisation");
14602 if (!isa<ConstantSDNode>(
N->getOperand(1)))
14619 EVT OType =
N->getValueType(1);
14632 "Unexpected custom legalisation");
14649 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1), Res,
14653 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1),
N->getOperand(0),
14671 !Subtarget.hasStdExtZbb() &&
"Unexpected custom legalisation");
14680 "Unexpected custom legalisation");
14686 "Unexpected custom legalisation");
14688 if (Subtarget.hasStdExtZbb()) {
14722 EVT VT =
N->getValueType(0);
14727 if (VT == MVT::i16 &&
14729 (Op0VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
14732 }
else if (VT == MVT::i32 && Op0VT == MVT::f32 && Subtarget.
is64Bit() &&
14735 DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Op0);
14737 }
else if (VT == MVT::i64 && Op0VT == MVT::f64 && !Subtarget.
is64Bit() &&
14740 DAG.
getVTList(MVT::i32, MVT::i32), Op0);
14759 assert(
N->getValueType(0) == MVT::i8 && Subtarget.hasStdExtZbkb() &&
14760 "Unexpected custom legalisation");
14769 case RISCVISD::BREV8:
14770 case RISCVISD::ORC_B: {
14771 MVT VT =
N->getSimpleValueType(0);
14773 assert((VT == MVT::i16 || (VT == MVT::i32 && Subtarget.
is64Bit())) &&
14774 "Unexpected custom legalisation");
14775 assert(((
N->getOpcode() == RISCVISD::BREV8 && Subtarget.hasStdExtZbkb()) ||
14776 (
N->getOpcode() == RISCVISD::ORC_B && Subtarget.hasStdExtZbb())) &&
14777 "Unexpected extension");
14803 assert(!Subtarget.
is64Bit() &&
N->getValueType(0) == MVT::i64 &&
14805 "Unexpected EXTRACT_VECTOR_ELT legalization");
14808 MVT ContainerVT = VecVT;
14835 DAG.
getNode(RISCVISD::SRL_VL,
DL, ContainerVT, Vec, ThirtyTwoV,
14836 DAG.
getUNDEF(ContainerVT), Mask, VL);
14844 unsigned IntNo =
N->getConstantOperandVal(0);
14848 "Don't know how to custom type legalize this intrinsic!");
14849 case Intrinsic::experimental_get_vector_length: {
14854 case Intrinsic::experimental_cttz_elts: {
14860 case Intrinsic::riscv_orc_b:
14861 case Intrinsic::riscv_brev8:
14862 case Intrinsic::riscv_sha256sig0:
14863 case Intrinsic::riscv_sha256sig1:
14864 case Intrinsic::riscv_sha256sum0:
14865 case Intrinsic::riscv_sha256sum1:
14866 case Intrinsic::riscv_sm3p0:
14867 case Intrinsic::riscv_sm3p1: {
14868 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
14872 case Intrinsic::riscv_orc_b:
Opc = RISCVISD::ORC_B;
break;
14873 case Intrinsic::riscv_brev8:
Opc = RISCVISD::BREV8;
break;
14874 case Intrinsic::riscv_sha256sig0:
Opc = RISCVISD::SHA256SIG0;
break;
14875 case Intrinsic::riscv_sha256sig1:
Opc = RISCVISD::SHA256SIG1;
break;
14876 case Intrinsic::riscv_sha256sum0:
Opc = RISCVISD::SHA256SUM0;
break;
14877 case Intrinsic::riscv_sha256sum1:
Opc = RISCVISD::SHA256SUM1;
break;
14878 case Intrinsic::riscv_sm3p0:
Opc = RISCVISD::SM3P0;
break;
14879 case Intrinsic::riscv_sm3p1:
Opc = RISCVISD::SM3P1;
break;
14888 case Intrinsic::riscv_sm4ks:
14889 case Intrinsic::riscv_sm4ed: {
14891 IntNo == Intrinsic::riscv_sm4ks ? RISCVISD::SM4KS : RISCVISD::SM4ED;
14897 DAG.
getNode(
Opc,
DL, MVT::i64, NewOp0, NewOp1,
N->getOperand(3));
14901 case Intrinsic::riscv_mopr: {
14902 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
14907 RISCVISD::MOP_R,
DL, MVT::i64, NewOp,
14912 case Intrinsic::riscv_moprr: {
14913 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
14920 RISCVISD::MOP_RR,
DL, MVT::i64, NewOp0, NewOp1,
14925 case Intrinsic::riscv_clmul: {
14926 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
14937 case Intrinsic::riscv_clmulh:
14938 case Intrinsic::riscv_clmulr: {
14939 if (!Subtarget.
is64Bit() ||
N->getValueType(0) != MVT::i32)
14959 unsigned Opc = IntNo == Intrinsic::riscv_clmulh ? RISCVISD::CLMULH
14960 : RISCVISD::CLMULR;
14967 case Intrinsic::riscv_vmv_x_s: {
14968 EVT VT =
N->getValueType(0);
14970 if (VT.
bitsLT(XLenVT)) {
14979 "Unexpected custom legalization");
14995 SDValue LShr32 = DAG.
getNode(RISCVISD::SRL_VL,
DL, VecVT, Vec, ThirtyTwoV,
15017 case ISD::VP_REDUCE_ADD:
15018 case ISD::VP_REDUCE_AND:
15019 case ISD::VP_REDUCE_OR:
15020 case ISD::VP_REDUCE_XOR:
15021 case ISD::VP_REDUCE_SMAX:
15022 case ISD::VP_REDUCE_UMAX:
15023 case ISD::VP_REDUCE_SMIN:
15024 case ISD::VP_REDUCE_UMIN:
15088 const EVT VT =
N->getValueType(0);
15089 const unsigned Opc =
N->getOpcode();
15096 (
Opc !=
ISD::FADD || !
N->getFlags().hasAllowReassociation()))
15101 "Inconsistent mappings");
15112 !isa<ConstantSDNode>(
RHS.getOperand(1)))
15115 uint64_t RHSIdx = cast<ConstantSDNode>(
RHS.getOperand(1))->getLimitedValue();
15130 LHS.getOperand(0) == SrcVec && isa<ConstantSDNode>(
LHS.getOperand(1))) {
15132 cast<ConstantSDNode>(
LHS.getOperand(1))->getLimitedValue();
15133 if (0 == std::min(LHSIdx, RHSIdx) && 1 == std::max(LHSIdx, RHSIdx)) {
15136 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
N->getFlags());
15143 if (
LHS.getOpcode() != ReduceOpc)
15157 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
15158 ReduceVec->
getFlags() &
N->getFlags());
15168 auto BinOpToRVVReduce = [](
unsigned Opc) {
15173 return RISCVISD::VECREDUCE_ADD_VL;
15175 return RISCVISD::VECREDUCE_UMAX_VL;
15177 return RISCVISD::VECREDUCE_SMAX_VL;
15179 return RISCVISD::VECREDUCE_UMIN_VL;
15181 return RISCVISD::VECREDUCE_SMIN_VL;
15183 return RISCVISD::VECREDUCE_AND_VL;
15185 return RISCVISD::VECREDUCE_OR_VL;
15187 return RISCVISD::VECREDUCE_XOR_VL;
15189 return RISCVISD::VECREDUCE_FADD_VL;
15191 return RISCVISD::VECREDUCE_FMAX_VL;
15193 return RISCVISD::VECREDUCE_FMIN_VL;
15197 auto IsReduction = [&BinOpToRVVReduce](
SDValue V,
unsigned Opc) {
15200 V.getOperand(0).getOpcode() == BinOpToRVVReduce(
Opc);
15203 unsigned Opc =
N->getOpcode();
15204 unsigned ReduceIdx;
15205 if (IsReduction(
N->getOperand(0),
Opc))
15207 else if (IsReduction(
N->getOperand(1),
Opc))
15213 if (
Opc ==
ISD::FADD && !
N->getFlags().hasAllowReassociation())
15216 SDValue Extract =
N->getOperand(ReduceIdx);
15229 if (ScalarV.
getOpcode() != RISCVISD::VFMV_S_F_VL &&
15230 ScalarV.
getOpcode() != RISCVISD::VMV_S_X_VL &&
15231 ScalarV.
getOpcode() != RISCVISD::VMV_V_X_VL)
15248 SDValue NewStart =
N->getOperand(1 - ReduceIdx);
15275 const bool HasStdExtZba = Subtarget.hasStdExtZba();
15276 const bool HasVendorXAndesPerf = Subtarget.hasVendorXAndesPerf();
15277 const bool HasVendorXqciac = Subtarget.hasVendorXqciac();
15279 if (!HasStdExtZba && !HasVendorXAndesPerf && !HasVendorXqciac)
15283 EVT VT =
N->getValueType(0);
15295 auto *N0C = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
15296 auto *N1C = dyn_cast<ConstantSDNode>(N1->
getOperand(1));
15299 int64_t C0 = N0C->getSExtValue();
15300 int64_t C1 = N1C->getSExtValue();
15301 if (C0 <= 0 || C1 <= 0)
15304 int64_t Diff = std::abs(C0 - C1);
15305 bool IsShXaddDiff = Diff == 1 || Diff == 2 || Diff == 3;
15306 bool HasShXadd = HasStdExtZba || HasVendorXAndesPerf;
15309 if ((!IsShXaddDiff && HasShXadd && !HasVendorXqciac) ||
15310 (IsShXaddDiff && !HasShXadd && HasVendorXqciac))
15314 if (Diff == 0 || Diff > 31)
15319 int64_t Bits = std::min(C0, C1);
15334 if (isa<ConstantSDNode>(
N->getOperand(1)))
15344 if (!sd_match(AddI,
m_Add(
m_Value(SHLVal), m_ConstInt(AddVal))))
15351 if (VShift.
slt(1) || VShift.
sgt(3))
15355 EVT VT =
N->getValueType(0);
15375 EVT VT =
N->getValueType(0);
15403 EVT VT =
N->getValueType(0);
15411 if ((!Subtarget.hasStdExtZicond() &&
15412 !Subtarget.hasVendorXVentanaCondOps()) ||
15426 Slct.
getOpcode() != RISCVISD::SELECT_CC) ||
15434 bool SwapSelectOps;
15435 unsigned OpOffset = Slct.
getOpcode() == RISCVISD::SELECT_CC ? 2 : 0;
15440 SwapSelectOps =
false;
15441 NonConstantVal = FalseVal;
15443 SwapSelectOps =
true;
15444 NonConstantVal = TrueVal;
15450 FalseVal = DAG.
getNode(
N->getOpcode(),
SDLoc(
N), VT, OtherOp, NonConstantVal);
15455 if (Slct.
getOpcode() == RISCVISD::SELECT_CC)
15498 EVT VT =
N->getValueType(0);
15506 auto *N0C = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
15507 auto *N1C = dyn_cast<ConstantSDNode>(
N->getOperand(1));
15513 if (!N0C->hasOneUse())
15515 int64_t C0 = N0C->getSExtValue();
15516 int64_t C1 = N1C->getSExtValue();
15518 if (C0 == -1 || C0 == 0 || C0 == 1 || isInt<12>(C1))
15521 if ((C1 / C0) != 0 && isInt<12>(C1 / C0) && isInt<12>(C1 % C0) &&
15522 !isInt<12>(C0 * (C1 / C0))) {
15525 }
else if ((C1 / C0 + 1) != 0 && isInt<12>(C1 / C0 + 1) &&
15526 isInt<12>(C1 % C0 - C0) && !isInt<12>(C0 * (C1 / C0 + 1))) {
15529 }
else if ((C1 / C0 - 1) != 0 && isInt<12>(C1 / C0 - 1) &&
15530 isInt<12>(C1 % C0 + C0) && !isInt<12>(C0 * (C1 / C0 - 1))) {
15557 EVT VT =
N->getValueType(0);
15588 unsigned OuterExtend =
15592 OuterExtend,
SDLoc(
N), VT,
15600 EVT VT =
N->getValueType(0);
15651 EVT VT =
N->getValueType(0);
15655 auto *N0C = dyn_cast<ConstantSDNode>(N0);
15661 APInt ImmValMinus1 = N0C->getAPIntValue() - 1;
15671 if (!isIntEqualitySetCC(CCVal) || !SetCCOpVT.
isInteger())
15694 if (!Subtarget.hasStdExtZbb())
15697 EVT VT =
N->getValueType(0);
15699 if (VT != Subtarget.
getXLenVT() && VT != MVT::i32 && VT != MVT::i16)
15708 auto *ShAmtCLeft = dyn_cast<ConstantSDNode>(N0.
getOperand(1));
15711 unsigned ShiftedAmount = 8 - ShAmtCLeft->getZExtValue();
15713 if (ShiftedAmount >= 8)
15717 SDValue RightShiftOperand = N1;
15719 if (ShiftedAmount != 0) {
15722 auto *ShAmtCRight = dyn_cast<ConstantSDNode>(N1.
getOperand(1));
15723 if (!ShAmtCRight || ShAmtCRight->getZExtValue() != ShiftedAmount)
15732 if (LeftShiftOperand != RightShiftOperand)
15736 Mask <<= ShiftedAmount;
15742 return DAG.
getNode(RISCVISD::ORC_B,
SDLoc(
N), VT, LeftShiftOperand);
15750 EVT VT =
N->getValueType(0);
15781 bool IsAnd =
N->getOpcode() ==
ISD::AND;
15805 EVT VT =
N->getValueType(0);
15829 EVT VT =
N->getValueType(0);
15856 if (CondLHS != True)
15863 if (!CondRHSC || CondRHSC->
getAPIntValue() != (1ULL << ScalarBits))
15875 if (!FalseRHSC || !FalseRHSC->
isZero())
15895 EVT VT =
N->getValueType(0);
15902 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() && VT == MVT::i1 &&
15939 using namespace SDPatternMatch;
15945 EVT VT =
N->getValueType(0);
15964 EVT WideVT =
X.getValueType();
15996 ConstantSDNode *MaskConst = dyn_cast<ConstantSDNode>(
N->getOperand(1));
16001 if (Mask != ExpectedMask)
16027 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
16065 if (N0.
getOpcode() != RISCVISD::CZERO_EQZ ||
16066 N1.
getOpcode() != RISCVISD::CZERO_NEZ ||
16084 EVT VT =
N->getValueType(0);
16131 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
16146 if (N0.
getOpcode() == RISCVISD::SLLW &&
16150 return DAG.
getNode(RISCVISD::ROLW,
DL, MVT::i64,
16156 auto *ConstN00 = dyn_cast<ConstantSDNode>(N0.
getOperand(0));
16161 const APInt &Imm = ConstN00->getAPIntValue();
16162 if ((Imm + 1).isSignedIntN(12))
16183 EVT VT =
N->getValueType(0);
16190 for (
uint64_t E = MulAmt,
I = 0; E && I < BitWidth; ++I, E >>= 1) {
16192 bool IsAdd = (E & 3) == 1;
16193 E -= IsAdd ? 1 : -1;
16197 Result = DAG.
getNode(AddSubOp,
DL, VT, Result, ShiftVal);
16207 uint64_t MulAmtLowBit = MulAmt & (-MulAmt);
16212 ShiftAmt1 = MulAmt + MulAmtLowBit;
16215 ShiftAmt1 = MulAmt - MulAmtLowBit;
16219 EVT VT =
N->getValueType(0);
16233 EVT VT =
N->getValueType(0);
16242 bool ShouldExpandMul =
16244 !Subtarget.hasStdExtZmmul();
16245 if (!ShouldExpandMul)
16254 if (Subtarget.hasVendorXqciac() && isInt<12>(CNode->
getSExtValue()))
16257 const bool HasShlAdd = Subtarget.hasStdExtZba() ||
16258 Subtarget.hasVendorXTHeadBa() ||
16259 Subtarget.hasVendorXAndesPerf();
16268 for (
uint64_t Divisor : {3, 5, 9}) {
16269 if (MulAmt % Divisor != 0)
16271 uint64_t MulAmt2 = MulAmt / Divisor;
16278 if (
X.getOpcode() ==
ISD::AND && isa<ConstantSDNode>(
X.getOperand(1)) &&
16279 X.getConstantOperandVal(1) == UINT64_C(0xffffffff)) {
16282 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, Shl,
16296 if (MulAmt2 == 3 || MulAmt2 == 5 || MulAmt2 == 9) {
16301 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, Mul359,
16312 if (ScaleShift >= 1 && ScaleShift < 4) {
16313 unsigned ShiftAmt =
Log2_64((MulAmt & (MulAmt - 1)));
16317 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT,
X,
16327 for (
uint64_t Divisor : {3, 5, 9}) {
16332 if ((
C >> TZ) == Divisor && (TZ == 1 || TZ == 2 || TZ == 3)) {
16337 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, Mul359,
16343 if (MulAmt > 2 &&
isPowerOf2_64((MulAmt - 1) & (MulAmt - 2))) {
16345 if (ScaleShift >= 1 && ScaleShift < 4) {
16346 unsigned ShiftAmt =
Log2_64(((MulAmt - 1) & (MulAmt - 2)));
16372 for (
uint64_t Divisor : {3, 5, 9}) {
16373 if (MulAmt % Divisor != 0)
16375 uint64_t MulAmt2 = MulAmt / Divisor;
16378 for (
uint64_t Divisor2 : {3, 5, 9}) {
16379 if (MulAmt2 % Divisor2 != 0)
16381 uint64_t MulAmt3 = MulAmt2 / Divisor2;
16388 RISCVISD::SHL_ADD,
DL, VT, Mul359A,
16400 if (!Subtarget.hasStdExtZmmul())
16410 EVT VT =
N->getValueType(0);
16417 if (
N->getOperand(0).getOpcode() !=
ISD::AND ||
16418 N->getOperand(0).getOperand(0).getOpcode() !=
ISD::SRL)
16431 if (!V1.
isMask(HalfSize) || V2 != (1ULL | 1ULL << HalfSize) ||
16432 V3 != (HalfSize - 1))
16448 EVT VT =
N->getValueType(0);
16456 unsigned AddSubOpc;
16462 auto IsAddSubWith1 = [&](
SDValue V) ->
bool {
16463 AddSubOpc = V->getOpcode();
16465 SDValue Opnd = V->getOperand(1);
16466 MulOper = V->getOperand(0);
16475 if (IsAddSubWith1(N0)) {
16477 return DAG.
getNode(AddSubOpc,
DL, VT, N1, MulVal);
16480 if (IsAddSubWith1(N1)) {
16482 return DAG.
getNode(AddSubOpc,
DL, VT, N0, MulVal);
16497 if (isIndexTypeSigned(IndexType))
16500 if (!
N->hasOneUse())
16503 EVT VT =
N.getValueType();
16542 EVT SrcVT = Src.getValueType();
16546 NewElen = std::max(NewElen, 8U);
16573 EVT OpVT =
X.getValueType();
16581 if (OpSize <= Subtarget.
getXLen() ||
16587 auto IsVectorBitCastCheap = [](
SDValue X) {
16589 return isa<ConstantSDNode>(
X) ||
X.getValueType().isVector() ||
16592 if (!IsVectorBitCastCheap(
X) || !IsVectorBitCastCheap(
Y))
16596 Attribute::NoImplicitFloat))
16603 unsigned VecSize = OpSize / 8;
16615 DAG.
getNode(ISD::VP_REDUCE_OR,
DL, XLenVT,
16632 EVT VT =
N->getValueType(0);
16637 if (!isIntEqualitySetCC(
Cond))
16648 const APInt &AndRHSC =
16649 cast<ConstantSDNode>(N0.
getOperand(1))->getAPIntValue();
16658 if (OpVT != MVT::i64 || !Subtarget.
is64Bit())
16662 auto *N1C = dyn_cast<ConstantSDNode>(N1);
16678 const APInt &C1 = N1C->getAPIntValue();
16696 EVT VT =
N->getValueType(0);
16697 EVT SrcVT = cast<VTSDNode>(
N->getOperand(1))->
getVT();
16698 unsigned Opc = Src.getOpcode();
16703 if (
Opc == RISCVISD::FMV_X_ANYEXTH && SrcVT.
bitsGE(MVT::i16) &&
16704 Subtarget.hasStdExtZfhmin())
16705 return DAG.
getNode(RISCVISD::FMV_X_SIGNEXTH,
DL, VT, Src.getOperand(0));
16709 VT == MVT::i64 && !isa<ConstantSDNode>(Src.getOperand(1)) &&
16711 return DAG.
getNode(RISCVISD::SLLW,
DL, VT, Src.getOperand(0),
16712 Src.getOperand(1));
16731struct CombineResult;
16765struct NodeExtensionHelper {
16774 bool SupportsFPExt;
16776 bool SupportsBF16Ext;
16779 bool EnforceOneUse;
16789 case RISCVISD::VSEXT_VL:
16790 case RISCVISD::VZEXT_VL:
16791 case RISCVISD::FP_EXTEND_VL:
16794 return OrigOperand;
16800 return OrigOperand.
getOpcode() == RISCVISD::VMV_V_X_VL ||
16805 unsigned getExtOpc(ExtKind SupportsExt)
const {
16806 switch (SupportsExt) {
16807 case ExtKind::SExt:
16808 return RISCVISD::VSEXT_VL;
16809 case ExtKind::ZExt:
16810 return RISCVISD::VZEXT_VL;
16811 case ExtKind::FPExt:
16812 case ExtKind::BF16Ext:
16813 return RISCVISD::FP_EXTEND_VL;
16823 std::optional<ExtKind> SupportsExt)
const {
16824 if (!SupportsExt.has_value())
16825 return OrigOperand;
16827 MVT NarrowVT = getNarrowType(Root, *SupportsExt);
16831 if (
Source.getValueType() == NarrowVT)
16834 unsigned ExtOpc = getExtOpc(*SupportsExt);
16838 auto [
Mask, VL] = getMaskAndVL(Root, DAG, Subtarget);
16842 case RISCVISD::VSEXT_VL:
16843 case RISCVISD::VZEXT_VL:
16844 case RISCVISD::FP_EXTEND_VL:
16845 return DAG.
getNode(ExtOpc,
DL, NarrowVT, Source, Mask, VL);
16848 case RISCVISD::VMV_V_X_VL:
16849 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, NarrowVT,
16851 case RISCVISD::VFMV_V_F_VL:
16856 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL, NarrowVT,
16857 DAG.
getUNDEF(NarrowVT), Source, VL);
16870 static MVT getNarrowType(
const SDNode *Root, ExtKind SupportsExt) {
16876 MVT EltVT = SupportsExt == ExtKind::BF16Ext ? MVT::bf16
16877 : SupportsExt == ExtKind::FPExt
16879 :
MVT::getIntegerVT(NarrowSize);
16881 assert((
int)NarrowSize >= (SupportsExt == ExtKind::FPExt ? 16 : 8) &&
16882 "Trying to extend something we can't represent");
16889 static unsigned getSExtOpcode(
unsigned Opcode) {
16892 case RISCVISD::ADD_VL:
16893 case RISCVISD::VWADD_W_VL:
16894 case RISCVISD::VWADDU_W_VL:
16896 case RISCVISD::OR_VL:
16897 return RISCVISD::VWADD_VL;
16899 case RISCVISD::SUB_VL:
16900 case RISCVISD::VWSUB_W_VL:
16901 case RISCVISD::VWSUBU_W_VL:
16902 return RISCVISD::VWSUB_VL;
16904 case RISCVISD::MUL_VL:
16905 return RISCVISD::VWMUL_VL;
16913 static unsigned getZExtOpcode(
unsigned Opcode) {
16916 case RISCVISD::ADD_VL:
16917 case RISCVISD::VWADD_W_VL:
16918 case RISCVISD::VWADDU_W_VL:
16920 case RISCVISD::OR_VL:
16921 return RISCVISD::VWADDU_VL;
16923 case RISCVISD::SUB_VL:
16924 case RISCVISD::VWSUB_W_VL:
16925 case RISCVISD::VWSUBU_W_VL:
16926 return RISCVISD::VWSUBU_VL;
16928 case RISCVISD::MUL_VL:
16929 return RISCVISD::VWMULU_VL;
16931 case RISCVISD::SHL_VL:
16932 return RISCVISD::VWSLL_VL;
16940 static unsigned getFPExtOpcode(
unsigned Opcode) {
16942 case RISCVISD::FADD_VL:
16943 case RISCVISD::VFWADD_W_VL:
16944 return RISCVISD::VFWADD_VL;
16945 case RISCVISD::FSUB_VL:
16946 case RISCVISD::VFWSUB_W_VL:
16947 return RISCVISD::VFWSUB_VL;
16948 case RISCVISD::FMUL_VL:
16949 return RISCVISD::VFWMUL_VL;
16950 case RISCVISD::VFMADD_VL:
16951 return RISCVISD::VFWMADD_VL;
16952 case RISCVISD::VFMSUB_VL:
16953 return RISCVISD::VFWMSUB_VL;
16954 case RISCVISD::VFNMADD_VL:
16955 return RISCVISD::VFWNMADD_VL;
16956 case RISCVISD::VFNMSUB_VL:
16957 return RISCVISD::VFWNMSUB_VL;
16965 static unsigned getSUOpcode(
unsigned Opcode) {
16967 "SU is only supported for MUL");
16968 return RISCVISD::VWMULSU_VL;
16973 static unsigned getWOpcode(
unsigned Opcode, ExtKind SupportsExt) {
16976 case RISCVISD::ADD_VL:
16978 case RISCVISD::OR_VL:
16979 return SupportsExt == ExtKind::SExt ? RISCVISD::VWADD_W_VL
16980 : RISCVISD::VWADDU_W_VL;
16982 case RISCVISD::SUB_VL:
16983 return SupportsExt == ExtKind::SExt ? RISCVISD::VWSUB_W_VL
16984 : RISCVISD::VWSUBU_W_VL;
16985 case RISCVISD::FADD_VL:
16986 return RISCVISD::VFWADD_W_VL;
16987 case RISCVISD::FSUB_VL:
16988 return RISCVISD::VFWSUB_W_VL;
16994 using CombineToTry = std::function<std::optional<CombineResult>(
16995 SDNode * ,
const NodeExtensionHelper & ,
17000 bool needToPromoteOtherUsers()
const {
return EnforceOneUse; }
17008 "Unexpected Opcode");
17021 unsigned ScalarBits =
Op.getValueSizeInBits();
17023 if (ScalarBits < EltBits) {
17025 assert(
Opc == RISCVISD::VMV_V_X_VL && EltBits == 64 && ScalarBits == 32 &&
17026 !Subtarget.
is64Bit() &&
"Unexpected splat");
17028 SupportsSExt =
true;
17032 SupportsZExt =
true;
17034 EnforceOneUse =
false;
17038 unsigned NarrowSize = EltBits / 2;
17041 if (NarrowSize < 8)
17045 SupportsSExt =
true;
17049 SupportsZExt =
true;
17051 EnforceOneUse =
false;
17055 return (NarrowEltVT == MVT::f32 ||
17060 return NarrowEltVT == MVT::bf16 && Subtarget.hasStdExtZvfbfwma();
17067 SupportsZExt =
false;
17068 SupportsSExt =
false;
17069 SupportsFPExt =
false;
17070 SupportsBF16Ext =
false;
17071 EnforceOneUse =
true;
17093 case RISCVISD::VZEXT_VL:
17094 SupportsZExt =
true;
17096 case RISCVISD::VSEXT_VL:
17097 SupportsSExt =
true;
17099 case RISCVISD::FP_EXTEND_VL: {
17102 if (isSupportedFPExtend(NarrowEltVT, Subtarget))
17103 SupportsFPExt =
true;
17104 if (isSupportedBF16Extend(NarrowEltVT, Subtarget))
17105 SupportsBF16Ext =
true;
17110 case RISCVISD::VMV_V_X_VL:
17111 fillUpExtensionSupportForSplat(Root, DAG, Subtarget);
17113 case RISCVISD::VFMV_V_F_VL: {
17124 unsigned ScalarBits =
Op.getOperand(0).getValueSizeInBits();
17125 if (NarrowSize != ScalarBits)
17128 if (isSupportedFPExtend(
Op.getOperand(0).getSimpleValueType(), Subtarget))
17129 SupportsFPExt =
true;
17130 if (isSupportedBF16Extend(
Op.getOperand(0).getSimpleValueType(),
17132 SupportsBF16Ext =
true;
17141 static bool isSupportedRoot(
const SDNode *Root,
17154 case RISCVISD::ADD_VL:
17155 case RISCVISD::MUL_VL:
17156 case RISCVISD::VWADD_W_VL:
17157 case RISCVISD::VWADDU_W_VL:
17158 case RISCVISD::SUB_VL:
17159 case RISCVISD::VWSUB_W_VL:
17160 case RISCVISD::VWSUBU_W_VL:
17162 case RISCVISD::FADD_VL:
17163 case RISCVISD::FSUB_VL:
17164 case RISCVISD::FMUL_VL:
17165 case RISCVISD::VFWADD_W_VL:
17166 case RISCVISD::VFWSUB_W_VL:
17168 case RISCVISD::OR_VL:
17172 Subtarget.hasStdExtZvbb();
17173 case RISCVISD::SHL_VL:
17174 return Subtarget.hasStdExtZvbb();
17175 case RISCVISD::VFMADD_VL:
17176 case RISCVISD::VFNMSUB_VL:
17177 case RISCVISD::VFNMADD_VL:
17178 case RISCVISD::VFMSUB_VL:
17188 assert(isSupportedRoot(Root, Subtarget) &&
17189 "Trying to build an helper with an "
17190 "unsupported root");
17191 assert(OperandIdx < 2 &&
"Requesting something else than LHS or RHS");
17201 case RISCVISD::VWADD_W_VL:
17202 case RISCVISD::VWADDU_W_VL:
17203 case RISCVISD::VWSUB_W_VL:
17204 case RISCVISD::VWSUBU_W_VL:
17205 case RISCVISD::VFWADD_W_VL:
17206 case RISCVISD::VFWSUB_W_VL:
17207 if (OperandIdx == 1) {
17209 Opc == RISCVISD::VWADDU_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL;
17211 Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWSUB_W_VL;
17213 Opc == RISCVISD::VFWADD_W_VL ||
Opc == RISCVISD::VFWSUB_W_VL;
17216 EnforceOneUse =
false;
17221 fillUpExtensionSupport(Root, DAG, Subtarget);
17227 static std::pair<SDValue, SDValue>
17230 assert(isSupportedRoot(Root, Subtarget) &&
"Unexpected root");
17249 switch (
N->getOpcode()) {
17253 case RISCVISD::ADD_VL:
17254 case RISCVISD::MUL_VL:
17255 case RISCVISD::OR_VL:
17256 case RISCVISD::VWADD_W_VL:
17257 case RISCVISD::VWADDU_W_VL:
17258 case RISCVISD::FADD_VL:
17259 case RISCVISD::FMUL_VL:
17260 case RISCVISD::VFWADD_W_VL:
17261 case RISCVISD::VFMADD_VL:
17262 case RISCVISD::VFNMSUB_VL:
17263 case RISCVISD::VFNMADD_VL:
17264 case RISCVISD::VFMSUB_VL:
17267 case RISCVISD::SUB_VL:
17268 case RISCVISD::VWSUB_W_VL:
17269 case RISCVISD::VWSUBU_W_VL:
17270 case RISCVISD::FSUB_VL:
17271 case RISCVISD::VFWSUB_W_VL:
17273 case RISCVISD::SHL_VL:
17292struct CombineResult {
17294 unsigned TargetOpcode;
17296 std::optional<ExtKind> LHSExt;
17297 std::optional<ExtKind> RHSExt;
17301 NodeExtensionHelper
LHS;
17303 NodeExtensionHelper
RHS;
17305 CombineResult(
unsigned TargetOpcode,
SDNode *Root,
17306 const NodeExtensionHelper &
LHS, std::optional<ExtKind> LHSExt,
17307 const NodeExtensionHelper &
RHS, std::optional<ExtKind> RHSExt)
17308 : TargetOpcode(TargetOpcode), LHSExt(LHSExt), RHSExt(RHSExt), Root(Root),
17317 std::tie(Mask, VL) =
17318 NodeExtensionHelper::getMaskAndVL(Root, DAG, Subtarget);
17332 LHS.getOrCreateExtendedOp(Root, DAG, Subtarget, LHSExt),
17333 RHS.getOrCreateExtendedOp(Root, DAG, Subtarget, RHSExt),
17334 Passthru, Mask, VL);
17348static std::optional<CombineResult>
17349canFoldToVWWithSameExtensionImpl(
SDNode *Root,
const NodeExtensionHelper &LHS,
17350 const NodeExtensionHelper &RHS,
17353 if ((AllowExtMask & ExtKind::ZExt) &&
LHS.SupportsZExt &&
RHS.SupportsZExt)
17354 return CombineResult(NodeExtensionHelper::getZExtOpcode(Root->
getOpcode()),
17355 Root, LHS, {ExtKind::ZExt}, RHS,
17357 if ((AllowExtMask & ExtKind::SExt) &&
LHS.SupportsSExt &&
RHS.SupportsSExt)
17358 return CombineResult(NodeExtensionHelper::getSExtOpcode(Root->
getOpcode()),
17359 Root, LHS, {ExtKind::SExt}, RHS,
17361 if ((AllowExtMask & ExtKind::FPExt) &&
LHS.SupportsFPExt &&
RHS.SupportsFPExt)
17362 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
17363 Root, LHS, {ExtKind::FPExt}, RHS,
17365 if ((AllowExtMask & ExtKind::BF16Ext) &&
LHS.SupportsBF16Ext &&
17366 RHS.SupportsBF16Ext)
17367 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
17368 Root, LHS, {ExtKind::BF16Ext}, RHS,
17369 {ExtKind::BF16Ext});
17370 return std::nullopt;
17379static std::optional<CombineResult>
17380canFoldToVWWithSameExtension(
SDNode *Root,
const NodeExtensionHelper &LHS,
17383 return canFoldToVWWithSameExtensionImpl(
17384 Root, LHS, RHS, ExtKind::ZExt | ExtKind::SExt | ExtKind::FPExt, DAG,
17392static std::optional<CombineResult>
17393canFoldToVW_W(
SDNode *Root,
const NodeExtensionHelper &LHS,
17396 if (
RHS.SupportsFPExt)
17397 return CombineResult(
17398 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::FPExt),
17399 Root, LHS, std::nullopt, RHS, {ExtKind::FPExt});
17406 return CombineResult(
17407 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::ZExt), Root,
17408 LHS, std::nullopt, RHS, {ExtKind::ZExt});
17410 return CombineResult(
17411 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::SExt), Root,
17412 LHS, std::nullopt, RHS, {ExtKind::SExt});
17413 return std::nullopt;
17420static std::optional<CombineResult>
17421canFoldToVWWithSEXT(
SDNode *Root,
const NodeExtensionHelper &LHS,
17424 return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::SExt, DAG,
17432static std::optional<CombineResult>
17433canFoldToVWWithZEXT(
SDNode *Root,
const NodeExtensionHelper &LHS,
17436 return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::ZExt, DAG,
17444static std::optional<CombineResult>
17445canFoldToVWWithFPEXT(
SDNode *Root,
const NodeExtensionHelper &LHS,
17448 return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::FPExt, DAG,
17456static std::optional<CombineResult>
17457canFoldToVWWithBF16EXT(
SDNode *Root,
const NodeExtensionHelper &LHS,
17460 return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::BF16Ext, DAG,
17468static std::optional<CombineResult>
17469canFoldToVW_SU(
SDNode *Root,
const NodeExtensionHelper &LHS,
17473 if (!
LHS.SupportsSExt || !
RHS.SupportsZExt)
17474 return std::nullopt;
17475 return CombineResult(NodeExtensionHelper::getSUOpcode(Root->
getOpcode()),
17476 Root, LHS, {ExtKind::SExt}, RHS,
17481NodeExtensionHelper::getSupportedFoldings(
const SDNode *Root) {
17487 case RISCVISD::ADD_VL:
17488 case RISCVISD::SUB_VL:
17489 case RISCVISD::OR_VL:
17490 case RISCVISD::FADD_VL:
17491 case RISCVISD::FSUB_VL:
17493 Strategies.
push_back(canFoldToVWWithSameExtension);
17497 case RISCVISD::FMUL_VL:
17498 case RISCVISD::VFMADD_VL:
17499 case RISCVISD::VFMSUB_VL:
17500 case RISCVISD::VFNMADD_VL:
17501 case RISCVISD::VFNMSUB_VL:
17502 Strategies.
push_back(canFoldToVWWithSameExtension);
17503 if (Root->
getOpcode() == RISCVISD::VFMADD_VL)
17504 Strategies.
push_back(canFoldToVWWithBF16EXT);
17507 case RISCVISD::MUL_VL:
17509 Strategies.
push_back(canFoldToVWWithSameExtension);
17514 case RISCVISD::SHL_VL:
17516 Strategies.
push_back(canFoldToVWWithZEXT);
17518 case RISCVISD::VWADD_W_VL:
17519 case RISCVISD::VWSUB_W_VL:
17521 Strategies.
push_back(canFoldToVWWithSEXT);
17523 case RISCVISD::VWADDU_W_VL:
17524 case RISCVISD::VWSUBU_W_VL:
17526 Strategies.
push_back(canFoldToVWWithZEXT);
17528 case RISCVISD::VFWADD_W_VL:
17529 case RISCVISD::VFWSUB_W_VL:
17531 Strategies.
push_back(canFoldToVWWithFPEXT);
17542 assert(
N->getOpcode() == RISCVISD::ADD_VL);
17545 SDValue Passthru =
N->getOperand(2);
17579 if (!NodeExtensionHelper::isSupportedRoot(
N, Subtarget))
17585 Inserted.insert(
N);
17588 while (!Worklist.
empty()) {
17591 NodeExtensionHelper
LHS(Root, 0, DAG, Subtarget);
17592 NodeExtensionHelper
RHS(Root, 1, DAG, Subtarget);
17593 auto AppendUsersIfNeeded = [&Worklist, &Subtarget,
17594 &Inserted](
const NodeExtensionHelper &
Op) {
17595 if (
Op.needToPromoteOtherUsers()) {
17598 if (!NodeExtensionHelper::isSupportedRoot(TheUser, Subtarget))
17603 if (Inserted.insert(TheUser).second)
17616 NodeExtensionHelper::getSupportedFoldings(Root);
17618 assert(!FoldingStrategies.
empty() &&
"Nothing to be folded");
17619 bool Matched =
false;
17620 for (
int Attempt = 0;
17621 (Attempt != 1 + NodeExtensionHelper::isCommutative(Root)) && !Matched;
17624 for (NodeExtensionHelper::CombineToTry FoldingStrategy :
17625 FoldingStrategies) {
17626 std::optional<CombineResult> Res =
17627 FoldingStrategy(Root,
LHS,
RHS, DAG, Subtarget);
17634 if (Res->LHSExt.has_value())
17635 if (!AppendUsersIfNeeded(
LHS))
17637 if (Res->RHSExt.has_value())
17638 if (!AppendUsersIfNeeded(
RHS))
17650 SDValue InputRootReplacement;
17657 for (CombineResult Res : CombinesToApply) {
17658 SDValue NewValue = Res.materialize(DAG, Subtarget);
17659 if (!InputRootReplacement) {
17661 "First element is expected to be the current node");
17662 InputRootReplacement = NewValue;
17667 for (std::pair<SDValue, SDValue> OldNewValues : ValuesToReplace) {
17671 return InputRootReplacement;
17678 unsigned Opc =
N->getOpcode();
17679 assert(
Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWADDU_W_VL ||
17680 Opc == RISCVISD::VWSUB_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL);
17683 SDValue MergeOp =
N->getOperand(1);
17684 unsigned MergeOpc = MergeOp.
getOpcode();
17686 if (MergeOpc != RISCVISD::VMERGE_VL && MergeOpc !=
ISD::VSELECT)
17695 SDValue Passthru =
N->getOperand(2);
17701 if (Mask.getOpcode() != RISCVISD::VMSET_VL)
17709 Z = Z.getOperand(1);
17715 {Y, X, Y, MergeOp->getOperand(0), N->getOperand(4)},
17722 [[maybe_unused]]
unsigned Opc =
N->getOpcode();
17723 assert(
Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWADDU_W_VL ||
17724 Opc == RISCVISD::VWSUB_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL);
17751 EVT NewMemVT = (MemVT == MVT::i32) ? MVT::i64 : MVT::i128;
17757 auto Ext = cast<LoadSDNode>(LSNode1)->getExtensionType();
17759 if (MemVT == MVT::i32)
17760 Opcode = (Ext ==
ISD::ZEXTLOAD) ? RISCVISD::TH_LWUD : RISCVISD::TH_LWD;
17762 Opcode = RISCVISD::TH_LDD;
17765 Opcode,
SDLoc(LSNode1), DAG.
getVTList({XLenVT, XLenVT, MVT::Other}),
17778 unsigned Opcode = (MemVT == MVT::i32) ? RISCVISD::TH_SWD : RISCVISD::TH_SDD;
17800 if (!Subtarget.hasVendorXTHeadMemPair())
17812 auto ExtractBaseAndOffset = [](
SDValue Ptr) -> std::pair<SDValue, uint64_t> {
17814 if (
auto *C1 = dyn_cast<ConstantSDNode>(
Ptr->getOperand(1)))
17815 return {
Ptr->getOperand(0), C1->getZExtValue()};
17819 auto [Base1, Offset1] = ExtractBaseAndOffset(LSNode1->
getOperand(OpNum));
17840 auto [Base2, Offset2] = ExtractBaseAndOffset(LSNode2->
getOperand(OpNum));
17843 if (Base1 != Base2)
17847 bool Valid =
false;
17848 if (MemVT == MVT::i32) {
17850 if ((Offset1 + 4 == Offset2) && isShiftedUInt<2, 3>(Offset1))
17852 }
else if (MemVT == MVT::i64) {
17854 if ((Offset1 + 8 == Offset2) && isShiftedUInt<2, 4>(Offset1))
17888 if (Src->isStrictFPOpcode())
17896 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
17906 EVT VT =
N->getValueType(0);
17909 MVT SrcVT = Src.getSimpleValueType();
17910 MVT SrcContainerVT = SrcVT;
17912 SDValue XVal = Src.getOperand(0);
17938 IsSigned ? RISCVISD::VFCVT_RTZ_X_F_VL : RISCVISD::VFCVT_RTZ_XU_F_VL;
17939 FpToInt = DAG.
getNode(
Opc,
DL, ContainerVT, XVal, Mask, VL);
17942 IsSigned ? RISCVISD::VFCVT_RM_X_F_VL : RISCVISD::VFCVT_RM_XU_F_VL;
17943 FpToInt = DAG.
getNode(
Opc,
DL, ContainerVT, XVal, Mask,
17956 if (VT != MVT::i32 && VT != XLenVT)
17961 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
17963 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
17986 EVT DstVT =
N->getValueType(0);
17987 if (DstVT != XLenVT)
17993 if (Src->isStrictFPOpcode())
18001 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
18004 EVT SatVT = cast<VTSDNode>(
N->getOperand(1))->getVT();
18013 if (SatVT == DstVT)
18014 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
18015 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
18016 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
18021 Src = Src.getOperand(0);
18029 if (
Opc == RISCVISD::FCVT_WU_RV64)
18042 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected extension");
18048 EVT VT =
N->getValueType(0);
18054 return DAG.
getNode(RISCVISD::BREV8,
DL, VT, Src.getOperand(0));
18063 auto *VPLoad = dyn_cast<VPLoadSDNode>(
N->getOperand(0));
18067 EVT LoadVT = VPLoad->getValueType(0);
18071 N->getOperand(2) != VPLoad->getVectorLength() ||
18072 !
N->getOperand(0).hasOneUse())
18079 SDValue LoadMask = VPLoad->getMask();
18084 if (LoadMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
18086 LoadMask.
getOperand(2) != VPLoad->getVectorLength())
18094 SDValue NumElem = VPLoad->getVectorLength();
18095 uint64_t ElemWidthByte = VPLoad->getValueType(0).getScalarSizeInBits() / 8;
18107 PtrInfo, VPLoad->getMemOperand()->getFlags(),
18111 LoadVT,
DL, VPLoad->getChain(),
Base, Stride, LoadMask,
18112 VPLoad->getVectorLength(), MMO, VPLoad->isExpandingLoad());
18124 auto *VPStore = cast<VPStoreSDNode>(
N);
18126 if (VPStore->getValue().getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE)
18129 SDValue VPReverse = VPStore->getValue();
18135 VPStore->getVectorLength() != VPReverse.
getOperand(2) ||
18139 SDValue StoreMask = VPStore->getMask();
18144 if (StoreMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
18146 StoreMask.
getOperand(2) != VPStore->getVectorLength())
18154 SDValue NumElem = VPStore->getVectorLength();
18168 PtrInfo, VPStore->getMemOperand()->getFlags(),
18173 VPStore->getOffset(), Stride, StoreMask, VPStore->getVectorLength(),
18174 VPStore->getMemoryVT(), MMO, VPStore->getAddressingMode(),
18175 VPStore->isTruncatingStore(), VPStore->isCompressingStore());
18187 EVT VT =
N->getValueType(0);
18199 if (In.getOpcode() != ISD::VP_SRL || In.getOperand(2) != Mask ||
18200 In.getOperand(3) != VL)
18209 if (
LHS.getOpcode() != ISD::VP_ADD ||
LHS.getOperand(2) != Mask ||
18210 LHS.getOperand(3) != VL)
18217 if (V.getOpcode() != ISD::VP_ADD || V.getOperand(2) != Mask ||
18218 V.getOperand(3) != VL)
18230 if (!FindAdd(LHS0, LHS1) && !FindAdd(LHS1, LHS0))
18244 if (
Op.getOpcode() != ISD::VP_ZERO_EXTEND ||
Op.getOperand(1) != Mask ||
18245 Op.getOperand(2) != VL)
18255 Operands[0].getOperand(0), Mask, VL);
18257 Operands[1].getOperand(0), Mask, VL);
18261 return DAG.
getNode(RISCVISD::AVGCEILU_VL,
DL, VT,
18262 {NewOp0, NewOp1, DAG.
getUNDEF(VT), Mask, VL});
18274 case RISCVISD::VFMADD_VL: Opcode = RISCVISD::VFNMSUB_VL;
break;
18275 case RISCVISD::VFNMSUB_VL: Opcode = RISCVISD::VFMADD_VL;
break;
18276 case RISCVISD::VFNMADD_VL: Opcode = RISCVISD::VFMSUB_VL;
break;
18277 case RISCVISD::VFMSUB_VL: Opcode = RISCVISD::VFNMADD_VL;
break;
18278 case RISCVISD::STRICT_VFMADD_VL: Opcode = RISCVISD::STRICT_VFNMSUB_VL;
break;
18279 case RISCVISD::STRICT_VFNMSUB_VL: Opcode = RISCVISD::STRICT_VFMADD_VL;
break;
18280 case RISCVISD::STRICT_VFNMADD_VL: Opcode = RISCVISD::STRICT_VFMSUB_VL;
break;
18281 case RISCVISD::STRICT_VFMSUB_VL: Opcode = RISCVISD::STRICT_VFNMADD_VL;
break;
18291 case RISCVISD::VFMADD_VL: Opcode = RISCVISD::VFMSUB_VL;
break;
18292 case RISCVISD::VFMSUB_VL: Opcode = RISCVISD::VFMADD_VL;
break;
18293 case RISCVISD::VFNMADD_VL: Opcode = RISCVISD::VFNMSUB_VL;
break;
18294 case RISCVISD::VFNMSUB_VL: Opcode = RISCVISD::VFNMADD_VL;
break;
18295 case RISCVISD::STRICT_VFMADD_VL: Opcode = RISCVISD::STRICT_VFMSUB_VL;
break;
18296 case RISCVISD::STRICT_VFMSUB_VL: Opcode = RISCVISD::STRICT_VFMADD_VL;
break;
18297 case RISCVISD::STRICT_VFNMADD_VL: Opcode = RISCVISD::STRICT_VFNMSUB_VL;
break;
18298 case RISCVISD::STRICT_VFNMSUB_VL: Opcode = RISCVISD::STRICT_VFNMADD_VL;
break;
18311 unsigned Offset = IsStrict ? 1 : 0;
18318 auto invertIfNegative = [&Mask, &VL](
SDValue &V) {
18319 if (V.getOpcode() == RISCVISD::FNEG_VL && V.getOperand(1) == Mask &&
18320 V.getOperand(2) == VL) {
18322 V = V.getOperand(0);
18329 bool NegA = invertIfNegative(
A);
18330 bool NegB = invertIfNegative(
B);
18331 bool NegC = invertIfNegative(
C);
18334 if (!NegA && !NegB && !NegC)
18340 {N->getOperand(0), A, B, C, Mask, VL});
18364 EVT VT =
N->getValueType(0);
18369 if (!isa<ConstantSDNode>(
N->getOperand(1)))
18371 uint64_t ShAmt =
N->getConstantOperandVal(1);
18379 cast<VTSDNode>(N0.
getOperand(1))->getVT().getSizeInBits();
18384 if (LShAmt < ExtSize) {
18397 if (ShAmt > 32 || VT != MVT::i64)
18413 AddC = dyn_cast<ConstantSDNode>(N0.
getOperand(IsAdd ? 1 : 0));
18426 !isa<ConstantSDNode>(U->getOperand(1)) ||
18427 U->getConstantOperandVal(1) > 32)
18482 if (!
Cond.hasOneUse())
18501 EVT VT =
Cond.getValueType();
18546 LHS =
LHS.getOperand(0);
18556 LHS.getOperand(0).getValueType() == Subtarget.
getXLenVT()) {
18560 CCVal = cast<CondCodeSDNode>(
LHS.getOperand(2))->get();
18564 RHS =
LHS.getOperand(1);
18565 LHS =
LHS.getOperand(0);
18574 auto isXorImmediate = [](
const SDValue &
Op) ->
bool {
18575 if (
const auto *XorCnst = dyn_cast<ConstantSDNode>(
Op))
18576 return isInt<12>(XorCnst->getSExtValue());
18580 auto singleBitOp = [&DAG](
const SDValue &VarOp,
18581 const SDValue &ConstOp) ->
bool {
18582 if (
const auto *XorCnst = dyn_cast<ConstantSDNode>(ConstOp)) {
18584 return (XorCnst->getSExtValue() == 1) &&
18589 auto onlyUsedBySelectOrBR = [](
const SDValue &
Op) ->
bool {
18590 for (
const SDNode *UserNode :
Op->users()) {
18591 const unsigned Opcode = UserNode->getOpcode();
18592 if (Opcode != RISCVISD::SELECT_CC && Opcode != RISCVISD::BR_CC)
18597 auto isFoldableXorEq = [isXorImmediate, singleBitOp, onlyUsedBySelectOrBR](
18600 (!isXorImmediate(
LHS.getOperand(1)) ||
18601 singleBitOp(
LHS.getOperand(0),
LHS.getOperand(1)) ||
18602 onlyUsedBySelectOrBR(
LHS));
18605 if (isFoldableXorEq(
LHS,
RHS)) {
18606 RHS =
LHS.getOperand(1);
18607 LHS =
LHS.getOperand(0);
18613 if (isFoldableXorEq(LHS0,
RHS) && isa<ConstantSDNode>(LHS0.
getOperand(1))) {
18633 if (Subtarget.hasVendorXAndesPerf()) {
18643 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
18686 bool Commutative =
true;
18687 unsigned Opc = TrueVal.getOpcode();
18697 Commutative =
false;
18705 if (!TrueVal.hasOneUse() || isa<ConstantSDNode>(FalseVal))
18709 if (FalseVal == TrueVal.getOperand(0))
18711 else if (Commutative && FalseVal == TrueVal.getOperand(1))
18716 EVT VT =
N->getValueType(0);
18718 SDValue OtherOp = TrueVal.getOperand(1 - OpToFold);
18724 assert(IdentityOperand &&
"No identity operand!");
18729 DAG.
getSelect(
DL, OtherOpVT,
N->getOperand(0), OtherOp, IdentityOperand);
18730 return DAG.
getNode(TrueVal.getOpcode(),
DL, VT, FalseVal, NewSel);
18751 CountZeroes =
N->getOperand(2);
18752 ValOnZero =
N->getOperand(1);
18754 CountZeroes =
N->getOperand(1);
18755 ValOnZero =
N->getOperand(2);
18774 if (
Cond->getOperand(0) != CountZeroesArgument)
18790 CountZeroes, BitWidthMinusOne);
18800 EVT VT =
N->getValueType(0);
18801 EVT CondVT =
Cond.getValueType();
18809 (Subtarget.hasStdExtZicond() || Subtarget.hasVendorXVentanaCondOps())) {
18815 const APInt &MaskVal =
LHS.getConstantOperandAPInt(1);
18826 if (!TrueVal.hasOneUse() || !FalseVal.hasOneUse())
18830 if (TrueVal.getOpcode() ==
ISD::SUB && FalseVal.getOpcode() ==
ISD::ADD) {
18838 SDValue A = FalseVal.getOperand(0);
18839 SDValue B = FalseVal.getOperand(1);
18841 return ((TrueVal.getOperand(0) ==
A && TrueVal.getOperand(1) ==
B) ||
18842 (TrueVal.getOperand(1) ==
A && TrueVal.getOperand(0) ==
B));
18850 EVT VT =
N->getValueType(0);
18852 SDValue TrueVal =
N->getOperand(1);
18853 SDValue FalseVal =
N->getOperand(2);
18883 SDValue TrueVal =
N->getOperand(1);
18884 SDValue FalseVal =
N->getOperand(2);
18899 EVT VT =
N->getValueType(0);
18906 const unsigned Opcode =
N->op_begin()->getNode()->getOpcode();
18921 if (
Op.isUndef()) {
18934 if (
Op.getOpcode() != Opcode || !
Op.hasOneUse())
18938 if (!isa<ConstantSDNode>(
Op.getOperand(1)) &&
18939 !isa<ConstantFPSDNode>(
Op.getOperand(1)))
18943 if (
Op.getOperand(0).getValueType() !=
Op.getOperand(1).getValueType())
18967 EVT AVT =
A.getValueType();
18968 EVT BVT =
B.getValueType();
18998 if (AOpt || BOpt) {
19016 EVT OpVT =
A.getValueType();
19041 EVT OpVT =
A.getOperand(0).getValueType();
19043 OpVT !=
B.getOperand(0).getValueType() ||
19072 if (!Subtarget.hasStdExtZvqdotq())
19076 EVT VT =
N->getValueType(0);
19101 const unsigned InVecOpcode = InVec->
getOpcode();
19111 if (!isa<ConstantSDNode>(InValRHS) && !isa<ConstantFPSDNode>(InValRHS))
19118 InVecLHS, InValLHS, EltNo);
19120 InVecRHS, InValRHS, EltNo);
19129 auto *IndexC = dyn_cast<ConstantSDNode>(EltNo);
19132 unsigned Elt = IndexC->getZExtValue();
19138 unsigned NewIdx = Elt % ConcatNumElts;
19140 unsigned ConcatOpIdx = Elt / ConcatNumElts;
19145 ConcatOps[ConcatOpIdx] = ConcatOp;
19157 EVT VT =
N->getValueType(0);
19167 auto *BaseLd = dyn_cast<LoadSDNode>(
N->getOperand(0));
19169 !
SDValue(BaseLd, 0).hasOneUse())
19172 EVT BaseLdVT = BaseLd->getValueType(0);
19179 auto *Ld = dyn_cast<LoadSDNode>(
Op);
19180 if (!Ld || !Ld->isSimple() || !
Op.hasOneUse() ||
19182 Ld->getValueType(0) != BaseLdVT)
19191 using PtrDiff = std::pair<std::variant<int64_t, SDValue>,
bool>;
19193 LoadSDNode *Ld2) -> std::optional<PtrDiff> {
19198 if (BIO1.equalBaseIndex(BIO2, DAG))
19203 SDValue P2 = Ld2->getBasePtr();
19206 if (P1.getOpcode() ==
ISD::ADD && P1.getOperand(0) == P2)
19207 return {{P1.getOperand(1),
true}};
19209 return std::nullopt;
19213 auto BaseDiff = GetPtrDiff(Lds[0], Lds[1]);
19218 for (
auto *It = Lds.
begin() + 1; It != Lds.
end() - 1; It++)
19219 if (GetPtrDiff(*It, *std::next(It)) != BaseDiff)
19227 unsigned WideScalarBitWidth =
19240 auto [StrideVariant, MustNegateStride] = *BaseDiff;
19242 std::holds_alternative<SDValue>(StrideVariant)
19243 ? std::get<SDValue>(StrideVariant)
19246 if (MustNegateStride)
19254 if (
auto *ConstStride = dyn_cast<ConstantSDNode>(Stride);
19255 ConstStride && ConstStride->getSExtValue() >= 0)
19259 ConstStride->getSExtValue() * (
N->getNumOperands() - 1);
19265 BaseLd->getPointerInfo(), BaseLd->getMemOperand()->getFlags(), MemSize,
19269 WideVecVT,
DL, BaseLd->getChain(), BaseLd->getBasePtr(), Stride,
19283 EVT VT =
N->getValueType(0);
19300 for (
int MaskIndex : Mask) {
19301 bool SelectMaskVal = (MaskIndex < (int)NumElts);
19304 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
19341 if (
N->getValueType(0).isFixedLengthVector())
19344 SDValue Addend =
N->getOperand(0);
19347 if (
N->getOpcode() == RISCVISD::ADD_VL) {
19348 SDValue AddPassthruOp =
N->getOperand(2);
19349 if (!AddPassthruOp.
isUndef())
19353 auto IsVWMulOpc = [](
unsigned Opc) {
19355 case RISCVISD::VWMUL_VL:
19356 case RISCVISD::VWMULU_VL:
19357 case RISCVISD::VWMULSU_VL:
19372 if (!MulPassthruOp.
isUndef())
19382 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
19383 }(
N, DAG, Subtarget);
19388 if (AddMask != MulMask || AddVL != MulVL)
19391 const auto &TSInfo =
19393 unsigned Opc = TSInfo.getMAccOpcode(MulOp.
getOpcode());
19396 EVT VT =
N->getValueType(0);
19407 if (!
N->getValueType(0).isVector())
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 IsVqdotqOpc = [](
unsigned Opc) {
19421 case RISCVISD::VQDOT_VL:
19422 case RISCVISD::VQDOTU_VL:
19423 case RISCVISD::VQDOTSU_VL:
19443 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
19444 }(
N, DAG, Subtarget);
19447 if (AddVL != MulVL)
19450 if (AddMask.getOpcode() != RISCVISD::VMSET_VL ||
19451 AddMask.getOperand(0) != MulVL)
19456 EVT VT =
N->getValueType(0);
19457 Addend = DAG.
getNode(RISCVISD::ADD_VL,
DL, VT, Addend, AccumOp,
19458 DAG.
getUNDEF(VT), AddMask, AddVL);
19476 const EVT IndexVT = Index.getValueType();
19480 if (!isIndexTypeSigned(IndexType))
19512 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
19515 if (Index->getOperand(i)->isUndef())
19517 uint64_t C = Index->getConstantOperandVal(i);
19518 if (
C % ElementSize != 0)
19520 C =
C / ElementSize;
19524 ActiveLanes.
set(
C);
19526 return ActiveLanes.
all();
19544 if (NumElems % 2 != 0)
19548 const unsigned WiderElementSize = ElementSize * 2;
19549 if (WiderElementSize > ST.getELen()/8)
19552 if (!ST.enableUnalignedVectorMem() && BaseAlign < WiderElementSize)
19555 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
19558 if (Index->getOperand(i)->isUndef())
19562 uint64_t C = Index->getConstantOperandVal(i);
19564 if (
C % WiderElementSize != 0)
19569 if (
C !=
Last + ElementSize)
19586 (isa<RegisterSDNode>(VL) &&
19587 cast<RegisterSDNode>(VL)->getReg() == RISCV::X0);
19588 if (!IsVLMAX || Mask.getOpcode() != RISCVISD::VMSET_VL ||
19589 Mask.getOperand(0) != VL)
19592 auto IsTruncNode = [&](
SDValue V) {
19593 return V.getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL &&
19594 V.getOperand(1) == Mask && V.getOperand(2) == VL;
19601 while (IsTruncNode(
Op)) {
19602 if (!
Op.hasOneUse())
19604 Op =
Op.getOperand(0);
19637 assert(
N->getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL);
19639 MVT VT =
N->getSimpleValueType(0);
19644 auto MatchMinMax = [&VL, &Mask](
SDValue V,
unsigned Opc,
unsigned OpcVL,
19646 if (V.getOpcode() !=
Opc &&
19647 !(V.getOpcode() == OpcVL && V.getOperand(2).isUndef() &&
19648 V.getOperand(3) == Mask && V.getOperand(4) == VL))
19656 Op.getOperand(1).getValueType().isFixedLengthVector() &&
19658 Op.getOperand(1).getOperand(0).getValueType() ==
Op.getValueType() &&
19660 Op =
Op.getOperand(1).getOperand(0);
19663 return V.getOperand(0);
19665 if (
Op.getOpcode() == RISCVISD::VMV_V_X_VL &&
Op.getOperand(0).isUndef() &&
19666 Op.getOperand(2) == VL) {
19667 if (
auto *Op1 = dyn_cast<ConstantSDNode>(
Op.getOperand(1))) {
19669 Op1->getAPIntValue().sextOrTrunc(
Op.getScalarValueSizeInBits());
19670 return V.getOperand(0);
19679 auto DetectUSatPattern = [&](
SDValue V) {
19691 MatchMinMax(SMinOp,
ISD::SMAX, RISCVISD::SMAX_VL, LoC))
19700 MatchMinMax(SMaxOp,
ISD::SMIN, RISCVISD::SMIN_VL, HiC))
19703 return DAG.
getNode(RISCVISD::SMAX_VL,
DL, V.getValueType(), SMinOp,
19704 V.getOperand(1), DAG.
getUNDEF(V.getValueType()),
19710 auto DetectSSatPattern = [&](
SDValue V) {
19712 unsigned NumSrcBits = V.getScalarValueSizeInBits();
19719 MatchMinMax(SMinOp,
ISD::SMAX, RISCVISD::SMAX_VL, LoC))
19720 if (HiC == SignedMax && LoC == SignedMin)
19725 MatchMinMax(SMaxOp,
ISD::SMIN, RISCVISD::SMIN_VL, HiC))
19726 if (HiC == SignedMax && LoC == SignedMin)
19735 while (Src.getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL &&
19736 Src.getOperand(1) == Mask && Src.getOperand(2) == VL &&
19738 Src = Src.getOperand(0);
19742 if ((Val = DetectUSatPattern(Src)))
19743 ClipOpc = RISCVISD::TRUNCATE_VECTOR_VL_USAT;
19744 else if ((Val = DetectSSatPattern(Src)))
19745 ClipOpc = RISCVISD::TRUNCATE_VECTOR_VL_SSAT;
19754 Val = DAG.
getNode(ClipOpc,
DL, ValVT, Val, Mask, VL);
19755 }
while (ValVT != VT);
19773 unsigned Opc =
N->getOpcode();
19775 "Unexpected opcode");
19776 EVT VT =
N->getValueType(0);
19785 Src = Src.getOperand(0);
19789 Src = Src.getOperand(0);
19793 Src = Src.getOperand(0);
19796 EVT SrcEVT = Src.getValueType();
19818 VectorBitsMax, EltSize, MinSize);
19823 MVT ContainerVT = SrcMVT;
19854 switch (
LHS.getOpcode()) {
19856 case RISCVISD::VSEXT_VL:
19857 Opcode = RISCVISD::VWMULSU_VL;
19860 case RISCVISD::VZEXT_VL:
19861 Opcode = RISCVISD::VWMULU_VL;
19872 else if (
RHS.getOpcode() == RISCVISD::VMV_V_X_VL &&
19874 ShAmtInt =
RHS.getConstantOperandVal(1);
19887 if (ShAmtInt >= NarrowBits)
19889 MVT VT =
N->getSimpleValueType(0);
19896 switch (
N->getOpcode()) {
19901 case RISCVISD::SHL_VL:
19902 Passthru =
N->getOperand(2);
19903 Mask =
N->getOperand(3);
19904 VL =
N->getOperand(4);
19909 return DAG.
getNode(Opcode,
DL, VT, NarrowOp,
19911 Passthru, Mask, VL);
19923 auto SimplifyDemandedLowBitsHelper = [&](
unsigned OpNo,
unsigned LowBits) {
19934 switch (
N->getOpcode()) {
19937 case RISCVISD::SplitF64: {
19941 if (Op0->
getOpcode() == RISCVISD::BuildPairF64)
19954 APInt V =
C->getValueAPF().bitcastToAPInt();
19983 case RISCVISD::SLLW:
19984 case RISCVISD::SRAW:
19985 case RISCVISD::SRLW:
19986 case RISCVISD::RORW:
19987 case RISCVISD::ROLW: {
19989 if (SimplifyDemandedLowBitsHelper(0, 32) ||
19990 SimplifyDemandedLowBitsHelper(1, 5))
19995 case RISCVISD::CLZW:
19996 case RISCVISD::CTZW: {
19998 if (SimplifyDemandedLowBitsHelper(0, 32))
20002 case RISCVISD::FMV_W_X_RV64: {
20007 if (Op0.
getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64)
20011 case RISCVISD::FMV_X_ANYEXTH:
20012 case RISCVISD::FMV_X_ANYEXTW_RV64: {
20015 MVT VT =
N->getSimpleValueType(0);
20018 if (
auto *CFP = dyn_cast<ConstantFPSDNode>(Op0)) {
20026 if ((
N->getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64 &&
20027 Op0->
getOpcode() == RISCVISD::FMV_W_X_RV64) ||
20028 (
N->getOpcode() == RISCVISD::FMV_X_ANYEXTH &&
20029 Op0->
getOpcode() == RISCVISD::FMV_H_X)) {
20031 "Unexpected value type!");
20036 cast<LoadSDNode>(Op0)->isSimple()) {
20038 auto *LN0 = cast<LoadSDNode>(Op0);
20041 LN0->getBasePtr(), IVT, LN0->getMemOperand());
20054 unsigned FPBits =
N->getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64 ? 32 : 16;
20065 EVT VT =
N->getValueType(0);
20120 if (!
C || !
C->getValueAPF().isExactlyValue(+1.0))
20122 EVT VT =
N->getValueType(0);
20151 if (
N->getValueType(0) == MVT::i64 && Subtarget.
is64Bit()) {
20156 Src.getOperand(0));
20161 Src.getOperand(0), Src.getOperand(1));
20169 case RISCVISD::TRUNCATE_VECTOR_VL:
20173 case ISD::VP_TRUNCATE:
20181 case RISCVISD::CZERO_EQZ:
20182 case RISCVISD::CZERO_NEZ: {
20186 unsigned Opc =
N->getOpcode();
20189 if (
Opc == RISCVISD::CZERO_EQZ && Val ==
Cond)
20193 Opc == RISCVISD::CZERO_EQZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ;
20201 return DAG.
getNode(InvOpc,
SDLoc(
N),
N->getValueType(0), Val, NewCond);
20211 N->getValueType(0), Val,
Cond.getOperand(0));
20215 case RISCVISD::SELECT_CC: {
20222 SDValue FalseV =
N->getOperand(4);
20224 EVT VT =
N->getValueType(0);
20227 if (TrueV == FalseV)
20232 if (!Subtarget.hasShortForwardBranchOpt() && isa<ConstantSDNode>(TrueV) &&
20238 int64_t TrueSImm = cast<ConstantSDNode>(TrueV)->getSExtValue();
20239 int64_t FalseSImm = cast<ConstantSDNode>(FalseV)->getSExtValue();
20242 if (isInt<12>(TrueSImm) && isInt<12>(FalseSImm) &&
20243 isInt<12>(TrueSImm - FalseSImm)) {
20258 return DAG.
getNode(RISCVISD::SELECT_CC,
DL,
N->getValueType(0),
20259 {LHS, RHS, CC, TrueV, FalseV});
20318 case RISCVISD::BR_CC: {
20325 return DAG.
getNode(RISCVISD::BR_CC,
DL,
N->getValueType(0),
20326 N->getOperand(0),
LHS,
RHS, CC,
N->getOperand(4));
20339 EVT VT =
N->getValueType(0);
20363 const auto *MGN = cast<MaskedGatherSDNode>(
N);
20364 const EVT VT =
N->getValueType(0);
20365 SDValue Index = MGN->getIndex();
20366 SDValue ScaleOp = MGN->getScale();
20368 assert(!MGN->isIndexScaled() &&
20369 "Scaled gather/scatter should not be formed");
20374 N->getVTList(), MGN->getMemoryVT(),
DL,
20375 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
20376 MGN->getBasePtr(), Index, ScaleOp},
20377 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
20381 N->getVTList(), MGN->getMemoryVT(),
DL,
20382 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
20383 MGN->getBasePtr(), Index, ScaleOp},
20384 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
20390 if (std::optional<VIDSequence> SimpleVID =
20392 SimpleVID && SimpleVID->StepDenominator == 1) {
20393 const int64_t StepNumerator = SimpleVID->StepNumerator;
20394 const int64_t Addend = SimpleVID->Addend;
20401 assert(MGN->getBasePtr()->getValueType(0) == PtrVT);
20409 VT,
DL, MGN->getChain(), BasePtr,
20411 EVL, MGN->getMemOperand());
20413 StridedLoad, MGN->getPassThru(), EVL);
20423 MGN->getBasePtr(), DAG.
getUNDEF(XLenVT),
20425 MGN->getMemoryVT(), MGN->getMemOperand(),
20434 MGN->getMemOperand()->getBaseAlign(), Subtarget)) {
20436 for (
unsigned i = 0; i < Index->getNumOperands(); i += 2)
20437 NewIndices.
push_back(Index.getOperand(i));
20438 EVT IndexVT = Index.getValueType()
20439 .getHalfNumVectorElementsVT(*DAG.
getContext());
20445 assert(EltCnt.isKnownEven() &&
"Splitting vector, but not in half!");
20447 EltCnt.divideCoefficientBy(2));
20450 EltCnt.divideCoefficientBy(2));
20455 {MGN->getChain(), Passthru, Mask, MGN->getBasePtr(),
20464 const auto *MSN = cast<MaskedScatterSDNode>(
N);
20465 SDValue Index = MSN->getIndex();
20466 SDValue ScaleOp = MSN->getScale();
20468 assert(!MSN->isIndexScaled() &&
20469 "Scaled gather/scatter should not be formed");
20474 N->getVTList(), MSN->getMemoryVT(),
DL,
20475 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
20477 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
20481 N->getVTList(), MSN->getMemoryVT(),
DL,
20482 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
20484 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
20486 EVT VT = MSN->getValue()->getValueType(0);
20488 if (!MSN->isTruncatingStore() &&
20492 return DAG.
getMaskedStore(MSN->getChain(),
DL, Shuffle, MSN->getBasePtr(),
20493 DAG.
getUNDEF(XLenVT), MSN->getMask(),
20494 MSN->getMemoryVT(), MSN->getMemOperand(),
20499 case ISD::VP_GATHER: {
20500 const auto *VPGN = cast<VPGatherSDNode>(
N);
20501 SDValue Index = VPGN->getIndex();
20502 SDValue ScaleOp = VPGN->getScale();
20504 assert(!VPGN->isIndexScaled() &&
20505 "Scaled gather/scatter should not be formed");
20510 {VPGN->getChain(), VPGN->getBasePtr(), Index,
20511 ScaleOp, VPGN->getMask(),
20512 VPGN->getVectorLength()},
20513 VPGN->getMemOperand(), IndexType);
20517 {VPGN->getChain(), VPGN->getBasePtr(), Index,
20518 ScaleOp, VPGN->getMask(),
20519 VPGN->getVectorLength()},
20520 VPGN->getMemOperand(), IndexType);
20524 case ISD::VP_SCATTER: {
20525 const auto *VPSN = cast<VPScatterSDNode>(
N);
20526 SDValue Index = VPSN->getIndex();
20527 SDValue ScaleOp = VPSN->getScale();
20529 assert(!VPSN->isIndexScaled() &&
20530 "Scaled gather/scatter should not be formed");
20535 {VPSN->getChain(), VPSN->getValue(),
20536 VPSN->getBasePtr(), Index, ScaleOp,
20537 VPSN->getMask(), VPSN->getVectorLength()},
20538 VPSN->getMemOperand(), IndexType);
20542 {VPSN->getChain(), VPSN->getValue(),
20543 VPSN->getBasePtr(), Index, ScaleOp,
20544 VPSN->getMask(), VPSN->getVectorLength()},
20545 VPSN->getMemOperand(), IndexType);
20548 case RISCVISD::SHL_VL:
20552 case RISCVISD::SRA_VL:
20553 case RISCVISD::SRL_VL: {
20555 if (ShAmt.
getOpcode() == RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL) {
20559 EVT VT =
N->getValueType(0);
20562 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt,
20563 N->getOperand(2),
N->getOperand(3),
N->getOperand(4));
20578 if (ShAmt.
getOpcode() == RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL) {
20581 EVT VT =
N->getValueType(0);
20585 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt);
20589 case RISCVISD::ADD_VL:
20597 case RISCVISD::VWADD_W_VL:
20598 case RISCVISD::VWADDU_W_VL:
20599 case RISCVISD::VWSUB_W_VL:
20600 case RISCVISD::VWSUBU_W_VL:
20602 case RISCVISD::OR_VL:
20603 case RISCVISD::SUB_VL:
20604 case RISCVISD::MUL_VL:
20606 case RISCVISD::VFMADD_VL:
20607 case RISCVISD::VFNMADD_VL:
20608 case RISCVISD::VFMSUB_VL:
20609 case RISCVISD::VFNMSUB_VL:
20610 case RISCVISD::STRICT_VFMADD_VL:
20611 case RISCVISD::STRICT_VFNMADD_VL:
20612 case RISCVISD::STRICT_VFMSUB_VL:
20613 case RISCVISD::STRICT_VFNMSUB_VL:
20615 case RISCVISD::FADD_VL:
20616 case RISCVISD::FSUB_VL:
20617 case RISCVISD::FMUL_VL:
20618 case RISCVISD::VFWADD_W_VL:
20619 case RISCVISD::VFWSUB_W_VL:
20630 auto *Store = cast<StoreSDNode>(
N);
20631 SDValue Chain = Store->getChain();
20632 EVT MemVT = Store->getMemoryVT();
20633 SDValue Val = Store->getValue();
20636 bool IsScalarizable =
20638 Store->isSimple() &&
20668 NewVT, *Store->getMemOperand())) {
20670 return DAG.
getStore(Chain,
DL, NewV, Store->getBasePtr(),
20671 Store->getPointerInfo(), Store->getBaseAlign(),
20672 Store->getMemOperand()->getFlags());
20680 if (
auto *L = dyn_cast<LoadSDNode>(Val);
20682 L->hasNUsesOfValue(1, 0) && L->hasNUsesOfValue(1, 1) &&
20684 L->getMemoryVT() == MemVT) {
20687 NewVT, *Store->getMemOperand()) &&
20689 NewVT, *L->getMemOperand())) {
20691 L->getPointerInfo(), L->getBaseAlign(),
20692 L->getMemOperand()->getFlags());
20693 return DAG.
getStore(Chain,
DL, NewL, Store->getBasePtr(),
20694 Store->getPointerInfo(), Store->getBaseAlign(),
20695 Store->getMemOperand()->getFlags());
20702 if ((Val.
getOpcode() == RISCVISD::VMV_X_S ||
20708 MVT VecVT = Src.getSimpleValueType();
20715 Store->getChain(),
DL, Src, Store->getBasePtr(), Store->getOffset(),
20718 Store->getMemOperand(), Store->getAddressingMode(),
20719 Store->isTruncatingStore(),
false);
20726 EVT VT =
N->getValueType(0);
20751 case RISCVISD::VFMV_V_F_VL: {
20752 const MVT VT =
N->getSimpleValueType(0);
20753 SDValue Passthru =
N->getOperand(0);
20754 SDValue Scalar =
N->getOperand(1);
20759 return DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL, VT, Passthru, Scalar, VL);
20762 case RISCVISD::VMV_V_X_VL: {
20763 const MVT VT =
N->getSimpleValueType(0);
20764 SDValue Passthru =
N->getOperand(0);
20765 SDValue Scalar =
N->getOperand(1);
20770 unsigned ScalarSize = Scalar.getValueSizeInBits();
20772 if (ScalarSize > EltWidth && Passthru.
isUndef())
20773 if (SimplifyDemandedLowBitsHelper(1, EltWidth))
20780 (!Const || Const->isZero() ||
20781 !Const->getAPIntValue().sextOrTrunc(EltWidth).isSignedIntN(5)))
20782 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, VT, Passthru, Scalar, VL);
20786 case RISCVISD::VFMV_S_F_VL: {
20791 if (
N->getOperand(0).isUndef() &&
20794 Src.getOperand(0).getValueType().isScalableVector()) {
20795 EVT VT =
N->getValueType(0);
20796 SDValue EVSrc = Src.getOperand(0);
20815 case RISCVISD::VMV_S_X_VL: {
20816 const MVT VT =
N->getSimpleValueType(0);
20817 SDValue Passthru =
N->getOperand(0);
20818 SDValue Scalar =
N->getOperand(1);
20824 unsigned ScalarSize = Scalar.getValueSizeInBits();
20826 if (ScalarSize > EltWidth && SimplifyDemandedLowBitsHelper(1, EltWidth))
20829 if (Scalar.getOpcode() == RISCVISD::VMV_X_S && Passthru.
isUndef() &&
20830 Scalar.getOperand(0).getValueType() ==
N->getValueType(0))
20831 return Scalar.getOperand(0);
20838 DAG.
getNode(
N->getOpcode(),
DL, M1VT, M1Passthru, Scalar, VL);
20847 Const && !Const->isZero() && isInt<5>(Const->getSExtValue()) &&
20849 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru, Scalar, VL);
20853 case RISCVISD::VMV_X_S: {
20855 MVT VecVT =
N->getOperand(0).getSimpleValueType();
20857 if (M1VT.
bitsLT(VecVT)) {
20859 return DAG.
getNode(RISCVISD::VMV_X_S,
DL,
N->getSimpleValueType(0), Vec);
20867 unsigned IntNo =
N->getConstantOperandVal(IntOpNo);
20872 case Intrinsic::riscv_vcpop:
20873 case Intrinsic::riscv_vcpop_mask:
20874 case Intrinsic::riscv_vfirst:
20875 case Intrinsic::riscv_vfirst_mask: {
20877 if (IntNo == Intrinsic::riscv_vcpop_mask ||
20878 IntNo == Intrinsic::riscv_vfirst_mask)
20879 VL =
N->getOperand(3);
20884 EVT VT =
N->getValueType(0);
20885 if (IntNo == Intrinsic::riscv_vfirst ||
20886 IntNo == Intrinsic::riscv_vfirst_mask)
20890 case Intrinsic::riscv_vsseg2_mask:
20891 case Intrinsic::riscv_vsseg3_mask:
20892 case Intrinsic::riscv_vsseg4_mask:
20893 case Intrinsic::riscv_vsseg5_mask:
20894 case Intrinsic::riscv_vsseg6_mask:
20895 case Intrinsic::riscv_vsseg7_mask:
20896 case Intrinsic::riscv_vsseg8_mask: {
20901 Tuple.
getOpcode() != RISCVISD::TUPLE_INSERT ||
20910 "Type mismatch without bitcast?");
20911 unsigned Stride = SEW / 8 * NF;
20926 auto *OldMemSD = cast<MemIntrinsicSDNode>(
N);
20939 case ISD::EXPERIMENTAL_VP_REVERSE:
20941 case ISD::VP_STORE:
20946 EVT VT =
N->getValueType(0);
20957 for (
unsigned i = 0; i < NF; ++i)
20958 Result = DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VT, Result,
Splat,
20964 if ((SrcVT == MVT::v1i1 || SrcVT == MVT::v2i1 || SrcVT == MVT::v4i1) &&
20985 case RISCVISD::VRGATHER_VX_VL: {
20988 EVT VT =
N->getValueType(0);
20991 SDValue Passthru =
N->getOperand(2);
20998 Src = Src.getOperand(1);
21000 switch (Src.getOpcode()) {
21003 case RISCVISD::VMV_V_X_VL:
21004 case RISCVISD::VFMV_V_F_VL:
21008 if (Passthru.
isUndef() && VL == Src.getOperand(2) &&
21009 Src.getValueType() == VT)
21012 case RISCVISD::VMV_S_X_VL:
21013 case RISCVISD::VFMV_S_F_VL:
21019 VL == Src.getOperand(2)) {
21029 case RISCVISD::TUPLE_EXTRACT: {
21030 EVT VT =
N->getValueType(0);
21032 unsigned Idx =
N->getConstantOperandVal(1);
21040 case Intrinsic::riscv_vlseg2_mask:
21041 case Intrinsic::riscv_vlseg3_mask:
21042 case Intrinsic::riscv_vlseg4_mask:
21043 case Intrinsic::riscv_vlseg5_mask:
21044 case Intrinsic::riscv_vlseg6_mask:
21045 case Intrinsic::riscv_vlseg7_mask:
21046 case Intrinsic::riscv_vlseg8_mask:
21056 "Type mismatch without bitcast?");
21057 unsigned Stride = SEW / 8 * NF;
21072 auto *TupleMemSD = cast<MemIntrinsicSDNode>(Tuple);
21083 return Result.getValue(0);
21085 case RISCVISD::TUPLE_INSERT: {
21087 if (
N->getOperand(1).isUndef())
21088 return N->getOperand(0);
21097 EVT XVT,
unsigned KeptBits)
const {
21102 if (XVT != MVT::i32 && XVT != MVT::i64)
21106 if (KeptBits == 32 || KeptBits == 64)
21110 return Subtarget.hasStdExtZbb() &&
21111 ((KeptBits == 8 && XVT == MVT::i64 && !Subtarget.
is64Bit()) ||
21119 "Expected shift op");
21137 if (!isa<StoreSDNode>(
Use) && !isa<LoadSDNode>(
Use))
21146 return isUsedByLdSt(N0.
getNode(),
N);
21148 auto *C1 = dyn_cast<ConstantSDNode>(N0->
getOperand(1));
21149 auto *C2 = dyn_cast<ConstantSDNode>(
N->getOperand(1));
21152 (Subtarget.hasStdExtZba() || Subtarget.hasVendorXAndesPerf()) && C2 &&
21153 C2->getZExtValue() >= 1 && C2->getZExtValue() <= 3;
21154 bool IsQCShlAdd = Subtarget.hasVendorXqciac() && C2 &&
21155 C2->getZExtValue() >= 4 && C2->getZExtValue() <= 31;
21158 if ((IsShXAdd || IsQCShlAdd) &&
N->hasOneUse() &&
21159 N->user_begin()->getOpcode() ==
ISD::ADD &&
21160 !isUsedByLdSt(*
N->user_begin(),
nullptr) &&
21161 !isa<ConstantSDNode>(
N->user_begin()->getOperand(1)))
21165 const APInt &C1Int = C1->getAPIntValue();
21166 APInt ShiftedC1Int = C1Int << C2->getAPIntValue();
21192 if (C1Cost < ShiftedC1Cost)
21215 EVT VT =
Op.getValueType();
21219 unsigned Opcode =
Op.getOpcode();
21227 const APInt &Mask =
C->getAPIntValue();
21236 auto IsLegalMask = [ShrunkMask, ExpandedMask](
const APInt &Mask) ->
bool {
21237 return ShrunkMask.
isSubsetOf(Mask) && Mask.isSubsetOf(ExpandedMask);
21239 auto UseMask = [Mask,
Op, &TLO](
const APInt &NewMask) ->
bool {
21240 if (NewMask == Mask)
21245 Op.getOperand(0), NewC);
21258 APInt NewMask =
APInt(Mask.getBitWidth(), 0xffff);
21259 if (IsLegalMask(NewMask))
21260 return UseMask(NewMask);
21263 if (VT == MVT::i64) {
21265 if (IsLegalMask(NewMask))
21266 return UseMask(NewMask);
21281 APInt NewMask = ShrunkMask;
21282 if (MinSignedBits <= 12)
21284 else if (!
C->isOpaque() && MinSignedBits <= 32 && !ShrunkMask.
isSignedIntN(32))
21290 assert(IsLegalMask(NewMask));
21291 return UseMask(NewMask);
21295 static const uint64_t GREVMasks[] = {
21296 0x5555555555555555ULL, 0x3333333333333333ULL, 0x0F0F0F0F0F0F0F0FULL,
21297 0x00FF00FF00FF00FFULL, 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL};
21299 for (
unsigned Stage = 0; Stage != 6; ++Stage) {
21300 unsigned Shift = 1 << Stage;
21301 if (ShAmt & Shift) {
21303 uint64_t Res = ((x & Mask) << Shift) | ((x >> Shift) & Mask);
21315 const APInt &DemandedElts,
21317 unsigned Depth)
const {
21319 unsigned Opc =
Op.getOpcode();
21324 "Should use MaskedValueIsZero if you don't know whether Op"
21325 " is a target node!");
21330 case RISCVISD::SELECT_CC: {
21341 case RISCVISD::VCPOP_VL: {
21346 case RISCVISD::CZERO_EQZ:
21347 case RISCVISD::CZERO_NEZ:
21353 case RISCVISD::REMUW: {
21363 case RISCVISD::DIVUW: {
21373 case RISCVISD::SLLW: {
21382 case RISCVISD::CTZW: {
21389 case RISCVISD::CLZW: {
21396 case RISCVISD::BREV8:
21397 case RISCVISD::ORC_B: {
21401 bool IsGORC =
Op.getOpcode() == RISCVISD::ORC_B;
21409 case RISCVISD::READ_VLENB: {
21414 assert(MinVLenB > 0 &&
"READ_VLENB without vector extension enabled?");
21417 if (MaxVLenB == MinVLenB)
21421 case RISCVISD::FCLASS: {
21434 case Intrinsic::riscv_vsetvli:
21435 case Intrinsic::riscv_vsetvlimax: {
21436 bool HasAVL = IntNo == Intrinsic::riscv_vsetvli;
21437 unsigned VSEW =
Op.getConstantOperandVal(HasAVL + 1);
21443 MaxVL = (Fractional) ? MaxVL / LMul : MaxVL * LMul;
21446 if (HasAVL && isa<ConstantSDNode>(
Op.getOperand(1)))
21447 MaxVL = std::min(MaxVL,
Op.getConstantOperandVal(1));
21449 unsigned KnownZeroFirstBit =
Log2_32(MaxVL) + 1;
21462 unsigned Depth)
const {
21463 switch (
Op.getOpcode()) {
21466 case RISCVISD::SELECT_CC: {
21469 if (Tmp == 1)
return 1;
21472 return std::min(Tmp, Tmp2);
21474 case RISCVISD::CZERO_EQZ:
21475 case RISCVISD::CZERO_NEZ:
21479 case RISCVISD::ABSW: {
21484 if (Tmp < 33)
return 1;
21487 case RISCVISD::SRAW: {
21494 return std::max(Tmp, 33U);
21496 case RISCVISD::SLLW:
21497 case RISCVISD::SRLW:
21498 case RISCVISD::DIVW:
21499 case RISCVISD::DIVUW:
21500 case RISCVISD::REMUW:
21501 case RISCVISD::ROLW:
21502 case RISCVISD::RORW:
21503 case RISCVISD::FCVT_W_RV64:
21504 case RISCVISD::FCVT_WU_RV64:
21505 case RISCVISD::STRICT_FCVT_W_RV64:
21506 case RISCVISD::STRICT_FCVT_WU_RV64:
21509 case RISCVISD::VMV_X_S: {
21515 unsigned XLen = Subtarget.
getXLen();
21516 unsigned EltBits =
Op.getOperand(0).getScalarValueSizeInBits();
21517 if (EltBits <= XLen)
21518 return XLen - EltBits + 1;
21522 unsigned IntNo =
Op.getConstantOperandVal(1);
21526 case Intrinsic::riscv_masked_atomicrmw_xchg:
21527 case Intrinsic::riscv_masked_atomicrmw_add:
21528 case Intrinsic::riscv_masked_atomicrmw_sub:
21529 case Intrinsic::riscv_masked_atomicrmw_nand:
21530 case Intrinsic::riscv_masked_atomicrmw_max:
21531 case Intrinsic::riscv_masked_atomicrmw_min:
21532 case Intrinsic::riscv_masked_atomicrmw_umax:
21533 case Intrinsic::riscv_masked_atomicrmw_umin:
21534 case Intrinsic::riscv_masked_cmpxchg:
21541 assert(Subtarget.hasStdExtA());
21542 return Op.getValueSizeInBits() - 31;
21554 unsigned Depth)
const {
21557 switch (
Op.getOpcode()) {
21558 case RISCVISD::BREV8:
21559 case RISCVISD::ORC_B: {
21561 bool IsGORC =
Op.getOpcode() == RISCVISD::ORC_B;
21569 OriginalDemandedElts, Known2, TLO,
Depth + 1))
21581 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
21589 switch (
Op.getOpcode()) {
21590 case RISCVISD::SLLW:
21591 case RISCVISD::SRAW:
21592 case RISCVISD::SRLW:
21593 case RISCVISD::RORW:
21594 case RISCVISD::ROLW:
21598 case RISCVISD::SELECT_CC:
21600 assert(
Op.getOperand(0).getValueType().isInteger() &&
21601 "RISCVISD::SELECT_CC only compares integers");
21610 assert(Ld &&
"Unexpected null LoadSDNode");
21618 auto *CNode = dyn_cast<ConstantPoolSDNode>(
Ptr);
21619 if (!CNode || CNode->isMachineConstantPoolEntry() ||
21620 CNode->getOffset() != 0)
21627 if (
Ptr.getOpcode() == RISCVISD::LLA) {
21628 auto *CNode = GetSupportedConstantPool(
Ptr.getOperand(0));
21629 if (!CNode || CNode->getTargetFlags() != 0)
21632 return CNode->getConstVal();
21636 if (
Ptr.getOpcode() != RISCVISD::ADD_LO ||
21637 Ptr.getOperand(0).getOpcode() != RISCVISD::HI)
21640 auto *CNodeLo = GetSupportedConstantPool(
Ptr.getOperand(1));
21641 auto *CNodeHi = GetSupportedConstantPool(
Ptr.getOperand(0).getOperand(0));
21647 if (CNodeLo->getConstVal() != CNodeHi->getConstVal())
21650 return CNodeLo->getConstVal();
21655 assert(
MI.getOpcode() == RISCV::ReadCounterWide &&
"Unexpected instruction");
21687 Register ReadAgainReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
21690 int64_t LoCounter =
MI.getOperand(2).getImm();
21691 int64_t HiCounter =
MI.getOperand(3).getImm();
21701 BuildMI(LoopMBB,
DL,
TII->get(RISCV::CSRRS), ReadAgainReg)
21713 MI.eraseFromParent();
21721 assert(
MI.getOpcode() == RISCV::SplitF64Pseudo &&
"Unexpected instruction");
21729 Register SrcReg =
MI.getOperand(2).getReg();
21749 MI.eraseFromParent();
21756 assert(
MI.getOpcode() == RISCV::BuildPairF64Pseudo &&
21757 "Unexpected instruction");
21763 Register DstReg =
MI.getOperand(0).getReg();
21786 MI.eraseFromParent();
21791 unsigned RelOpcode,
unsigned EqOpcode,
21794 Register DstReg =
MI.getOperand(0).getReg();
21795 Register Src1Reg =
MI.getOperand(1).getReg();
21796 Register Src2Reg =
MI.getOperand(2).getReg();
21798 Register SavedFFlags =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
21822 MI.eraseFromParent();
21873 F->insert(It, FirstMBB);
21874 F->insert(It, SecondMBB);
21875 F->insert(It, SinkMBB);
21925 First.eraseFromParent();
21964 if (
MI.getOpcode() != RISCV::Select_GPR_Using_CC_GPR &&
21965 MI.getOperand(1).isReg() &&
MI.getOperand(2).isReg() &&
21966 Next != BB->
end() && Next->getOpcode() ==
MI.getOpcode() &&
21967 Next->getOperand(5).getReg() ==
MI.getOperand(0).getReg() &&
21968 Next->getOperand(5).isKill())
21973 if (
MI.getOperand(2).isReg())
21974 RHS =
MI.getOperand(2).getReg();
21979 SelectDests.
insert(
MI.getOperand(0).getReg());
21983 SequenceMBBI != E; ++SequenceMBBI) {
21984 if (SequenceMBBI->isDebugInstr())
21986 if (RISCVInstrInfo::isSelectPseudo(*SequenceMBBI)) {
21987 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
21988 !SequenceMBBI->getOperand(2).isReg() ||
21989 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
21990 SequenceMBBI->getOperand(3).getImm() != CC ||
21991 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
21992 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
21994 LastSelectPseudo = &*SequenceMBBI;
21996 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
21999 if (SequenceMBBI->hasUnmodeledSideEffects() ||
22000 SequenceMBBI->mayLoadOrStore() ||
22001 SequenceMBBI->usesCustomInsertionHook())
22004 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
22019 F->insert(
I, IfFalseMBB);
22020 F->insert(
I, TailMBB);
22023 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
22029 TailMBB->
push_back(DebugInstr->removeFromParent());
22033 TailMBB->
splice(TailMBB->
end(), HeadMBB,
22043 if (
MI.getOperand(2).isImm())
22046 .
addImm(
MI.getOperand(2).getImm())
22058 auto SelectMBBI =
MI.getIterator();
22059 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
22061 while (SelectMBBI != SelectEnd) {
22062 auto Next = std::next(SelectMBBI);
22063 if (RISCVInstrInfo::isSelectPseudo(*SelectMBBI)) {
22066 TII.get(RISCV::PHI), SelectMBBI->getOperand(0).getReg())
22067 .
addReg(SelectMBBI->getOperand(4).getReg())
22069 .
addReg(SelectMBBI->getOperand(5).getReg())
22076 F->getProperties().resetNoPHIs();
22084 RISCVVInversePseudosTable::getBaseInfo(MCOpcode, LMul, SEW);
22085 assert(
Inverse &&
"Unexpected LMUL and SEW pair for instruction");
22087 RISCV::lookupMaskedIntrinsicByUnmasked(
Inverse->Pseudo);
22088 assert(
Masked &&
"Could not find masked instruction for LMUL and SEW pair");
22094 unsigned CVTXOpc) {
22100 Register SavedFFLAGS =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22113 .
add(
MI.getOperand(1))
22114 .
add(
MI.getOperand(2))
22115 .
add(
MI.getOperand(3))
22117 .
add(
MI.getOperand(4))
22118 .
add(
MI.getOperand(5))
22119 .
add(
MI.getOperand(6))
22134 .
add(
MI.getOperand(0))
22135 .
add(
MI.getOperand(1))
22137 .
add(
MI.getOperand(3))
22139 .
add(
MI.getOperand(4))
22140 .
add(
MI.getOperand(5))
22141 .
add(
MI.getOperand(6))
22151 MI.eraseFromParent();
22157 unsigned CmpOpc, F2IOpc, I2FOpc, FSGNJOpc, FSGNJXOpc;
22159 switch (
MI.getOpcode()) {
22162 case RISCV::PseudoFROUND_H:
22163 CmpOpc = RISCV::FLT_H;
22164 F2IOpc = RISCV::FCVT_W_H;
22165 I2FOpc = RISCV::FCVT_H_W;
22166 FSGNJOpc = RISCV::FSGNJ_H;
22167 FSGNJXOpc = RISCV::FSGNJX_H;
22168 RC = &RISCV::FPR16RegClass;
22170 case RISCV::PseudoFROUND_H_INX:
22171 CmpOpc = RISCV::FLT_H_INX;
22172 F2IOpc = RISCV::FCVT_W_H_INX;
22173 I2FOpc = RISCV::FCVT_H_W_INX;
22174 FSGNJOpc = RISCV::FSGNJ_H_INX;
22175 FSGNJXOpc = RISCV::FSGNJX_H_INX;
22176 RC = &RISCV::GPRF16RegClass;
22178 case RISCV::PseudoFROUND_S:
22179 CmpOpc = RISCV::FLT_S;
22180 F2IOpc = RISCV::FCVT_W_S;
22181 I2FOpc = RISCV::FCVT_S_W;
22182 FSGNJOpc = RISCV::FSGNJ_S;
22183 FSGNJXOpc = RISCV::FSGNJX_S;
22184 RC = &RISCV::FPR32RegClass;
22186 case RISCV::PseudoFROUND_S_INX:
22187 CmpOpc = RISCV::FLT_S_INX;
22188 F2IOpc = RISCV::FCVT_W_S_INX;
22189 I2FOpc = RISCV::FCVT_S_W_INX;
22190 FSGNJOpc = RISCV::FSGNJ_S_INX;
22191 FSGNJXOpc = RISCV::FSGNJX_S_INX;
22192 RC = &RISCV::GPRF32RegClass;
22194 case RISCV::PseudoFROUND_D:
22196 CmpOpc = RISCV::FLT_D;
22197 F2IOpc = RISCV::FCVT_L_D;
22198 I2FOpc = RISCV::FCVT_D_L;
22199 FSGNJOpc = RISCV::FSGNJ_D;
22200 FSGNJXOpc = RISCV::FSGNJX_D;
22201 RC = &RISCV::FPR64RegClass;
22203 case RISCV::PseudoFROUND_D_INX:
22205 CmpOpc = RISCV::FLT_D_INX;
22206 F2IOpc = RISCV::FCVT_L_D_INX;
22207 I2FOpc = RISCV::FCVT_D_L_INX;
22208 FSGNJOpc = RISCV::FSGNJ_D_INX;
22209 FSGNJXOpc = RISCV::FSGNJX_D_INX;
22210 RC = &RISCV::GPRRegClass;
22222 F->insert(
I, CvtMBB);
22223 F->insert(
I, DoneMBB);
22234 Register DstReg =
MI.getOperand(0).getReg();
22235 Register SrcReg =
MI.getOperand(1).getReg();
22236 Register MaxReg =
MI.getOperand(2).getReg();
22237 int64_t FRM =
MI.getOperand(3).getImm();
22242 Register FabsReg =
MRI.createVirtualRegister(RC);
22246 Register CmpReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22261 Register F2IReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22283 MI.eraseFromParent();
22290 switch (
MI.getOpcode()) {
22293 case RISCV::ReadCounterWide:
22295 "ReadCounterWide is only to be used on riscv32");
22297 case RISCV::Select_GPR_Using_CC_GPR:
22298 case RISCV::Select_GPR_Using_CC_SImm5_CV:
22299 case RISCV::Select_GPRNoX0_Using_CC_SImm5NonZero_QC:
22300 case RISCV::Select_GPRNoX0_Using_CC_UImm5NonZero_QC:
22301 case RISCV::Select_GPRNoX0_Using_CC_SImm16NonZero_QC:
22302 case RISCV::Select_GPRNoX0_Using_CC_UImm16NonZero_QC:
22303 case RISCV::Select_GPR_Using_CC_UImmLog2XLen_NDS:
22304 case RISCV::Select_GPR_Using_CC_UImm7_NDS:
22305 case RISCV::Select_FPR16_Using_CC_GPR:
22306 case RISCV::Select_FPR16INX_Using_CC_GPR:
22307 case RISCV::Select_FPR32_Using_CC_GPR:
22308 case RISCV::Select_FPR32INX_Using_CC_GPR:
22309 case RISCV::Select_FPR64_Using_CC_GPR:
22310 case RISCV::Select_FPR64INX_Using_CC_GPR:
22311 case RISCV::Select_FPR64IN32X_Using_CC_GPR:
22313 case RISCV::BuildPairF64Pseudo:
22315 case RISCV::SplitF64Pseudo:
22317 case RISCV::PseudoQuietFLE_H:
22319 case RISCV::PseudoQuietFLE_H_INX:
22320 return emitQuietFCMP(
MI, BB, RISCV::FLE_H_INX, RISCV::FEQ_H_INX, Subtarget);
22321 case RISCV::PseudoQuietFLT_H:
22323 case RISCV::PseudoQuietFLT_H_INX:
22324 return emitQuietFCMP(
MI, BB, RISCV::FLT_H_INX, RISCV::FEQ_H_INX, Subtarget);
22325 case RISCV::PseudoQuietFLE_S:
22327 case RISCV::PseudoQuietFLE_S_INX:
22328 return emitQuietFCMP(
MI, BB, RISCV::FLE_S_INX, RISCV::FEQ_S_INX, Subtarget);
22329 case RISCV::PseudoQuietFLT_S:
22331 case RISCV::PseudoQuietFLT_S_INX:
22332 return emitQuietFCMP(
MI, BB, RISCV::FLT_S_INX, RISCV::FEQ_S_INX, Subtarget);
22333 case RISCV::PseudoQuietFLE_D:
22335 case RISCV::PseudoQuietFLE_D_INX:
22336 return emitQuietFCMP(
MI, BB, RISCV::FLE_D_INX, RISCV::FEQ_D_INX, Subtarget);
22337 case RISCV::PseudoQuietFLE_D_IN32X:
22340 case RISCV::PseudoQuietFLT_D:
22342 case RISCV::PseudoQuietFLT_D_INX:
22343 return emitQuietFCMP(
MI, BB, RISCV::FLT_D_INX, RISCV::FEQ_D_INX, Subtarget);
22344 case RISCV::PseudoQuietFLT_D_IN32X:
22348 case RISCV::PseudoVFROUND_NOEXCEPT_V_M1_MASK:
22350 case RISCV::PseudoVFROUND_NOEXCEPT_V_M2_MASK:
22352 case RISCV::PseudoVFROUND_NOEXCEPT_V_M4_MASK:
22354 case RISCV::PseudoVFROUND_NOEXCEPT_V_M8_MASK:
22356 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF2_MASK:
22358 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF4_MASK:
22360 case RISCV::PseudoFROUND_H:
22361 case RISCV::PseudoFROUND_H_INX:
22362 case RISCV::PseudoFROUND_S:
22363 case RISCV::PseudoFROUND_S_INX:
22364 case RISCV::PseudoFROUND_D:
22365 case RISCV::PseudoFROUND_D_INX:
22366 case RISCV::PseudoFROUND_D_IN32X:
22368 case RISCV::PROBED_STACKALLOC_DYN:
22370 case TargetOpcode::STATEPOINT:
22376 MI.addOperand(*
MI.getMF(),
22382 case TargetOpcode::STACKMAP:
22383 case TargetOpcode::PATCHPOINT:
22386 "supported on 64-bit targets");
22396 if (
auto *FRMDef =
MI.findRegisterDefOperand(RISCV::FRM,
nullptr)) {
22397 FRMDef->setIsDead(
false);
22401 int Idx = RISCV::getNamedOperandIdx(
MI.getOpcode(), RISCV::OpName::frm);
22411 if (
MI.readsRegister(RISCV::FRM,
nullptr))
22417void RISCVTargetLowering::analyzeInputArgs(
22434void RISCVTargetLowering::analyzeOutputArgs(
22439 MVT ArgVT = Out.VT;
22461 return DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, Val);
22495 if (In.isOrigArg()) {
22500 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
22501 (
BitWidth < 32 && In.Flags.isZExt())) {
22522 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, LocVT, Val);
22523 if (LocVT == MVT::i64 && VA.
getValVT() == MVT::f32)
22524 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Val);
22572 ExtType,
DL, LocVT, Chain, FIN,
22589 Register LoVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
22602 Register HiVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
22606 return DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64,
Lo,
Hi);
22617 switch (CallConv) {
22626#define CC_VLS_CASE(ABI_VLEN) case CallingConv::RISCV_VLSCall_##ABI_VLEN:
22642 if (Subtarget.hasStdExtE())
22646 "(Zdinx/D) instruction set extensions");
22650 if (Func.hasFnAttribute(
"interrupt")) {
22651 if (!Func.arg_empty())
22653 "Functions with the interrupt attribute cannot have arguments!");
22664 "SiFive-CLIC-preemptible",
22665 "SiFive-CLIC-stack-swap",
22666 "SiFive-CLIC-preemptible-stack-swap",
22670 "Function interrupt attribute argument not supported!");
22672 if (Kind.starts_with(
"qci-") && !Subtarget.hasVendorXqciint())
22674 "'qci-*' interrupt kinds require Xqciint extension");
22676 if (Kind.starts_with(
"SiFive-CLIC-") && !Subtarget.hasVendorXSfmclic())
22678 "'SiFive-CLIC-*' interrupt kinds require XSfmclic extension");
22680 if (Kind ==
"rnmi" && !Subtarget.hasStdExtSmrnmi())
22683 if (Kind.starts_with(
"SiFive-CLIC-preemptible") && TFI->
hasFP(MF))
22685 "have a frame pointer");
22690 unsigned XLenInBytes = Subtarget.
getXLen() / 8;
22692 std::vector<SDValue> OutChains;
22701 analyzeInputArgs(MF, CCInfo, Ins,
false,
22705 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
22726 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
22727 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
22729 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
22731 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
22760 int VarArgsSaveSize = XLenInBytes * (ArgRegs.
size() -
Idx);
22765 if (VarArgsSaveSize == 0) {
22769 int VaArgOffset = -VarArgsSaveSize;
22777 XLenInBytes, VaArgOffset -
static_cast<int>(XLenInBytes),
true);
22778 VarArgsSaveSize += XLenInBytes;
22785 for (
unsigned I =
Idx;
I < ArgRegs.
size(); ++
I) {
22790 Chain,
DL, ArgValue, FIN,
22792 OutChains.push_back(Store);
22806 if (!OutChains.empty()) {
22807 OutChains.push_back(Chain);
22817bool RISCVTargetLowering::isEligibleForTailCallOptimization(
22821 auto CalleeCC = CLI.CallConv;
22822 auto &Outs = CLI.Outs;
22824 auto CallerCC = Caller.getCallingConv();
22831 if (Caller.hasFnAttribute(
"interrupt"))
22846 for (
auto &VA : ArgLocs)
22852 auto IsCallerStructRet = Caller.hasStructRetAttr();
22853 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
22854 if (IsCallerStructRet || IsCalleeStructRet)
22859 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
22860 if (CalleeCC != CallerCC) {
22861 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
22862 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
22869 for (
auto &Arg : Outs)
22870 if (Arg.Flags.isByVal())
22911 if (Subtarget.hasStdExtE())
22915 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
22921 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
22927 "call site marked musttail");
22934 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
22936 if (!Flags.isByVal())
22940 unsigned Size = Flags.getByValSize();
22941 Align Alignment = Flags.getNonZeroByValAlign();
22948 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
22950 false,
nullptr, IsTailCall,
22962 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
22965 SDValue ArgValue = OutVals[OutIdx];
22973 RISCVISD::SplitF64,
DL, DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
22985 if (!StackPtr.getNode())
22997 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
23015 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
23016 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
23022 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
23023 SDValue PartValue = OutVals[OutIdx + 1];
23024 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
23036 int FI = cast<FrameIndexSDNode>(SpillSlot)->getIndex();
23038 DAG.
getStore(Chain,
DL, ArgValue, SpillSlot,
23040 for (
const auto &Part : Parts) {
23041 SDValue PartValue = Part.first;
23042 SDValue PartOffset = Part.second;
23049 ArgValue = SpillSlot;
23055 if (Flags.isByVal())
23056 ArgValue = ByValArgs[j++];
23063 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
23064 "for passing parameters");
23067 if (!StackPtr.getNode())
23081 if (!MemOpChains.
empty())
23087 for (
auto &Reg : RegsToPass) {
23088 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
23095 validateCCReservedRegs(RegsToPass, MF);
23099 "Return address register required, but has been reserved."});
23104 bool CalleeIsLargeExternalSymbol =
false;
23106 if (
auto *S = dyn_cast<GlobalAddressSDNode>(Callee))
23108 else if (
auto *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
23110 CalleeIsLargeExternalSymbol =
true;
23126 for (
auto &Reg : RegsToPass)
23131 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
23132 assert(Mask &&
"Missing call preserved mask for calling convention");
23140 "Unexpected CFI type for a direct call");
23148 bool NeedSWGuarded =
false;
23150 Subtarget.hasStdExtZicfilp() &&
23152 NeedSWGuarded =
true;
23157 NeedSWGuarded ? RISCVISD::SW_GUARDED_TAIL : RISCVISD::TAIL;
23168 unsigned CallOpc = NeedSWGuarded ? RISCVISD::SW_GUARDED_CALL : RISCVISD::CALL;
23169 Chain = DAG.
getNode(CallOpc,
DL, NodeTys, Ops);
23186 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_RISCV);
23189 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
23190 auto &VA = RVLocs[i];
23198 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
23199 assert(VA.needsCustom());
23204 RetValue = DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64, RetValue,
23222 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
23223 MVT VT = Outs[i].VT;
23226 true, Outs[i].OrigTy))
23258 for (
unsigned i = 0, e = RVLocs.size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
23259 SDValue Val = OutVals[OutIdx];
23268 DAG.
getVTList(MVT::i32, MVT::i32), Val);
23272 Register RegHi = RVLocs[++i].getLocReg();
23278 "Return value register required, but has been reserved."});
23294 "Return value register required, but has been reserved."});
23313 unsigned RetOpc = RISCVISD::RET_GLUE;
23316 if (Func.hasFnAttribute(
"interrupt")) {
23317 if (!Func.getReturnType()->isVoidTy())
23319 "Functions with the interrupt attribute must have void return type!");
23325 if (Kind ==
"supervisor")
23326 RetOpc = RISCVISD::SRET_GLUE;
23327 else if (Kind ==
"rnmi") {
23328 assert(STI.hasFeature(RISCV::FeatureStdExtSmrnmi) &&
23329 "Need Smrnmi extension for rnmi");
23330 RetOpc = RISCVISD::MNRET_GLUE;
23331 }
else if (Kind ==
"qci-nest" || Kind ==
"qci-nonest") {
23332 assert(STI.hasFeature(RISCV::FeatureVendorXqciint) &&
23333 "Need Xqciint for qci-(no)nest");
23334 RetOpc = RISCVISD::QC_C_MILEAVERET_GLUE;
23336 RetOpc = RISCVISD::MRET_GLUE;
23339 return DAG.
getNode(RetOpc,
DL, MVT::Other, RetOps);
23342void RISCVTargetLowering::validateCCReservedRegs(
23343 const SmallVectorImpl<std::pair<llvm::Register, llvm::SDValue>> &Regs,
23352 F,
"Argument register required, but has been reserved."});
23358 if (
N->getNumValues() != 1)
23360 if (!
N->hasNUsesOfValue(1, 0))
23363 SDNode *Copy = *
N->user_begin();
23377 if (Copy->getOperand(Copy->getNumOperands() - 1).getValueType() == MVT::Glue)
23381 bool HasRet =
false;
23382 for (
SDNode *Node : Copy->users()) {
23383 if (Node->getOpcode() != RISCVISD::RET_GLUE)
23390 Chain = Copy->getOperand(0);
23402 if (Constraint.
size() == 1) {
23403 switch (Constraint[0]) {
23420 if (Constraint ==
"vr" || Constraint ==
"vd" || Constraint ==
"vm")
23422 if (Constraint ==
"cr" || Constraint ==
"cR" || Constraint ==
"cf")
23428std::pair<unsigned, const TargetRegisterClass *>
23434 if (Constraint.
size() == 1) {
23435 switch (Constraint[0]) {
23440 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
23441 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
23442 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
23443 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
23444 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
23445 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23446 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
23448 if (VT == MVT::f16) {
23449 if (Subtarget.hasStdExtZfhmin())
23450 return std::make_pair(0U, &RISCV::FPR16RegClass);
23451 if (Subtarget.hasStdExtZhinxmin())
23452 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
23453 }
else if (VT == MVT::f32) {
23454 if (Subtarget.hasStdExtF())
23455 return std::make_pair(0U, &RISCV::FPR32RegClass);
23456 if (Subtarget.hasStdExtZfinx())
23457 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
23458 }
else if (VT == MVT::f64) {
23459 if (Subtarget.hasStdExtD())
23460 return std::make_pair(0U, &RISCV::FPR64RegClass);
23461 if (Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
23462 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23463 if (Subtarget.hasStdExtZdinx() && Subtarget.
is64Bit())
23464 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
23468 if (((VT == MVT::i64 || VT == MVT::f64) && !Subtarget.
is64Bit()) ||
23469 (VT == MVT::i128 && Subtarget.
is64Bit()))
23470 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23475 }
else if (Constraint ==
"vr") {
23476 for (
const auto *RC :
23477 {&RISCV::VRRegClass, &RISCV::VRM2RegClass, &RISCV::VRM4RegClass,
23478 &RISCV::VRM8RegClass, &RISCV::VRN2M1RegClass, &RISCV::VRN3M1RegClass,
23479 &RISCV::VRN4M1RegClass, &RISCV::VRN5M1RegClass,
23480 &RISCV::VRN6M1RegClass, &RISCV::VRN7M1RegClass,
23481 &RISCV::VRN8M1RegClass, &RISCV::VRN2M2RegClass,
23482 &RISCV::VRN3M2RegClass, &RISCV::VRN4M2RegClass,
23483 &RISCV::VRN2M4RegClass}) {
23485 return std::make_pair(0U, RC);
23489 if (
TRI->isTypeLegalForClass(*RC, ContainerVT))
23490 return std::make_pair(0U, RC);
23493 }
else if (Constraint ==
"vd") {
23494 for (
const auto *RC :
23495 {&RISCV::VRNoV0RegClass, &RISCV::VRM2NoV0RegClass,
23496 &RISCV::VRM4NoV0RegClass, &RISCV::VRM8NoV0RegClass,
23497 &RISCV::VRN2M1NoV0RegClass, &RISCV::VRN3M1NoV0RegClass,
23498 &RISCV::VRN4M1NoV0RegClass, &RISCV::VRN5M1NoV0RegClass,
23499 &RISCV::VRN6M1NoV0RegClass, &RISCV::VRN7M1NoV0RegClass,
23500 &RISCV::VRN8M1NoV0RegClass, &RISCV::VRN2M2NoV0RegClass,
23501 &RISCV::VRN3M2NoV0RegClass, &RISCV::VRN4M2NoV0RegClass,
23502 &RISCV::VRN2M4NoV0RegClass}) {
23504 return std::make_pair(0U, RC);
23508 if (
TRI->isTypeLegalForClass(*RC, ContainerVT))
23509 return std::make_pair(0U, RC);
23512 }
else if (Constraint ==
"vm") {
23513 if (
TRI->isTypeLegalForClass(RISCV::VMV0RegClass, VT.
SimpleTy))
23514 return std::make_pair(0U, &RISCV::VMV0RegClass);
23520 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, ContainerVT))
23521 return std::make_pair(0U, &RISCV::VMV0RegClass);
23523 }
else if (Constraint ==
"cr") {
23524 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
23525 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
23526 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
23527 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
23528 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
23529 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23531 return std::make_pair(0U, &RISCV::GPRCRegClass);
23532 }
else if (Constraint ==
"cR") {
23533 if (((VT == MVT::i64 || VT == MVT::f64) && !Subtarget.
is64Bit()) ||
23534 (VT == MVT::i128 && Subtarget.
is64Bit()))
23535 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23536 }
else if (Constraint ==
"cf") {
23537 if (VT == MVT::f16) {
23538 if (Subtarget.hasStdExtZfhmin())
23539 return std::make_pair(0U, &RISCV::FPR16CRegClass);
23540 if (Subtarget.hasStdExtZhinxmin())
23541 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
23542 }
else if (VT == MVT::f32) {
23543 if (Subtarget.hasStdExtF())
23544 return std::make_pair(0U, &RISCV::FPR32CRegClass);
23545 if (Subtarget.hasStdExtZfinx())
23546 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
23547 }
else if (VT == MVT::f64) {
23548 if (Subtarget.hasStdExtD())
23549 return std::make_pair(0U, &RISCV::FPR64CRegClass);
23550 if (Subtarget.hasStdExtZdinx() && !Subtarget.
is64Bit())
23551 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23552 if (Subtarget.hasStdExtZdinx() && Subtarget.
is64Bit())
23553 return std::make_pair(0U, &RISCV::GPRCRegClass);
23562 .
Case(
"{zero}", RISCV::X0)
23563 .
Case(
"{ra}", RISCV::X1)
23564 .
Case(
"{sp}", RISCV::X2)
23565 .
Case(
"{gp}", RISCV::X3)
23566 .
Case(
"{tp}", RISCV::X4)
23567 .
Case(
"{t0}", RISCV::X5)
23568 .
Case(
"{t1}", RISCV::X6)
23569 .
Case(
"{t2}", RISCV::X7)
23570 .
Cases(
"{s0}",
"{fp}", RISCV::X8)
23571 .
Case(
"{s1}", RISCV::X9)
23572 .
Case(
"{a0}", RISCV::X10)
23573 .
Case(
"{a1}", RISCV::X11)
23574 .
Case(
"{a2}", RISCV::X12)
23575 .
Case(
"{a3}", RISCV::X13)
23576 .
Case(
"{a4}", RISCV::X14)
23577 .
Case(
"{a5}", RISCV::X15)
23578 .
Case(
"{a6}", RISCV::X16)
23579 .
Case(
"{a7}", RISCV::X17)
23580 .
Case(
"{s2}", RISCV::X18)
23581 .
Case(
"{s3}", RISCV::X19)
23582 .
Case(
"{s4}", RISCV::X20)
23583 .
Case(
"{s5}", RISCV::X21)
23584 .
Case(
"{s6}", RISCV::X22)
23585 .
Case(
"{s7}", RISCV::X23)
23586 .
Case(
"{s8}", RISCV::X24)
23587 .
Case(
"{s9}", RISCV::X25)
23588 .
Case(
"{s10}", RISCV::X26)
23589 .
Case(
"{s11}", RISCV::X27)
23590 .
Case(
"{t3}", RISCV::X28)
23591 .
Case(
"{t4}", RISCV::X29)
23592 .
Case(
"{t5}", RISCV::X30)
23593 .
Case(
"{t6}", RISCV::X31)
23595 if (XRegFromAlias != RISCV::NoRegister)
23596 return std::make_pair(XRegFromAlias, &RISCV::GPRRegClass);
23605 if (Subtarget.hasStdExtF()) {
23607 .
Cases(
"{f0}",
"{ft0}", RISCV::F0_F)
23608 .
Cases(
"{f1}",
"{ft1}", RISCV::F1_F)
23609 .
Cases(
"{f2}",
"{ft2}", RISCV::F2_F)
23610 .
Cases(
"{f3}",
"{ft3}", RISCV::F3_F)
23611 .
Cases(
"{f4}",
"{ft4}", RISCV::F4_F)
23612 .
Cases(
"{f5}",
"{ft5}", RISCV::F5_F)
23613 .
Cases(
"{f6}",
"{ft6}", RISCV::F6_F)
23614 .
Cases(
"{f7}",
"{ft7}", RISCV::F7_F)
23615 .
Cases(
"{f8}",
"{fs0}", RISCV::F8_F)
23616 .
Cases(
"{f9}",
"{fs1}", RISCV::F9_F)
23617 .
Cases(
"{f10}",
"{fa0}", RISCV::F10_F)
23618 .
Cases(
"{f11}",
"{fa1}", RISCV::F11_F)
23619 .
Cases(
"{f12}",
"{fa2}", RISCV::F12_F)
23620 .
Cases(
"{f13}",
"{fa3}", RISCV::F13_F)
23621 .
Cases(
"{f14}",
"{fa4}", RISCV::F14_F)
23622 .
Cases(
"{f15}",
"{fa5}", RISCV::F15_F)
23623 .
Cases(
"{f16}",
"{fa6}", RISCV::F16_F)
23624 .
Cases(
"{f17}",
"{fa7}", RISCV::F17_F)
23625 .
Cases(
"{f18}",
"{fs2}", RISCV::F18_F)
23626 .
Cases(
"{f19}",
"{fs3}", RISCV::F19_F)
23627 .
Cases(
"{f20}",
"{fs4}", RISCV::F20_F)
23628 .
Cases(
"{f21}",
"{fs5}", RISCV::F21_F)
23629 .
Cases(
"{f22}",
"{fs6}", RISCV::F22_F)
23630 .
Cases(
"{f23}",
"{fs7}", RISCV::F23_F)
23631 .
Cases(
"{f24}",
"{fs8}", RISCV::F24_F)
23632 .
Cases(
"{f25}",
"{fs9}", RISCV::F25_F)
23633 .
Cases(
"{f26}",
"{fs10}", RISCV::F26_F)
23634 .
Cases(
"{f27}",
"{fs11}", RISCV::F27_F)
23635 .
Cases(
"{f28}",
"{ft8}", RISCV::F28_F)
23636 .
Cases(
"{f29}",
"{ft9}", RISCV::F29_F)
23637 .
Cases(
"{f30}",
"{ft10}", RISCV::F30_F)
23638 .
Cases(
"{f31}",
"{ft11}", RISCV::F31_F)
23640 if (FReg != RISCV::NoRegister) {
23641 assert(RISCV::F0_F <= FReg && FReg <= RISCV::F31_F &&
"Unknown fp-reg");
23642 if (Subtarget.hasStdExtD() && (VT == MVT::f64 || VT == MVT::Other)) {
23643 unsigned RegNo = FReg - RISCV::F0_F;
23644 unsigned DReg = RISCV::F0_D + RegNo;
23645 return std::make_pair(DReg, &RISCV::FPR64RegClass);
23647 if (VT == MVT::f32 || VT == MVT::Other)
23648 return std::make_pair(FReg, &RISCV::FPR32RegClass);
23649 if (Subtarget.hasStdExtZfhmin() && VT == MVT::f16) {
23650 unsigned RegNo = FReg - RISCV::F0_F;
23651 unsigned HReg = RISCV::F0_H + RegNo;
23652 return std::make_pair(HReg, &RISCV::FPR16RegClass);
23659 .
Case(
"{v0}", RISCV::V0)
23660 .
Case(
"{v1}", RISCV::V1)
23661 .
Case(
"{v2}", RISCV::V2)
23662 .
Case(
"{v3}", RISCV::V3)
23663 .
Case(
"{v4}", RISCV::V4)
23664 .
Case(
"{v5}", RISCV::V5)
23665 .
Case(
"{v6}", RISCV::V6)
23666 .
Case(
"{v7}", RISCV::V7)
23667 .
Case(
"{v8}", RISCV::V8)
23668 .
Case(
"{v9}", RISCV::V9)
23669 .
Case(
"{v10}", RISCV::V10)
23670 .
Case(
"{v11}", RISCV::V11)
23671 .
Case(
"{v12}", RISCV::V12)
23672 .
Case(
"{v13}", RISCV::V13)
23673 .
Case(
"{v14}", RISCV::V14)
23674 .
Case(
"{v15}", RISCV::V15)
23675 .
Case(
"{v16}", RISCV::V16)
23676 .
Case(
"{v17}", RISCV::V17)
23677 .
Case(
"{v18}", RISCV::V18)
23678 .
Case(
"{v19}", RISCV::V19)
23679 .
Case(
"{v20}", RISCV::V20)
23680 .
Case(
"{v21}", RISCV::V21)
23681 .
Case(
"{v22}", RISCV::V22)
23682 .
Case(
"{v23}", RISCV::V23)
23683 .
Case(
"{v24}", RISCV::V24)
23684 .
Case(
"{v25}", RISCV::V25)
23685 .
Case(
"{v26}", RISCV::V26)
23686 .
Case(
"{v27}", RISCV::V27)
23687 .
Case(
"{v28}", RISCV::V28)
23688 .
Case(
"{v29}", RISCV::V29)
23689 .
Case(
"{v30}", RISCV::V30)
23690 .
Case(
"{v31}", RISCV::V31)
23692 if (VReg != RISCV::NoRegister) {
23693 if (
TRI->isTypeLegalForClass(RISCV::VMRegClass, VT.
SimpleTy))
23694 return std::make_pair(VReg, &RISCV::VMRegClass);
23695 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, VT.
SimpleTy))
23696 return std::make_pair(VReg, &RISCV::VRRegClass);
23697 for (
const auto *RC :
23698 {&RISCV::VRM2RegClass, &RISCV::VRM4RegClass, &RISCV::VRM8RegClass}) {
23699 if (
TRI->isTypeLegalForClass(*RC, VT.
SimpleTy)) {
23700 VReg =
TRI->getMatchingSuperReg(VReg, RISCV::sub_vrm1_0, RC);
23701 return std::make_pair(VReg, RC);
23707 std::pair<Register, const TargetRegisterClass *> Res =
23713 if (Res.second == &RISCV::GPRF16RegClass ||
23714 Res.second == &RISCV::GPRF32RegClass ||
23715 Res.second == &RISCV::GPRPairRegClass)
23716 return std::make_pair(Res.first, &RISCV::GPRRegClass);
23724 if (ConstraintCode.
size() == 1) {
23725 switch (ConstraintCode[0]) {
23740 if (Constraint.
size() == 1) {
23741 switch (Constraint[0]) {
23744 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
23746 if (isInt<12>(CVal))
23759 if (
auto *
C = dyn_cast<ConstantSDNode>(
Op)) {
23761 if (isUInt<5>(CVal))
23779 if (Subtarget.hasStdExtZtso()) {
23795 if (Subtarget.hasStdExtZtso()) {
23803 if (Subtarget.enableTrailingSeqCstFence() && isa<StoreInst>(Inst) &&
23822 if (Subtarget.hasForcedAtomics())
23827 if (Subtarget.hasStdExtZacas() &&
23828 (
Size >= 32 || Subtarget.hasStdExtZabha()))
23834 if (
Size < 32 && !Subtarget.hasStdExtZabha())
23846 return Intrinsic::riscv_masked_atomicrmw_xchg;
23848 return Intrinsic::riscv_masked_atomicrmw_add;
23850 return Intrinsic::riscv_masked_atomicrmw_sub;
23852 return Intrinsic::riscv_masked_atomicrmw_nand;
23854 return Intrinsic::riscv_masked_atomicrmw_max;
23856 return Intrinsic::riscv_masked_atomicrmw_min;
23858 return Intrinsic::riscv_masked_atomicrmw_umax;
23860 return Intrinsic::riscv_masked_atomicrmw_umin;
23883 unsigned XLen = Subtarget.
getXLen();
23907 unsigned ValWidth =
23912 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
23915 Builder.
CreateCall(LrwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
23927 if (Subtarget.hasForcedAtomics())
23931 if (!(Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas()) &&
23940 unsigned XLen = Subtarget.
getXLen();
23942 Intrinsic::ID CmpXchgIntrID = Intrinsic::riscv_masked_cmpxchg;
23950 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, Ordering});
23957 EVT DataVT)
const {
23973 return Subtarget.hasStdExtZfhmin();
23975 return Subtarget.hasStdExtF();
23977 return Subtarget.hasStdExtD();
24009 "RVVBitsPerBlock changed, audit needed");
24018 if (!Subtarget.hasVendorXTHeadMemIdx())
24024 Base =
Op->getOperand(0);
24026 int64_t RHSC =
RHS->getSExtValue();
24032 bool isLegalIndexedOffset =
false;
24033 for (
unsigned i = 0; i < 4; i++)
24034 if (isInt<5>(RHSC >> i) && ((RHSC % (1LL << i)) == 0)) {
24035 isLegalIndexedOffset =
true;
24039 if (!isLegalIndexedOffset)
24056 VT = LD->getMemoryVT();
24057 Ptr = LD->getBasePtr();
24058 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
24059 VT = ST->getMemoryVT();
24060 Ptr = ST->getBasePtr();
24076 if (Subtarget.hasVendorXCVmem() && !Subtarget.
is64Bit()) {
24081 Base = LS->getBasePtr();
24085 if (
Base ==
Op->getOperand(0))
24087 else if (
Base ==
Op->getOperand(1))
24099 VT = LD->getMemoryVT();
24100 Ptr = LD->getBasePtr();
24101 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
24102 VT = ST->getMemoryVT();
24103 Ptr = ST->getBasePtr();
24146 const Constant *PersonalityFn)
const {
24151 const Constant *PersonalityFn)
const {
24166 bool IsSigned)
const {
24181 const bool HasZmmul = Subtarget.hasStdExtZmmul();
24185 auto *ConstNode = cast<ConstantSDNode>(
C);
24186 const APInt &Imm = ConstNode->getAPIntValue();
24189 if (Subtarget.hasVendorXqciac() && Imm.isSignedIntN(12))
24193 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
24194 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
24198 if (Subtarget.hasStdExtZba() && !Imm.isSignedIntN(12) &&
24199 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
24200 (Imm - 8).isPowerOf2()))
24205 if (!Imm.isSignedIntN(12) && Imm.countr_zero() < 12 &&
24206 ConstNode->hasOneUse()) {
24207 APInt ImmS = Imm.ashr(Imm.countr_zero());
24208 if ((ImmS + 1).isPowerOf2() || (ImmS - 1).isPowerOf2() ||
24209 (1 - ImmS).isPowerOf2())
24232 if (C1.
isSignedIntN(12) && !(C1 * C2).isSignedIntN(12))
24241 unsigned *
Fast)
const {
24244 *
Fast = Subtarget.enableUnalignedScalarMem();
24245 return Subtarget.enableUnalignedScalarMem();
24261 *
Fast = Subtarget.enableUnalignedVectorMem();
24262 return Subtarget.enableUnalignedVectorMem();
24271 if (FuncAttributes.
hasFnAttr(Attribute::NoImplicitFloat))
24283 const unsigned MinVLenInBytes =
24286 if (
Op.size() < MinVLenInBytes)
24301 MVT PreferredVT = (
Op.isMemset() && !
Op.isZeroMemset()) ? MVT::i8 : ELenVT;
24305 if (PreferredVT != MVT::i8 && !Subtarget.enableUnalignedVectorMem()) {
24307 if (
Op.isFixedDstAlign())
24308 RequiredAlign = std::min(RequiredAlign,
Op.getDstAlign());
24310 RequiredAlign = std::min(RequiredAlign,
Op.getSrcAlign());
24318 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
24319 bool IsABIRegCopy = CC.has_value();
24322 MVT PairVT = Subtarget.
is64Bit() ? MVT::i128 : MVT::i64;
24323 if ((ValueVT == PairVT ||
24324 (!Subtarget.
is64Bit() && Subtarget.hasStdExtZdinx() &&
24325 ValueVT == MVT::f64)) &&
24326 NumParts == 1 && PartVT == MVT::Untyped) {
24329 if (ValueVT == MVT::f64)
24334 Parts[0] = DAG.
getNode(RISCVISD::BuildGPRPair,
DL, PartVT,
Lo,
Hi);
24338 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
24339 PartVT == MVT::f32) {
24354 [[maybe_unused]]
unsigned ValLMUL =
24358 [[maybe_unused]]
unsigned PartLMUL =
24361 assert(ValNF == PartNF && ValLMUL == PartLMUL &&
24362 "RISC-V vector tuple type only accepts same register class type "
24383 if (PartVTBitSize % ValueVTBitSize == 0) {
24384 assert(PartVTBitSize >= ValueVTBitSize);
24391 if (ValueEltVT != PartEltVT) {
24392 if (PartVTBitSize > ValueVTBitSize) {
24394 assert(Count != 0 &&
"The number of element should not be zero.");
24395 EVT SameEltTypeVT =
24413 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
24414 bool IsABIRegCopy = CC.has_value();
24416 MVT PairVT = Subtarget.
is64Bit() ? MVT::i128 : MVT::i64;
24417 if ((ValueVT == PairVT ||
24418 (!Subtarget.
is64Bit() && Subtarget.hasStdExtZdinx() &&
24419 ValueVT == MVT::f64)) &&
24420 NumParts == 1 && PartVT == MVT::Untyped) {
24431 if (ValueVT == MVT::f64)
24436 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
24437 PartVT == MVT::f32) {
24459 if (PartVTBitSize % ValueVTBitSize == 0) {
24460 assert(PartVTBitSize >= ValueVTBitSize);
24461 EVT SameEltTypeVT = ValueVT;
24468 if (ValueEltVT != PartEltVT) {
24470 assert(Count != 0 &&
"The number of element should not be zero.");
24489 bool OptSize = Attr.
hasFnAttr(Attribute::MinSize);
24496 unsigned Opc =
N->getOpcode();
24505 M, Intrinsic::thread_pointer, IRB.
getPtrTy());
24524 if (M->getStackProtectorGuard() ==
"tls") {
24526 int Offset = M->getStackProtectorGuardOffset();
24534 Align Alignment)
const {
24546 if (!Subtarget.enableUnalignedVectorMem() &&
24558 "Invalid call instruction for a KCFI check");
24560 MBBI->getOpcode()));
24563 Target.setIsRenamable(
false);
24571#define GET_REGISTER_MATCHER
24572#include "RISCVGenAsmMatcher.inc"
24592 const MDNode *NontemporalInfo =
I.getMetadata(LLVMContext::MD_nontemporal);
24594 if (NontemporalInfo ==
nullptr)
24602 int NontemporalLevel = 5;
24603 const MDNode *RISCVNontemporalInfo =
24604 I.getMetadata(
"riscv-nontemporal-domain");
24605 if (RISCVNontemporalInfo !=
nullptr)
24608 cast<ConstantAsMetadata>(RISCVNontemporalInfo->
getOperand(0))
24612 assert((1 <= NontemporalLevel && NontemporalLevel <= 5) &&
24613 "RISC-V target doesn't support this non-temporal domain.");
24615 NontemporalLevel -= 2;
24617 if (NontemporalLevel & 0b1)
24619 if (NontemporalLevel & 0b10)
24632 return TargetFlags;
24642 return isTypeLegal(VT) && Subtarget.hasStdExtZvbb();
24645 return Subtarget.hasStdExtZbb() &&
24656 if (Subtarget.hasStdExtZalasr()) {
24657 if (Subtarget.hasStdExtZtso()) {
24662 auto *LI = dyn_cast<LoadInst>(
I);
24663 auto *SI = dyn_cast<StoreInst>(
I);
24673 return isa<LoadInst>(
I) || isa<StoreInst>(
I);
24680 return isa<LoadInst>(
I) || isa<StoreInst>(
I);
24687 if (
Op == Instruction::Add ||
Op == Instruction::Sub ||
24688 Op == Instruction::And ||
Op == Instruction::Or ||
24689 Op == Instruction::Xor ||
Op == Instruction::InsertElement ||
24690 Op == Instruction::ShuffleVector ||
Op == Instruction::Load ||
24691 Op == Instruction::Freeze ||
Op == Instruction::Store)
24699 !isa<ReturnInst>(&Inst))
24702 if (
const AllocaInst *AI = dyn_cast<AllocaInst>(&Inst)) {
24703 if (AI->getAllocatedType()->isScalableTy())
24711RISCVTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
24719 if (!Subtarget.hasShortForwardBranchOpt())
24721 EVT VT =
N->getValueType(0);
24722 if (!(VT == MVT::i32 || (VT == MVT::i64 && Subtarget.
is64Bit())))
24726 if (Divisor.
sgt(2048) || Divisor.
slt(-2048))
24731bool RISCVTargetLowering::shouldFoldSelectWithSingleBitTest(
24732 EVT VT,
const APInt &AndMask)
const {
24733 if (Subtarget.hasStdExtZicond() || Subtarget.hasVendorXVentanaCondOps())
24734 return !Subtarget.hasStdExtZbs() && AndMask.
ugt(1024);
24738unsigned RISCVTargetLowering::getMinimumJumpTableEntries()
const {
24746 if (Subtarget.hasStdExtZicfilp()) {
24753 return DAG.
getNode(RISCVISD::SW_GUARDED_BRIND, dl, MVT::Other, Chain,
Addr);
24770std::pair<const TargetRegisterClass *, uint8_t>
24790#define GET_RISCVVIntrinsicsTable_IMPL
24791#include "RISCVGenSearchableTables.inc"
24806 Align StackAlign)
const {
24810 unsigned StackProbeSize =
24814 return StackProbeSize ? StackProbeSize : StackAlign.
value();
24829 cast<ConstantSDNode>(
Op.getOperand(2))->getMaybeAlignValue();
24831 EVT VT =
Op.getValueType();
24835 Chain = SP.getValue(1);
24842 Chain = DAG.
getNode(RISCVISD::PROBED_ALLOCA, dl, MVT::Other, Chain, SP);
24852 Register TargetReg =
MI.getOperand(0).getReg();
24855 bool IsRV64 = Subtarget.
is64Bit();
24863 MF.
insert(MBBInsertPoint, LoopTestMBB);
24865 MF.
insert(MBBInsertPoint, ExitMBB);
24881 TII->get(IsRV64 ? RISCV::SD : RISCV::SW))
24904 MI.eraseFromParent();
24906 return ExitMBB->
begin()->getParent();
24911 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.
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 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)