42#include "llvm/IR/IntrinsicsRISCV.h"
56#define DEBUG_TYPE "riscv-lower"
62 cl::desc(
"Give the maximum size (in number of nodes) of the web of "
63 "instructions that we will consider for VW expansion"),
68 cl::desc(
"Allow the formation of VW_W operations (e.g., "
69 "VWADD_W) with splat constants"),
74 cl::desc(
"Set the minimum number of repetitions of a divisor to allow "
75 "transformation to multiplications by the reciprocal"),
80 cl::desc(
"Give the maximum number of instructions that we will "
81 "use for creating a floating-point immediate value"),
86 cl::desc(
"Swap add and addi in cases where the add may "
87 "be combined with a shift"),
92 ISD::VP_FNEG, ISD::VP_FABS, ISD::VP_FCOPYSIGN};
105 !Subtarget.hasStdExtF()) {
106 errs() <<
"Hard-float 'f' ABI can't be used for a target that "
107 "doesn't support the F instruction set extension (ignoring "
111 !Subtarget.hasStdExtD()) {
112 errs() <<
"Hard-float 'd' ABI can't be used for a target that "
113 "doesn't support the D instruction set extension (ignoring "
132 MVT XLenVT = Subtarget.getXLenVT();
137 if (Subtarget.hasStdExtZfhmin())
139 if (Subtarget.hasStdExtZfbfmin() || Subtarget.hasVendorXAndesBFHCvt())
141 if (Subtarget.hasStdExtF())
143 if (Subtarget.hasStdExtD())
145 if (Subtarget.hasStdExtZhinxmin())
147 if (Subtarget.hasStdExtZfinx())
149 if (Subtarget.hasStdExtZdinx()) {
150 if (Subtarget.is64Bit())
157 MVT::nxv1i1, MVT::nxv2i1, MVT::nxv4i1, MVT::nxv8i1,
158 MVT::nxv16i1, MVT::nxv32i1, MVT::nxv64i1};
160 MVT::nxv1i8, MVT::nxv2i8, MVT::nxv4i8, MVT::nxv8i8, MVT::nxv16i8,
161 MVT::nxv32i8, MVT::nxv64i8, MVT::nxv1i16, MVT::nxv2i16, MVT::nxv4i16,
162 MVT::nxv8i16, MVT::nxv16i16, MVT::nxv32i16, MVT::nxv1i32, MVT::nxv2i32,
163 MVT::nxv4i32, MVT::nxv8i32, MVT::nxv16i32, MVT::nxv1i64, MVT::nxv2i64,
164 MVT::nxv4i64, MVT::nxv8i64};
166 MVT::nxv1f16, MVT::nxv2f16, MVT::nxv4f16,
167 MVT::nxv8f16, MVT::nxv16f16, MVT::nxv32f16};
169 MVT::nxv1bf16, MVT::nxv2bf16, MVT::nxv4bf16,
170 MVT::nxv8bf16, MVT::nxv16bf16, MVT::nxv32bf16};
172 MVT::nxv1f32, MVT::nxv2f32, MVT::nxv4f32, MVT::nxv8f32, MVT::nxv16f32};
174 MVT::nxv1f64, MVT::nxv2f64, MVT::nxv4f64, MVT::nxv8f64};
176 MVT::riscv_nxv1i8x2, MVT::riscv_nxv1i8x3, MVT::riscv_nxv1i8x4,
177 MVT::riscv_nxv1i8x5, MVT::riscv_nxv1i8x6, MVT::riscv_nxv1i8x7,
178 MVT::riscv_nxv1i8x8, MVT::riscv_nxv2i8x2, MVT::riscv_nxv2i8x3,
179 MVT::riscv_nxv2i8x4, MVT::riscv_nxv2i8x5, MVT::riscv_nxv2i8x6,
180 MVT::riscv_nxv2i8x7, MVT::riscv_nxv2i8x8, MVT::riscv_nxv4i8x2,
181 MVT::riscv_nxv4i8x3, MVT::riscv_nxv4i8x4, MVT::riscv_nxv4i8x5,
182 MVT::riscv_nxv4i8x6, MVT::riscv_nxv4i8x7, MVT::riscv_nxv4i8x8,
183 MVT::riscv_nxv8i8x2, MVT::riscv_nxv8i8x3, MVT::riscv_nxv8i8x4,
184 MVT::riscv_nxv8i8x5, MVT::riscv_nxv8i8x6, MVT::riscv_nxv8i8x7,
185 MVT::riscv_nxv8i8x8, MVT::riscv_nxv16i8x2, MVT::riscv_nxv16i8x3,
186 MVT::riscv_nxv16i8x4, MVT::riscv_nxv32i8x2};
188 if (Subtarget.hasVInstructions()) {
189 auto addRegClassForRVV = [
this](
MVT VT) {
193 if (VT.getVectorMinNumElements() < MinElts)
196 unsigned Size = VT.getSizeInBits().getKnownMinValue();
199 RC = &RISCV::VRRegClass;
201 RC = &RISCV::VRM2RegClass;
203 RC = &RISCV::VRM4RegClass;
205 RC = &RISCV::VRM8RegClass;
212 for (
MVT VT : BoolVecVTs)
213 addRegClassForRVV(VT);
214 for (
MVT VT : IntVecVTs) {
215 if (VT.getVectorElementType() == MVT::i64 &&
216 !Subtarget.hasVInstructionsI64())
218 addRegClassForRVV(VT);
221 if (Subtarget.hasVInstructionsF16Minimal() ||
222 Subtarget.hasVendorXAndesVPackFPH())
223 for (
MVT VT : F16VecVTs)
224 addRegClassForRVV(VT);
226 if (Subtarget.hasVInstructionsBF16Minimal() ||
227 Subtarget.hasVendorXAndesVBFHCvt())
228 for (
MVT VT : BF16VecVTs)
229 addRegClassForRVV(VT);
231 if (Subtarget.hasVInstructionsF32())
232 for (
MVT VT : F32VecVTs)
233 addRegClassForRVV(VT);
235 if (Subtarget.hasVInstructionsF64())
236 for (
MVT VT : F64VecVTs)
237 addRegClassForRVV(VT);
239 if (Subtarget.useRVVForFixedLengthVectors()) {
240 auto addRegClassForFixedVectors = [
this](
MVT VT) {
247 if (useRVVForFixedLengthVectorVT(VT))
248 addRegClassForFixedVectors(VT);
251 if (useRVVForFixedLengthVectorVT(VT))
252 addRegClassForFixedVectors(VT);
290 if (Subtarget.enablePExtCodeGen()) {
291 if (Subtarget.is64Bit()) {
324 if (!(Subtarget.hasVendorXCValu() && !Subtarget.is64Bit())) {
334 if (!Subtarget.hasVendorXTHeadBb() && !Subtarget.hasVendorXqcibm() &&
335 !Subtarget.hasVendorXAndesPerf())
340 if (!Subtarget.hasStdExtZbb() && !Subtarget.hasVendorXTHeadBb() &&
341 !Subtarget.hasVendorXqcibm() && !Subtarget.hasVendorXAndesPerf() &&
342 !(Subtarget.hasVendorXCValu() && !Subtarget.is64Bit()))
345 if (Subtarget.hasStdExtZilsd() && !Subtarget.is64Bit()) {
350 if (Subtarget.is64Bit()) {
357 if (!Subtarget.hasStdExtZbb())
363 if (!Subtarget.hasStdExtZmmul()) {
365 }
else if (Subtarget.is64Bit()) {
372 if (!Subtarget.hasStdExtM()) {
375 }
else if (Subtarget.is64Bit()) {
377 {MVT::i8, MVT::i16, MVT::i32},
Custom);
387 if (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) {
388 if (Subtarget.is64Bit())
390 }
else if (Subtarget.hasVendorXTHeadBb()) {
391 if (Subtarget.is64Bit())
394 }
else if (Subtarget.hasVendorXCVbitmanip() && !Subtarget.is64Bit()) {
403 if ((Subtarget.hasVendorXCVbitmanip() || Subtarget.hasVendorXqcibm()) &&
404 !Subtarget.is64Bit()) {
410 if (Subtarget.hasStdExtZbkb())
414 if (Subtarget.hasStdExtZbb() ||
415 (Subtarget.hasVendorXCValu() && !Subtarget.is64Bit())) {
420 if (Subtarget.hasCTZLike()) {
421 if (Subtarget.is64Bit())
427 if (!Subtarget.hasCPOPLike()) {
430 if (Subtarget.is64Bit())
437 if (Subtarget.hasCLZLike()) {
441 if (Subtarget.is64Bit() &&
442 (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtP()))
448 if (Subtarget.hasStdExtP() ||
449 (Subtarget.hasVendorXCValu() && !Subtarget.is64Bit())) {
451 if (Subtarget.is64Bit())
453 }
else if (Subtarget.hasShortForwardBranchIALU()) {
456 }
else if (Subtarget.is64Bit()) {
460 if (!Subtarget.useMIPSCCMovInsn() && !Subtarget.hasVendorXTHeadCondMov())
463 if (Subtarget.hasVendorXqcia() && !Subtarget.is64Bit()) {
472 static const unsigned FPLegalNodeTypes[] = {
486 static const unsigned FPOpToExpand[] = {
490 static const unsigned FPRndMode[] = {
494 static const unsigned ZfhminZfbfminPromoteOps[] = {
505 if (Subtarget.enablePExtCodeGen()) {
510 if (Subtarget.is64Bit()) {
511 VTs.
append({MVT::v2i32, MVT::v4i16, MVT::v8i8});
518 VTs.
append({MVT::v2i16, MVT::v4i8});
534 if (Subtarget.hasStdExtZfbfmin()) {
549 if (Subtarget.hasStdExtZfhminOrZhinxmin()) {
550 if (Subtarget.hasStdExtZfhOrZhinx()) {
557 if (Subtarget.hasStdExtZfa())
584 Subtarget.hasStdExtZfh() && Subtarget.hasStdExtZfa() ?
Legal :
Promote);
600 if (Subtarget.is64Bit())
604 if (Subtarget.hasStdExtFOrZfinx()) {
626 if (Subtarget.hasStdExtZfa()) {
635 if (Subtarget.hasStdExtFOrZfinx() && Subtarget.is64Bit())
638 if (Subtarget.hasStdExtDOrZdinx()) {
641 if (!Subtarget.is64Bit())
644 if (Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
645 !Subtarget.is64Bit()) {
650 if (Subtarget.hasStdExtZfa()) {
656 if (Subtarget.is64Bit())
685 if (Subtarget.is64Bit()) {
692 if (Subtarget.hasStdExtFOrZfinx()) {
718 if (Subtarget.is64Bit())
728 if (Subtarget.is64Bit()) {
735 if (Subtarget.is64Bit())
738 if (Subtarget.hasVendorXMIPSCBOP())
740 else if (Subtarget.hasStdExtZicbop())
743 if (Subtarget.hasStdExtZalrsc()) {
745 if (Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas())
749 }
else if (Subtarget.hasForcedAtomics()) {
764 if (Subtarget.hasVInstructions()) {
773 {MVT::i8, MVT::i16},
Custom);
774 if (Subtarget.is64Bit())
784 static const unsigned IntegerVPOps[] = {
785 ISD::VP_ADD, ISD::VP_SUB, ISD::VP_MUL,
786 ISD::VP_SDIV, ISD::VP_UDIV, ISD::VP_SREM,
787 ISD::VP_UREM, ISD::VP_AND, ISD::VP_OR,
788 ISD::VP_XOR, ISD::VP_SRA, ISD::VP_SRL,
789 ISD::VP_SHL, ISD::VP_REDUCE_ADD, ISD::VP_REDUCE_AND,
790 ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR, ISD::VP_REDUCE_SMAX,
791 ISD::VP_REDUCE_SMIN, ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN,
792 ISD::VP_MERGE, ISD::VP_SELECT, ISD::VP_FP_TO_SINT,
793 ISD::VP_FP_TO_UINT, ISD::VP_SETCC, ISD::VP_SIGN_EXTEND,
794 ISD::VP_ZERO_EXTEND, ISD::VP_TRUNCATE, ISD::VP_SMIN,
795 ISD::VP_SMAX, ISD::VP_UMIN, ISD::VP_UMAX,
796 ISD::VP_ABS, ISD::EXPERIMENTAL_VP_REVERSE, ISD::EXPERIMENTAL_VP_SPLICE,
797 ISD::VP_SADDSAT, ISD::VP_UADDSAT, ISD::VP_SSUBSAT,
798 ISD::VP_USUBSAT, ISD::VP_CTTZ_ELTS, ISD::VP_CTTZ_ELTS_ZERO_UNDEF};
800 static const unsigned FloatingPointVPOps[] = {
801 ISD::VP_FADD, ISD::VP_FSUB, ISD::VP_FMUL,
802 ISD::VP_FDIV, ISD::VP_FNEG, ISD::VP_FABS,
803 ISD::VP_FMA, ISD::VP_REDUCE_FADD, ISD::VP_REDUCE_SEQ_FADD,
804 ISD::VP_REDUCE_FMIN, ISD::VP_REDUCE_FMAX, ISD::VP_MERGE,
805 ISD::VP_SELECT, ISD::VP_SINT_TO_FP, ISD::VP_UINT_TO_FP,
806 ISD::VP_SETCC, ISD::VP_FP_ROUND, ISD::VP_FP_EXTEND,
807 ISD::VP_SQRT, ISD::VP_FMINNUM, ISD::VP_FMAXNUM,
808 ISD::VP_FCEIL, ISD::VP_FFLOOR, ISD::VP_FROUND,
809 ISD::VP_FROUNDEVEN, ISD::VP_FCOPYSIGN, ISD::VP_FROUNDTOZERO,
810 ISD::VP_FRINT, ISD::VP_FNEARBYINT, ISD::VP_IS_FPCLASS,
811 ISD::VP_FMINIMUM, ISD::VP_FMAXIMUM, ISD::VP_LRINT,
812 ISD::VP_LLRINT, ISD::VP_REDUCE_FMINIMUM,
813 ISD::VP_REDUCE_FMAXIMUM};
815 static const unsigned IntegerVecReduceOps[] = {
820 static const unsigned FloatingPointVecReduceOps[] = {
824 static const unsigned FloatingPointLibCallOps[] = {
828 if (!Subtarget.is64Bit()) {
837 ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR,
838 ISD::VP_REDUCE_SMAX, ISD::VP_REDUCE_SMIN,
839 ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN},
843 for (
MVT VT : BoolVecVTs) {
873 {ISD::VP_REDUCE_AND, ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR}, VT,
897 ISD::VP_TRUNCATE, ISD::VP_SETCC},
913 for (
MVT VT : IntVecVTs) {
924 if (VT.getVectorElementType() == MVT::i64 && !Subtarget.hasStdExtV())
974 {ISD::VP_LOAD, ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
975 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER, ISD::VP_SCATTER},
1000 if (Subtarget.hasStdExtZvkb()) {
1008 if (Subtarget.hasStdExtZvbb()) {
1012 ISD::VP_CTTZ_ZERO_UNDEF, ISD::VP_CTPOP},
1018 ISD::VP_CTTZ_ZERO_UNDEF, ISD::VP_CTPOP},
1027 ISD::VP_CTLZ_ZERO_UNDEF, ISD::VP_CTTZ_ZERO_UNDEF},
1035 for (
MVT VT : VecTupleVTs) {
1056 static const unsigned ZvfhminZvfbfminPromoteOps[] = {
1090 static const unsigned ZvfbfaPromoteOps[] = {
ISD::FMINNUM,
1120 static const unsigned ZvfhminZvfbfminPromoteVPOps[] = {
1126 ISD::VP_REDUCE_FMIN,
1127 ISD::VP_REDUCE_FMAX,
1135 ISD::VP_FROUNDTOZERO,
1141 ISD::VP_REDUCE_FMINIMUM,
1142 ISD::VP_REDUCE_FMAXIMUM};
1145 const auto SetCommonVFPActions = [&](
MVT VT) {
1183 {ISD::VP_LOAD, ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1184 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER, ISD::VP_SCATTER},
1220 const auto SetCommonVFPExtLoadTruncStoreActions =
1222 for (
auto SmallVT : SmallerVTs) {
1230 const auto SetCommonPromoteToF32Actions = [&](
MVT VT) {
1257 ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1258 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1283 const auto SetZvfbfaActions = [&](
MVT VT) {
1309 ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1310 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1329 if (Subtarget.hasVInstructionsF16()) {
1330 for (
MVT VT : F16VecVTs) {
1333 SetCommonVFPActions(VT);
1335 }
else if (Subtarget.hasVInstructionsF16Minimal()) {
1336 for (
MVT VT : F16VecVTs) {
1339 SetCommonPromoteToF32Actions(VT);
1343 if (Subtarget.hasVInstructionsBF16()) {
1344 for (
MVT VT : BF16VecVTs) {
1347 SetZvfbfaActions(VT);
1349 }
else if (Subtarget.hasVInstructionsBF16Minimal()) {
1350 for (
MVT VT : BF16VecVTs) {
1353 SetCommonPromoteToF32Actions(VT);
1357 if (Subtarget.hasVInstructionsF32()) {
1358 for (
MVT VT : F32VecVTs) {
1361 SetCommonVFPActions(VT);
1362 SetCommonVFPExtLoadTruncStoreActions(VT, F16VecVTs);
1363 SetCommonVFPExtLoadTruncStoreActions(VT, BF16VecVTs);
1367 if (Subtarget.hasVInstructionsF64()) {
1368 for (
MVT VT : F64VecVTs) {
1371 SetCommonVFPActions(VT);
1372 SetCommonVFPExtLoadTruncStoreActions(VT, F16VecVTs);
1373 SetCommonVFPExtLoadTruncStoreActions(VT, BF16VecVTs);
1374 SetCommonVFPExtLoadTruncStoreActions(VT, F32VecVTs);
1378 if (Subtarget.useRVVForFixedLengthVectors()) {
1380 if (!useRVVForFixedLengthVectorVT(VT))
1429 {ISD::VP_REDUCE_AND, ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR}, VT,
1456 ISD::VP_SETCC, ISD::VP_TRUNCATE},
1483 ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1484 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1522 if (Subtarget.hasStdExtZvkb())
1525 if (Subtarget.hasStdExtZvbb()) {
1549 if (!useRVVForFixedLengthVectorVT(VT))
1575 ISD::VP_SCATTER, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1576 ISD::EXPERIMENTAL_VP_STRIDED_STORE},
1585 !Subtarget.hasVInstructionsF16()) {
1595 if (Subtarget.hasStdExtZfhmin()) {
1621 if (Subtarget.hasStdExtZfbfmin()) {
1628 if (Subtarget.hasStdExtZvfbfa()) {
1642 if (Subtarget.hasStdExtZvfbfa())
1688 if (Subtarget.is64Bit())
1690 if (Subtarget.hasStdExtZfhminOrZhinxmin())
1692 if (Subtarget.hasStdExtZfbfmin())
1694 if (Subtarget.hasStdExtFOrZfinx())
1696 if (Subtarget.hasStdExtDOrZdinx())
1701 if (Subtarget.hasStdExtZaamo())
1704 if (Subtarget.hasForcedAtomics()) {
1714 if (Subtarget.hasVendorXTHeadMemIdx()) {
1723 if (Subtarget.is64Bit()) {
1730 if (Subtarget.hasVendorXCVmem() && !Subtarget.is64Bit()) {
1741 if (Subtarget.hasStdExtZvqdotq() && Subtarget.getELen() >= 64) {
1751 if (Subtarget.useRVVForFixedLengthVectors()) {
1753 if (VT.getVectorElementType() != MVT::i32 ||
1754 !useRVVForFixedLengthVectorVT(VT))
1764 if (Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh()) {
1770 const Align FunctionAlignment(Subtarget.hasStdExtZca() ? 2 : 4);
1782 if (Subtarget.hasStdExtFOrZfinx())
1785 if (Subtarget.hasStdExtZbb())
1788 if ((Subtarget.hasStdExtZbs() && Subtarget.is64Bit()) ||
1789 Subtarget.hasVInstructions())
1792 if (Subtarget.hasStdExtZbkb())
1795 if (Subtarget.hasStdExtFOrZfinx())
1798 if (Subtarget.hasVInstructions())
1801 ISD::VP_GATHER, ISD::VP_SCATTER,
ISD::SRA,
1804 ISD::VP_STORE, ISD::VP_TRUNCATE, ISD::EXPERIMENTAL_VP_REVERSE,
1810 if (Subtarget.hasVendorXTHeadMemPair())
1812 if (Subtarget.useRVVForFixedLengthVectors())
1834 Subtarget.getMaxStoresPerMemmove(
true);
1843 if (Subtarget.is64Bit() && Subtarget.enablePExtCodeGen())
1844 if (VT == MVT::v2i16 || VT == MVT::v4i8)
1855 if (Subtarget.hasVInstructions() &&
1866bool RISCVTargetLowering::shouldExpandGetVectorLength(
EVT TripCountVT,
1868 bool IsScalable)
const {
1875 if (TripCountVT != MVT::i32 && TripCountVT != Subtarget.
getXLenVT())
1893 return !Subtarget.hasVInstructions() ||
1901 auto &
DL =
I.getDataLayout();
1903 auto SetRVVLoadStoreInfo = [&](
unsigned PtrOp,
bool IsStore,
1904 bool IsUnitStrided,
bool UsePtrVal =
false) {
1909 Info.ptrVal =
I.getArgOperand(PtrOp);
1911 Info.fallbackAddressSpace =
1912 I.getArgOperand(PtrOp)->getType()->getPointerAddressSpace();
1916 MemTy =
I.getArgOperand(0)->getType();
1919 MemTy =
I.getType();
1934 Info.align =
DL.getABITypeAlign(MemTy);
1944 if (
I.hasMetadata(LLVMContext::MD_nontemporal))
1951 case Intrinsic::riscv_masked_atomicrmw_xchg:
1952 case Intrinsic::riscv_masked_atomicrmw_add:
1953 case Intrinsic::riscv_masked_atomicrmw_sub:
1954 case Intrinsic::riscv_masked_atomicrmw_nand:
1955 case Intrinsic::riscv_masked_atomicrmw_max:
1956 case Intrinsic::riscv_masked_atomicrmw_min:
1957 case Intrinsic::riscv_masked_atomicrmw_umax:
1958 case Intrinsic::riscv_masked_atomicrmw_umin:
1959 case Intrinsic::riscv_masked_cmpxchg:
1966 Info.memVT = MVT::i32;
1967 Info.ptrVal =
I.getArgOperand(0);
1969 Info.align =
Align(4);
1973 case Intrinsic::riscv_seg2_load_mask:
1974 case Intrinsic::riscv_seg3_load_mask:
1975 case Intrinsic::riscv_seg4_load_mask:
1976 case Intrinsic::riscv_seg5_load_mask:
1977 case Intrinsic::riscv_seg6_load_mask:
1978 case Intrinsic::riscv_seg7_load_mask:
1979 case Intrinsic::riscv_seg8_load_mask:
1980 case Intrinsic::riscv_sseg2_load_mask:
1981 case Intrinsic::riscv_sseg3_load_mask:
1982 case Intrinsic::riscv_sseg4_load_mask:
1983 case Intrinsic::riscv_sseg5_load_mask:
1984 case Intrinsic::riscv_sseg6_load_mask:
1985 case Intrinsic::riscv_sseg7_load_mask:
1986 case Intrinsic::riscv_sseg8_load_mask:
1987 return SetRVVLoadStoreInfo( 0,
false,
1989 case Intrinsic::riscv_seg2_store_mask:
1990 case Intrinsic::riscv_seg3_store_mask:
1991 case Intrinsic::riscv_seg4_store_mask:
1992 case Intrinsic::riscv_seg5_store_mask:
1993 case Intrinsic::riscv_seg6_store_mask:
1994 case Intrinsic::riscv_seg7_store_mask:
1995 case Intrinsic::riscv_seg8_store_mask:
1997 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
2000 case Intrinsic::riscv_sseg2_store_mask:
2001 case Intrinsic::riscv_sseg3_store_mask:
2002 case Intrinsic::riscv_sseg4_store_mask:
2003 case Intrinsic::riscv_sseg5_store_mask:
2004 case Intrinsic::riscv_sseg6_store_mask:
2005 case Intrinsic::riscv_sseg7_store_mask:
2006 case Intrinsic::riscv_sseg8_store_mask:
2008 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
2011 case Intrinsic::riscv_vlm:
2012 return SetRVVLoadStoreInfo( 0,
2016 case Intrinsic::riscv_vle:
2017 case Intrinsic::riscv_vle_mask:
2018 case Intrinsic::riscv_vleff:
2019 case Intrinsic::riscv_vleff_mask:
2020 return SetRVVLoadStoreInfo( 1,
2024 case Intrinsic::riscv_vsm:
2025 case Intrinsic::riscv_vse:
2026 case Intrinsic::riscv_vse_mask:
2027 return SetRVVLoadStoreInfo( 1,
2031 case Intrinsic::riscv_vlse:
2032 case Intrinsic::riscv_vlse_mask:
2033 case Intrinsic::riscv_vloxei:
2034 case Intrinsic::riscv_vloxei_mask:
2035 case Intrinsic::riscv_vluxei:
2036 case Intrinsic::riscv_vluxei_mask:
2037 return SetRVVLoadStoreInfo( 1,
2040 case Intrinsic::riscv_vsse:
2041 case Intrinsic::riscv_vsse_mask:
2042 case Intrinsic::riscv_vsoxei:
2043 case Intrinsic::riscv_vsoxei_mask:
2044 case Intrinsic::riscv_vsuxei:
2045 case Intrinsic::riscv_vsuxei_mask:
2046 return SetRVVLoadStoreInfo( 1,
2049 case Intrinsic::riscv_vlseg2:
2050 case Intrinsic::riscv_vlseg3:
2051 case Intrinsic::riscv_vlseg4:
2052 case Intrinsic::riscv_vlseg5:
2053 case Intrinsic::riscv_vlseg6:
2054 case Intrinsic::riscv_vlseg7:
2055 case Intrinsic::riscv_vlseg8:
2056 case Intrinsic::riscv_vlseg2ff:
2057 case Intrinsic::riscv_vlseg3ff:
2058 case Intrinsic::riscv_vlseg4ff:
2059 case Intrinsic::riscv_vlseg5ff:
2060 case Intrinsic::riscv_vlseg6ff:
2061 case Intrinsic::riscv_vlseg7ff:
2062 case Intrinsic::riscv_vlseg8ff:
2063 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
2066 case Intrinsic::riscv_vlseg2_mask:
2067 case Intrinsic::riscv_vlseg3_mask:
2068 case Intrinsic::riscv_vlseg4_mask:
2069 case Intrinsic::riscv_vlseg5_mask:
2070 case Intrinsic::riscv_vlseg6_mask:
2071 case Intrinsic::riscv_vlseg7_mask:
2072 case Intrinsic::riscv_vlseg8_mask:
2073 case Intrinsic::riscv_vlseg2ff_mask:
2074 case Intrinsic::riscv_vlseg3ff_mask:
2075 case Intrinsic::riscv_vlseg4ff_mask:
2076 case Intrinsic::riscv_vlseg5ff_mask:
2077 case Intrinsic::riscv_vlseg6ff_mask:
2078 case Intrinsic::riscv_vlseg7ff_mask:
2079 case Intrinsic::riscv_vlseg8ff_mask:
2080 return SetRVVLoadStoreInfo(
I.arg_size() - 5,
2083 case Intrinsic::riscv_vlsseg2:
2084 case Intrinsic::riscv_vlsseg3:
2085 case Intrinsic::riscv_vlsseg4:
2086 case Intrinsic::riscv_vlsseg5:
2087 case Intrinsic::riscv_vlsseg6:
2088 case Intrinsic::riscv_vlsseg7:
2089 case Intrinsic::riscv_vlsseg8:
2090 case Intrinsic::riscv_vloxseg2:
2091 case Intrinsic::riscv_vloxseg3:
2092 case Intrinsic::riscv_vloxseg4:
2093 case Intrinsic::riscv_vloxseg5:
2094 case Intrinsic::riscv_vloxseg6:
2095 case Intrinsic::riscv_vloxseg7:
2096 case Intrinsic::riscv_vloxseg8:
2097 case Intrinsic::riscv_vluxseg2:
2098 case Intrinsic::riscv_vluxseg3:
2099 case Intrinsic::riscv_vluxseg4:
2100 case Intrinsic::riscv_vluxseg5:
2101 case Intrinsic::riscv_vluxseg6:
2102 case Intrinsic::riscv_vluxseg7:
2103 case Intrinsic::riscv_vluxseg8:
2104 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
2107 case Intrinsic::riscv_vlsseg2_mask:
2108 case Intrinsic::riscv_vlsseg3_mask:
2109 case Intrinsic::riscv_vlsseg4_mask:
2110 case Intrinsic::riscv_vlsseg5_mask:
2111 case Intrinsic::riscv_vlsseg6_mask:
2112 case Intrinsic::riscv_vlsseg7_mask:
2113 case Intrinsic::riscv_vlsseg8_mask:
2114 case Intrinsic::riscv_vloxseg2_mask:
2115 case Intrinsic::riscv_vloxseg3_mask:
2116 case Intrinsic::riscv_vloxseg4_mask:
2117 case Intrinsic::riscv_vloxseg5_mask:
2118 case Intrinsic::riscv_vloxseg6_mask:
2119 case Intrinsic::riscv_vloxseg7_mask:
2120 case Intrinsic::riscv_vloxseg8_mask:
2121 case Intrinsic::riscv_vluxseg2_mask:
2122 case Intrinsic::riscv_vluxseg3_mask:
2123 case Intrinsic::riscv_vluxseg4_mask:
2124 case Intrinsic::riscv_vluxseg5_mask:
2125 case Intrinsic::riscv_vluxseg6_mask:
2126 case Intrinsic::riscv_vluxseg7_mask:
2127 case Intrinsic::riscv_vluxseg8_mask:
2128 return SetRVVLoadStoreInfo(
I.arg_size() - 6,
2131 case Intrinsic::riscv_vsseg2:
2132 case Intrinsic::riscv_vsseg3:
2133 case Intrinsic::riscv_vsseg4:
2134 case Intrinsic::riscv_vsseg5:
2135 case Intrinsic::riscv_vsseg6:
2136 case Intrinsic::riscv_vsseg7:
2137 case Intrinsic::riscv_vsseg8:
2138 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
2141 case Intrinsic::riscv_vsseg2_mask:
2142 case Intrinsic::riscv_vsseg3_mask:
2143 case Intrinsic::riscv_vsseg4_mask:
2144 case Intrinsic::riscv_vsseg5_mask:
2145 case Intrinsic::riscv_vsseg6_mask:
2146 case Intrinsic::riscv_vsseg7_mask:
2147 case Intrinsic::riscv_vsseg8_mask:
2148 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
2151 case Intrinsic::riscv_vssseg2:
2152 case Intrinsic::riscv_vssseg3:
2153 case Intrinsic::riscv_vssseg4:
2154 case Intrinsic::riscv_vssseg5:
2155 case Intrinsic::riscv_vssseg6:
2156 case Intrinsic::riscv_vssseg7:
2157 case Intrinsic::riscv_vssseg8:
2158 case Intrinsic::riscv_vsoxseg2:
2159 case Intrinsic::riscv_vsoxseg3:
2160 case Intrinsic::riscv_vsoxseg4:
2161 case Intrinsic::riscv_vsoxseg5:
2162 case Intrinsic::riscv_vsoxseg6:
2163 case Intrinsic::riscv_vsoxseg7:
2164 case Intrinsic::riscv_vsoxseg8:
2165 case Intrinsic::riscv_vsuxseg2:
2166 case Intrinsic::riscv_vsuxseg3:
2167 case Intrinsic::riscv_vsuxseg4:
2168 case Intrinsic::riscv_vsuxseg5:
2169 case Intrinsic::riscv_vsuxseg6:
2170 case Intrinsic::riscv_vsuxseg7:
2171 case Intrinsic::riscv_vsuxseg8:
2172 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
2175 case Intrinsic::riscv_vssseg2_mask:
2176 case Intrinsic::riscv_vssseg3_mask:
2177 case Intrinsic::riscv_vssseg4_mask:
2178 case Intrinsic::riscv_vssseg5_mask:
2179 case Intrinsic::riscv_vssseg6_mask:
2180 case Intrinsic::riscv_vssseg7_mask:
2181 case Intrinsic::riscv_vssseg8_mask:
2182 case Intrinsic::riscv_vsoxseg2_mask:
2183 case Intrinsic::riscv_vsoxseg3_mask:
2184 case Intrinsic::riscv_vsoxseg4_mask:
2185 case Intrinsic::riscv_vsoxseg5_mask:
2186 case Intrinsic::riscv_vsoxseg6_mask:
2187 case Intrinsic::riscv_vsoxseg7_mask:
2188 case Intrinsic::riscv_vsoxseg8_mask:
2189 case Intrinsic::riscv_vsuxseg2_mask:
2190 case Intrinsic::riscv_vsuxseg3_mask:
2191 case Intrinsic::riscv_vsuxseg4_mask:
2192 case Intrinsic::riscv_vsuxseg5_mask:
2193 case Intrinsic::riscv_vsuxseg6_mask:
2194 case Intrinsic::riscv_vsuxseg7_mask:
2195 case Intrinsic::riscv_vsuxseg8_mask:
2196 return SetRVVLoadStoreInfo(
I.arg_size() - 5,
2199 case Intrinsic::riscv_sf_vlte8:
2200 case Intrinsic::riscv_sf_vlte16:
2201 case Intrinsic::riscv_sf_vlte32:
2202 case Intrinsic::riscv_sf_vlte64:
2204 Info.ptrVal =
I.getArgOperand(1);
2206 case Intrinsic::riscv_sf_vlte8:
2207 Info.memVT = MVT::i8;
2208 Info.align =
Align(1);
2210 case Intrinsic::riscv_sf_vlte16:
2211 Info.memVT = MVT::i16;
2212 Info.align =
Align(2);
2214 case Intrinsic::riscv_sf_vlte32:
2215 Info.memVT = MVT::i32;
2216 Info.align =
Align(4);
2218 case Intrinsic::riscv_sf_vlte64:
2219 Info.memVT = MVT::i64;
2220 Info.align =
Align(8);
2226 case Intrinsic::riscv_sf_vste8:
2227 case Intrinsic::riscv_sf_vste16:
2228 case Intrinsic::riscv_sf_vste32:
2229 case Intrinsic::riscv_sf_vste64:
2231 Info.ptrVal =
I.getArgOperand(1);
2233 case Intrinsic::riscv_sf_vste8:
2234 Info.memVT = MVT::i8;
2235 Info.align =
Align(1);
2237 case Intrinsic::riscv_sf_vste16:
2238 Info.memVT = MVT::i16;
2239 Info.align =
Align(2);
2241 case Intrinsic::riscv_sf_vste32:
2242 Info.memVT = MVT::i32;
2243 Info.align =
Align(4);
2245 case Intrinsic::riscv_sf_vste64:
2246 Info.memVT = MVT::i64;
2247 Info.align =
Align(8);
2304 if (Subtarget.is64Bit() || !SrcTy->isIntegerTy() || !DstTy->
isIntegerTy())
2306 unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
2308 return (SrcBits == 64 && DestBits == 32);
2319 return (SrcBits == 64 && DestBits == 32);
2325 if (Subtarget.hasVInstructions() &&
2330 if (SrcBits == DestBits * 2) {
2342 EVT MemVT = LD->getMemoryVT();
2343 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
2353 return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
2361 return Subtarget.hasCTZLike();
2365 return Subtarget.hasCLZLike();
2376 if (!Subtarget.hasBEXTILike())
2381 return !Mask->getValue().isSignedIntN(12) && Mask->getValue().isPowerOf2();
2385 EVT VT =
Y.getValueType();
2390 return (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
2395 EVT VT =
Y.getValueType();
2400 return Subtarget.hasStdExtZvkb();
2405 if (Subtarget.hasStdExtZbs())
2406 return X.getValueType().isScalarInteger();
2409 if (Subtarget.hasVendorXTHeadBs())
2410 return C !=
nullptr;
2412 return C &&
C->getAPIntValue().ule(10);
2416 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
2422 if (!VT.
isVector() || !Subtarget.hasVInstructions())
2433 assert(Ty->isIntegerTy());
2435 unsigned BitSize = Ty->getIntegerBitWidth();
2436 if (BitSize > Subtarget.getXLen())
2440 int64_t Val = Imm.getSExtValue();
2448 if (!Subtarget.enableUnalignedScalarMem())
2458 return Seq.
size() <= Subtarget.getMaxBuildIntsCost();
2464 unsigned OldShiftOpcode,
unsigned NewShiftOpcode,
2519 if (!Subtarget.hasStdExtZfa())
2522 bool IsSupportedVT =
false;
2523 if (VT == MVT::f16) {
2524 IsSupportedVT = Subtarget.hasStdExtZfh() || Subtarget.hasStdExtZvfh();
2525 }
else if (VT == MVT::f32) {
2526 IsSupportedVT =
true;
2527 }
else if (VT == MVT::f64) {
2528 assert(Subtarget.hasStdExtD() &&
"Expect D extension");
2529 IsSupportedVT =
true;
2539 bool ForCodeSize)
const {
2540 bool IsLegalVT =
false;
2542 IsLegalVT = Subtarget.hasStdExtZfhminOrZhinxmin();
2543 else if (VT == MVT::f32)
2544 IsLegalVT = Subtarget.hasStdExtFOrZfinx();
2545 else if (VT == MVT::f64)
2546 IsLegalVT = Subtarget.hasStdExtDOrZdinx();
2547 else if (VT == MVT::bf16)
2548 IsLegalVT = Subtarget.hasStdExtZfbfmin();
2564 return Imm.isZero();
2568 if (Imm.isNegZero())
2573 const int FmvCost = Subtarget.hasStdExtZfinx() ? 0 : 1;
2576 Subtarget.getXLen(), Subtarget);
2582 unsigned Index)
const {
2599 if (EltVT == MVT::i1)
2605 unsigned MinVLen = Subtarget.getRealMinVLen();
2612 if (Index + ResElts <= MinVLMAX && Index < 31)
2621 return (ResElts * 2) == SrcElts && Index == ResElts;
2629 if (VT == MVT::f16 && Subtarget.hasStdExtFOrZfinx() &&
2630 !Subtarget.hasStdExtZfhminOrZhinxmin())
2638 std::optional<MVT> RegisterVT)
const {
2640 if (VT == (Subtarget.is64Bit() ? MVT::i128 : MVT::i64) && RegisterVT &&
2641 *RegisterVT == MVT::Untyped)
2652 if (VT == MVT::f16 && Subtarget.hasStdExtFOrZfinx() &&
2653 !Subtarget.hasStdExtZfhminOrZhinxmin())
2672 !Subtarget.hasVendorXAndesPerf()) {
2678 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
2692 int64_t
C = RHSC->getSExtValue();
2702 if ((Subtarget.hasVendorXqcicm() || Subtarget.hasVendorXqcicli()) &&
2728 if ((Subtarget.hasVendorXqcicm() || Subtarget.hasVendorXqcicli()) &&
2763 if (VT.
SimpleTy >= MVT::riscv_nxv1i8x2 &&
2764 VT.
SimpleTy <= MVT::riscv_nxv1i8x8)
2766 if (VT.
SimpleTy >= MVT::riscv_nxv2i8x2 &&
2767 VT.
SimpleTy <= MVT::riscv_nxv2i8x8)
2769 if (VT.
SimpleTy >= MVT::riscv_nxv4i8x2 &&
2770 VT.
SimpleTy <= MVT::riscv_nxv4i8x8)
2772 if (VT.
SimpleTy >= MVT::riscv_nxv8i8x2 &&
2773 VT.
SimpleTy <= MVT::riscv_nxv8i8x8)
2775 if (VT.
SimpleTy >= MVT::riscv_nxv16i8x2 &&
2776 VT.
SimpleTy <= MVT::riscv_nxv16i8x4)
2778 if (VT.
SimpleTy == MVT::riscv_nxv32i8x2)
2788 switch (KnownSize) {
2816 return RISCV::VRRegClassID;
2818 return RISCV::VRM2RegClassID;
2820 return RISCV::VRM4RegClassID;
2822 return RISCV::VRM8RegClassID;
2830 static_assert(RISCV::sub_vrm1_7 == RISCV::sub_vrm1_0 + 7,
2831 "Unexpected subreg numbering");
2832 return RISCV::sub_vrm1_0 + Index;
2835 static_assert(RISCV::sub_vrm2_3 == RISCV::sub_vrm2_0 + 3,
2836 "Unexpected subreg numbering");
2837 return RISCV::sub_vrm2_0 + Index;
2840 static_assert(RISCV::sub_vrm4_1 == RISCV::sub_vrm4_0 + 1,
2841 "Unexpected subreg numbering");
2842 return RISCV::sub_vrm4_0 + Index;
2850 unsigned RegsPerField =
2853 switch (RegsPerField) {
2856 return RISCV::VRN2M1RegClassID;
2858 return RISCV::VRN3M1RegClassID;
2860 return RISCV::VRN4M1RegClassID;
2862 return RISCV::VRN5M1RegClassID;
2864 return RISCV::VRN6M1RegClassID;
2866 return RISCV::VRN7M1RegClassID;
2868 return RISCV::VRN8M1RegClassID;
2872 return RISCV::VRN2M2RegClassID;
2874 return RISCV::VRN3M2RegClassID;
2876 return RISCV::VRN4M2RegClassID;
2880 return RISCV::VRN2M4RegClassID;
2888 return RISCV::VRRegClassID;
2897std::pair<unsigned, unsigned>
2899 MVT VecVT,
MVT SubVecVT,
unsigned InsertExtractIdx,
2901 static_assert((RISCV::VRM8RegClassID > RISCV::VRM4RegClassID &&
2902 RISCV::VRM4RegClassID > RISCV::VRM2RegClassID &&
2903 RISCV::VRM2RegClassID > RISCV::VRRegClassID),
2904 "Register classes not ordered");
2911 if (VecRegClassID == SubRegClassID)
2912 return {RISCV::NoSubRegister, 0};
2915 "Only allow scalable vector subvector.");
2917 "Invalid vector tuple insert/extract for vector and subvector with "
2928 unsigned SubRegIdx = RISCV::NoSubRegister;
2929 for (
const unsigned RCID :
2930 {RISCV::VRM4RegClassID, RISCV::VRM2RegClassID, RISCV::VRRegClassID})
2931 if (VecRegClassID > RCID && SubRegClassID <= RCID) {
2935 SubRegIdx =
TRI->composeSubRegIndices(SubRegIdx,
2940 return {SubRegIdx, InsertExtractIdx};
2945bool RISCVTargetLowering::mergeStoresAfterLegalization(
EVT VT)
const {
2955 return Subtarget.is64Bit() ? Subtarget.hasVInstructionsI64() :
true;
2959 return Subtarget.hasVInstructions();
2961 return Subtarget.hasVInstructionsI64();
2963 return Subtarget.hasVInstructionsF16Minimal();
2965 return Subtarget.hasVInstructionsBF16Minimal();
2967 return Subtarget.hasVInstructionsF32();
2969 return Subtarget.hasVInstructionsF64();
2983 "Unexpected opcode");
2985 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
2987 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
2990 return Op.getOperand(
II->VLOperand + 1 + HasChain);
3064bool RISCVTargetLowering::useRVVForFixedLengthVectorVT(
MVT VT)
const {
3065 return ::useRVVForFixedLengthVectorVT(VT, Subtarget);
3074 "Expected legal fixed length vector!");
3077 unsigned MaxELen = Subtarget.
getELen();
3111 return ::getContainerForFixedLengthVector(*
this, VT,
getSubtarget());
3118 "Expected to convert into a scalable vector!");
3119 assert(V.getValueType().isFixedLengthVector() &&
3120 "Expected a fixed length vector operand!");
3129 "Expected to convert into a fixed length vector!");
3130 assert(V.getValueType().isScalableVector() &&
3131 "Expected a scalable vector operand!");
3150 return DAG.
getNode(RISCVISD::VMSET_VL,
DL, MaskVT, VL);
3153static std::pair<SDValue, SDValue>
3162static std::pair<SDValue, SDValue>
3175static std::pair<SDValue, SDValue>
3192std::pair<unsigned, unsigned>
3200 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
3204 unsigned VectorBitsMin = Subtarget.getRealMinVLen();
3208 return std::make_pair(MinVLMAX, MaxVLMAX);
3220 EVT VT,
unsigned DefinedValues)
const {
3229 unsigned DLenFactor = Subtarget.getDLenFactor();
3234 std::tie(LMul, Fractional) =
3237 Cost = LMul <= DLenFactor ? (DLenFactor / LMul) : 1;
3239 Cost = (LMul * DLenFactor);
3253 bool Log2CostModel =
3255 if (Log2CostModel && LMULCost.isValid()) {
3256 unsigned Log =
Log2_64(LMULCost.getValue());
3258 return LMULCost * Log;
3260 return LMULCost * LMULCost;
3291 Op.getValueType() == MVT::bf16) {
3292 bool IsStrict =
Op->isStrictFPOpcode();
3297 {Op.getOperand(0), Op.getOperand(1)});
3299 {
Op.getValueType(), MVT::Other},
3305 DAG.
getNode(
Op.getOpcode(),
DL, MVT::f32,
Op.getOperand(0)),
3320 MVT DstVT =
Op.getSimpleValueType();
3329 Src.getValueType() == MVT::bf16) {
3335 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
3336 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
3337 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
3344 Opc,
DL, DstVT, Src,
3347 if (
Opc == RISCVISD::FCVT_WU_RV64)
3358 MVT SrcVT = Src.getSimpleValueType();
3364 if (SatVT != DstEltVT)
3367 MVT DstContainerVT = DstVT;
3368 MVT SrcContainerVT = SrcVT;
3374 "Expected same element count");
3383 {Src, Src, DAG.getCondCode(ISD::SETNE),
3384 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
3388 if (DstEltSize > (2 * SrcEltSize)) {
3391 Src = DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, InterVT, Src, Mask, VL);
3394 MVT CvtContainerVT = DstContainerVT;
3395 MVT CvtEltVT = DstEltVT;
3396 if (SrcEltSize > (2 * DstEltSize)) {
3402 IsSigned ? RISCVISD::VFCVT_RTZ_X_F_VL : RISCVISD::VFCVT_RTZ_XU_F_VL;
3405 while (CvtContainerVT != DstContainerVT) {
3409 unsigned ClipOpc = IsSigned ? RISCVISD::TRUNCATE_VECTOR_VL_SSAT
3410 : RISCVISD::TRUNCATE_VECTOR_VL_USAT;
3411 Res = DAG.
getNode(ClipOpc,
DL, CvtContainerVT, Res, Mask, VL);
3415 RISCVISD::VMV_V_X_VL,
DL, DstContainerVT, DAG.
getUNDEF(DstContainerVT),
3417 Res = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, DstContainerVT, IsNan, SplatZero,
3418 Res, DAG.
getUNDEF(DstContainerVT), VL);
3428 bool IsStrict =
Op->isStrictFPOpcode();
3429 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
3439 {
Op.getOperand(0), SrcVal});
3440 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
3441 {Ext.getValue(1), Ext.getValue(0)});
3455 case ISD::VP_FROUNDEVEN:
3459 case ISD::VP_FROUNDTOZERO:
3463 case ISD::VP_FFLOOR:
3475 case ISD::VP_FROUND:
3485 case ISD::VP_LLRINT:
3499 MVT VT =
Op.getSimpleValueType();
3509 MVT ContainerVT = VT;
3516 if (
Op->isVPOpcode()) {
3517 Mask =
Op.getOperand(1);
3521 VL =
Op.getOperand(2);
3527 SDValue Abs = DAG.
getNode(RISCVISD::FABS_VL,
DL, ContainerVT, Src, Mask, VL);
3540 DAG.
getUNDEF(ContainerVT), MaxValNode, VL);
3545 DAG.
getNode(RISCVISD::SETCC_VL,
DL, SetccVT,
3554 switch (
Op.getOpcode()) {
3562 case ISD::VP_FFLOOR:
3565 case ISD::VP_FROUND:
3566 case ISD::VP_FROUNDEVEN:
3567 case ISD::VP_FROUNDTOZERO: {
3570 Truncated = DAG.
getNode(RISCVISD::VFCVT_RM_X_F_VL,
DL, IntVT, Src, Mask,
3575 Truncated = DAG.
getNode(RISCVISD::VFCVT_RTZ_X_F_VL,
DL, IntVT, Src,
3579 case ISD::VP_FNEARBYINT:
3580 Truncated = DAG.
getNode(RISCVISD::VFROUND_NOEXCEPT_VL,
DL, ContainerVT, Src,
3586 if (Truncated.
getOpcode() != RISCVISD::VFROUND_NOEXCEPT_VL)
3587 Truncated = DAG.
getNode(RISCVISD::SINT_TO_FP_VL,
DL, ContainerVT, Truncated,
3591 Truncated = DAG.
getNode(RISCVISD::FCOPYSIGN_VL,
DL, ContainerVT, Truncated,
3592 Src, Src, Mask, VL);
3607 MVT VT =
Op.getSimpleValueType();
3611 MVT ContainerVT = VT;
3623 MVT MaskVT = Mask.getSimpleValueType();
3626 {Chain, Src, Src, DAG.getCondCode(ISD::SETUNE),
3627 DAG.getUNDEF(MaskVT), Mask, VL});
3629 Src = DAG.
getNode(RISCVISD::STRICT_FADD_VL,
DL,
3631 {Chain, Src, Src, Src, Unorder, VL});
3635 SDValue Abs = DAG.
getNode(RISCVISD::FABS_VL,
DL, ContainerVT, Src, Mask, VL);
3648 DAG.
getUNDEF(ContainerVT), MaxValNode, VL);
3652 RISCVISD::SETCC_VL,
DL, MaskVT,
3660 switch (
Op.getOpcode()) {
3670 RISCVISD::STRICT_VFCVT_RM_X_F_VL,
DL, DAG.
getVTList(IntVT, MVT::Other),
3671 {Chain, Src, Mask, DAG.getTargetConstant(FRM, DL, XLenVT), VL});
3676 DAG.
getNode(RISCVISD::STRICT_VFCVT_RTZ_X_F_VL,
DL,
3677 DAG.
getVTList(IntVT, MVT::Other), Chain, Src, Mask, VL);
3680 Truncated = DAG.
getNode(RISCVISD::STRICT_VFROUND_NOEXCEPT_VL,
DL,
3681 DAG.
getVTList(ContainerVT, MVT::Other), Chain, Src,
3689 Truncated = DAG.
getNode(RISCVISD::STRICT_SINT_TO_FP_VL,
DL,
3690 DAG.
getVTList(ContainerVT, MVT::Other), Chain,
3691 Truncated, Mask, VL);
3696 Truncated = DAG.
getNode(RISCVISD::FCOPYSIGN_VL,
DL, ContainerVT, Truncated,
3697 Src, Src, Mask, VL);
3707 MVT VT =
Op.getSimpleValueType();
3728 return DAG.
getNode(RISCVISD::FROUND,
DL, VT, Src, MaxValNode,
3736 MVT DstVT =
Op.getSimpleValueType();
3738 MVT SrcVT = Src.getSimpleValueType();
3743 MVT DstContainerVT = DstVT;
3744 MVT SrcContainerVT = SrcVT;
3756 if (SrcElemType == MVT::f16 || SrcElemType == MVT::bf16) {
3758 Src = DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, F32VT, Src, Mask, VL);
3762 DAG.
getNode(RISCVISD::VFCVT_RM_X_F_VL,
DL, DstContainerVT, Src, Mask,
3782 return DAG.
getNode(RISCVISD::VSLIDEDOWN_VL,
DL, VT,
Ops);
3794 return DAG.
getNode(RISCVISD::VSLIDEUP_VL,
DL, VT,
Ops);
3819 return std::nullopt;
3837 unsigned EltSizeInBits) {
3840 return std::nullopt;
3841 bool IsInteger =
Op.getValueType().isInteger();
3843 std::optional<unsigned> SeqStepDenom;
3844 std::optional<APInt> SeqStepNum;
3845 std::optional<APInt> SeqAddend;
3846 std::optional<std::pair<APInt, unsigned>> PrevElt;
3847 assert(EltSizeInBits >=
Op.getValueType().getScalarSizeInBits());
3852 const unsigned OpSize =
Op.getScalarValueSizeInBits();
3853 for (
auto [Idx, Elt] :
enumerate(
Op->op_values())) {
3854 if (Elt.isUndef()) {
3855 Elts[Idx] = std::nullopt;
3859 Elts[Idx] = Elt->getAsAPIntVal().trunc(OpSize).zext(EltSizeInBits);
3864 return std::nullopt;
3865 Elts[Idx] = *ExactInteger;
3869 for (
auto [Idx, Elt] :
enumerate(Elts)) {
3878 unsigned IdxDiff = Idx - PrevElt->second;
3879 APInt ValDiff = *Elt - PrevElt->first;
3887 int64_t Remainder = ValDiff.
srem(IdxDiff);
3892 return std::nullopt;
3893 ValDiff = ValDiff.
sdiv(IdxDiff);
3898 SeqStepNum = ValDiff;
3899 else if (ValDiff != SeqStepNum)
3900 return std::nullopt;
3903 SeqStepDenom = IdxDiff;
3904 else if (IdxDiff != *SeqStepDenom)
3905 return std::nullopt;
3909 if (!PrevElt || PrevElt->first != *Elt)
3910 PrevElt = std::make_pair(*Elt, Idx);
3914 if (!SeqStepNum || !SeqStepDenom)
3915 return std::nullopt;
3919 for (
auto [Idx, Elt] :
enumerate(Elts)) {
3923 (
APInt(EltSizeInBits, Idx,
false,
true) *
3925 .sdiv(*SeqStepDenom);
3927 APInt Addend = *Elt - ExpectedVal;
3930 else if (Addend != SeqAddend)
3931 return std::nullopt;
3934 assert(SeqAddend &&
"Must have an addend if we have a step");
3936 return VIDSequence{SeqStepNum->getSExtValue(), *SeqStepDenom,
3937 SeqAddend->getSExtValue()};
3952 if (EltTy == MVT::i1 ||
3955 MVT SrcVT = Src.getSimpleValueType();
3971 MVT ContainerVT = VT;
3975 MVT SrcContainerVT = SrcVT;
3990 SDValue Gather = DAG.
getNode(RISCVISD::VRGATHER_VX_VL,
DL, ContainerVT, Src,
3991 Idx, DAG.
getUNDEF(ContainerVT), Mask, VL);
3999 MVT VT =
Op.getSimpleValueType();
4008 int64_t StepNumerator = SimpleVID->StepNumerator;
4009 unsigned StepDenominator = SimpleVID->StepDenominator;
4010 int64_t Addend = SimpleVID->Addend;
4012 assert(StepNumerator != 0 &&
"Invalid step");
4013 bool Negate =
false;
4014 int64_t SplatStepVal = StepNumerator;
4018 if (StepNumerator != 1 && StepNumerator !=
INT64_MIN &&
4020 Negate = StepNumerator < 0;
4022 SplatStepVal =
Log2_64(std::abs(StepNumerator));
4032 (SplatStepVal >= 0 || StepDenominator == 1) &&
isInt<32>(Addend)) {
4035 MVT VIDContainerVT =
4043 if ((StepOpcode ==
ISD::MUL && SplatStepVal != 1) ||
4044 (StepOpcode ==
ISD::SHL && SplatStepVal != 0)) {
4046 VID = DAG.
getNode(StepOpcode,
DL, VIDVT, VID, SplatStep);
4048 if (StepDenominator != 1) {
4053 if (Addend != 0 || Negate) {
4079 MVT VT =
Op.getSimpleValueType();
4088 unsigned NumElts =
Op.getNumOperands();
4091 unsigned MostCommonCount = 0;
4093 unsigned NumUndefElts =
4101 unsigned NumScalarLoads = 0;
4107 unsigned &
Count = ValueCounts[V];
4110 NumScalarLoads += !CFP->isExactlyValue(+0.0);
4115 if (++
Count >= MostCommonCount) {
4117 MostCommonCount =
Count;
4121 assert(DominantValue &&
"Not expecting an all-undef BUILD_VECTOR");
4122 unsigned NumDefElts = NumElts - NumUndefElts;
4123 unsigned DominantValueCountThreshold = NumDefElts <= 2 ? 0 : NumDefElts - 2;
4129 ((MostCommonCount > DominantValueCountThreshold) ||
4141 if (
SDValue LastOp =
Op->getOperand(
Op->getNumOperands() - 1);
4142 !LastOp.isUndef() && ValueCounts[LastOp] == 1 &&
4143 LastOp != DominantValue) {
4146 VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1DOWN_VL : RISCVISD::VSLIDE1DOWN_VL;
4152 Processed.
insert(LastOp);
4158 if (V.isUndef() || !Processed.
insert(V).second)
4160 if (ValueCounts[V] == 1) {
4168 return DAG.getConstant(V == V1, DL, XLenVT);
4184 MVT VT =
Op.getSimpleValueType();
4193 unsigned NumElts =
Op.getNumOperands();
4214 unsigned NumViaIntegerBits = std::clamp(NumElts, 8u, Subtarget.
getXLen());
4215 NumViaIntegerBits = std::min(NumViaIntegerBits, Subtarget.
getELen());
4223 unsigned IntegerViaVecElts =
divideCeil(NumElts, NumViaIntegerBits);
4224 MVT IntegerViaVecVT =
4229 unsigned BitPos = 0, IntegerEltIdx = 0;
4232 for (
unsigned I = 0;
I < NumElts;) {
4234 bool BitValue = !V.isUndef() && V->getAsZExtVal();
4235 Bits |= ((
uint64_t)BitValue << BitPos);
4241 if (
I % NumViaIntegerBits == 0 ||
I == NumElts) {
4242 if (NumViaIntegerBits <= 32)
4245 Elts[IntegerEltIdx] = Elt;
4254 if (NumElts < NumViaIntegerBits) {
4258 assert(IntegerViaVecVT == MVT::v1i8 &&
"Unexpected mask vector type");
4273 : RISCVISD::VMV_V_X_VL;
4293 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32) &&
4294 "Unexpected sequence type");
4298 unsigned ViaVecLen =
4306 const auto &SeqV =
OpIdx.value();
4307 if (!SeqV.isUndef())
4309 ((SeqV->getAsZExtVal() & EltMask) << (
OpIdx.index() * EltBitSize));
4315 if (ViaIntVT == MVT::i32)
4338 BV->getRepeatedSequence(Sequence) &&
4339 (Sequence.size() * EltBitSize) <= Subtarget.
getELen()) {
4340 unsigned SeqLen = Sequence.size();
4342 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32 ||
4343 ViaIntVT == MVT::i64) &&
4344 "Unexpected sequence type");
4349 const unsigned RequiredVL = NumElts / SeqLen;
4350 const unsigned ViaVecLen =
4352 NumElts : RequiredVL;
4355 unsigned EltIdx = 0;
4360 for (
const auto &SeqV : Sequence) {
4361 if (!SeqV.isUndef())
4363 ((SeqV->getAsZExtVal() & EltMask) << (EltIdx * EltBitSize));
4370 if (ViaIntVT == MVT::i32)
4377 (!Subtarget.
is64Bit() && ViaIntVT == MVT::i64)) &&
4378 "Unexpected bitcast sequence");
4382 MVT ViaContainerVT =
4385 DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ViaContainerVT,
4389 if (ViaVecLen != RequiredVL)
4408 Source, DAG, Subtarget);
4409 SDValue Res = DAG.
getNode(RISCVISD::VSEXT_VL,
DL, ContainerVT, Source, Mask, VL);
4428 return RISCV::PACKH;
4430 return Subtarget.
is64Bit() ? RISCV::PACKW : RISCV::PACK;
4445 MVT VT =
Op.getSimpleValueType();
4453 if (!Subtarget.hasStdExtZbb() || !Subtarget.hasStdExtZba())
4458 if (ElemSizeInBits >= std::min(Subtarget.
getELen(), Subtarget.
getXLen()) ||
4472 if (Subtarget.hasStdExtZbkb())
4477 ElemDL, XLenVT,
A,
B),
4489 NewOperands.
reserve(NumElts / 2);
4491 NewOperands.
push_back(pack(
Op.getOperand(i),
Op.getOperand(i + 1)));
4501 MVT VT =
Op.getSimpleValueType();
4510 if (VT != MVT::v4i8)
4523 DAG.
getNode(RISCVISD::PPACK_DH,
DL, {MVT::v2i16, MVT::v2i16},
4524 {Val0, Val1, Val2, Val3});
4530 RISCV::PACK,
DL, MVT::i32,
4531 {DAG.getNode(ISD::BITCAST, DL, MVT::i32, PackDH.getValue(0)),
4532 DAG.getNode(ISD::BITCAST, DL, MVT::i32, PackDH.getValue(1))}),
4539 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) || EltVT == MVT::bf16) {
4544 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4545 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin())) {
4555 NewOps[
I] = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Elem);
4605 [](
const SDUse &U) { return U.get().isUndef(); })) {
4646 auto OneVRegOfOps =
ArrayRef(BuildVectorOps).slice(i, ElemsPerVReg);
4650 unsigned InsertIdx = (i / ElemsPerVReg) * NumOpElts;
4672 unsigned NumUndefElts =
4674 unsigned NumDefElts = NumElts - NumUndefElts;
4675 if (NumDefElts >= 8 && NumDefElts > NumElts / 2 &&
4682 for (
const auto &[Idx, U] :
enumerate(
Op->ops())) {
4684 if (Idx < NumElts / 2) {
4691 bool SelectMaskVal = (Idx < NumElts / 2);
4694 assert(SubVecAOps.
size() == NumElts && SubVecBOps.
size() == NumElts &&
4695 MaskVals.
size() == NumElts);
4730 unsigned UndefCount = 0;
4737 LinearBudget -= PerSlideCost;
4740 LinearBudget -= PerSlideCost;
4743 LinearBudget -= PerSlideCost;
4746 if (LinearBudget < 0)
4751 "Illegal type which will result in reserved encoding");
4767 bool SlideUp =
false;
4792 if (EVecEltVT != ContainerEltVT)
4813 std::reverse(Operands.
begin(), Operands.
end());
4841 Vec = getVSlide(ContainerVT, DAG.
getUNDEF(ContainerVT), Vec,
Offset, Mask,
4848 Opcode = SlideUp ? RISCVISD::VFSLIDE1UP_VL : RISCVISD::VFSLIDE1DOWN_VL;
4850 Opcode = SlideUp ? RISCVISD::VSLIDE1UP_VL : RISCVISD::VSLIDE1DOWN_VL;
4859 Vec = getVSlide(ContainerVT, DAG.
getUNDEF(ContainerVT), Vec,
Offset, Mask,
4875 if ((LoC >> 31) == HiC)
4876 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4888 auto InterVec = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, InterVT,
4897 Hi.getConstantOperandVal(1) == 31)
4898 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4903 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4906 return DAG.
getNode(RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL,
DL, VT, Passthru,
Lo,
4916 assert(Scalar.getValueType() == MVT::i64 &&
"Unexpected VT!");
4928 bool HasPassthru = Passthru && !Passthru.
isUndef();
4929 if (!HasPassthru && !Passthru)
4936 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
4938 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4939 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
4940 Scalar = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Scalar);
4949 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL, VT, Passthru, Scalar, VL);
4953 if (Scalar.getValueType().bitsLE(XLenVT)) {
4960 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4961 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru, Scalar, VL);
4964 assert(XLenVT == MVT::i32 && Scalar.getValueType() == MVT::i64 &&
4965 "Unexpected scalar for splat lowering!");
4968 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, VT, Passthru,
4994 MVT ExtractedContainerVT = ExtractedVT;
4997 DAG, ExtractedContainerVT, Subtarget);
4999 ExtractedVal, DAG, Subtarget);
5001 if (ExtractedContainerVT.
bitsLE(VT))
5013 if (!Scalar.getValueType().bitsLE(XLenVT))
5016 VT,
DL, DAG, Subtarget);
5024 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
5065 Src && Src.
getValueType().getVectorNumElements() == (NumElts * 2))
5082 !Subtarget.hasVendorXRivosVizip())
5085 int Size = Mask.size();
5087 assert(
Size == (
int)NumElts &&
"Unexpected mask size");
5093 EvenSrc = StartIndexes[0];
5094 OddSrc = StartIndexes[1];
5097 if (EvenSrc != 0 && OddSrc != 0)
5107 int HalfNumElts = NumElts / 2;
5108 return ((EvenSrc % HalfNumElts) == 0) && ((OddSrc % HalfNumElts) == 0);
5113 std::array<std::pair<int, int>, 2> &SrcInfo) {
5118 if (SrcInfo[0].second == 0 && SrcInfo[1].second == 0)
5122 if ((SrcInfo[0].second > 0 && SrcInfo[1].second < 0) ||
5123 SrcInfo[1].second == 0)
5125 assert(SrcInfo[0].first != -1 &&
"Must find one slide");
5133 if (SrcInfo[1].first == -1)
5135 return SrcInfo[0].second < 0 && SrcInfo[1].second > 0 &&
5136 SrcInfo[1].second - SrcInfo[0].second == (int)NumElts;
5141 bool RequiredPolarity) {
5142 int NumElts = Mask.size();
5143 for (
const auto &[Idx, M] :
enumerate(Mask)) {
5146 int Src = M >= NumElts;
5147 int Diff = (int)Idx - (M % NumElts);
5148 bool C = Src == SrcInfo[1].first && Diff == SrcInfo[1].second;
5149 assert(
C != (Src == SrcInfo[0].first && Diff == SrcInfo[0].second) &&
5150 "Must match exactly one of the two slides");
5151 if (RequiredPolarity != (
C == (Idx / Factor) % 2))
5162static bool isZipEven(
const std::array<std::pair<int, int>, 2> &SrcInfo,
5164 Factor = SrcInfo[1].second;
5166 Mask.size() % Factor == 0 &&
5177static bool isZipOdd(
const std::array<std::pair<int, int>, 2> &SrcInfo,
5179 Factor = -SrcInfo[1].second;
5181 Mask.size() % Factor == 0 &&
5194 ElementCount SrcEC = Src.getValueType().getVectorElementCount();
5201 unsigned Shift = Index * EltBits;
5226 std::optional<int> SplatIdx;
5228 if (M == -1 ||
I == (
unsigned)M)
5230 if (SplatIdx && *SplatIdx != M)
5239 for (
int MaskIndex : Mask) {
5240 bool SelectMaskVal = MaskIndex == *SplatIdx;
5243 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
5268 auto findNonEXTRACT_SUBVECTORParent =
5269 [](
SDValue Parent) -> std::pair<SDValue, uint64_t> {
5274 Parent.getOperand(0).getSimpleValueType().isFixedLengthVector()) {
5275 Offset += Parent.getConstantOperandVal(1);
5276 Parent = Parent.getOperand(0);
5278 return std::make_pair(Parent,
Offset);
5281 auto [V1Src, V1IndexOffset] = findNonEXTRACT_SUBVECTORParent(V1);
5282 auto [V2Src, V2IndexOffset] = findNonEXTRACT_SUBVECTORParent(V2);
5291 for (
size_t i = 0; i != NewMask.
size(); ++i) {
5292 if (NewMask[i] == -1)
5295 if (
static_cast<size_t>(NewMask[i]) < NewMask.
size()) {
5296 NewMask[i] = NewMask[i] + V1IndexOffset;
5300 NewMask[i] = NewMask[i] - NewMask.
size() + V2IndexOffset;
5306 if (NewMask[0] <= 0)
5310 for (
unsigned i = 1; i != NewMask.
size(); ++i)
5311 if (NewMask[i - 1] + 1 != NewMask[i])
5315 MVT SrcVT = Src.getSimpleValueType();
5344 int NumSubElts, Index;
5349 bool OpsSwapped = Mask[Index] < (int)NumElts;
5350 SDValue InPlace = OpsSwapped ? V2 : V1;
5351 SDValue ToInsert = OpsSwapped ? V1 : V2;
5362 if (NumSubElts + Index >= (
int)NumElts)
5373 Res = DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, ContainerVT, InPlace, ToInsert,
5376 Res =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, InPlace, ToInsert,
5388 bool OpsSwapped =
false;
5403 const unsigned E = Mask.size() - ((
Offset > 0) ?
Offset : 0);
5404 for (
unsigned i = S; i !=
E; ++i)
5405 if (Mask[i] >= 0 && (
unsigned)Mask[i] !=
Base + i +
Offset)
5411 bool IsVSlidedown = isSlideMask(Mask, OpsSwapped ? 0 : NumElts, 1);
5412 if (!IsVSlidedown && !isSlideMask(Mask, OpsSwapped ? 0 : NumElts, -1))
5415 const int InsertIdx = Mask[IsVSlidedown ? (NumElts - 1) : 0];
5417 if (InsertIdx < 0 || InsertIdx / NumElts != (
unsigned)OpsSwapped)
5434 IsVSlidedown ? RISCVISD::VSLIDE1DOWN_VL : RISCVISD::VSLIDE1UP_VL,
DL,
5440 auto OpCode = IsVSlidedown ?
5441 (VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1DOWN_VL : RISCVISD::VSLIDE1DOWN_VL) :
5442 (VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1UP_VL : RISCVISD::VSLIDE1UP_VL);
5445 auto Vec = DAG.
getNode(OpCode,
DL, ContainerVT,
5448 Splat, TrueMask, VL);
5460 for (
unsigned i = 0; i < Mask.size(); i++)
5461 LaneIsUndef[i % Factor] &= (Mask[i] == -1);
5464 for (
unsigned i = 0; i < Factor; i++) {
5475 for (
unsigned i = 0; i < Mask.size() / Factor; i++) {
5476 unsigned j = i * Factor + Index;
5477 if (Mask[j] != -1 && (
unsigned)Mask[j] != i)
5486 assert(RISCVISD::RI_VZIPEVEN_VL ==
Opc || RISCVISD::RI_VZIPODD_VL ==
Opc ||
5487 RISCVISD::RI_VZIP2A_VL ==
Opc || RISCVISD::RI_VZIP2B_VL ==
Opc ||
5488 RISCVISD::RI_VUNZIP2A_VL ==
Opc || RISCVISD::RI_VUNZIP2B_VL ==
Opc);
5496 MVT ContainerVT = IntVT;
5503 MVT InnerVT = ContainerVT;
5507 (RISCVISD::RI_VUNZIP2A_VL ==
Opc || RISCVISD::RI_VUNZIP2B_VL ==
Opc)) {
5519 if (InnerVT.
bitsLT(ContainerVT))
5534 MVT VT = V.getSimpleValueType();
5549 EC.multiplyCoefficientBy(Factor));
5568 MVT VecContainerVT = VecVT;
5585 MVT WideContainerVT = WideVT;
5591 EvenV = DAG.
getBitcast(VecContainerVT, EvenV);
5598 if (Subtarget.hasStdExtZvbb()) {
5602 Interleaved = DAG.
getNode(RISCVISD::VWSLL_VL,
DL, WideContainerVT, OddV,
5603 OffsetVec, Passthru, Mask, VL);
5604 Interleaved = DAG.
getNode(RISCVISD::VWADDU_W_VL,
DL, WideContainerVT,
5605 Interleaved, EvenV, Passthru, Mask, VL);
5612 Interleaved = DAG.
getNode(RISCVISD::VWADDU_VL,
DL, WideContainerVT, EvenV,
5613 OddV, Passthru, Mask, VL);
5619 OddV, AllOnesVec, Passthru, Mask, VL);
5626 Interleaved = DAG.
getNode(RISCVISD::ADD_VL,
DL, WideContainerVT,
5627 Interleaved, OddsMul, Passthru, Mask, VL);
5634 Interleaved = DAG.
getBitcast(ResultContainerVT, Interleaved);
5680 if (ViaEltSize > NumElts)
5688 if (ViaEltSize > NumElts)
5694 if (ViaEltSize > NumElts)
5701 MVT &RotateVT,
unsigned &RotateAmt) {
5704 unsigned NumSubElts;
5706 NumElts, NumSubElts, RotateAmt))
5709 NumElts / NumSubElts);
5777 unsigned NumOfSrcRegs = NumElts / NumOpElts;
5778 unsigned NumOfDestRegs = NumElts / NumOpElts;
5787 Mask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs,
5789 [&](
ArrayRef<int> SrcSubMask,
unsigned SrcVecIdx,
unsigned DstVecIdx) {
5790 Operands.
emplace_back().emplace_back(SrcVecIdx, UINT_MAX,
5793 [&](
ArrayRef<int> SrcSubMask,
unsigned Idx1,
unsigned Idx2,
bool NewReg) {
5798 assert(Operands.
size() == NumOfDestRegs &&
"Whole vector must be processed");
5803 unsigned NumShuffles = std::accumulate(
5804 Operands.
begin(), Operands.
end(), 0u,
5810 for (const auto &P : Data) {
5811 unsigned Idx2 = std::get<1>(P);
5812 ArrayRef<int> Mask = std::get<2>(P);
5813 if (Idx2 != UINT_MAX)
5815 else if (ShuffleVectorInst::isIdentityMask(Mask, Mask.size()))
5820 if ((NumOfDestRegs > 2 && NumShuffles > NumOfDestRegs) ||
5821 (NumOfDestRegs <= 2 && NumShuffles >= 4))
5823 auto ExtractValue = [&, &DAG = DAG](
SDValue SrcVec,
unsigned ExtractIdx) {
5824 SDValue SubVec = DAG.getExtractSubvector(
DL, M1VT, SrcVec, ExtractIdx);
5828 auto PerformShuffle = [&, &DAG = DAG](
SDValue SubVec1,
SDValue SubVec2,
5830 SDValue SubVec = DAG.getVectorShuffle(OneRegVT,
DL, SubVec1, SubVec2, Mask);
5833 SDValue Vec = DAG.getUNDEF(ContainerVT);
5839 const auto &[Idx1, Idx2,
_] =
Data[
I];
5847 V = ExtractValue(Idx1 >= NumOfSrcRegs ? V2 : V1,
5848 (Idx1 % NumOfSrcRegs) * NumOpElts);
5849 if (Idx2 != UINT_MAX) {
5852 V = ExtractValue(Idx2 >= NumOfSrcRegs ? V2 : V1,
5853 (Idx2 % NumOfSrcRegs) * NumOpElts);
5857 for (
const auto &[Idx1, Idx2, Mask] :
Data) {
5859 SDValue V2 = Idx2 == UINT_MAX ? V1 : Values.
at(Idx2);
5860 V = PerformShuffle(V1, V2, Mask);
5864 unsigned InsertIdx =
I * NumOpElts;
5866 Vec = DAG.getInsertSubvector(
DL, Vec, V, InsertIdx);
5876 bool SawUndef =
false;
5877 for (
const auto &[Idx, M] :
enumerate(Mask)) {
5884 if (Idx > (
unsigned)M)
5917 for (
int Idx : Mask) {
5920 unsigned SrcIdx = Idx % Mask.size();
5921 int Src = (
uint32_t)Idx < Mask.size() ? 0 : 1;
5922 if (Srcs[SrcIdx] == -1)
5925 else if (Srcs[SrcIdx] != Src)
5931 for (
int Lane : Srcs) {
5944 for (
unsigned I = 0;
I < Mask.size();
I++) {
5948 NewMask[
I] = Mask[
I] % Mask.size();
5962 if ((M / Span) != (
int)(
I / Span))
5964 int SpanIdx =
I % Span;
5974 return all_of(Mask, [&](
const auto &Idx) {
return Idx == -1 || Idx < Span; });
5986 int SpanIdx =
I % Span;
5987 if (Mask[SpanIdx] != M)
6001 MVT VT =
Op.getSimpleValueType();
6009 if (ElementSize > 32)
6032 MVT VT =
Op.getSimpleValueType();
6060 auto [TrueMask, VL] = TrueMaskVL;
6075 V.getOperand(0).getSimpleValueType().getVectorNumElements();
6076 V = V.getOperand(
Offset / OpElements);
6106 MVT SplatVT = ContainerVT;
6109 if (SVT == MVT::bf16 ||
6110 (SVT == MVT::f16 && !Subtarget.hasStdExtZfh())) {
6119 V = DAG.
getLoad(SVT,
DL, Ld->getChain(), NewAddr,
6120 Ld->getPointerInfo().getWithOffset(
Offset),
6121 Ld->getBaseAlign(), Ld->getMemOperand()->
getFlags());
6124 Ld->getPointerInfo().getWithOffset(
Offset), SVT,
6126 Ld->getMemOperand()->getFlags());
6130 : RISCVISD::VMV_V_X_VL;
6138 assert(Lane < (
int)NumElts &&
"Unexpected lane!");
6141 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
6163 if (Subtarget.hasStdExtZvkb())
6179 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
6180 for (
unsigned Factor = 2; Factor <= MaxFactor; Factor <<= 1) {
6183 1 <
count_if(Mask, [](
int Idx) {
return Idx != -1; })) {
6187 [&Mask](
int Idx) {
return Idx < (int)Mask.size(); }) &&
6188 1 <
count_if(Mask, [&Mask](
int Idx) {
6189 return Idx >= (int)Mask.size();
6219 if (Subtarget.hasVendorXRivosVizip() &&
6221 1 <
count_if(Mask, [](
int Idx) {
return Idx != -1; })) {
6223 Index == 0 ? RISCVISD::RI_VUNZIP2A_VL : RISCVISD::RI_VUNZIP2B_VL;
6239 [&Mask](
int Idx) {
return Idx < (int)Mask.size(); }) &&
6241 [&Mask](
int Idx) {
return Idx >= (int)Mask.size(); })) {
6245 if (NumElts < MinVLMAX) {
6269 int EvenSrc, OddSrc;
6279 bool LaneIsUndef[2] = {
true,
true};
6280 for (
const auto &[Idx, M] :
enumerate(Mask))
6281 LaneIsUndef[Idx % 2] &= (M == -1);
6283 int Size = Mask.size();
6285 if (LaneIsUndef[0]) {
6288 assert(EvenSrc >= 0 &&
"Undef source?");
6289 EvenV = (EvenSrc /
Size) == 0 ? V1 : V2;
6293 if (LaneIsUndef[1]) {
6296 assert(OddSrc >= 0 &&
"Undef source?");
6297 OddV = (OddSrc /
Size) == 0 ? V1 : V2;
6303 if (Subtarget.hasVendorXRivosVizip()) {
6306 return lowerVZIP(RISCVISD::RI_VZIP2A_VL, EvenV, OddV,
DL, DAG, Subtarget);
6317 std::array<std::pair<int, int>, 2> SrcInfo;
6324 auto GetSourceFor = [&](
const std::pair<int, int> &
Info) {
6325 int SrcIdx =
Info.first;
6326 assert(SrcIdx == 0 || SrcIdx == 1);
6327 SDValue &Src = Sources[SrcIdx];
6329 SDValue SrcV = SrcIdx == 0 ? V1 : V2;
6334 auto GetSlide = [&](
const std::pair<int, int> &Src,
SDValue Mask,
6336 auto [TrueMask, VL] = TrueMaskVL;
6337 SDValue SrcV = GetSourceFor(Src);
6338 int SlideAmt = Src.second;
6339 if (SlideAmt == 0) {
6341 assert(Mask == TrueMask);
6348 return getVSlideup(DAG, Subtarget,
DL, ContainerVT, Passthru, SrcV,
6353 if (SrcInfo[1].first == -1) {
6355 Res = GetSlide(SrcInfo[0], TrueMask, Res);
6359 if (Subtarget.hasVendorXRivosVizip()) {
6360 bool TryWiden =
false;
6364 SDValue Src1 = SrcInfo[0].first == 0 ? V1 : V2;
6365 SDValue Src2 = SrcInfo[1].first == 0 ? V1 : V2;
6366 return lowerVZIP(RISCVISD::RI_VZIPEVEN_VL, Src1, Src2,
DL, DAG,
6371 if (
isZipOdd(SrcInfo, Mask, Factor)) {
6373 SDValue Src1 = SrcInfo[1].first == 0 ? V1 : V2;
6374 SDValue Src2 = SrcInfo[0].first == 0 ? V1 : V2;
6375 return lowerVZIP(RISCVISD::RI_VZIPODD_VL, Src1, Src2,
DL, DAG,
6393 for (
const auto &[Idx, M] :
enumerate(Mask)) {
6395 (SrcInfo[1].second > 0 && Idx < (
unsigned)SrcInfo[1].second)) {
6399 int Src = M >= (int)NumElts;
6400 int Diff = (int)Idx - (M % NumElts);
6401 bool C = Src == SrcInfo[1].first && Diff == SrcInfo[1].second;
6402 assert(
C ^ (Src == SrcInfo[0].first && Diff == SrcInfo[0].second) &&
6403 "Must match exactly one of the two slides");
6406 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
6413 Res = GetSlide(SrcInfo[0], TrueMask, Res);
6414 Res = GetSlide(SrcInfo[1], SelectMask, Res);
6419 assert(!V1.
isUndef() &&
"Unexpected shuffle canonicalization");
6434 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
6435 for (
unsigned Factor = 4; Factor <= MaxFactor; Factor <<= 1) {
6450 if (NumElts > MinVLMAX) {
6451 unsigned MaxIdx = 0;
6455 MaxIdx = std::max(std::max((
unsigned)
I, (
unsigned)M), MaxIdx);
6457 unsigned NewNumElts =
6459 if (NewNumElts != NumElts) {
6463 Mask.take_front(NewNumElts));
6480 for (
auto Idx : Mask) {
6483 assert(Idx >= 0 && (
unsigned)Idx < NumElts);
6493 any_of(Mask, [&](
const auto &Idx) {
return Idx > 255; })) {
6503 unsigned GatherVVOpc = RISCVISD::VRGATHER_VV_VL;
6509 GatherVVOpc = RISCVISD::VRGATHEREI16_VV_VL;
6518 GatherVVOpc = RISCVISD::VRGATHEREI16_VV_VL;
6522 MVT IndexContainerVT =
6527 for (
int MaskIndex : Mask) {
6528 bool IsLHSIndex = MaskIndex < (int)NumElts && MaskIndex >= 0;
6538 if (NumElts <= MinVLMAX) {
6540 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
6546 auto [InnerTrueMask, InnerVL] =
6558 for (
int i = 0; i <
N; i++) {
6562 DAG.
getNode(GatherVVOpc,
DL, M1VT, SubV1, SubIndex,
6563 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6580 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6582 for (
int i = 0; i <
N; i++)
6598 for (
int i = 0; i <
N; i++) {
6601 DAG.
getUNDEF(IndexContainerVT), LHSIndices,
6602 SlideAmt, TrueMask, VL);
6606 DAG.
getNode(GatherVVOpc,
DL, M1VT, SubV1, SubIndex,
6607 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6617 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
6627 for (
int MaskIndex : Mask) {
6628 bool IsLHSOrUndefIndex = MaskIndex < (int)NumElts;
6629 ShuffleMaskLHS.
push_back(IsLHSOrUndefIndex && MaskIndex >= 0
6631 ShuffleMaskRHS.
push_back(IsLHSOrUndefIndex ? -1 : (MaskIndex - NumElts));
6662 for (
int MaskIndex : Mask) {
6663 bool SelectMaskVal = (MaskIndex < (int)NumElts) ^ !SwapOps;
6667 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
6685 const unsigned NumElts = M.size();
6692 std::array<std::pair<int, int>, 2> SrcInfo;
6703RISCVTargetLowering::lowerCTLZ_CTTZ_ZERO_UNDEF(
SDValue Op,
6705 MVT VT =
Op.getSimpleValueType();
6709 MVT ContainerVT = VT;
6712 if (
Op->isVPOpcode()) {
6713 Mask =
Op.getOperand(1);
6717 VL =
Op.getOperand(2);
6723 MVT FloatEltVT = (EltSize >= 32) ? MVT::f64 :
MVT::f32;
6725 FloatEltVT = MVT::f32;
6732 "Expected legal float type!");
6739 }
else if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF) {
6742 Src = DAG.
getNode(ISD::VP_AND,
DL, VT, Src, Neg, Mask, VL);
6747 if (FloatVT.
bitsGT(VT)) {
6748 if (
Op->isVPOpcode())
6749 FloatVal = DAG.
getNode(ISD::VP_UINT_TO_FP,
DL, FloatVT, Src, Mask, VL);
6758 if (!
Op->isVPOpcode())
6762 MVT ContainerFloatVT =
6764 FloatVal = DAG.
getNode(RISCVISD::VFCVT_RM_F_XU_VL,
DL, ContainerFloatVT,
6765 Src, Mask, RTZRM, VL);
6772 unsigned ShiftAmt = FloatEltVT == MVT::f64 ? 52 : 23;
6776 if (
Op->isVPOpcode()) {
6785 else if (IntVT.
bitsGT(VT))
6790 unsigned ExponentBias = FloatEltVT == MVT::f64 ? 1023 : 127;
6795 if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF)
6796 return DAG.
getNode(ISD::VP_SUB,
DL, VT, Exp,
6801 unsigned Adjust = ExponentBias + (EltSize - 1);
6803 if (
Op->isVPOpcode())
6813 else if (
Op.getOpcode() == ISD::VP_CTLZ)
6814 Res = DAG.
getNode(ISD::VP_UMIN,
DL, VT, Res,
6822 MVT XLenVT = Subtarget.getXLenVT();
6824 MVT SrcVT =
Source.getSimpleValueType();
6833 SrcVT = ContainerVT;
6845 SDValue Res = DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Source, Mask, EVL);
6846 if (
Op->getOpcode() == ISD::VP_CTTZ_ELTS_ZERO_UNDEF)
6864 assert(Load &&
Load->getMemoryVT().isVector() &&
"Expected vector load");
6867 Load->getMemoryVT(),
6868 *
Load->getMemOperand()))
6872 MVT VT =
Op.getSimpleValueType();
6874 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
6875 "Unexpected unaligned RVV load type");
6879 "Expecting equally-sized RVV vector types to be legal");
6881 Load->getPointerInfo(),
Load->getBaseAlign(),
6882 Load->getMemOperand()->getFlags());
6893 assert(Store &&
Store->getValue().getValueType().isVector() &&
6894 "Expected vector store");
6897 Store->getMemoryVT(),
6898 *
Store->getMemOperand()))
6905 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
6906 "Unexpected unaligned RVV store type");
6910 "Expecting equally-sized RVV vector types to be legal");
6911 StoredVal = DAG.
getBitcast(NewVT, StoredVal);
6913 Store->getPointerInfo(),
Store->getBaseAlign(),
6914 Store->getMemOperand()->getFlags());
6924 assert(Load &&
Load->getMemoryVT().isVector() &&
"Expected vector load");
6927 Load->getMemoryVT(),
6928 *
Load->getMemOperand()))
6938 MVT VT =
Op.getSimpleValueType();
6940 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
6941 "Unexpected unaligned RVV load type");
6945 "Expecting equally-sized RVV vector types to be legal");
6954 Load->getPointerInfo(),
Load->getBaseAlign(),
6955 Load->getMemOperand()->getFlags(), AAMDNodes());
6966 assert(Store &&
Store->getValue().getValueType().isVector() &&
6967 "Expected vector store");
6970 Store->getMemoryVT(),
6971 *
Store->getMemOperand()))
6984 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
6985 "Unexpected unaligned RVV store type");
6989 "Expecting equally-sized RVV vector types to be legal");
6995 StoredVal = DAG.
getBitcast(NewVT, StoredVal);
7000 Store->getPointerInfo(),
Store->getMemOperand()->getFlags(),
Size,
7001 Store->getBaseAlign());
7012 assert(
Op.getValueType() == MVT::i64 &&
"Unexpected VT");
7041 unsigned ShiftAmt, AddOpc;
7052 MVT VT =
Op.getSimpleValueType();
7056 bool Negate =
false;
7060 if (Index < 0 &&
Imm.isNegative()) {
7083 unsigned IsData =
Op.getConstantOperandVal(4);
7086 if (Subtarget.hasVendorXMIPSCBOP() && !IsData)
7087 return Op.getOperand(0);
7099 if (Subtarget.hasStdExtZtso()) {
7123 MVT VT =
Op.getSimpleValueType();
7124 MVT XLenVT = Subtarget.getXLenVT();
7125 unsigned Check =
Op.getConstantOperandVal(1);
7126 unsigned TDCMask = 0;
7154 MVT VT0 =
Op.getOperand(0).getSimpleValueType();
7159 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
7161 VL =
Op.getOperand(3);
7164 VL,
Op->getFlags());
7179 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
7181 MVT MaskContainerVT =
7184 VL =
Op.getOperand(3);
7188 SDValue FPCLASS = DAG.
getNode(RISCVISD::FCLASS_VL,
DL, ContainerDstVT, Op0,
7189 Mask, VL,
Op->getFlags());
7191 TDCMaskV = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerDstVT,
7192 DAG.
getUNDEF(ContainerDstVT), TDCMaskV, VL);
7195 DAG.
getNode(RISCVISD::SETCC_VL,
DL, ContainerVT,
7201 TDCMaskV, DAG.
getUNDEF(ContainerDstVT), Mask, VL);
7204 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerDstVT,
7205 DAG.
getUNDEF(ContainerDstVT), SplatZero, VL);
7225 MVT VT =
Op.getSimpleValueType();
7259 MVT ContainerVT = VT;
7267 if (
Op->isVPOpcode()) {
7268 Mask =
Op.getOperand(2);
7272 VL =
Op.getOperand(3);
7279 SDValue XIsNonNan = DAG.
getNode(RISCVISD::SETCC_VL,
DL, Mask.getValueType(),
7280 {X, X, DAG.getCondCode(ISD::SETOEQ),
7281 DAG.getUNDEF(ContainerVT), Mask, VL});
7282 NewY = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, XIsNonNan,
Y,
X,
7288 SDValue YIsNonNan = DAG.
getNode(RISCVISD::SETCC_VL,
DL, Mask.getValueType(),
7289 {Y, Y, DAG.getCondCode(ISD::SETOEQ),
7290 DAG.getUNDEF(ContainerVT), Mask, VL});
7291 NewX = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, YIsNonNan,
X,
Y,
7297 ? RISCVISD::VFMAX_VL
7298 : RISCVISD::VFMIN_VL;
7300 DAG.
getUNDEF(ContainerVT), Mask, VL);
7310 "Wrong opcode for lowering FABS or FNEG.");
7313 MVT VT =
Op.getSimpleValueType();
7314 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
7318 DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT,
Op.getOperand(0));
7321 Mask = Mask.sext(Subtarget.
getXLen());
7326 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, Logic);
7334 MVT VT =
Op.getSimpleValueType();
7335 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
7345 if (SignSize == Subtarget.
getXLen())
7349 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Sign);
7351 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, XLenVT, Sign);
7353 assert(XLenVT == MVT::i32 &&
"Unexpected type");
7356 return DAG.
getNode(RISCVISD::SplitF64,
DL, {MVT::i32, MVT::i32}, Sign)
7386 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, CopiedSign);
7391#define OP_CASE(NODE) \
7393 return RISCVISD::NODE##_VL;
7394#define VP_CASE(NODE) \
7395 case ISD::VP_##NODE: \
7396 return RISCVISD::NODE##_VL;
7398 switch (
Op.getOpcode()) {
7477 case ISD::VP_CTLZ_ZERO_UNDEF:
7478 return RISCVISD::CTLZ_VL;
7480 case ISD::VP_CTTZ_ZERO_UNDEF:
7481 return RISCVISD::CTTZ_VL;
7484 return RISCVISD::VFMADD_VL;
7486 return RISCVISD::STRICT_VFMADD_VL;
7489 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7490 return RISCVISD::VMAND_VL;
7491 return RISCVISD::AND_VL;
7494 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7495 return RISCVISD::VMOR_VL;
7496 return RISCVISD::OR_VL;
7499 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7500 return RISCVISD::VMXOR_VL;
7501 return RISCVISD::XOR_VL;
7504 return RISCVISD::VZEXT_VL;
7506 return RISCVISD::VSEXT_VL;
7508 return RISCVISD::SETCC_VL;
7510 return RISCVISD::VMERGE_VL;
7511 case ISD::VP_SELECT:
7513 return RISCVISD::VMERGE_VL;
7515 return RISCVISD::SRA_VL;
7517 return RISCVISD::SRL_VL;
7519 return RISCVISD::FSQRT_VL;
7520 case ISD::VP_SIGN_EXTEND:
7521 return RISCVISD::VSEXT_VL;
7522 case ISD::VP_ZERO_EXTEND:
7523 return RISCVISD::VZEXT_VL;
7524 case ISD::VP_FP_TO_SINT:
7525 return RISCVISD::VFCVT_RTZ_X_F_VL;
7526 case ISD::VP_FP_TO_UINT:
7527 return RISCVISD::VFCVT_RTZ_XU_F_VL;
7530 case ISD::VP_FMINNUM:
7531 return RISCVISD::VFMIN_VL;
7534 case ISD::VP_FMAXNUM:
7535 return RISCVISD::VFMAX_VL;
7539 case ISD::VP_LLRINT:
7540 return RISCVISD::VFCVT_RM_X_F_VL;
7549 return (
Op.getValueType() == MVT::nxv32f16 &&
7552 (
Op.getValueType() == MVT::nxv32bf16 &&
7566 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7567 if (!
Op.getOperand(j).getValueType().isVector()) {
7568 LoOperands[j] =
Op.getOperand(j);
7569 HiOperands[j] =
Op.getOperand(j);
7572 std::tie(LoOperands[j], HiOperands[j]) =
7577 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
7579 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
7592 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7594 std::tie(LoOperands[j], HiOperands[j]) =
7598 if (!
Op.getOperand(j).getValueType().isVector()) {
7599 LoOperands[j] =
Op.getOperand(j);
7600 HiOperands[j] =
Op.getOperand(j);
7603 std::tie(LoOperands[j], HiOperands[j]) =
7608 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
7610 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
7620 auto [EVLLo, EVLHi] =
7621 DAG.
SplitEVL(
Op.getOperand(3),
Op.getOperand(1).getValueType(),
DL);
7625 {Op.getOperand(0), Lo, MaskLo, EVLLo},
Op->getFlags());
7627 {ResLo, Hi, MaskHi, EVLHi},
Op->getFlags());
7644 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7645 if (!
Op.getOperand(j).getValueType().isVector()) {
7646 LoOperands[j] =
Op.getOperand(j);
7647 HiOperands[j] =
Op.getOperand(j);
7650 std::tie(LoOperands[j], HiOperands[j]) =
7655 DAG.
getNode(
Op.getOpcode(),
DL, LoVTs, LoOperands,
Op->getFlags());
7658 DAG.
getNode(
Op.getOpcode(),
DL, HiVTs, HiOperands,
Op->getFlags());
7666RISCVTargetLowering::lowerXAndesBfHCvtBFloat16Load(
SDValue Op,
7668 assert(Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh() &&
7669 "Unexpected bfloat16 load lowering");
7673 EVT MemVT =
LD->getMemoryVT();
7678 LD->getMemOperand());
7686 DAG.
getNode(RISCVISD::NDS_FMV_BF16_X,
DL, MVT::bf16, OrSixteenOne);
7691RISCVTargetLowering::lowerXAndesBfHCvtBFloat16Store(
SDValue Op,
7693 assert(Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh() &&
7694 "Unexpected bfloat16 store lowering");
7699 Subtarget.getXLenVT(),
ST->getValue());
7701 ST->getChain(),
DL, FMV,
ST->getBasePtr(),
7703 ST->getMemOperand());
7708 switch (
Op.getOpcode()) {
7711 "Unimplemented RISCVTargetLowering::LowerOperation Case");
7717 return lowerGlobalAddress(
Op, DAG);
7719 return lowerBlockAddress(
Op, DAG);
7721 return lowerConstantPool(
Op, DAG);
7723 return lowerJumpTable(
Op, DAG);
7725 return lowerGlobalTLSAddress(
Op, DAG);
7729 return lowerConstantFP(
Op, DAG);
7731 return lowerSELECT(
Op, DAG);
7733 return lowerBRCOND(
Op, DAG);
7735 return lowerVASTART(
Op, DAG);
7737 return lowerFRAMEADDR(
Op, DAG);
7739 return lowerRETURNADDR(
Op, DAG);
7741 return lowerShiftLeftParts(
Op, DAG);
7743 return lowerShiftRightParts(
Op, DAG,
true);
7745 return lowerShiftRightParts(
Op, DAG,
false);
7748 if (
Op.getValueType().isFixedLengthVector()) {
7749 assert(Subtarget.hasStdExtZvkb());
7750 return lowerToScalableOp(
Op, DAG);
7752 assert(Subtarget.hasVendorXTHeadBb() &&
7753 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
7754 "Unexpected custom legalization");
7761 EVT VT =
Op.getValueType();
7764 MVT XLenVT = Subtarget.getXLenVT();
7765 if (Op0VT == MVT::i16 &&
7766 ((VT == MVT::f16 && Subtarget.hasStdExtZfhminOrZhinxmin()) ||
7767 (VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
7769 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, NewOp0);
7771 if (VT == MVT::f32 && Op0VT == MVT::i32 && Subtarget.is64Bit() &&
7772 Subtarget.hasStdExtFOrZfinx()) {
7774 return DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, NewOp0);
7776 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit() &&
7777 Subtarget.hasStdExtDOrZdinx()) {
7780 return DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64,
Lo,
Hi);
7783 if (Subtarget.enablePExtCodeGen()) {
7785 (VT == MVT::i32 && (Op0VT == MVT::v4i8 || Op0VT == MVT::v2i16)) ||
7786 (Op0VT == MVT::i32 && (VT == MVT::v4i8 || VT == MVT::v2i16));
7788 (VT == MVT::i64 && (Op0VT == MVT::v8i8 || Op0VT == MVT::v4i16 ||
7789 Op0VT == MVT::v2i32)) ||
7790 (Op0VT == MVT::i64 &&
7791 (VT == MVT::v8i8 || VT == MVT::v4i16 || VT == MVT::v2i32));
7792 if (Is32BitCast || Is64BitCast)
7805 "Unexpected types");
7837 return LowerINTRINSIC_WO_CHAIN(
Op, DAG);
7839 return LowerINTRINSIC_W_CHAIN(
Op, DAG);
7841 return LowerINTRINSIC_VOID(
Op, DAG);
7843 return LowerIS_FPCLASS(
Op, DAG);
7845 MVT VT =
Op.getSimpleValueType();
7847 assert(Subtarget.hasStdExtZvbb());
7848 return lowerToScalableOp(
Op, DAG);
7851 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected custom legalization");
7855 return DAG.
getNode(RISCVISD::BREV8,
DL, VT, BSwap);
7861 if (!
Op.getSimpleValueType().isVector())
7863 return lowerVectorTruncLike(
Op, DAG);
7866 if (
Op.getOperand(0).getValueType().isVector() &&
7867 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7868 return lowerVectorMaskExt(
Op, DAG, 1);
7869 if (
Op.getValueType().isScalableVector())
7871 return lowerToScalableOp(
Op, DAG);
7873 if (
Op.getOperand(0).getValueType().isVector() &&
7874 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7875 return lowerVectorMaskExt(
Op, DAG, -1);
7876 if (
Op.getValueType().isScalableVector())
7878 return lowerToScalableOp(
Op, DAG);
7880 return lowerSPLAT_VECTOR_PARTS(
Op, DAG);
7882 return lowerINSERT_VECTOR_ELT(
Op, DAG);
7884 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
7886 MVT VT =
Op.getSimpleValueType();
7894 MVT ContainerVT = VT;
7901 V = DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL, ContainerVT,
7902 DAG.
getUNDEF(ContainerVT), Scalar, VL);
7905 V = DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, ContainerVT,
7906 DAG.
getUNDEF(ContainerVT), Scalar, VL);
7913 MVT XLenVT = Subtarget.getXLenVT();
7914 MVT VT =
Op.getSimpleValueType();
7933 }
else if (
Log2 > 3) {
7937 }
else if ((Val % 8) == 0) {
7955 if (
Op.getValueType() == MVT::f16 && Subtarget.is64Bit() &&
7956 Op.getOperand(1).getValueType() == MVT::i32) {
7973 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
7976 return lowerStrictFPExtendOrRoundLike(
Op, DAG);
7979 if (
Op.getValueType().isVector() &&
7980 ((
Op.getValueType().getScalarType() == MVT::f16 &&
7981 (Subtarget.hasVInstructionsF16Minimal() &&
7982 !Subtarget.hasVInstructionsF16())) ||
7983 Op.getValueType().getScalarType() == MVT::bf16)) {
7999 Op1.getValueType().isVector() &&
8000 ((Op1.getValueType().getScalarType() == MVT::f16 &&
8001 (Subtarget.hasVInstructionsF16Minimal() &&
8002 !Subtarget.hasVInstructionsF16())) ||
8003 Op1.getValueType().getScalarType() == MVT::bf16)) {
8009 Op1.getValueType().getVectorElementCount());
8012 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), WidenVec);
8022 MVT VT =
Op.getSimpleValueType();
8025 bool IsStrict =
Op->isStrictFPOpcode();
8026 SDValue Src =
Op.getOperand(0 + IsStrict);
8027 MVT SrcVT = Src.getSimpleValueType();
8038 "Unexpected vector element types");
8042 if (EltSize > (2 * SrcEltSize)) {
8054 Op.getOperand(0), Ext);
8058 assert(SrcEltVT == MVT::f16 &&
"Unexpected FP_TO_[US]INT lowering");
8063 auto [FExt, Chain] =
8065 return DAG.
getNode(
Op.getOpcode(),
DL,
Op->getVTList(), Chain, FExt);
8072 if (SrcEltSize > (2 * EltSize)) {
8075 assert(EltVT == MVT::f16 &&
"Unexpected [US]_TO_FP lowering");
8080 Op.getOperand(0), Src);
8095 Op.getOperand(0), Src);
8109 unsigned RVVOpc = 0;
8110 switch (
Op.getOpcode()) {
8114 RVVOpc = RISCVISD::VFCVT_RTZ_X_F_VL;
8117 RVVOpc = RISCVISD::VFCVT_RTZ_XU_F_VL;
8120 RVVOpc = RISCVISD::SINT_TO_FP_VL;
8123 RVVOpc = RISCVISD::UINT_TO_FP_VL;
8126 RVVOpc = RISCVISD::STRICT_VFCVT_RTZ_X_F_VL;
8129 RVVOpc = RISCVISD::STRICT_VFCVT_RTZ_XU_F_VL;
8132 RVVOpc = RISCVISD::STRICT_SINT_TO_FP_VL;
8135 RVVOpc = RISCVISD::STRICT_UINT_TO_FP_VL;
8142 "Expected same element count");
8149 Op.getOperand(0), Src, Mask, VL);
8153 Src = DAG.
getNode(RVVOpc,
DL, ContainerVT, Src, Mask, VL);
8162 assert(!Subtarget.isSoftFPABI() &&
"Unexpected custom legalization");
8168 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
8169 if (Subtarget.is64Bit())
8170 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Res);
8174 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalization");
8175 MVT VT =
Op.getSimpleValueType();
8180 SDValue Res = Subtarget.is64Bit()
8181 ? DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32,
Op)
8192 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalisation");
8195 bool IsStrict =
Op->isStrictFPOpcode();
8196 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
8200 std::tie(Res, Chain) =
8201 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
8202 if (Subtarget.is64Bit())
8203 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Res);
8213 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalisation");
8216 bool IsStrict =
Op->isStrictFPOpcode();
8217 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
8219 SDValue Arg = Subtarget.is64Bit()
8220 ? DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, Op0)
8223 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
8224 CallOptions,
DL, Chain);
8243 if (
Op.getValueType().isVector())
8245 assert(
Op.getOperand(0).getValueType() == MVT::f16 &&
8246 "Unexpected custom legalisation");
8249 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), Ext);
8255 assert(
Op.getOperand(1).getValueType() == MVT::f16 &&
8256 "Unexpected custom legalisation");
8259 {
Op.getOperand(0),
Op.getOperand(1)});
8260 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
8261 {Ext.getValue(1), Ext.getValue(0)});
8268 return lowerVECREDUCE(
Op, DAG);
8272 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
8273 return lowerVectorMaskVecReduction(
Op, DAG,
false);
8274 return lowerVECREDUCE(
Op, DAG);
8281 return lowerFPVECREDUCE(
Op, DAG);
8282 case ISD::VP_REDUCE_ADD:
8283 case ISD::VP_REDUCE_UMAX:
8284 case ISD::VP_REDUCE_SMAX:
8285 case ISD::VP_REDUCE_UMIN:
8286 case ISD::VP_REDUCE_SMIN:
8287 case ISD::VP_REDUCE_FADD:
8288 case ISD::VP_REDUCE_SEQ_FADD:
8289 case ISD::VP_REDUCE_FMIN:
8290 case ISD::VP_REDUCE_FMAX:
8291 case ISD::VP_REDUCE_FMINIMUM:
8292 case ISD::VP_REDUCE_FMAXIMUM:
8295 return lowerVPREDUCE(
Op, DAG);
8296 case ISD::VP_REDUCE_AND:
8297 case ISD::VP_REDUCE_OR:
8298 case ISD::VP_REDUCE_XOR:
8299 if (
Op.getOperand(1).getValueType().getVectorElementType() == MVT::i1)
8300 return lowerVectorMaskVecReduction(
Op, DAG,
true);
8301 return lowerVPREDUCE(
Op, DAG);
8302 case ISD::VP_CTTZ_ELTS:
8303 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
8304 return lowerVPCttzElements(
Op, DAG);
8308 DAG.
getUNDEF(ContainerVT), DAG, Subtarget);
8311 return lowerINSERT_SUBVECTOR(
Op, DAG);
8313 return lowerEXTRACT_SUBVECTOR(
Op, DAG);
8315 return lowerVECTOR_DEINTERLEAVE(
Op, DAG);
8317 return lowerVECTOR_INTERLEAVE(
Op, DAG);
8319 return lowerSTEP_VECTOR(
Op, DAG);
8321 return lowerVECTOR_REVERSE(
Op, DAG);
8323 return lowerVECTOR_SPLICE(
Op, DAG);
8325 MVT VT =
Op.getSimpleValueType();
8327 if (!Subtarget.is64Bit() && EltVT == MVT::i64)
8332 MVT VT =
Op.getSimpleValueType();
8334 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
8335 EltVT == MVT::bf16) {
8338 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
8339 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
8340 Elt = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, Subtarget.getXLenVT(),
8349 if (EltVT == MVT::i1)
8350 return lowerVectorMaskSplat(
Op, DAG);
8359 MVT VT =
Op.getSimpleValueType();
8360 MVT ContainerVT = VT;
8372 if (
Op.getNumOperands() > 2 &&
8376 size_t HalfNumOps =
Op.getNumOperands() / 2;
8378 Op->ops().take_front(HalfNumOps));
8380 Op->ops().drop_front(HalfNumOps));
8384 unsigned NumOpElts =
8385 Op.getOperand(0).getSimpleValueType().getVectorMinNumElements();
8398 EVT VT = Load->getValueType(0);
8399 if (VT == MVT::f64) {
8400 assert(Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
8401 !Subtarget.is64Bit() &&
"Unexpected custom legalisation");
8405 SDValue BasePtr = Load->getBasePtr();
8406 SDValue Chain = Load->getChain();
8409 DAG.
getLoad(MVT::i32,
DL, Chain, BasePtr, Load->getPointerInfo(),
8410 Load->getBaseAlign(), Load->getMemOperand()->getFlags());
8413 MVT::i32,
DL, Chain, BasePtr, Load->getPointerInfo().getWithOffset(4),
8414 Load->getBaseAlign(), Load->getMemOperand()->getFlags());
8422 if (VT == MVT::bf16)
8423 return lowerXAndesBfHCvtBFloat16Load(
Op, DAG);
8428 MVT XLenVT = Subtarget.getXLenVT();
8431 unsigned NumElts = Sz / (NF * 8);
8432 int Log2LMUL =
Log2_64(NumElts) - 3;
8435 Flag.setNoUnsignedWrap(
true);
8437 SDValue BasePtr = Load->getBasePtr();
8445 for (
unsigned i = 0; i < NF; ++i) {
8450 Ret = DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VT, Ret, LoadVal,
8458 if (
auto V = expandUnalignedRVVLoad(
Op, DAG))
8460 if (
Op.getValueType().isFixedLengthVector())
8461 return lowerFixedLengthVectorLoadToRVV(
Op, DAG);
8466 SDValue StoredVal = Store->getValue();
8468 if (Subtarget.enablePExtCodeGen()) {
8469 if (VT == MVT::v2i16 || VT == MVT::v4i8) {
8473 DAG.
getStore(Store->getChain(),
DL, Cast, Store->getBasePtr(),
8474 Store->getPointerInfo(), Store->getBaseAlign(),
8475 Store->getMemOperand()->getFlags());
8479 if (VT == MVT::f64) {
8480 assert(Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
8481 !Subtarget.is64Bit() &&
"Unexpected custom legalisation");
8485 SDValue BasePtr = Store->getBasePtr();
8486 SDValue Chain = Store->getChain();
8488 DAG.
getVTList(MVT::i32, MVT::i32), StoredVal);
8491 Store->getPointerInfo(), Store->getBaseAlign(),
8492 Store->getMemOperand()->getFlags());
8495 Store->getPointerInfo().getWithOffset(4),
8496 Store->getBaseAlign(),
8497 Store->getMemOperand()->getFlags());
8500 if (VT == MVT::i64) {
8501 assert(Subtarget.hasStdExtZilsd() && !Subtarget.is64Bit() &&
8502 "Unexpected custom legalisation");
8503 if (Store->isTruncatingStore())
8506 if (Store->getAlign() < Subtarget.getZilsdAlign())
8517 {Store->getChain(), Lo, Hi, Store->getBasePtr()}, MVT::i64,
8518 Store->getMemOperand());
8521 if (VT == MVT::bf16)
8522 return lowerXAndesBfHCvtBFloat16Store(
Op, DAG);
8527 MVT XLenVT = Subtarget.getXLenVT();
8530 unsigned NumElts = Sz / (NF * 8);
8531 int Log2LMUL =
Log2_64(NumElts) - 3;
8534 Flag.setNoUnsignedWrap(
true);
8536 SDValue Chain = Store->getChain();
8537 SDValue BasePtr = Store->getBasePtr();
8544 for (
unsigned i = 0; i < NF; ++i) {
8546 DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL,
8549 Ret = DAG.
getStore(Chain,
DL, Extract, BasePtr,
8551 Store->getBaseAlign(),
8552 Store->getMemOperand()->getFlags());
8559 if (
auto V = expandUnalignedRVVStore(
Op, DAG))
8561 if (
Op.getOperand(1).getValueType().isFixedLengthVector())
8562 return lowerFixedLengthVectorStoreToRVV(
Op, DAG);
8566 if (
SDValue V = expandUnalignedVPLoad(
Op, DAG))
8570 return lowerMaskedLoad(
Op, DAG);
8571 case ISD::VP_LOAD_FF:
8572 return lowerLoadFF(
Op, DAG);
8574 if (
SDValue V = expandUnalignedVPStore(
Op, DAG))
8578 return lowerMaskedStore(
Op, DAG);
8580 return lowerVectorCompress(
Op, DAG);
8589 EVT VT =
Op.getValueType();
8600 MVT OpVT =
Op.getOperand(0).getSimpleValueType();
8602 MVT VT =
Op.getSimpleValueType();
8607 "Unexpected CondCode");
8640 return DAG.
getSetCC(
DL, VT, RHS, LHS, CCVal);
8646 return lowerToScalableOp(
Op, DAG);
8663 return lowerToScalableOp(
Op, DAG);
8667 if (
Op.getSimpleValueType().isFixedLengthVector()) {
8668 if (Subtarget.enablePExtCodeGen()) {
8678 return lowerToScalableOp(
Op, DAG);
8681 assert(
Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.is64Bit() &&
8682 "Unexpected custom legalisation");
8686 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
8714 return lowerToScalableOp(
Op, DAG);
8718 EVT VT =
Op->getValueType(0);
8733 return lowerABS(
Op, DAG);
8738 if (Subtarget.hasStdExtZvbb())
8739 return lowerToScalableOp(
Op, DAG);
8741 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8743 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
8747 return lowerToScalableOp(
Op, DAG);
8756 return lowerToScalableOp(
Op, DAG);
8759 return lowerVectorStrictFSetcc(
Op, DAG);
8769 case ISD::VP_GATHER:
8770 return lowerMaskedGather(
Op, DAG);
8772 case ISD::VP_SCATTER:
8773 return lowerMaskedScatter(
Op, DAG);
8775 return lowerGET_ROUNDING(
Op, DAG);
8777 return lowerSET_ROUNDING(
Op, DAG);
8779 return lowerGET_FPENV(
Op, DAG);
8781 return lowerSET_FPENV(
Op, DAG);
8783 return lowerRESET_FPENV(
Op, DAG);
8785 return lowerGET_FPMODE(
Op, DAG);
8787 return lowerSET_FPMODE(
Op, DAG);
8789 return lowerRESET_FPMODE(
Op, DAG);
8791 return lowerEH_DWARF_CFA(
Op, DAG);
8793 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
8794 return lowerVPMergeMask(
Op, DAG);
8796 case ISD::VP_SELECT:
8804 case ISD::VP_UADDSAT:
8805 case ISD::VP_USUBSAT:
8806 case ISD::VP_SADDSAT:
8807 case ISD::VP_SSUBSAT:
8809 case ISD::VP_LLRINT:
8810 return lowerVPOp(
Op, DAG);
8814 return lowerLogicVPOp(
Op, DAG);
8823 case ISD::VP_FMINNUM:
8824 case ISD::VP_FMAXNUM:
8825 case ISD::VP_FCOPYSIGN:
8832 return lowerVPOp(
Op, DAG);
8833 case ISD::VP_IS_FPCLASS:
8834 return LowerIS_FPCLASS(
Op, DAG);
8835 case ISD::VP_SIGN_EXTEND:
8836 case ISD::VP_ZERO_EXTEND:
8837 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
8838 return lowerVPExtMaskOp(
Op, DAG);
8839 return lowerVPOp(
Op, DAG);
8840 case ISD::VP_TRUNCATE:
8841 return lowerVectorTruncLike(
Op, DAG);
8842 case ISD::VP_FP_EXTEND:
8843 case ISD::VP_FP_ROUND:
8844 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
8845 case ISD::VP_SINT_TO_FP:
8846 case ISD::VP_UINT_TO_FP:
8847 if (
Op.getValueType().isVector() &&
8848 ((
Op.getValueType().getScalarType() == MVT::f16 &&
8849 (Subtarget.hasVInstructionsF16Minimal() &&
8850 !Subtarget.hasVInstructionsF16())) ||
8851 Op.getValueType().getScalarType() == MVT::bf16)) {
8864 case ISD::VP_FP_TO_SINT:
8865 case ISD::VP_FP_TO_UINT:
8867 Op1.getValueType().isVector() &&
8868 ((Op1.getValueType().getScalarType() == MVT::f16 &&
8869 (Subtarget.hasVInstructionsF16Minimal() &&
8870 !Subtarget.hasVInstructionsF16())) ||
8871 Op1.getValueType().getScalarType() == MVT::bf16)) {
8877 Op1.getValueType().getVectorElementCount());
8881 {WidenVec, Op.getOperand(1), Op.getOperand(2)});
8883 return lowerVPFPIntConvOp(
Op, DAG);
8887 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
8888 return lowerVPSetCCMaskOp(
Op, DAG);
8894 case ISD::VP_BITREVERSE:
8896 return lowerVPOp(
Op, DAG);
8898 case ISD::VP_CTLZ_ZERO_UNDEF:
8899 if (Subtarget.hasStdExtZvbb())
8900 return lowerVPOp(
Op, DAG);
8901 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8903 case ISD::VP_CTTZ_ZERO_UNDEF:
8904 if (Subtarget.hasStdExtZvbb())
8905 return lowerVPOp(
Op, DAG);
8906 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8908 return lowerVPOp(
Op, DAG);
8909 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
8910 return lowerVPStridedLoad(
Op, DAG);
8911 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
8912 return lowerVPStridedStore(
Op, DAG);
8914 case ISD::VP_FFLOOR:
8916 case ISD::VP_FNEARBYINT:
8917 case ISD::VP_FROUND:
8918 case ISD::VP_FROUNDEVEN:
8919 case ISD::VP_FROUNDTOZERO:
8923 case ISD::VP_FMAXIMUM:
8924 case ISD::VP_FMINIMUM:
8928 case ISD::EXPERIMENTAL_VP_SPLICE:
8929 return lowerVPSpliceExperimental(
Op, DAG);
8930 case ISD::EXPERIMENTAL_VP_REVERSE:
8931 return lowerVPReverseExperimental(
Op, DAG);
8934 "llvm.clear_cache only needs custom lower on Linux targets");
8937 return emitFlushICache(DAG,
Op.getOperand(0),
Op.getOperand(1),
8938 Op.getOperand(2), Flags,
DL);
8941 return lowerDYNAMIC_STACKALLOC(
Op, DAG);
8943 return lowerINIT_TRAMPOLINE(
Op, DAG);
8945 return lowerADJUST_TRAMPOLINE(
Op, DAG);
8949 return lowerPARTIAL_REDUCE_MLA(
Op, DAG);
8956 MakeLibCallOptions CallOptions;
8957 std::pair<SDValue, SDValue> CallResult =
8958 makeLibCall(DAG, RTLIB::RISCV_FLUSH_ICACHE, MVT::isVoid,
8959 {Start, End, Flags}, CallOptions,
DL, InChain);
8962 return CallResult.second;
8967 if (!Subtarget.is64Bit())
8975 std::unique_ptr<MCCodeEmitter> CodeEmitter(
9003 const bool HasCFBranch =
9004 Subtarget.hasStdExtZicfilp() &&
9006 "cf-protection-branch");
9007 const unsigned StaticChainIdx = HasCFBranch ? 5 : 4;
9008 const unsigned StaticChainOffset = StaticChainIdx * 4;
9009 const unsigned FunctionAddressOffset = StaticChainOffset + 8;
9013 auto GetEncoding = [&](
const MCInst &MC) {
9016 CodeEmitter->encodeInstruction(MC, CB, Fixups, *STI);
9023 SmallVector<uint32_t> Encodings;
9028 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X7).addImm(0)),
9032 GetEncoding(MCInstBuilder(RISCV::LD)
9035 .addImm(FunctionAddressOffset)),
9038 GetEncoding(MCInstBuilder(RISCV::LD)
9041 .addImm(StaticChainOffset)),
9044 GetEncoding(MCInstBuilder(RISCV::JALR)
9052 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X0).addImm(0)),
9055 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X28).addImm(0)),
9059 GetEncoding(MCInstBuilder(RISCV::LD)
9062 .addImm(FunctionAddressOffset - 4)),
9065 GetEncoding(MCInstBuilder(RISCV::LD)
9068 .addImm(StaticChainOffset - 4)),
9071 GetEncoding(MCInstBuilder(RISCV::JALR)
9083 Root, dl, DAG.
getConstant(Encoding, dl, MVT::i64), Addr,
9084 MachinePointerInfo(TrmpAddr, Idx * 4), MVT::i32));
9088 SDValue FunctionAddress =
Op.getOperand(2);
9092 struct OffsetValuePair {
9096 } OffsetValues[] = {
9097 {StaticChainOffset, StaticChain},
9098 {FunctionAddressOffset, FunctionAddress},
9100 for (
auto &OffsetValue : OffsetValues) {
9103 DAG.
getConstant(OffsetValue.Offset, dl, MVT::i64));
9104 OffsetValue.Addr = Addr;
9106 DAG.
getStore(Root, dl, OffsetValue.Value, Addr,
9107 MachinePointerInfo(TrmpAddr, OffsetValue.Offset)));
9110 assert(OutChains.
size() == StaticChainIdx + 2 &&
9111 "Size of OutChains mismatch");
9116 SDValue EndOfTrmp = OffsetValues[0].Addr;
9127 if (!Subtarget.is64Bit())
9130 return Op.getOperand(0);
9139 MVT VT =
Op.getSimpleValueType();
9145 MVT ArgVT =
A.getSimpleValueType();
9146 assert(ArgVT ==
B.getSimpleValueType() &&
9156 MVT ContainerVT = VT;
9165 switch (
Op.getOpcode()) {
9167 Opc = RISCVISD::VQDOT_VL;
9170 Opc = RISCVISD::VQDOTU_VL;
9173 Opc = RISCVISD::VQDOTSU_VL;
9199 N->getOffset(), Flags);
9228template <
class NodeTy>
9230 bool IsLocal,
bool IsExternWeak)
const {
9240 if (IsLocal && !Subtarget.allowTaggedGlobals())
9244 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
9267 if (Subtarget.hasVendorXqcili()) {
9271 return DAG.
getNode(RISCVISD::QC_E_LI,
DL, Ty, Addr);
9278 return DAG.
getNode(RISCVISD::ADD_LO,
DL, Ty, MNHi, AddrLo);
9302 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
9310 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
9318 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
9319 const GlobalValue *GV =
N->getGlobal();
9327 return getAddr(
N, DAG);
9334 return getAddr(
N, DAG);
9341 return getAddr(
N, DAG);
9346 bool UseGOT)
const {
9349 const GlobalValue *GV =
N->getGlobal();
9350 MVT XLenVT = Subtarget.getXLenVT();
9387 DAG.
getNode(RISCVISD::ADD_TPREL,
DL, Ty, MNHi, TPReg, AddrAdd);
9388 return DAG.
getNode(RISCVISD::ADD_LO,
DL, Ty, MNAdd, AddrLo);
9396 const GlobalValue *GV =
N->getGlobal();
9407 Args.emplace_back(Load, CallTy);
9410 TargetLowering::CallLoweringInfo CLI(DAG);
9424 const GlobalValue *GV =
N->getGlobal();
9440 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
9454 Addr = getStaticTLSAddr(
N, DAG,
false);
9457 Addr = getStaticTLSAddr(
N, DAG,
true);
9462 : getDynamicTLSAddr(
N, DAG);
9479 if (
LHS == LHS2 &&
RHS == RHS2) {
9484 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
9492 return std::nullopt;
9504 MVT VT =
N->getSimpleValueType(0);
9531 uint64_t TrueM1 = TrueC->getZExtValue() - 1;
9533 unsigned ShAmount =
Log2_64(TrueM1);
9535 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, CondV,
9551 if (~TrueVal == FalseVal) {
9591 if (Subtarget.hasShortForwardBranchIALU())
9594 unsigned SelOpNo = 0;
9604 unsigned ConstSelOpNo = 1;
9605 unsigned OtherSelOpNo = 2;
9612 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
9617 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
9623 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
9625 std::swap(NewConstOps[0], NewConstOps[1]);
9637 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
9639 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
9642 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
9643 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
9652 MVT VT =
Op.getSimpleValueType();
9653 MVT XLenVT = Subtarget.getXLenVT();
9668 bool FPinGPR = Subtarget.hasStdExtZfinx();
9672 Subtarget.getXLenVT().getSizeInBits());
9674 bool UseZicondForFPSel = Subtarget.hasStdExtZicond() && FPinGPR &&
9677 if (UseZicondForFPSel) {
9685 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, V);
9687 if (VT == MVT::f32 && Subtarget.is64Bit())
9688 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, XLenVT, V);
9693 SDValue TrueVInt = CastToInt(TrueV);
9694 SDValue FalseVInt = CastToInt(FalseV);
9701 if (VT == MVT::f32 && Subtarget.is64Bit())
9702 return DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, VT, ResultInt);
9705 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, ResultInt);
9718 return DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV);
9721 return DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV);
9725 auto getNotOperand = [](
const SDValue &
Op) -> std::optional<const SDValue> {
9726 using namespace llvm::SDPatternMatch;
9731 return std::nullopt;
9737 auto NotOperand = (TrueV.
getOperand(0) == FalseV)
9739 : getNotOperand(TrueV.getOperand(0));
9742 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, *NotOperand, CondV);
9748 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV));
9755 auto NotOperand = (FalseV.
getOperand(0) == TrueV)
9757 : getNotOperand(FalseV.getOperand(0));
9760 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, *NotOperand, CondV);
9766 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV));
9783 int64_t TrueImm =
TrueVal.getSExtValue();
9784 int64_t FalseImm =
FalseVal.getSExtValue();
9803 if ((TrueVal - FalseVal).isPowerOf2() &&
FalseVal.isSignedIntN(12)) {
9808 if ((FalseVal - TrueVal).isPowerOf2() &&
TrueVal.isSignedIntN(12)) {
9815 auto getCost = [&](
const APInt &Delta,
const APInt &Addend) {
9817 Delta, Subtarget.getXLen(), Subtarget,
true);
9819 if (Addend.isSignedIntN(12))
9822 Addend, Subtarget.getXLen(), Subtarget,
true);
9823 return AddendCost + DeltaCost;
9825 bool IsCZERO_NEZ =
getCost(FalseVal - TrueVal, TrueVal) <=
9826 getCost(TrueVal - FalseVal, FalseVal);
9828 IsCZERO_NEZ ? FalseVal - TrueVal : TrueVal - FalseVal,
DL, VT);
9830 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9831 DL, VT, LHSVal, CondV);
9839 SDValue ConstVal = IsCZERO_NEZ ? TrueV : FalseV;
9840 SDValue RegV = IsCZERO_NEZ ? FalseV : TrueV;
9846 unsigned SubOpc = (RawConstVal == -0x800) ?
ISD::XOR : ISD::
SUB;
9847 unsigned AddOpc = (RawConstVal == -0x800) ?
ISD::XOR : ISD::
ADD;
9850 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9851 DL, VT, SubOp, CondV);
9852 return DAG.
getNode(AddOpc,
DL, VT, CZERO, ConstVal);
9858 if (!Subtarget.hasConditionalMoveFusion())
9861 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV),
9862 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV),
9866 if (
Op.hasOneUse()) {
9867 unsigned UseOpc =
Op->user_begin()->getOpcode();
9869 SDNode *BinOp = *
Op->user_begin();
9876 return lowerSELECT(NewSel, DAG);
9930 if (TrueVal - 1 == FalseVal)
9932 if (TrueVal + 1 == FalseVal)
9939 RHS == TrueV &&
LHS == FalseV) {
9970 MVT XLenVT = Subtarget.getXLenVT();
9981 return DAG.
getNode(RISCVISD::BR_CC,
DL,
Op.getValueType(),
Op.getOperand(0),
9982 LHS,
RHS, TargetCC,
Op.getOperand(2));
9985 return DAG.
getNode(RISCVISD::BR_CC,
DL,
Op.getValueType(),
Op.getOperand(0),
9992 RISCVMachineFunctionInfo *FuncInfo = MF.
getInfo<RISCVMachineFunctionInfo>();
10002 MachinePointerInfo(SV));
10007 const RISCVRegisterInfo &RI = *Subtarget.getRegisterInfo();
10012 int XLenInBytes = Subtarget.getXLen() / 8;
10014 EVT VT =
Op.getValueType();
10017 unsigned Depth =
Op.getConstantOperandVal(0);
10019 int Offset = -(XLenInBytes * 2);
10031 const RISCVRegisterInfo &RI = *Subtarget.getRegisterInfo();
10035 MVT XLenVT = Subtarget.getXLenVT();
10036 int XLenInBytes = Subtarget.getXLen() / 8;
10038 EVT VT =
Op.getValueType();
10040 unsigned Depth =
Op.getConstantOperandVal(0);
10042 int Off = -XLenInBytes;
10043 SDValue FrameAddr = lowerFRAMEADDR(
Op, DAG);
10047 MachinePointerInfo());
10062 EVT VT =
Lo.getValueType();
10096 bool IsSRA)
const {
10101 EVT VT =
Lo.getValueType();
10152 MVT VT =
Op.getSimpleValueType();
10157 return DAG.
getNode(RISCVISD::VMSET_VL,
DL, VT, VL);
10161 return DAG.
getNode(RISCVISD::VMCLR_VL,
DL, VT, VL);
10178 MVT VecVT =
Op.getSimpleValueType();
10180 "Unexpected SPLAT_VECTOR_PARTS lowering");
10186 MVT ContainerVT = VecVT;
10206 int64_t ExtTrueVal)
const {
10208 MVT VecVT =
Op.getSimpleValueType();
10211 assert(Src.getValueType().isVector() &&
10212 Src.getValueType().getVectorElementType() == MVT::i1);
10217 if (Src.getOpcode() ==
ISD::XOR &&
10225 MVT I1ContainerVT =
10232 MVT XLenVT = Subtarget.getXLenVT();
10238 if (
Xor.getOpcode() == RISCVISD::VMXOR_VL) {
10250 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
10251 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
10252 SplatTrueVal = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
10253 DAG.
getUNDEF(ContainerVT), SplatTrueVal, VL);
10255 DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, CC, SplatTrueVal,
10256 SplatZero, DAG.
getUNDEF(ContainerVT), VL);
10266 bool IsVPTrunc =
Op.getOpcode() == ISD::VP_TRUNCATE;
10268 EVT MaskVT =
Op.getValueType();
10271 "Unexpected type for vector mask lowering");
10273 MVT VecVT = Src.getSimpleValueType();
10276 Mask =
Op.getOperand(1);
10277 VL =
Op.getOperand(2);
10280 MVT ContainerVT = VecVT;
10286 MVT MaskContainerVT =
10293 std::tie(Mask, VL) =
10300 SplatOne = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
10301 DAG.
getUNDEF(ContainerVT), SplatOne, VL);
10302 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
10303 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
10306 SDValue Trunc = DAG.
getNode(RISCVISD::AND_VL,
DL, ContainerVT, Src, SplatOne,
10307 DAG.
getUNDEF(ContainerVT), Mask, VL);
10308 Trunc = DAG.
getNode(RISCVISD::SETCC_VL,
DL, MaskContainerVT,
10318 unsigned Opc =
Op.getOpcode();
10319 bool IsVPTrunc =
Opc == ISD::VP_TRUNCATE;
10322 MVT VT =
Op.getSimpleValueType();
10324 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
10328 return lowerVectorMaskTruncLike(
Op, DAG);
10336 MVT SrcVT = Src.getSimpleValueType();
10341 "Unexpected vector truncate lowering");
10343 MVT ContainerVT = SrcVT;
10346 Mask =
Op.getOperand(1);
10347 VL =
Op.getOperand(2);
10360 std::tie(Mask, VL) =
10366 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL_SSAT;
10368 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL_USAT;
10370 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL;
10376 }
while (SrcEltVT != DstEltVT);
10385RISCVTargetLowering::lowerStrictFPExtendOrRoundLike(
SDValue Op,
10390 MVT VT =
Op.getSimpleValueType();
10391 MVT SrcVT = Src.getSimpleValueType();
10392 MVT ContainerVT = VT;
10411 ? RISCVISD::STRICT_FP_EXTEND_VL
10412 : RISCVISD::STRICT_VFNCVT_ROD_VL;
10415 Chain, Src, Mask, VL);
10416 Chain = Src.getValue(1);
10420 ? RISCVISD::STRICT_FP_EXTEND_VL
10421 : RISCVISD::STRICT_FP_ROUND_VL;
10423 Chain, Src, Mask, VL);
10434RISCVTargetLowering::lowerVectorFPExtendOrRoundLike(
SDValue Op,
10437 Op.getOpcode() == ISD::VP_FP_ROUND ||
Op.getOpcode() == ISD::VP_FP_EXTEND;
10444 MVT VT =
Op.getSimpleValueType();
10446 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
10449 MVT SrcVT = Src.getSimpleValueType();
10451 bool IsDirectExtend =
10459 bool IsDirectConv = IsDirectExtend || IsDirectTrunc;
10466 MVT ContainerVT = VT;
10469 Mask =
Op.getOperand(1);
10470 VL =
Op.getOperand(2);
10484 std::tie(Mask, VL) =
10487 unsigned ConvOpc = IsExtend ? RISCVISD::FP_EXTEND_VL : RISCVISD::FP_ROUND_VL;
10489 if (IsDirectConv) {
10490 Src = DAG.
getNode(ConvOpc,
DL, ContainerVT, Src, Mask, VL);
10496 unsigned InterConvOpc =
10497 IsExtend ? RISCVISD::FP_EXTEND_VL : RISCVISD::VFNCVT_ROD_VL;
10501 DAG.
getNode(InterConvOpc,
DL, InterVT, Src, Mask, VL);
10503 DAG.
getNode(ConvOpc,
DL, ContainerVT, IntermediateConv, Mask, VL);
10514static std::optional<MVT>
10520 const unsigned MinVLMAX = VectorBitsMin / EltSize;
10522 if (MaxIdx < MinVLMAX)
10524 else if (MaxIdx < MinVLMAX * 2)
10527 else if (MaxIdx < MinVLMAX * 4)
10532 return std::nullopt;
10540 return isUInt<5>(IdxC->getZExtValue());
10552 MVT VecVT =
Op.getSimpleValueType();
10553 MVT XLenVT = Subtarget.getXLenVT();
10568 if ((ValVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
10569 (ValVT == MVT::bf16 && !Subtarget.hasVInstructionsBF16())) {
10574 DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Val), Idx);
10578 MVT ContainerVT = VecVT;
10588 std::optional<unsigned> AlignedIdx;
10590 const unsigned OrigIdx = IdxC->getZExtValue();
10593 DL, DAG, Subtarget)) {
10594 ContainerVT = *ShrunkVT;
10602 if (
auto VLEN = Subtarget.getRealVLen(); VLEN && ContainerVT.
bitsGT(M1VT)) {
10605 unsigned RemIdx = OrigIdx % ElemsPerVReg;
10606 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
10609 ContainerVT = M1VT;
10616 bool IsLegalInsert = Subtarget.is64Bit() || Val.
getValueType() != MVT::i64;
10624 IsLegalInsert =
true;
10633 if (IsLegalInsert) {
10635 VecVT.
isFloatingPoint() ? RISCVISD::VFMV_S_F_VL : RISCVISD::VMV_S_X_VL;
10639 Vec = DAG.
getNode(
Opc,
DL, ContainerVT, Vec, Val, VL);
10649 if (Subtarget.hasVendorXRivosVisni() && VecVT.
isInteger() &&
10654 Vec = DAG.
getNode(RISCVISD::RI_VINSERT_VL,
DL, ContainerVT, Vec, Val, Idx,
10670 std::tie(ValLo, ValHi) = DAG.
SplitScalar(Val,
DL, MVT::i32, MVT::i32);
10671 MVT I32ContainerVT =
10681 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10682 Vec, Vec, ValLo, I32Mask, InsertI64VL);
10686 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10687 Tail, ValInVec, ValHi, I32Mask, InsertI64VL);
10689 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
10700 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10702 DAG.
getUNDEF(I32ContainerVT), ValLo,
10703 I32Mask, InsertI64VL);
10704 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10705 DAG.
getUNDEF(I32ContainerVT), ValInVec, ValHi,
10706 I32Mask, InsertI64VL);
10708 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
10721 Idx, Mask, InsertVL, Policy);
10739 EVT EltVT =
Op.getValueType();
10741 MVT XLenVT = Subtarget.getXLenVT();
10746 MVT ContainerVT = VecVT;
10753 DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Vec, Mask, VL);
10760 if (NumElts >= 8) {
10762 unsigned WidenVecLen;
10765 unsigned MaxEEW = Subtarget.getELen();
10770 "the number of elements should be power of 2");
10774 ExtractBitIdx = Idx;
10776 WideEltVT = LargestEltVT;
10779 ExtractElementIdx = DAG.
getNode(
10790 Vec, ExtractElementIdx);
10805 if ((EltVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
10806 (EltVT == MVT::bf16 && !Subtarget.hasVInstructionsBF16())) {
10812 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, EltVT, IntExtract);
10816 if (VecVT != MVT::v4i16 && VecVT != MVT::v2i16 && VecVT != MVT::v8i8 &&
10817 VecVT != MVT::v4i8 && VecVT != MVT::v2i32)
10827 MVT ContainerVT = VecVT;
10837 const auto VLen = Subtarget.getRealVLen();
10839 IdxC && VLen && VecVT.
getSizeInBits().getKnownMinValue() > *VLen) {
10841 unsigned OrigIdx = IdxC->getZExtValue();
10844 unsigned RemIdx = OrigIdx % ElemsPerVReg;
10845 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
10846 unsigned ExtractIdx =
10850 ContainerVT = M1VT;
10855 std::optional<uint64_t> MaxIdx;
10859 MaxIdx = IdxC->getZExtValue();
10861 if (
auto SmallerVT =
10863 ContainerVT = *SmallerVT;
10870 if (Subtarget.hasVendorXRivosVisni() && EltVT.
isInteger() &&
10898 DAG.
getUNDEF(ContainerVT), Vec, Idx, Mask, VL);
10917 "Unexpected opcode");
10924 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
10929 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
10930 if (!
II || !
II->hasScalarOperand())
10933 unsigned SplatOp =
II->ScalarOperand + 1 + HasChain;
10934 assert(SplatOp <
Op.getNumOperands());
10937 SDValue &ScalarOp = Operands[SplatOp];
10946 if (OpVT.
bitsLT(XLenVT)) {
10953 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
10954 return DAG.
getNode(
Op->getOpcode(),
DL,
Op->getVTList(), Operands);
10963 assert(
II->ScalarOperand > 0 &&
"Unexpected splat operand!");
10964 MVT VT =
Op.getOperand(SplatOp - 1).getSimpleValueType();
10967 assert(XLenVT == MVT::i32 && OpVT == MVT::i64 &&
10974 return DAG.
getNode(
Op->getOpcode(),
DL,
Op->getVTList(), Operands);
10978 case Intrinsic::riscv_vslide1up:
10979 case Intrinsic::riscv_vslide1down:
10980 case Intrinsic::riscv_vslide1up_mask:
10981 case Intrinsic::riscv_vslide1down_mask: {
10983 unsigned NumOps =
Op.getNumOperands();
10984 bool IsMasked =
NumOps == 7;
10990 std::tie(ScalarLo, ScalarHi) =
10999 const auto [MinVLMAX, MaxVLMAX] =
11003 if (AVLInt <= MinVLMAX) {
11005 }
else if (AVLInt >= 2 * MaxVLMAX) {
11037 Passthru = DAG.
getBitcast(I32VT, Operands[1]);
11039 if (IntNo == Intrinsic::riscv_vslide1up ||
11040 IntNo == Intrinsic::riscv_vslide1up_mask) {
11041 Vec = DAG.
getNode(RISCVISD::VSLIDE1UP_VL,
DL, I32VT, Passthru, Vec,
11042 ScalarHi, I32Mask, I32VL);
11043 Vec = DAG.
getNode(RISCVISD::VSLIDE1UP_VL,
DL, I32VT, Passthru, Vec,
11044 ScalarLo, I32Mask, I32VL);
11046 Vec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32VT, Passthru, Vec,
11047 ScalarLo, I32Mask, I32VL);
11048 Vec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32VT, Passthru, Vec,
11049 ScalarHi, I32Mask, I32VL);
11059 SDValue MaskedOff = Operands[1];
11067 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, Mask, Vec, MaskedOff,
11071 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, Mask, Vec, MaskedOff,
11080 return DAG.
getNode(
Op->getOpcode(),
DL,
Op->getVTList(), Operands);
11098 const unsigned ElementWidth = 8;
11103 [[maybe_unused]]
unsigned MinVF =
11106 [[maybe_unused]]
unsigned VF =
N->getConstantOperandVal(2);
11110 bool Fractional = VF < LMul1VF;
11111 unsigned LMulVal = Fractional ? LMul1VF / VF : VF / LMul1VF;
11132 MVT ContainerVT = OpVT;
11140 SDValue Res = DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Op0, Mask, VL);
11148 return DAG.
getSelect(
DL, XLenVT, Setcc, VL, Res);
11159 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
11163 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
11164 if (!
II || !
II->hasScalarOperand())
11167 unsigned SplatOp =
II->ScalarOperand + 1;
11168 assert(SplatOp <
Op.getNumOperands());
11170 SDValue &ScalarOp = Operands[SplatOp];
11180 if (OpVT.
bitsLT(XLenVT)) {
11183 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
11193 for (
SDValue &V : Operands) {
11194 EVT ValType = V.getValueType();
11195 if (ValType.isVector() && ValType.isFloatingPoint()) {
11198 ValType.getVectorElementCount());
11201 if (ValType.isFixedLengthVector()) {
11203 DAG, V.getSimpleValueType(), Subtarget);
11219 unsigned IntNo =
Op.getConstantOperandVal(0);
11221 MVT XLenVT = Subtarget.getXLenVT();
11226 case Intrinsic::riscv_tuple_insert: {
11231 return DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL,
Op.getValueType(), Vec,
11234 case Intrinsic::riscv_tuple_extract: {
11238 return DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL,
Op.getValueType(), Vec,
11241 case Intrinsic::thread_pointer: {
11245 case Intrinsic::riscv_orc_b:
11246 case Intrinsic::riscv_brev8:
11247 case Intrinsic::riscv_sha256sig0:
11248 case Intrinsic::riscv_sha256sig1:
11249 case Intrinsic::riscv_sha256sum0:
11250 case Intrinsic::riscv_sha256sum1:
11251 case Intrinsic::riscv_sm3p0:
11252 case Intrinsic::riscv_sm3p1: {
11255 case Intrinsic::riscv_orc_b:
Opc = RISCVISD::ORC_B;
break;
11256 case Intrinsic::riscv_brev8:
Opc = RISCVISD::BREV8;
break;
11257 case Intrinsic::riscv_sha256sig0:
Opc = RISCVISD::SHA256SIG0;
break;
11258 case Intrinsic::riscv_sha256sig1:
Opc = RISCVISD::SHA256SIG1;
break;
11259 case Intrinsic::riscv_sha256sum0:
Opc = RISCVISD::SHA256SUM0;
break;
11260 case Intrinsic::riscv_sha256sum1:
Opc = RISCVISD::SHA256SUM1;
break;
11261 case Intrinsic::riscv_sm3p0:
Opc = RISCVISD::SM3P0;
break;
11262 case Intrinsic::riscv_sm3p1:
Opc = RISCVISD::SM3P1;
break;
11267 case Intrinsic::riscv_sm4ks:
11268 case Intrinsic::riscv_sm4ed: {
11270 IntNo == Intrinsic::riscv_sm4ks ? RISCVISD::SM4KS : RISCVISD::SM4ED;
11275 case Intrinsic::riscv_zip:
11276 case Intrinsic::riscv_unzip: {
11278 IntNo == Intrinsic::riscv_zip ? RISCVISD::ZIP : RISCVISD::UNZIP;
11281 case Intrinsic::riscv_mopr:
11282 return DAG.
getNode(RISCVISD::MOP_R,
DL, XLenVT,
Op.getOperand(1),
11285 case Intrinsic::riscv_moprr: {
11286 return DAG.
getNode(RISCVISD::MOP_RR,
DL, XLenVT,
Op.getOperand(1),
11287 Op.getOperand(2),
Op.getOperand(3));
11289 case Intrinsic::riscv_clmul:
11290 return DAG.
getNode(RISCVISD::CLMUL,
DL, XLenVT,
Op.getOperand(1),
11292 case Intrinsic::riscv_clmulh:
11293 case Intrinsic::riscv_clmulr: {
11295 IntNo == Intrinsic::riscv_clmulh ? RISCVISD::CLMULH : RISCVISD::CLMULR;
11298 case Intrinsic::experimental_get_vector_length:
11300 case Intrinsic::experimental_cttz_elts:
11302 case Intrinsic::riscv_vmv_x_s: {
11306 case Intrinsic::riscv_vfmv_f_s:
11308 case Intrinsic::riscv_vmv_v_x:
11310 Op.getOperand(3),
Op.getSimpleValueType(),
DL, DAG,
11312 case Intrinsic::riscv_vfmv_v_f:
11313 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL,
Op.getValueType(),
11314 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
11315 case Intrinsic::riscv_vmv_s_x: {
11318 if (
Scalar.getValueType().bitsLE(XLenVT)) {
11320 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL,
Op.getValueType(),
11321 Op.getOperand(1), Scalar,
Op.getOperand(3));
11324 assert(
Scalar.getValueType() == MVT::i64 &&
"Unexpected scalar VT!");
11341 MVT VT =
Op.getSimpleValueType();
11346 if (
Op.getOperand(1).isUndef())
11347 return SplattedVal;
11356 DAG.
getNode(RISCVISD::SETCC_VL,
DL, MaskVT,
11359 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, SelectCond, SplattedVal,
11362 case Intrinsic::riscv_vfmv_s_f:
11363 return DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL,
Op.getSimpleValueType(),
11364 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
11366 case Intrinsic::riscv_vaesdf_vv:
11367 case Intrinsic::riscv_vaesdf_vs:
11368 case Intrinsic::riscv_vaesdm_vv:
11369 case Intrinsic::riscv_vaesdm_vs:
11370 case Intrinsic::riscv_vaesef_vv:
11371 case Intrinsic::riscv_vaesef_vs:
11372 case Intrinsic::riscv_vaesem_vv:
11373 case Intrinsic::riscv_vaesem_vs:
11374 case Intrinsic::riscv_vaeskf1:
11375 case Intrinsic::riscv_vaeskf2:
11376 case Intrinsic::riscv_vaesz_vs:
11377 case Intrinsic::riscv_vsm4k:
11378 case Intrinsic::riscv_vsm4r_vv:
11379 case Intrinsic::riscv_vsm4r_vs: {
11380 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
11381 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
11382 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
11387 case Intrinsic::riscv_vsm3c:
11388 case Intrinsic::riscv_vsm3me: {
11389 if (!
isValidEGW(8,
Op.getSimpleValueType(), Subtarget) ||
11390 !
isValidEGW(8,
Op->getOperand(1).getSimpleValueType(), Subtarget))
11395 case Intrinsic::riscv_vsha2ch:
11396 case Intrinsic::riscv_vsha2cl:
11397 case Intrinsic::riscv_vsha2ms: {
11398 if (
Op->getSimpleValueType(0).getScalarSizeInBits() == 64 &&
11399 !Subtarget.hasStdExtZvknhb())
11401 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
11402 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
11403 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
11407 case Intrinsic::riscv_sf_vc_v_x:
11408 case Intrinsic::riscv_sf_vc_v_i:
11409 case Intrinsic::riscv_sf_vc_v_xv:
11410 case Intrinsic::riscv_sf_vc_v_iv:
11411 case Intrinsic::riscv_sf_vc_v_vv:
11412 case Intrinsic::riscv_sf_vc_v_fv:
11413 case Intrinsic::riscv_sf_vc_v_xvv:
11414 case Intrinsic::riscv_sf_vc_v_ivv:
11415 case Intrinsic::riscv_sf_vc_v_vvv:
11416 case Intrinsic::riscv_sf_vc_v_fvv:
11417 case Intrinsic::riscv_sf_vc_v_xvw:
11418 case Intrinsic::riscv_sf_vc_v_ivw:
11419 case Intrinsic::riscv_sf_vc_v_vvw:
11420 case Intrinsic::riscv_sf_vc_v_fvw: {
11421 MVT VT =
Op.getSimpleValueType();
11458 MVT VT =
Op.getSimpleValueType();
11462 if (VT.isFloatingPoint()) {
11464 VT.getVectorElementCount());
11467 if (VT.isFixedLengthVector())
11477 if (VT.isFixedLengthVector())
11479 if (VT.isFloatingPoint())
11502 case Intrinsic::riscv_seg2_load_mask:
11503 case Intrinsic::riscv_seg3_load_mask:
11504 case Intrinsic::riscv_seg4_load_mask:
11505 case Intrinsic::riscv_seg5_load_mask:
11506 case Intrinsic::riscv_seg6_load_mask:
11507 case Intrinsic::riscv_seg7_load_mask:
11508 case Intrinsic::riscv_seg8_load_mask:
11511 case Intrinsic::riscv_sseg2_load_mask:
11512 case Intrinsic::riscv_sseg3_load_mask:
11513 case Intrinsic::riscv_sseg4_load_mask:
11514 case Intrinsic::riscv_sseg5_load_mask:
11515 case Intrinsic::riscv_sseg6_load_mask:
11516 case Intrinsic::riscv_sseg7_load_mask:
11517 case Intrinsic::riscv_sseg8_load_mask:
11525 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
11526 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
11527 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
11528 Intrinsic::riscv_vlseg8_mask};
11530 Intrinsic::riscv_vlsseg2_mask, Intrinsic::riscv_vlsseg3_mask,
11531 Intrinsic::riscv_vlsseg4_mask, Intrinsic::riscv_vlsseg5_mask,
11532 Intrinsic::riscv_vlsseg6_mask, Intrinsic::riscv_vlsseg7_mask,
11533 Intrinsic::riscv_vlsseg8_mask};
11536 unsigned NF =
Op->getNumValues() - 1;
11537 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
11539 MVT VT =
Op->getSimpleValueType(0);
11547 SDValue VL =
Op.getOperand(
Op.getNumOperands() - 1);
11548 SDValue Mask =
Op.getOperand(
Op.getNumOperands() - 2);
11549 MVT MaskVT = Mask.getSimpleValueType();
11550 MVT MaskContainerVT =
11555 IsStrided ? VlssegInts[NF - 2] : VlsegInts[NF - 2],
DL, XLenVT);
11571 Ops.insert(std::next(
Ops.begin(), 4),
Op.getOperand(3));
11575 Load->getMemoryVT(), Load->getMemOperand());
11577 for (
unsigned int RetIdx = 0; RetIdx < NF; RetIdx++) {
11579 Result.getValue(0),
11583 Results.push_back(Result.getValue(1));
11589 unsigned IntNo =
Op.getConstantOperandVal(1);
11593 case Intrinsic::riscv_seg2_load_mask:
11594 case Intrinsic::riscv_seg3_load_mask:
11595 case Intrinsic::riscv_seg4_load_mask:
11596 case Intrinsic::riscv_seg5_load_mask:
11597 case Intrinsic::riscv_seg6_load_mask:
11598 case Intrinsic::riscv_seg7_load_mask:
11599 case Intrinsic::riscv_seg8_load_mask:
11600 case Intrinsic::riscv_sseg2_load_mask:
11601 case Intrinsic::riscv_sseg3_load_mask:
11602 case Intrinsic::riscv_sseg4_load_mask:
11603 case Intrinsic::riscv_sseg5_load_mask:
11604 case Intrinsic::riscv_sseg6_load_mask:
11605 case Intrinsic::riscv_sseg7_load_mask:
11606 case Intrinsic::riscv_sseg8_load_mask:
11609 case Intrinsic::riscv_sf_vc_v_x_se:
11611 case Intrinsic::riscv_sf_vc_v_i_se:
11613 case Intrinsic::riscv_sf_vc_v_xv_se:
11615 case Intrinsic::riscv_sf_vc_v_iv_se:
11617 case Intrinsic::riscv_sf_vc_v_vv_se:
11619 case Intrinsic::riscv_sf_vc_v_fv_se:
11621 case Intrinsic::riscv_sf_vc_v_xvv_se:
11623 case Intrinsic::riscv_sf_vc_v_ivv_se:
11625 case Intrinsic::riscv_sf_vc_v_vvv_se:
11627 case Intrinsic::riscv_sf_vc_v_fvv_se:
11629 case Intrinsic::riscv_sf_vc_v_xvw_se:
11631 case Intrinsic::riscv_sf_vc_v_ivw_se:
11633 case Intrinsic::riscv_sf_vc_v_vvw_se:
11635 case Intrinsic::riscv_sf_vc_v_fvw_se:
11648 case Intrinsic::riscv_seg2_store_mask:
11649 case Intrinsic::riscv_seg3_store_mask:
11650 case Intrinsic::riscv_seg4_store_mask:
11651 case Intrinsic::riscv_seg5_store_mask:
11652 case Intrinsic::riscv_seg6_store_mask:
11653 case Intrinsic::riscv_seg7_store_mask:
11654 case Intrinsic::riscv_seg8_store_mask:
11657 case Intrinsic::riscv_sseg2_store_mask:
11658 case Intrinsic::riscv_sseg3_store_mask:
11659 case Intrinsic::riscv_sseg4_store_mask:
11660 case Intrinsic::riscv_sseg5_store_mask:
11661 case Intrinsic::riscv_sseg6_store_mask:
11662 case Intrinsic::riscv_sseg7_store_mask:
11663 case Intrinsic::riscv_sseg8_store_mask:
11672 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
11673 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
11674 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
11675 Intrinsic::riscv_vsseg8_mask};
11677 Intrinsic::riscv_vssseg2_mask, Intrinsic::riscv_vssseg3_mask,
11678 Intrinsic::riscv_vssseg4_mask, Intrinsic::riscv_vssseg5_mask,
11679 Intrinsic::riscv_vssseg6_mask, Intrinsic::riscv_vssseg7_mask,
11680 Intrinsic::riscv_vssseg8_mask};
11684 unsigned NF =
Op->getNumOperands() - (IsStrided ? 6 : 5);
11685 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
11687 MVT VT =
Op->getOperand(2).getSimpleValueType();
11693 SDValue VL =
Op.getOperand(
Op.getNumOperands() - 1);
11694 SDValue Mask =
Op.getOperand(
Op.getNumOperands() - 2);
11695 MVT MaskVT = Mask.getSimpleValueType();
11696 MVT MaskContainerVT =
11701 IsStrided ? VsssegInts[NF - 2] : VssegInts[NF - 2],
DL, XLenVT);
11707 for (
unsigned i = 0; i < NF; i++)
11709 RISCVISD::TUPLE_INSERT,
DL, VecTupTy, StoredVal,
11715 FixedIntrinsic->getChain(),
11724 Ops.insert(std::next(
Ops.begin(), 4),
11725 Op.getOperand(
Op.getNumOperands() - 3));
11729 FixedIntrinsic->getMemoryVT(), FixedIntrinsic->getMemOperand());
11734 unsigned IntNo =
Op.getConstantOperandVal(1);
11738 case Intrinsic::riscv_seg2_store_mask:
11739 case Intrinsic::riscv_seg3_store_mask:
11740 case Intrinsic::riscv_seg4_store_mask:
11741 case Intrinsic::riscv_seg5_store_mask:
11742 case Intrinsic::riscv_seg6_store_mask:
11743 case Intrinsic::riscv_seg7_store_mask:
11744 case Intrinsic::riscv_seg8_store_mask:
11745 case Intrinsic::riscv_sseg2_store_mask:
11746 case Intrinsic::riscv_sseg3_store_mask:
11747 case Intrinsic::riscv_sseg4_store_mask:
11748 case Intrinsic::riscv_sseg5_store_mask:
11749 case Intrinsic::riscv_sseg6_store_mask:
11750 case Intrinsic::riscv_sseg7_store_mask:
11751 case Intrinsic::riscv_sseg8_store_mask:
11754 case Intrinsic::riscv_sf_vc_xv_se:
11756 case Intrinsic::riscv_sf_vc_iv_se:
11758 case Intrinsic::riscv_sf_vc_vv_se:
11760 case Intrinsic::riscv_sf_vc_fv_se:
11762 case Intrinsic::riscv_sf_vc_xvv_se:
11764 case Intrinsic::riscv_sf_vc_ivv_se:
11766 case Intrinsic::riscv_sf_vc_vvv_se:
11768 case Intrinsic::riscv_sf_vc_fvv_se:
11770 case Intrinsic::riscv_sf_vc_xvw_se:
11772 case Intrinsic::riscv_sf_vc_ivw_se:
11774 case Intrinsic::riscv_sf_vc_vvw_se:
11776 case Intrinsic::riscv_sf_vc_fvw_se:
11784 switch (ISDOpcode) {
11787 case ISD::VP_REDUCE_ADD:
11789 return RISCVISD::VECREDUCE_ADD_VL;
11790 case ISD::VP_REDUCE_UMAX:
11792 return RISCVISD::VECREDUCE_UMAX_VL;
11793 case ISD::VP_REDUCE_SMAX:
11795 return RISCVISD::VECREDUCE_SMAX_VL;
11796 case ISD::VP_REDUCE_UMIN:
11798 return RISCVISD::VECREDUCE_UMIN_VL;
11799 case ISD::VP_REDUCE_SMIN:
11801 return RISCVISD::VECREDUCE_SMIN_VL;
11802 case ISD::VP_REDUCE_AND:
11804 return RISCVISD::VECREDUCE_AND_VL;
11805 case ISD::VP_REDUCE_OR:
11807 return RISCVISD::VECREDUCE_OR_VL;
11808 case ISD::VP_REDUCE_XOR:
11810 return RISCVISD::VECREDUCE_XOR_VL;
11811 case ISD::VP_REDUCE_FADD:
11812 return RISCVISD::VECREDUCE_FADD_VL;
11813 case ISD::VP_REDUCE_SEQ_FADD:
11814 return RISCVISD::VECREDUCE_SEQ_FADD_VL;
11815 case ISD::VP_REDUCE_FMAX:
11816 case ISD::VP_REDUCE_FMAXIMUM:
11817 return RISCVISD::VECREDUCE_FMAX_VL;
11818 case ISD::VP_REDUCE_FMIN:
11819 case ISD::VP_REDUCE_FMINIMUM:
11820 return RISCVISD::VECREDUCE_FMIN_VL;
11829 SDValue Vec =
Op.getOperand(IsVP ? 1 : 0);
11834 Op.getOpcode() == ISD::VP_REDUCE_AND ||
11835 Op.getOpcode() == ISD::VP_REDUCE_OR ||
11836 Op.getOpcode() == ISD::VP_REDUCE_XOR) &&
11837 "Unexpected reduction lowering");
11839 MVT XLenVT = Subtarget.getXLenVT();
11841 MVT ContainerVT = VecVT;
11849 Mask =
Op.getOperand(2);
11850 VL =
Op.getOperand(3);
11852 std::tie(Mask, VL) =
11857 switch (
Op.getOpcode()) {
11861 case ISD::VP_REDUCE_AND: {
11865 Vec = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Vec, TrueMask, VL);
11868 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11873 case ISD::VP_REDUCE_OR:
11875 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11879 case ISD::VP_REDUCE_XOR: {
11882 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11903 return DAG.
getNode(BaseOpc,
DL,
Op.getValueType(), SetCC,
Op.getOperand(0));
11909 return (RegisterAVL && RegisterAVL->getReg() == RISCV::X0) ||
11910 (ImmAVL && ImmAVL->getZExtValue() >= 1);
11926 auto InnerVT = VecVT.
bitsLE(M1VT) ? VecVT : M1VT;
11930 auto InnerVL = NonZeroAVL ? VL : DAG.
getConstant(1,
DL, XLenVT);
11933 if (M1VT != InnerVT)
11938 SDValue Ops[] = {PassThru, Vec, InitialValue, Mask, VL, Policy};
11956 VecEVT =
Lo.getValueType();
11969 MVT ContainerVT = VecVT;
11988 Mask, VL,
DL, DAG, Subtarget);
11994static std::tuple<unsigned, SDValue, SDValue>
11998 auto Flags =
Op->getFlags();
11999 unsigned Opcode =
Op.getOpcode();
12007 return std::make_tuple(RISCVISD::VECREDUCE_FADD_VL,
Op.getOperand(0), Zero);
12010 return std::make_tuple(RISCVISD::VECREDUCE_SEQ_FADD_VL,
Op.getOperand(1),
12019 ? RISCVISD::VECREDUCE_FMIN_VL
12020 : RISCVISD::VECREDUCE_FMAX_VL;
12021 return std::make_tuple(RVVOpc,
Op.getOperand(0), Front);
12029 MVT VecEltVT =
Op.getSimpleValueType();
12031 unsigned RVVOpcode;
12032 SDValue VectorVal, ScalarVal;
12033 std::tie(RVVOpcode, VectorVal, ScalarVal) =
12037 MVT ContainerVT = VecVT;
12043 MVT ResVT =
Op.getSimpleValueType();
12046 VL,
DL, DAG, Subtarget);
12051 if (
Op->getFlags().hasNoNaNs())
12057 {VectorVal, VectorVal, DAG.getCondCode(ISD::SETNE),
12058 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
12059 MVT XLenVT = Subtarget.getXLenVT();
12060 SDValue CPop = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, IsNan, Mask, VL);
12064 DL, ResVT, NoNaNs, Res,
12071 unsigned Opc =
Op.getOpcode();
12075 MVT XLenVT = Subtarget.getXLenVT();
12094 Vec, Mask, VL,
DL, DAG, Subtarget);
12095 if ((
Opc != ISD::VP_REDUCE_FMINIMUM &&
Opc != ISD::VP_REDUCE_FMAXIMUM) ||
12096 Op->getFlags().hasNoNaNs())
12103 RISCVISD::SETCC_VL,
DL, PredVT,
12105 SDValue VCPop = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, IsNaN, Mask, VL);
12113 DL, ResVT, NoNaNs, Res,
12125 MVT XLenVT = Subtarget.getXLenVT();
12126 unsigned OrigIdx =
Op.getConstantOperandVal(2);
12127 const RISCVRegisterInfo *
TRI = Subtarget.getRegisterInfo();
12129 if (OrigIdx == 0 && Vec.
isUndef())
12140 assert(OrigIdx % 8 == 0 &&
"Invalid index");
12143 "Unexpected mask vector lowering");
12173 const auto VLen = Subtarget.getRealVLen();
12175 MVT ContainerVT = VecVT;
12197 if (OrigIdx == 0) {
12199 DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, ContainerVT, Vec, SubVec, VL);
12202 SubVec =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, Vec, SubVec,
12203 SlideupAmt, Mask, VL, Policy);
12211 MVT ContainerVecVT = VecVT;
12217 MVT ContainerSubVecVT = SubVecVT;
12223 unsigned SubRegIdx;
12224 ElementCount RemIdx;
12233 ContainerVecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
12234 SubRegIdx = Decompose.first;
12236 (OrigIdx % Vscale));
12240 ContainerVecVT, ContainerSubVecVT, OrigIdx,
TRI);
12241 SubRegIdx = Decompose.first;
12247 Subtarget.expandVScale(SubVecVT.
getSizeInBits()).getKnownMinValue()));
12248 bool ExactlyVecRegSized =
12250 .isKnownMultipleOf(Subtarget.expandVScale(VecRegSize));
12265 if (RemIdx.
isZero() && (ExactlyVecRegSized || Vec.
isUndef())) {
12269 if (SubRegIdx == RISCV::NoSubRegister) {
12291 MVT InterSubVT = ContainerVecVT;
12292 SDValue AlignedExtract = Vec;
12314 if (Subtarget.expandVScale(EndIndex) ==
12321 SubVec = DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, InterSubVT, AlignedExtract,
12329 SubVec =
getVSlideup(DAG, Subtarget,
DL, InterSubVT, AlignedExtract, SubVec,
12330 SlideupAmt, Mask, VL, Policy);
12335 if (ContainerVecVT.
bitsGT(InterSubVT))
12343 return DAG.
getBitcast(
Op.getSimpleValueType(), SubVec);
12349 MVT SubVecVT =
Op.getSimpleValueType();
12353 MVT XLenVT = Subtarget.getXLenVT();
12354 unsigned OrigIdx =
Op.getConstantOperandVal(1);
12355 const RISCVRegisterInfo *
TRI = Subtarget.getRegisterInfo();
12370 assert(OrigIdx % 8 == 0 &&
"Invalid index");
12373 "Unexpected mask vector lowering");
12399 const auto VLen = Subtarget.getRealVLen();
12407 MVT ContainerVT = VecVT;
12415 if (
auto ShrunkVT =
12417 ContainerVT = *ShrunkVT;
12429 DAG.
getUNDEF(ContainerVT), Vec, SlidedownAmt, Mask, VL);
12440 MVT ContainerSubVecVT = SubVecVT;
12444 unsigned SubRegIdx;
12445 ElementCount RemIdx;
12454 VecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
12455 SubRegIdx = Decompose.first;
12457 (OrigIdx % Vscale));
12461 VecVT, ContainerSubVecVT, OrigIdx,
TRI);
12462 SubRegIdx = Decompose.first;
12489 MVT InterSubVT = VecVT;
12494 assert(SubRegIdx != RISCV::NoSubRegister);
12513 Vec, SlidedownAmt, Mask, VL);
12521 return DAG.
getBitcast(
Op.getSimpleValueType(), Slidedown);
12528 MVT VT =
N.getSimpleValueType();
12532 assert(
Op.getSimpleValueType() == VT &&
12533 "Operands and result must be same type");
12537 unsigned NumVals =
N->getNumValues();
12540 NumVals,
N.getValueType().changeVectorElementType(MVT::i8)));
12543 for (
unsigned I = 0;
I < NumVals;
I++) {
12549 if (TruncVals.
size() > 1)
12551 return TruncVals.
front();
12557 MVT VecVT =
Op.getSimpleValueType();
12559 const unsigned Factor =
Op->getNumValues();
12570 for (
unsigned i = 0U; i < Factor; ++i)
12579 for (
unsigned i = 0U; i < Factor; ++i)
12589 for (
unsigned i = 0; i != Factor; ++i) {
12592 Ops[i * 2 + 1] = OpHi;
12603 for (
unsigned i = 0; i != Factor; ++i)
12610 if (Subtarget.hasVendorXRivosVizip() && Factor == 2) {
12611 MVT VT =
Op->getSimpleValueType(0);
12636 lowerVZIP(RISCVISD::RI_VUNZIP2A_VL, V1, V2,
DL, DAG, Subtarget);
12638 lowerVZIP(RISCVISD::RI_VUNZIP2B_VL, V1, V2,
DL, DAG, Subtarget);
12671 EvenSplat = DAG.
getBitcast(MVT::nxv64i1, EvenSplat);
12675 OddSplat = DAG.
getBitcast(MVT::nxv64i1, OddSplat);
12680 EvenMask, DAG.
getUNDEF(ConcatVT));
12692 MVT XLenVT = Subtarget.getXLenVT();
12714 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
12715 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
12716 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
12717 Intrinsic::riscv_vlseg8_mask};
12741 for (
unsigned i = 0U; i < Factor; ++i)
12742 Res[i] = DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL, VecVT, Load,
12751 MVT VecVT =
Op.getSimpleValueType();
12764 for (
unsigned i = 0U; i < Factor; ++i)
12772 for (
unsigned i = 0U; i < Factor; ++i)
12778 MVT XLenVT = Subtarget.getXLenVT();
12785 for (
unsigned i = 0; i != Factor; ++i) {
12788 Ops[i + Factor] = OpHi;
12799 for (
unsigned i = 0; i != Factor; ++i) {
12800 unsigned IdxLo = 2 * i;
12801 unsigned IdxHi = 2 * i + 1;
12803 Res[IdxLo / Factor].getValue(IdxLo % Factor),
12804 Res[IdxHi / Factor].getValue(IdxHi % Factor));
12822 EVT PtrVT =
StackPtr.getValueType();
12828 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
12829 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
12830 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
12831 Intrinsic::riscv_vsseg8_mask,
12839 for (
unsigned i = 0; i < Factor; i++)
12841 DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VecTupTy, StoredVal,
12861 for (
unsigned i = 0; i != Factor; ++i) {
12865 Loads[i] = DAG.
getLoad(VecVT,
DL, Chain, StackPtr, PtrInfo);
12873 if (Subtarget.hasVendorXRivosVizip() && !
Op.getOperand(0).isUndef() &&
12874 !
Op.getOperand(1).isUndef()) {
12894 Op.getOperand(0),
Op.getOperand(1));
12918 DAG.
getNode(RISCVISD::ADD_VL,
DL, IdxVT, Idx, VLMax, Idx, OddMask, VL);
12923 Interleaved = DAG.
getNode(RISCVISD::VRGATHEREI16_VV_VL,
DL, ConcatVT,
12940 MVT VT =
Op.getSimpleValueType();
12942 MVT XLenVT = Subtarget.getXLenVT();
12945 uint64_t StepValImm =
Op.getConstantOperandVal(0);
12946 if (StepValImm != 1) {
12955 VL, VT,
DL, DAG, Subtarget);
12970 MVT VecVT =
Op.getSimpleValueType();
12979 MVT ContainerVT = VecVT;
12986 MVT XLenVT = Subtarget.getXLenVT();
13032 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
13033 unsigned MaxVLMAX =
13038 unsigned GatherOpc = RISCVISD::VRGATHER_VV_VL;
13043 if (MaxVLMAX > 256 && EltSize == 8) {
13059 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
13067 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
13092 DAG.
getUNDEF(ContainerVT), Mask, VL);
13103 MVT XLenVT = Subtarget.getXLenVT();
13104 MVT VecVT =
Op.getSimpleValueType();
13109 SDValue DownOffset, UpOffset;
13110 if (ImmValue >= 0) {
13125 DAG, Subtarget,
DL, VecVT, DAG.
getUNDEF(VecVT), V1, DownOffset, TrueMask,
13126 Subtarget.hasVLDependentLatency() ? UpOffset
13128 return getVSlideup(DAG, Subtarget,
DL, VecVT, SlideDown, V2, UpOffset,
13134RISCVTargetLowering::lowerFixedLengthVectorLoadToRVV(
SDValue Op,
13140 Load->getMemoryVT(),
13141 *
Load->getMemOperand()) &&
13142 "Expecting a correctly-aligned load");
13144 MVT VT =
Op.getSimpleValueType();
13145 MVT XLenVT = Subtarget.getXLenVT();
13150 const auto [MinVLMAX, MaxVLMAX] =
13154 MachineMemOperand *MMO =
Load->getMemOperand();
13167 IsMaskOp ? Intrinsic::riscv_vlm : Intrinsic::riscv_vle,
DL, XLenVT);
13171 Ops.push_back(
Load->getBasePtr());
13173 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
13176 Load->getMemoryVT(),
Load->getMemOperand());
13183RISCVTargetLowering::lowerFixedLengthVectorStoreToRVV(
SDValue Op,
13189 Store->getMemoryVT(),
13190 *
Store->getMemOperand()) &&
13191 "Expecting a correctly-aligned store");
13195 MVT XLenVT = Subtarget.getXLenVT();
13211 const auto [MinVLMAX, MaxVLMAX] =
13215 MachineMemOperand *MMO =
Store->getMemOperand();
13225 IsMaskOp ? Intrinsic::riscv_vsm : Intrinsic::riscv_vse,
DL, XLenVT);
13228 {Store->getChain(), IntID, NewValue, Store->getBasePtr(), VL},
13229 Store->getMemoryVT(),
Store->getMemOperand());
13235 MVT VT =
Op.getSimpleValueType();
13238 EVT MemVT = MemSD->getMemoryVT();
13239 MachineMemOperand *MMO = MemSD->getMemOperand();
13240 SDValue Chain = MemSD->getChain();
13244 bool IsExpandingLoad =
false;
13246 Mask = VPLoad->getMask();
13248 VL = VPLoad->getVectorLength();
13252 PassThru =
MLoad->getPassThru();
13253 IsExpandingLoad =
MLoad->isExpandingLoad();
13258 MVT XLenVT = Subtarget.getXLenVT();
13260 MVT ContainerVT = VT;
13274 if (!IsUnmasked && IsExpandingLoad) {
13277 DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Mask,
13281 unsigned IntID = IsUnmasked || IsExpandingLoad ? Intrinsic::riscv_vle
13282 : Intrinsic::riscv_vle_mask;
13284 if (IntID == Intrinsic::riscv_vle)
13287 Ops.push_back(PassThru);
13288 Ops.push_back(BasePtr);
13289 if (IntID == Intrinsic::riscv_vle_mask)
13290 Ops.push_back(Mask);
13292 if (IntID == Intrinsic::riscv_vle_mask)
13295 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
13299 Chain =
Result.getValue(1);
13301 MVT IndexVT = ContainerVT;
13306 bool UseVRGATHEREI16 =
false;
13314 UseVRGATHEREI16 =
true;
13320 DAG.
getUNDEF(IndexVT), Mask, ExpandingVL);
13322 DAG.
getNode(UseVRGATHEREI16 ? RISCVISD::VRGATHEREI16_VV_VL
13323 : RISCVISD::VRGATHER_VV_VL,
13324 DL, ContainerVT, Result, Iota, PassThru, Mask, ExpandingVL);
13335 MVT VT =
Op->getSimpleValueType(0);
13338 EVT MemVT = VPLoadFF->getMemoryVT();
13339 MachineMemOperand *MMO = VPLoadFF->getMemOperand();
13340 SDValue Chain = VPLoadFF->getChain();
13344 SDValue VL = VPLoadFF->getVectorLength();
13346 MVT XLenVT = Subtarget.getXLenVT();
13348 MVT ContainerVT = VT;
13355 unsigned IntID = Intrinsic::riscv_vleff_mask;
13365 SDVTList VTs = DAG.
getVTList({ContainerVT,
Op->getValueType(1), MVT::Other});
13370 Chain =
Result.getValue(2);
13383 EVT MemVT = MemSD->getMemoryVT();
13384 MachineMemOperand *MMO = MemSD->getMemOperand();
13385 SDValue Chain = MemSD->getChain();
13389 bool IsCompressingStore =
false;
13391 Val = VPStore->getValue();
13392 Mask = VPStore->getMask();
13393 VL = VPStore->getVectorLength();
13396 Val = MStore->getValue();
13397 Mask = MStore->getMask();
13398 IsCompressingStore = MStore->isCompressingStore();
13405 MVT XLenVT = Subtarget.getXLenVT();
13407 MVT ContainerVT = VT;
13412 if (!IsUnmasked || IsCompressingStore) {
13421 if (IsCompressingStore) {
13424 DAG.
getUNDEF(ContainerVT), Val, Mask, VL);
13426 DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Mask,
13431 IsUnmasked ? Intrinsic::riscv_vse : Intrinsic::riscv_vse_mask;
13433 Ops.push_back(Val);
13434 Ops.push_back(BasePtr);
13436 Ops.push_back(Mask);
13451 MVT XLenVT = Subtarget.getXLenVT();
13452 MVT ContainerVT = VT;
13465 Passthru, Val, Mask, VL);
13475 unsigned Opc =
Op.getOpcode();
13482 MVT VT =
Op.getSimpleValueType();
13490 SDVTList VTList =
Op->getVTList();
13515 MVT ContainerInVT = InVT;
13533 RISCVISD::STRICT_FSETCC_VL,
DL, DAG.
getVTList(MaskVT, MVT::Other),
13534 {Chain, Op1, Op1, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
13537 RISCVISD::STRICT_FSETCC_VL,
DL, DAG.
getVTList(MaskVT, MVT::Other),
13538 {Chain, Op2, Op2, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
13541 DAG.
getNode(RISCVISD::VMAND_VL,
DL, MaskVT, OrderMask1, OrderMask2, VL);
13544 Res = DAG.
getNode(RISCVISD::STRICT_FSETCCS_VL,
DL,
13546 {Chain, Op1, Op2, CC, Mask, Mask, VL});
13549 : RISCVISD::STRICT_FSETCCS_VL;
13551 {Chain, Op1, Op2, CC, DAG.getUNDEF(MaskVT), Mask, VL});
13564 MVT VT =
Op.getSimpleValueType();
13568 "Unexpected type for ISD::ABS");
13570 MVT ContainerVT = VT;
13577 if (
Op->getOpcode() == ISD::VP_ABS) {
13578 Mask =
Op->getOperand(1);
13582 VL =
Op->getOperand(2);
13587 RISCVISD::VMV_V_X_VL,
DL, ContainerVT, DAG.
getUNDEF(ContainerVT),
13590 DAG.
getUNDEF(ContainerVT), Mask, VL);
13592 DAG.
getUNDEF(ContainerVT), Mask, VL);
13601 const auto &TSInfo =
13605 bool HasPassthruOp = TSInfo.hasPassthruOp(NewOpc);
13606 bool HasMask = TSInfo.hasMaskOp(NewOpc);
13608 MVT VT =
Op.getSimpleValueType();
13613 for (
const SDValue &V :
Op->op_values()) {
13617 if (!
V.getValueType().isVector()) {
13623 assert(useRVVForFixedLengthVectorVT(
V.getSimpleValueType()) &&
13624 "Only fixed length vectors are supported!");
13626 V.getSimpleValueType().getVectorElementType());
13635 Ops.push_back(Mask);
13640 if (
Op->isStrictFPOpcode()) {
13659 const auto &TSInfo =
13663 bool HasPassthruOp = TSInfo.hasPassthruOp(RISCVISDOpc);
13666 MVT VT =
Op.getSimpleValueType();
13669 MVT ContainerVT = VT;
13678 if (HasPassthruOp) {
13681 if (*MaskIdx ==
OpIdx.index())
13685 if (
Op.getOpcode() == ISD::VP_MERGE) {
13687 Ops.push_back(
Ops.back());
13689 assert(
Op.getOpcode() == ISD::VP_SELECT);
13696 if (RISCVISDOpc == RISCVISD::VFCVT_RM_X_F_VL &&
13699 Subtarget.getXLenVT()));
13701 if (!
V.getValueType().isFixedLengthVector()) {
13706 MVT OpVT =
V.getSimpleValueType();
13708 assert(useRVVForFixedLengthVectorVT(OpVT) &&
13709 "Only fixed length vectors are supported!");
13724 MVT VT =
Op.getSimpleValueType();
13730 MVT ContainerVT = VT;
13737 MVT XLenVT = Subtarget.getXLenVT();
13740 DAG.
getUNDEF(ContainerVT), Zero, VL);
13743 Op.getOpcode() == ISD::VP_ZERO_EXTEND ? 1 : -1,
DL, XLenVT);
13745 DAG.
getUNDEF(ContainerVT), SplatValue, VL);
13748 ZeroSplat, DAG.
getUNDEF(ContainerVT), VL);
13757 MVT VT =
Op.getSimpleValueType();
13765 MVT ContainerVT = VT;
13773 SDValue AllOneMask = DAG.
getNode(RISCVISD::VMSET_VL,
DL, ContainerVT, VL);
13775 switch (Condition) {
13780 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, Op2, VL);
13785 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, Op2, VL);
13787 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, AllOneMask, VL);
13795 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, AllOneMask, VL);
13796 Result = DAG.
getNode(RISCVISD::VMAND_VL,
DL, ContainerVT, Temp, Op2, VL);
13804 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op2, AllOneMask, VL);
13805 Result = DAG.
getNode(RISCVISD::VMAND_VL,
DL, ContainerVT, Op1, Temp, VL);
13813 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, AllOneMask, VL);
13814 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, Op2, VL);
13822 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op2, AllOneMask, VL);
13823 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, Op1, VL);
13843 MVT DstVT =
Op.getSimpleValueType();
13844 MVT SrcVT = Src.getSimpleValueType();
13857 if (DstEltSize >= SrcEltSize) {
13861 unsigned RISCVISDExtOpc = RISCVISDOpc == RISCVISD::SINT_TO_FP_VL
13862 ? RISCVISD::VSEXT_VL
13863 : RISCVISD::VZEXT_VL;
13866 if (SrcEltSize == 1) {
13868 MVT XLenVT = Subtarget.getXLenVT();
13873 RISCVISDExtOpc == RISCVISD::VZEXT_VL ? 1 : -1,
DL, XLenVT);
13876 Src = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, IntVT, Src, OneSplat,
13877 ZeroSplat, DAG.
getUNDEF(IntVT), VL);
13878 }
else if (DstEltSize > (2 * SrcEltSize)) {
13882 Src = DAG.
getNode(RISCVISDExtOpc,
DL, IntVT, Src, Mask, VL);
13888 "Wrong input/output vector types");
13891 if (DstEltSize > (2 * SrcEltSize)) {
13896 DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, InterimFVT, Src, Mask, VL);
13907 MVT InterimFVT = DstVT;
13908 if (SrcEltSize > (2 * DstEltSize)) {
13909 assert(SrcEltSize == (4 * DstEltSize) &&
"Unexpected types!");
13916 if (InterimFVT != DstVT) {
13918 Result = DAG.
getNode(RISCVISD::FP_ROUND_VL,
DL, DstVT, Src, Mask, VL);
13922 "Wrong input/output vector types");
13926 if (DstEltSize == 1) {
13929 assert(SrcEltSize >= 16 &&
"Unexpected FP type!");
13936 MVT XLenVT = Subtarget.getXLenVT();
13938 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, InterimIVT,
13939 DAG.
getUNDEF(InterimIVT), SplatZero, VL);
13949 while (InterimIVT != DstVT) {
13961 MVT VT =
Op.getSimpleValueType();
13970 MVT VT =
Op.getSimpleValueType();
13971 MVT XLenVT = Subtarget.getXLenVT();
13984 MVT ContainerVT = VT;
14004 TrueVal = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, PromotedVT, TrueVal, SplatOne,
14005 SplatZero, DAG.
getUNDEF(PromotedVT), VL);
14008 SplatOne, SplatZero, DAG.
getUNDEF(PromotedVT), VLMax);
14012 TrueVal, FalseVal, FalseVal, VL);
14017 RISCVISD::SETCC_VL,
DL, ContainerVT,
14027RISCVTargetLowering::lowerVPSpliceExperimental(
SDValue Op,
14029 using namespace SDPatternMatch;
14040 const MVT XLenVT = Subtarget.getXLenVT();
14041 MVT VT =
Op.getSimpleValueType();
14042 MVT ContainerVT = VT;
14052 if (IsMaskVector) {
14062 Op1 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, Op1, SplatOneOp1,
14063 SplatZeroOp1, DAG.
getUNDEF(ContainerVT), EVL1);
14071 Op2 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, Op2, SplatOneOp2,
14072 SplatZeroOp2, DAG.
getUNDEF(ContainerVT), EVL2);
14075 auto getVectorFirstEle = [](
SDValue Vec) {
14088 if (
auto FirstEle = getVectorFirstEle(
Op->getOperand(0))) {
14091 if ((EltVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
14092 EltVT == MVT::bf16) {
14100 : RISCVISD::VSLIDE1UP_VL,
14101 DL, ContainerVT, DAG.
getUNDEF(ContainerVT), Op2,
14102 FirstEle, Mask, EVL2);
14112 SDValue DownOffset, UpOffset;
14113 if (ImmValue >= 0) {
14127 DAG.
getUNDEF(ContainerVT), Op1, DownOffset, Mask,
14128 Subtarget.hasVLDependentLatency() ? UpOffset : EVL2);
14132 if (IsMaskVector) {
14136 {Result, DAG.getConstant(0, DL, ContainerVT),
14137 DAG.getCondCode(ISD::SETNE), DAG.getUNDEF(getMaskTypeFor(ContainerVT)),
14147RISCVTargetLowering::lowerVPReverseExperimental(
SDValue Op,
14150 MVT VT =
Op.getSimpleValueType();
14151 MVT XLenVT = Subtarget.getXLenVT();
14157 MVT ContainerVT = VT;
14165 MVT GatherVT = ContainerVT;
14169 if (IsMaskVector) {
14179 Op1 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, IndicesVT, Op1, SplatOne,
14180 SplatZero, DAG.
getUNDEF(IndicesVT), EVL);
14185 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
14186 unsigned MaxVLMAX =
14189 unsigned GatherOpc = RISCVISD::VRGATHER_VV_VL;
14195 if (MaxVLMAX > 256 && EltSize == 8) {
14222 DAG.
getUNDEF(GatherVT), Result, Diff, Mask, EVL);
14224 if (IsMaskVector) {
14227 DAG.
getNode(RISCVISD::SETCC_VL,
DL, ContainerVT,
14240 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
14247 DAG.
getUNDEF(IndicesVT), VecLen, EVL);
14248 SDValue VRSUB = DAG.
getNode(RISCVISD::SUB_VL,
DL, IndicesVT, VecLenSplat, VID,
14249 DAG.
getUNDEF(IndicesVT), Mask, EVL);
14251 DAG.
getUNDEF(GatherVT), Mask, EVL);
14253 if (IsMaskVector) {
14256 RISCVISD::SETCC_VL,
DL, ContainerVT,
14268 MVT VT =
Op.getSimpleValueType();
14270 return lowerVPOp(
Op, DAG);
14277 MVT ContainerVT = VT;
14295 MVT XLenVT = Subtarget.getXLenVT();
14296 MVT VT =
Op.getSimpleValueType();
14297 MVT ContainerVT = VT;
14301 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
14309 : Intrinsic::riscv_vlse_mask,
14312 DAG.
getUNDEF(ContainerVT), VPNode->getBasePtr(),
14313 VPNode->getStride()};
14319 Ops.push_back(Mask);
14321 Ops.push_back(VPNode->getVectorLength());
14325 Ops.push_back(Policy);
14330 VPNode->getMemoryVT(), VPNode->getMemOperand());
14342 MVT XLenVT = Subtarget.getXLenVT();
14345 SDValue StoreVal = VPNode->getValue();
14347 MVT ContainerVT = VT;
14358 : Intrinsic::riscv_vsse_mask,
14361 VPNode->getBasePtr(), VPNode->getStride()};
14367 Ops.push_back(Mask);
14369 Ops.push_back(VPNode->getVectorLength());
14372 Ops, VPNode->getMemoryVT(),
14373 VPNode->getMemOperand());
14385 MVT VT =
Op.getSimpleValueType();
14388 EVT MemVT = MemSD->getMemoryVT();
14389 MachineMemOperand *MMO = MemSD->getMemOperand();
14390 SDValue Chain = MemSD->getChain();
14397 Index = VPGN->getIndex();
14398 Mask = VPGN->getMask();
14400 VL = VPGN->getVectorLength();
14406 Index = MGN->getIndex();
14407 Mask = MGN->getMask();
14408 PassThru = MGN->getPassThru();
14412 MVT IndexVT =
Index.getSimpleValueType();
14413 MVT XLenVT = Subtarget.getXLenVT();
14416 "Unexpected VTs!");
14417 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
14420 "Unexpected extending MGATHER/VP_GATHER");
14426 MVT ContainerVT = VT;
14450 IsUnmasked ? Intrinsic::riscv_vluxei : Intrinsic::riscv_vluxei_mask;
14455 Ops.push_back(PassThru);
14456 Ops.push_back(BasePtr);
14457 Ops.push_back(Index);
14459 Ops.push_back(Mask);
14464 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
14467 Chain =
Result.getValue(1);
14485 EVT MemVT = MemSD->getMemoryVT();
14486 MachineMemOperand *MMO = MemSD->getMemOperand();
14487 SDValue Chain = MemSD->getChain();
14490 [[maybe_unused]]
bool IsTruncatingStore =
false;
14494 Index = VPSN->getIndex();
14495 Mask = VPSN->getMask();
14496 Val = VPSN->getValue();
14497 VL = VPSN->getVectorLength();
14499 IsTruncatingStore =
false;
14503 Index = MSN->getIndex();
14504 Mask = MSN->getMask();
14505 Val = MSN->getValue();
14506 IsTruncatingStore = MSN->isTruncatingStore();
14510 MVT IndexVT =
Index.getSimpleValueType();
14511 MVT XLenVT = Subtarget.getXLenVT();
14514 "Unexpected VTs!");
14515 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
14518 assert(!IsTruncatingStore &&
"Unexpected truncating MSCATTER/VP_SCATTER");
14524 MVT ContainerVT = VT;
14548 IsUnmasked ? Intrinsic::riscv_vsoxei : Intrinsic::riscv_vsoxei_mask;
14550 Ops.push_back(Val);
14551 Ops.push_back(BasePtr);
14552 Ops.push_back(Index);
14554 Ops.push_back(Mask);
14563 const MVT XLenVT = Subtarget.getXLenVT();
14567 SDVTList VTs = DAG.
getVTList(XLenVT, MVT::Other);
14574 static const int Table =
14593 const MVT XLenVT = Subtarget.getXLenVT();
14603 static const unsigned Table =
14618 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14624 const MVT XLenVT = Subtarget.getXLenVT();
14628 SDVTList VTs = DAG.
getVTList(XLenVT, MVT::Other);
14629 return DAG.
getNode(RISCVISD::READ_CSR,
DL, VTs, Chain, SysRegNo);
14634 const MVT XLenVT = Subtarget.getXLenVT();
14641 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14647 const MVT XLenVT = Subtarget.getXLenVT();
14653 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14667 SDValue Result = DAG.
getNode(RISCVISD::READ_CSR,
DL, VTs, Chain, SysRegNo);
14668 Chain = Result.getValue(1);
14674 const MVT XLenVT = Subtarget.getXLenVT();
14684 Chain = DAG.
getNode(RISCVISD::CLEAR_CSR,
DL, MVT::Other, Chain, SysRegNo,
14686 return DAG.
getNode(RISCVISD::SET_CSR,
DL, MVT::Other, Chain, SysRegNo,
14692 const MVT XLenVT = Subtarget.getXLenVT();
14699 return DAG.
getNode(RISCVISD::CLEAR_CSR,
DL, MVT::Other, Chain, SysRegNo,
14707 bool isRISCV64 = Subtarget.is64Bit();
14721 return RISCVISD::SLLW;
14723 return RISCVISD::SRAW;
14725 return RISCVISD::SRLW;
14727 return RISCVISD::DIVW;
14729 return RISCVISD::DIVUW;
14731 return RISCVISD::REMUW;
14733 return RISCVISD::ROLW;
14735 return RISCVISD::RORW;
14771 switch (
N->getOpcode()) {
14773 llvm_unreachable(
"Don't know how to custom type legalize this operation!");
14778 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14779 "Unexpected custom legalisation");
14780 bool IsStrict =
N->isStrictFPOpcode();
14783 SDValue Op0 = IsStrict ?
N->getOperand(1) :
N->getOperand(0);
14792 !Subtarget.hasStdExtZfhOrZhinx()) {
14797 unsigned Opc = IsSigned ? RISCVISD::STRICT_FCVT_W_RV64
14798 : RISCVISD::STRICT_FCVT_WU_RV64;
14801 Opc,
DL, VTs, Chain, Op0,
14810 !Subtarget.hasStdExtZfhOrZhinx()) ||
14814 unsigned Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
14835 std::tie(Result, Chain) =
14836 makeLibCall(DAG, LC,
N->getValueType(0), Op0, CallOptions,
DL, Chain);
14851 if (Op0.
getValueType() == MVT::f16 && !Subtarget.hasStdExtZfhOrZhinx())
14855 DAG.
getNode(RISCVISD::FCVT_W_RV64,
DL, MVT::i64, Op0,
14863 RTLIB::Libcall LC =
14864 Op0.
getValueType() == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
14875 assert(!Subtarget.is64Bit() &&
"READCYCLECOUNTER/READSTEADYCOUNTER only "
14876 "has custom type legalization on riscv32");
14878 SDValue LoCounter, HiCounter;
14879 MVT XLenVT = Subtarget.getXLenVT();
14889 N->getOperand(0), LoCounter, HiCounter);
14904 if (
N->getValueType(0) == MVT::i64) {
14905 assert(Subtarget.hasStdExtZilsd() && !Subtarget.is64Bit() &&
14906 "Unexpected custom legalisation");
14908 if (Ld->
getAlign() < Subtarget.getZilsdAlign())
14913 RISCVISD::LD_RV32,
DL,
14914 DAG.
getVTList({MVT::i32, MVT::i32, MVT::Other}),
14915 {Ld->getChain(), Ld->getBasePtr()}, MVT::i64, Ld->
getMemOperand());
14919 Results.append({Pair, Result.getValue(2)});
14923 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14924 "Unexpected custom legalisation");
14935 unsigned Size =
N->getSimpleValueType(0).getSizeInBits();
14936 unsigned XLen = Subtarget.getXLen();
14939 assert(
Size == (XLen * 2) &&
"Unexpected custom legalisation");
14947 if (LHSIsU == RHSIsU)
14951 MVT XLenVT = Subtarget.getXLenVT();
14964 if (RHSIsU && LHSIsS && !RHSIsS)
14965 Results.push_back(MakeMULPair(LHS, RHS));
14966 else if (LHSIsU && RHSIsS && !LHSIsS)
14967 Results.push_back(MakeMULPair(RHS, LHS));
14975 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14976 "Unexpected custom legalisation");
14982 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14983 "Unexpected custom legalisation");
14986 if (
N->getOpcode() ==
ISD::SHL && Subtarget.hasStdExtZbs() &&
15011 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
15012 "Unexpected custom legalisation");
15013 assert((Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb() ||
15014 Subtarget.hasVendorXTHeadBb()) &&
15015 "Unexpected custom legalization");
15017 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()))
15025 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
15026 "Unexpected custom legalisation");
15033 unsigned Opc = IsCTZ ? RISCVISD::CTZW : RISCVISD::CLZW;
15041 MVT VT =
N->getSimpleValueType(0);
15042 assert((VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32) &&
15043 Subtarget.is64Bit() && Subtarget.hasStdExtM() &&
15044 "Unexpected custom legalisation");
15056 if (VT != MVT::i32)
15064 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
15065 "Unexpected custom legalisation");
15086 EVT OType =
N->getValueType(1);
15098 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
15099 "Unexpected custom legalisation");
15116 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1), Res,
15120 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1),
N->getOperand(0),
15127 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1), Res, LHS,
15137 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
15138 !Subtarget.hasStdExtZbb() &&
"Unexpected custom legalisation");
15146 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
15147 "Unexpected custom legalisation");
15152 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
15153 "Unexpected custom legalisation");
15155 if (Subtarget.hasStdExtP()) {
15163 if (Subtarget.hasStdExtZbb()) {
15197 EVT VT =
N->getValueType(0);
15201 MVT XLenVT = Subtarget.getXLenVT();
15202 if (VT == MVT::i16 &&
15203 ((Op0VT == MVT::f16 && Subtarget.hasStdExtZfhminOrZhinxmin()) ||
15204 (Op0VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
15207 }
else if (VT == MVT::i32 && Op0VT == MVT::f32 && Subtarget.is64Bit() &&
15208 Subtarget.hasStdExtFOrZfinx()) {
15210 DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Op0);
15212 }
else if (VT == MVT::i64 && Op0VT == MVT::f64 && !Subtarget.is64Bit() &&
15213 Subtarget.hasStdExtDOrZdinx()) {
15215 DAG.
getVTList(MVT::i32, MVT::i32), Op0);
15234 assert(
N->getValueType(0) == MVT::i8 && Subtarget.hasStdExtZbkb() &&
15235 "Unexpected custom legalisation");
15236 MVT XLenVT = Subtarget.getXLenVT();
15244 case RISCVISD::BREV8:
15245 case RISCVISD::ORC_B: {
15246 MVT VT =
N->getSimpleValueType(0);
15247 MVT XLenVT = Subtarget.getXLenVT();
15248 assert((VT == MVT::i16 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
15249 "Unexpected custom legalisation");
15250 assert(((
N->getOpcode() == RISCVISD::BREV8 && Subtarget.hasStdExtZbkb()) ||
15251 (
N->getOpcode() == RISCVISD::ORC_B && Subtarget.hasStdExtZbb())) &&
15252 "Unexpected extension");
15260 case RISCVISD::PASUB:
15261 case RISCVISD::PASUBU: {
15262 MVT VT =
N->getSimpleValueType(0);
15265 assert(VT == MVT::v2i16 || VT == MVT::v4i8);
15266 MVT NewVT = MVT::v4i16;
15267 if (VT == MVT::v4i8)
15293 assert(!Subtarget.is64Bit() &&
N->getValueType(0) == MVT::i64 &&
15295 "Unexpected EXTRACT_VECTOR_ELT legalization");
15298 MVT ContainerVT = VecVT;
15304 MVT XLenVT = Subtarget.getXLenVT();
15313 DAG.
getUNDEF(ContainerVT), Vec, Idx, Mask, VL);
15325 DAG.
getNode(RISCVISD::SRL_VL,
DL, ContainerVT, Vec, ThirtyTwoV,
15326 DAG.
getUNDEF(ContainerVT), Mask, VL);
15334 unsigned IntNo =
N->getConstantOperandVal(0);
15338 "Don't know how to custom type legalize this intrinsic!");
15339 case Intrinsic::experimental_get_vector_length: {
15344 case Intrinsic::experimental_cttz_elts: {
15350 case Intrinsic::riscv_orc_b:
15351 case Intrinsic::riscv_brev8:
15352 case Intrinsic::riscv_sha256sig0:
15353 case Intrinsic::riscv_sha256sig1:
15354 case Intrinsic::riscv_sha256sum0:
15355 case Intrinsic::riscv_sha256sum1:
15356 case Intrinsic::riscv_sm3p0:
15357 case Intrinsic::riscv_sm3p1: {
15358 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15362 case Intrinsic::riscv_orc_b:
Opc = RISCVISD::ORC_B;
break;
15363 case Intrinsic::riscv_brev8:
Opc = RISCVISD::BREV8;
break;
15364 case Intrinsic::riscv_sha256sig0:
Opc = RISCVISD::SHA256SIG0;
break;
15365 case Intrinsic::riscv_sha256sig1:
Opc = RISCVISD::SHA256SIG1;
break;
15366 case Intrinsic::riscv_sha256sum0:
Opc = RISCVISD::SHA256SUM0;
break;
15367 case Intrinsic::riscv_sha256sum1:
Opc = RISCVISD::SHA256SUM1;
break;
15368 case Intrinsic::riscv_sm3p0:
Opc = RISCVISD::SM3P0;
break;
15369 case Intrinsic::riscv_sm3p1:
Opc = RISCVISD::SM3P1;
break;
15378 case Intrinsic::riscv_sm4ks:
15379 case Intrinsic::riscv_sm4ed: {
15381 IntNo == Intrinsic::riscv_sm4ks ? RISCVISD::SM4KS : RISCVISD::SM4ED;
15387 DAG.
getNode(
Opc,
DL, MVT::i64, NewOp0, NewOp1,
N->getOperand(3));
15391 case Intrinsic::riscv_mopr: {
15392 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15397 RISCVISD::MOP_R,
DL, MVT::i64, NewOp,
15402 case Intrinsic::riscv_moprr: {
15403 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15410 RISCVISD::MOP_RR,
DL, MVT::i64, NewOp0, NewOp1,
15415 case Intrinsic::riscv_clmul: {
15416 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15427 case Intrinsic::riscv_clmulh:
15428 case Intrinsic::riscv_clmulr: {
15429 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15449 unsigned Opc = IntNo == Intrinsic::riscv_clmulh ? RISCVISD::CLMULH
15450 : RISCVISD::CLMULR;
15457 case Intrinsic::riscv_vmv_x_s: {
15458 EVT VT =
N->getValueType(0);
15459 MVT XLenVT = Subtarget.getXLenVT();
15460 if (VT.
bitsLT(XLenVT)) {
15463 Subtarget.getXLenVT(),
N->getOperand(1));
15468 assert(VT == MVT::i64 && !Subtarget.is64Bit() &&
15469 "Unexpected custom legalization");
15485 SDValue LShr32 = DAG.
getNode(RISCVISD::SRL_VL,
DL, VecVT, Vec, ThirtyTwoV,
15507 case ISD::VP_REDUCE_ADD:
15508 case ISD::VP_REDUCE_AND:
15509 case ISD::VP_REDUCE_OR:
15510 case ISD::VP_REDUCE_XOR:
15511 case ISD::VP_REDUCE_SMAX:
15512 case ISD::VP_REDUCE_UMAX:
15513 case ISD::VP_REDUCE_SMIN:
15514 case ISD::VP_REDUCE_UMIN:
15582 const EVT VT =
N->getValueType(0);
15583 const unsigned Opc =
N->getOpcode();
15593 if (!
N->getFlags().hasAllowReassociation())
15604 "Inconsistent mappings");
15608 if (!
LHS.hasOneUse() || !
RHS.hasOneUse())
15636 if (0 == std::min(LHSIdx, RHSIdx) && 1 == std::max(LHSIdx, RHSIdx)) {
15639 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
N->getFlags());
15646 if (
LHS.getOpcode() != ReduceOpc)
15660 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
15661 ReduceVec->
getFlags() &
N->getFlags());
15671 auto BinOpToRVVReduce = [](
unsigned Opc) {
15676 return RISCVISD::VECREDUCE_ADD_VL;
15678 return RISCVISD::VECREDUCE_UMAX_VL;
15680 return RISCVISD::VECREDUCE_SMAX_VL;
15682 return RISCVISD::VECREDUCE_UMIN_VL;
15684 return RISCVISD::VECREDUCE_SMIN_VL;
15686 return RISCVISD::VECREDUCE_AND_VL;
15688 return RISCVISD::VECREDUCE_OR_VL;
15690 return RISCVISD::VECREDUCE_XOR_VL;
15692 return RISCVISD::VECREDUCE_FADD_VL;
15694 return RISCVISD::VECREDUCE_FMAX_VL;
15696 return RISCVISD::VECREDUCE_FMIN_VL;
15700 auto IsReduction = [&BinOpToRVVReduce](
SDValue V,
unsigned Opc) {
15703 V.getOperand(0).getOpcode() == BinOpToRVVReduce(
Opc);
15706 unsigned Opc =
N->getOpcode();
15707 unsigned ReduceIdx;
15708 if (IsReduction(
N->getOperand(0),
Opc))
15710 else if (IsReduction(
N->getOperand(1),
Opc))
15716 if (
Opc ==
ISD::FADD && !
N->getFlags().hasAllowReassociation())
15719 SDValue Extract =
N->getOperand(ReduceIdx);
15732 if (ScalarV.
getOpcode() != RISCVISD::VFMV_S_F_VL &&
15733 ScalarV.
getOpcode() != RISCVISD::VMV_S_X_VL &&
15734 ScalarV.
getOpcode() != RISCVISD::VMV_V_X_VL)
15751 SDValue NewStart =
N->getOperand(1 - ReduceIdx);
15784 EVT VT =
N->getValueType(0);
15800 int64_t C0 = N0C->getSExtValue();
15801 int64_t C1 = N1C->getSExtValue();
15802 if (C0 <= 0 || C1 <= 0)
15805 int64_t Diff = std::abs(C0 - C1);
15811 int64_t Bits = std::min(C0, C1);
15843 if (VShift.
slt(1) || VShift.
sgt(3))
15847 EVT VT =
N->getValueType(0);
15867 EVT VT =
N->getValueType(0);
15895 EVT VT =
N->getValueType(0);
15916 Slct.
getOpcode() != RISCVISD::SELECT_CC) ||
15924 bool SwapSelectOps;
15925 unsigned OpOffset = Slct.
getOpcode() == RISCVISD::SELECT_CC ? 2 : 0;
15930 SwapSelectOps =
false;
15931 NonConstantVal = FalseVal;
15933 SwapSelectOps =
true;
15934 NonConstantVal = TrueVal;
15940 FalseVal = DAG.
getNode(
N->getOpcode(),
SDLoc(
N), VT, OtherOp, NonConstantVal);
15945 if (Slct.
getOpcode() == RISCVISD::SELECT_CC)
15988 EVT VT =
N->getValueType(0);
16003 if (!N0C->hasOneUse())
16005 int64_t C0 = N0C->getSExtValue();
16006 int64_t C1 = N1C->getSExtValue();
16008 if (C0 == -1 || C0 == 0 || C0 == 1 ||
isInt<12>(C1))
16015 }
else if ((C1 / C0 + 1) != 0 &&
isInt<12>(C1 / C0 + 1) &&
16019 }
else if ((C1 / C0 - 1) != 0 &&
isInt<12>(C1 / C0 - 1) &&
16047 EVT VT =
N->getValueType(0);
16078 unsigned OuterExtend =
16082 OuterExtend,
SDLoc(
N), VT,
16090 EVT VT =
N->getValueType(0);
16140 EVT VT =
N->getValueType(0);
16150 APInt ImmValMinus1 = N0C->getAPIntValue() - 1;
16160 if (!isIntEqualitySetCC(CCVal) || !SetCCOpVT.
isInteger())
16183 if (!Subtarget.hasStdExtZbb())
16186 EVT VT =
N->getValueType(0);
16188 if (VT != Subtarget.
getXLenVT() && VT != MVT::i32 && VT != MVT::i16)
16200 unsigned ShiftedAmount = 8 - ShAmtCLeft->getZExtValue();
16202 if (ShiftedAmount >= 8)
16206 SDValue RightShiftOperand = N1;
16208 if (ShiftedAmount != 0) {
16212 if (!ShAmtCRight || ShAmtCRight->getZExtValue() != ShiftedAmount)
16221 if (LeftShiftOperand != RightShiftOperand)
16225 Mask <<= ShiftedAmount;
16231 return DAG.
getNode(RISCVISD::ORC_B,
SDLoc(
N), VT, LeftShiftOperand);
16239 EVT VT =
N->getValueType(0);
16271 bool IsAnd =
N->getOpcode() ==
ISD::AND;
16295 EVT VT =
N->getValueType(0);
16319 EVT VT =
N->getValueType(0);
16346 if (CondLHS != True)
16353 if (!CondRHSC || CondRHSC->
getAPIntValue() != (1ULL << ScalarBits))
16365 if (!FalseRHSC || !FalseRHSC->
isZero())
16388 EVT VT =
N->getValueType(0);
16393 if (VecVT != MVT::v4i16 && VecVT != MVT::v2i16 && VecVT != MVT::v8i8 &&
16394 VecVT != MVT::v4i8 && VecVT != MVT::v2i32)
16411 if (
C->getZExtValue() != 1)
16429 if (!IsSignExt && !IsZeroExt)
16436 if (
A.getValueType() != VT ||
B.getValueType() != VT)
16442 Opc = RISCVISD::PASUB;
16443 else if (IsZeroExt)
16444 Opc = RISCVISD::PASUBU;
16455 EVT VT =
N->getValueType(0);
16465 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() && VT == MVT::i1 &&
16508 EVT VT =
N->getValueType(0);
16527 EVT WideVT =
X.getValueType();
16554 auto IsEqualCompZero = [](
SDValue &V) ->
bool {
16563 if (!IsEqualCompZero(N0) || !N0.
hasOneUse())
16565 if (!IsEqualCompZero(N0) || !N0.
hasOneUse())
16572 unsigned CzeroOpcode =
16574 ? RISCVISD::CZERO_EQZ
16575 : RISCVISD::CZERO_NEZ;
16577 EVT VT =
N->getValueType(0);
16604 if (Mask != ExpectedMask)
16630 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
16670 if (N0.
getOpcode() != RISCVISD::CZERO_EQZ ||
16671 N1.
getOpcode() != RISCVISD::CZERO_NEZ ||
16689 EVT VT =
N->getValueType(0);
16707 if (!Subtarget.hasVendorXqcibm())
16719 if (
N->getValueType(0) != MVT::i32)
16721 unsigned Width, ShAmt;
16738 return DAG.
getNode(RISCVISD::QC_INSB,
DL, MVT::i32,
Ops);
16743 if (!Subtarget.hasVendorXqcibm())
16753 unsigned ShAmt, Width;
16757 if (
N->getValueType(0) != MVT::i32)
16762 if (Width == 1 && Subtarget.hasStdExtZbs())
16774 return DAG.
getNode(RISCVISD::QC_INSB,
DL, MVT::i32,
Ops);
16782 if (!Subtarget.hasVendorXqcibm())
16788 APInt MaskImm, OrImm;
16807 unsigned ShAmt, Width;
16820 return DAG.
getNode(RISCVISD::QC_INSB,
DL, MVT::i32,
Ops);
16862 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
16877 if (N0.
getOpcode() == RISCVISD::SLLW &&
16881 return DAG.
getNode(RISCVISD::ROLW,
DL, MVT::i64,
16892 const APInt &Imm = ConstN00->getAPIntValue();
16893 if ((Imm + 1).isSignedIntN(12))
16917 EVT VT =
N->getValueType(0);
16926 bool IsAdd = (
E & 3) == 1;
16927 E -= IsAdd ? 1 : -1;
16931 Result = DAG.
getNode(AddSubOp,
DL, VT, Result, ShiftVal);
16941 uint64_t MulAmtLowBit = MulAmt & (-MulAmt);
16946 auto PreferSub = [
X, MulAmtLowBit]() {
16955 if (
isPowerOf2_64(MulAmt - MulAmtLowBit) && !(CanSub && PreferSub())) {
16957 ShiftAmt1 = MulAmt - MulAmtLowBit;
16958 }
else if (CanSub) {
16960 ShiftAmt1 = MulAmt + MulAmtLowBit;
16964 EVT VT =
N->getValueType(0);
16974 unsigned ShY,
bool AddX,
unsigned Shift) {
16976 EVT VT =
N->getValueType(0);
16991 ShlAdd = DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, ShlAdd,
17001 uint64_t MulAmt,
unsigned Shift) {
17027 assert(ShX != 0 &&
"MulAmt=4,6,10 handled before");
17034 EVT VT =
N->getValueType(0);
17051 EVT VT =
N->getValueType(0);
17060 bool ShouldExpandMul =
17062 !Subtarget.hasStdExtZmmul();
17063 if (!ShouldExpandMul)
17093 if (Shift >= 1 && Shift <= 3 &&
isPowerOf2_64(MulAmt & (MulAmt - 1))) {
17098 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT,
X,
17105 if (MulAmt > 2 &&
isPowerOf2_64((MulAmt - 1) & (MulAmt - 2))) {
17107 if (ScaleShift >= 1 && ScaleShift < 4) {
17139 if (!Subtarget.hasStdExtZmmul())
17149 EVT VT =
N->getValueType(0);
17156 if (
N->getOperand(0).getOpcode() !=
ISD::AND ||
17157 N->getOperand(0).getOperand(0).getOpcode() !=
ISD::SRL)
17170 if (!V1.
isMask(HalfSize) || V2 != (1ULL | 1ULL << HalfSize) ||
17171 V3 != (HalfSize - 1))
17187 EVT VT =
N->getValueType(0);
17195 unsigned AddSubOpc;
17201 auto IsAddSubWith1 = [&](
SDValue V) ->
bool {
17202 AddSubOpc = V->getOpcode();
17214 if (IsAddSubWith1(N0)) {
17216 return DAG.
getNode(AddSubOpc,
DL, VT, N1, MulVal);
17219 if (IsAddSubWith1(N1)) {
17221 return DAG.
getNode(AddSubOpc,
DL, VT, N0, MulVal);
17236 if (isIndexTypeSigned(IndexType))
17239 if (!
N->hasOneUse())
17242 EVT VT =
N.getValueType();
17281 EVT SrcVT = Src.getValueType();
17285 NewElen = std::max(NewElen, 8U);
17312 EVT OpVT =
X.getValueType();
17320 if (OpSize <= Subtarget.
getXLen() ||
17326 auto IsVectorBitCastCheap = [](
SDValue X) {
17331 if (!IsVectorBitCastCheap(
X) || !IsVectorBitCastCheap(
Y))
17335 Attribute::NoImplicitFloat))
17342 unsigned VecSize = OpSize / 8;
17354 DAG.
getNode(ISD::VP_REDUCE_OR,
DL, XLenVT,
17367 EVT VT =
N->getValueType(0);
17372 if (!isIntEqualitySetCC(
Cond))
17397 if (OpVT == MVT::i64 &&
isUInt<32>(AndRHSInt) &&
17401 if (NewC >= -2048 && NewC <= 2048) {
17407 return DAG.
getSetCC(dl, VT, Shift,
17417 if (OpVT != MVT::i64 || !Subtarget.
is64Bit())
17437 const APInt &C1 = N1C->getAPIntValue();
17455 EVT VT =
N->getValueType(0);
17457 unsigned Opc = Src.getOpcode();
17462 if (
Opc == RISCVISD::FMV_X_ANYEXTH && SrcVT.
bitsGE(MVT::i16) &&
17463 Subtarget.hasStdExtZfhmin())
17464 return DAG.
getNode(RISCVISD::FMV_X_SIGNEXTH,
DL, VT, Src.getOperand(0));
17470 return DAG.
getNode(RISCVISD::SLLW,
DL, VT, Src.getOperand(0),
17471 Src.getOperand(1));
17490struct CombineResult;
17492enum ExtKind : uint8_t {
17524struct NodeExtensionHelper {
17533 bool SupportsFPExt;
17535 bool SupportsBF16Ext;
17538 bool EnforceOneUse;
17548 case RISCVISD::VSEXT_VL:
17549 case RISCVISD::VZEXT_VL:
17550 case RISCVISD::FP_EXTEND_VL:
17553 return OrigOperand;
17559 return OrigOperand.
getOpcode() == RISCVISD::VMV_V_X_VL ||
17564 unsigned getExtOpc(ExtKind SupportsExt)
const {
17565 switch (SupportsExt) {
17566 case ExtKind::SExt:
17567 return RISCVISD::VSEXT_VL;
17568 case ExtKind::ZExt:
17569 return RISCVISD::VZEXT_VL;
17570 case ExtKind::FPExt:
17571 case ExtKind::BF16Ext:
17572 return RISCVISD::FP_EXTEND_VL;
17580 SDValue getOrCreateExtendedOp(SDNode *Root, SelectionDAG &DAG,
17581 const RISCVSubtarget &Subtarget,
17582 std::optional<ExtKind> SupportsExt)
const {
17583 if (!SupportsExt.has_value())
17584 return OrigOperand;
17586 MVT NarrowVT = getNarrowType(Root, *SupportsExt);
17590 if (
Source.getValueType() == NarrowVT)
17593 unsigned ExtOpc = getExtOpc(*SupportsExt);
17596 SDLoc
DL(OrigOperand);
17597 auto [
Mask, VL] = getMaskAndVL(Root, DAG, Subtarget);
17601 case RISCVISD::VSEXT_VL:
17602 case RISCVISD::VZEXT_VL:
17603 case RISCVISD::FP_EXTEND_VL:
17604 return DAG.
getNode(ExtOpc,
DL, NarrowVT, Source, Mask, VL);
17607 case RISCVISD::VMV_V_X_VL:
17608 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, NarrowVT,
17610 case RISCVISD::VFMV_V_F_VL:
17615 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL, NarrowVT,
17616 DAG.
getUNDEF(NarrowVT), Source, VL);
17629 static MVT getNarrowType(
const SDNode *Root, ExtKind SupportsExt) {
17635 MVT EltVT = SupportsExt == ExtKind::BF16Ext ? MVT::bf16
17636 : SupportsExt == ExtKind::FPExt
17638 : MVT::getIntegerVT(NarrowSize);
17640 assert((
int)NarrowSize >= (SupportsExt == ExtKind::FPExt ? 16 : 8) &&
17641 "Trying to extend something we can't represent");
17648 static unsigned getSExtOpcode(
unsigned Opcode) {
17651 case RISCVISD::ADD_VL:
17652 case RISCVISD::VWADD_W_VL:
17653 case RISCVISD::VWADDU_W_VL:
17655 case RISCVISD::OR_VL:
17656 return RISCVISD::VWADD_VL;
17658 case RISCVISD::SUB_VL:
17659 case RISCVISD::VWSUB_W_VL:
17660 case RISCVISD::VWSUBU_W_VL:
17661 return RISCVISD::VWSUB_VL;
17663 case RISCVISD::MUL_VL:
17664 return RISCVISD::VWMUL_VL;
17672 static unsigned getZExtOpcode(
unsigned Opcode) {
17675 case RISCVISD::ADD_VL:
17676 case RISCVISD::VWADD_W_VL:
17677 case RISCVISD::VWADDU_W_VL:
17679 case RISCVISD::OR_VL:
17680 return RISCVISD::VWADDU_VL;
17682 case RISCVISD::SUB_VL:
17683 case RISCVISD::VWSUB_W_VL:
17684 case RISCVISD::VWSUBU_W_VL:
17685 return RISCVISD::VWSUBU_VL;
17687 case RISCVISD::MUL_VL:
17688 return RISCVISD::VWMULU_VL;
17690 case RISCVISD::SHL_VL:
17691 return RISCVISD::VWSLL_VL;
17699 static unsigned getFPExtOpcode(
unsigned Opcode) {
17701 case RISCVISD::FADD_VL:
17702 case RISCVISD::VFWADD_W_VL:
17703 return RISCVISD::VFWADD_VL;
17704 case RISCVISD::FSUB_VL:
17705 case RISCVISD::VFWSUB_W_VL:
17706 return RISCVISD::VFWSUB_VL;
17707 case RISCVISD::FMUL_VL:
17708 return RISCVISD::VFWMUL_VL;
17709 case RISCVISD::VFMADD_VL:
17710 return RISCVISD::VFWMADD_VL;
17711 case RISCVISD::VFMSUB_VL:
17712 return RISCVISD::VFWMSUB_VL;
17713 case RISCVISD::VFNMADD_VL:
17714 return RISCVISD::VFWNMADD_VL;
17715 case RISCVISD::VFNMSUB_VL:
17716 return RISCVISD::VFWNMSUB_VL;
17724 static unsigned getSUOpcode(
unsigned Opcode) {
17726 "SU is only supported for MUL");
17727 return RISCVISD::VWMULSU_VL;
17732 static unsigned getWOpcode(
unsigned Opcode, ExtKind SupportsExt) {
17735 case RISCVISD::ADD_VL:
17737 case RISCVISD::OR_VL:
17738 return SupportsExt == ExtKind::SExt ? RISCVISD::VWADD_W_VL
17739 : RISCVISD::VWADDU_W_VL;
17741 case RISCVISD::SUB_VL:
17742 return SupportsExt == ExtKind::SExt ? RISCVISD::VWSUB_W_VL
17743 : RISCVISD::VWSUBU_W_VL;
17744 case RISCVISD::FADD_VL:
17745 return RISCVISD::VFWADD_W_VL;
17746 case RISCVISD::FSUB_VL:
17747 return RISCVISD::VFWSUB_W_VL;
17753 using CombineToTry = std::function<std::optional<CombineResult>(
17754 SDNode * ,
const NodeExtensionHelper & ,
17755 const NodeExtensionHelper & , SelectionDAG &,
17756 const RISCVSubtarget &)>;
17759 bool needToPromoteOtherUsers()
const {
return EnforceOneUse; }
17761 void fillUpExtensionSupportForSplat(SDNode *Root, SelectionDAG &DAG,
17762 const RISCVSubtarget &Subtarget) {
17767 "Unexpected Opcode");
17780 unsigned ScalarBits =
Op.getValueSizeInBits();
17782 if (ScalarBits < EltBits) {
17784 assert(
Opc == RISCVISD::VMV_V_X_VL && EltBits == 64 && ScalarBits == 32 &&
17785 !Subtarget.
is64Bit() &&
"Unexpected splat");
17787 SupportsSExt =
true;
17791 SupportsZExt =
true;
17793 EnforceOneUse =
false;
17797 unsigned NarrowSize = EltBits / 2;
17800 if (NarrowSize < 8)
17804 SupportsSExt =
true;
17808 SupportsZExt =
true;
17810 EnforceOneUse =
false;
17813 bool isSupportedFPExtend(MVT NarrowEltVT,
const RISCVSubtarget &Subtarget) {
17814 return (NarrowEltVT == MVT::f32 ||
17818 bool isSupportedBF16Extend(MVT NarrowEltVT,
const RISCVSubtarget &Subtarget) {
17819 return NarrowEltVT == MVT::bf16 && Subtarget.hasStdExtZvfbfwma();
17824 void fillUpExtensionSupport(SDNode *Root, SelectionDAG &DAG,
17825 const RISCVSubtarget &Subtarget) {
17826 SupportsZExt =
false;
17827 SupportsSExt =
false;
17828 SupportsFPExt =
false;
17829 SupportsBF16Ext =
false;
17830 EnforceOneUse =
true;
17852 case RISCVISD::VZEXT_VL:
17853 SupportsZExt =
true;
17855 case RISCVISD::VSEXT_VL:
17856 SupportsSExt =
true;
17858 case RISCVISD::FP_EXTEND_VL: {
17861 if (isSupportedFPExtend(NarrowEltVT, Subtarget))
17862 SupportsFPExt =
true;
17863 if (isSupportedBF16Extend(NarrowEltVT, Subtarget))
17864 SupportsBF16Ext =
true;
17869 case RISCVISD::VMV_V_X_VL:
17870 fillUpExtensionSupportForSplat(Root, DAG, Subtarget);
17872 case RISCVISD::VFMV_V_F_VL: {
17883 unsigned ScalarBits =
Op.getOperand(0).getValueSizeInBits();
17884 if (NarrowSize != ScalarBits)
17887 if (isSupportedFPExtend(
Op.getOperand(0).getSimpleValueType(), Subtarget))
17888 SupportsFPExt =
true;
17889 if (isSupportedBF16Extend(
Op.getOperand(0).getSimpleValueType(),
17891 SupportsBF16Ext =
true;
17900 static bool isSupportedRoot(
const SDNode *Root,
17901 const RISCVSubtarget &Subtarget) {
17913 case RISCVISD::ADD_VL:
17914 case RISCVISD::MUL_VL:
17915 case RISCVISD::VWADD_W_VL:
17916 case RISCVISD::VWADDU_W_VL:
17917 case RISCVISD::SUB_VL:
17918 case RISCVISD::VWSUB_W_VL:
17919 case RISCVISD::VWSUBU_W_VL:
17921 case RISCVISD::FADD_VL:
17922 case RISCVISD::FSUB_VL:
17923 case RISCVISD::FMUL_VL:
17924 case RISCVISD::VFWADD_W_VL:
17925 case RISCVISD::VFWSUB_W_VL:
17927 case RISCVISD::OR_VL:
17931 Subtarget.hasStdExtZvbb();
17932 case RISCVISD::SHL_VL:
17933 return Subtarget.hasStdExtZvbb();
17934 case RISCVISD::VFMADD_VL:
17935 case RISCVISD::VFNMSUB_VL:
17936 case RISCVISD::VFNMADD_VL:
17937 case RISCVISD::VFMSUB_VL:
17945 NodeExtensionHelper(SDNode *Root,
unsigned OperandIdx, SelectionDAG &DAG,
17946 const RISCVSubtarget &Subtarget) {
17947 assert(isSupportedRoot(Root, Subtarget) &&
17948 "Trying to build an helper with an "
17949 "unsupported root");
17950 assert(OperandIdx < 2 &&
"Requesting something else than LHS or RHS");
17960 case RISCVISD::VWADD_W_VL:
17961 case RISCVISD::VWADDU_W_VL:
17962 case RISCVISD::VWSUB_W_VL:
17963 case RISCVISD::VWSUBU_W_VL:
17964 case RISCVISD::VFWADD_W_VL:
17965 case RISCVISD::VFWSUB_W_VL:
17967 if (OperandIdx == 1)
17971 fillUpExtensionSupport(Root, DAG, Subtarget);
17977 static std::pair<SDValue, SDValue>
17978 getMaskAndVL(
const SDNode *Root, SelectionDAG &DAG,
17979 const RISCVSubtarget &Subtarget) {
17980 assert(isSupportedRoot(Root, Subtarget) &&
"Unexpected root");
17999 switch (
N->getOpcode()) {
18003 case RISCVISD::ADD_VL:
18004 case RISCVISD::MUL_VL:
18005 case RISCVISD::OR_VL:
18006 case RISCVISD::FADD_VL:
18007 case RISCVISD::FMUL_VL:
18008 case RISCVISD::VFMADD_VL:
18009 case RISCVISD::VFNMSUB_VL:
18010 case RISCVISD::VFNMADD_VL:
18011 case RISCVISD::VFMSUB_VL:
18013 case RISCVISD::VWADD_W_VL:
18014 case RISCVISD::VWADDU_W_VL:
18016 case RISCVISD::SUB_VL:
18017 case RISCVISD::VWSUB_W_VL:
18018 case RISCVISD::VWSUBU_W_VL:
18019 case RISCVISD::VFWADD_W_VL:
18020 case RISCVISD::FSUB_VL:
18021 case RISCVISD::VFWSUB_W_VL:
18023 case RISCVISD::SHL_VL:
18042struct CombineResult {
18044 unsigned TargetOpcode;
18046 std::optional<ExtKind> LHSExt;
18047 std::optional<ExtKind> RHSExt;
18051 NodeExtensionHelper
LHS;
18053 NodeExtensionHelper
RHS;
18055 CombineResult(
unsigned TargetOpcode, SDNode *Root,
18056 const NodeExtensionHelper &
LHS, std::optional<ExtKind> LHSExt,
18057 const NodeExtensionHelper &
RHS, std::optional<ExtKind> RHSExt)
18058 : TargetOpcode(TargetOpcode), LHSExt(LHSExt), RHSExt(RHSExt), Root(Root),
18064 SDValue materialize(SelectionDAG &DAG,
18065 const RISCVSubtarget &Subtarget)
const {
18067 std::tie(Mask, VL) =
18068 NodeExtensionHelper::getMaskAndVL(Root, DAG, Subtarget);
18082 LHS.getOrCreateExtendedOp(Root, DAG, Subtarget, LHSExt),
18083 RHS.getOrCreateExtendedOp(Root, DAG, Subtarget, RHSExt),
18084 Passthru, Mask, VL);
18098static std::optional<CombineResult>
18099canFoldToVWWithSameExtensionImpl(
SDNode *Root,
const NodeExtensionHelper &
LHS,
18100 const NodeExtensionHelper &
RHS,
18103 if ((AllowExtMask & ExtKind::ZExt) &&
LHS.SupportsZExt &&
RHS.SupportsZExt)
18104 return CombineResult(NodeExtensionHelper::getZExtOpcode(Root->
getOpcode()),
18105 Root,
LHS, {ExtKind::ZExt},
RHS,
18107 if ((AllowExtMask & ExtKind::SExt) &&
LHS.SupportsSExt &&
RHS.SupportsSExt)
18108 return CombineResult(NodeExtensionHelper::getSExtOpcode(Root->
getOpcode()),
18109 Root,
LHS, {ExtKind::SExt},
RHS,
18111 if ((AllowExtMask & ExtKind::FPExt) &&
LHS.SupportsFPExt &&
RHS.SupportsFPExt)
18112 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
18113 Root,
LHS, {ExtKind::FPExt},
RHS,
18115 if ((AllowExtMask & ExtKind::BF16Ext) &&
LHS.SupportsBF16Ext &&
18116 RHS.SupportsBF16Ext)
18117 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
18118 Root,
LHS, {ExtKind::BF16Ext},
RHS,
18119 {ExtKind::BF16Ext});
18120 return std::nullopt;
18129static std::optional<CombineResult>
18130canFoldToVWWithSameExtension(
SDNode *Root,
const NodeExtensionHelper &
LHS,
18133 return canFoldToVWWithSameExtensionImpl(
18134 Root,
LHS,
RHS, ExtKind::ZExt | ExtKind::SExt | ExtKind::FPExt, DAG,
18142static std::optional<CombineResult>
18143canFoldToVWWithSameExtZEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
18146 return canFoldToVWWithSameExtensionImpl(Root,
LHS,
RHS, ExtKind::ZExt, DAG,
18154static std::optional<CombineResult>
18155canFoldToVWWithSameExtBF16(
SDNode *Root,
const NodeExtensionHelper &
LHS,
18158 return canFoldToVWWithSameExtensionImpl(Root,
LHS,
RHS, ExtKind::BF16Ext, DAG,
18166static std::optional<CombineResult>
18167canFoldToVW_W(
SDNode *Root,
const NodeExtensionHelper &
LHS,
18170 if (
RHS.SupportsFPExt)
18171 return CombineResult(
18172 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::FPExt),
18173 Root,
LHS, std::nullopt,
RHS, {ExtKind::FPExt});
18180 return CombineResult(
18181 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::ZExt), Root,
18182 LHS, std::nullopt,
RHS, {ExtKind::ZExt});
18184 return CombineResult(
18185 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::SExt), Root,
18186 LHS, std::nullopt,
RHS, {ExtKind::SExt});
18187 return std::nullopt;
18194static std::optional<CombineResult>
18195canFoldToVWWithSEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
18198 if (
LHS.SupportsSExt)
18199 return CombineResult(NodeExtensionHelper::getSExtOpcode(Root->
getOpcode()),
18200 Root,
LHS, {ExtKind::SExt},
RHS,
18202 return std::nullopt;
18209static std::optional<CombineResult>
18210canFoldToVWWithZEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
18213 if (
LHS.SupportsZExt)
18214 return CombineResult(NodeExtensionHelper::getZExtOpcode(Root->
getOpcode()),
18215 Root,
LHS, {ExtKind::ZExt},
RHS,
18217 return std::nullopt;
18224static std::optional<CombineResult>
18225canFoldToVWWithFPEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
18228 if (
LHS.SupportsFPExt)
18229 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
18230 Root,
LHS, {ExtKind::FPExt},
RHS,
18232 return std::nullopt;
18239static std::optional<CombineResult>
18240canFoldToVW_SU(
SDNode *Root,
const NodeExtensionHelper &
LHS,
18244 if (!
LHS.SupportsSExt || !
RHS.SupportsZExt)
18245 return std::nullopt;
18246 return CombineResult(NodeExtensionHelper::getSUOpcode(Root->
getOpcode()),
18247 Root,
LHS, {ExtKind::SExt},
RHS,
18252NodeExtensionHelper::getSupportedFoldings(
const SDNode *Root) {
18258 case RISCVISD::ADD_VL:
18259 case RISCVISD::SUB_VL:
18260 case RISCVISD::OR_VL:
18261 case RISCVISD::FADD_VL:
18262 case RISCVISD::FSUB_VL:
18264 Strategies.
push_back(canFoldToVWWithSameExtension);
18268 case RISCVISD::FMUL_VL:
18269 case RISCVISD::VFMADD_VL:
18270 case RISCVISD::VFMSUB_VL:
18271 case RISCVISD::VFNMADD_VL:
18272 case RISCVISD::VFNMSUB_VL:
18273 Strategies.
push_back(canFoldToVWWithSameExtension);
18274 if (Root->
getOpcode() == RISCVISD::VFMADD_VL)
18275 Strategies.
push_back(canFoldToVWWithSameExtBF16);
18278 case RISCVISD::MUL_VL:
18280 Strategies.
push_back(canFoldToVWWithSameExtension);
18285 case RISCVISD::SHL_VL:
18287 Strategies.
push_back(canFoldToVWWithSameExtZEXT);
18289 case RISCVISD::VWADD_W_VL:
18290 case RISCVISD::VWSUB_W_VL:
18292 Strategies.
push_back(canFoldToVWWithSEXT);
18294 case RISCVISD::VWADDU_W_VL:
18295 case RISCVISD::VWSUBU_W_VL:
18297 Strategies.
push_back(canFoldToVWWithZEXT);
18299 case RISCVISD::VFWADD_W_VL:
18300 case RISCVISD::VFWSUB_W_VL:
18302 Strategies.
push_back(canFoldToVWWithFPEXT);
18313 assert(
N->getOpcode() == RISCVISD::ADD_VL);
18316 SDValue Passthru =
N->getOperand(2);
18350 if (!NodeExtensionHelper::isSupportedRoot(
N, Subtarget))
18357 Inserted.insert(
N);
18360 while (!Worklist.
empty()) {
18363 NodeExtensionHelper
LHS(Root, 0, DAG, Subtarget);
18364 NodeExtensionHelper
RHS(Root, 1, DAG, Subtarget);
18365 auto AppendUsersIfNeeded =
18366 [&Worklist, &Subtarget, &Inserted,
18367 &ExtensionsToRemove](
const NodeExtensionHelper &
Op) {
18368 if (
Op.needToPromoteOtherUsers()) {
18370 ExtensionsToRemove.
insert(
Op.OrigOperand.getNode());
18373 if (!NodeExtensionHelper::isSupportedRoot(TheUser, Subtarget))
18378 if (Inserted.insert(TheUser).second)
18391 NodeExtensionHelper::getSupportedFoldings(Root);
18393 assert(!FoldingStrategies.
empty() &&
"Nothing to be folded");
18394 bool Matched =
false;
18395 for (
int Attempt = 0;
18396 (Attempt != 1 + NodeExtensionHelper::isCommutative(Root)) && !Matched;
18399 for (NodeExtensionHelper::CombineToTry FoldingStrategy :
18400 FoldingStrategies) {
18401 std::optional<CombineResult> Res =
18402 FoldingStrategy(Root,
LHS,
RHS, DAG, Subtarget);
18406 if (!Res->LHSExt.has_value() &&
18407 ExtensionsToRemove.
contains(
LHS.OrigOperand.getNode()))
18409 if (!Res->RHSExt.has_value() &&
18410 ExtensionsToRemove.
contains(
RHS.OrigOperand.getNode()))
18418 if (Res->LHSExt.has_value())
18419 if (!AppendUsersIfNeeded(
LHS))
18421 if (Res->RHSExt.has_value())
18422 if (!AppendUsersIfNeeded(
RHS))
18434 SDValue InputRootReplacement;
18441 for (CombineResult Res : CombinesToApply) {
18442 SDValue NewValue = Res.materialize(DAG, Subtarget);
18443 if (!InputRootReplacement) {
18445 "First element is expected to be the current node");
18446 InputRootReplacement = NewValue;
18451 for (std::pair<SDValue, SDValue> OldNewValues : ValuesToReplace) {
18452 DCI.
CombineTo(OldNewValues.first.getNode(), OldNewValues.second);
18454 return InputRootReplacement;
18461 unsigned Opc =
N->getOpcode();
18462 assert(
Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWADDU_W_VL ||
18463 Opc == RISCVISD::VWSUB_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL);
18466 SDValue MergeOp =
N->getOperand(1);
18467 unsigned MergeOpc = MergeOp.
getOpcode();
18469 if (MergeOpc != RISCVISD::VMERGE_VL && MergeOpc !=
ISD::VSELECT)
18478 SDValue Passthru =
N->getOperand(2);
18484 if (Mask.getOpcode() != RISCVISD::VMSET_VL)
18492 Z = Z.getOperand(1);
18498 {Y, X, Y, MergeOp->getOperand(0), N->getOperand(4)},
18505 [[maybe_unused]]
unsigned Opc =
N->getOpcode();
18506 assert(
Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWADDU_W_VL ||
18507 Opc == RISCVISD::VWSUB_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL);
18534 EVT NewMemVT = (MemVT == MVT::i32) ? MVT::i64 : MVT::i128;
18542 if (MemVT == MVT::i32)
18543 Opcode = (Ext ==
ISD::ZEXTLOAD) ? RISCVISD::TH_LWUD : RISCVISD::TH_LWD;
18545 Opcode = RISCVISD::TH_LDD;
18548 Opcode,
SDLoc(LSNode1), DAG.
getVTList({XLenVT, XLenVT, MVT::Other}),
18549 {LSNode1->getChain(), BasePtr,
18550 DAG.getConstant(Imm, SDLoc(LSNode1), XLenVT)},
18561 unsigned Opcode = (MemVT == MVT::i32) ? RISCVISD::TH_SWD : RISCVISD::TH_SDD;
18565 {LSNode1->getChain(), LSNode1->getOperand(1), LSNode2->getOperand(1),
18566 BasePtr, DAG.getConstant(Imm, SDLoc(LSNode1), XLenVT)},
18583 if (!Subtarget.hasVendorXTHeadMemPair())
18595 auto ExtractBaseAndOffset = [](
SDValue Ptr) -> std::pair<SDValue, uint64_t> {
18598 return {Ptr->
getOperand(0), C1->getZExtValue()};
18602 auto [Base1, Offset1] = ExtractBaseAndOffset(LSNode1->
getOperand(OpNum));
18623 auto [Base2, Offset2] = ExtractBaseAndOffset(LSNode2->
getOperand(OpNum));
18626 if (Base1 != Base2)
18630 bool Valid =
false;
18631 if (MemVT == MVT::i32) {
18635 }
else if (MemVT == MVT::i64) {
18671 if (Src->isStrictFPOpcode())
18679 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
18689 EVT VT =
N->getValueType(0);
18692 MVT SrcVT = Src.getSimpleValueType();
18693 MVT SrcContainerVT = SrcVT;
18721 IsSigned ? RISCVISD::VFCVT_RTZ_X_F_VL : RISCVISD::VFCVT_RTZ_XU_F_VL;
18722 FpToInt = DAG.
getNode(
Opc,
DL, ContainerVT, XVal, Mask, VL);
18725 IsSigned ? RISCVISD::VFCVT_RM_X_F_VL : RISCVISD::VFCVT_RM_XU_F_VL;
18726 FpToInt = DAG.
getNode(
Opc,
DL, ContainerVT, XVal, Mask,
18739 if (VT != MVT::i32 && VT != XLenVT)
18744 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
18746 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
18769 EVT DstVT =
N->getValueType(0);
18770 if (DstVT != XLenVT)
18776 if (Src->isStrictFPOpcode())
18784 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
18796 if (SatVT == DstVT)
18797 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
18798 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
18799 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
18804 Src = Src.getOperand(0);
18812 if (
Opc == RISCVISD::FCVT_WU_RV64)
18825 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected extension");
18831 EVT VT =
N->getValueType(0);
18837 return DAG.
getNode(RISCVISD::BREV8,
DL, VT, Src.getOperand(0));
18850 EVT LoadVT = VPLoad->getValueType(0);
18854 N->getOperand(2) != VPLoad->getVectorLength() ||
18855 !
N->getOperand(0).hasOneUse())
18862 SDValue LoadMask = VPLoad->getMask();
18867 if (LoadMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
18869 LoadMask.
getOperand(2) != VPLoad->getVectorLength())
18877 SDValue NumElem = VPLoad->getVectorLength();
18878 uint64_t ElemWidthByte = VPLoad->getValueType(0).getScalarSizeInBits() / 8;
18890 PtrInfo, VPLoad->getMemOperand()->getFlags(),
18894 LoadVT,
DL, VPLoad->getChain(),
Base, Stride, LoadMask,
18895 VPLoad->getVectorLength(), MMO, VPLoad->isExpandingLoad());
18909 if (VPStore->getValue().getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE)
18912 SDValue VPReverse = VPStore->getValue();
18918 VPStore->getVectorLength() != VPReverse.
getOperand(2) ||
18922 SDValue StoreMask = VPStore->getMask();
18927 if (StoreMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
18929 StoreMask.
getOperand(2) != VPStore->getVectorLength())
18937 SDValue NumElem = VPStore->getVectorLength();
18951 PtrInfo, VPStore->getMemOperand()->getFlags(),
18956 VPStore->getOffset(), Stride, StoreMask, VPStore->getVectorLength(),
18957 VPStore->getMemoryVT(), MMO, VPStore->getAddressingMode(),
18958 VPStore->isTruncatingStore(), VPStore->isCompressingStore());
18970 EVT VT =
N->getValueType(0);
18982 if (In.getOpcode() != ISD::VP_SRL || In.getOperand(2) != Mask ||
18983 In.getOperand(3) != VL)
18992 if (
LHS.getOpcode() != ISD::VP_ADD ||
LHS.getOperand(2) != Mask ||
18993 LHS.getOperand(3) != VL)
19000 if (V.getOpcode() != ISD::VP_ADD || V.getOperand(2) != Mask ||
19001 V.getOperand(3) != VL)
19004 Operands[0] =
Other;
19013 if (!FindAdd(LHS0, LHS1) && !FindAdd(LHS1, LHS0))
19020 if (
I == std::end(Operands))
19027 if (
Op.getOpcode() != ISD::VP_ZERO_EXTEND ||
Op.getOperand(1) != Mask ||
19028 Op.getOperand(2) != VL)
19038 Operands[0].getOperand(0), Mask, VL);
19040 Operands[1].getOperand(0), Mask, VL);
19044 return DAG.
getNode(RISCVISD::AVGCEILU_VL,
DL, VT,
19045 {NewOp0, NewOp1, DAG.
getUNDEF(VT), Mask, VL});
19057 case RISCVISD::VFMADD_VL: Opcode = RISCVISD::VFNMSUB_VL;
break;
19058 case RISCVISD::VFNMSUB_VL: Opcode = RISCVISD::VFMADD_VL;
break;
19059 case RISCVISD::VFNMADD_VL: Opcode = RISCVISD::VFMSUB_VL;
break;
19060 case RISCVISD::VFMSUB_VL: Opcode = RISCVISD::VFNMADD_VL;
break;
19061 case RISCVISD::STRICT_VFMADD_VL: Opcode = RISCVISD::STRICT_VFNMSUB_VL;
break;
19062 case RISCVISD::STRICT_VFNMSUB_VL: Opcode = RISCVISD::STRICT_VFMADD_VL;
break;
19063 case RISCVISD::STRICT_VFNMADD_VL: Opcode = RISCVISD::STRICT_VFMSUB_VL;
break;
19064 case RISCVISD::STRICT_VFMSUB_VL: Opcode = RISCVISD::STRICT_VFNMADD_VL;
break;
19074 case RISCVISD::VFMADD_VL: Opcode = RISCVISD::VFMSUB_VL;
break;
19075 case RISCVISD::VFMSUB_VL: Opcode = RISCVISD::VFMADD_VL;
break;
19076 case RISCVISD::VFNMADD_VL: Opcode = RISCVISD::VFNMSUB_VL;
break;
19077 case RISCVISD::VFNMSUB_VL: Opcode = RISCVISD::VFNMADD_VL;
break;
19078 case RISCVISD::STRICT_VFMADD_VL: Opcode = RISCVISD::STRICT_VFMSUB_VL;
break;
19079 case RISCVISD::STRICT_VFMSUB_VL: Opcode = RISCVISD::STRICT_VFMADD_VL;
break;
19080 case RISCVISD::STRICT_VFNMADD_VL: Opcode = RISCVISD::STRICT_VFNMSUB_VL;
break;
19081 case RISCVISD::STRICT_VFNMSUB_VL: Opcode = RISCVISD::STRICT_VFNMADD_VL;
break;
19094 unsigned Offset = IsStrict ? 1 : 0;
19101 auto invertIfNegative = [&Mask, &VL](
SDValue &V) {
19102 if (V.getOpcode() == RISCVISD::FNEG_VL && V.getOperand(1) == Mask &&
19103 V.getOperand(2) == VL) {
19105 V = V.getOperand(0);
19112 bool NegA = invertIfNegative(
A);
19113 bool NegB = invertIfNegative(
B);
19114 bool NegC = invertIfNegative(
C);
19117 if (!NegA && !NegB && !NegC)
19123 {N->getOperand(0), A, B, C, Mask, VL});
19147 EVT VT =
N->getValueType(0);
19154 uint64_t ShAmt =
N->getConstantOperandVal(1);
19167 if (LShAmt < ExtSize) {
19180 if (ShAmt > 32 || VT != MVT::i64)
19210 U->getConstantOperandVal(1) > 32)
19265 if (!
Cond.hasOneUse())
19284 EVT VT =
Cond.getValueType();
19329 LHS =
LHS.getOperand(0);
19339 LHS.getOperand(0).getValueType() == Subtarget.
getXLenVT()) {
19347 RHS =
LHS.getOperand(1);
19348 LHS =
LHS.getOperand(0);
19357 auto isXorImmediate = [](
const SDValue &
Op) ->
bool {
19359 return isInt<12>(XorCnst->getSExtValue());
19363 auto singleBitOp = [&DAG](
const SDValue &VarOp,
19364 const SDValue &ConstOp) ->
bool {
19367 return (XorCnst->getSExtValue() == 1) &&
19372 auto onlyUsedBySelectOrBR = [](
const SDValue &
Op) ->
bool {
19373 for (
const SDNode *UserNode :
Op->users()) {
19374 const unsigned Opcode = UserNode->getOpcode();
19375 if (Opcode != RISCVISD::SELECT_CC && Opcode != RISCVISD::BR_CC)
19380 auto isFoldableXorEq = [isXorImmediate, singleBitOp, onlyUsedBySelectOrBR](
19383 (!isXorImmediate(
LHS.getOperand(1)) ||
19384 singleBitOp(
LHS.getOperand(0),
LHS.getOperand(1)) ||
19385 onlyUsedBySelectOrBR(
LHS));
19388 if (isFoldableXorEq(
LHS,
RHS)) {
19389 RHS =
LHS.getOperand(1);
19390 LHS =
LHS.getOperand(0);
19416 if (Subtarget.hasVendorXAndesPerf()) {
19426 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
19469 bool Commutative =
true;
19470 unsigned Opc = TrueVal.getOpcode();
19480 Commutative =
false;
19490 if (!TrueVal.hasOneUse())
19494 if (FalseVal == TrueVal.getOperand(0))
19496 else if (Commutative && FalseVal == TrueVal.getOperand(1))
19501 EVT VT =
N->getValueType(0);
19503 SDValue OtherOp = TrueVal.getOperand(1 - OpToFold);
19509 assert(IdentityOperand &&
"No identity operand!");
19514 DAG.
getSelect(
DL, OtherOpVT,
N->getOperand(0), OtherOp, IdentityOperand);
19515 return DAG.
getNode(TrueVal.getOpcode(),
DL, VT, FalseVal, NewSel);
19536 CountZeroes =
N->getOperand(2);
19537 ValOnZero =
N->getOperand(1);
19539 CountZeroes =
N->getOperand(1);
19540 ValOnZero =
N->getOperand(2);
19559 if (
Cond->getOperand(0) != CountZeroesArgument)
19578 CountZeroes, BitWidthMinusOne);
19588 EVT VT =
N->getValueType(0);
19589 EVT CondVT =
Cond.getValueType();
19597 (Subtarget.
hasCZEROLike() || Subtarget.hasVendorXTHeadCondMov())) {
19603 const APInt &MaskVal =
LHS.getConstantOperandAPInt(1);
19614 if (!TrueVal.hasOneUse() || !FalseVal.hasOneUse())
19618 if (TrueVal.getOpcode() ==
ISD::SUB && FalseVal.getOpcode() ==
ISD::ADD) {
19626 SDValue A = FalseVal.getOperand(0);
19627 SDValue B = FalseVal.getOperand(1);
19629 return ((TrueVal.getOperand(0) ==
A && TrueVal.getOperand(1) ==
B) ||
19630 (TrueVal.getOperand(1) ==
A && TrueVal.getOperand(0) ==
B));
19638 EVT VT =
N->getValueType(0);
19640 SDValue TrueVal =
N->getOperand(1);
19641 SDValue FalseVal =
N->getOperand(2);
19671 SDValue TrueVal =
N->getOperand(1);
19672 SDValue FalseVal =
N->getOperand(2);
19687 EVT VT =
N->getValueType(0);
19694 const unsigned Opcode =
N->op_begin()->getNode()->getOpcode();
19709 if (
Op.isUndef()) {
19722 if (
Op.getOpcode() != Opcode || !
Op.hasOneUse())
19731 if (
Op.getOperand(0).getValueType() !=
Op.getOperand(1).getValueType())
19755 EVT AVT =
A.getValueType();
19756 EVT BVT =
B.getValueType();
19786 if (AOpt || BOpt) {
19804 EVT OpVT =
A.getValueType();
19826 EVT OpVT =
A.getOperand(0).getValueType();
19828 OpVT !=
B.getOperand(0).getValueType() ||
19857 if (!Subtarget.hasStdExtZvqdotq())
19861 EVT VT =
N->getValueType(0);
19886 const unsigned InVecOpcode = InVec->
getOpcode();
19903 InVecLHS, InValLHS, EltNo);
19905 InVecRHS, InValRHS, EltNo);
19917 unsigned Elt = IndexC->getZExtValue();
19923 unsigned NewIdx = Elt % ConcatNumElts;
19925 unsigned ConcatOpIdx = Elt / ConcatNumElts;
19930 ConcatOps[ConcatOpIdx] = ConcatOp;
19942 EVT VT =
N->getValueType(0);
19954 !
SDValue(BaseLd, 0).hasOneUse())
19957 EVT BaseLdVT = BaseLd->getValueType(0);
19965 if (!Ld || !Ld->isSimple() || !
Op.hasOneUse() ||
19967 Ld->getValueType(0) != BaseLdVT)
19976 using PtrDiff = std::pair<std::variant<int64_t, SDValue>,
bool>;
19978 LoadSDNode *Ld2) -> std::optional<PtrDiff> {
19983 if (BIO1.equalBaseIndex(BIO2, DAG))
19988 SDValue P2 = Ld2->getBasePtr();
19991 if (P1.getOpcode() ==
ISD::ADD && P1.getOperand(0) == P2)
19992 return {{P1.getOperand(1),
true}};
19994 return std::nullopt;
19998 auto BaseDiff = GetPtrDiff(Lds[0], Lds[1]);
20003 for (
auto *It = Lds.
begin() + 1; It != Lds.
end() - 1; It++)
20004 if (GetPtrDiff(*It, *std::next(It)) != BaseDiff)
20012 unsigned WideScalarBitWidth =
20025 auto [StrideVariant, MustNegateStride] = *BaseDiff;
20027 std::holds_alternative<SDValue>(StrideVariant)
20028 ? std::get<SDValue>(StrideVariant)
20031 if (MustNegateStride)
20040 ConstStride && ConstStride->getSExtValue() >= 0)
20044 ConstStride->getSExtValue() * (
N->getNumOperands() - 1);
20050 BaseLd->getPointerInfo(), BaseLd->getMemOperand()->getFlags(), MemSize,
20054 WideVecVT,
DL, BaseLd->getChain(), BaseLd->getBasePtr(), Stride,
20068 EVT VT =
N->getValueType(0);
20085 for (
int MaskIndex : Mask) {
20086 bool SelectMaskVal = (MaskIndex < (int)NumElts);
20089 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
20126 if (
N->getValueType(0).isFixedLengthVector())
20129 SDValue Addend =
N->getOperand(0);
20132 if (
N->getOpcode() == RISCVISD::ADD_VL) {
20133 SDValue AddPassthruOp =
N->getOperand(2);
20134 if (!AddPassthruOp.
isUndef())
20138 auto IsVWMulOpc = [](
unsigned Opc) {
20140 case RISCVISD::VWMUL_VL:
20141 case RISCVISD::VWMULU_VL:
20142 case RISCVISD::VWMULSU_VL:
20157 if (!MulPassthruOp.
isUndef())
20167 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
20168 }(
N, DAG, Subtarget);
20173 if (AddMask != MulMask || AddVL != MulVL)
20176 const auto &TSInfo =
20178 unsigned Opc = TSInfo.getMAccOpcode(MulOp.
getOpcode());
20181 EVT VT =
N->getValueType(0);
20192 if (!
N->getValueType(0).isVector())
20195 SDValue Addend =
N->getOperand(0);
20198 if (
N->getOpcode() == RISCVISD::ADD_VL) {
20199 SDValue AddPassthruOp =
N->getOperand(2);
20200 if (!AddPassthruOp.
isUndef())
20204 auto IsVqdotqOpc = [](
unsigned Opc) {
20206 case RISCVISD::VQDOT_VL:
20207 case RISCVISD::VQDOTU_VL:
20208 case RISCVISD::VQDOTSU_VL:
20228 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
20229 }(
N, DAG, Subtarget);
20232 if (AddVL != MulVL)
20235 if (AddMask.getOpcode() != RISCVISD::VMSET_VL ||
20236 AddMask.getOperand(0) != MulVL)
20241 EVT VT =
N->getValueType(0);
20242 Addend = DAG.
getNode(RISCVISD::ADD_VL,
DL, VT, Addend, AccumOp,
20243 DAG.
getUNDEF(VT), AddMask, AddVL);
20261 const EVT IndexVT = Index.getValueType();
20265 if (!isIndexTypeSigned(IndexType))
20297 assert(ShuffleMask.empty());
20299 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
20302 if (Index->getOperand(i)->isUndef())
20304 uint64_t C = Index->getConstantOperandVal(i);
20305 if (
C % ElementSize != 0)
20307 C =
C / ElementSize;
20310 ShuffleMask.push_back(
C);
20311 ActiveLanes.
set(
C);
20313 return ActiveLanes.
all();
20331 if (NumElems % 2 != 0)
20335 const unsigned WiderElementSize = ElementSize * 2;
20336 if (WiderElementSize > ST.getELen()/8)
20339 if (!ST.enableUnalignedVectorMem() && BaseAlign < WiderElementSize)
20342 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
20345 if (Index->getOperand(i)->isUndef())
20349 uint64_t C = Index->getConstantOperandVal(i);
20351 if (
C % WiderElementSize != 0)
20356 if (
C !=
Last + ElementSize)
20375 if (!IsVLMAX || Mask.getOpcode() != RISCVISD::VMSET_VL ||
20376 Mask.getOperand(0) != VL)
20379 auto IsTruncNode = [&](
SDValue V) {
20380 return V.getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL &&
20381 V.getOperand(1) == Mask && V.getOperand(2) == VL;
20388 while (IsTruncNode(
Op)) {
20389 if (!
Op.hasOneUse())
20391 Op =
Op.getOperand(0);
20424 assert(
N->getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL);
20426 MVT VT =
N->getSimpleValueType(0);
20431 auto MatchMinMax = [&VL, &Mask](
SDValue V,
unsigned Opc,
unsigned OpcVL,
20433 if (V.getOpcode() !=
Opc &&
20434 !(V.getOpcode() == OpcVL && V.getOperand(2).isUndef() &&
20435 V.getOperand(3) == Mask && V.getOperand(4) == VL))
20443 Op.getOperand(1).getValueType().isFixedLengthVector() &&
20445 Op.getOperand(1).getOperand(0).getValueType() ==
Op.getValueType() &&
20447 Op =
Op.getOperand(1).getOperand(0);
20450 return V.getOperand(0);
20452 if (
Op.getOpcode() == RISCVISD::VMV_V_X_VL &&
Op.getOperand(0).isUndef() &&
20453 Op.getOperand(2) == VL) {
20456 Op1->getAPIntValue().sextOrTrunc(
Op.getScalarValueSizeInBits());
20466 auto DetectUSatPattern = [&](
SDValue V) {
20478 MatchMinMax(SMinOp,
ISD::SMAX, RISCVISD::SMAX_VL, LoC))
20487 MatchMinMax(SMaxOp,
ISD::SMIN, RISCVISD::SMIN_VL, HiC))
20490 return DAG.
getNode(RISCVISD::SMAX_VL,
DL, V.getValueType(), SMinOp,
20491 V.getOperand(1), DAG.
getUNDEF(V.getValueType()),
20497 auto DetectSSatPattern = [&](
SDValue V) {
20499 unsigned NumSrcBits = V.getScalarValueSizeInBits();
20506 MatchMinMax(SMinOp,
ISD::SMAX, RISCVISD::SMAX_VL, LoC))
20507 if (HiC == SignedMax && LoC == SignedMin)
20512 MatchMinMax(SMaxOp,
ISD::SMIN, RISCVISD::SMIN_VL, HiC))
20513 if (HiC == SignedMax && LoC == SignedMin)
20522 while (Src.getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL &&
20523 Src.getOperand(1) == Mask && Src.getOperand(2) == VL &&
20525 Src = Src.getOperand(0);
20529 if ((Val = DetectUSatPattern(Src)))
20530 ClipOpc = RISCVISD::TRUNCATE_VECTOR_VL_USAT;
20531 else if ((Val = DetectSSatPattern(Src)))
20532 ClipOpc = RISCVISD::TRUNCATE_VECTOR_VL_SSAT;
20541 Val = DAG.
getNode(ClipOpc,
DL, ValVT, Val, Mask, VL);
20542 }
while (ValVT != VT);
20560 unsigned Opc =
N->getOpcode();
20562 "Unexpected opcode");
20563 EVT VT =
N->getValueType(0);
20572 Src = Src.getOperand(0);
20576 Src = Src.getOperand(0);
20580 Src = Src.getOperand(0);
20583 EVT SrcEVT = Src.getValueType();
20605 VectorBitsMax, EltSize, MinSize);
20610 MVT ContainerVT = SrcMVT;
20638 if (!
LHS.hasOneUse())
20641 switch (
LHS.getOpcode()) {
20643 case RISCVISD::VSEXT_VL:
20644 Opcode = RISCVISD::VWMULSU_VL;
20647 case RISCVISD::VZEXT_VL:
20648 Opcode = RISCVISD::VWMULU_VL;
20659 else if (
RHS.getOpcode() == RISCVISD::VMV_V_X_VL &&
20661 ShAmtInt =
RHS.getConstantOperandVal(1);
20674 if (ShAmtInt >= NarrowBits)
20676 MVT VT =
N->getSimpleValueType(0);
20683 switch (
N->getOpcode()) {
20688 case RISCVISD::SHL_VL:
20689 Passthru =
N->getOperand(2);
20690 Mask =
N->getOperand(3);
20691 VL =
N->getOperand(4);
20696 return DAG.
getNode(Opcode,
DL, VT, NarrowOp,
20698 Passthru, Mask, VL);
20704 const MVT XLenVT = Subtarget.getXLenVT();
20710 auto SimplifyDemandedLowBitsHelper = [&](
unsigned OpNo,
unsigned LowBits) {
20721 switch (
N->getOpcode()) {
20724 case RISCVISD::SplitF64: {
20728 if (Op0->
getOpcode() == RISCVISD::BuildPairF64)
20741 APInt V =
C->getValueAPF().bitcastToAPInt();
20770 case RISCVISD::SLLW:
20771 case RISCVISD::SRAW:
20772 case RISCVISD::SRLW:
20773 case RISCVISD::RORW:
20774 case RISCVISD::ROLW: {
20776 if (SimplifyDemandedLowBitsHelper(0, 32) ||
20777 SimplifyDemandedLowBitsHelper(1, 5))
20782 case RISCVISD::ABSW:
20783 case RISCVISD::CLZW:
20784 case RISCVISD::CTZW: {
20786 if (SimplifyDemandedLowBitsHelper(0, 32))
20790 case RISCVISD::FMV_W_X_RV64: {
20795 if (Op0.
getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64)
20799 case RISCVISD::FMV_X_ANYEXTH:
20800 case RISCVISD::FMV_X_ANYEXTW_RV64: {
20803 MVT VT =
N->getSimpleValueType(0);
20814 if ((
N->getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64 &&
20815 Op0->
getOpcode() == RISCVISD::FMV_W_X_RV64) ||
20816 (
N->getOpcode() == RISCVISD::FMV_X_ANYEXTH &&
20817 Op0->
getOpcode() == RISCVISD::FMV_H_X)) {
20819 "Unexpected value type!");
20829 LN0->getBasePtr(), IVT, LN0->getMemOperand());
20842 unsigned FPBits =
N->getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64 ? 32 : 16;
20853 EVT VT =
N->getValueType(0);
20902 EVT VT =
N->getValueType(0);
20920 if (!
C || !
C->getValueAPF().isExactlyValue(+1.0))
20950 if (
N->getValueType(0) == MVT::i64 && Subtarget.is64Bit()) {
20955 Src.getOperand(0));
20960 Src.getOperand(0), Src.getOperand(1));
20968 case RISCVISD::TRUNCATE_VECTOR_VL:
20972 case ISD::VP_TRUNCATE:
20980 case RISCVISD::CZERO_EQZ:
20981 case RISCVISD::CZERO_NEZ: {
20985 unsigned Opc =
N->getOpcode();
20988 if (
Opc == RISCVISD::CZERO_EQZ && Val ==
Cond)
20992 Opc == RISCVISD::CZERO_EQZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ;
21000 return DAG.
getNode(InvOpc,
SDLoc(
N),
N->getValueType(0), Val, NewCond);
21010 N->getValueType(0), Val,
Cond.getOperand(0));
21014 case RISCVISD::SELECT_CC: {
21021 SDValue FalseV =
N->getOperand(4);
21023 EVT VT =
N->getValueType(0);
21026 if (TrueV == FalseV)
21057 return DAG.
getNode(RISCVISD::SELECT_CC,
DL,
N->getValueType(0),
21058 {LHS, RHS, CC, TrueV, FalseV});
21060 if (!Subtarget.hasConditionalMoveFusion()) {
21117 case RISCVISD::BR_CC: {
21124 return DAG.
getNode(RISCVISD::BR_CC,
DL,
N->getValueType(0),
21125 N->getOperand(0), LHS, RHS, CC,
N->getOperand(4));
21138 EVT VT =
N->getValueType(0);
21163 const EVT VT =
N->getValueType(0);
21164 SDValue Index = MGN->getIndex();
21165 SDValue ScaleOp = MGN->getScale();
21167 assert(!MGN->isIndexScaled() &&
21168 "Scaled gather/scatter should not be formed");
21173 N->getVTList(), MGN->getMemoryVT(),
DL,
21174 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
21175 MGN->getBasePtr(), Index, ScaleOp},
21176 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
21180 N->getVTList(), MGN->getMemoryVT(),
DL,
21181 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
21182 MGN->getBasePtr(), Index, ScaleOp},
21183 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
21189 if (std::optional<VIDSequence> SimpleVID =
21191 SimpleVID && SimpleVID->StepDenominator == 1) {
21192 const int64_t StepNumerator = SimpleVID->StepNumerator;
21193 const int64_t Addend = SimpleVID->Addend;
21200 assert(MGN->getBasePtr()->getValueType(0) == PtrVT);
21208 VT,
DL, MGN->getChain(), BasePtr,
21210 EVL, MGN->getMemOperand());
21212 MGN->getPassThru());
21222 MGN->getBasePtr(), DAG.
getUNDEF(XLenVT),
21224 MGN->getMemoryVT(), MGN->getMemOperand(),
21233 MGN->getMemOperand()->getBaseAlign(), Subtarget)) {
21235 for (
unsigned i = 0; i < Index->getNumOperands(); i += 2)
21236 NewIndices.
push_back(Index.getOperand(i));
21237 EVT IndexVT = Index.getValueType()
21244 assert(EltCnt.isKnownEven() &&
"Splitting vector, but not in half!");
21246 EltCnt.divideCoefficientBy(2));
21249 EltCnt.divideCoefficientBy(2));
21254 {MGN->getChain(), Passthru, Mask, MGN->getBasePtr(),
21264 SDValue Index = MSN->getIndex();
21265 SDValue ScaleOp = MSN->getScale();
21267 assert(!MSN->isIndexScaled() &&
21268 "Scaled gather/scatter should not be formed");
21273 N->getVTList(), MSN->getMemoryVT(),
DL,
21274 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
21276 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
21280 N->getVTList(), MSN->getMemoryVT(),
DL,
21281 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
21283 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
21285 EVT VT = MSN->getValue()->getValueType(0);
21287 if (!MSN->isTruncatingStore() &&
21291 return DAG.
getMaskedStore(MSN->getChain(),
DL, Shuffle, MSN->getBasePtr(),
21292 DAG.
getUNDEF(XLenVT), MSN->getMask(),
21293 MSN->getMemoryVT(), MSN->getMemOperand(),
21298 case ISD::VP_GATHER: {
21300 SDValue Index = VPGN->getIndex();
21301 SDValue ScaleOp = VPGN->getScale();
21303 assert(!VPGN->isIndexScaled() &&
21304 "Scaled gather/scatter should not be formed");
21309 {VPGN->getChain(), VPGN->getBasePtr(), Index,
21310 ScaleOp, VPGN->getMask(),
21311 VPGN->getVectorLength()},
21312 VPGN->getMemOperand(), IndexType);
21316 {VPGN->getChain(), VPGN->getBasePtr(), Index,
21317 ScaleOp, VPGN->getMask(),
21318 VPGN->getVectorLength()},
21319 VPGN->getMemOperand(), IndexType);
21323 case ISD::VP_SCATTER: {
21325 SDValue Index = VPSN->getIndex();
21326 SDValue ScaleOp = VPSN->getScale();
21328 assert(!VPSN->isIndexScaled() &&
21329 "Scaled gather/scatter should not be formed");
21334 {VPSN->getChain(), VPSN->getValue(),
21335 VPSN->getBasePtr(), Index, ScaleOp,
21336 VPSN->getMask(), VPSN->getVectorLength()},
21337 VPSN->getMemOperand(), IndexType);
21341 {VPSN->getChain(), VPSN->getValue(),
21342 VPSN->getBasePtr(), Index, ScaleOp,
21343 VPSN->getMask(), VPSN->getVectorLength()},
21344 VPSN->getMemOperand(), IndexType);
21347 case RISCVISD::SHL_VL:
21351 case RISCVISD::SRA_VL:
21352 case RISCVISD::SRL_VL: {
21354 if (ShAmt.
getOpcode() == RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL) {
21358 EVT VT =
N->getValueType(0);
21361 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt,
21362 N->getOperand(2),
N->getOperand(3),
N->getOperand(4));
21377 if (ShAmt.
getOpcode() == RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL) {
21380 EVT VT =
N->getValueType(0);
21383 DAG.
getRegister(RISCV::X0, Subtarget.getXLenVT()));
21384 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt);
21388 case RISCVISD::ADD_VL:
21396 case RISCVISD::VWADD_W_VL:
21397 case RISCVISD::VWADDU_W_VL:
21398 case RISCVISD::VWSUB_W_VL:
21399 case RISCVISD::VWSUBU_W_VL:
21401 case RISCVISD::OR_VL:
21402 case RISCVISD::SUB_VL:
21403 case RISCVISD::MUL_VL:
21405 case RISCVISD::VFMADD_VL:
21406 case RISCVISD::VFNMADD_VL:
21407 case RISCVISD::VFMSUB_VL:
21408 case RISCVISD::VFNMSUB_VL:
21409 case RISCVISD::STRICT_VFMADD_VL:
21410 case RISCVISD::STRICT_VFNMADD_VL:
21411 case RISCVISD::STRICT_VFMSUB_VL:
21412 case RISCVISD::STRICT_VFNMSUB_VL:
21414 case RISCVISD::FADD_VL:
21415 case RISCVISD::FSUB_VL:
21416 case RISCVISD::FMUL_VL:
21417 case RISCVISD::VFWADD_W_VL:
21418 case RISCVISD::VFWSUB_W_VL:
21430 SDValue Chain = Store->getChain();
21431 EVT MemVT = Store->getMemoryVT();
21432 SDValue Val = Store->getValue();
21435 bool IsScalarizable =
21437 Store->isSimple() &&
21467 NewVT, *Store->getMemOperand())) {
21469 return DAG.
getStore(Chain,
DL, NewV, Store->getBasePtr(),
21470 Store->getPointerInfo(), Store->getBaseAlign(),
21471 Store->getMemOperand()->getFlags());
21481 L->hasNUsesOfValue(1, 0) && L->hasNUsesOfValue(1, 1) &&
21483 L->getMemoryVT() == MemVT) {
21486 NewVT, *Store->getMemOperand()) &&
21488 NewVT, *L->getMemOperand())) {
21490 L->getPointerInfo(), L->getBaseAlign(),
21491 L->getMemOperand()->getFlags());
21492 return DAG.
getStore(Chain,
DL, NewL, Store->getBasePtr(),
21493 Store->getPointerInfo(), Store->getBaseAlign(),
21494 Store->getMemOperand()->getFlags());
21501 if ((Val.
getOpcode() == RISCVISD::VMV_X_S ||
21507 MVT VecVT = Src.getSimpleValueType();
21514 Store->getChain(),
DL, Src, Store->getBasePtr(), Store->getOffset(),
21517 Store->getMemOperand(), Store->getAddressingMode(),
21518 Store->isTruncatingStore(),
false);
21525 EVT VT =
N->getValueType(0);
21550 case RISCVISD::VFMV_V_F_VL: {
21551 const MVT VT =
N->getSimpleValueType(0);
21552 SDValue Passthru =
N->getOperand(0);
21553 SDValue Scalar =
N->getOperand(1);
21558 return DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL, VT, Passthru, Scalar, VL);
21561 case RISCVISD::VMV_V_X_VL: {
21562 const MVT VT =
N->getSimpleValueType(0);
21563 SDValue Passthru =
N->getOperand(0);
21564 SDValue Scalar =
N->getOperand(1);
21569 unsigned ScalarSize = Scalar.getValueSizeInBits();
21571 if (ScalarSize > EltWidth && Passthru.
isUndef())
21572 if (SimplifyDemandedLowBitsHelper(1, EltWidth))
21579 (!Const || Const->isZero() ||
21580 !Const->getAPIntValue().sextOrTrunc(EltWidth).isSignedIntN(5)))
21581 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, VT, Passthru, Scalar, VL);
21585 case RISCVISD::VFMV_S_F_VL: {
21590 if (
N->getOperand(0).isUndef() &&
21593 Src.getOperand(0).getValueType().isScalableVector()) {
21594 EVT VT =
N->getValueType(0);
21614 case RISCVISD::VMV_S_X_VL: {
21615 const MVT VT =
N->getSimpleValueType(0);
21616 SDValue Passthru =
N->getOperand(0);
21617 SDValue Scalar =
N->getOperand(1);
21623 unsigned ScalarSize = Scalar.getValueSizeInBits();
21625 if (ScalarSize > EltWidth && SimplifyDemandedLowBitsHelper(1, EltWidth))
21628 if (Scalar.getOpcode() == RISCVISD::VMV_X_S && Passthru.
isUndef() &&
21629 Scalar.getOperand(0).getValueType() ==
N->getValueType(0))
21630 return Scalar.getOperand(0);
21637 DAG.
getNode(
N->getOpcode(),
DL, M1VT, M1Passthru, Scalar, VL);
21646 Const && !Const->isZero() &&
isInt<5>(Const->getSExtValue()) &&
21648 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru, Scalar, VL);
21652 case RISCVISD::VMV_X_S: {
21654 MVT VecVT =
N->getOperand(0).getSimpleValueType();
21656 if (M1VT.
bitsLT(VecVT)) {
21658 return DAG.
getNode(RISCVISD::VMV_X_S,
DL,
N->getSimpleValueType(0), Vec);
21666 unsigned IntNo =
N->getConstantOperandVal(IntOpNo);
21671 case Intrinsic::riscv_vcpop:
21672 case Intrinsic::riscv_vcpop_mask:
21673 case Intrinsic::riscv_vfirst:
21674 case Intrinsic::riscv_vfirst_mask: {
21676 if (IntNo == Intrinsic::riscv_vcpop_mask ||
21677 IntNo == Intrinsic::riscv_vfirst_mask)
21678 VL =
N->getOperand(3);
21683 EVT VT =
N->getValueType(0);
21684 if (IntNo == Intrinsic::riscv_vfirst ||
21685 IntNo == Intrinsic::riscv_vfirst_mask)
21689 case Intrinsic::riscv_vsseg2_mask:
21690 case Intrinsic::riscv_vsseg3_mask:
21691 case Intrinsic::riscv_vsseg4_mask:
21692 case Intrinsic::riscv_vsseg5_mask:
21693 case Intrinsic::riscv_vsseg6_mask:
21694 case Intrinsic::riscv_vsseg7_mask:
21695 case Intrinsic::riscv_vsseg8_mask: {
21697 unsigned NF = Tuple.getValueType().getRISCVVectorTupleNumFields();
21699 if (Subtarget.hasOptimizedSegmentLoadStore(NF) || !Tuple.hasOneUse() ||
21700 Tuple.getOpcode() != RISCVISD::TUPLE_INSERT ||
21701 !Tuple.getOperand(0).isUndef())
21709 "Type mismatch without bitcast?");
21710 unsigned Stride = SEW / 8 * NF;
21711 unsigned Offset = SEW / 8 * Idx;
21738 case ISD::EXPERIMENTAL_VP_REVERSE:
21740 case ISD::VP_STORE:
21743 assert(Subtarget.useRVVForFixedLengthVectors());
21745 EVT VT =
N->getValueType(0);
21756 for (
unsigned i = 0; i < NF; ++i)
21757 Result = DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VT, Result,
Splat,
21763 if ((SrcVT == MVT::v1i1 || SrcVT == MVT::v2i1 || SrcVT == MVT::v4i1) &&
21784 case RISCVISD::VRGATHER_VX_VL: {
21787 EVT VT =
N->getValueType(0);
21790 SDValue Passthru =
N->getOperand(2);
21797 Src = Src.getOperand(1);
21799 switch (Src.getOpcode()) {
21802 case RISCVISD::VMV_V_X_VL:
21803 case RISCVISD::VFMV_V_F_VL:
21811 case RISCVISD::VMV_S_X_VL:
21812 case RISCVISD::VFMV_S_F_VL:
21828 case RISCVISD::TUPLE_EXTRACT: {
21829 EVT VT =
N->getValueType(0);
21831 unsigned Idx =
N->getConstantOperandVal(1);
21836 switch (Tuple.getConstantOperandVal(1)) {
21839 case Intrinsic::riscv_vlseg2_mask:
21840 case Intrinsic::riscv_vlseg3_mask:
21841 case Intrinsic::riscv_vlseg4_mask:
21842 case Intrinsic::riscv_vlseg5_mask:
21843 case Intrinsic::riscv_vlseg6_mask:
21844 case Intrinsic::riscv_vlseg7_mask:
21845 case Intrinsic::riscv_vlseg8_mask:
21846 NF = Tuple.getValueType().getRISCVVectorTupleNumFields();
21850 if (!NF || Subtarget.hasOptimizedSegmentLoadStore(NF))
21855 "Type mismatch without bitcast?");
21856 unsigned Stride = SEW / 8 * NF;
21857 unsigned Offset = SEW / 8 * Idx;
21860 Tuple.getOperand(0),
21882 return Result.getValue(0);
21884 case RISCVISD::TUPLE_INSERT: {
21886 if (
N->getOperand(1).isUndef())
21887 return N->getOperand(0);
21890 case RISCVISD::VMERGE_VL: {
21894 SDValue Passthru =
N->getOperand(3);
21906 return DAG.
getNode(RISCVISD::VMV_V_V_VL,
SDLoc(
N),
N->getSimpleValueType(0),
21907 Passthru, True, VL);
21909 case RISCVISD::VMV_V_V_VL: {
21911 SDValue Passthru =
N->getOperand(0);
21924 MVT VT =
N->getSimpleValueType(0);
21928 case RISCVISD::VSLIDEDOWN_VL:
21929 case RISCVISD::VSLIDEUP_VL:
21930 if (
N->getOperand(1)->isUndef())
21931 return N->getOperand(0);
21933 case RISCVISD::VSLIDE1UP_VL:
21934 case RISCVISD::VFSLIDE1UP_VL: {
21938 MVT VT =
N->getSimpleValueType(0);
21942 if (!
N->getOperand(0).isUndef() ||
21961 return getVSlideup(DAG, Subtarget,
DL, VT, SrcVec,
N->getOperand(1),
21971 EVT XVT,
unsigned KeptBits)
const {
21976 if (XVT != MVT::i32 && XVT != MVT::i64)
21980 if (KeptBits == 32 || KeptBits == 64)
21984 return Subtarget.hasStdExtZbb() &&
21985 ((KeptBits == 8 && XVT == MVT::i64 && !Subtarget.is64Bit()) ||
21993 "Expected shift op");
22017 if (Ty.isScalarInteger() &&
22020 return isUsedByLdSt(N0.
getNode(),
N);
22026 if (C2 && Subtarget.hasShlAdd(C2->getZExtValue()) &&
N->hasOneUse() &&
22027 N->user_begin()->getOpcode() ==
ISD::ADD &&
22028 !isUsedByLdSt(*
N->user_begin(),
nullptr) &&
22033 const APInt &C1Int = C1->getAPIntValue();
22034 APInt ShiftedC1Int = C1Int << C2->getAPIntValue();
22055 ShiftedC1Int, Ty.getSizeInBits(), Subtarget,
22060 if (C1Cost < ShiftedC1Cost)
22083 EVT VT =
Op.getValueType();
22087 unsigned Opcode =
Op.getOpcode();
22095 const APInt &Mask =
C->getAPIntValue();
22104 auto IsLegalMask = [ShrunkMask, ExpandedMask](
const APInt &Mask) ->
bool {
22105 return ShrunkMask.
isSubsetOf(Mask) && Mask.isSubsetOf(ExpandedMask);
22107 auto UseMask = [Mask,
Op, &TLO](
const APInt &NewMask) ->
bool {
22108 if (NewMask == Mask)
22113 Op.getOperand(0), NewC);
22126 APInt NewMask =
APInt(Mask.getBitWidth(), 0xffff);
22127 if (IsLegalMask(NewMask))
22128 return UseMask(NewMask);
22131 if (VT == MVT::i64) {
22133 if (IsLegalMask(NewMask))
22134 return UseMask(NewMask);
22149 APInt NewMask = ShrunkMask;
22150 if (MinSignedBits <= 12)
22152 else if (!
C->isOpaque() && MinSignedBits <= 32 && !ShrunkMask.
isSignedIntN(32))
22158 assert(IsLegalMask(NewMask));
22159 return UseMask(NewMask);
22163 static const uint64_t GREVMasks[] = {
22164 0x5555555555555555ULL, 0x3333333333333333ULL, 0x0F0F0F0F0F0F0F0FULL,
22165 0x00FF00FF00FF00FFULL, 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL};
22167 for (
unsigned Stage = 0; Stage != 6; ++Stage) {
22168 unsigned Shift = 1 << Stage;
22169 if (ShAmt & Shift) {
22171 uint64_t Res = ((x & Mask) << Shift) | ((x >> Shift) & Mask);
22183 const APInt &DemandedElts,
22185 unsigned Depth)
const {
22187 unsigned Opc =
Op.getOpcode();
22192 "Should use MaskedValueIsZero if you don't know whether Op"
22193 " is a target node!");
22198 case RISCVISD::SELECT_CC: {
22209 case RISCVISD::VCPOP_VL: {
22214 case RISCVISD::CZERO_EQZ:
22215 case RISCVISD::CZERO_NEZ:
22221 case RISCVISD::REMUW: {
22231 case RISCVISD::DIVUW: {
22241 case RISCVISD::SLLW: {
22250 case RISCVISD::SRLW: {
22259 case RISCVISD::SRAW: {
22268 case RISCVISD::SHL_ADD: {
22271 unsigned ShAmt =
Op.getConstantOperandVal(1);
22278 case RISCVISD::CTZW: {
22285 case RISCVISD::CLZW: {
22292 case RISCVISD::BREV8:
22293 case RISCVISD::ORC_B: {
22297 bool IsGORC =
Op.getOpcode() == RISCVISD::ORC_B;
22305 case RISCVISD::READ_VLENB: {
22308 const unsigned MinVLenB = Subtarget.getRealMinVLen() / 8;
22309 const unsigned MaxVLenB = Subtarget.getRealMaxVLen() / 8;
22310 assert(MinVLenB > 0 &&
"READ_VLENB without vector extension enabled?");
22313 if (MaxVLenB == MinVLenB)
22317 case RISCVISD::FCLASS: {
22330 case Intrinsic::riscv_vsetvli:
22331 case Intrinsic::riscv_vsetvlimax: {
22332 bool HasAVL = IntNo == Intrinsic::riscv_vsetvli;
22333 unsigned VSEW =
Op.getConstantOperandVal(HasAVL + 1);
22338 uint64_t MaxVL = Subtarget.getRealMaxVLen() / SEW;
22339 MaxVL = (Fractional) ? MaxVL / LMul : MaxVL * LMul;
22343 MaxVL = std::min(MaxVL,
Op.getConstantOperandVal(1));
22345 unsigned KnownZeroFirstBit =
Log2_32(MaxVL) + 1;
22358 unsigned Depth)
const {
22359 switch (
Op.getOpcode()) {
22362 case RISCVISD::SELECT_CC: {
22365 if (Tmp == 1)
return 1;
22368 return std::min(Tmp, Tmp2);
22370 case RISCVISD::CZERO_EQZ:
22371 case RISCVISD::CZERO_NEZ:
22375 case RISCVISD::NEGW_MAX: {
22380 if (Tmp < 33)
return 1;
22383 case RISCVISD::SRAW: {
22390 return std::max(Tmp, 33U);
22392 case RISCVISD::SLLW:
22393 case RISCVISD::SRLW:
22394 case RISCVISD::DIVW:
22395 case RISCVISD::DIVUW:
22396 case RISCVISD::REMUW:
22397 case RISCVISD::ROLW:
22398 case RISCVISD::RORW:
22399 case RISCVISD::ABSW:
22400 case RISCVISD::FCVT_W_RV64:
22401 case RISCVISD::FCVT_WU_RV64:
22402 case RISCVISD::STRICT_FCVT_W_RV64:
22403 case RISCVISD::STRICT_FCVT_WU_RV64:
22406 case RISCVISD::VMV_X_S: {
22412 unsigned XLen = Subtarget.getXLen();
22413 unsigned EltBits =
Op.getOperand(0).getScalarValueSizeInBits();
22414 if (EltBits <= XLen)
22415 return XLen - EltBits + 1;
22419 unsigned IntNo =
Op.getConstantOperandVal(1);
22423 case Intrinsic::riscv_masked_atomicrmw_xchg:
22424 case Intrinsic::riscv_masked_atomicrmw_add:
22425 case Intrinsic::riscv_masked_atomicrmw_sub:
22426 case Intrinsic::riscv_masked_atomicrmw_nand:
22427 case Intrinsic::riscv_masked_atomicrmw_max:
22428 case Intrinsic::riscv_masked_atomicrmw_min:
22429 case Intrinsic::riscv_masked_atomicrmw_umax:
22430 case Intrinsic::riscv_masked_atomicrmw_umin:
22431 case Intrinsic::riscv_masked_cmpxchg:
22438 assert(Subtarget.hasStdExtZalrsc());
22439 return Op.getValueSizeInBits() - 31;
22451 unsigned Depth)
const {
22454 switch (
Op.getOpcode()) {
22455 case RISCVISD::BREV8:
22456 case RISCVISD::ORC_B: {
22458 bool IsGORC =
Op.getOpcode() == RISCVISD::ORC_B;
22466 OriginalDemandedElts, Known2, TLO,
Depth + 1))
22478 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
22486 switch (
Op.getOpcode()) {
22487 case RISCVISD::SLLW:
22488 case RISCVISD::SRAW:
22489 case RISCVISD::SRLW:
22490 case RISCVISD::RORW:
22491 case RISCVISD::ROLW:
22495 case RISCVISD::SELECT_CC:
22497 assert(
Op.getOperand(0).getValueType().isInteger() &&
22498 "RISCVISD::SELECT_CC only compares integers");
22507 assert(Ld &&
"Unexpected null LoadSDNode");
22516 if (!CNode || CNode->isMachineConstantPoolEntry() ||
22517 CNode->getOffset() != 0)
22524 if (Ptr.
getOpcode() == RISCVISD::LLA) {
22525 auto *CNode = GetSupportedConstantPool(Ptr.
getOperand(0));
22526 if (!CNode || CNode->getTargetFlags() != 0)
22529 return CNode->getConstVal();
22533 if (Ptr.
getOpcode() != RISCVISD::ADD_LO ||
22537 auto *CNodeLo = GetSupportedConstantPool(Ptr.
getOperand(1));
22544 if (CNodeLo->getConstVal() != CNodeHi->getConstVal())
22547 return CNodeLo->getConstVal();
22552 assert(
MI.getOpcode() == RISCV::ReadCounterWide &&
"Unexpected instruction");
22584 Register ReadAgainReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
22587 int64_t LoCounter =
MI.getOperand(2).getImm();
22588 int64_t HiCounter =
MI.getOperand(3).getImm();
22598 BuildMI(LoopMBB,
DL,
TII->get(RISCV::CSRRS), ReadAgainReg)
22610 MI.eraseFromParent();
22618 assert(
MI.getOpcode() == RISCV::SplitF64Pseudo &&
"Unexpected instruction");
22625 Register SrcReg =
MI.getOperand(2).getReg();
22630 TII.storeRegToStackSlot(*BB,
MI, SrcReg,
MI.getOperand(2).isKill(), FI, SrcRC,
22645 MI.eraseFromParent();
22652 assert(
MI.getOpcode() == RISCV::BuildPairF64Pseudo &&
22653 "Unexpected instruction");
22658 Register DstReg =
MI.getOperand(0).getReg();
22680 TII.loadRegFromStackSlot(*BB,
MI, DstReg, FI, DstRC,
Register());
22681 MI.eraseFromParent();
22686 unsigned RelOpcode,
unsigned EqOpcode,
22689 Register DstReg =
MI.getOperand(0).getReg();
22690 Register Src1Reg =
MI.getOperand(1).getReg();
22691 Register Src2Reg =
MI.getOperand(2).getReg();
22693 Register SavedFFlags =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22717 MI.eraseFromParent();
22768 F->insert(It, FirstMBB);
22769 F->insert(It, SecondMBB);
22770 F->insert(It, SinkMBB);
22820 First.eraseFromParent();
22860 if (
MI.getOpcode() != RISCV::Select_GPR_Using_CC_GPR &&
22861 MI.getOperand(1).isReg() &&
MI.getOperand(2).isReg() &&
22862 Next != BB->
end() &&
Next->getOpcode() ==
MI.getOpcode() &&
22863 Next->getOperand(5).getReg() ==
MI.getOperand(0).getReg() &&
22864 Next->getOperand(5).isKill())
22869 if (
MI.getOperand(2).isReg())
22870 RHS =
MI.getOperand(2).getReg();
22875 SelectDests.
insert(
MI.getOperand(0).getReg());
22881 SequenceMBBI !=
E; ++SequenceMBBI) {
22882 if (SequenceMBBI->isDebugInstr())
22884 if (RISCVInstrInfo::isSelectPseudo(*SequenceMBBI)) {
22885 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
22886 !SequenceMBBI->getOperand(2).isReg() ||
22887 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
22888 SequenceMBBI->getOperand(3).getImm() != CC ||
22889 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
22890 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
22892 LastSelectPseudo = &*SequenceMBBI;
22894 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
22897 if (SequenceMBBI->hasUnmodeledSideEffects() ||
22898 SequenceMBBI->mayLoadOrStore() ||
22899 SequenceMBBI->usesCustomInsertionHook() ||
22900 TII.isFrameInstr(*SequenceMBBI) ||
22901 SequenceMBBI->isStackAligningInlineAsm())
22904 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
22918 F->insert(
I, IfFalseMBB);
22919 F->insert(
I, TailMBB);
22922 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
22928 TailMBB->
push_back(DebugInstr->removeFromParent());
22932 TailMBB->
splice(TailMBB->
end(), HeadMBB,
22942 if (
MI.getOperand(2).isImm())
22945 .
addImm(
MI.getOperand(2).getImm())
22957 auto SelectMBBI =
MI.getIterator();
22958 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
22960 while (SelectMBBI != SelectEnd) {
22961 auto Next = std::next(SelectMBBI);
22962 if (RISCVInstrInfo::isSelectPseudo(*SelectMBBI)) {
22965 TII.get(RISCV::PHI), SelectMBBI->getOperand(0).getReg())
22966 .
addReg(SelectMBBI->getOperand(4).getReg())
22968 .
addReg(SelectMBBI->getOperand(5).getReg())
22975 F->getProperties().resetNoPHIs();
22983 RISCVVInversePseudosTable::getBaseInfo(MCOpcode, LMul, SEW);
22984 assert(
Inverse &&
"Unexpected LMUL and SEW pair for instruction");
22986 RISCV::lookupMaskedIntrinsicByUnmasked(
Inverse->Pseudo);
22987 assert(
Masked &&
"Could not find masked instruction for LMUL and SEW pair");
22993 unsigned CVTXOpc) {
22999 Register SavedFFLAGS =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
23012 .
add(
MI.getOperand(1))
23013 .
add(
MI.getOperand(2))
23014 .
add(
MI.getOperand(3))
23016 .
add(
MI.getOperand(4))
23017 .
add(
MI.getOperand(5))
23018 .
add(
MI.getOperand(6))
23033 .
add(
MI.getOperand(0))
23034 .
add(
MI.getOperand(1))
23036 .
add(
MI.getOperand(3))
23038 .
add(
MI.getOperand(4))
23039 .
add(
MI.getOperand(5))
23040 .
add(
MI.getOperand(6))
23050 MI.eraseFromParent();
23056 unsigned CmpOpc, F2IOpc, I2FOpc, FSGNJOpc, FSGNJXOpc;
23058 switch (
MI.getOpcode()) {
23061 case RISCV::PseudoFROUND_H:
23062 CmpOpc = RISCV::FLT_H;
23063 F2IOpc = RISCV::FCVT_W_H;
23064 I2FOpc = RISCV::FCVT_H_W;
23065 FSGNJOpc = RISCV::FSGNJ_H;
23066 FSGNJXOpc = RISCV::FSGNJX_H;
23067 RC = &RISCV::FPR16RegClass;
23069 case RISCV::PseudoFROUND_H_INX:
23070 CmpOpc = RISCV::FLT_H_INX;
23071 F2IOpc = RISCV::FCVT_W_H_INX;
23072 I2FOpc = RISCV::FCVT_H_W_INX;
23073 FSGNJOpc = RISCV::FSGNJ_H_INX;
23074 FSGNJXOpc = RISCV::FSGNJX_H_INX;
23075 RC = &RISCV::GPRF16RegClass;
23077 case RISCV::PseudoFROUND_S:
23078 CmpOpc = RISCV::FLT_S;
23079 F2IOpc = RISCV::FCVT_W_S;
23080 I2FOpc = RISCV::FCVT_S_W;
23081 FSGNJOpc = RISCV::FSGNJ_S;
23082 FSGNJXOpc = RISCV::FSGNJX_S;
23083 RC = &RISCV::FPR32RegClass;
23085 case RISCV::PseudoFROUND_S_INX:
23086 CmpOpc = RISCV::FLT_S_INX;
23087 F2IOpc = RISCV::FCVT_W_S_INX;
23088 I2FOpc = RISCV::FCVT_S_W_INX;
23089 FSGNJOpc = RISCV::FSGNJ_S_INX;
23090 FSGNJXOpc = RISCV::FSGNJX_S_INX;
23091 RC = &RISCV::GPRF32RegClass;
23093 case RISCV::PseudoFROUND_D:
23095 CmpOpc = RISCV::FLT_D;
23096 F2IOpc = RISCV::FCVT_L_D;
23097 I2FOpc = RISCV::FCVT_D_L;
23098 FSGNJOpc = RISCV::FSGNJ_D;
23099 FSGNJXOpc = RISCV::FSGNJX_D;
23100 RC = &RISCV::FPR64RegClass;
23102 case RISCV::PseudoFROUND_D_INX:
23104 CmpOpc = RISCV::FLT_D_INX;
23105 F2IOpc = RISCV::FCVT_L_D_INX;
23106 I2FOpc = RISCV::FCVT_D_L_INX;
23107 FSGNJOpc = RISCV::FSGNJ_D_INX;
23108 FSGNJXOpc = RISCV::FSGNJX_D_INX;
23109 RC = &RISCV::GPRRegClass;
23121 F->insert(
I, CvtMBB);
23122 F->insert(
I, DoneMBB);
23130 MBB->addSuccessor(CvtMBB);
23131 MBB->addSuccessor(DoneMBB);
23133 Register DstReg =
MI.getOperand(0).getReg();
23134 Register SrcReg =
MI.getOperand(1).getReg();
23135 Register MaxReg =
MI.getOperand(2).getReg();
23136 int64_t FRM =
MI.getOperand(3).getImm();
23141 Register FabsReg =
MRI.createVirtualRegister(RC);
23145 Register CmpReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
23160 Register F2IReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
23182 MI.eraseFromParent();
23189 switch (
MI.getOpcode()) {
23192 case RISCV::ReadCounterWide:
23193 assert(!Subtarget.is64Bit() &&
23194 "ReadCounterWide is only to be used on riscv32");
23196 case RISCV::Select_GPR_Using_CC_GPR:
23197 case RISCV::Select_GPR_Using_CC_Imm5_Zibi:
23198 case RISCV::Select_GPR_Using_CC_SImm5_CV:
23199 case RISCV::Select_GPRNoX0_Using_CC_SImm5NonZero_QC:
23200 case RISCV::Select_GPRNoX0_Using_CC_UImm5NonZero_QC:
23201 case RISCV::Select_GPRNoX0_Using_CC_SImm16NonZero_QC:
23202 case RISCV::Select_GPRNoX0_Using_CC_UImm16NonZero_QC:
23203 case RISCV::Select_GPR_Using_CC_UImmLog2XLen_NDS:
23204 case RISCV::Select_GPR_Using_CC_UImm7_NDS:
23205 case RISCV::Select_FPR16_Using_CC_GPR:
23206 case RISCV::Select_FPR16INX_Using_CC_GPR:
23207 case RISCV::Select_FPR32_Using_CC_GPR:
23208 case RISCV::Select_FPR32INX_Using_CC_GPR:
23209 case RISCV::Select_FPR64_Using_CC_GPR:
23210 case RISCV::Select_FPR64INX_Using_CC_GPR:
23211 case RISCV::Select_FPR64IN32X_Using_CC_GPR:
23213 case RISCV::BuildPairF64Pseudo:
23215 case RISCV::SplitF64Pseudo:
23217 case RISCV::PseudoQuietFLE_H:
23219 case RISCV::PseudoQuietFLE_H_INX:
23220 return emitQuietFCMP(
MI, BB, RISCV::FLE_H_INX, RISCV::FEQ_H_INX, Subtarget);
23221 case RISCV::PseudoQuietFLT_H:
23223 case RISCV::PseudoQuietFLT_H_INX:
23224 return emitQuietFCMP(
MI, BB, RISCV::FLT_H_INX, RISCV::FEQ_H_INX, Subtarget);
23225 case RISCV::PseudoQuietFLE_S:
23227 case RISCV::PseudoQuietFLE_S_INX:
23228 return emitQuietFCMP(
MI, BB, RISCV::FLE_S_INX, RISCV::FEQ_S_INX, Subtarget);
23229 case RISCV::PseudoQuietFLT_S:
23231 case RISCV::PseudoQuietFLT_S_INX:
23232 return emitQuietFCMP(
MI, BB, RISCV::FLT_S_INX, RISCV::FEQ_S_INX, Subtarget);
23233 case RISCV::PseudoQuietFLE_D:
23235 case RISCV::PseudoQuietFLE_D_INX:
23236 return emitQuietFCMP(
MI, BB, RISCV::FLE_D_INX, RISCV::FEQ_D_INX, Subtarget);
23237 case RISCV::PseudoQuietFLE_D_IN32X:
23240 case RISCV::PseudoQuietFLT_D:
23242 case RISCV::PseudoQuietFLT_D_INX:
23243 return emitQuietFCMP(
MI, BB, RISCV::FLT_D_INX, RISCV::FEQ_D_INX, Subtarget);
23244 case RISCV::PseudoQuietFLT_D_IN32X:
23248 case RISCV::PseudoVFROUND_NOEXCEPT_V_M1_MASK:
23250 case RISCV::PseudoVFROUND_NOEXCEPT_V_M2_MASK:
23252 case RISCV::PseudoVFROUND_NOEXCEPT_V_M4_MASK:
23254 case RISCV::PseudoVFROUND_NOEXCEPT_V_M8_MASK:
23256 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF2_MASK:
23258 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF4_MASK:
23260 case RISCV::PseudoFROUND_H:
23261 case RISCV::PseudoFROUND_H_INX:
23262 case RISCV::PseudoFROUND_S:
23263 case RISCV::PseudoFROUND_S_INX:
23264 case RISCV::PseudoFROUND_D:
23265 case RISCV::PseudoFROUND_D_INX:
23266 case RISCV::PseudoFROUND_D_IN32X:
23268 case RISCV::PROBED_STACKALLOC_DYN:
23270 case TargetOpcode::STATEPOINT:
23276 MI.addOperand(*
MI.getMF(),
23282 case TargetOpcode::STACKMAP:
23283 case TargetOpcode::PATCHPOINT:
23284 if (!Subtarget.is64Bit())
23286 "supported on 64-bit targets");
23296 if (
auto *FRMDef =
MI.findRegisterDefOperand(RISCV::FRM,
nullptr)) {
23297 FRMDef->setIsDead(
false);
23301 int Idx = RISCV::getNamedOperandIdx(
MI.getOpcode(), RISCV::OpName::frm);
23311 if (
MI.readsRegister(RISCV::FRM,
nullptr))
23317void RISCVTargetLowering::analyzeInputArgs(
23321 for (
const auto &[Idx, In] :
enumerate(Ins)) {
23327 LLVM_DEBUG(
dbgs() <<
"InputArg #" << Idx <<
" has unhandled type "
23334void RISCVTargetLowering::analyzeOutputArgs(
23338 for (
const auto &[Idx, Out] :
enumerate(Outs)) {
23339 MVT ArgVT = Out.VT;
23340 ISD::ArgFlagsTy ArgFlags = Out.Flags;
23344 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << Idx <<
" has unhandled type "
23361 return DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, Val);
23395 if (In.isOrigArg()) {
23400 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
23401 (
BitWidth < 32 && In.Flags.isZExt())) {
23422 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, LocVT, Val);
23423 if (LocVT == MVT::i64 && VA.
getValVT() == MVT::f32)
23424 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Val);
23472 ExtType,
DL, LocVT, Chain, FIN,
23489 Register LoVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
23502 Register HiVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
23506 return DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64,
Lo,
Hi);
23517 switch (CallConv) {
23526#define CC_VLS_CASE(ABI_VLEN) case CallingConv::RISCV_VLSCall_##ABI_VLEN:
23542 if (Subtarget.hasStdExtE())
23544 if (!Subtarget.hasStdExtFOrZfinx() || !Subtarget.hasStdExtDOrZdinx())
23546 "(Zdinx/D) instruction set extensions");
23550 if (Func.hasFnAttribute(
"interrupt")) {
23551 if (!Func.arg_empty())
23553 "Functions with the interrupt attribute cannot have arguments!");
23564 "SiFive-CLIC-preemptible",
23565 "SiFive-CLIC-stack-swap",
23566 "SiFive-CLIC-preemptible-stack-swap",
23570 "Function interrupt attribute argument not supported!");
23572 if (Kind.starts_with(
"qci-") && !Subtarget.hasVendorXqciint())
23574 "'qci-*' interrupt kinds require Xqciint extension");
23576 if (Kind.starts_with(
"SiFive-CLIC-") && !Subtarget.hasVendorXSfmclic())
23578 "'SiFive-CLIC-*' interrupt kinds require XSfmclic extension");
23580 if (Kind ==
"rnmi" && !Subtarget.hasStdExtSmrnmi())
23583 if (Kind.starts_with(
"SiFive-CLIC-preemptible") && TFI->
hasFP(MF))
23585 "have a frame pointer");
23589 MVT XLenVT = Subtarget.getXLenVT();
23590 unsigned XLenInBytes = Subtarget.getXLen() / 8;
23592 std::vector<SDValue> OutChains;
23601 analyzeInputArgs(MF, CCInfo, Ins,
false,
23605 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
23626 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
23627 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
23629 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
23631 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
23660 int VarArgsSaveSize = XLenInBytes * (ArgRegs.
size() - Idx);
23665 if (VarArgsSaveSize == 0) {
23669 int VaArgOffset = -VarArgsSaveSize;
23677 XLenInBytes, VaArgOffset -
static_cast<int>(XLenInBytes),
true);
23678 VarArgsSaveSize += XLenInBytes;
23685 for (
unsigned I = Idx;
I < ArgRegs.
size(); ++
I) {
23686 const Register Reg = RegInfo.createVirtualRegister(RC);
23687 RegInfo.addLiveIn(ArgRegs[
I], Reg);
23690 Chain,
DL, ArgValue, FIN,
23692 OutChains.push_back(Store);
23706 if (!OutChains.empty()) {
23707 OutChains.push_back(Chain);
23717bool RISCVTargetLowering::isEligibleForTailCallOptimization(
23721 auto CalleeCC = CLI.CallConv;
23722 auto &Outs = CLI.Outs;
23724 auto CallerCC = Caller.getCallingConv();
23731 if (Caller.hasFnAttribute(
"interrupt"))
23746 for (
auto &VA : ArgLocs)
23752 auto IsCallerStructRet = Caller.hasStructRetAttr();
23753 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
23754 if (IsCallerStructRet || IsCalleeStructRet)
23759 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
23760 if (CalleeCC != CallerCC) {
23761 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
23762 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
23769 for (
auto &Arg : Outs)
23770 if (Arg.Flags.isByVal())
23796 MVT XLenVT = Subtarget.getXLenVT();
23811 if (Subtarget.hasStdExtE())
23815 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
23821 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
23827 "call site marked musttail");
23834 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
23836 if (!Flags.isByVal())
23840 unsigned Size = Flags.getByValSize();
23841 Align Alignment = Flags.getNonZeroByValAlign();
23848 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
23850 false,
nullptr, IsTailCall,
23862 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
23865 SDValue ArgValue = OutVals[OutIdx];
23873 RISCVISD::SplitF64,
DL, DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
23885 if (!StackPtr.getNode())
23897 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
23915 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
23916 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
23922 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
23923 SDValue PartValue = OutVals[OutIdx + 1];
23924 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
23938 DAG.
getStore(Chain,
DL, ArgValue, SpillSlot,
23940 for (
const auto &Part : Parts) {
23941 SDValue PartValue = Part.first;
23942 SDValue PartOffset = Part.second;
23949 ArgValue = SpillSlot;
23955 if (Flags.isByVal())
23956 ArgValue = ByValArgs[j++];
23963 if (
Options.EmitCallSiteInfo)
23967 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
23968 "for passing parameters");
23971 if (!StackPtr.getNode())
23985 if (!MemOpChains.
empty())
23991 for (
auto &Reg : RegsToPass) {
23992 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
23999 validateCCReservedRegs(RegsToPass, MF);
24003 "Return address register required, but has been reserved."});
24008 bool CalleeIsLargeExternalSymbol =
false;
24014 CalleeIsLargeExternalSymbol =
true;
24025 Ops.push_back(Chain);
24026 Ops.push_back(Callee);
24030 for (
auto &Reg : RegsToPass)
24031 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
24035 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
24036 assert(Mask &&
"Missing call preserved mask for calling convention");
24041 Ops.push_back(Glue);
24044 "Unexpected CFI type for a direct call");
24052 bool NeedSWGuarded =
false;
24054 Subtarget.hasStdExtZicfilp() &&
24056 NeedSWGuarded =
true;
24061 NeedSWGuarded ? RISCVISD::SW_GUARDED_TAIL : RISCVISD::TAIL;
24070 unsigned CallOpc = NeedSWGuarded ? RISCVISD::SW_GUARDED_CALL : RISCVISD::CALL;
24086 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_RISCV);
24089 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
24090 auto &VA = RVLocs[i];
24098 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
24099 assert(VA.needsCustom());
24104 RetValue = DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64, RetValue,
24118 const Type *RetTy)
const {
24120 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
24122 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
24123 MVT VT = Outs[i].VT;
24126 true, Outs[i].OrigTy))
24157 for (
unsigned i = 0, e = RVLocs.
size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
24158 SDValue Val = OutVals[OutIdx];
24167 DAG.
getVTList(MVT::i32, MVT::i32), Val);
24171 Register RegHi = RVLocs[++i].getLocReg();
24173 if (Subtarget.isRegisterReservedByUser(RegLo) ||
24174 Subtarget.isRegisterReservedByUser(RegHi))
24177 "Return value register required, but has been reserved."});
24190 if (Subtarget.isRegisterReservedByUser(VA.
getLocReg()))
24193 "Return value register required, but has been reserved."});
24212 unsigned RetOpc = RISCVISD::RET_GLUE;
24215 if (Func.hasFnAttribute(
"interrupt")) {
24216 if (!Func.getReturnType()->isVoidTy())
24218 "Functions with the interrupt attribute must have void return type!");
24224 if (Kind ==
"supervisor")
24225 RetOpc = RISCVISD::SRET_GLUE;
24226 else if (Kind ==
"rnmi") {
24227 assert(Subtarget.hasFeature(RISCV::FeatureStdExtSmrnmi) &&
24228 "Need Smrnmi extension for rnmi");
24229 RetOpc = RISCVISD::MNRET_GLUE;
24230 }
else if (Kind ==
"qci-nest" || Kind ==
"qci-nonest") {
24231 assert(Subtarget.hasFeature(RISCV::FeatureVendorXqciint) &&
24232 "Need Xqciint for qci-(no)nest");
24233 RetOpc = RISCVISD::QC_C_MILEAVERET_GLUE;
24235 RetOpc = RISCVISD::MRET_GLUE;
24238 return DAG.
getNode(RetOpc,
DL, MVT::Other, RetOps);
24241void RISCVTargetLowering::validateCCReservedRegs(
24242 const SmallVectorImpl<std::pair<llvm::Register, llvm::SDValue>> &Regs,
24250 F,
"Argument register required, but has been reserved."});
24256 if (
N->getNumValues() != 1)
24258 if (!
N->hasNUsesOfValue(1, 0))
24261 SDNode *Copy = *
N->user_begin();
24275 if (Copy->getOperand(Copy->getNumOperands() - 1).getValueType() == MVT::Glue)
24279 bool HasRet =
false;
24281 if (
Node->getOpcode() != RISCVISD::RET_GLUE)
24288 Chain = Copy->getOperand(0);
24300 if (Constraint.
size() == 1) {
24301 switch (Constraint[0]) {
24318 if (Constraint ==
"vr" || Constraint ==
"vd" || Constraint ==
"vm")
24320 if (Constraint ==
"cr" || Constraint ==
"cR" || Constraint ==
"cf")
24326std::pair<unsigned, const TargetRegisterClass *>
24332 if (Constraint.
size() == 1) {
24333 switch (Constraint[0]) {
24338 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
24339 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
24340 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
24341 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
24342 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
24343 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
24344 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
24346 if (VT == MVT::f16) {
24347 if (Subtarget.hasStdExtZfhmin())
24348 return std::make_pair(0U, &RISCV::FPR16RegClass);
24349 if (Subtarget.hasStdExtZhinxmin())
24350 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
24351 }
else if (VT == MVT::f32) {
24352 if (Subtarget.hasStdExtF())
24353 return std::make_pair(0U, &RISCV::FPR32RegClass);
24354 if (Subtarget.hasStdExtZfinx())
24355 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
24356 }
else if (VT == MVT::f64) {
24357 if (Subtarget.hasStdExtD())
24358 return std::make_pair(0U, &RISCV::FPR64RegClass);
24359 if (Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
24360 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
24361 if (Subtarget.hasStdExtZdinx() && Subtarget.is64Bit())
24362 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
24366 if (((VT == MVT::i64 || VT == MVT::f64) && !Subtarget.is64Bit()) ||
24367 (VT == MVT::i128 && Subtarget.is64Bit()))
24368 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
24373 }
else if (Constraint ==
"vr") {
24376 for (
const auto *RC :
24377 {&RISCV::VMRegClass, &RISCV::VRMF8RegClass, &RISCV::VRMF4RegClass,
24378 &RISCV::VRMF2RegClass, &RISCV::VRRegClass, &RISCV::VRM2RegClass,
24379 &RISCV::VRM4RegClass, &RISCV::VRM8RegClass, &RISCV::VRN2M1RegClass,
24380 &RISCV::VRN3M1RegClass, &RISCV::VRN4M1RegClass,
24381 &RISCV::VRN5M1RegClass, &RISCV::VRN6M1RegClass,
24382 &RISCV::VRN7M1RegClass, &RISCV::VRN8M1RegClass,
24383 &RISCV::VRN2M2RegClass, &RISCV::VRN3M2RegClass,
24384 &RISCV::VRN4M2RegClass, &RISCV::VRN2M4RegClass}) {
24386 return std::make_pair(0U, RC);
24390 if (
TRI->isTypeLegalForClass(*RC, ContainerVT))
24391 return std::make_pair(0U, RC);
24394 }
else if (Constraint ==
"vd") {
24397 for (
const auto *RC :
24398 {&RISCV::VMNoV0RegClass, &RISCV::VRMF8NoV0RegClass,
24399 &RISCV::VRMF4NoV0RegClass, &RISCV::VRMF2NoV0RegClass,
24400 &RISCV::VRNoV0RegClass, &RISCV::VRM2NoV0RegClass,
24401 &RISCV::VRM4NoV0RegClass, &RISCV::VRM8NoV0RegClass,
24402 &RISCV::VRN2M1NoV0RegClass, &RISCV::VRN3M1NoV0RegClass,
24403 &RISCV::VRN4M1NoV0RegClass, &RISCV::VRN5M1NoV0RegClass,
24404 &RISCV::VRN6M1NoV0RegClass, &RISCV::VRN7M1NoV0RegClass,
24405 &RISCV::VRN8M1NoV0RegClass, &RISCV::VRN2M2NoV0RegClass,
24406 &RISCV::VRN3M2NoV0RegClass, &RISCV::VRN4M2NoV0RegClass,
24407 &RISCV::VRN2M4NoV0RegClass}) {
24409 return std::make_pair(0U, RC);
24413 if (
TRI->isTypeLegalForClass(*RC, ContainerVT))
24414 return std::make_pair(0U, RC);
24417 }
else if (Constraint ==
"vm") {
24418 if (
TRI->isTypeLegalForClass(RISCV::VMV0RegClass, VT.
SimpleTy))
24419 return std::make_pair(0U, &RISCV::VMV0RegClass);
24425 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, ContainerVT))
24426 return std::make_pair(0U, &RISCV::VMV0RegClass);
24428 }
else if (Constraint ==
"cr") {
24429 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
24430 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
24431 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
24432 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
24433 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
24434 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
24436 return std::make_pair(0U, &RISCV::GPRCRegClass);
24437 }
else if (Constraint ==
"cR") {
24438 if (((VT == MVT::i64 || VT == MVT::f64) && !Subtarget.is64Bit()) ||
24439 (VT == MVT::i128 && Subtarget.is64Bit()))
24440 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
24441 }
else if (Constraint ==
"cf") {
24442 if (VT == MVT::f16) {
24443 if (Subtarget.hasStdExtZfhmin())
24444 return std::make_pair(0U, &RISCV::FPR16CRegClass);
24445 if (Subtarget.hasStdExtZhinxmin())
24446 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
24447 }
else if (VT == MVT::f32) {
24448 if (Subtarget.hasStdExtF())
24449 return std::make_pair(0U, &RISCV::FPR32CRegClass);
24450 if (Subtarget.hasStdExtZfinx())
24451 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
24452 }
else if (VT == MVT::f64) {
24453 if (Subtarget.hasStdExtD())
24454 return std::make_pair(0U, &RISCV::FPR64CRegClass);
24455 if (Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
24456 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
24457 if (Subtarget.hasStdExtZdinx() && Subtarget.is64Bit())
24458 return std::make_pair(0U, &RISCV::GPRCRegClass);
24467 .
Case(
"{zero}", RISCV::X0)
24468 .
Case(
"{ra}", RISCV::X1)
24469 .
Case(
"{sp}", RISCV::X2)
24470 .
Case(
"{gp}", RISCV::X3)
24471 .
Case(
"{tp}", RISCV::X4)
24472 .
Case(
"{t0}", RISCV::X5)
24473 .
Case(
"{t1}", RISCV::X6)
24474 .
Case(
"{t2}", RISCV::X7)
24475 .
Cases({
"{s0}",
"{fp}"}, RISCV::X8)
24476 .Case(
"{s1}", RISCV::X9)
24477 .
Case(
"{a0}", RISCV::X10)
24478 .
Case(
"{a1}", RISCV::X11)
24479 .
Case(
"{a2}", RISCV::X12)
24480 .
Case(
"{a3}", RISCV::X13)
24481 .
Case(
"{a4}", RISCV::X14)
24482 .
Case(
"{a5}", RISCV::X15)
24483 .
Case(
"{a6}", RISCV::X16)
24484 .
Case(
"{a7}", RISCV::X17)
24485 .
Case(
"{s2}", RISCV::X18)
24486 .
Case(
"{s3}", RISCV::X19)
24487 .
Case(
"{s4}", RISCV::X20)
24488 .
Case(
"{s5}", RISCV::X21)
24489 .
Case(
"{s6}", RISCV::X22)
24490 .
Case(
"{s7}", RISCV::X23)
24491 .
Case(
"{s8}", RISCV::X24)
24492 .
Case(
"{s9}", RISCV::X25)
24493 .
Case(
"{s10}", RISCV::X26)
24494 .
Case(
"{s11}", RISCV::X27)
24495 .
Case(
"{t3}", RISCV::X28)
24496 .
Case(
"{t4}", RISCV::X29)
24497 .
Case(
"{t5}", RISCV::X30)
24498 .
Case(
"{t6}", RISCV::X31)
24500 if (XRegFromAlias != RISCV::NoRegister)
24501 return std::make_pair(XRegFromAlias, &RISCV::GPRRegClass);
24510 if (Subtarget.hasStdExtF()) {
24512 .
Cases({
"{f0}",
"{ft0}"}, RISCV::F0_F)
24513 .Cases({
"{f1}",
"{ft1}"}, RISCV::F1_F)
24514 .Cases({
"{f2}",
"{ft2}"}, RISCV::F2_F)
24515 .Cases({
"{f3}",
"{ft3}"}, RISCV::F3_F)
24516 .Cases({
"{f4}",
"{ft4}"}, RISCV::F4_F)
24517 .Cases({
"{f5}",
"{ft5}"}, RISCV::F5_F)
24518 .Cases({
"{f6}",
"{ft6}"}, RISCV::F6_F)
24519 .Cases({
"{f7}",
"{ft7}"}, RISCV::F7_F)
24520 .Cases({
"{f8}",
"{fs0}"}, RISCV::F8_F)
24521 .Cases({
"{f9}",
"{fs1}"}, RISCV::F9_F)
24522 .Cases({
"{f10}",
"{fa0}"}, RISCV::F10_F)
24523 .Cases({
"{f11}",
"{fa1}"}, RISCV::F11_F)
24524 .Cases({
"{f12}",
"{fa2}"}, RISCV::F12_F)
24525 .Cases({
"{f13}",
"{fa3}"}, RISCV::F13_F)
24526 .Cases({
"{f14}",
"{fa4}"}, RISCV::F14_F)
24527 .Cases({
"{f15}",
"{fa5}"}, RISCV::F15_F)
24528 .Cases({
"{f16}",
"{fa6}"}, RISCV::F16_F)
24529 .Cases({
"{f17}",
"{fa7}"}, RISCV::F17_F)
24530 .Cases({
"{f18}",
"{fs2}"}, RISCV::F18_F)
24531 .Cases({
"{f19}",
"{fs3}"}, RISCV::F19_F)
24532 .Cases({
"{f20}",
"{fs4}"}, RISCV::F20_F)
24533 .Cases({
"{f21}",
"{fs5}"}, RISCV::F21_F)
24534 .Cases({
"{f22}",
"{fs6}"}, RISCV::F22_F)
24535 .Cases({
"{f23}",
"{fs7}"}, RISCV::F23_F)
24536 .Cases({
"{f24}",
"{fs8}"}, RISCV::F24_F)
24537 .Cases({
"{f25}",
"{fs9}"}, RISCV::F25_F)
24538 .Cases({
"{f26}",
"{fs10}"}, RISCV::F26_F)
24539 .Cases({
"{f27}",
"{fs11}"}, RISCV::F27_F)
24540 .Cases({
"{f28}",
"{ft8}"}, RISCV::F28_F)
24541 .Cases({
"{f29}",
"{ft9}"}, RISCV::F29_F)
24542 .Cases({
"{f30}",
"{ft10}"}, RISCV::F30_F)
24543 .Cases({
"{f31}",
"{ft11}"}, RISCV::F31_F)
24545 if (FReg != RISCV::NoRegister) {
24546 assert(RISCV::F0_F <= FReg && FReg <= RISCV::F31_F &&
"Unknown fp-reg");
24547 if (Subtarget.hasStdExtD() && (VT == MVT::f64 || VT == MVT::Other)) {
24548 unsigned RegNo = FReg - RISCV::F0_F;
24549 unsigned DReg = RISCV::F0_D + RegNo;
24550 return std::make_pair(DReg, &RISCV::FPR64RegClass);
24552 if (VT == MVT::f32 || VT == MVT::Other)
24553 return std::make_pair(FReg, &RISCV::FPR32RegClass);
24554 if (Subtarget.hasStdExtZfhmin() && VT == MVT::f16) {
24555 unsigned RegNo = FReg - RISCV::F0_F;
24556 unsigned HReg = RISCV::F0_H + RegNo;
24557 return std::make_pair(HReg, &RISCV::FPR16RegClass);
24562 if (Subtarget.hasVInstructions()) {
24564 .
Case(
"{v0}", RISCV::V0)
24565 .
Case(
"{v1}", RISCV::V1)
24566 .
Case(
"{v2}", RISCV::V2)
24567 .
Case(
"{v3}", RISCV::V3)
24568 .
Case(
"{v4}", RISCV::V4)
24569 .
Case(
"{v5}", RISCV::V5)
24570 .
Case(
"{v6}", RISCV::V6)
24571 .
Case(
"{v7}", RISCV::V7)
24572 .
Case(
"{v8}", RISCV::V8)
24573 .
Case(
"{v9}", RISCV::V9)
24574 .
Case(
"{v10}", RISCV::V10)
24575 .
Case(
"{v11}", RISCV::V11)
24576 .
Case(
"{v12}", RISCV::V12)
24577 .
Case(
"{v13}", RISCV::V13)
24578 .
Case(
"{v14}", RISCV::V14)
24579 .
Case(
"{v15}", RISCV::V15)
24580 .
Case(
"{v16}", RISCV::V16)
24581 .
Case(
"{v17}", RISCV::V17)
24582 .
Case(
"{v18}", RISCV::V18)
24583 .
Case(
"{v19}", RISCV::V19)
24584 .
Case(
"{v20}", RISCV::V20)
24585 .
Case(
"{v21}", RISCV::V21)
24586 .
Case(
"{v22}", RISCV::V22)
24587 .
Case(
"{v23}", RISCV::V23)
24588 .
Case(
"{v24}", RISCV::V24)
24589 .
Case(
"{v25}", RISCV::V25)
24590 .
Case(
"{v26}", RISCV::V26)
24591 .
Case(
"{v27}", RISCV::V27)
24592 .
Case(
"{v28}", RISCV::V28)
24593 .
Case(
"{v29}", RISCV::V29)
24594 .
Case(
"{v30}", RISCV::V30)
24595 .
Case(
"{v31}", RISCV::V31)
24597 if (VReg != RISCV::NoRegister) {
24598 if (
TRI->isTypeLegalForClass(RISCV::VMRegClass, VT.
SimpleTy))
24599 return std::make_pair(VReg, &RISCV::VMRegClass);
24600 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, VT.
SimpleTy))
24601 return std::make_pair(VReg, &RISCV::VRRegClass);
24602 for (
const auto *RC :
24603 {&RISCV::VRM2RegClass, &RISCV::VRM4RegClass, &RISCV::VRM8RegClass}) {
24604 if (
TRI->isTypeLegalForClass(*RC, VT.
SimpleTy)) {
24605 VReg =
TRI->getMatchingSuperReg(VReg, RISCV::sub_vrm1_0, RC);
24606 return std::make_pair(VReg, RC);
24618 if (ConstraintCode.
size() == 1) {
24619 switch (ConstraintCode[0]) {
24634 if (Constraint.
size() == 1) {
24635 switch (Constraint[0]) {
24642 Subtarget.getXLenVT()));
24673 if (Subtarget.hasStdExtZtso()) {
24675 return Builder.CreateFence(Ord);
24680 return Builder.CreateFence(Ord);
24689 if (Subtarget.hasStdExtZtso()) {
24691 return Builder.CreateFence(Ord);
24697 if (Subtarget.enableTrailingSeqCstFence() &&
isa<StoreInst>(Inst) &&
24716 if (Subtarget.hasForcedAtomics())
24721 if (Subtarget.hasStdExtZacas() &&
24722 (
Size >= 32 || Subtarget.hasStdExtZabha()))
24728 if (
Size < 32 && !Subtarget.hasStdExtZabha())
24740 return Intrinsic::riscv_masked_atomicrmw_xchg;
24742 return Intrinsic::riscv_masked_atomicrmw_add;
24744 return Intrinsic::riscv_masked_atomicrmw_sub;
24746 return Intrinsic::riscv_masked_atomicrmw_nand;
24748 return Intrinsic::riscv_masked_atomicrmw_max;
24750 return Intrinsic::riscv_masked_atomicrmw_min;
24752 return Intrinsic::riscv_masked_atomicrmw_umax;
24754 return Intrinsic::riscv_masked_atomicrmw_umin;
24770 Builder.CreateNot(Mask,
"Inv_Mask"),
24777 unsigned XLen = Subtarget.getXLen();
24780 Type *Tys[] = {Builder.getIntNTy(XLen), AlignedAddr->
getType()};
24786 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
24787 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
24788 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
24801 unsigned ValWidth =
24804 Builder.CreateSub(Builder.getIntN(XLen, XLen - ValWidth), ShiftAmt);
24805 Result = Builder.CreateCall(LrwOpScwLoop,
24806 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
24809 Builder.CreateCall(LrwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
24813 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
24821 if (Subtarget.hasForcedAtomics())
24825 if (!(Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas()) &&
24834 unsigned XLen = Subtarget.getXLen();
24835 Value *Ordering = Builder.getIntN(XLen,
static_cast<uint64_t>(Ord));
24836 Intrinsic::ID CmpXchgIntrID = Intrinsic::riscv_masked_cmpxchg;
24838 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
24839 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
24840 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
24842 Type *Tys[] = {Builder.getIntNTy(XLen), AlignedAddr->
getType()};
24843 Value *Result = Builder.CreateIntrinsic(
24844 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, Ordering});
24846 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
24851 EVT DataVT)
const {
24867 return Subtarget.hasStdExtZfhmin();
24869 return Subtarget.hasStdExtF();
24871 return Subtarget.hasStdExtD();
24901 assert(Subtarget.getRealMinVLen() >= 64 &&
"zve32* unsupported");
24903 "RVVBitsPerBlock changed, audit needed");
24912 if (!Subtarget.hasVendorXTHeadMemIdx())
24918 Base =
Op->getOperand(0);
24920 int64_t RHSC = RHS->getSExtValue();
24926 bool isLegalIndexedOffset =
false;
24927 for (
unsigned i = 0; i < 4; i++)
24928 if (
isInt<5>(RHSC >> i) && ((RHSC % (1LL << i)) == 0)) {
24929 isLegalIndexedOffset =
true;
24933 if (!isLegalIndexedOffset)
24950 VT = LD->getMemoryVT();
24951 Ptr = LD->getBasePtr();
24953 VT = ST->getMemoryVT();
24954 Ptr = ST->getBasePtr();
24970 if (Subtarget.hasVendorXCVmem() && !Subtarget.is64Bit()) {
24975 Base = LS->getBasePtr();
24979 if (
Base ==
Op->getOperand(0))
24981 else if (
Base ==
Op->getOperand(1))
24993 VT = LD->getMemoryVT();
24994 Ptr = LD->getBasePtr();
24996 VT = ST->getMemoryVT();
24997 Ptr = ST->getBasePtr();
25021 return VT.
isVector() ? Subtarget.hasVInstructionsF16()
25022 : Subtarget.hasStdExtZfhOrZhinx();
25024 return Subtarget.hasStdExtFOrZfinx();
25026 return Subtarget.hasStdExtDOrZdinx();
25041 if (Subtarget.hasStdExtZaamo() || Subtarget.hasForcedAtomics())
25045 assert(Subtarget.hasStdExtZalrsc());
25059 const Constant *PersonalityFn)
const {
25064 const Constant *PersonalityFn)
const {
25071 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
25072 Type.getSizeInBits() < Subtarget.getXLen()))
25079 bool IsSigned)
const {
25080 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
25094 const bool HasZmmul = Subtarget.hasStdExtZmmul();
25099 const APInt &Imm = ConstNode->getAPIntValue();
25102 if (Subtarget.hasVendorXqciac() && Imm.isSignedIntN(12))
25106 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
25107 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
25111 if (Subtarget.hasShlAdd(3) && !Imm.isSignedIntN(12) &&
25112 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
25113 (Imm - 8).isPowerOf2()))
25118 if (!Imm.isSignedIntN(12) && Imm.countr_zero() < 12 &&
25119 ConstNode->hasOneUse()) {
25120 APInt ImmS = Imm.ashr(Imm.countr_zero());
25121 if ((ImmS + 1).isPowerOf2() || (ImmS - 1).isPowerOf2() ||
25122 (1 - ImmS).isPowerOf2())
25145 if (C1.
isSignedIntN(12) && !(C1 * C2).isSignedIntN(12))
25154 unsigned *
Fast)
const {
25157 *
Fast = Subtarget.enableUnalignedScalarMem();
25158 return Subtarget.enableUnalignedScalarMem();
25174 *
Fast = Subtarget.enableUnalignedVectorMem();
25175 return Subtarget.enableUnalignedVectorMem();
25180 const AttributeList &FuncAttributes)
const {
25181 if (!Subtarget.hasVInstructions())
25184 if (FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat))
25196 const unsigned MinVLenInBytes =
25197 std::min(Subtarget.getRealMinVLen() / 8, 1024U);
25199 if (
Op.size() < MinVLenInBytes)
25214 MVT PreferredVT = (
Op.isMemset() && !
Op.isZeroMemset()) ? MVT::i8 : ELenVT;
25218 if (PreferredVT != MVT::i8 && !Subtarget.enableUnalignedVectorMem()) {
25220 if (
Op.isFixedDstAlign())
25221 RequiredAlign = std::min(RequiredAlign,
Op.getDstAlign());
25223 RequiredAlign = std::min(RequiredAlign,
Op.getSrcAlign());
25231 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
25232 bool IsABIRegCopy = CC.has_value();
25235 MVT PairVT = Subtarget.is64Bit() ? MVT::i128 : MVT::i64;
25236 if ((ValueVT == PairVT ||
25237 (!Subtarget.is64Bit() && Subtarget.hasStdExtZdinx() &&
25238 ValueVT == MVT::f64)) &&
25239 NumParts == 1 && PartVT == MVT::Untyped) {
25241 MVT XLenVT = Subtarget.getXLenVT();
25242 if (ValueVT == MVT::f64)
25247 Parts[0] = DAG.
getNode(RISCVISD::BuildGPRPair,
DL, PartVT,
Lo,
Hi);
25251 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
25252 PartVT == MVT::f32) {
25267 [[maybe_unused]]
unsigned ValLMUL =
25271 [[maybe_unused]]
unsigned PartLMUL =
25274 assert(ValNF == PartNF && ValLMUL == PartLMUL &&
25275 "RISC-V vector tuple type only accepts same register class type "
25294 if (PartVTBitSize % ValueVTBitSize == 0) {
25295 assert(PartVTBitSize >= ValueVTBitSize);
25302 if (ValueEltVT != PartEltVT) {
25303 if (PartVTBitSize > ValueVTBitSize) {
25305 assert(
Count != 0 &&
"The number of element should not be zero.");
25306 EVT SameEltTypeVT =
25324 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
25325 bool IsABIRegCopy = CC.has_value();
25327 MVT PairVT = Subtarget.is64Bit() ? MVT::i128 : MVT::i64;
25328 if ((ValueVT == PairVT ||
25329 (!Subtarget.is64Bit() && Subtarget.hasStdExtZdinx() &&
25330 ValueVT == MVT::f64)) &&
25331 NumParts == 1 && PartVT == MVT::Untyped) {
25333 MVT XLenVT = Subtarget.getXLenVT();
25342 if (ValueVT == MVT::f64)
25347 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
25348 PartVT == MVT::f32) {
25364 unsigned ValueVTBitSize =
25370 if (PartVTBitSize % ValueVTBitSize == 0) {
25371 assert(PartVTBitSize >= ValueVTBitSize);
25372 EVT SameEltTypeVT = ValueVT;
25379 if (ValueEltVT != PartEltVT) {
25381 assert(
Count != 0 &&
"The number of element should not be zero.");
25400 bool OptSize = Attr.hasFnAttr(Attribute::MinSize);
25401 return OptSize && !VT.
isVector() &&
25408 unsigned Opc =
N->getOpcode();
25417 M, Intrinsic::thread_pointer, IRB.
getPtrTy());
25425 if (Subtarget.isTargetFuchsia())
25431 if (Subtarget.isTargetAndroid())
25436 if (M->getStackProtectorGuard() ==
"tls") {
25438 int Offset = M->getStackProtectorGuardOffset();
25446 Align Alignment)
const {
25447 if (!Subtarget.hasVInstructions())
25451 if (DataType.isFixedLengthVector() && !Subtarget.useRVVForFixedLengthVectors())
25458 if (!Subtarget.enableUnalignedVectorMem() &&
25466 Align Alignment)
const {
25467 if (!Subtarget.hasVInstructions())
25474 if (!Subtarget.enableUnalignedVectorMem() &&
25486 "Invalid call instruction for a KCFI check");
25488 MBBI->getOpcode()));
25491 Target.setIsRenamable(
false);
25499#define GET_REGISTER_MATCHER
25500#include "RISCVGenAsmMatcher.inc"
25511 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
25512 if (!ReservedRegs.
test(Reg) && !Subtarget.isRegisterReservedByUser(Reg))
25520 const MDNode *NontemporalInfo =
I.getMetadata(LLVMContext::MD_nontemporal);
25522 if (NontemporalInfo ==
nullptr)
25530 int NontemporalLevel = 5;
25531 const MDNode *RISCVNontemporalInfo =
25532 I.getMetadata(
"riscv-nontemporal-domain");
25533 if (RISCVNontemporalInfo !=
nullptr)
25540 assert((1 <= NontemporalLevel && NontemporalLevel <= 5) &&
25541 "RISC-V target doesn't support this non-temporal domain.");
25543 NontemporalLevel -= 2;
25545 if (NontemporalLevel & 0b1)
25547 if (NontemporalLevel & 0b10)
25560 return TargetFlags;
25573 return Subtarget.hasStdExtZvbb();
25578 return Subtarget.hasCPOPLike() && (VT == MVT::i32 || VT == MVT::i64);
25588 if (Subtarget.hasStdExtZalasr()) {
25589 if (Subtarget.hasStdExtZtso()) {
25619 if (
Op == Instruction::Add ||
Op == Instruction::Sub ||
25620 Op == Instruction::And ||
Op == Instruction::Or ||
25621 Op == Instruction::Xor ||
Op == Instruction::InsertElement ||
25622 Op == Instruction::ShuffleVector ||
Op == Instruction::Load ||
25623 Op == Instruction::Freeze ||
Op == Instruction::Store)
25628 if (RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(
II->getIntrinsicID())) {
25635 for (
unsigned i = 0; i <
II->arg_size(); ++i)
25636 if (
II->getArgOperand(i)->getType()->isRISCVVectorTupleTy())
25641 if (
II->getIntrinsicID() == Intrinsic::vector_extract)
25654 if (AI->getAllocatedType()->isScalableTy())
25662RISCVTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
25670 if (!Subtarget.hasShortForwardBranchIALU())
25672 EVT VT =
N->getValueType(0);
25673 if (!(VT == MVT::i32 || (VT == MVT::i64 && Subtarget.
is64Bit())))
25677 if (Divisor.
sgt(2048) || Divisor.
slt(-2048))
25682bool RISCVTargetLowering::shouldFoldSelectWithSingleBitTest(
25683 EVT VT,
const APInt &AndMask)
const {
25684 if (Subtarget.
hasCZEROLike() || Subtarget.hasVendorXTHeadCondMov())
25690 return Subtarget.getMinimumJumpTableEntries();
25697 if (Subtarget.hasStdExtZicfilp()) {
25704 return DAG.
getNode(RISCVISD::SW_GUARDED_BRIND, dl, MVT::Other, Chain, Addr);
25721std::pair<const TargetRegisterClass *, uint8_t>
25741#define GET_RISCVVIntrinsicsTable_IMPL
25742#include "RISCVGenSearchableTables.inc"
25757 Align StackAlign)
const {
25761 unsigned StackProbeSize =
25765 return StackProbeSize ? StackProbeSize : StackAlign.
value();
25782 EVT VT =
Op.getValueType();
25793 Chain = DAG.
getNode(RISCVISD::PROBED_ALLOCA, dl, MVT::Other, Chain, SP);
25803 Register TargetReg =
MI.getOperand(0).getReg();
25806 bool IsRV64 = Subtarget.is64Bit();
25807 Align StackAlign = Subtarget.getFrameLowering()->getStackAlign();
25814 MF.
insert(MBBInsertPoint, LoopTestMBB);
25816 MF.
insert(MBBInsertPoint, ExitMBB);
25832 TII->get(IsRV64 ? RISCV::SD : RISCV::SW))
25853 MBB->addSuccessor(LoopTestMBB);
25855 MI.eraseFromParent();
25857 return ExitMBB->
begin()->getParent();
25861 if (Subtarget.hasStdExtFOrZfinx()) {
25862 static const MCPhysReg RCRegs[] = {RISCV::FRM, RISCV::FFLAGS};
25869 EVT VT =
Y.getValueType();
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(ConstantPoolSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, unsigned Flags)
static constexpr unsigned long long mask(BlockVerifier::State S)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
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)
const HexagonInstrInfo * TII
This file defines an InstructionCost class that is used when calculating the cost of an instruction,...
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define CC_VLS_CASE(ABIVlen)
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)
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).
Register const TargetRegisterInfo * TRI
Promote Memory to Register
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 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 combinePExtTruncate(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
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 void processVCIXOperands(SDValue OrigOp, MutableArrayRef< SDValue > Operands, SelectionDAG &DAG)
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 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 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 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(3))
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 const unsigned ZvfbfaVPOps[]
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 void promoteVCIXScalar(SDValue Op, MutableArrayRef< SDValue > Operands, 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 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 SDValue combineOrToBitfieldInsert(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue getVCIXISDNodeVOID(SDValue Op, SelectionDAG &DAG, unsigned Type)
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 const unsigned ZvfbfaOps[]
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 SDValue combineXorToBitfieldInsert(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue combineANDOfSETCCToCZERO(SDNode *N, SelectionDAG &DAG, 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 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 getVCIXISDNodeWCHAIN(SDValue Op, SelectionDAG &DAG, unsigned Type)
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 bool isSimm12Constant(SDValue V)
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 SDValue getShlAddShlAdd(SDNode *N, SelectionDAG &DAG, unsigned ShX, unsigned ShY, bool AddX, unsigned Shift)
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 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 lowerSelectToBinOp(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 expandMulToShlAddShlAdd(SDNode *N, SelectionDAG &DAG, uint64_t MulAmt, unsigned Shift)
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 SDValue combineOrAndToBitfieldInsert(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
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, bool IsCopyable=false)
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 TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static constexpr int Concat[]
static constexpr roundingMode rmNearestTiesToEven
static LLVM_ABI unsigned int semanticsPrecision(const fltSemantics &)
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.
bool isShiftedMask() const
Return true if this APInt value contains a non-empty sequence of ones with the remainder zero.
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.
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 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.
A "pseudo-class" with methods for operating on BUILD_VECTORs.
LLVM_ABI SDValue getSplatValue(const APInt &DemandedElts, BitVector *UndefElements=nullptr) const
Returns the demanded splatted value or a null value if this is not a splat.
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.
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.
ValueT & at(const_arg_type_t< KeyT > Val)
at - Return the entry for the specified key, or abort if no such entry exists.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
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...
Common base class shared among various IRBuilders.
Value * CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
BasicBlock * GetInsertBlock() const
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
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.
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 LocationSize precise(uint64_t Value)
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.
MCContext & getContext() const
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...
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.
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.
BasicBlockListType::iterator iterator
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)
CreateMachineInstr - Allocate a new MachineInstr.
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...
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.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
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)
unsigned getMaxLMULForFixedLengthVectors() const
bool hasVInstructionsI64() const
bool hasVInstructionsF64() const
bool hasStdExtZfhOrZhinx() const
bool hasShlAdd(int64_t ShAmt) const
unsigned getRealMinVLen() const
bool useRVVForFixedLengthVectors() const
bool hasVInstructionsBF16Minimal() const
bool hasVInstructionsF16Minimal() const
bool hasConditionalMoveFusion() const
bool hasVInstructionsF16() const
bool hasVInstructionsBF16() const
unsigned getMaxBuildIntsCost() const
bool hasVInstructions() const
bool isRegisterReservedByUser(Register i) const override
std::optional< unsigned > getRealVLen() const
bool useConstantPoolForLargeInts() const
unsigned getRealMaxVLen() const
const RISCVRegisterInfo * getRegisterInfo() const override
const RISCVInstrInfo * getInstrInfo() const override
bool hasBEXTILike() const
const RISCVTargetLowering * getTargetLowering() const override
bool enablePExtCodeGen() const
bool hasVInstructionsF32() const
bool hasCZEROLike() const
static std::pair< unsigned, unsigned > computeVLMAXBounds(MVT ContainerVT, const RISCVSubtarget &Subtarget)
static std::pair< unsigned, unsigned > decomposeSubvectorInsertExtractToSubRegs(MVT VecVT, MVT SubVecVT, unsigned InsertExtractIdx, const RISCVRegisterInfo *TRI)
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 ...
ISD::NodeType getExtendForAtomicRMWArg(unsigned Op) const override
Returns how the platform's atomic rmw operations expect their input argument to be extended (ZERO_EXT...
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.
bool isReassocProfitable(SelectionDAG &DAG, SDValue N0, SDValue N1) const override
Control the following reassociation of operands: (op (op x, c1), y) -> (op (op x, y),...
bool shouldFoldMaskToVariableShiftPair(SDValue Y) const override
There are two ways to clear extreme bits (either low or high): Mask: x & (-1 << y) (the instcombine c...
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 isLegalElementTypeForRVV(EVT ScalarTy) const
bool isLegalFirstFaultLoad(EVT DataType, Align Alignment) const
Return true if a fault-only-first load of the given result type and alignment is legal.
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,...
LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Customize the preferred legalization strategy for certain types.
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.
bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallBase &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...
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 SDValue getElementCount(const SDLoc &DL, EVT VT, ElementCount EC)
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 getSplatValue(SDValue V, bool LegalTypes=false)
If V is a splat vector, return its scalar source operand by extracting that element from the source v...
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 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 UnrollVectorOp(SDNode *N, unsigned ResNE=0)
Utility function used by legalize and lowering to "unroll" a vector operation by splitting out the sc...
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 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 SDValue getTypeSize(const SDLoc &DL, EVT VT, TypeSize TS)
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 getLoadVP(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, SDValue Offset, SDValue Mask, SDValue EVL, MachinePointerInfo PtrInfo, EVT MemVT, Align Alignment, MachineMemOperand::Flags MMOFlags, const AAMDNodes &AAInfo, const MDNode *Ranges=nullptr, bool IsExpanding=false)
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)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
iterator erase(const_iterator CI)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
pointer data()
Return a pointer to the vector's buffer, even if empty().
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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(std::initializer_list< StringLiteral > CaseStrings, 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.
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...
void setMaxDivRemBitWidthSupported(unsigned SizeInBits)
Set the size in bits of the maximum div/rem the backend supports.
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.
virtual unsigned getMinimumJumpTableEntries() const
Return lower limit for number of blocks in a jump table.
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.
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
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 TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const
Return the preferred vector type legalization action.
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.
unsigned getMaxDivRemBitWidthSupported() const
Returns the size in bits of the maximum div/rem the backend supports.
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...
virtual MVT getVPExplicitVectorLengthTy() const
Returns the type to be used for the EVL/AVL operand of VP nodes: ISD::VP_ADD, ISD::VP_SUB,...
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...
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.
TargetLowering(const TargetLowering &)=delete
virtual unsigned combineRepeatedFPDivisors() const
Indicate whether this target prefers to combine FDIVs with the same divisor.
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.
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::LibcallImpl LibcallImpl, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
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 unsigned getIntegerBitWidth() const
LLVM_ABI Type * getStructElementType(unsigned N) const
LLVM_ABI bool isScalableTy(SmallPtrSetImpl< const Type * > &Visited) const
Return true if this is a type whose size is a known multiple of vscale.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
bool isStructTy() const
True if this is an instance of StructType.
LLVM_ABI bool isRISCVVectorTupleTy() const
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
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.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
A Use represents the edge between a Value definition and its users.
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
User * getUser() const
Returns the User that contains this Use.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
std::pair< iterator, bool > insert(const ValueT &V)
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 Align[]
Key for Kernel::Arg::Metadata::mAlign.
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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ 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.
@ FMODF
FMODF - Decomposes the operand into integral and fractional parts, each having the same type and sign...
@ 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...
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
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.
BinaryOp_match< LHS, RHS, Instruction::Xor > m_Xor(const LHS &L, const RHS &R)
specific_intval< false > m_SpecificInt(const APInt &V)
Match a specific integer value or vector with all elements equal to the value.
BinaryOp_match< LHS, RHS, Instruction::FMul > m_FMul(const LHS &L, const RHS &R)
TwoOps_match< Val_t, Idx_t, Instruction::ExtractElement > m_ExtractElt(const Val_t &Val, const Idx_t &Idx)
Matches ExtractElementInst.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
deferredval_ty< Value > m_Deferred(Value *const &V)
Like m_Specific(), but works if the specific value to match is determined as part of the same match()...
match_combine_or< BinaryOp_match< LHS, RHS, Instruction::Add >, DisjointOr_match< LHS, RHS > > m_AddLike(const LHS &L, const RHS &R)
Match either "add" or "or disjoint".
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
FNeg_match< OpTy > m_FNeg(const OpTy &X)
Match 'fneg X' as 'fsub -0.0, X'.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
auto m_Undef()
Match an arbitrary undef constant.
BinaryOp_match< LHS, RHS, Instruction::Or > m_Or(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)
SmallVector< Inst, 8 > InstSeq
static VLMUL encodeLMUL(unsigned LMUL, bool Fractional)
static unsigned decodeVSEW(unsigned VSEW)
@ TAIL_UNDISTURBED_MASK_UNDISTURBED
LLVM_ABI std::pair< unsigned, bool > decodeVLMUL(VLMUL VLMul)
static unsigned encodeSEW(unsigned SEW)
static constexpr unsigned FPMASK_Negative_Zero
static constexpr unsigned FPMASK_Positive_Subnormal
static constexpr unsigned FPMASK_Positive_Normal
static constexpr unsigned FPMASK_Negative_Subnormal
static constexpr unsigned FPMASK_Negative_Normal
static constexpr unsigned FPMASK_Positive_Infinity
static constexpr unsigned FPMASK_Negative_Infinity
static constexpr unsigned FPMASK_Quiet_NaN
ArrayRef< MCPhysReg > getArgGPRs(const RISCVABI::ABI ABI)
static constexpr unsigned FPMASK_Signaling_NaN
static constexpr unsigned FPMASK_Positive_Zero
static constexpr unsigned RVVBitsPerBlock
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.
auto m_ExactSr(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS > m_Srl(const LHS &L, const RHS &R)
auto m_SpecificVT(EVT RefVT, const Pattern &P)
Match a specific ValueType.
TernaryOpc_match< LHS, RHS, IDX > m_InsertSubvector(const LHS &Base, const RHS &Sub, const IDX &Idx)
Or< Preds... > m_AnyOf(const Preds &...preds)
auto m_Node(unsigned Opcode, const OpndPreds &...preds)
bool sd_match(SDNode *N, const SelectionDAG *DAG, Pattern &&P)
ConstantInt_match m_ConstInt()
Match any integer constants or splat of an integer constant.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
@ System
Synchronized with respect to all concurrently executing threads.
@ CMOV
X86 conditional moves.
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.
FunctionAddr VTableAddr Value
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.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
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,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
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.
constexpr bool has_single_bit(T Value) noexcept
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.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
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...
FunctionAddr VTableAddr Count
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
bool CC_RISCV(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
int isShifted359(T Value, int &Shift)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
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.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
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)
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
FunctionAddr VTableAddr Next
DWARFExpression::Operation Op
RoundingMode
Rounding mode.
@ TowardZero
roundTowardZero.
@ NearestTiesToEven
roundTiesToEven.
@ TowardPositive
roundTowardPositive.
@ NearestTiesToAway
roundTiesToAway.
@ TowardNegative
roundTowardNegative.
ArrayRef(const T &OneElt) -> ArrayRef< T >
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...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
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 bool isNullFPConstant(SDValue V)
Returns true if V is an FP constant with a value of positive zero.
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
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.
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
@ Increment
Incrementally increasing token ID.
@ Default
The result values are uniform if and only if all operands are uniform.
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
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.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
uint64_t getScalarStoreSize() const
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
bool isByteSized() const
Return true if the bit size is a multiple of 8.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
unsigned getRISCVVectorTupleNumFields() const
Given a RISCV vector tuple type, return the num_fields.
uint64_t getScalarSizeInBits() const
EVT getHalfSizedIntegerVT(LLVMContext &Context) const
Finds the smallest simple value type that is greater than or equal to half the width of this EVT.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
bool isRISCVVectorTuple() const
Return true if this is a vector value type.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isFixedLengthVector() const
EVT getRoundIntegerType(LLVMContext &Context) const
Rounds the bit-width of the given integer EVT up to the nearest power of two (and at least to eight),...
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
bool bitsGE(EVT VT) const
Return true if this has no less bits than VT.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
EVT changeVectorElementType(EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
bool isInteger() const
Return true if this is an integer or a vector integer type.
static LLVM_ABI KnownBits ashr(const KnownBits &LHS, const KnownBits &RHS, bool ShAmtNonZero=false, bool Exact=false)
Compute known bits for ashr(LHS, RHS).
static LLVM_ABI KnownBits urem(const KnownBits &LHS, const KnownBits &RHS)
Compute known bits for urem(LHS, RHS).
bool isUnknown() const
Returns true if we don't know any bits.
unsigned countMaxTrailingZeros() const
Returns the maximum number of trailing zero bits possible.
KnownBits trunc(unsigned BitWidth) const
Return known bits for a truncation of the value we're tracking.
unsigned getBitWidth() const
Get the bit width of this value.
KnownBits zext(unsigned BitWidth) const
Return known bits for a zero extension of the value we're tracking.
void resetAll()
Resets the known state of all bits.
static LLVM_ABI KnownBits lshr(const KnownBits &LHS, const KnownBits &RHS, bool ShAmtNonZero=false, bool Exact=false)
Compute known bits for lshr(LHS, RHS).
unsigned countMaxActiveBits() const
Returns the maximum number of bits needed to represent all possible unsigned values with these known ...
KnownBits intersectWith(const KnownBits &RHS) const
Returns KnownBits information that is known to be true for both this and RHS.
KnownBits sext(unsigned BitWidth) const
Return known bits for a sign extension of the value we're tracking.
static KnownBits add(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false)
Compute knownbits resulting from addition of LHS and RHS.
APInt getMaxValue() const
Return the maximal unsigned value possible given these KnownBits.
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).
SmallVector< ArgRegPair, 1 > ArgRegPairs
Vector of call argument and its forwarding register.
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.
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)