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};
108 !Subtarget.hasStdExtF()) {
109 errs() <<
"Hard-float 'f' ABI can't be used for a target that "
110 "doesn't support the F instruction set extension (ignoring "
114 !Subtarget.hasStdExtD()) {
115 errs() <<
"Hard-float 'd' ABI can't be used for a target that "
116 "doesn't support the D instruction set extension (ignoring "
135 MVT XLenVT = Subtarget.getXLenVT();
140 if (Subtarget.hasStdExtZfhmin())
142 if (Subtarget.hasStdExtZfbfmin() || Subtarget.hasVendorXAndesBFHCvt())
144 if (Subtarget.hasStdExtF())
146 if (Subtarget.hasStdExtD())
148 if (Subtarget.hasStdExtZhinxmin())
150 if (Subtarget.hasStdExtZfinx())
152 if (Subtarget.hasStdExtZdinx()) {
153 if (Subtarget.is64Bit())
160 MVT::nxv1i1, MVT::nxv2i1, MVT::nxv4i1, MVT::nxv8i1,
161 MVT::nxv16i1, MVT::nxv32i1, MVT::nxv64i1};
163 MVT::nxv1i8, MVT::nxv2i8, MVT::nxv4i8, MVT::nxv8i8, MVT::nxv16i8,
164 MVT::nxv32i8, MVT::nxv64i8, MVT::nxv1i16, MVT::nxv2i16, MVT::nxv4i16,
165 MVT::nxv8i16, MVT::nxv16i16, MVT::nxv32i16, MVT::nxv1i32, MVT::nxv2i32,
166 MVT::nxv4i32, MVT::nxv8i32, MVT::nxv16i32, MVT::nxv1i64, MVT::nxv2i64,
167 MVT::nxv4i64, MVT::nxv8i64};
169 MVT::nxv1f16, MVT::nxv2f16, MVT::nxv4f16,
170 MVT::nxv8f16, MVT::nxv16f16, MVT::nxv32f16};
172 MVT::nxv1bf16, MVT::nxv2bf16, MVT::nxv4bf16,
173 MVT::nxv8bf16, MVT::nxv16bf16, MVT::nxv32bf16};
175 MVT::nxv1f32, MVT::nxv2f32, MVT::nxv4f32, MVT::nxv8f32, MVT::nxv16f32};
177 MVT::nxv1f64, MVT::nxv2f64, MVT::nxv4f64, MVT::nxv8f64};
179 MVT::riscv_nxv1i8x2, MVT::riscv_nxv1i8x3, MVT::riscv_nxv1i8x4,
180 MVT::riscv_nxv1i8x5, MVT::riscv_nxv1i8x6, MVT::riscv_nxv1i8x7,
181 MVT::riscv_nxv1i8x8, MVT::riscv_nxv2i8x2, MVT::riscv_nxv2i8x3,
182 MVT::riscv_nxv2i8x4, MVT::riscv_nxv2i8x5, MVT::riscv_nxv2i8x6,
183 MVT::riscv_nxv2i8x7, MVT::riscv_nxv2i8x8, MVT::riscv_nxv4i8x2,
184 MVT::riscv_nxv4i8x3, MVT::riscv_nxv4i8x4, MVT::riscv_nxv4i8x5,
185 MVT::riscv_nxv4i8x6, MVT::riscv_nxv4i8x7, MVT::riscv_nxv4i8x8,
186 MVT::riscv_nxv8i8x2, MVT::riscv_nxv8i8x3, MVT::riscv_nxv8i8x4,
187 MVT::riscv_nxv8i8x5, MVT::riscv_nxv8i8x6, MVT::riscv_nxv8i8x7,
188 MVT::riscv_nxv8i8x8, MVT::riscv_nxv16i8x2, MVT::riscv_nxv16i8x3,
189 MVT::riscv_nxv16i8x4, MVT::riscv_nxv32i8x2};
191 if (Subtarget.hasVInstructions()) {
192 auto addRegClassForRVV = [
this](
MVT VT) {
196 if (VT.getVectorMinNumElements() < MinElts)
199 unsigned Size = VT.getSizeInBits().getKnownMinValue();
202 RC = &RISCV::VRRegClass;
204 RC = &RISCV::VRM2RegClass;
206 RC = &RISCV::VRM4RegClass;
208 RC = &RISCV::VRM8RegClass;
215 for (
MVT VT : BoolVecVTs)
216 addRegClassForRVV(VT);
217 for (
MVT VT : IntVecVTs) {
218 if (VT.getVectorElementType() == MVT::i64 &&
219 !Subtarget.hasVInstructionsI64())
221 addRegClassForRVV(VT);
224 if (Subtarget.hasVInstructionsF16Minimal() ||
225 Subtarget.hasVendorXAndesVPackFPH())
226 for (
MVT VT : F16VecVTs)
227 addRegClassForRVV(VT);
229 if (Subtarget.hasVInstructionsBF16Minimal() ||
230 Subtarget.hasVendorXAndesVBFHCvt())
231 for (
MVT VT : BF16VecVTs)
232 addRegClassForRVV(VT);
234 if (Subtarget.hasVInstructionsF32())
235 for (
MVT VT : F32VecVTs)
236 addRegClassForRVV(VT);
238 if (Subtarget.hasVInstructionsF64())
239 for (
MVT VT : F64VecVTs)
240 addRegClassForRVV(VT);
242 if (Subtarget.useRVVForFixedLengthVectors()) {
243 auto addRegClassForFixedVectors = [
this](
MVT VT) {
250 if (useRVVForFixedLengthVectorVT(VT))
251 addRegClassForFixedVectors(VT);
254 if (useRVVForFixedLengthVectorVT(VT))
255 addRegClassForFixedVectors(VT);
293 if (Subtarget.hasStdExtP()) {
294 if (Subtarget.is64Bit()) {
327 if (!(Subtarget.hasVendorXCValu() && !Subtarget.is64Bit())) {
337 if (!Subtarget.hasVendorXTHeadBb() && !Subtarget.hasVendorXqcibm() &&
338 !Subtarget.hasVendorXAndesPerf())
343 if (!Subtarget.hasStdExtZbb() && !Subtarget.hasVendorXTHeadBb() &&
344 !Subtarget.hasVendorXqcibm() && !Subtarget.hasVendorXAndesPerf() &&
345 !(Subtarget.hasVendorXCValu() && !Subtarget.is64Bit()))
348 if (Subtarget.hasStdExtZilsd() && !Subtarget.is64Bit()) {
353 if (Subtarget.is64Bit()) {
361 }
else if (Subtarget.hasStdExtP()) {
366 if (!Subtarget.hasStdExtZmmul()) {
368 }
else if (Subtarget.is64Bit()) {
375 if (!Subtarget.hasStdExtM()) {
378 }
else if (Subtarget.is64Bit()) {
380 {MVT::i8, MVT::i16, MVT::i32},
Custom);
388 if (!Subtarget.hasStdExtP() || !Subtarget.hasStdExtZmmul() ||
395 if (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) {
396 if (Subtarget.is64Bit())
398 }
else if (Subtarget.hasVendorXTHeadBb()) {
399 if (Subtarget.is64Bit())
402 }
else if (Subtarget.hasVendorXCVbitmanip() && !Subtarget.is64Bit()) {
408 if (Subtarget.hasStdExtP())
414 if (Subtarget.hasREVLike()) {
420 if (Subtarget.hasStdExtZbkb())
424 if (Subtarget.hasStdExtZbb() ||
425 (Subtarget.hasVendorXCValu() && !Subtarget.is64Bit())) {
430 if (Subtarget.hasCTZLike()) {
431 if (Subtarget.is64Bit())
437 if (!Subtarget.hasCPOPLike()) {
440 if (Subtarget.is64Bit())
447 if (Subtarget.hasCLZLike()) {
451 if (Subtarget.is64Bit() &&
452 (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtP()))
458 if (Subtarget.hasStdExtP()) {
460 if (Subtarget.is64Bit())
464 if (Subtarget.hasStdExtP() ||
465 (Subtarget.hasVendorXCValu() && !Subtarget.is64Bit())) {
467 if (Subtarget.is64Bit())
469 }
else if (Subtarget.hasShortForwardBranchIALU()) {
472 }
else if (Subtarget.is64Bit()) {
476 if (!Subtarget.useMIPSCCMovInsn() && !Subtarget.hasVendorXTHeadCondMov())
479 if ((Subtarget.hasStdExtP() || Subtarget.hasVendorXqcia()) &&
480 !Subtarget.is64Bit()) {
483 }
else if (Subtarget.hasStdExtP() && Subtarget.is64Bit()) {
486 }
else if (!Subtarget.hasStdExtZbb() && Subtarget.is64Bit()) {
491 if (Subtarget.hasVendorXqcia() && !Subtarget.is64Bit()) {
495 if ((Subtarget.hasStdExtP() || Subtarget.hasVendorXqcia()) &&
496 !Subtarget.is64Bit()) {
502 if (Subtarget.hasStdExtZbc() || Subtarget.hasStdExtZbkc())
504 if (Subtarget.hasStdExtZbc())
507 static const unsigned FPLegalNodeTypes[] = {
523 static const unsigned FPOpToLibCall[] = {
ISD::FREM};
525 static const unsigned FPRndMode[] = {
529 static const unsigned ZfhminZfbfminPromoteOps[] = {
540 if (Subtarget.hasStdExtP()) {
542 static const MVT RV32VTs[] = {MVT::v2i16, MVT::v4i8};
543 static const MVT RV64VTs[] = {MVT::v2i32, MVT::v4i16, MVT::v8i8};
545 if (Subtarget.is64Bit()) {
552 {MVT::v2i16, MVT::v4i8},
Custom);
578 if (VT != MVT::v2i32)
580 if (VT.getVectorElementType() != MVT::i8)
599 if (!Subtarget.is64Bit())
606 if (Subtarget.hasStdExtZfbfmin()) {
621 if (Subtarget.hasStdExtZfhminOrZhinxmin()) {
622 if (Subtarget.hasStdExtZfhOrZhinx()) {
629 if (Subtarget.hasStdExtZfa())
645 if (!Subtarget.hasStdExtD()) {
665 Subtarget.hasStdExtZfh() && Subtarget.hasStdExtZfa() ?
Legal :
Promote);
681 if (Subtarget.is64Bit())
685 if (Subtarget.hasStdExtFOrZfinx()) {
708 if (Subtarget.hasStdExtZfa()) {
717 if (Subtarget.hasStdExtFOrZfinx() && Subtarget.is64Bit())
720 if (Subtarget.hasStdExtDOrZdinx()) {
723 if (!Subtarget.is64Bit())
726 if (Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
727 !Subtarget.is64Bit()) {
732 if (Subtarget.hasStdExtZfa()) {
738 if (Subtarget.is64Bit())
768 if (Subtarget.is64Bit()) {
775 if (Subtarget.hasStdExtFOrZfinx()) {
801 if (Subtarget.is64Bit())
811 if (Subtarget.is64Bit()) {
818 if (Subtarget.is64Bit())
821 if (Subtarget.hasVendorXMIPSCBOP())
823 else if (Subtarget.hasStdExtZicbop())
826 if (Subtarget.hasStdExtZalrsc()) {
828 if (Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas())
832 }
else if (Subtarget.hasForcedAtomics()) {
847 if (Subtarget.hasVInstructions()) {
856 {MVT::i8, MVT::i16},
Custom);
857 if (Subtarget.is64Bit())
867 static const unsigned IntegerVPOps[] = {
868 ISD::VP_ADD, ISD::VP_SUB, ISD::VP_MUL,
869 ISD::VP_SDIV, ISD::VP_UDIV, ISD::VP_SREM,
870 ISD::VP_UREM, ISD::VP_AND, ISD::VP_OR,
871 ISD::VP_XOR, ISD::VP_SRA, ISD::VP_SRL,
872 ISD::VP_SHL, ISD::VP_REDUCE_ADD, ISD::VP_REDUCE_AND,
873 ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR, ISD::VP_REDUCE_SMAX,
874 ISD::VP_REDUCE_SMIN, ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN,
875 ISD::VP_MERGE, ISD::VP_SELECT, ISD::VP_FP_TO_SINT,
876 ISD::VP_FP_TO_UINT, ISD::VP_SETCC, ISD::VP_SIGN_EXTEND,
877 ISD::VP_ZERO_EXTEND, ISD::VP_TRUNCATE, ISD::VP_SMIN,
878 ISD::VP_SMAX, ISD::VP_UMIN, ISD::VP_UMAX,
879 ISD::VP_ABS, ISD::EXPERIMENTAL_VP_REVERSE, ISD::EXPERIMENTAL_VP_SPLICE,
880 ISD::VP_SADDSAT, ISD::VP_UADDSAT, ISD::VP_SSUBSAT,
881 ISD::VP_USUBSAT, ISD::VP_CTTZ_ELTS, ISD::VP_CTTZ_ELTS_ZERO_UNDEF};
883 static const unsigned FloatingPointVPOps[] = {
884 ISD::VP_FADD, ISD::VP_FSUB, ISD::VP_FMUL,
885 ISD::VP_FDIV, ISD::VP_FNEG, ISD::VP_FABS,
886 ISD::VP_FMA, ISD::VP_REDUCE_FADD, ISD::VP_REDUCE_SEQ_FADD,
887 ISD::VP_REDUCE_FMIN, ISD::VP_REDUCE_FMAX, ISD::VP_MERGE,
888 ISD::VP_SELECT, ISD::VP_SINT_TO_FP, ISD::VP_UINT_TO_FP,
889 ISD::VP_SETCC, ISD::VP_FP_ROUND, ISD::VP_FP_EXTEND,
890 ISD::VP_SQRT, ISD::VP_FMINNUM, ISD::VP_FMAXNUM,
891 ISD::VP_FCEIL, ISD::VP_FFLOOR, ISD::VP_FROUND,
892 ISD::VP_FROUNDEVEN, ISD::VP_FCOPYSIGN, ISD::VP_FROUNDTOZERO,
893 ISD::VP_FRINT, ISD::VP_FNEARBYINT, ISD::VP_IS_FPCLASS,
894 ISD::VP_FMINIMUM, ISD::VP_FMAXIMUM, ISD::VP_LRINT,
895 ISD::VP_LLRINT, ISD::VP_REDUCE_FMINIMUM,
896 ISD::VP_REDUCE_FMAXIMUM};
898 static const unsigned IntegerVecReduceOps[] = {
903 static const unsigned FloatingPointVecReduceOps[] = {
907 static const unsigned FloatingPointLibCallOps[] = {
911 if (!Subtarget.is64Bit()) {
920 ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR,
921 ISD::VP_REDUCE_SMAX, ISD::VP_REDUCE_SMIN,
922 ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN},
926 for (
MVT VT : BoolVecVTs) {
956 {ISD::VP_REDUCE_AND, ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR}, VT,
980 ISD::VP_TRUNCATE, ISD::VP_SETCC},
996 for (
MVT VT : IntVecVTs) {
1007 if (VT.getVectorElementType() == MVT::i64 && !Subtarget.hasStdExtV())
1013 if (Subtarget.hasStdExtZvabd()) {
1016 if (VT.getVectorElementType() == MVT::i8 ||
1017 VT.getVectorElementType() == MVT::i16)
1066 {ISD::VP_LOAD, ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1067 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER, ISD::VP_SCATTER},
1092 if (Subtarget.hasStdExtZvkb()) {
1100 if (Subtarget.hasStdExtZvbb()) {
1104 ISD::VP_CTTZ_ZERO_UNDEF, ISD::VP_CTPOP},
1110 ISD::VP_CTTZ_ZERO_UNDEF, ISD::VP_CTPOP},
1119 ISD::VP_CTLZ_ZERO_UNDEF, ISD::VP_CTTZ_ZERO_UNDEF},
1124 if (VT.getVectorElementType() == MVT::i64) {
1125 if (Subtarget.hasStdExtZvbc())
1128 if (Subtarget.hasStdExtZvbc32e()) {
1130 }
else if (Subtarget.hasStdExtZvbc()) {
1143 for (
MVT VT : VecTupleVTs) {
1164 static const unsigned ZvfhminZvfbfminPromoteOps[] = {
1198 static const unsigned ZvfbfaPromoteOps[] = {
ISD::FDIV,
1215 static const unsigned ZvfhminZvfbfminPromoteVPOps[] = {
1221 ISD::VP_REDUCE_FMIN,
1222 ISD::VP_REDUCE_FMAX,
1230 ISD::VP_FROUNDTOZERO,
1236 ISD::VP_REDUCE_FMINIMUM,
1237 ISD::VP_REDUCE_FMAXIMUM};
1240 const auto SetCommonVFPActions = [&](
MVT VT) {
1278 {ISD::VP_LOAD, ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1279 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER, ISD::VP_SCATTER},
1317 const auto SetCommonVFPExtLoadTruncStoreActions =
1319 for (
auto SmallVT : SmallerVTs) {
1327 const auto SetCommonPromoteToF32Actions = [&](
MVT VT) {
1354 ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1355 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1380 const auto SetZvfbfaActions = [&](
MVT VT) {
1416 ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1417 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1436 if (Subtarget.hasVInstructionsF16()) {
1437 for (
MVT VT : F16VecVTs) {
1440 SetCommonVFPActions(VT);
1442 }
else if (Subtarget.hasVInstructionsF16Minimal()) {
1443 for (
MVT VT : F16VecVTs) {
1446 SetCommonPromoteToF32Actions(VT);
1450 if (Subtarget.hasVInstructionsBF16()) {
1451 for (
MVT VT : BF16VecVTs) {
1454 SetZvfbfaActions(VT);
1456 }
else if (Subtarget.hasVInstructionsBF16Minimal()) {
1457 for (
MVT VT : BF16VecVTs) {
1460 SetCommonPromoteToF32Actions(VT);
1464 if (Subtarget.hasVInstructionsF32()) {
1465 for (
MVT VT : F32VecVTs) {
1468 SetCommonVFPActions(VT);
1469 SetCommonVFPExtLoadTruncStoreActions(VT, F16VecVTs);
1470 SetCommonVFPExtLoadTruncStoreActions(VT, BF16VecVTs);
1474 if (Subtarget.hasVInstructionsF64()) {
1475 for (
MVT VT : F64VecVTs) {
1478 SetCommonVFPActions(VT);
1479 SetCommonVFPExtLoadTruncStoreActions(VT, F16VecVTs);
1480 SetCommonVFPExtLoadTruncStoreActions(VT, BF16VecVTs);
1481 SetCommonVFPExtLoadTruncStoreActions(VT, F32VecVTs);
1485 if (Subtarget.useRVVForFixedLengthVectors()) {
1487 if (!useRVVForFixedLengthVectorVT(VT))
1536 {ISD::VP_REDUCE_AND, ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR}, VT,
1563 ISD::VP_SETCC, ISD::VP_TRUNCATE},
1590 ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1591 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1629 if (Subtarget.hasStdExtZvkb())
1632 if (Subtarget.hasStdExtZvbb()) {
1656 if (!useRVVForFixedLengthVectorVT(VT))
1682 ISD::VP_SCATTER, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1683 ISD::EXPERIMENTAL_VP_STRIDED_STORE},
1694 !Subtarget.hasVInstructionsF16()) {
1703 if (Subtarget.hasStdExtZfhmin()) {
1728 if (Subtarget.hasStdExtZfbfmin()) {
1735 if (Subtarget.hasStdExtZvfbfa()) {
1750 if (Subtarget.hasStdExtZvfbfa())
1794 if (Subtarget.is64Bit())
1796 if (Subtarget.hasStdExtZfhminOrZhinxmin())
1798 if (Subtarget.hasStdExtZfbfmin())
1800 if (Subtarget.hasStdExtFOrZfinx())
1802 if (Subtarget.hasStdExtDOrZdinx())
1807 if (Subtarget.hasStdExtZaamo())
1810 if (Subtarget.hasForcedAtomics()) {
1820 if (Subtarget.hasVendorXTHeadMemIdx()) {
1829 if (Subtarget.is64Bit()) {
1836 if (Subtarget.hasVendorXCVmem() && !Subtarget.is64Bit()) {
1847 if (Subtarget.hasStdExtZvdot4a8i() && Subtarget.getELen() >= 64) {
1857 if (Subtarget.useRVVForFixedLengthVectors()) {
1859 if (VT.getVectorElementType() != MVT::i32 ||
1860 !useRVVForFixedLengthVectorVT(VT))
1870 if (Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh()) {
1876 const Align FunctionAlignment(Subtarget.hasStdExtZca() ? 2 : 4);
1888 if (Subtarget.hasStdExtFOrZfinx())
1891 if (Subtarget.hasStdExtZbb())
1894 if ((Subtarget.hasStdExtZbs() && Subtarget.is64Bit()) ||
1895 Subtarget.hasVInstructions())
1898 if (Subtarget.hasStdExtZbkb())
1901 if (Subtarget.hasStdExtFOrZfinx())
1904 if (Subtarget.hasVInstructions())
1907 ISD::VP_GATHER, ISD::VP_SCATTER,
ISD::SRA,
1910 ISD::VP_STORE, ISD::VP_TRUNCATE, ISD::EXPERIMENTAL_VP_REVERSE,
1916 if (Subtarget.hasVendorXTHeadMemPair())
1918 if (Subtarget.useRVVForFixedLengthVectors())
1940 Subtarget.getMaxStoresPerMemmove(
true);
1949 if (Subtarget.is64Bit() && Subtarget.hasStdExtP())
1950 if (VT == MVT::v2i16 || VT == MVT::v4i8)
1961 if (Subtarget.hasVInstructions() &&
1972bool RISCVTargetLowering::shouldExpandGetVectorLength(
EVT TripCountVT,
1974 bool IsScalable)
const {
1981 if (TripCountVT != MVT::i32 && TripCountVT != Subtarget.
getXLenVT())
1999 return !Subtarget.hasVInstructions() ||
2007 auto &
DL =
I.getDataLayout();
2009 auto SetRVVLoadStoreInfo = [&](
unsigned PtrOp,
bool IsStore,
2010 bool IsUnitStrided,
bool UsePtrVal =
false) {
2015 Info.ptrVal =
I.getArgOperand(PtrOp);
2017 Info.fallbackAddressSpace =
2018 I.getArgOperand(PtrOp)->getType()->getPointerAddressSpace();
2022 MemTy =
I.getArgOperand(0)->getType();
2025 MemTy =
I.getType();
2040 Info.align =
DL.getABITypeAlign(MemTy);
2050 if (
I.hasMetadata(LLVMContext::MD_nontemporal))
2057 case Intrinsic::riscv_masked_atomicrmw_xchg:
2058 case Intrinsic::riscv_masked_atomicrmw_add:
2059 case Intrinsic::riscv_masked_atomicrmw_sub:
2060 case Intrinsic::riscv_masked_atomicrmw_nand:
2061 case Intrinsic::riscv_masked_atomicrmw_max:
2062 case Intrinsic::riscv_masked_atomicrmw_min:
2063 case Intrinsic::riscv_masked_atomicrmw_umax:
2064 case Intrinsic::riscv_masked_atomicrmw_umin:
2065 case Intrinsic::riscv_masked_cmpxchg:
2072 Info.memVT = MVT::i32;
2073 Info.ptrVal =
I.getArgOperand(0);
2075 Info.align =
Align(4);
2080 case Intrinsic::riscv_seg2_load_mask:
2081 case Intrinsic::riscv_seg3_load_mask:
2082 case Intrinsic::riscv_seg4_load_mask:
2083 case Intrinsic::riscv_seg5_load_mask:
2084 case Intrinsic::riscv_seg6_load_mask:
2085 case Intrinsic::riscv_seg7_load_mask:
2086 case Intrinsic::riscv_seg8_load_mask:
2087 case Intrinsic::riscv_sseg2_load_mask:
2088 case Intrinsic::riscv_sseg3_load_mask:
2089 case Intrinsic::riscv_sseg4_load_mask:
2090 case Intrinsic::riscv_sseg5_load_mask:
2091 case Intrinsic::riscv_sseg6_load_mask:
2092 case Intrinsic::riscv_sseg7_load_mask:
2093 case Intrinsic::riscv_sseg8_load_mask:
2094 SetRVVLoadStoreInfo( 0,
false,
2097 case Intrinsic::riscv_seg2_store_mask:
2098 case Intrinsic::riscv_seg3_store_mask:
2099 case Intrinsic::riscv_seg4_store_mask:
2100 case Intrinsic::riscv_seg5_store_mask:
2101 case Intrinsic::riscv_seg6_store_mask:
2102 case Intrinsic::riscv_seg7_store_mask:
2103 case Intrinsic::riscv_seg8_store_mask:
2105 SetRVVLoadStoreInfo(
I.arg_size() - 3,
2109 case Intrinsic::riscv_sseg2_store_mask:
2110 case Intrinsic::riscv_sseg3_store_mask:
2111 case Intrinsic::riscv_sseg4_store_mask:
2112 case Intrinsic::riscv_sseg5_store_mask:
2113 case Intrinsic::riscv_sseg6_store_mask:
2114 case Intrinsic::riscv_sseg7_store_mask:
2115 case Intrinsic::riscv_sseg8_store_mask:
2117 SetRVVLoadStoreInfo(
I.arg_size() - 4,
2121 case Intrinsic::riscv_vlm:
2122 SetRVVLoadStoreInfo( 0,
2127 case Intrinsic::riscv_vle:
2128 case Intrinsic::riscv_vle_mask:
2129 case Intrinsic::riscv_vleff:
2130 case Intrinsic::riscv_vleff_mask:
2131 SetRVVLoadStoreInfo( 1,
2136 case Intrinsic::riscv_vsm:
2137 case Intrinsic::riscv_vse:
2138 case Intrinsic::riscv_vse_mask:
2139 SetRVVLoadStoreInfo( 1,
2144 case Intrinsic::riscv_vlse:
2145 case Intrinsic::riscv_vlse_mask:
2146 case Intrinsic::riscv_vloxei:
2147 case Intrinsic::riscv_vloxei_mask:
2148 case Intrinsic::riscv_vluxei:
2149 case Intrinsic::riscv_vluxei_mask:
2150 SetRVVLoadStoreInfo( 1,
2154 case Intrinsic::riscv_vsse:
2155 case Intrinsic::riscv_vsse_mask:
2156 case Intrinsic::riscv_vsoxei:
2157 case Intrinsic::riscv_vsoxei_mask:
2158 case Intrinsic::riscv_vsuxei:
2159 case Intrinsic::riscv_vsuxei_mask:
2160 SetRVVLoadStoreInfo( 1,
2164 case Intrinsic::riscv_vlseg2:
2165 case Intrinsic::riscv_vlseg3:
2166 case Intrinsic::riscv_vlseg4:
2167 case Intrinsic::riscv_vlseg5:
2168 case Intrinsic::riscv_vlseg6:
2169 case Intrinsic::riscv_vlseg7:
2170 case Intrinsic::riscv_vlseg8:
2171 case Intrinsic::riscv_vlseg2ff:
2172 case Intrinsic::riscv_vlseg3ff:
2173 case Intrinsic::riscv_vlseg4ff:
2174 case Intrinsic::riscv_vlseg5ff:
2175 case Intrinsic::riscv_vlseg6ff:
2176 case Intrinsic::riscv_vlseg7ff:
2177 case Intrinsic::riscv_vlseg8ff:
2178 SetRVVLoadStoreInfo(
I.arg_size() - 3,
2182 case Intrinsic::riscv_vlseg2_mask:
2183 case Intrinsic::riscv_vlseg3_mask:
2184 case Intrinsic::riscv_vlseg4_mask:
2185 case Intrinsic::riscv_vlseg5_mask:
2186 case Intrinsic::riscv_vlseg6_mask:
2187 case Intrinsic::riscv_vlseg7_mask:
2188 case Intrinsic::riscv_vlseg8_mask:
2189 case Intrinsic::riscv_vlseg2ff_mask:
2190 case Intrinsic::riscv_vlseg3ff_mask:
2191 case Intrinsic::riscv_vlseg4ff_mask:
2192 case Intrinsic::riscv_vlseg5ff_mask:
2193 case Intrinsic::riscv_vlseg6ff_mask:
2194 case Intrinsic::riscv_vlseg7ff_mask:
2195 case Intrinsic::riscv_vlseg8ff_mask:
2196 SetRVVLoadStoreInfo(
I.arg_size() - 5,
2200 case Intrinsic::riscv_vlsseg2:
2201 case Intrinsic::riscv_vlsseg3:
2202 case Intrinsic::riscv_vlsseg4:
2203 case Intrinsic::riscv_vlsseg5:
2204 case Intrinsic::riscv_vlsseg6:
2205 case Intrinsic::riscv_vlsseg7:
2206 case Intrinsic::riscv_vlsseg8:
2207 case Intrinsic::riscv_vloxseg2:
2208 case Intrinsic::riscv_vloxseg3:
2209 case Intrinsic::riscv_vloxseg4:
2210 case Intrinsic::riscv_vloxseg5:
2211 case Intrinsic::riscv_vloxseg6:
2212 case Intrinsic::riscv_vloxseg7:
2213 case Intrinsic::riscv_vloxseg8:
2214 case Intrinsic::riscv_vluxseg2:
2215 case Intrinsic::riscv_vluxseg3:
2216 case Intrinsic::riscv_vluxseg4:
2217 case Intrinsic::riscv_vluxseg5:
2218 case Intrinsic::riscv_vluxseg6:
2219 case Intrinsic::riscv_vluxseg7:
2220 case Intrinsic::riscv_vluxseg8:
2221 SetRVVLoadStoreInfo(
I.arg_size() - 4,
2225 case Intrinsic::riscv_vlsseg2_mask:
2226 case Intrinsic::riscv_vlsseg3_mask:
2227 case Intrinsic::riscv_vlsseg4_mask:
2228 case Intrinsic::riscv_vlsseg5_mask:
2229 case Intrinsic::riscv_vlsseg6_mask:
2230 case Intrinsic::riscv_vlsseg7_mask:
2231 case Intrinsic::riscv_vlsseg8_mask:
2232 case Intrinsic::riscv_vloxseg2_mask:
2233 case Intrinsic::riscv_vloxseg3_mask:
2234 case Intrinsic::riscv_vloxseg4_mask:
2235 case Intrinsic::riscv_vloxseg5_mask:
2236 case Intrinsic::riscv_vloxseg6_mask:
2237 case Intrinsic::riscv_vloxseg7_mask:
2238 case Intrinsic::riscv_vloxseg8_mask:
2239 case Intrinsic::riscv_vluxseg2_mask:
2240 case Intrinsic::riscv_vluxseg3_mask:
2241 case Intrinsic::riscv_vluxseg4_mask:
2242 case Intrinsic::riscv_vluxseg5_mask:
2243 case Intrinsic::riscv_vluxseg6_mask:
2244 case Intrinsic::riscv_vluxseg7_mask:
2245 case Intrinsic::riscv_vluxseg8_mask:
2246 SetRVVLoadStoreInfo(
I.arg_size() - 6,
2250 case Intrinsic::riscv_vsseg2:
2251 case Intrinsic::riscv_vsseg3:
2252 case Intrinsic::riscv_vsseg4:
2253 case Intrinsic::riscv_vsseg5:
2254 case Intrinsic::riscv_vsseg6:
2255 case Intrinsic::riscv_vsseg7:
2256 case Intrinsic::riscv_vsseg8:
2257 SetRVVLoadStoreInfo(
I.arg_size() - 3,
2261 case Intrinsic::riscv_vsseg2_mask:
2262 case Intrinsic::riscv_vsseg3_mask:
2263 case Intrinsic::riscv_vsseg4_mask:
2264 case Intrinsic::riscv_vsseg5_mask:
2265 case Intrinsic::riscv_vsseg6_mask:
2266 case Intrinsic::riscv_vsseg7_mask:
2267 case Intrinsic::riscv_vsseg8_mask:
2268 SetRVVLoadStoreInfo(
I.arg_size() - 4,
2272 case Intrinsic::riscv_vssseg2:
2273 case Intrinsic::riscv_vssseg3:
2274 case Intrinsic::riscv_vssseg4:
2275 case Intrinsic::riscv_vssseg5:
2276 case Intrinsic::riscv_vssseg6:
2277 case Intrinsic::riscv_vssseg7:
2278 case Intrinsic::riscv_vssseg8:
2279 case Intrinsic::riscv_vsoxseg2:
2280 case Intrinsic::riscv_vsoxseg3:
2281 case Intrinsic::riscv_vsoxseg4:
2282 case Intrinsic::riscv_vsoxseg5:
2283 case Intrinsic::riscv_vsoxseg6:
2284 case Intrinsic::riscv_vsoxseg7:
2285 case Intrinsic::riscv_vsoxseg8:
2286 case Intrinsic::riscv_vsuxseg2:
2287 case Intrinsic::riscv_vsuxseg3:
2288 case Intrinsic::riscv_vsuxseg4:
2289 case Intrinsic::riscv_vsuxseg5:
2290 case Intrinsic::riscv_vsuxseg6:
2291 case Intrinsic::riscv_vsuxseg7:
2292 case Intrinsic::riscv_vsuxseg8:
2293 SetRVVLoadStoreInfo(
I.arg_size() - 4,
2297 case Intrinsic::riscv_vssseg2_mask:
2298 case Intrinsic::riscv_vssseg3_mask:
2299 case Intrinsic::riscv_vssseg4_mask:
2300 case Intrinsic::riscv_vssseg5_mask:
2301 case Intrinsic::riscv_vssseg6_mask:
2302 case Intrinsic::riscv_vssseg7_mask:
2303 case Intrinsic::riscv_vssseg8_mask:
2304 case Intrinsic::riscv_vsoxseg2_mask:
2305 case Intrinsic::riscv_vsoxseg3_mask:
2306 case Intrinsic::riscv_vsoxseg4_mask:
2307 case Intrinsic::riscv_vsoxseg5_mask:
2308 case Intrinsic::riscv_vsoxseg6_mask:
2309 case Intrinsic::riscv_vsoxseg7_mask:
2310 case Intrinsic::riscv_vsoxseg8_mask:
2311 case Intrinsic::riscv_vsuxseg2_mask:
2312 case Intrinsic::riscv_vsuxseg3_mask:
2313 case Intrinsic::riscv_vsuxseg4_mask:
2314 case Intrinsic::riscv_vsuxseg5_mask:
2315 case Intrinsic::riscv_vsuxseg6_mask:
2316 case Intrinsic::riscv_vsuxseg7_mask:
2317 case Intrinsic::riscv_vsuxseg8_mask:
2318 SetRVVLoadStoreInfo(
I.arg_size() - 5,
2322 case Intrinsic::riscv_sf_vlte8:
2323 case Intrinsic::riscv_sf_vlte16:
2324 case Intrinsic::riscv_sf_vlte32:
2325 case Intrinsic::riscv_sf_vlte64:
2327 Info.ptrVal =
I.getArgOperand(1);
2329 case Intrinsic::riscv_sf_vlte8:
2330 Info.memVT = MVT::i8;
2331 Info.align =
Align(1);
2333 case Intrinsic::riscv_sf_vlte16:
2334 Info.memVT = MVT::i16;
2335 Info.align =
Align(2);
2337 case Intrinsic::riscv_sf_vlte32:
2338 Info.memVT = MVT::i32;
2339 Info.align =
Align(4);
2341 case Intrinsic::riscv_sf_vlte64:
2342 Info.memVT = MVT::i64;
2343 Info.align =
Align(8);
2350 case Intrinsic::riscv_sf_vste8:
2351 case Intrinsic::riscv_sf_vste16:
2352 case Intrinsic::riscv_sf_vste32:
2353 case Intrinsic::riscv_sf_vste64:
2355 Info.ptrVal =
I.getArgOperand(1);
2357 case Intrinsic::riscv_sf_vste8:
2358 Info.memVT = MVT::i8;
2359 Info.align =
Align(1);
2361 case Intrinsic::riscv_sf_vste16:
2362 Info.memVT = MVT::i16;
2363 Info.align =
Align(2);
2365 case Intrinsic::riscv_sf_vste32:
2366 Info.memVT = MVT::i32;
2367 Info.align =
Align(4);
2369 case Intrinsic::riscv_sf_vste64:
2370 Info.memVT = MVT::i64;
2371 Info.align =
Align(8);
2429 if (Subtarget.is64Bit() || !SrcTy->isIntegerTy() || !DstTy->
isIntegerTy())
2431 unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
2433 return (SrcBits == 64 && DestBits == 32);
2444 return (SrcBits == 64 && DestBits == 32);
2450 if (Subtarget.hasVInstructions() &&
2455 if (SrcBits == DestBits * 2) {
2467 EVT MemVT = LD->getMemoryVT();
2468 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
2478 return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
2486 return Subtarget.hasCTZLike();
2490 return Subtarget.hasCLZLike();
2501 if (!Subtarget.hasBEXTILike())
2506 return !Mask->getValue().isSignedIntN(12) && Mask->getValue().isPowerOf2();
2510 EVT VT =
Y.getValueType();
2515 return (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
2520 EVT VT =
Y.getValueType();
2525 return Subtarget.hasStdExtZvkb();
2530 if (Subtarget.hasStdExtZbs())
2531 return X.getValueType().isScalarInteger();
2534 if (Subtarget.hasVendorXTHeadBs())
2535 return C !=
nullptr;
2537 return C &&
C->getAPIntValue().ule(10);
2541 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
2547 if (!VT.
isVector() || !Subtarget.hasVInstructions())
2558 assert(Ty->isIntegerTy());
2560 unsigned BitSize = Ty->getIntegerBitWidth();
2561 if (BitSize > Subtarget.getXLen())
2565 int64_t Val = Imm.getSExtValue();
2573 if (!Subtarget.enableUnalignedScalarMem())
2583 return Seq.
size() <= Subtarget.getMaxBuildIntsCost();
2589 unsigned OldShiftOpcode,
unsigned NewShiftOpcode,
2644 if (!Subtarget.hasStdExtZfa())
2647 bool IsSupportedVT =
false;
2648 if (VT == MVT::f16) {
2649 IsSupportedVT = Subtarget.hasStdExtZfh() || Subtarget.hasStdExtZvfh();
2650 }
else if (VT == MVT::f32) {
2651 IsSupportedVT =
true;
2652 }
else if (VT == MVT::f64) {
2653 assert(Subtarget.hasStdExtD() &&
"Expect D extension");
2654 IsSupportedVT =
true;
2664 bool ForCodeSize)
const {
2665 bool IsLegalVT =
false;
2667 IsLegalVT = Subtarget.hasStdExtZfhminOrZhinxmin();
2668 else if (VT == MVT::f32)
2669 IsLegalVT = Subtarget.hasStdExtFOrZfinx();
2670 else if (VT == MVT::f64)
2671 IsLegalVT = Subtarget.hasStdExtDOrZdinx();
2672 else if (VT == MVT::bf16)
2673 IsLegalVT = Subtarget.hasStdExtZfbfmin();
2689 return Imm.isZero();
2693 if (Imm.isNegZero())
2698 const int FmvCost = Subtarget.hasStdExtZfinx() ? 0 : 1;
2701 Subtarget.getXLen(), Subtarget);
2707 unsigned Index)
const {
2723 if (EltVT == MVT::i1)
2729 unsigned MinVLen = Subtarget.getRealMinVLen();
2736 if (Index + ResElts <= MinVLMAX && Index < 31)
2745 return (ResElts * 2) == SrcElts && Index == ResElts;
2753 if (VT == MVT::f16 && Subtarget.hasStdExtFOrZfinx() &&
2754 !Subtarget.hasStdExtZfhminOrZhinxmin())
2762 std::optional<MVT> RegisterVT)
const {
2764 if (VT == (Subtarget.is64Bit() ? MVT::i128 : MVT::i64) && RegisterVT &&
2765 *RegisterVT == MVT::Untyped)
2776 if (VT == MVT::f16 && Subtarget.hasStdExtFOrZfinx() &&
2777 !Subtarget.hasStdExtZfhminOrZhinxmin())
2796 !Subtarget.hasVendorXAndesPerf()) {
2802 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
2816 int64_t
C = RHSC->getSExtValue();
2826 if ((Subtarget.hasVendorXqcicm() || Subtarget.hasVendorXqcicli()) &&
2852 if ((Subtarget.hasVendorXqcicm() || Subtarget.hasVendorXqcicli()) &&
2887 if (VT.
SimpleTy >= MVT::riscv_nxv1i8x2 &&
2888 VT.
SimpleTy <= MVT::riscv_nxv1i8x8)
2890 if (VT.
SimpleTy >= MVT::riscv_nxv2i8x2 &&
2891 VT.
SimpleTy <= MVT::riscv_nxv2i8x8)
2893 if (VT.
SimpleTy >= MVT::riscv_nxv4i8x2 &&
2894 VT.
SimpleTy <= MVT::riscv_nxv4i8x8)
2896 if (VT.
SimpleTy >= MVT::riscv_nxv8i8x2 &&
2897 VT.
SimpleTy <= MVT::riscv_nxv8i8x8)
2899 if (VT.
SimpleTy >= MVT::riscv_nxv16i8x2 &&
2900 VT.
SimpleTy <= MVT::riscv_nxv16i8x4)
2902 if (VT.
SimpleTy == MVT::riscv_nxv32i8x2)
2912 switch (KnownSize) {
2940 return RISCV::VRRegClassID;
2942 return RISCV::VRM2RegClassID;
2944 return RISCV::VRM4RegClassID;
2946 return RISCV::VRM8RegClassID;
2954 static_assert(RISCV::sub_vrm1_7 == RISCV::sub_vrm1_0 + 7,
2955 "Unexpected subreg numbering");
2956 return RISCV::sub_vrm1_0 + Index;
2959 static_assert(RISCV::sub_vrm2_3 == RISCV::sub_vrm2_0 + 3,
2960 "Unexpected subreg numbering");
2961 return RISCV::sub_vrm2_0 + Index;
2964 static_assert(RISCV::sub_vrm4_1 == RISCV::sub_vrm4_0 + 1,
2965 "Unexpected subreg numbering");
2966 return RISCV::sub_vrm4_0 + Index;
2974 unsigned RegsPerField =
2977 switch (RegsPerField) {
2980 return RISCV::VRN2M1RegClassID;
2982 return RISCV::VRN3M1RegClassID;
2984 return RISCV::VRN4M1RegClassID;
2986 return RISCV::VRN5M1RegClassID;
2988 return RISCV::VRN6M1RegClassID;
2990 return RISCV::VRN7M1RegClassID;
2992 return RISCV::VRN8M1RegClassID;
2996 return RISCV::VRN2M2RegClassID;
2998 return RISCV::VRN3M2RegClassID;
3000 return RISCV::VRN4M2RegClassID;
3004 return RISCV::VRN2M4RegClassID;
3012 return RISCV::VRRegClassID;
3021std::pair<unsigned, unsigned>
3023 MVT VecVT,
MVT SubVecVT,
unsigned InsertExtractIdx,
3025 static_assert((RISCV::VRM8RegClassID > RISCV::VRM4RegClassID &&
3026 RISCV::VRM4RegClassID > RISCV::VRM2RegClassID &&
3027 RISCV::VRM2RegClassID > RISCV::VRRegClassID),
3028 "Register classes not ordered");
3035 if (VecRegClassID == SubRegClassID)
3036 return {RISCV::NoSubRegister, 0};
3039 "Only allow scalable vector subvector.");
3041 "Invalid vector tuple insert/extract for vector and subvector with "
3052 unsigned SubRegIdx = RISCV::NoSubRegister;
3053 for (
const unsigned RCID :
3054 {RISCV::VRM4RegClassID, RISCV::VRM2RegClassID, RISCV::VRRegClassID})
3055 if (VecRegClassID > RCID && SubRegClassID <= RCID) {
3059 SubRegIdx =
TRI->composeSubRegIndices(SubRegIdx,
3064 return {SubRegIdx, InsertExtractIdx};
3069bool RISCVTargetLowering::mergeStoresAfterLegalization(
EVT VT)
const {
3079 return Subtarget.is64Bit() ? Subtarget.hasVInstructionsI64() :
true;
3083 return Subtarget.hasVInstructions();
3085 return Subtarget.hasVInstructionsI64();
3087 return Subtarget.hasVInstructionsF16Minimal();
3089 return Subtarget.hasVInstructionsBF16Minimal();
3091 return Subtarget.hasVInstructionsF32();
3093 return Subtarget.hasVInstructionsF64();
3107 "Unexpected opcode");
3109 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
3111 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
3114 return Op.getOperand(
II->VLOperand + 1 + HasChain);
3188bool RISCVTargetLowering::useRVVForFixedLengthVectorVT(
MVT VT)
const {
3189 return ::useRVVForFixedLengthVectorVT(VT, Subtarget);
3198 "Expected legal fixed length vector!");
3201 unsigned MaxELen = Subtarget.
getELen();
3235 return ::getContainerForFixedLengthVector(*
this, VT,
getSubtarget());
3242 "Expected to convert into a scalable vector!");
3243 assert(V.getValueType().isFixedLengthVector() &&
3244 "Expected a fixed length vector operand!");
3253 "Expected to convert into a fixed length vector!");
3254 assert(V.getValueType().isScalableVector() &&
3255 "Expected a scalable vector operand!");
3274 return DAG.
getNode(RISCVISD::VMSET_VL,
DL, MaskVT, VL);
3277static std::pair<SDValue, SDValue>
3286static std::pair<SDValue, SDValue>
3299static std::pair<SDValue, SDValue>
3316std::pair<unsigned, unsigned>
3324 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
3328 unsigned VectorBitsMin = Subtarget.getRealMinVLen();
3332 return std::make_pair(MinVLMAX, MaxVLMAX);
3344 EVT VT,
unsigned DefinedValues)
const {
3353 unsigned DLenFactor = Subtarget.getDLenFactor();
3358 std::tie(LMul, Fractional) =
3361 Cost = LMul <= DLenFactor ? (DLenFactor / LMul) : 1;
3363 Cost = (LMul * DLenFactor);
3377 bool Log2CostModel =
3379 if (Log2CostModel && LMULCost.isValid()) {
3380 unsigned Log =
Log2_64(LMULCost.getValue());
3382 return LMULCost * Log;
3384 return LMULCost * LMULCost;
3415 Op.getValueType() == MVT::bf16) {
3416 bool IsStrict =
Op->isStrictFPOpcode();
3421 {Op.getOperand(0), Op.getOperand(1)});
3423 {
Op.getValueType(), MVT::Other},
3429 DAG.
getNode(
Op.getOpcode(),
DL, MVT::f32,
Op.getOperand(0)),
3444 MVT DstVT =
Op.getSimpleValueType();
3453 Src.getValueType() == MVT::bf16) {
3459 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
3460 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
3461 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
3468 Opc,
DL, DstVT, Src,
3471 if (
Opc == RISCVISD::FCVT_WU_RV64)
3482 MVT SrcVT = Src.getSimpleValueType();
3488 if (SatVT != DstEltVT)
3491 MVT DstContainerVT = DstVT;
3492 MVT SrcContainerVT = SrcVT;
3498 "Expected same element count");
3507 {Src, Src, DAG.getCondCode(ISD::SETNE),
3508 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
3512 if (DstEltSize > (2 * SrcEltSize)) {
3515 Src = DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, InterVT, Src, Mask, VL);
3518 MVT CvtContainerVT = DstContainerVT;
3519 MVT CvtEltVT = DstEltVT;
3520 if (SrcEltSize > (2 * DstEltSize)) {
3526 IsSigned ? RISCVISD::VFCVT_RTZ_X_F_VL : RISCVISD::VFCVT_RTZ_XU_F_VL;
3529 while (CvtContainerVT != DstContainerVT) {
3533 unsigned ClipOpc = IsSigned ? RISCVISD::TRUNCATE_VECTOR_VL_SSAT
3534 : RISCVISD::TRUNCATE_VECTOR_VL_USAT;
3535 Res = DAG.
getNode(ClipOpc,
DL, CvtContainerVT, Res, Mask, VL);
3539 RISCVISD::VMV_V_X_VL,
DL, DstContainerVT, DAG.
getUNDEF(DstContainerVT),
3541 Res = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, DstContainerVT, IsNan, SplatZero,
3542 Res, DAG.
getUNDEF(DstContainerVT), VL);
3552 bool IsStrict =
Op->isStrictFPOpcode();
3553 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
3563 {
Op.getOperand(0), SrcVal});
3564 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
3565 {Ext.getValue(1), Ext.getValue(0)});
3579 case ISD::VP_FROUNDEVEN:
3583 case ISD::VP_FROUNDTOZERO:
3587 case ISD::VP_FFLOOR:
3599 case ISD::VP_FROUND:
3609 case ISD::VP_LLRINT:
3623 MVT VT =
Op.getSimpleValueType();
3633 MVT ContainerVT = VT;
3640 if (
Op->isVPOpcode()) {
3641 Mask =
Op.getOperand(1);
3645 VL =
Op.getOperand(2);
3651 SDValue Abs = DAG.
getNode(RISCVISD::FABS_VL,
DL, ContainerVT, Src, Mask, VL);
3664 DAG.
getUNDEF(ContainerVT), MaxValNode, VL);
3669 DAG.
getNode(RISCVISD::SETCC_VL,
DL, SetccVT,
3678 switch (
Op.getOpcode()) {
3686 case ISD::VP_FFLOOR:
3689 case ISD::VP_FROUND:
3690 case ISD::VP_FROUNDEVEN:
3691 case ISD::VP_FROUNDTOZERO: {
3694 Truncated = DAG.
getNode(RISCVISD::VFCVT_RM_X_F_VL,
DL, IntVT, Src, Mask,
3699 Truncated = DAG.
getNode(RISCVISD::VFCVT_RTZ_X_F_VL,
DL, IntVT, Src,
3703 case ISD::VP_FNEARBYINT:
3704 Truncated = DAG.
getNode(RISCVISD::VFROUND_NOEXCEPT_VL,
DL, ContainerVT, Src,
3710 if (Truncated.
getOpcode() != RISCVISD::VFROUND_NOEXCEPT_VL)
3711 Truncated = DAG.
getNode(RISCVISD::SINT_TO_FP_VL,
DL, ContainerVT, Truncated,
3715 Truncated = DAG.
getNode(RISCVISD::FCOPYSIGN_VL,
DL, ContainerVT, Truncated,
3716 Src, Src, Mask, VL);
3731 MVT VT =
Op.getSimpleValueType();
3735 MVT ContainerVT = VT;
3747 MVT MaskVT = Mask.getSimpleValueType();
3750 {Chain, Src, Src, DAG.getCondCode(ISD::SETUNE),
3751 DAG.getUNDEF(MaskVT), Mask, VL});
3753 Src = DAG.
getNode(RISCVISD::STRICT_FADD_VL,
DL,
3755 {Chain, Src, Src, Src, Unorder, VL});
3759 SDValue Abs = DAG.
getNode(RISCVISD::FABS_VL,
DL, ContainerVT, Src, Mask, VL);
3772 DAG.
getUNDEF(ContainerVT), MaxValNode, VL);
3776 RISCVISD::SETCC_VL,
DL, MaskVT,
3784 switch (
Op.getOpcode()) {
3794 RISCVISD::STRICT_VFCVT_RM_X_F_VL,
DL, DAG.
getVTList(IntVT, MVT::Other),
3795 {Chain, Src, Mask, DAG.getTargetConstant(FRM, DL, XLenVT), VL});
3800 DAG.
getNode(RISCVISD::STRICT_VFCVT_RTZ_X_F_VL,
DL,
3801 DAG.
getVTList(IntVT, MVT::Other), Chain, Src, Mask, VL);
3804 Truncated = DAG.
getNode(RISCVISD::STRICT_VFROUND_NOEXCEPT_VL,
DL,
3805 DAG.
getVTList(ContainerVT, MVT::Other), Chain, Src,
3813 Truncated = DAG.
getNode(RISCVISD::STRICT_SINT_TO_FP_VL,
DL,
3814 DAG.
getVTList(ContainerVT, MVT::Other), Chain,
3815 Truncated, Mask, VL);
3820 Truncated = DAG.
getNode(RISCVISD::FCOPYSIGN_VL,
DL, ContainerVT, Truncated,
3821 Src, Src, Mask, VL);
3831 MVT VT =
Op.getSimpleValueType();
3852 return DAG.
getNode(RISCVISD::FROUND,
DL, VT, Src, MaxValNode,
3860 MVT DstVT =
Op.getSimpleValueType();
3862 MVT SrcVT = Src.getSimpleValueType();
3867 MVT DstContainerVT = DstVT;
3868 MVT SrcContainerVT = SrcVT;
3880 if (SrcElemType == MVT::f16 || SrcElemType == MVT::bf16) {
3882 Src = DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, F32VT, Src, Mask, VL);
3886 DAG.
getNode(RISCVISD::VFCVT_RM_X_F_VL,
DL, DstContainerVT, Src, Mask,
3906 return DAG.
getNode(RISCVISD::VSLIDEDOWN_VL,
DL, VT,
Ops);
3918 return DAG.
getNode(RISCVISD::VSLIDEUP_VL,
DL, VT,
Ops);
3943 return std::nullopt;
3961 unsigned EltSizeInBits) {
3964 return std::nullopt;
3965 bool IsInteger =
Op.getValueType().isInteger();
3967 std::optional<unsigned> SeqStepDenom;
3968 std::optional<APInt> SeqStepNum;
3969 std::optional<APInt> SeqAddend;
3970 std::optional<std::pair<APInt, unsigned>> PrevElt;
3971 assert(EltSizeInBits >=
Op.getValueType().getScalarSizeInBits());
3976 const unsigned OpSize =
Op.getScalarValueSizeInBits();
3977 for (
auto [Idx, Elt] :
enumerate(
Op->op_values())) {
3978 if (Elt.isUndef()) {
3979 Elts[Idx] = std::nullopt;
3983 Elts[Idx] = Elt->getAsAPIntVal().trunc(OpSize).zext(EltSizeInBits);
3988 return std::nullopt;
3989 Elts[Idx] = *ExactInteger;
3993 for (
auto [Idx, Elt] :
enumerate(Elts)) {
4002 unsigned IdxDiff = Idx - PrevElt->second;
4003 APInt ValDiff = *Elt - PrevElt->first;
4011 int64_t Remainder = ValDiff.
srem(IdxDiff);
4016 return std::nullopt;
4017 ValDiff = ValDiff.
sdiv(IdxDiff);
4022 SeqStepNum = ValDiff;
4023 else if (ValDiff != SeqStepNum)
4024 return std::nullopt;
4027 SeqStepDenom = IdxDiff;
4028 else if (IdxDiff != *SeqStepDenom)
4029 return std::nullopt;
4033 if (!PrevElt || PrevElt->first != *Elt)
4034 PrevElt = std::make_pair(*Elt, Idx);
4038 if (!SeqStepNum || !SeqStepDenom)
4039 return std::nullopt;
4043 for (
auto [Idx, Elt] :
enumerate(Elts)) {
4047 (
APInt(EltSizeInBits, Idx,
false,
true) *
4049 .sdiv(*SeqStepDenom);
4051 APInt Addend = *Elt - ExpectedVal;
4054 else if (Addend != SeqAddend)
4055 return std::nullopt;
4058 assert(SeqAddend &&
"Must have an addend if we have a step");
4060 return VIDSequence{SeqStepNum->getSExtValue(), *SeqStepDenom,
4061 SeqAddend->getSExtValue()};
4076 if (EltTy == MVT::i1 ||
4079 MVT SrcVT = Src.getSimpleValueType();
4095 MVT ContainerVT = VT;
4099 MVT SrcContainerVT = SrcVT;
4114 SDValue Gather = DAG.
getNode(RISCVISD::VRGATHER_VX_VL,
DL, ContainerVT, Src,
4115 Idx, DAG.
getUNDEF(ContainerVT), Mask, VL);
4123 MVT VT =
Op.getSimpleValueType();
4132 int64_t StepNumerator = SimpleVID->StepNumerator;
4133 unsigned StepDenominator = SimpleVID->StepDenominator;
4134 int64_t Addend = SimpleVID->Addend;
4136 assert(StepNumerator != 0 &&
"Invalid step");
4137 bool Negate =
false;
4138 int64_t SplatStepVal = StepNumerator;
4142 if (StepNumerator != 1 && StepNumerator !=
INT64_MIN &&
4144 Negate = StepNumerator < 0;
4146 SplatStepVal =
Log2_64(std::abs(StepNumerator));
4156 (SplatStepVal >= 0 || StepDenominator == 1) &&
isInt<32>(Addend)) {
4159 MVT VIDContainerVT =
4167 if ((StepOpcode ==
ISD::MUL && SplatStepVal != 1) ||
4168 (StepOpcode ==
ISD::SHL && SplatStepVal != 0)) {
4170 VID = DAG.
getNode(StepOpcode,
DL, VIDVT, VID, SplatStep);
4172 if (StepDenominator != 1) {
4177 if (Addend != 0 || Negate) {
4203 MVT VT =
Op.getSimpleValueType();
4212 unsigned NumElts =
Op.getNumOperands();
4215 unsigned MostCommonCount = 0;
4217 unsigned NumUndefElts =
4225 unsigned NumScalarLoads = 0;
4231 unsigned &
Count = ValueCounts[V];
4234 NumScalarLoads += !CFP->isExactlyValue(+0.0);
4239 if (++
Count >= MostCommonCount) {
4241 MostCommonCount =
Count;
4245 assert(DominantValue &&
"Not expecting an all-undef BUILD_VECTOR");
4246 unsigned NumDefElts = NumElts - NumUndefElts;
4247 unsigned DominantValueCountThreshold = NumDefElts <= 2 ? 0 : NumDefElts - 2;
4253 ((MostCommonCount > DominantValueCountThreshold) ||
4265 if (
SDValue LastOp =
Op->getOperand(
Op->getNumOperands() - 1);
4266 !LastOp.isUndef() && ValueCounts[LastOp] == 1 &&
4267 LastOp != DominantValue) {
4270 VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1DOWN_VL : RISCVISD::VSLIDE1DOWN_VL;
4276 Processed.
insert(LastOp);
4282 if (V.isUndef() || !Processed.
insert(V).second)
4284 if (ValueCounts[V] == 1) {
4292 return DAG.getConstant(V == V1, DL, XLenVT);
4308 MVT VT =
Op.getSimpleValueType();
4317 unsigned NumElts =
Op.getNumOperands();
4338 unsigned NumViaIntegerBits = std::clamp(NumElts, 8u, Subtarget.
getXLen());
4339 NumViaIntegerBits = std::min(NumViaIntegerBits, Subtarget.
getELen());
4347 unsigned IntegerViaVecElts =
divideCeil(NumElts, NumViaIntegerBits);
4348 MVT IntegerViaVecVT =
4353 unsigned BitPos = 0, IntegerEltIdx = 0;
4356 for (
unsigned I = 0;
I < NumElts;) {
4358 bool BitValue = !V.isUndef() && V->getAsZExtVal();
4359 Bits |= ((
uint64_t)BitValue << BitPos);
4365 if (
I % NumViaIntegerBits == 0 ||
I == NumElts) {
4366 if (NumViaIntegerBits <= 32)
4369 Elts[IntegerEltIdx] = Elt;
4378 if (NumElts < NumViaIntegerBits) {
4382 assert(IntegerViaVecVT == MVT::v1i8 &&
"Unexpected mask vector type");
4397 : RISCVISD::VMV_V_X_VL;
4417 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32) &&
4418 "Unexpected sequence type");
4422 unsigned ViaVecLen =
4430 const auto &SeqV =
OpIdx.value();
4431 if (!SeqV.isUndef())
4433 ((SeqV->getAsZExtVal() & EltMask) << (
OpIdx.index() * EltBitSize));
4439 if (ViaIntVT == MVT::i32)
4462 BV->getRepeatedSequence(Sequence) &&
4463 (Sequence.size() * EltBitSize) <= Subtarget.
getELen()) {
4464 unsigned SeqLen = Sequence.size();
4466 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32 ||
4467 ViaIntVT == MVT::i64) &&
4468 "Unexpected sequence type");
4473 const unsigned RequiredVL = NumElts / SeqLen;
4474 const unsigned ViaVecLen =
4476 NumElts : RequiredVL;
4479 unsigned EltIdx = 0;
4484 for (
const auto &SeqV : Sequence) {
4485 if (!SeqV.isUndef())
4487 ((SeqV->getAsZExtVal() & EltMask) << (EltIdx * EltBitSize));
4494 if (ViaIntVT == MVT::i32)
4501 (!Subtarget.
is64Bit() && ViaIntVT == MVT::i64)) &&
4502 "Unexpected bitcast sequence");
4506 MVT ViaContainerVT =
4509 DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ViaContainerVT,
4513 if (ViaVecLen != RequiredVL)
4532 Source, DAG, Subtarget);
4533 SDValue Res = DAG.
getNode(RISCVISD::VSEXT_VL,
DL, ContainerVT, Source, Mask, VL);
4552 return RISCV::PACKH;
4554 return Subtarget.
is64Bit() ? RISCV::PACKW : RISCV::PACK;
4569 MVT VT =
Op.getSimpleValueType();
4577 if (!Subtarget.hasStdExtZbb() || !Subtarget.hasStdExtZba())
4582 if (ElemSizeInBits >= std::min(Subtarget.
getELen(), Subtarget.
getXLen()) ||
4596 if (Subtarget.hasStdExtZbkb())
4601 ElemDL, XLenVT,
A,
B),
4613 NewOperands.
reserve(NumElts / 2);
4615 NewOperands.
push_back(pack(
Op.getOperand(i),
Op.getOperand(i + 1)));
4625 MVT VT =
Op.getSimpleValueType();
4633 if (Subtarget.isRV32() && Subtarget.hasStdExtP()) {
4634 if (VT != MVT::v4i8)
4647 DAG.
getNode(RISCVISD::PPAIRE_DB,
DL, {MVT::v4i8, MVT::v4i8},
4648 {Val0, Val2, Val1, Val3});
4654 RISCV::PACK,
DL, MVT::i32,
4655 {DAG.getNode(ISD::BITCAST, DL, MVT::i32, PPairDB.getValue(0)),
4656 DAG.getNode(ISD::BITCAST, DL, MVT::i32, PPairDB.getValue(1))}),
4663 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
4669 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4670 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin())) {
4680 NewOps[
I] = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Elem);
4730 [](
const SDUse &U) { return U.get().isUndef(); })) {
4771 auto OneVRegOfOps =
ArrayRef(BuildVectorOps).slice(i, ElemsPerVReg);
4775 unsigned InsertIdx = (i / ElemsPerVReg) * NumOpElts;
4797 unsigned NumUndefElts =
4799 unsigned NumDefElts = NumElts - NumUndefElts;
4800 if (NumDefElts >= 8 && NumDefElts > NumElts / 2 &&
4807 for (
const auto &[Idx, U] :
enumerate(
Op->ops())) {
4809 if (Idx < NumElts / 2) {
4816 bool SelectMaskVal = (Idx < NumElts / 2);
4819 assert(SubVecAOps.
size() == NumElts && SubVecBOps.
size() == NumElts &&
4820 MaskVals.
size() == NumElts);
4855 unsigned UndefCount = 0;
4862 LinearBudget -= PerSlideCost;
4865 LinearBudget -= PerSlideCost;
4868 LinearBudget -= PerSlideCost;
4871 if (LinearBudget < 0)
4876 "Illegal type which will result in reserved encoding");
4892 bool SlideUp =
false;
4917 if (EVecEltVT != ContainerEltVT)
4938 std::reverse(Operands.
begin(), Operands.
end());
4966 Vec = getVSlide(ContainerVT, DAG.
getUNDEF(ContainerVT), Vec,
Offset, Mask,
4973 Opcode = SlideUp ? RISCVISD::VFSLIDE1UP_VL : RISCVISD::VFSLIDE1DOWN_VL;
4975 Opcode = SlideUp ? RISCVISD::VSLIDE1UP_VL : RISCVISD::VSLIDE1DOWN_VL;
4984 Vec = getVSlide(ContainerVT, DAG.
getUNDEF(ContainerVT), Vec,
Offset, Mask,
5000 if ((LoC >> 31) == HiC)
5001 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
5013 auto InterVec = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, InterVT,
5022 Hi.getConstantOperandVal(1) == 31)
5023 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
5028 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
5031 return DAG.
getNode(RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL,
DL, VT, Passthru,
Lo,
5041 assert(Scalar.getValueType() == MVT::i64 &&
"Unexpected VT!");
5053 bool HasPassthru = Passthru && !Passthru.
isUndef();
5054 if (!HasPassthru && !Passthru)
5061 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
5063 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
5064 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
5065 Scalar = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Scalar);
5074 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL, VT, Passthru, Scalar, VL);
5078 if (Scalar.getValueType().bitsLE(XLenVT)) {
5085 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
5086 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru, Scalar, VL);
5089 assert(XLenVT == MVT::i32 && Scalar.getValueType() == MVT::i64 &&
5090 "Unexpected scalar for splat lowering!");
5093 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, VT, Passthru,
5119 MVT ExtractedContainerVT = ExtractedVT;
5122 DAG, ExtractedContainerVT, Subtarget);
5124 ExtractedVal, DAG, Subtarget);
5126 if (ExtractedContainerVT.
bitsLE(VT))
5138 if (!Scalar.getValueType().bitsLE(XLenVT))
5141 VT,
DL, DAG, Subtarget);
5149 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
5190 Src && Src.
getValueType().getVectorNumElements() == (NumElts * 2))
5207 !Subtarget.hasVendorXRivosVizip())
5210 int Size = Mask.size();
5212 assert(
Size == (
int)NumElts &&
"Unexpected mask size");
5218 EvenSrc = StartIndexes[0];
5219 OddSrc = StartIndexes[1];
5222 if (EvenSrc != 0 && OddSrc != 0)
5232 int HalfNumElts = NumElts / 2;
5233 return ((EvenSrc % HalfNumElts) == 0) && ((OddSrc % HalfNumElts) == 0);
5238 std::array<std::pair<int, int>, 2> &SrcInfo) {
5243 if (SrcInfo[0].second == 0 && SrcInfo[1].second == 0)
5247 if ((SrcInfo[0].second > 0 && SrcInfo[1].second < 0) ||
5248 SrcInfo[1].second == 0)
5250 assert(SrcInfo[0].first != -1 &&
"Must find one slide");
5258 if (SrcInfo[1].first == -1)
5260 return SrcInfo[0].second < 0 && SrcInfo[1].second > 0 &&
5261 SrcInfo[1].second - SrcInfo[0].second == (int)NumElts;
5266 bool RequiredPolarity) {
5267 int NumElts = Mask.size();
5268 for (
const auto &[Idx, M] :
enumerate(Mask)) {
5271 int Src = M >= NumElts;
5272 int Diff = (int)Idx - (M % NumElts);
5273 bool C = Src == SrcInfo[1].first && Diff == SrcInfo[1].second;
5274 assert(
C != (Src == SrcInfo[0].first && Diff == SrcInfo[0].second) &&
5275 "Must match exactly one of the two slides");
5276 if (RequiredPolarity != (
C == (Idx / Factor) % 2))
5287static bool isZipEven(
const std::array<std::pair<int, int>, 2> &SrcInfo,
5289 Factor = SrcInfo[1].second;
5291 Mask.size() % Factor == 0 &&
5302static bool isZipOdd(
const std::array<std::pair<int, int>, 2> &SrcInfo,
5304 Factor = -SrcInfo[1].second;
5306 Mask.size() % Factor == 0 &&
5319 ElementCount SrcEC = Src.getValueType().getVectorElementCount();
5326 unsigned Shift = Index * EltBits;
5351 std::optional<int> SplatIdx;
5353 if (M == -1 ||
I == (
unsigned)M)
5355 if (SplatIdx && *SplatIdx != M)
5364 for (
int MaskIndex : Mask) {
5365 bool SelectMaskVal = MaskIndex == *SplatIdx;
5368 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
5393 auto findNonEXTRACT_SUBVECTORParent =
5394 [](
SDValue Parent) -> std::pair<SDValue, uint64_t> {
5399 Parent.getOperand(0).getSimpleValueType().isFixedLengthVector()) {
5400 Offset += Parent.getConstantOperandVal(1);
5401 Parent = Parent.getOperand(0);
5403 return std::make_pair(Parent,
Offset);
5406 auto [V1Src, V1IndexOffset] = findNonEXTRACT_SUBVECTORParent(V1);
5407 auto [V2Src, V2IndexOffset] = findNonEXTRACT_SUBVECTORParent(V2);
5416 for (
size_t i = 0; i != NewMask.
size(); ++i) {
5417 if (NewMask[i] == -1)
5420 if (
static_cast<size_t>(NewMask[i]) < NewMask.
size()) {
5421 NewMask[i] = NewMask[i] + V1IndexOffset;
5425 NewMask[i] = NewMask[i] - NewMask.
size() + V2IndexOffset;
5431 if (NewMask[0] <= 0)
5435 for (
unsigned i = 1; i != NewMask.
size(); ++i)
5436 if (NewMask[i - 1] + 1 != NewMask[i])
5440 MVT SrcVT = Src.getSimpleValueType();
5469 int NumSubElts, Index;
5474 bool OpsSwapped = Mask[Index] < (int)NumElts;
5475 SDValue InPlace = OpsSwapped ? V2 : V1;
5476 SDValue ToInsert = OpsSwapped ? V1 : V2;
5487 if (NumSubElts + Index >= (
int)NumElts)
5498 Res = DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, ContainerVT, InPlace, ToInsert,
5501 Res =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, InPlace, ToInsert,
5524 unsigned NumElts = Mask.size();
5527 int Lane = Mask[Idx];
5532 bool SecondOp =
false;
5533 if ((
unsigned)Lane < NumElts) {
5534 OrigLane = V1Mask[Lane];
5536 OrigLane = V2Mask[Lane - NumElts];
5542 if ((
unsigned)OrigLane >= NumElts)
5545 OrigLane += NumElts;
5546 NewMask[Idx] = OrigLane;
5563 bool OpsSwapped =
false;
5578 const unsigned E = Mask.size() - ((
Offset > 0) ?
Offset : 0);
5579 for (
unsigned i = S; i !=
E; ++i)
5580 if (Mask[i] >= 0 && (
unsigned)Mask[i] !=
Base + i +
Offset)
5586 bool IsVSlidedown = isSlideMask(Mask, OpsSwapped ? 0 : NumElts, 1);
5587 if (!IsVSlidedown && !isSlideMask(Mask, OpsSwapped ? 0 : NumElts, -1))
5590 const int InsertIdx = Mask[IsVSlidedown ? (NumElts - 1) : 0];
5592 if (InsertIdx < 0 || InsertIdx / NumElts != (
unsigned)OpsSwapped)
5609 IsVSlidedown ? RISCVISD::VSLIDE1DOWN_VL : RISCVISD::VSLIDE1UP_VL,
DL,
5615 auto OpCode = IsVSlidedown ?
5616 (VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1DOWN_VL : RISCVISD::VSLIDE1DOWN_VL) :
5617 (VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1UP_VL : RISCVISD::VSLIDE1UP_VL);
5620 auto Vec = DAG.
getNode(OpCode,
DL, ContainerVT,
5623 Splat, TrueMask, VL);
5635 for (
unsigned i = 0; i < Mask.size(); i++)
5636 LaneIsUndef[i % Factor] &= (Mask[i] == -1);
5639 for (
unsigned i = 0; i < Factor; i++) {
5650 for (
unsigned i = 0; i < Mask.size() / Factor; i++) {
5651 unsigned j = i * Factor + Index;
5652 if (Mask[j] != -1 && (
unsigned)Mask[j] != i)
5661 assert(RISCVISD::RI_VZIPEVEN_VL ==
Opc || RISCVISD::RI_VZIPODD_VL ==
Opc ||
5662 RISCVISD::RI_VZIP2A_VL ==
Opc || RISCVISD::RI_VZIP2B_VL ==
Opc ||
5663 RISCVISD::RI_VUNZIP2A_VL ==
Opc || RISCVISD::RI_VUNZIP2B_VL ==
Opc);
5671 MVT ContainerVT = IntVT;
5678 MVT InnerVT = ContainerVT;
5682 (RISCVISD::RI_VUNZIP2A_VL ==
Opc || RISCVISD::RI_VUNZIP2B_VL ==
Opc)) {
5694 if (InnerVT.
bitsLT(ContainerVT))
5709 MVT VT = V.getSimpleValueType();
5724 EC.multiplyCoefficientBy(Factor));
5743 MVT VecContainerVT = VecVT;
5760 MVT WideContainerVT = WideVT;
5766 EvenV = DAG.
getBitcast(VecContainerVT, EvenV);
5773 if (Subtarget.hasStdExtZvbb()) {
5777 Interleaved = DAG.
getNode(RISCVISD::VWSLL_VL,
DL, WideContainerVT, OddV,
5778 OffsetVec, Passthru, Mask, VL);
5779 Interleaved = DAG.
getNode(RISCVISD::VWADDU_W_VL,
DL, WideContainerVT,
5780 Interleaved, EvenV, Passthru, Mask, VL);
5787 Interleaved = DAG.
getNode(RISCVISD::VWADDU_VL,
DL, WideContainerVT, EvenV,
5788 OddV, Passthru, Mask, VL);
5794 OddV, AllOnesVec, Passthru, Mask, VL);
5801 Interleaved = DAG.
getNode(RISCVISD::ADD_VL,
DL, WideContainerVT,
5802 Interleaved, OddsMul, Passthru, Mask, VL);
5809 Interleaved = DAG.
getBitcast(ResultContainerVT, Interleaved);
5855 if (ViaEltSize > NumElts)
5863 if (ViaEltSize > NumElts)
5869 if (ViaEltSize > NumElts)
5876 MVT &RotateVT,
unsigned &RotateAmt) {
5879 unsigned NumSubElts;
5881 NumElts, NumSubElts, RotateAmt))
5884 NumElts / NumSubElts);
5952 unsigned NumOfSrcRegs = NumElts / NumOpElts;
5953 unsigned NumOfDestRegs = NumElts / NumOpElts;
5962 Mask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs,
5964 [&](
ArrayRef<int> SrcSubMask,
unsigned SrcVecIdx,
unsigned DstVecIdx) {
5965 Operands.
emplace_back().emplace_back(SrcVecIdx, UINT_MAX,
5968 [&](
ArrayRef<int> SrcSubMask,
unsigned Idx1,
unsigned Idx2,
bool NewReg) {
5973 assert(Operands.
size() == NumOfDestRegs &&
"Whole vector must be processed");
5978 unsigned NumShuffles = std::accumulate(
5979 Operands.
begin(), Operands.
end(), 0u,
5985 for (const auto &P : Data) {
5986 unsigned Idx2 = std::get<1>(P);
5987 ArrayRef<int> Mask = std::get<2>(P);
5988 if (Idx2 != UINT_MAX)
5990 else if (ShuffleVectorInst::isIdentityMask(Mask, Mask.size()))
5995 if ((NumOfDestRegs > 2 && NumShuffles > NumOfDestRegs) ||
5996 (NumOfDestRegs <= 2 && NumShuffles >= 4))
5998 auto ExtractValue = [&, &DAG = DAG](
SDValue SrcVec,
unsigned ExtractIdx) {
5999 SDValue SubVec = DAG.getExtractSubvector(
DL, M1VT, SrcVec, ExtractIdx);
6003 auto PerformShuffle = [&, &DAG = DAG](
SDValue SubVec1,
SDValue SubVec2,
6005 SDValue SubVec = DAG.getVectorShuffle(OneRegVT,
DL, SubVec1, SubVec2, Mask);
6008 SDValue Vec = DAG.getUNDEF(ContainerVT);
6014 const auto &[Idx1, Idx2,
_] =
Data[
I];
6022 V = ExtractValue(Idx1 >= NumOfSrcRegs ? V2 : V1,
6023 (Idx1 % NumOfSrcRegs) * NumOpElts);
6024 if (Idx2 != UINT_MAX) {
6027 V = ExtractValue(Idx2 >= NumOfSrcRegs ? V2 : V1,
6028 (Idx2 % NumOfSrcRegs) * NumOpElts);
6032 for (
const auto &[Idx1, Idx2, Mask] :
Data) {
6034 SDValue V2 = Idx2 == UINT_MAX ? V1 : Values.
at(Idx2);
6035 V = PerformShuffle(V1, V2, Mask);
6039 unsigned InsertIdx =
I * NumOpElts;
6041 Vec = DAG.getInsertSubvector(
DL, Vec, V, InsertIdx);
6051 bool SawUndef =
false;
6052 for (
const auto &[Idx, M] :
enumerate(Mask)) {
6059 if (Idx > (
unsigned)M)
6092 for (
int Idx : Mask) {
6095 unsigned SrcIdx = Idx % Mask.size();
6096 int Src = (
uint32_t)Idx < Mask.size() ? 0 : 1;
6097 if (Srcs[SrcIdx] == -1)
6100 else if (Srcs[SrcIdx] != Src)
6106 for (
int Lane : Srcs) {
6119 for (
unsigned I = 0;
I < Mask.size();
I++) {
6123 NewMask[
I] = Mask[
I] % Mask.size();
6137 if ((M / Span) != (
int)(
I / Span))
6139 int SpanIdx =
I % Span;
6149 return all_of(Mask, [&](
const auto &Idx) {
return Idx == -1 || Idx < Span; });
6161 int SpanIdx =
I % Span;
6162 if (Mask[SpanIdx] != M)
6176 MVT VT =
Op.getSimpleValueType();
6184 if (ElementSize > 32)
6207 MVT VT =
Op.getSimpleValueType();
6235 auto [TrueMask, VL] = TrueMaskVL;
6250 V.getOperand(0).getSimpleValueType().getVectorNumElements();
6251 V = V.getOperand(
Offset / OpElements);
6281 MVT SplatVT = ContainerVT;
6284 if (SVT == MVT::bf16 ||
6285 (SVT == MVT::f16 && !Subtarget.hasStdExtZfh())) {
6294 V = DAG.
getLoad(SVT,
DL, Ld->getChain(), NewAddr,
6295 Ld->getPointerInfo().getWithOffset(
Offset),
6296 Ld->getBaseAlign(), Ld->getMemOperand()->
getFlags());
6299 Ld->getPointerInfo().getWithOffset(
Offset), SVT,
6301 Ld->getMemOperand()->getFlags());
6305 : RISCVISD::VMV_V_X_VL;
6313 assert(Lane < (
int)NumElts &&
"Unexpected lane!");
6316 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
6338 if (Subtarget.hasStdExtZvkb())
6354 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
6355 for (
unsigned Factor = 2; Factor <= MaxFactor; Factor <<= 1) {
6358 1 <
count_if(Mask, [](
int Idx) {
return Idx != -1; })) {
6362 [&Mask](
int Idx) {
return Idx < (int)Mask.size(); }) &&
6363 1 <
count_if(Mask, [&Mask](
int Idx) {
6364 return Idx >= (int)Mask.size();
6394 if (Subtarget.hasVendorXRivosVizip() &&
6396 1 <
count_if(Mask, [](
int Idx) {
return Idx != -1; })) {
6398 Index == 0 ? RISCVISD::RI_VUNZIP2A_VL : RISCVISD::RI_VUNZIP2B_VL;
6414 [&Mask](
int Idx) {
return Idx < (int)Mask.size(); }) &&
6416 [&Mask](
int Idx) {
return Idx >= (int)Mask.size(); })) {
6420 if (NumElts < MinVLMAX) {
6444 int EvenSrc, OddSrc;
6454 bool LaneIsUndef[2] = {
true,
true};
6455 for (
const auto &[Idx, M] :
enumerate(Mask))
6456 LaneIsUndef[Idx % 2] &= (M == -1);
6458 int Size = Mask.size();
6460 if (LaneIsUndef[0]) {
6463 assert(EvenSrc >= 0 &&
"Undef source?");
6464 EvenV = (EvenSrc /
Size) == 0 ? V1 : V2;
6468 if (LaneIsUndef[1]) {
6471 assert(OddSrc >= 0 &&
"Undef source?");
6472 OddV = (OddSrc /
Size) == 0 ? V1 : V2;
6478 if (Subtarget.hasVendorXRivosVizip()) {
6481 return lowerVZIP(RISCVISD::RI_VZIP2A_VL, EvenV, OddV,
DL, DAG, Subtarget);
6492 std::array<std::pair<int, int>, 2> SrcInfo;
6499 auto GetSourceFor = [&](
const std::pair<int, int> &Info) {
6500 int SrcIdx = Info.first;
6501 assert(SrcIdx == 0 || SrcIdx == 1);
6502 SDValue &Src = Sources[SrcIdx];
6504 SDValue SrcV = SrcIdx == 0 ? V1 : V2;
6509 auto GetSlide = [&](
const std::pair<int, int> &Src,
SDValue Mask,
6511 auto [TrueMask, VL] = TrueMaskVL;
6512 SDValue SrcV = GetSourceFor(Src);
6513 int SlideAmt = Src.second;
6514 if (SlideAmt == 0) {
6516 assert(Mask == TrueMask);
6523 return getVSlideup(DAG, Subtarget,
DL, ContainerVT, Passthru, SrcV,
6528 if (SrcInfo[1].first == -1) {
6530 Res = GetSlide(SrcInfo[0], TrueMask, Res);
6534 if (Subtarget.hasVendorXRivosVizip()) {
6535 bool TryWiden =
false;
6539 SDValue Src1 = SrcInfo[0].first == 0 ? V1 : V2;
6540 SDValue Src2 = SrcInfo[1].first == 0 ? V1 : V2;
6541 return lowerVZIP(RISCVISD::RI_VZIPEVEN_VL, Src1, Src2,
DL, DAG,
6546 if (
isZipOdd(SrcInfo, Mask, Factor)) {
6548 SDValue Src1 = SrcInfo[1].first == 0 ? V1 : V2;
6549 SDValue Src2 = SrcInfo[0].first == 0 ? V1 : V2;
6550 return lowerVZIP(RISCVISD::RI_VZIPODD_VL, Src1, Src2,
DL, DAG,
6568 for (
const auto &[Idx, M] :
enumerate(Mask)) {
6570 (SrcInfo[1].second > 0 && Idx < (
unsigned)SrcInfo[1].second)) {
6574 int Src = M >= (int)NumElts;
6575 int Diff = (int)Idx - (M % NumElts);
6576 bool C = Src == SrcInfo[1].first && Diff == SrcInfo[1].second;
6577 assert(
C ^ (Src == SrcInfo[0].first && Diff == SrcInfo[0].second) &&
6578 "Must match exactly one of the two slides");
6581 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
6588 Res = GetSlide(SrcInfo[0], TrueMask, Res);
6589 Res = GetSlide(SrcInfo[1], SelectMask, Res);
6594 assert(!V1.
isUndef() &&
"Unexpected shuffle canonicalization");
6609 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
6610 for (
unsigned Factor = 4; Factor <= MaxFactor; Factor <<= 1) {
6625 if (NumElts > MinVLMAX) {
6626 unsigned MaxIdx = 0;
6630 MaxIdx = std::max(std::max((
unsigned)
I, (
unsigned)M), MaxIdx);
6632 unsigned NewNumElts =
6634 if (NewNumElts != NumElts) {
6638 Mask.take_front(NewNumElts));
6655 for (
auto Idx : Mask) {
6658 assert(Idx >= 0 && (
unsigned)Idx < NumElts);
6668 any_of(Mask, [&](
const auto &Idx) {
return Idx > 255; })) {
6678 unsigned GatherVVOpc = RISCVISD::VRGATHER_VV_VL;
6684 GatherVVOpc = RISCVISD::VRGATHEREI16_VV_VL;
6693 GatherVVOpc = RISCVISD::VRGATHEREI16_VV_VL;
6697 MVT IndexContainerVT =
6702 for (
int MaskIndex : Mask) {
6703 bool IsLHSIndex = MaskIndex < (int)NumElts && MaskIndex >= 0;
6713 if (NumElts <= MinVLMAX) {
6715 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
6721 auto [InnerTrueMask, InnerVL] =
6733 for (
int i = 0; i <
N; i++) {
6737 DAG.
getNode(GatherVVOpc,
DL, M1VT, SubV1, SubIndex,
6738 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6755 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6757 for (
int i = 0; i <
N; i++)
6773 for (
int i = 0; i <
N; i++) {
6776 DAG.
getUNDEF(IndexContainerVT), LHSIndices,
6777 SlideAmt, TrueMask, VL);
6781 DAG.
getNode(GatherVVOpc,
DL, M1VT, SubV1, SubIndex,
6782 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6792 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
6802 for (
int MaskIndex : Mask) {
6803 bool IsLHSOrUndefIndex = MaskIndex < (int)NumElts;
6804 ShuffleMaskLHS.
push_back(IsLHSOrUndefIndex && MaskIndex >= 0
6806 ShuffleMaskRHS.
push_back(IsLHSOrUndefIndex ? -1 : (MaskIndex - NumElts));
6837 for (
int MaskIndex : Mask) {
6838 bool SelectMaskVal = (MaskIndex < (int)NumElts) ^ !SwapOps;
6842 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
6853 if (!
isTypeLegal(VT) || !Subtarget.hasVInstructions())
6860 const unsigned NumElts = M.size();
6867 std::array<std::pair<int, int>, 2> SrcInfo;
6878RISCVTargetLowering::lowerCTLZ_CTTZ_ZERO_UNDEF(
SDValue Op,
6880 MVT VT =
Op.getSimpleValueType();
6884 MVT ContainerVT = VT;
6887 if (
Op->isVPOpcode()) {
6888 Mask =
Op.getOperand(1);
6892 VL =
Op.getOperand(2);
6898 MVT FloatEltVT = (EltSize >= 32) ? MVT::f64 :
MVT::f32;
6900 FloatEltVT = MVT::f32;
6907 "Expected legal float type!");
6914 }
else if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF) {
6917 Src = DAG.
getNode(ISD::VP_AND,
DL, VT, Src, Neg, Mask, VL);
6922 if (FloatVT.
bitsGT(VT)) {
6923 if (
Op->isVPOpcode())
6924 FloatVal = DAG.
getNode(ISD::VP_UINT_TO_FP,
DL, FloatVT, Src, Mask, VL);
6933 if (!
Op->isVPOpcode())
6937 MVT ContainerFloatVT =
6939 FloatVal = DAG.
getNode(RISCVISD::VFCVT_RM_F_XU_VL,
DL, ContainerFloatVT,
6940 Src, Mask, RTZRM, VL);
6947 unsigned ShiftAmt = FloatEltVT == MVT::f64 ? 52 : 23;
6951 if (
Op->isVPOpcode()) {
6960 else if (IntVT.
bitsGT(VT))
6965 unsigned ExponentBias = FloatEltVT == MVT::f64 ? 1023 : 127;
6970 if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF)
6971 return DAG.
getNode(ISD::VP_SUB,
DL, VT, Exp,
6976 unsigned Adjust = ExponentBias + (EltSize - 1);
6978 if (
Op->isVPOpcode())
6988 else if (
Op.getOpcode() == ISD::VP_CTLZ)
6989 Res = DAG.
getNode(ISD::VP_UMIN,
DL, VT, Res,
6997 MVT XLenVT = Subtarget.getXLenVT();
6999 MVT SrcVT =
Source.getSimpleValueType();
7008 SrcVT = ContainerVT;
7020 SDValue Res = DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Source, Mask, EVL);
7021 if (
Op->getOpcode() == ISD::VP_CTTZ_ELTS_ZERO_UNDEF)
7039 assert(Load &&
Load->getMemoryVT().isVector() &&
"Expected vector load");
7042 Load->getMemoryVT(),
7043 *
Load->getMemOperand()))
7047 MVT VT =
Op.getSimpleValueType();
7049 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
7050 "Unexpected unaligned RVV load type");
7054 "Expecting equally-sized RVV vector types to be legal");
7056 Load->getPointerInfo(),
Load->getBaseAlign(),
7057 Load->getMemOperand()->getFlags());
7068 assert(Store &&
Store->getValue().getValueType().isVector() &&
7069 "Expected vector store");
7072 Store->getMemoryVT(),
7073 *
Store->getMemOperand()))
7080 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
7081 "Unexpected unaligned RVV store type");
7085 "Expecting equally-sized RVV vector types to be legal");
7086 StoredVal = DAG.
getBitcast(NewVT, StoredVal);
7088 Store->getPointerInfo(),
Store->getBaseAlign(),
7089 Store->getMemOperand()->getFlags());
7099 assert(Load &&
Load->getMemoryVT().isVector() &&
"Expected vector load");
7102 Load->getMemoryVT(),
7103 *
Load->getMemOperand()))
7113 MVT VT =
Op.getSimpleValueType();
7115 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
7116 "Unexpected unaligned RVV load type");
7120 "Expecting equally-sized RVV vector types to be legal");
7129 Load->getPointerInfo(),
Load->getBaseAlign(),
7130 Load->getMemOperand()->getFlags(), AAMDNodes());
7141 assert(Store &&
Store->getValue().getValueType().isVector() &&
7142 "Expected vector store");
7145 Store->getMemoryVT(),
7146 *
Store->getMemOperand()))
7159 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
7160 "Unexpected unaligned RVV store type");
7164 "Expecting equally-sized RVV vector types to be legal");
7170 StoredVal = DAG.
getBitcast(NewVT, StoredVal);
7175 Store->getPointerInfo(),
Store->getMemOperand()->getFlags(),
Size,
7176 Store->getBaseAlign());
7187 assert(
Op.getValueType() == MVT::i64 &&
"Unexpected VT");
7216 unsigned ShiftAmt, AddOpc;
7227 MVT VT =
Op.getSimpleValueType();
7231 bool Negate =
false;
7235 if (Index < 0 &&
Imm.isNegative()) {
7258 unsigned IsData =
Op.getConstantOperandVal(4);
7261 if (Subtarget.hasVendorXMIPSCBOP() && !IsData)
7262 return Op.getOperand(0);
7274 if (Subtarget.hasStdExtZtso()) {
7298 MVT VT =
Op.getSimpleValueType();
7299 MVT XLenVT = Subtarget.getXLenVT();
7300 unsigned Check =
Op.getConstantOperandVal(1);
7301 unsigned TDCMask = 0;
7329 MVT VT0 =
Op.getOperand(0).getSimpleValueType();
7334 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
7336 VL =
Op.getOperand(3);
7339 VL,
Op->getFlags());
7354 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
7356 MVT MaskContainerVT =
7359 VL =
Op.getOperand(3);
7363 SDValue FPCLASS = DAG.
getNode(RISCVISD::FCLASS_VL,
DL, ContainerDstVT, Op0,
7364 Mask, VL,
Op->getFlags());
7366 TDCMaskV = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerDstVT,
7367 DAG.
getUNDEF(ContainerDstVT), TDCMaskV, VL);
7370 DAG.
getNode(RISCVISD::SETCC_VL,
DL, ContainerVT,
7376 TDCMaskV, DAG.
getUNDEF(ContainerDstVT), Mask, VL);
7379 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerDstVT,
7380 DAG.
getUNDEF(ContainerDstVT), SplatZero, VL);
7400 MVT VT =
Op.getSimpleValueType();
7434 MVT ContainerVT = VT;
7442 if (
Op->isVPOpcode()) {
7443 Mask =
Op.getOperand(2);
7447 VL =
Op.getOperand(3);
7454 SDValue XIsNonNan = DAG.
getNode(RISCVISD::SETCC_VL,
DL, Mask.getValueType(),
7455 {X, X, DAG.getCondCode(ISD::SETOEQ),
7456 DAG.getUNDEF(ContainerVT), Mask, VL});
7457 NewY = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, XIsNonNan,
Y,
X,
7463 SDValue YIsNonNan = DAG.
getNode(RISCVISD::SETCC_VL,
DL, Mask.getValueType(),
7464 {Y, Y, DAG.getCondCode(ISD::SETOEQ),
7465 DAG.getUNDEF(ContainerVT), Mask, VL});
7466 NewX = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, YIsNonNan,
X,
Y,
7472 ? RISCVISD::VFMAX_VL
7473 : RISCVISD::VFMIN_VL;
7475 DAG.
getUNDEF(ContainerVT), Mask, VL);
7485 "Wrong opcode for lowering FABS or FNEG.");
7488 MVT VT =
Op.getSimpleValueType();
7489 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
7493 DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT,
Op.getOperand(0));
7496 Mask = Mask.sext(Subtarget.
getXLen());
7501 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, Logic);
7509 MVT VT =
Op.getSimpleValueType();
7510 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
7520 if (SignSize == Subtarget.
getXLen())
7524 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Sign);
7526 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, XLenVT, Sign);
7528 assert(XLenVT == MVT::i32 &&
"Unexpected type");
7531 return DAG.
getNode(RISCVISD::SplitF64,
DL, {MVT::i32, MVT::i32}, Sign)
7561 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, CopiedSign);
7566#define OP_CASE(NODE) \
7568 return RISCVISD::NODE##_VL;
7569#define VP_CASE(NODE) \
7570 case ISD::VP_##NODE: \
7571 return RISCVISD::NODE##_VL;
7573 switch (
Op.getOpcode()) {
7654 case ISD::VP_CTLZ_ZERO_UNDEF:
7655 return RISCVISD::CTLZ_VL;
7657 case ISD::VP_CTTZ_ZERO_UNDEF:
7658 return RISCVISD::CTTZ_VL;
7661 return RISCVISD::VFMADD_VL;
7663 return RISCVISD::STRICT_VFMADD_VL;
7666 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7667 return RISCVISD::VMAND_VL;
7668 return RISCVISD::AND_VL;
7671 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7672 return RISCVISD::VMOR_VL;
7673 return RISCVISD::OR_VL;
7676 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7677 return RISCVISD::VMXOR_VL;
7678 return RISCVISD::XOR_VL;
7681 return RISCVISD::VZEXT_VL;
7683 return RISCVISD::VSEXT_VL;
7685 return RISCVISD::SETCC_VL;
7687 return RISCVISD::VMERGE_VL;
7688 case ISD::VP_SELECT:
7690 return RISCVISD::VMERGE_VL;
7692 return RISCVISD::SRA_VL;
7694 return RISCVISD::SRL_VL;
7696 return RISCVISD::FSQRT_VL;
7697 case ISD::VP_SIGN_EXTEND:
7698 return RISCVISD::VSEXT_VL;
7699 case ISD::VP_ZERO_EXTEND:
7700 return RISCVISD::VZEXT_VL;
7701 case ISD::VP_FP_TO_SINT:
7702 return RISCVISD::VFCVT_RTZ_X_F_VL;
7703 case ISD::VP_FP_TO_UINT:
7704 return RISCVISD::VFCVT_RTZ_XU_F_VL;
7707 case ISD::VP_FMINNUM:
7708 return RISCVISD::VFMIN_VL;
7711 case ISD::VP_FMAXNUM:
7712 return RISCVISD::VFMAX_VL;
7716 case ISD::VP_LLRINT:
7717 return RISCVISD::VFCVT_RM_X_F_VL;
7726 return (
Op.getValueType() == MVT::nxv32f16 &&
7729 (
Op.getValueType() == MVT::nxv32bf16 &&
7743 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7744 if (!
Op.getOperand(j).getValueType().isVector()) {
7745 LoOperands[j] =
Op.getOperand(j);
7746 HiOperands[j] =
Op.getOperand(j);
7749 std::tie(LoOperands[j], HiOperands[j]) =
7754 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
7756 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
7769 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7771 std::tie(LoOperands[j], HiOperands[j]) =
7775 if (!
Op.getOperand(j).getValueType().isVector()) {
7776 LoOperands[j] =
Op.getOperand(j);
7777 HiOperands[j] =
Op.getOperand(j);
7780 std::tie(LoOperands[j], HiOperands[j]) =
7785 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
7787 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
7797 auto [EVLLo, EVLHi] =
7798 DAG.
SplitEVL(
Op.getOperand(3),
Op.getOperand(1).getValueType(),
DL);
7802 {Op.getOperand(0), Lo, MaskLo, EVLLo},
Op->getFlags());
7804 {ResLo, Hi, MaskHi, EVLHi},
Op->getFlags());
7821 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7822 if (!
Op.getOperand(j).getValueType().isVector()) {
7823 LoOperands[j] =
Op.getOperand(j);
7824 HiOperands[j] =
Op.getOperand(j);
7827 std::tie(LoOperands[j], HiOperands[j]) =
7832 DAG.
getNode(
Op.getOpcode(),
DL, LoVTs, LoOperands,
Op->getFlags());
7835 DAG.
getNode(
Op.getOpcode(),
DL, HiVTs, HiOperands,
Op->getFlags());
7843RISCVTargetLowering::lowerXAndesBfHCvtBFloat16Load(
SDValue Op,
7845 assert(Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh() &&
7846 "Unexpected bfloat16 load lowering");
7850 EVT MemVT =
LD->getMemoryVT();
7855 LD->getMemOperand());
7863 DAG.
getNode(RISCVISD::NDS_FMV_BF16_X,
DL, MVT::bf16, OrSixteenOne);
7868RISCVTargetLowering::lowerXAndesBfHCvtBFloat16Store(
SDValue Op,
7870 assert(Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh() &&
7871 "Unexpected bfloat16 store lowering");
7876 Subtarget.getXLenVT(),
ST->getValue());
7878 ST->getChain(),
DL, FMV,
ST->getBasePtr(),
7880 ST->getMemOperand());
7885 switch (
Op.getOpcode()) {
7888 "Unimplemented RISCVTargetLowering::LowerOperation Case");
7894 return lowerGlobalAddress(
Op, DAG);
7896 return lowerBlockAddress(
Op, DAG);
7898 return lowerConstantPool(
Op, DAG);
7900 return lowerJumpTable(
Op, DAG);
7902 return lowerGlobalTLSAddress(
Op, DAG);
7906 return lowerConstantFP(
Op, DAG);
7908 return lowerSELECT(
Op, DAG);
7910 return lowerBRCOND(
Op, DAG);
7912 return lowerVASTART(
Op, DAG);
7914 return lowerFRAMEADDR(
Op, DAG);
7916 return lowerRETURNADDR(
Op, DAG);
7918 return lowerShiftLeftParts(
Op, DAG);
7920 return lowerShiftRightParts(
Op, DAG,
true);
7922 return lowerShiftRightParts(
Op, DAG,
false);
7925 if (
Op.getValueType().isFixedLengthVector()) {
7926 assert(Subtarget.hasStdExtZvkb());
7927 return lowerToScalableOp(
Op, DAG);
7929 assert(Subtarget.hasVendorXTHeadBb() &&
7930 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
7931 "Unexpected custom legalization");
7938 EVT VT =
Op.getValueType();
7941 MVT XLenVT = Subtarget.getXLenVT();
7942 if (Op0VT == MVT::i16 &&
7943 ((VT == MVT::f16 && Subtarget.hasStdExtZfhminOrZhinxmin()) ||
7944 (VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
7946 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, NewOp0);
7948 if (VT == MVT::f32 && Op0VT == MVT::i32 && Subtarget.is64Bit() &&
7949 Subtarget.hasStdExtFOrZfinx()) {
7951 return DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, NewOp0);
7953 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit() &&
7954 Subtarget.hasStdExtDOrZdinx()) {
7957 return DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64,
Lo,
Hi);
7960 if (Subtarget.hasStdExtP()) {
7962 (VT == MVT::i32 && (Op0VT == MVT::v4i8 || Op0VT == MVT::v2i16)) ||
7963 (Op0VT == MVT::i32 && (VT == MVT::v4i8 || VT == MVT::v2i16));
7965 (VT == MVT::i64 && (Op0VT == MVT::v8i8 || Op0VT == MVT::v4i16 ||
7966 Op0VT == MVT::v2i32)) ||
7967 (Op0VT == MVT::i64 &&
7968 (VT == MVT::v8i8 || VT == MVT::v4i16 || VT == MVT::v2i32));
7969 if (Is32BitCast || Is64BitCast)
7982 "Unexpected types");
8014 return LowerINTRINSIC_WO_CHAIN(
Op, DAG);
8016 return LowerINTRINSIC_W_CHAIN(
Op, DAG);
8018 return LowerINTRINSIC_VOID(
Op, DAG);
8020 return LowerIS_FPCLASS(
Op, DAG);
8022 MVT VT =
Op.getSimpleValueType();
8024 assert(Subtarget.hasStdExtZvbb());
8025 return lowerToScalableOp(
Op, DAG);
8028 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected custom legalization");
8032 return DAG.
getNode(RISCVISD::BREV8,
DL, VT, BSwap);
8038 if (!
Op.getSimpleValueType().isVector())
8040 return lowerVectorTruncLike(
Op, DAG);
8043 if (
Op.getOperand(0).getValueType().isVector() &&
8044 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
8045 return lowerVectorMaskExt(
Op, DAG, 1);
8046 if (
Op.getValueType().isScalableVector())
8048 return lowerToScalableOp(
Op, DAG);
8050 if (
Op.getOperand(0).getValueType().isVector() &&
8051 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
8052 return lowerVectorMaskExt(
Op, DAG, -1);
8053 if (
Op.getValueType().isScalableVector())
8055 return lowerToScalableOp(
Op, DAG);
8057 return lowerSPLAT_VECTOR_PARTS(
Op, DAG);
8059 return lowerINSERT_VECTOR_ELT(
Op, DAG);
8061 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
8063 MVT VT =
Op.getSimpleValueType();
8071 MVT ContainerVT = VT;
8078 V = DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL, ContainerVT,
8079 DAG.
getUNDEF(ContainerVT), Scalar, VL);
8082 V = DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, ContainerVT,
8083 DAG.
getUNDEF(ContainerVT), Scalar, VL);
8090 MVT XLenVT = Subtarget.getXLenVT();
8091 MVT VT =
Op.getSimpleValueType();
8110 }
else if (
Log2 > 3) {
8114 }
else if ((Val % 8) == 0) {
8132 if (
Op.getValueType() == MVT::f16 && Subtarget.is64Bit() &&
8133 Op.getOperand(1).getValueType() == MVT::i32) {
8150 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
8153 return lowerStrictFPExtendOrRoundLike(
Op, DAG);
8156 if (
Op.getValueType().isVector() &&
8157 ((
Op.getValueType().getScalarType() == MVT::f16 &&
8158 (Subtarget.hasVInstructionsF16Minimal() &&
8159 !Subtarget.hasVInstructionsF16())) ||
8160 Op.getValueType().getScalarType() == MVT::bf16)) {
8176 Op1.getValueType().isVector() &&
8177 ((Op1.getValueType().getScalarType() == MVT::f16 &&
8178 (Subtarget.hasVInstructionsF16Minimal() &&
8179 !Subtarget.hasVInstructionsF16())) ||
8180 Op1.getValueType().getScalarType() == MVT::bf16)) {
8186 Op1.getValueType().getVectorElementCount());
8189 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), WidenVec);
8199 MVT VT =
Op.getSimpleValueType();
8202 bool IsStrict =
Op->isStrictFPOpcode();
8203 SDValue Src =
Op.getOperand(0 + IsStrict);
8204 MVT SrcVT = Src.getSimpleValueType();
8215 "Unexpected vector element types");
8219 if (EltSize > (2 * SrcEltSize)) {
8231 Op.getOperand(0), Ext);
8235 assert(SrcEltVT == MVT::f16 &&
"Unexpected FP_TO_[US]INT lowering");
8240 auto [FExt, Chain] =
8242 return DAG.
getNode(
Op.getOpcode(),
DL,
Op->getVTList(), Chain, FExt);
8249 if (SrcEltSize > (2 * EltSize)) {
8252 assert(EltVT == MVT::f16 &&
"Unexpected [US]_TO_FP lowering");
8257 Op.getOperand(0), Src);
8272 Op.getOperand(0), Src);
8290 unsigned RVVOpc = 0;
8291 switch (
Op.getOpcode()) {
8295 RVVOpc = RISCVISD::VFCVT_RTZ_X_F_VL;
8298 RVVOpc = RISCVISD::VFCVT_RTZ_XU_F_VL;
8301 RVVOpc = RISCVISD::SINT_TO_FP_VL;
8304 RVVOpc = RISCVISD::UINT_TO_FP_VL;
8307 RVVOpc = RISCVISD::STRICT_VFCVT_RTZ_X_F_VL;
8310 RVVOpc = RISCVISD::STRICT_VFCVT_RTZ_XU_F_VL;
8313 RVVOpc = RISCVISD::STRICT_SINT_TO_FP_VL;
8316 RVVOpc = RISCVISD::STRICT_UINT_TO_FP_VL;
8323 "Expected same element count");
8330 Op.getOperand(0), Src, Mask, VL);
8334 Src = DAG.
getNode(RVVOpc,
DL, ContainerVT, Src, Mask, VL);
8343 assert(!Subtarget.isSoftFPABI() &&
"Unexpected custom legalization");
8349 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
8350 if (Subtarget.is64Bit())
8351 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Res);
8355 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalization");
8356 MVT VT =
Op.getSimpleValueType();
8361 SDValue Res = Subtarget.is64Bit()
8362 ? DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32,
Op)
8373 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalisation");
8376 bool IsStrict =
Op->isStrictFPOpcode();
8377 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
8381 std::tie(Res, Chain) =
8382 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
8383 if (Subtarget.is64Bit())
8384 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Res);
8394 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalisation");
8397 bool IsStrict =
Op->isStrictFPOpcode();
8398 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
8400 SDValue Arg = Subtarget.is64Bit()
8401 ? DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, Op0)
8404 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
8405 CallOptions,
DL, Chain);
8424 if (
Op.getValueType().isVector())
8426 assert(
Op.getOperand(0).getValueType() == MVT::f16 &&
8427 "Unexpected custom legalisation");
8430 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), Ext);
8436 assert(
Op.getOperand(1).getValueType() == MVT::f16 &&
8437 "Unexpected custom legalisation");
8440 {
Op.getOperand(0),
Op.getOperand(1)});
8441 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
8442 {Ext.getValue(1), Ext.getValue(0)});
8449 return lowerVECREDUCE(
Op, DAG);
8453 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
8454 return lowerVectorMaskVecReduction(
Op, DAG,
false);
8455 return lowerVECREDUCE(
Op, DAG);
8462 return lowerFPVECREDUCE(
Op, DAG);
8463 case ISD::VP_REDUCE_ADD:
8464 case ISD::VP_REDUCE_UMAX:
8465 case ISD::VP_REDUCE_SMAX:
8466 case ISD::VP_REDUCE_UMIN:
8467 case ISD::VP_REDUCE_SMIN:
8468 case ISD::VP_REDUCE_FADD:
8469 case ISD::VP_REDUCE_SEQ_FADD:
8470 case ISD::VP_REDUCE_FMIN:
8471 case ISD::VP_REDUCE_FMAX:
8472 case ISD::VP_REDUCE_FMINIMUM:
8473 case ISD::VP_REDUCE_FMAXIMUM:
8476 return lowerVPREDUCE(
Op, DAG);
8477 case ISD::VP_REDUCE_AND:
8478 case ISD::VP_REDUCE_OR:
8479 case ISD::VP_REDUCE_XOR:
8480 if (
Op.getOperand(1).getValueType().getVectorElementType() == MVT::i1)
8481 return lowerVectorMaskVecReduction(
Op, DAG,
true);
8482 return lowerVPREDUCE(
Op, DAG);
8483 case ISD::VP_CTTZ_ELTS:
8484 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
8485 return lowerVPCttzElements(
Op, DAG);
8489 DAG.
getUNDEF(ContainerVT), DAG, Subtarget);
8492 return lowerINSERT_SUBVECTOR(
Op, DAG);
8494 return lowerEXTRACT_SUBVECTOR(
Op, DAG);
8496 return lowerVECTOR_DEINTERLEAVE(
Op, DAG);
8498 return lowerVECTOR_INTERLEAVE(
Op, DAG);
8500 return lowerSTEP_VECTOR(
Op, DAG);
8502 return lowerVECTOR_REVERSE(
Op, DAG);
8505 return lowerVECTOR_SPLICE(
Op, DAG);
8507 MVT VT =
Op.getSimpleValueType();
8509 if (!Subtarget.is64Bit() && EltVT == MVT::i64)
8514 MVT VT =
Op.getSimpleValueType();
8516 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
8517 EltVT == MVT::bf16) {
8520 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
8521 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
8522 Elt = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, Subtarget.getXLenVT(),
8531 if (EltVT == MVT::i1)
8532 return lowerVectorMaskSplat(
Op, DAG);
8541 MVT VT =
Op.getSimpleValueType();
8542 MVT ContainerVT = VT;
8554 if (
Op.getNumOperands() > 2 &&
8558 size_t HalfNumOps =
Op.getNumOperands() / 2;
8560 Op->ops().take_front(HalfNumOps));
8562 Op->ops().drop_front(HalfNumOps));
8566 unsigned NumOpElts =
8567 Op.getOperand(0).getSimpleValueType().getVectorMinNumElements();
8580 EVT VT = Load->getValueType(0);
8581 if (VT == MVT::f64) {
8582 assert(Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
8583 !Subtarget.is64Bit() &&
"Unexpected custom legalisation");
8587 SDValue BasePtr = Load->getBasePtr();
8588 SDValue Chain = Load->getChain();
8591 DAG.
getLoad(MVT::i32,
DL, Chain, BasePtr, Load->getPointerInfo(),
8592 Load->getBaseAlign(), Load->getMemOperand()->getFlags());
8595 MVT::i32,
DL, Chain, BasePtr, Load->getPointerInfo().getWithOffset(4),
8596 Load->getBaseAlign(), Load->getMemOperand()->getFlags());
8601 if (!Subtarget.isLittleEndian())
8608 if (VT == MVT::bf16)
8609 return lowerXAndesBfHCvtBFloat16Load(
Op, DAG);
8614 MVT XLenVT = Subtarget.getXLenVT();
8617 unsigned NumElts = Sz / (NF * 8);
8618 int Log2LMUL =
Log2_64(NumElts) - 3;
8621 Flag.setNoUnsignedWrap(
true);
8623 SDValue BasePtr = Load->getBasePtr();
8631 for (
unsigned i = 0; i < NF; ++i) {
8636 Ret = DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VT, Ret, LoadVal,
8644 if (
auto V = expandUnalignedRVVLoad(
Op, DAG))
8646 if (
Op.getValueType().isFixedLengthVector())
8647 return lowerFixedLengthVectorLoadToRVV(
Op, DAG);
8652 SDValue StoredVal = Store->getValue();
8654 if (Subtarget.hasStdExtP()) {
8655 if (VT == MVT::v2i16 || VT == MVT::v4i8) {
8659 DAG.
getStore(Store->getChain(),
DL, Cast, Store->getBasePtr(),
8660 Store->getPointerInfo(), Store->getBaseAlign(),
8661 Store->getMemOperand()->getFlags());
8665 if (VT == MVT::f64) {
8666 assert(Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
8667 !Subtarget.is64Bit() &&
"Unexpected custom legalisation");
8671 SDValue BasePtr = Store->getBasePtr();
8672 SDValue Chain = Store->getChain();
8674 DAG.
getVTList(MVT::i32, MVT::i32), StoredVal);
8680 if (!Subtarget.isLittleEndian())
8684 Chain,
DL,
Lo, BasePtr, Store->getPointerInfo(),
8685 Store->getBaseAlign(), Store->getMemOperand()->getFlags());
8688 Chain,
DL,
Hi, BasePtr, Store->getPointerInfo().getWithOffset(4),
8689 Store->getBaseAlign(), Store->getMemOperand()->getFlags());
8692 if (VT == MVT::i64) {
8693 assert(Subtarget.hasStdExtZilsd() && !Subtarget.is64Bit() &&
8694 "Unexpected custom legalisation");
8695 if (Store->isTruncatingStore())
8698 if (Store->getAlign() < Subtarget.getZilsdAlign())
8709 {Store->getChain(), Lo, Hi, Store->getBasePtr()}, MVT::i64,
8710 Store->getMemOperand());
8713 if (VT == MVT::bf16)
8714 return lowerXAndesBfHCvtBFloat16Store(
Op, DAG);
8719 MVT XLenVT = Subtarget.getXLenVT();
8722 unsigned NumElts = Sz / (NF * 8);
8723 int Log2LMUL =
Log2_64(NumElts) - 3;
8726 Flag.setNoUnsignedWrap(
true);
8728 SDValue Chain = Store->getChain();
8729 SDValue BasePtr = Store->getBasePtr();
8736 for (
unsigned i = 0; i < NF; ++i) {
8738 DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL,
8741 Ret = DAG.
getStore(Chain,
DL, Extract, BasePtr,
8743 Store->getBaseAlign(),
8744 Store->getMemOperand()->getFlags());
8751 if (
auto V = expandUnalignedRVVStore(
Op, DAG))
8753 if (
Op.getOperand(1).getValueType().isFixedLengthVector())
8754 return lowerFixedLengthVectorStoreToRVV(
Op, DAG);
8758 if (
SDValue V = expandUnalignedVPLoad(
Op, DAG))
8762 return lowerMaskedLoad(
Op, DAG);
8763 case ISD::VP_LOAD_FF:
8764 return lowerLoadFF(
Op, DAG);
8766 if (
SDValue V = expandUnalignedVPStore(
Op, DAG))
8770 return lowerMaskedStore(
Op, DAG);
8772 return lowerVectorCompress(
Op, DAG);
8781 EVT VT =
Op.getValueType();
8792 MVT OpVT =
Op.getOperand(0).getSimpleValueType();
8794 MVT VT =
Op.getSimpleValueType();
8799 "Unexpected CondCode");
8832 return DAG.
getSetCC(
DL, VT, RHS, LHS, CCVal);
8838 return lowerToScalableOp(
Op, DAG);
8855 return lowerToScalableOp(
Op, DAG);
8859 if (
Op.getSimpleValueType().isFixedLengthVector()) {
8860 if (Subtarget.hasStdExtP()) {
8872 switch (
Op.getOpcode()) {
8876 Opc = RISCVISD::PSHL;
8879 Opc = RISCVISD::PSRL;
8882 Opc = RISCVISD::PSRA;
8888 return lowerToScalableOp(
Op, DAG);
8891 assert(
Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.is64Bit() &&
8892 "Unexpected custom legalisation");
8895 MVT VT =
Op.getSimpleValueType();
8897 "Unexptect custom legalisation");
8905 return DAG.
getNode(RISCVISD::PSSLAI,
DL, VT,
Op.getOperand(0),
8910 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
8938 return lowerToScalableOp(
Op, DAG);
8941 EVT VT =
Op->getValueType(0);
8943 if (Subtarget.hasStdExtZvabd() && VT.
isVector() &&
8946 return lowerToScalableOp(
Op, DAG);
8963 return lowerABS(
Op, DAG);
8968 if (Subtarget.hasStdExtZvbb())
8969 return lowerToScalableOp(
Op, DAG);
8971 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8973 MVT VT =
Op.getSimpleValueType();
8975 "Unexpected custom legalisation");
8985 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
8989 return lowerToScalableOp(
Op, DAG);
8998 return lowerToScalableOp(
Op, DAG);
9001 return lowerVectorStrictFSetcc(
Op, DAG);
9011 case ISD::VP_GATHER:
9012 return lowerMaskedGather(
Op, DAG);
9014 case ISD::VP_SCATTER:
9015 return lowerMaskedScatter(
Op, DAG);
9017 return lowerGET_ROUNDING(
Op, DAG);
9019 return lowerSET_ROUNDING(
Op, DAG);
9021 return lowerGET_FPENV(
Op, DAG);
9023 return lowerSET_FPENV(
Op, DAG);
9025 return lowerRESET_FPENV(
Op, DAG);
9027 return lowerGET_FPMODE(
Op, DAG);
9029 return lowerSET_FPMODE(
Op, DAG);
9031 return lowerRESET_FPMODE(
Op, DAG);
9033 return lowerEH_DWARF_CFA(
Op, DAG);
9035 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
9036 return lowerVPMergeMask(
Op, DAG);
9038 case ISD::VP_SELECT:
9046 case ISD::VP_UADDSAT:
9047 case ISD::VP_USUBSAT:
9048 case ISD::VP_SADDSAT:
9049 case ISD::VP_SSUBSAT:
9051 case ISD::VP_LLRINT:
9052 return lowerVPOp(
Op, DAG);
9056 return lowerLogicVPOp(
Op, DAG);
9065 case ISD::VP_FMINNUM:
9066 case ISD::VP_FMAXNUM:
9067 case ISD::VP_FCOPYSIGN:
9074 return lowerVPOp(
Op, DAG);
9075 case ISD::VP_IS_FPCLASS:
9076 return LowerIS_FPCLASS(
Op, DAG);
9077 case ISD::VP_SIGN_EXTEND:
9078 case ISD::VP_ZERO_EXTEND:
9079 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
9080 return lowerVPExtMaskOp(
Op, DAG);
9081 return lowerVPOp(
Op, DAG);
9082 case ISD::VP_TRUNCATE:
9083 return lowerVectorTruncLike(
Op, DAG);
9084 case ISD::VP_FP_EXTEND:
9085 case ISD::VP_FP_ROUND:
9086 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
9087 case ISD::VP_SINT_TO_FP:
9088 case ISD::VP_UINT_TO_FP:
9089 if (
Op.getValueType().isVector() &&
9090 ((
Op.getValueType().getScalarType() == MVT::f16 &&
9091 (Subtarget.hasVInstructionsF16Minimal() &&
9092 !Subtarget.hasVInstructionsF16())) ||
9093 Op.getValueType().getScalarType() == MVT::bf16)) {
9106 case ISD::VP_FP_TO_SINT:
9107 case ISD::VP_FP_TO_UINT:
9109 Op1.getValueType().isVector() &&
9110 ((Op1.getValueType().getScalarType() == MVT::f16 &&
9111 (Subtarget.hasVInstructionsF16Minimal() &&
9112 !Subtarget.hasVInstructionsF16())) ||
9113 Op1.getValueType().getScalarType() == MVT::bf16)) {
9119 Op1.getValueType().getVectorElementCount());
9123 {WidenVec, Op.getOperand(1), Op.getOperand(2)});
9125 return lowerVPFPIntConvOp(
Op, DAG);
9129 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
9130 return lowerVPSetCCMaskOp(
Op, DAG);
9136 case ISD::VP_BITREVERSE:
9138 return lowerVPOp(
Op, DAG);
9140 case ISD::VP_CTLZ_ZERO_UNDEF:
9141 if (Subtarget.hasStdExtZvbb())
9142 return lowerVPOp(
Op, DAG);
9143 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
9145 case ISD::VP_CTTZ_ZERO_UNDEF:
9146 if (Subtarget.hasStdExtZvbb())
9147 return lowerVPOp(
Op, DAG);
9148 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
9150 return lowerVPOp(
Op, DAG);
9151 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
9152 return lowerVPStridedLoad(
Op, DAG);
9153 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
9154 return lowerVPStridedStore(
Op, DAG);
9156 case ISD::VP_FFLOOR:
9158 case ISD::VP_FNEARBYINT:
9159 case ISD::VP_FROUND:
9160 case ISD::VP_FROUNDEVEN:
9161 case ISD::VP_FROUNDTOZERO:
9165 case ISD::VP_FMAXIMUM:
9166 case ISD::VP_FMINIMUM:
9170 case ISD::EXPERIMENTAL_VP_SPLICE:
9171 return lowerVPSpliceExperimental(
Op, DAG);
9172 case ISD::EXPERIMENTAL_VP_REVERSE:
9173 return lowerVPReverseExperimental(
Op, DAG);
9176 "llvm.clear_cache only needs custom lower on Linux targets");
9179 return emitFlushICache(DAG,
Op.getOperand(0),
Op.getOperand(1),
9180 Op.getOperand(2), Flags,
DL);
9183 return lowerDYNAMIC_STACKALLOC(
Op, DAG);
9185 return lowerINIT_TRAMPOLINE(
Op, DAG);
9187 return lowerADJUST_TRAMPOLINE(
Op, DAG);
9191 return lowerPARTIAL_REDUCE_MLA(
Op, DAG);
9198 MakeLibCallOptions CallOptions;
9199 std::pair<SDValue, SDValue> CallResult =
9200 makeLibCall(DAG, RTLIB::RISCV_FLUSH_ICACHE, MVT::isVoid,
9201 {Start, End, Flags}, CallOptions,
DL, InChain);
9204 return CallResult.second;
9209 if (!Subtarget.is64Bit())
9217 std::unique_ptr<MCCodeEmitter> CodeEmitter(
9245 const bool HasCFBranch =
9246 Subtarget.hasStdExtZicfilp() &&
9248 "cf-protection-branch");
9249 const unsigned StaticChainIdx = HasCFBranch ? 5 : 4;
9250 const unsigned StaticChainOffset = StaticChainIdx * 4;
9251 const unsigned FunctionAddressOffset = StaticChainOffset + 8;
9255 auto GetEncoding = [&](
const MCInst &MC) {
9258 CodeEmitter->encodeInstruction(MC, CB, Fixups, *STI);
9265 SmallVector<uint32_t> Encodings;
9270 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X7).addImm(0)),
9274 GetEncoding(MCInstBuilder(RISCV::LD)
9277 .addImm(FunctionAddressOffset)),
9280 GetEncoding(MCInstBuilder(RISCV::LD)
9283 .addImm(StaticChainOffset)),
9286 GetEncoding(MCInstBuilder(RISCV::JALR)
9294 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X0).addImm(0)),
9297 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X28).addImm(0)),
9301 GetEncoding(MCInstBuilder(RISCV::LD)
9304 .addImm(FunctionAddressOffset - 4)),
9307 GetEncoding(MCInstBuilder(RISCV::LD)
9310 .addImm(StaticChainOffset - 4)),
9313 GetEncoding(MCInstBuilder(RISCV::JALR)
9325 Root, dl, DAG.
getConstant(Encoding, dl, MVT::i64), Addr,
9326 MachinePointerInfo(TrmpAddr, Idx * 4), MVT::i32));
9330 SDValue FunctionAddress =
Op.getOperand(2);
9334 struct OffsetValuePair {
9338 } OffsetValues[] = {
9339 {StaticChainOffset, StaticChain},
9340 {FunctionAddressOffset, FunctionAddress},
9342 for (
auto &OffsetValue : OffsetValues) {
9345 DAG.
getConstant(OffsetValue.Offset, dl, MVT::i64));
9346 OffsetValue.Addr = Addr;
9348 DAG.
getStore(Root, dl, OffsetValue.Value, Addr,
9349 MachinePointerInfo(TrmpAddr, OffsetValue.Offset)));
9352 assert(OutChains.
size() == StaticChainIdx + 2 &&
9353 "Size of OutChains mismatch");
9358 SDValue EndOfTrmp = OffsetValues[0].Addr;
9369 if (!Subtarget.is64Bit())
9372 return Op.getOperand(0);
9382 MVT VT =
Op.getSimpleValueType();
9388 MVT ArgVT =
A.getSimpleValueType();
9389 assert(ArgVT ==
B.getSimpleValueType() &&
9399 MVT ContainerVT = VT;
9408 switch (
Op.getOpcode()) {
9410 Opc = RISCVISD::VDOTA4_VL;
9413 Opc = RISCVISD::VDOTA4U_VL;
9416 Opc = RISCVISD::VDOTA4SU_VL;
9442 N->getOffset(), Flags);
9471template <
class NodeTy>
9473 bool IsLocal,
bool IsExternWeak)
const {
9483 if (IsLocal && !Subtarget.allowTaggedGlobals())
9487 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
9510 if (Subtarget.hasVendorXqcili()) {
9514 return DAG.
getNode(RISCVISD::QC_E_LI,
DL, Ty, Addr);
9521 return DAG.
getNode(RISCVISD::ADD_LO,
DL, Ty, MNHi, AddrLo);
9545 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
9553 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
9561 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
9562 const GlobalValue *GV =
N->getGlobal();
9571 return getAddr(
N, DAG);
9578 return getAddr(
N, DAG);
9585 return getAddr(
N, DAG);
9590 bool UseGOT)
const {
9593 const GlobalValue *GV =
N->getGlobal();
9594 MVT XLenVT = Subtarget.getXLenVT();
9631 DAG.
getNode(RISCVISD::ADD_TPREL,
DL, Ty, MNHi, TPReg, AddrAdd);
9632 return DAG.
getNode(RISCVISD::ADD_LO,
DL, Ty, MNAdd, AddrLo);
9640 const GlobalValue *GV =
N->getGlobal();
9651 Args.emplace_back(Load, CallTy);
9654 TargetLowering::CallLoweringInfo CLI(DAG);
9668 const GlobalValue *GV =
N->getGlobal();
9684 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
9698 Addr = getStaticTLSAddr(
N, DAG,
false);
9701 Addr = getStaticTLSAddr(
N, DAG,
true);
9706 : getDynamicTLSAddr(
N, DAG);
9723 if (
LHS == LHS2 &&
RHS == RHS2) {
9728 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
9736 return std::nullopt;
9748 MVT VT =
N->getSimpleValueType(0);
9775 uint64_t TrueM1 = TrueC->getZExtValue() - 1;
9777 unsigned ShAmount =
Log2_64(TrueM1);
9779 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, CondV,
9795 if (~TrueVal == FalseVal) {
9835 if (Subtarget.hasShortForwardBranchIALU())
9838 unsigned SelOpNo = 0;
9848 unsigned ConstSelOpNo = 1;
9849 unsigned OtherSelOpNo = 2;
9856 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
9861 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
9867 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
9869 std::swap(NewConstOps[0], NewConstOps[1]);
9881 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
9883 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
9886 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
9887 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
9896 MVT VT =
Op.getSimpleValueType();
9897 MVT XLenVT = Subtarget.getXLenVT();
9903 if (Subtarget.isPExtPackedType(VT)) {
9924 bool FPinGPR = Subtarget.hasStdExtZfinx();
9928 Subtarget.getXLenVT().getSizeInBits());
9930 bool UseZicondForFPSel = Subtarget.hasStdExtZicond() && FPinGPR &&
9933 if (UseZicondForFPSel) {
9941 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, V);
9943 if (VT == MVT::f32 && Subtarget.is64Bit())
9944 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, XLenVT, V);
9949 SDValue TrueVInt = CastToInt(TrueV);
9950 SDValue FalseVInt = CastToInt(FalseV);
9957 if (VT == MVT::f32 && Subtarget.is64Bit())
9958 return DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, VT, ResultInt);
9961 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, ResultInt);
9974 return DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV);
9977 return DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV);
9981 auto getNotOperand = [](
const SDValue &
Op) -> std::optional<const SDValue> {
9982 using namespace llvm::SDPatternMatch;
9987 return std::nullopt;
9993 auto NotOperand = (TrueV.
getOperand(0) == FalseV)
9995 : getNotOperand(TrueV.getOperand(0));
9998 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, *NotOperand, CondV);
10004 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV));
10011 auto NotOperand = (FalseV.
getOperand(0) == TrueV)
10013 : getNotOperand(FalseV.getOperand(0));
10016 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, *NotOperand, CondV);
10022 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV));
10039 int64_t TrueImm =
TrueVal.getSExtValue();
10040 int64_t FalseImm =
FalseVal.getSExtValue();
10059 if ((TrueVal - FalseVal).isPowerOf2() &&
FalseVal.isSignedIntN(12)) {
10064 if ((FalseVal - TrueVal).isPowerOf2() &&
TrueVal.isSignedIntN(12)) {
10071 auto getCost = [&](
const APInt &Delta,
const APInt &Addend) {
10073 Delta, Subtarget.getXLen(), Subtarget,
true);
10075 if (Addend.isSignedIntN(12))
10078 Addend, Subtarget.getXLen(), Subtarget,
true);
10079 return AddendCost + DeltaCost;
10081 bool IsCZERO_NEZ =
getCost(FalseVal - TrueVal, TrueVal) <=
10082 getCost(TrueVal - FalseVal, FalseVal);
10084 IsCZERO_NEZ ? FalseVal - TrueVal : TrueVal - FalseVal,
DL, VT);
10086 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
10087 DL, VT, LHSVal, CondV);
10095 SDValue ConstVal = IsCZERO_NEZ ? TrueV : FalseV;
10096 SDValue RegV = IsCZERO_NEZ ? FalseV : TrueV;
10102 unsigned SubOpc = (RawConstVal == -0x800) ?
ISD::XOR : ISD::
SUB;
10103 unsigned AddOpc = (RawConstVal == -0x800) ?
ISD::XOR : ISD::
ADD;
10106 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
10107 DL, VT, SubOp, CondV);
10108 return DAG.
getNode(AddOpc,
DL, VT, CZERO, ConstVal);
10114 if (!Subtarget.hasConditionalMoveFusion())
10117 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV),
10118 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV),
10122 if (
Op.hasOneUse()) {
10123 unsigned UseOpc =
Op->user_begin()->getOpcode();
10125 SDNode *BinOp = *
Op->user_begin();
10132 return lowerSELECT(NewSel, DAG);
10142 if (FPTV && FPFV) {
10186 if (TrueVal - 1 == FalseVal)
10188 if (TrueVal + 1 == FalseVal)
10195 RHS == TrueV &&
LHS == FalseV) {
10226 MVT XLenVT = Subtarget.getXLenVT();
10237 return DAG.
getNode(RISCVISD::BR_CC,
DL,
Op.getValueType(),
Op.getOperand(0),
10238 LHS,
RHS, TargetCC,
Op.getOperand(2));
10241 return DAG.
getNode(RISCVISD::BR_CC,
DL,
Op.getValueType(),
Op.getOperand(0),
10248 RISCVMachineFunctionInfo *FuncInfo = MF.
getInfo<RISCVMachineFunctionInfo>();
10258 MachinePointerInfo(SV));
10263 const RISCVRegisterInfo &RI = *Subtarget.getRegisterInfo();
10268 int XLenInBytes = Subtarget.getXLen() / 8;
10270 EVT VT =
Op.getValueType();
10273 unsigned Depth =
Op.getConstantOperandVal(0);
10275 int Offset = -(XLenInBytes * 2);
10287 const RISCVRegisterInfo &RI = *Subtarget.getRegisterInfo();
10291 MVT XLenVT = Subtarget.getXLenVT();
10292 int XLenInBytes = Subtarget.getXLen() / 8;
10294 EVT VT =
Op.getValueType();
10296 unsigned Depth =
Op.getConstantOperandVal(0);
10298 int Off = -XLenInBytes;
10299 SDValue FrameAddr = lowerFRAMEADDR(
Op, DAG);
10303 MachinePointerInfo());
10318 EVT VT =
Lo.getValueType();
10319 unsigned XLen = Subtarget.getXLen();
10322 if (Subtarget.hasStdExtP()) {
10386 bool IsSRA)
const {
10391 EVT VT =
Lo.getValueType();
10394 if (Subtarget.hasStdExtP()) {
10395 unsigned XLen = Subtarget.getXLen();
10398 if (Subtarget.is64Bit()) {
10406 LoRes = DAG.
getNode(IsSRA ? RISCVISD::NSRA : RISCVISD::NSRL,
DL, VT,
Lo,
10425 if (Subtarget.is64Bit()) {
10499 MVT VT =
Op.getSimpleValueType();
10504 return DAG.
getNode(RISCVISD::VMSET_VL,
DL, VT, VL);
10508 return DAG.
getNode(RISCVISD::VMCLR_VL,
DL, VT, VL);
10525 MVT VecVT =
Op.getSimpleValueType();
10527 "Unexpected SPLAT_VECTOR_PARTS lowering");
10533 MVT ContainerVT = VecVT;
10553 int64_t ExtTrueVal)
const {
10555 MVT VecVT =
Op.getSimpleValueType();
10558 assert(Src.getValueType().isVector() &&
10559 Src.getValueType().getVectorElementType() == MVT::i1);
10564 if (Src.getOpcode() ==
ISD::XOR &&
10572 MVT I1ContainerVT =
10579 MVT XLenVT = Subtarget.getXLenVT();
10585 if (
Xor.getOpcode() == RISCVISD::VMXOR_VL) {
10597 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
10598 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
10599 SplatTrueVal = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
10600 DAG.
getUNDEF(ContainerVT), SplatTrueVal, VL);
10602 DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, CC, SplatTrueVal,
10603 SplatZero, DAG.
getUNDEF(ContainerVT), VL);
10613 bool IsVPTrunc =
Op.getOpcode() == ISD::VP_TRUNCATE;
10615 EVT MaskVT =
Op.getValueType();
10618 "Unexpected type for vector mask lowering");
10620 MVT VecVT = Src.getSimpleValueType();
10623 Mask =
Op.getOperand(1);
10624 VL =
Op.getOperand(2);
10627 MVT ContainerVT = VecVT;
10633 MVT MaskContainerVT =
10640 std::tie(Mask, VL) =
10647 SplatOne = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
10648 DAG.
getUNDEF(ContainerVT), SplatOne, VL);
10649 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
10650 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
10653 SDValue Trunc = DAG.
getNode(RISCVISD::AND_VL,
DL, ContainerVT, Src, SplatOne,
10654 DAG.
getUNDEF(ContainerVT), Mask, VL);
10655 Trunc = DAG.
getNode(RISCVISD::SETCC_VL,
DL, MaskContainerVT,
10665 unsigned Opc =
Op.getOpcode();
10666 bool IsVPTrunc =
Opc == ISD::VP_TRUNCATE;
10669 MVT VT =
Op.getSimpleValueType();
10671 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
10675 return lowerVectorMaskTruncLike(
Op, DAG);
10683 MVT SrcVT = Src.getSimpleValueType();
10688 "Unexpected vector truncate lowering");
10690 MVT ContainerVT = SrcVT;
10693 Mask =
Op.getOperand(1);
10694 VL =
Op.getOperand(2);
10707 std::tie(Mask, VL) =
10713 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL_SSAT;
10715 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL_USAT;
10717 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL;
10723 }
while (SrcEltVT != DstEltVT);
10732RISCVTargetLowering::lowerStrictFPExtendOrRoundLike(
SDValue Op,
10737 MVT VT =
Op.getSimpleValueType();
10738 MVT SrcVT = Src.getSimpleValueType();
10739 MVT ContainerVT = VT;
10758 ? RISCVISD::STRICT_FP_EXTEND_VL
10759 : RISCVISD::STRICT_VFNCVT_ROD_VL;
10762 Chain, Src, Mask, VL);
10763 Chain = Src.getValue(1);
10767 ? RISCVISD::STRICT_FP_EXTEND_VL
10768 : RISCVISD::STRICT_FP_ROUND_VL;
10770 Chain, Src, Mask, VL);
10781RISCVTargetLowering::lowerVectorFPExtendOrRoundLike(
SDValue Op,
10784 Op.getOpcode() == ISD::VP_FP_ROUND ||
Op.getOpcode() == ISD::VP_FP_EXTEND;
10791 MVT VT =
Op.getSimpleValueType();
10793 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
10796 MVT SrcVT = Src.getSimpleValueType();
10798 bool IsDirectExtend =
10806 bool IsDirectConv = IsDirectExtend || IsDirectTrunc;
10813 MVT ContainerVT = VT;
10816 Mask =
Op.getOperand(1);
10817 VL =
Op.getOperand(2);
10831 std::tie(Mask, VL) =
10834 unsigned ConvOpc = IsExtend ? RISCVISD::FP_EXTEND_VL : RISCVISD::FP_ROUND_VL;
10836 if (IsDirectConv) {
10837 Src = DAG.
getNode(ConvOpc,
DL, ContainerVT, Src, Mask, VL);
10843 unsigned InterConvOpc =
10844 IsExtend ? RISCVISD::FP_EXTEND_VL : RISCVISD::VFNCVT_ROD_VL;
10848 DAG.
getNode(InterConvOpc,
DL, InterVT, Src, Mask, VL);
10850 DAG.
getNode(ConvOpc,
DL, ContainerVT, IntermediateConv, Mask, VL);
10861static std::optional<MVT>
10867 const unsigned MinVLMAX = VectorBitsMin / EltSize;
10869 if (MaxIdx < MinVLMAX)
10871 else if (MaxIdx < MinVLMAX * 2)
10874 else if (MaxIdx < MinVLMAX * 4)
10879 return std::nullopt;
10887 return isUInt<5>(IdxC->getZExtValue());
10899 MVT VecVT =
Op.getSimpleValueType();
10900 MVT XLenVT = Subtarget.getXLenVT();
10915 if ((ValVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
10916 (ValVT == MVT::bf16 && !Subtarget.hasVInstructionsBF16())) {
10921 DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Val), Idx);
10930 unsigned IdxVal = IdxC->getZExtValue();
10938 if (NumElts == 2) {
10955 if (NumElts == 4 || NumElts == 8) {
10957 unsigned ShiftAmt = IdxVal * EltBits;
10958 uint64_t PosMask = ((1ULL << EltBits) - 1) << ShiftAmt;
10964 DAG.
getNode(RISCVISD::MERGE,
DL, XLenVT, Mask, Vec, ShiftedVal);
10971 MVT ContainerVT = VecVT;
10981 std::optional<unsigned> AlignedIdx;
10983 const unsigned OrigIdx = IdxC->getZExtValue();
10986 DL, DAG, Subtarget)) {
10987 ContainerVT = *ShrunkVT;
10995 if (
auto VLEN = Subtarget.getRealVLen(); VLEN && ContainerVT.
bitsGT(M1VT)) {
10998 unsigned RemIdx = OrigIdx % ElemsPerVReg;
10999 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
11002 ContainerVT = M1VT;
11009 bool IsLegalInsert = Subtarget.is64Bit() || Val.
getValueType() != MVT::i64;
11014 if (!IsLegalInsert) {
11018 IsLegalInsert =
true;
11023 IsLegalInsert =
true;
11032 if (IsLegalInsert) {
11034 VecVT.
isFloatingPoint() ? RISCVISD::VFMV_S_F_VL : RISCVISD::VMV_S_X_VL;
11038 Vec = DAG.
getNode(
Opc,
DL, ContainerVT, Vec, Val, VL);
11048 if (Subtarget.hasVendorXRivosVisni() && VecVT.
isInteger() &&
11053 Vec = DAG.
getNode(RISCVISD::RI_VINSERT_VL,
DL, ContainerVT, Vec, Val, Idx,
11069 std::tie(ValLo, ValHi) = DAG.
SplitScalar(Val,
DL, MVT::i32, MVT::i32);
11070 MVT I32ContainerVT =
11080 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
11081 Vec, Vec, ValLo, I32Mask, InsertI64VL);
11085 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
11086 Tail, ValInVec, ValHi, I32Mask, InsertI64VL);
11088 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
11099 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
11101 DAG.
getUNDEF(I32ContainerVT), ValLo,
11102 I32Mask, InsertI64VL);
11103 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
11104 DAG.
getUNDEF(I32ContainerVT), ValInVec, ValHi,
11105 I32Mask, InsertI64VL);
11107 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
11120 Idx, Mask, InsertVL, Policy);
11138 EVT EltVT =
Op.getValueType();
11140 MVT XLenVT = Subtarget.getXLenVT();
11145 MVT ContainerVT = VecVT;
11152 DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Vec, Mask, VL);
11159 if (NumElts >= 8) {
11161 unsigned WidenVecLen;
11164 unsigned MaxEEW = Subtarget.getELen();
11169 "the number of elements should be power of 2");
11173 ExtractBitIdx = Idx;
11175 WideEltVT = LargestEltVT;
11178 ExtractElementIdx = DAG.
getNode(
11189 Vec, ExtractElementIdx);
11204 if ((EltVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
11205 (EltVT == MVT::bf16 && !Subtarget.hasVInstructionsBF16())) {
11211 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, EltVT, IntExtract);
11215 if (VecVT != MVT::v4i16 && VecVT != MVT::v2i16 && VecVT != MVT::v8i8 &&
11216 VecVT != MVT::v4i8 && VecVT != MVT::v2i32)
11226 MVT ContainerVT = VecVT;
11236 const auto VLen = Subtarget.getRealVLen();
11238 IdxC && VLen && VecVT.
getSizeInBits().getKnownMinValue() > *VLen) {
11240 unsigned OrigIdx = IdxC->getZExtValue();
11243 unsigned RemIdx = OrigIdx % ElemsPerVReg;
11244 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
11245 unsigned ExtractIdx =
11249 ContainerVT = M1VT;
11254 std::optional<uint64_t> MaxIdx;
11258 MaxIdx = IdxC->getZExtValue();
11260 if (
auto SmallerVT =
11262 ContainerVT = *SmallerVT;
11269 if (Subtarget.hasVendorXRivosVisni() && EltVT.
isInteger() &&
11297 DAG.
getUNDEF(ContainerVT), Vec, Idx, Mask, VL);
11316 "Unexpected opcode");
11323 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
11328 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
11329 if (!
II || !
II->hasScalarOperand())
11332 unsigned SplatOp =
II->ScalarOperand + 1 + HasChain;
11333 assert(SplatOp <
Op.getNumOperands());
11336 SDValue &ScalarOp = Operands[SplatOp];
11345 if (OpVT.
bitsLT(XLenVT)) {
11352 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
11353 return DAG.
getNode(
Op->getOpcode(),
DL,
Op->getVTList(), Operands);
11362 assert(
II->ScalarOperand > 0 &&
"Unexpected splat operand!");
11363 MVT VT =
Op.getOperand(SplatOp - 1).getSimpleValueType();
11366 assert(XLenVT == MVT::i32 && OpVT == MVT::i64 &&
11373 return DAG.
getNode(
Op->getOpcode(),
DL,
Op->getVTList(), Operands);
11377 case Intrinsic::riscv_vslide1up:
11378 case Intrinsic::riscv_vslide1down:
11379 case Intrinsic::riscv_vslide1up_mask:
11380 case Intrinsic::riscv_vslide1down_mask: {
11382 unsigned NumOps =
Op.getNumOperands();
11383 bool IsMasked =
NumOps == 7;
11389 std::tie(ScalarLo, ScalarHi) =
11398 const auto [MinVLMAX, MaxVLMAX] =
11402 if (AVLInt <= MinVLMAX) {
11404 }
else if (AVLInt >= 2 * MaxVLMAX) {
11436 Passthru = DAG.
getBitcast(I32VT, Operands[1]);
11438 if (IntNo == Intrinsic::riscv_vslide1up ||
11439 IntNo == Intrinsic::riscv_vslide1up_mask) {
11440 Vec = DAG.
getNode(RISCVISD::VSLIDE1UP_VL,
DL, I32VT, Passthru, Vec,
11441 ScalarHi, I32Mask, I32VL);
11442 Vec = DAG.
getNode(RISCVISD::VSLIDE1UP_VL,
DL, I32VT, Passthru, Vec,
11443 ScalarLo, I32Mask, I32VL);
11445 Vec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32VT, Passthru, Vec,
11446 ScalarLo, I32Mask, I32VL);
11447 Vec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32VT, Passthru, Vec,
11448 ScalarHi, I32Mask, I32VL);
11458 SDValue MaskedOff = Operands[1];
11466 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, Mask, Vec, MaskedOff,
11470 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, Mask, Vec, MaskedOff,
11479 return DAG.
getNode(
Op->getOpcode(),
DL,
Op->getVTList(), Operands);
11497 const unsigned ElementWidth = 8;
11502 [[maybe_unused]]
unsigned MinVF =
11505 [[maybe_unused]]
unsigned VF =
N->getConstantOperandVal(2);
11509 bool Fractional = VF < LMul1VF;
11510 unsigned LMulVal = Fractional ? LMul1VF / VF : VF / LMul1VF;
11531 MVT ContainerVT = OpVT;
11539 SDValue Res = DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Op0, Mask, VL);
11547 return DAG.
getSelect(
DL, XLenVT, Setcc, VL, Res);
11558 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
11562 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
11563 if (!
II || !
II->hasScalarOperand())
11566 unsigned SplatOp =
II->ScalarOperand + 1;
11567 assert(SplatOp <
Op.getNumOperands());
11569 SDValue &ScalarOp = Operands[SplatOp];
11579 if (OpVT.
bitsLT(XLenVT)) {
11582 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
11592 for (
SDValue &V : Operands) {
11593 EVT ValType = V.getValueType();
11594 if (ValType.isVector() && ValType.isFloatingPoint()) {
11597 ValType.getVectorElementCount());
11600 if (ValType.isFixedLengthVector()) {
11602 DAG, V.getSimpleValueType(), Subtarget);
11618 unsigned IntNo =
Op.getConstantOperandVal(0);
11620 MVT XLenVT = Subtarget.getXLenVT();
11625 case Intrinsic::riscv_tuple_insert: {
11630 return DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL,
Op.getValueType(), Vec,
11633 case Intrinsic::riscv_tuple_extract: {
11637 return DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL,
Op.getValueType(), Vec,
11640 case Intrinsic::thread_pointer: {
11644 case Intrinsic::riscv_orc_b:
11645 case Intrinsic::riscv_brev8:
11646 case Intrinsic::riscv_sha256sig0:
11647 case Intrinsic::riscv_sha256sig1:
11648 case Intrinsic::riscv_sha256sum0:
11649 case Intrinsic::riscv_sha256sum1:
11650 case Intrinsic::riscv_sm3p0:
11651 case Intrinsic::riscv_sm3p1: {
11654 case Intrinsic::riscv_orc_b:
Opc = RISCVISD::ORC_B;
break;
11655 case Intrinsic::riscv_brev8:
Opc = RISCVISD::BREV8;
break;
11656 case Intrinsic::riscv_sha256sig0:
Opc = RISCVISD::SHA256SIG0;
break;
11657 case Intrinsic::riscv_sha256sig1:
Opc = RISCVISD::SHA256SIG1;
break;
11658 case Intrinsic::riscv_sha256sum0:
Opc = RISCVISD::SHA256SUM0;
break;
11659 case Intrinsic::riscv_sha256sum1:
Opc = RISCVISD::SHA256SUM1;
break;
11660 case Intrinsic::riscv_sm3p0:
Opc = RISCVISD::SM3P0;
break;
11661 case Intrinsic::riscv_sm3p1:
Opc = RISCVISD::SM3P1;
break;
11666 case Intrinsic::riscv_sm4ks:
11667 case Intrinsic::riscv_sm4ed: {
11669 IntNo == Intrinsic::riscv_sm4ks ? RISCVISD::SM4KS : RISCVISD::SM4ED;
11674 case Intrinsic::riscv_zip:
11675 case Intrinsic::riscv_unzip: {
11677 IntNo == Intrinsic::riscv_zip ? RISCVISD::ZIP : RISCVISD::UNZIP;
11680 case Intrinsic::riscv_mopr:
11681 return DAG.
getNode(RISCVISD::MOP_R,
DL, XLenVT,
Op.getOperand(1),
11684 case Intrinsic::riscv_moprr: {
11685 return DAG.
getNode(RISCVISD::MOP_RR,
DL, XLenVT,
Op.getOperand(1),
11686 Op.getOperand(2),
Op.getOperand(3));
11688 case Intrinsic::riscv_clmulh:
11689 case Intrinsic::riscv_clmulr: {
11693 case Intrinsic::experimental_get_vector_length:
11695 case Intrinsic::experimental_cttz_elts:
11697 case Intrinsic::riscv_vmv_x_s: {
11701 case Intrinsic::riscv_vfmv_f_s:
11703 case Intrinsic::riscv_vmv_v_x:
11705 Op.getOperand(3),
Op.getSimpleValueType(),
DL, DAG,
11707 case Intrinsic::riscv_vfmv_v_f:
11708 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL,
Op.getValueType(),
11709 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
11710 case Intrinsic::riscv_vmv_s_x: {
11713 if (
Scalar.getValueType().bitsLE(XLenVT)) {
11715 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL,
Op.getValueType(),
11716 Op.getOperand(1), Scalar,
Op.getOperand(3));
11719 assert(
Scalar.getValueType() == MVT::i64 &&
"Unexpected scalar VT!");
11736 MVT VT =
Op.getSimpleValueType();
11741 if (
Op.getOperand(1).isUndef())
11742 return SplattedVal;
11751 DAG.
getNode(RISCVISD::SETCC_VL,
DL, MaskVT,
11754 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, SelectCond, SplattedVal,
11757 case Intrinsic::riscv_vfmv_s_f:
11758 return DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL,
Op.getValueType(),
11759 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
11761 case Intrinsic::riscv_vaesdf_vv:
11762 case Intrinsic::riscv_vaesdf_vs:
11763 case Intrinsic::riscv_vaesdm_vv:
11764 case Intrinsic::riscv_vaesdm_vs:
11765 case Intrinsic::riscv_vaesef_vv:
11766 case Intrinsic::riscv_vaesef_vs:
11767 case Intrinsic::riscv_vaesem_vv:
11768 case Intrinsic::riscv_vaesem_vs:
11769 case Intrinsic::riscv_vaeskf1:
11770 case Intrinsic::riscv_vaeskf2:
11771 case Intrinsic::riscv_vaesz_vs:
11772 case Intrinsic::riscv_vsm4k:
11773 case Intrinsic::riscv_vsm4r_vv:
11774 case Intrinsic::riscv_vsm4r_vs: {
11775 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
11776 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
11777 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
11782 case Intrinsic::riscv_vsm3c:
11783 case Intrinsic::riscv_vsm3me: {
11784 if (!
isValidEGW(8,
Op.getSimpleValueType(), Subtarget) ||
11785 !
isValidEGW(8,
Op->getOperand(1).getSimpleValueType(), Subtarget))
11790 case Intrinsic::riscv_vsha2ch:
11791 case Intrinsic::riscv_vsha2cl:
11792 case Intrinsic::riscv_vsha2ms: {
11793 if (
Op->getSimpleValueType(0).getScalarSizeInBits() == 64 &&
11794 !Subtarget.hasStdExtZvknhb())
11796 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
11797 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
11798 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
11802 case Intrinsic::riscv_sf_vc_v_x:
11803 case Intrinsic::riscv_sf_vc_v_i:
11804 case Intrinsic::riscv_sf_vc_v_xv:
11805 case Intrinsic::riscv_sf_vc_v_iv:
11806 case Intrinsic::riscv_sf_vc_v_vv:
11807 case Intrinsic::riscv_sf_vc_v_fv:
11808 case Intrinsic::riscv_sf_vc_v_xvv:
11809 case Intrinsic::riscv_sf_vc_v_ivv:
11810 case Intrinsic::riscv_sf_vc_v_vvv:
11811 case Intrinsic::riscv_sf_vc_v_fvv:
11812 case Intrinsic::riscv_sf_vc_v_xvw:
11813 case Intrinsic::riscv_sf_vc_v_ivw:
11814 case Intrinsic::riscv_sf_vc_v_vvw:
11815 case Intrinsic::riscv_sf_vc_v_fvw: {
11816 MVT VT =
Op.getSimpleValueType();
11853 MVT VT =
Op.getSimpleValueType();
11857 if (VT.isFloatingPoint()) {
11859 VT.getVectorElementCount());
11862 if (VT.isFixedLengthVector())
11872 if (VT.isFixedLengthVector())
11874 if (VT.isFloatingPoint())
11897 case Intrinsic::riscv_seg2_load_mask:
11898 case Intrinsic::riscv_seg3_load_mask:
11899 case Intrinsic::riscv_seg4_load_mask:
11900 case Intrinsic::riscv_seg5_load_mask:
11901 case Intrinsic::riscv_seg6_load_mask:
11902 case Intrinsic::riscv_seg7_load_mask:
11903 case Intrinsic::riscv_seg8_load_mask:
11906 case Intrinsic::riscv_sseg2_load_mask:
11907 case Intrinsic::riscv_sseg3_load_mask:
11908 case Intrinsic::riscv_sseg4_load_mask:
11909 case Intrinsic::riscv_sseg5_load_mask:
11910 case Intrinsic::riscv_sseg6_load_mask:
11911 case Intrinsic::riscv_sseg7_load_mask:
11912 case Intrinsic::riscv_sseg8_load_mask:
11920 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
11921 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
11922 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
11923 Intrinsic::riscv_vlseg8_mask};
11925 Intrinsic::riscv_vlsseg2_mask, Intrinsic::riscv_vlsseg3_mask,
11926 Intrinsic::riscv_vlsseg4_mask, Intrinsic::riscv_vlsseg5_mask,
11927 Intrinsic::riscv_vlsseg6_mask, Intrinsic::riscv_vlsseg7_mask,
11928 Intrinsic::riscv_vlsseg8_mask};
11931 unsigned NF =
Op->getNumValues() - 1;
11932 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
11934 MVT VT =
Op->getSimpleValueType(0);
11942 SDValue VL =
Op.getOperand(
Op.getNumOperands() - 1);
11943 SDValue Mask =
Op.getOperand(
Op.getNumOperands() - 2);
11944 MVT MaskVT = Mask.getSimpleValueType();
11945 MVT MaskContainerVT =
11950 IsStrided ? VlssegInts[NF - 2] : VlsegInts[NF - 2],
DL, XLenVT);
11966 Ops.insert(std::next(
Ops.begin(), 4),
Op.getOperand(3));
11970 Load->getMemoryVT(), Load->getMemOperand());
11972 for (
unsigned int RetIdx = 0; RetIdx < NF; RetIdx++) {
11974 Result.getValue(0),
11978 Results.push_back(Result.getValue(1));
11984 unsigned IntNo =
Op.getConstantOperandVal(1);
11988 case Intrinsic::riscv_seg2_load_mask:
11989 case Intrinsic::riscv_seg3_load_mask:
11990 case Intrinsic::riscv_seg4_load_mask:
11991 case Intrinsic::riscv_seg5_load_mask:
11992 case Intrinsic::riscv_seg6_load_mask:
11993 case Intrinsic::riscv_seg7_load_mask:
11994 case Intrinsic::riscv_seg8_load_mask:
11995 case Intrinsic::riscv_sseg2_load_mask:
11996 case Intrinsic::riscv_sseg3_load_mask:
11997 case Intrinsic::riscv_sseg4_load_mask:
11998 case Intrinsic::riscv_sseg5_load_mask:
11999 case Intrinsic::riscv_sseg6_load_mask:
12000 case Intrinsic::riscv_sseg7_load_mask:
12001 case Intrinsic::riscv_sseg8_load_mask:
12004 case Intrinsic::riscv_sf_vc_v_x_se:
12006 case Intrinsic::riscv_sf_vc_v_i_se:
12008 case Intrinsic::riscv_sf_vc_v_xv_se:
12010 case Intrinsic::riscv_sf_vc_v_iv_se:
12012 case Intrinsic::riscv_sf_vc_v_vv_se:
12014 case Intrinsic::riscv_sf_vc_v_fv_se:
12016 case Intrinsic::riscv_sf_vc_v_xvv_se:
12018 case Intrinsic::riscv_sf_vc_v_ivv_se:
12020 case Intrinsic::riscv_sf_vc_v_vvv_se:
12022 case Intrinsic::riscv_sf_vc_v_fvv_se:
12024 case Intrinsic::riscv_sf_vc_v_xvw_se:
12026 case Intrinsic::riscv_sf_vc_v_ivw_se:
12028 case Intrinsic::riscv_sf_vc_v_vvw_se:
12030 case Intrinsic::riscv_sf_vc_v_fvw_se:
12043 case Intrinsic::riscv_seg2_store_mask:
12044 case Intrinsic::riscv_seg3_store_mask:
12045 case Intrinsic::riscv_seg4_store_mask:
12046 case Intrinsic::riscv_seg5_store_mask:
12047 case Intrinsic::riscv_seg6_store_mask:
12048 case Intrinsic::riscv_seg7_store_mask:
12049 case Intrinsic::riscv_seg8_store_mask:
12052 case Intrinsic::riscv_sseg2_store_mask:
12053 case Intrinsic::riscv_sseg3_store_mask:
12054 case Intrinsic::riscv_sseg4_store_mask:
12055 case Intrinsic::riscv_sseg5_store_mask:
12056 case Intrinsic::riscv_sseg6_store_mask:
12057 case Intrinsic::riscv_sseg7_store_mask:
12058 case Intrinsic::riscv_sseg8_store_mask:
12067 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
12068 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
12069 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
12070 Intrinsic::riscv_vsseg8_mask};
12072 Intrinsic::riscv_vssseg2_mask, Intrinsic::riscv_vssseg3_mask,
12073 Intrinsic::riscv_vssseg4_mask, Intrinsic::riscv_vssseg5_mask,
12074 Intrinsic::riscv_vssseg6_mask, Intrinsic::riscv_vssseg7_mask,
12075 Intrinsic::riscv_vssseg8_mask};
12079 unsigned NF =
Op->getNumOperands() - (IsStrided ? 6 : 5);
12080 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
12082 MVT VT =
Op->getOperand(2).getSimpleValueType();
12088 SDValue VL =
Op.getOperand(
Op.getNumOperands() - 1);
12089 SDValue Mask =
Op.getOperand(
Op.getNumOperands() - 2);
12090 MVT MaskVT = Mask.getSimpleValueType();
12091 MVT MaskContainerVT =
12096 IsStrided ? VsssegInts[NF - 2] : VssegInts[NF - 2],
DL, XLenVT);
12102 for (
unsigned i = 0; i < NF; i++)
12104 RISCVISD::TUPLE_INSERT,
DL, VecTupTy, StoredVal,
12110 FixedIntrinsic->getChain(),
12119 Ops.insert(std::next(
Ops.begin(), 4),
12120 Op.getOperand(
Op.getNumOperands() - 3));
12124 FixedIntrinsic->getMemoryVT(), FixedIntrinsic->getMemOperand());
12129 unsigned IntNo =
Op.getConstantOperandVal(1);
12133 case Intrinsic::riscv_seg2_store_mask:
12134 case Intrinsic::riscv_seg3_store_mask:
12135 case Intrinsic::riscv_seg4_store_mask:
12136 case Intrinsic::riscv_seg5_store_mask:
12137 case Intrinsic::riscv_seg6_store_mask:
12138 case Intrinsic::riscv_seg7_store_mask:
12139 case Intrinsic::riscv_seg8_store_mask:
12140 case Intrinsic::riscv_sseg2_store_mask:
12141 case Intrinsic::riscv_sseg3_store_mask:
12142 case Intrinsic::riscv_sseg4_store_mask:
12143 case Intrinsic::riscv_sseg5_store_mask:
12144 case Intrinsic::riscv_sseg6_store_mask:
12145 case Intrinsic::riscv_sseg7_store_mask:
12146 case Intrinsic::riscv_sseg8_store_mask:
12149 case Intrinsic::riscv_sf_vc_xv_se:
12151 case Intrinsic::riscv_sf_vc_iv_se:
12153 case Intrinsic::riscv_sf_vc_vv_se:
12155 case Intrinsic::riscv_sf_vc_fv_se:
12157 case Intrinsic::riscv_sf_vc_xvv_se:
12159 case Intrinsic::riscv_sf_vc_ivv_se:
12161 case Intrinsic::riscv_sf_vc_vvv_se:
12163 case Intrinsic::riscv_sf_vc_fvv_se:
12165 case Intrinsic::riscv_sf_vc_xvw_se:
12167 case Intrinsic::riscv_sf_vc_ivw_se:
12169 case Intrinsic::riscv_sf_vc_vvw_se:
12171 case Intrinsic::riscv_sf_vc_fvw_se:
12179 switch (ISDOpcode) {
12182 case ISD::VP_REDUCE_ADD:
12184 return RISCVISD::VECREDUCE_ADD_VL;
12185 case ISD::VP_REDUCE_UMAX:
12187 return RISCVISD::VECREDUCE_UMAX_VL;
12188 case ISD::VP_REDUCE_SMAX:
12190 return RISCVISD::VECREDUCE_SMAX_VL;
12191 case ISD::VP_REDUCE_UMIN:
12193 return RISCVISD::VECREDUCE_UMIN_VL;
12194 case ISD::VP_REDUCE_SMIN:
12196 return RISCVISD::VECREDUCE_SMIN_VL;
12197 case ISD::VP_REDUCE_AND:
12199 return RISCVISD::VECREDUCE_AND_VL;
12200 case ISD::VP_REDUCE_OR:
12202 return RISCVISD::VECREDUCE_OR_VL;
12203 case ISD::VP_REDUCE_XOR:
12205 return RISCVISD::VECREDUCE_XOR_VL;
12206 case ISD::VP_REDUCE_FADD:
12207 return RISCVISD::VECREDUCE_FADD_VL;
12208 case ISD::VP_REDUCE_SEQ_FADD:
12209 return RISCVISD::VECREDUCE_SEQ_FADD_VL;
12210 case ISD::VP_REDUCE_FMAX:
12211 case ISD::VP_REDUCE_FMAXIMUM:
12212 return RISCVISD::VECREDUCE_FMAX_VL;
12213 case ISD::VP_REDUCE_FMIN:
12214 case ISD::VP_REDUCE_FMINIMUM:
12215 return RISCVISD::VECREDUCE_FMIN_VL;
12224 SDValue Vec =
Op.getOperand(IsVP ? 1 : 0);
12229 Op.getOpcode() == ISD::VP_REDUCE_AND ||
12230 Op.getOpcode() == ISD::VP_REDUCE_OR ||
12231 Op.getOpcode() == ISD::VP_REDUCE_XOR) &&
12232 "Unexpected reduction lowering");
12234 MVT XLenVT = Subtarget.getXLenVT();
12236 MVT ContainerVT = VecVT;
12244 Mask =
Op.getOperand(2);
12245 VL =
Op.getOperand(3);
12247 std::tie(Mask, VL) =
12252 switch (
Op.getOpcode()) {
12256 case ISD::VP_REDUCE_AND: {
12260 Vec = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Vec, TrueMask, VL);
12263 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
12268 case ISD::VP_REDUCE_OR:
12270 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
12274 case ISD::VP_REDUCE_XOR: {
12277 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
12298 return DAG.
getNode(BaseOpc,
DL,
Op.getValueType(), SetCC,
Op.getOperand(0));
12304 return (RegisterAVL && RegisterAVL->getReg() == RISCV::X0) ||
12305 (ImmAVL && ImmAVL->getZExtValue() >= 1);
12321 auto InnerVT = VecVT.
bitsLE(M1VT) ? VecVT : M1VT;
12325 auto InnerVL = NonZeroAVL ? VL : DAG.
getConstant(1,
DL, XLenVT);
12328 if (M1VT != InnerVT)
12333 SDValue Ops[] = {PassThru, Vec, InitialValue, Mask, VL, Policy};
12351 VecEVT =
Lo.getValueType();
12364 MVT ContainerVT = VecVT;
12383 Mask, VL,
DL, DAG, Subtarget);
12389static std::tuple<unsigned, SDValue, SDValue>
12393 auto Flags =
Op->getFlags();
12394 unsigned Opcode =
Op.getOpcode();
12402 return std::make_tuple(RISCVISD::VECREDUCE_FADD_VL,
Op.getOperand(0), Zero);
12405 return std::make_tuple(RISCVISD::VECREDUCE_SEQ_FADD_VL,
Op.getOperand(1),
12414 ? RISCVISD::VECREDUCE_FMIN_VL
12415 : RISCVISD::VECREDUCE_FMAX_VL;
12416 return std::make_tuple(RVVOpc,
Op.getOperand(0), Front);
12424 MVT VecEltVT =
Op.getSimpleValueType();
12426 unsigned RVVOpcode;
12427 SDValue VectorVal, ScalarVal;
12428 std::tie(RVVOpcode, VectorVal, ScalarVal) =
12432 MVT ContainerVT = VecVT;
12438 MVT ResVT =
Op.getSimpleValueType();
12441 VL,
DL, DAG, Subtarget);
12446 if (
Op->getFlags().hasNoNaNs())
12452 {VectorVal, VectorVal, DAG.getCondCode(ISD::SETNE),
12453 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
12454 MVT XLenVT = Subtarget.getXLenVT();
12455 SDValue CPop = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, IsNan, Mask, VL);
12459 DL, ResVT, NoNaNs, Res,
12466 unsigned Opc =
Op.getOpcode();
12470 MVT XLenVT = Subtarget.getXLenVT();
12489 Vec, Mask, VL,
DL, DAG, Subtarget);
12490 if ((
Opc != ISD::VP_REDUCE_FMINIMUM &&
Opc != ISD::VP_REDUCE_FMAXIMUM) ||
12491 Op->getFlags().hasNoNaNs())
12498 RISCVISD::SETCC_VL,
DL, PredVT,
12500 SDValue VCPop = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, IsNaN, Mask, VL);
12508 DL, ResVT, NoNaNs, Res,
12520 MVT XLenVT = Subtarget.getXLenVT();
12521 unsigned OrigIdx =
Op.getConstantOperandVal(2);
12522 const RISCVRegisterInfo *
TRI = Subtarget.getRegisterInfo();
12524 if (OrigIdx == 0 && Vec.
isUndef())
12535 assert(OrigIdx % 8 == 0 &&
"Invalid index");
12538 "Unexpected mask vector lowering");
12568 const auto VLen = Subtarget.getRealVLen();
12570 MVT ContainerVT = VecVT;
12592 if (OrigIdx == 0) {
12594 DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, ContainerVT, Vec, SubVec, VL);
12597 SubVec =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, Vec, SubVec,
12598 SlideupAmt, Mask, VL, Policy);
12606 MVT ContainerVecVT = VecVT;
12612 MVT ContainerSubVecVT = SubVecVT;
12618 unsigned SubRegIdx;
12619 ElementCount RemIdx;
12628 ContainerVecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
12629 SubRegIdx = Decompose.first;
12631 (OrigIdx % Vscale));
12635 ContainerVecVT, ContainerSubVecVT, OrigIdx,
TRI);
12636 SubRegIdx = Decompose.first;
12642 Subtarget.expandVScale(SubVecVT.
getSizeInBits()).getKnownMinValue()));
12643 bool ExactlyVecRegSized =
12645 .isKnownMultipleOf(Subtarget.expandVScale(VecRegSize));
12660 if (RemIdx.
isZero() && (ExactlyVecRegSized || Vec.
isUndef())) {
12664 if (SubRegIdx == RISCV::NoSubRegister) {
12686 MVT InterSubVT = ContainerVecVT;
12687 SDValue AlignedExtract = Vec;
12709 if (Subtarget.expandVScale(EndIndex) ==
12716 SubVec = DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, InterSubVT, AlignedExtract,
12724 SubVec =
getVSlideup(DAG, Subtarget,
DL, InterSubVT, AlignedExtract, SubVec,
12725 SlideupAmt, Mask, VL, Policy);
12730 if (ContainerVecVT.
bitsGT(InterSubVT))
12738 return DAG.
getBitcast(
Op.getSimpleValueType(), SubVec);
12744 MVT SubVecVT =
Op.getSimpleValueType();
12748 MVT XLenVT = Subtarget.getXLenVT();
12749 unsigned OrigIdx =
Op.getConstantOperandVal(1);
12750 const RISCVRegisterInfo *
TRI = Subtarget.getRegisterInfo();
12765 assert(OrigIdx % 8 == 0 &&
"Invalid index");
12768 "Unexpected mask vector lowering");
12794 const auto VLen = Subtarget.getRealVLen();
12802 MVT ContainerVT = VecVT;
12810 if (
auto ShrunkVT =
12812 ContainerVT = *ShrunkVT;
12824 DAG.
getUNDEF(ContainerVT), Vec, SlidedownAmt, Mask, VL);
12835 MVT ContainerSubVecVT = SubVecVT;
12839 unsigned SubRegIdx;
12840 ElementCount RemIdx;
12849 VecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
12850 SubRegIdx = Decompose.first;
12852 (OrigIdx % Vscale));
12856 VecVT, ContainerSubVecVT, OrigIdx,
TRI);
12857 SubRegIdx = Decompose.first;
12884 MVT InterSubVT = VecVT;
12889 assert(SubRegIdx != RISCV::NoSubRegister);
12908 Vec, SlidedownAmt, Mask, VL);
12916 return DAG.
getBitcast(
Op.getSimpleValueType(), Slidedown);
12923 MVT VT =
N.getSimpleValueType();
12927 assert(
Op.getSimpleValueType() == VT &&
12928 "Operands and result must be same type");
12932 unsigned NumVals =
N->getNumValues();
12936 N.getValueType().changeVectorElementType(*DAG.
getContext(), MVT::i8)));
12939 for (
unsigned I = 0;
I < NumVals;
I++) {
12945 if (TruncVals.
size() > 1)
12947 return TruncVals.
front();
12953 MVT VecVT =
Op.getSimpleValueType();
12955 const unsigned Factor =
Op->getNumValues();
12966 for (
unsigned i = 0U; i < Factor; ++i)
12975 for (
unsigned i = 0U; i < Factor; ++i)
12985 for (
unsigned i = 0; i != Factor; ++i) {
12988 Ops[i * 2 + 1] = OpHi;
12999 for (
unsigned i = 0; i != Factor; ++i)
13006 if (Subtarget.hasVendorXRivosVizip() && Factor == 2) {
13007 MVT VT =
Op->getSimpleValueType(0);
13032 lowerVZIP(RISCVISD::RI_VUNZIP2A_VL, V1, V2,
DL, DAG, Subtarget);
13034 lowerVZIP(RISCVISD::RI_VUNZIP2B_VL, V1, V2,
DL, DAG, Subtarget);
13067 EvenSplat = DAG.
getBitcast(MVT::nxv64i1, EvenSplat);
13071 OddSplat = DAG.
getBitcast(MVT::nxv64i1, OddSplat);
13076 EvenMask, DAG.
getUNDEF(ConcatVT));
13088 MVT XLenVT = Subtarget.getXLenVT();
13110 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
13111 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
13112 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
13113 Intrinsic::riscv_vlseg8_mask};
13137 for (
unsigned i = 0U; i < Factor; ++i)
13138 Res[i] = DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL, VecVT, Load,
13147 MVT VecVT =
Op.getSimpleValueType();
13160 for (
unsigned i = 0U; i < Factor; ++i)
13168 for (
unsigned i = 0U; i < Factor; ++i)
13174 MVT XLenVT = Subtarget.getXLenVT();
13181 for (
unsigned i = 0; i != Factor; ++i) {
13184 Ops[i + Factor] = OpHi;
13195 for (
unsigned i = 0; i != Factor; ++i) {
13196 unsigned IdxLo = 2 * i;
13197 unsigned IdxHi = 2 * i + 1;
13199 Res[IdxLo / Factor].getValue(IdxLo % Factor),
13200 Res[IdxHi / Factor].getValue(IdxHi % Factor));
13218 EVT PtrVT =
StackPtr.getValueType();
13224 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
13225 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
13226 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
13227 Intrinsic::riscv_vsseg8_mask,
13235 for (
unsigned i = 0; i < Factor; i++)
13237 DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VecTupTy, StoredVal,
13257 for (
unsigned i = 0; i != Factor; ++i) {
13261 Loads[i] = DAG.
getLoad(VecVT,
DL, Chain, StackPtr, PtrInfo);
13269 if (Subtarget.hasVendorXRivosVizip() && !
Op.getOperand(0).isUndef() &&
13270 !
Op.getOperand(1).isUndef()) {
13290 Op.getOperand(0),
Op.getOperand(1));
13314 DAG.
getNode(RISCVISD::ADD_VL,
DL, IdxVT, Idx, VLMax, Idx, OddMask, VL);
13319 Interleaved = DAG.
getNode(RISCVISD::VRGATHEREI16_VV_VL,
DL, ConcatVT,
13336 MVT VT =
Op.getSimpleValueType();
13338 MVT XLenVT = Subtarget.getXLenVT();
13341 uint64_t StepValImm =
Op.getConstantOperandVal(0);
13342 if (StepValImm != 1) {
13351 VL, VT,
DL, DAG, Subtarget);
13366 MVT VecVT =
Op.getSimpleValueType();
13375 MVT ContainerVT = VecVT;
13382 MVT XLenVT = Subtarget.getXLenVT();
13428 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
13429 unsigned MaxVLMAX =
13434 unsigned GatherOpc = RISCVISD::VRGATHER_VV_VL;
13439 if (MaxVLMAX > 256 && EltSize == 8) {
13455 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
13463 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
13488 DAG.
getUNDEF(ContainerVT), Mask, VL);
13500 MVT XLenVT = Subtarget.getXLenVT();
13501 MVT VecVT =
Op.getSimpleValueType();
13505 SDValue DownOffset, UpOffset;
13521 DAG, Subtarget,
DL, VecVT, DAG.
getUNDEF(VecVT), V1, DownOffset, TrueMask,
13522 Subtarget.hasVLDependentLatency() ? UpOffset
13524 return getVSlideup(DAG, Subtarget,
DL, VecVT, SlideDown, V2, UpOffset,
13530RISCVTargetLowering::lowerFixedLengthVectorLoadToRVV(
SDValue Op,
13536 Load->getMemoryVT(),
13537 *
Load->getMemOperand()) &&
13538 "Expecting a correctly-aligned load");
13540 MVT VT =
Op.getSimpleValueType();
13541 MVT XLenVT = Subtarget.getXLenVT();
13546 const auto [MinVLMAX, MaxVLMAX] =
13550 MachineMemOperand *MMO =
Load->getMemOperand();
13563 IsMaskOp ? Intrinsic::riscv_vlm : Intrinsic::riscv_vle,
DL, XLenVT);
13567 Ops.push_back(
Load->getBasePtr());
13569 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
13572 Load->getMemoryVT(),
Load->getMemOperand());
13579RISCVTargetLowering::lowerFixedLengthVectorStoreToRVV(
SDValue Op,
13585 Store->getMemoryVT(),
13586 *
Store->getMemOperand()) &&
13587 "Expecting a correctly-aligned store");
13591 MVT XLenVT = Subtarget.getXLenVT();
13607 const auto [MinVLMAX, MaxVLMAX] =
13611 MachineMemOperand *MMO =
Store->getMemOperand();
13621 IsMaskOp ? Intrinsic::riscv_vsm : Intrinsic::riscv_vse,
DL, XLenVT);
13624 {Store->getChain(), IntID, NewValue, Store->getBasePtr(), VL},
13625 Store->getMemoryVT(),
Store->getMemOperand());
13631 MVT VT =
Op.getSimpleValueType();
13634 EVT MemVT = MemSD->getMemoryVT();
13635 MachineMemOperand *MMO = MemSD->getMemOperand();
13636 SDValue Chain = MemSD->getChain();
13640 bool IsExpandingLoad =
false;
13642 Mask = VPLoad->getMask();
13644 VL = VPLoad->getVectorLength();
13648 PassThru =
MLoad->getPassThru();
13649 IsExpandingLoad =
MLoad->isExpandingLoad();
13654 MVT XLenVT = Subtarget.getXLenVT();
13656 MVT ContainerVT = VT;
13670 if (!IsUnmasked && IsExpandingLoad) {
13673 DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Mask,
13677 unsigned IntID = IsUnmasked || IsExpandingLoad ? Intrinsic::riscv_vle
13678 : Intrinsic::riscv_vle_mask;
13680 if (IntID == Intrinsic::riscv_vle)
13683 Ops.push_back(PassThru);
13684 Ops.push_back(BasePtr);
13685 if (IntID == Intrinsic::riscv_vle_mask)
13686 Ops.push_back(Mask);
13688 if (IntID == Intrinsic::riscv_vle_mask)
13691 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
13695 Chain =
Result.getValue(1);
13697 MVT IndexVT = ContainerVT;
13702 bool UseVRGATHEREI16 =
false;
13710 UseVRGATHEREI16 =
true;
13716 DAG.
getUNDEF(IndexVT), Mask, ExpandingVL);
13718 DAG.
getNode(UseVRGATHEREI16 ? RISCVISD::VRGATHEREI16_VV_VL
13719 : RISCVISD::VRGATHER_VV_VL,
13720 DL, ContainerVT, Result, Iota, PassThru, Mask, ExpandingVL);
13731 MVT VT =
Op->getSimpleValueType(0);
13734 EVT MemVT = VPLoadFF->getMemoryVT();
13735 MachineMemOperand *MMO = VPLoadFF->getMemOperand();
13736 SDValue Chain = VPLoadFF->getChain();
13740 SDValue VL = VPLoadFF->getVectorLength();
13742 MVT XLenVT = Subtarget.getXLenVT();
13744 MVT ContainerVT = VT;
13751 unsigned IntID = Intrinsic::riscv_vleff_mask;
13761 SDVTList VTs = DAG.
getVTList({ContainerVT,
Op->getValueType(1), MVT::Other});
13766 Chain =
Result.getValue(2);
13779 EVT MemVT = MemSD->getMemoryVT();
13780 MachineMemOperand *MMO = MemSD->getMemOperand();
13781 SDValue Chain = MemSD->getChain();
13785 bool IsCompressingStore =
false;
13787 Val = VPStore->getValue();
13788 Mask = VPStore->getMask();
13789 VL = VPStore->getVectorLength();
13792 Val = MStore->getValue();
13793 Mask = MStore->getMask();
13794 IsCompressingStore = MStore->isCompressingStore();
13801 MVT XLenVT = Subtarget.getXLenVT();
13803 MVT ContainerVT = VT;
13808 if (!IsUnmasked || IsCompressingStore) {
13817 if (IsCompressingStore) {
13821 DAG.
getUNDEF(ContainerVT), Val, Mask, VL);
13823 DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Mask,
13828 IsUnmasked ? Intrinsic::riscv_vse : Intrinsic::riscv_vse_mask;
13830 Ops.push_back(Val);
13831 Ops.push_back(BasePtr);
13833 Ops.push_back(Mask);
13848 MVT XLenVT = Subtarget.getXLenVT();
13849 MVT ContainerVT = VT;
13862 Passthru, Val, Mask, VL);
13872 unsigned Opc =
Op.getOpcode();
13879 MVT VT =
Op.getSimpleValueType();
13887 SDVTList VTList =
Op->getVTList();
13912 MVT ContainerInVT = InVT;
13930 RISCVISD::STRICT_FSETCC_VL,
DL, DAG.
getVTList(MaskVT, MVT::Other),
13931 {Chain, Op1, Op1, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
13934 RISCVISD::STRICT_FSETCC_VL,
DL, DAG.
getVTList(MaskVT, MVT::Other),
13935 {Chain, Op2, Op2, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
13938 DAG.
getNode(RISCVISD::VMAND_VL,
DL, MaskVT, OrderMask1, OrderMask2, VL);
13941 Res = DAG.
getNode(RISCVISD::STRICT_FSETCCS_VL,
DL,
13943 {Chain, Op1, Op2, CC, Mask, Mask, VL});
13946 : RISCVISD::STRICT_FSETCCS_VL;
13948 {Chain, Op1, Op2, CC, DAG.getUNDEF(MaskVT), Mask, VL});
13961 MVT VT =
Op.getSimpleValueType();
13965 "Unexpected type for ISD::ABS");
13967 MVT ContainerVT = VT;
13974 if (
Op->getOpcode() == ISD::VP_ABS) {
13975 Mask =
Op->getOperand(1);
13979 VL =
Op->getOperand(2);
13984 if (Subtarget.hasStdExtZvabd()) {
13986 DAG.
getUNDEF(ContainerVT), Mask, VL);
13989 RISCVISD::VMV_V_X_VL,
DL, ContainerVT, DAG.
getUNDEF(ContainerVT),
13992 DAG.
getUNDEF(ContainerVT), Mask, VL);
13994 DAG.
getUNDEF(ContainerVT), Mask, VL);
14003 const auto &TSInfo =
14007 bool HasPassthruOp = TSInfo.hasPassthruOp(NewOpc);
14008 bool HasMask = TSInfo.hasMaskOp(NewOpc);
14010 MVT VT =
Op.getSimpleValueType();
14015 for (
const SDValue &V :
Op->op_values()) {
14019 if (!
V.getValueType().isVector()) {
14025 assert(useRVVForFixedLengthVectorVT(
V.getSimpleValueType()) &&
14026 "Only fixed length vectors are supported!");
14028 V.getSimpleValueType().getVectorElementType());
14037 Ops.push_back(Mask);
14042 if (
Op->isStrictFPOpcode()) {
14061 const auto &TSInfo =
14065 bool HasPassthruOp = TSInfo.hasPassthruOp(RISCVISDOpc);
14068 MVT VT =
Op.getSimpleValueType();
14071 MVT ContainerVT = VT;
14080 if (HasPassthruOp) {
14083 if (*MaskIdx ==
OpIdx.index())
14087 if (
Op.getOpcode() == ISD::VP_MERGE) {
14089 Ops.push_back(
Ops.back());
14091 assert(
Op.getOpcode() == ISD::VP_SELECT);
14098 if (RISCVISDOpc == RISCVISD::VFCVT_RM_X_F_VL &&
14101 Subtarget.getXLenVT()));
14103 if (!
V.getValueType().isFixedLengthVector()) {
14108 MVT OpVT =
V.getSimpleValueType();
14110 assert(useRVVForFixedLengthVectorVT(OpVT) &&
14111 "Only fixed length vectors are supported!");
14126 MVT VT =
Op.getSimpleValueType();
14132 MVT ContainerVT = VT;
14139 MVT XLenVT = Subtarget.getXLenVT();
14142 DAG.
getUNDEF(ContainerVT), Zero, VL);
14145 Op.getOpcode() == ISD::VP_ZERO_EXTEND ? 1 : -1,
DL, XLenVT);
14147 DAG.
getUNDEF(ContainerVT), SplatValue, VL);
14150 ZeroSplat, DAG.
getUNDEF(ContainerVT), VL);
14159 MVT VT =
Op.getSimpleValueType();
14167 MVT ContainerVT = VT;
14175 SDValue AllOneMask = DAG.
getNode(RISCVISD::VMSET_VL,
DL, ContainerVT, VL);
14177 switch (Condition) {
14182 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, Op2, VL);
14187 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, Op2, VL);
14189 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, AllOneMask, VL);
14197 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, AllOneMask, VL);
14198 Result = DAG.
getNode(RISCVISD::VMAND_VL,
DL, ContainerVT, Temp, Op2, VL);
14206 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op2, AllOneMask, VL);
14207 Result = DAG.
getNode(RISCVISD::VMAND_VL,
DL, ContainerVT, Op1, Temp, VL);
14215 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, AllOneMask, VL);
14216 Result = DAG.
getNode(RISCVISD::VMOR_VL,
DL, ContainerVT, Temp, Op2, VL);
14224 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op2, AllOneMask, VL);
14225 Result = DAG.
getNode(RISCVISD::VMOR_VL,
DL, ContainerVT, Temp, Op1, VL);
14245 MVT DstVT =
Op.getSimpleValueType();
14246 MVT SrcVT = Src.getSimpleValueType();
14259 if (DstEltSize >= SrcEltSize) {
14263 unsigned RISCVISDExtOpc = RISCVISDOpc == RISCVISD::SINT_TO_FP_VL
14264 ? RISCVISD::VSEXT_VL
14265 : RISCVISD::VZEXT_VL;
14268 if (SrcEltSize == 1) {
14270 MVT XLenVT = Subtarget.getXLenVT();
14275 RISCVISDExtOpc == RISCVISD::VZEXT_VL ? 1 : -1,
DL, XLenVT);
14278 Src = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, IntVT, Src, OneSplat,
14279 ZeroSplat, DAG.
getUNDEF(IntVT), VL);
14280 }
else if (DstEltSize > (2 * SrcEltSize)) {
14284 Src = DAG.
getNode(RISCVISDExtOpc,
DL, IntVT, Src, Mask, VL);
14290 "Wrong input/output vector types");
14293 if (DstEltSize > (2 * SrcEltSize)) {
14298 DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, InterimFVT, Src, Mask, VL);
14309 MVT InterimFVT = DstVT;
14310 if (SrcEltSize > (2 * DstEltSize)) {
14311 assert(SrcEltSize == (4 * DstEltSize) &&
"Unexpected types!");
14318 if (InterimFVT != DstVT) {
14320 Result = DAG.
getNode(RISCVISD::FP_ROUND_VL,
DL, DstVT, Src, Mask, VL);
14324 "Wrong input/output vector types");
14328 if (DstEltSize == 1) {
14331 assert(SrcEltSize >= 16 &&
"Unexpected FP type!");
14338 MVT XLenVT = Subtarget.getXLenVT();
14340 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, InterimIVT,
14341 DAG.
getUNDEF(InterimIVT), SplatZero, VL);
14351 while (InterimIVT != DstVT) {
14363 MVT VT =
Op.getSimpleValueType();
14372 MVT VT =
Op.getSimpleValueType();
14373 MVT XLenVT = Subtarget.getXLenVT();
14386 MVT ContainerVT = VT;
14406 TrueVal = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, PromotedVT, TrueVal, SplatOne,
14407 SplatZero, DAG.
getUNDEF(PromotedVT), VL);
14410 SplatOne, SplatZero, DAG.
getUNDEF(PromotedVT), VLMax);
14414 TrueVal, FalseVal, FalseVal, VL);
14419 RISCVISD::SETCC_VL,
DL, ContainerVT,
14429RISCVTargetLowering::lowerVPSpliceExperimental(
SDValue Op,
14431 using namespace SDPatternMatch;
14442 const MVT XLenVT = Subtarget.getXLenVT();
14443 MVT VT =
Op.getSimpleValueType();
14444 MVT ContainerVT = VT;
14454 if (IsMaskVector) {
14464 Op1 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, Op1, SplatOneOp1,
14465 SplatZeroOp1, DAG.
getUNDEF(ContainerVT), EVL1);
14473 Op2 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, Op2, SplatOneOp2,
14474 SplatZeroOp2, DAG.
getUNDEF(ContainerVT), EVL2);
14477 auto getVectorFirstEle = [](
SDValue Vec) {
14490 if (
auto FirstEle = getVectorFirstEle(
Op->getOperand(0))) {
14493 if ((EltVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
14494 EltVT == MVT::bf16) {
14502 : RISCVISD::VSLIDE1UP_VL,
14503 DL, ContainerVT, DAG.
getUNDEF(ContainerVT), Op2,
14504 FirstEle, Mask, EVL2);
14514 SDValue DownOffset, UpOffset;
14515 if (ImmValue >= 0) {
14529 DAG.
getUNDEF(ContainerVT), Op1, DownOffset, Mask,
14530 Subtarget.hasVLDependentLatency() ? UpOffset : EVL2);
14534 if (IsMaskVector) {
14538 {Result, DAG.getConstant(0, DL, ContainerVT),
14539 DAG.getCondCode(ISD::SETNE), DAG.getUNDEF(getMaskTypeFor(ContainerVT)),
14549RISCVTargetLowering::lowerVPReverseExperimental(
SDValue Op,
14552 MVT VT =
Op.getSimpleValueType();
14553 MVT XLenVT = Subtarget.getXLenVT();
14559 MVT ContainerVT = VT;
14567 MVT GatherVT = ContainerVT;
14571 if (IsMaskVector) {
14581 Op1 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, IndicesVT, Op1, SplatOne,
14582 SplatZero, DAG.
getUNDEF(IndicesVT), EVL);
14587 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
14588 unsigned MaxVLMAX =
14591 unsigned GatherOpc = RISCVISD::VRGATHER_VV_VL;
14597 if (MaxVLMAX > 256 && EltSize == 8) {
14624 DAG.
getUNDEF(GatherVT), Result, Diff, Mask, EVL);
14626 if (IsMaskVector) {
14629 DAG.
getNode(RISCVISD::SETCC_VL,
DL, ContainerVT,
14642 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
14649 DAG.
getUNDEF(IndicesVT), VecLen, EVL);
14650 SDValue VRSUB = DAG.
getNode(RISCVISD::SUB_VL,
DL, IndicesVT, VecLenSplat, VID,
14651 DAG.
getUNDEF(IndicesVT), Mask, EVL);
14653 DAG.
getUNDEF(GatherVT), Mask, EVL);
14655 if (IsMaskVector) {
14658 RISCVISD::SETCC_VL,
DL, ContainerVT,
14670 MVT VT =
Op.getSimpleValueType();
14672 return lowerVPOp(
Op, DAG);
14679 MVT ContainerVT = VT;
14697 MVT XLenVT = Subtarget.getXLenVT();
14698 MVT VT =
Op.getSimpleValueType();
14699 MVT ContainerVT = VT;
14703 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
14711 : Intrinsic::riscv_vlse_mask,
14714 DAG.
getUNDEF(ContainerVT), VPNode->getBasePtr(),
14715 VPNode->getStride()};
14721 Ops.push_back(Mask);
14723 Ops.push_back(VPNode->getVectorLength());
14727 Ops.push_back(Policy);
14732 VPNode->getMemoryVT(), VPNode->getMemOperand());
14744 MVT XLenVT = Subtarget.getXLenVT();
14747 SDValue StoreVal = VPNode->getValue();
14749 MVT ContainerVT = VT;
14760 : Intrinsic::riscv_vsse_mask,
14763 VPNode->getBasePtr(), VPNode->getStride()};
14769 Ops.push_back(Mask);
14771 Ops.push_back(VPNode->getVectorLength());
14774 Ops, VPNode->getMemoryVT(),
14775 VPNode->getMemOperand());
14787 MVT VT =
Op.getSimpleValueType();
14790 EVT MemVT = MemSD->getMemoryVT();
14791 MachineMemOperand *MMO = MemSD->getMemOperand();
14792 SDValue Chain = MemSD->getChain();
14799 Index = VPGN->getIndex();
14800 Mask = VPGN->getMask();
14802 VL = VPGN->getVectorLength();
14808 Index = MGN->getIndex();
14809 Mask = MGN->getMask();
14810 PassThru = MGN->getPassThru();
14814 MVT IndexVT =
Index.getSimpleValueType();
14815 MVT XLenVT = Subtarget.getXLenVT();
14818 "Unexpected VTs!");
14819 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
14822 "Unexpected extending MGATHER/VP_GATHER");
14828 MVT ContainerVT = VT;
14852 IsUnmasked ? Intrinsic::riscv_vluxei : Intrinsic::riscv_vluxei_mask;
14857 Ops.push_back(PassThru);
14858 Ops.push_back(BasePtr);
14859 Ops.push_back(Index);
14861 Ops.push_back(Mask);
14866 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
14869 Chain =
Result.getValue(1);
14887 EVT MemVT = MemSD->getMemoryVT();
14888 MachineMemOperand *MMO = MemSD->getMemOperand();
14889 SDValue Chain = MemSD->getChain();
14892 [[maybe_unused]]
bool IsTruncatingStore =
false;
14896 Index = VPSN->getIndex();
14897 Mask = VPSN->getMask();
14898 Val = VPSN->getValue();
14899 VL = VPSN->getVectorLength();
14901 IsTruncatingStore =
false;
14905 Index = MSN->getIndex();
14906 Mask = MSN->getMask();
14907 Val = MSN->getValue();
14908 IsTruncatingStore = MSN->isTruncatingStore();
14912 MVT IndexVT =
Index.getSimpleValueType();
14913 MVT XLenVT = Subtarget.getXLenVT();
14916 "Unexpected VTs!");
14917 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
14920 assert(!IsTruncatingStore &&
"Unexpected truncating MSCATTER/VP_SCATTER");
14926 MVT ContainerVT = VT;
14950 IsUnmasked ? Intrinsic::riscv_vsoxei : Intrinsic::riscv_vsoxei_mask;
14952 Ops.push_back(Val);
14953 Ops.push_back(BasePtr);
14954 Ops.push_back(Index);
14956 Ops.push_back(Mask);
14965 const MVT XLenVT = Subtarget.getXLenVT();
14969 SDVTList VTs = DAG.
getVTList(XLenVT, MVT::Other);
14976 static const int Table =
14995 const MVT XLenVT = Subtarget.getXLenVT();
15005 static const unsigned Table =
15020 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
15026 const MVT XLenVT = Subtarget.getXLenVT();
15030 SDVTList VTs = DAG.
getVTList(XLenVT, MVT::Other);
15031 return DAG.
getNode(RISCVISD::READ_CSR,
DL, VTs, Chain, SysRegNo);
15036 const MVT XLenVT = Subtarget.getXLenVT();
15043 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
15049 const MVT XLenVT = Subtarget.getXLenVT();
15055 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
15069 SDValue Result = DAG.
getNode(RISCVISD::READ_CSR,
DL, VTs, Chain, SysRegNo);
15070 Chain = Result.getValue(1);
15076 const MVT XLenVT = Subtarget.getXLenVT();
15086 Chain = DAG.
getNode(RISCVISD::CLEAR_CSR,
DL, MVT::Other, Chain, SysRegNo,
15088 return DAG.
getNode(RISCVISD::SET_CSR,
DL, MVT::Other, Chain, SysRegNo,
15094 const MVT XLenVT = Subtarget.getXLenVT();
15101 return DAG.
getNode(RISCVISD::CLEAR_CSR,
DL, MVT::Other, Chain, SysRegNo,
15109 bool isRISCV64 = Subtarget.is64Bit();
15123 return RISCVISD::SLLW;
15125 return RISCVISD::SRAW;
15127 return RISCVISD::SRLW;
15129 return RISCVISD::DIVW;
15131 return RISCVISD::DIVUW;
15133 return RISCVISD::REMUW;
15135 return RISCVISD::ROLW;
15137 return RISCVISD::RORW;
15173 switch (
N->getOpcode()) {
15175 llvm_unreachable(
"Don't know how to custom type legalize this operation!");
15180 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
15181 "Unexpected custom legalisation");
15182 bool IsStrict =
N->isStrictFPOpcode();
15185 SDValue Op0 = IsStrict ?
N->getOperand(1) :
N->getOperand(0);
15194 !Subtarget.hasStdExtZfhOrZhinx()) {
15199 unsigned Opc = IsSigned ? RISCVISD::STRICT_FCVT_W_RV64
15200 : RISCVISD::STRICT_FCVT_WU_RV64;
15203 Opc,
DL, VTs, Chain, Op0,
15212 !Subtarget.hasStdExtZfhOrZhinx()) ||
15216 unsigned Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
15237 std::tie(Result, Chain) =
15238 makeLibCall(DAG, LC,
N->getValueType(0), Op0, CallOptions,
DL, Chain);
15253 if (Op0.
getValueType() == MVT::f16 && !Subtarget.hasStdExtZfhOrZhinx())
15257 DAG.
getNode(RISCVISD::FCVT_W_RV64,
DL, MVT::i64, Op0,
15265 RTLIB::Libcall LC =
15266 Op0.
getValueType() == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
15277 assert(!Subtarget.is64Bit() &&
"READCYCLECOUNTER/READSTEADYCOUNTER only "
15278 "has custom type legalization on riscv32");
15280 SDValue LoCounter, HiCounter;
15281 MVT XLenVT = Subtarget.getXLenVT();
15291 N->getOperand(0), LoCounter, HiCounter);
15306 if (
N->getValueType(0) == MVT::i64) {
15307 assert(Subtarget.hasStdExtZilsd() && !Subtarget.is64Bit() &&
15308 "Unexpected custom legalisation");
15310 if (Ld->
getAlign() < Subtarget.getZilsdAlign())
15315 RISCVISD::LD_RV32,
DL,
15316 DAG.
getVTList({MVT::i32, MVT::i32, MVT::Other}),
15317 {Ld->getChain(), Ld->getBasePtr()}, MVT::i64, Ld->
getMemOperand());
15321 Results.append({Pair, Result.getValue(2)});
15325 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
15326 "Unexpected custom legalisation");
15337 unsigned Size =
N->getSimpleValueType(0).getSizeInBits();
15338 unsigned XLen = Subtarget.getXLen();
15346 assert(
Size == (XLen * 2) &&
"Unexpected custom legalisation");
15349 unsigned LoHiOpc) {
15350 MVT XLenVT = Subtarget.getXLenVT();
15354 if (Subtarget.hasStdExtP() && !Subtarget.is64Bit()) {
15357 Hi =
Lo.getValue(1);
15371 if (LHSIsU && RHSIsU) {
15378 if (LHSIsS && RHSIsS)
15380 else if (RHSIsU && LHSIsS)
15382 MakeMULPair(LHS, RHS, RISCVISD::MULHSU, RISCVISD::WMULSU));
15383 else if (LHSIsU && RHSIsS)
15385 MakeMULPair(RHS, LHS, RISCVISD::MULHSU, RISCVISD::WMULSU));
15393 if (
N->getValueType(0) == MVT::i64) {
15394 assert(!Subtarget.is64Bit() && Subtarget.hasStdExtP() &&
15395 "Unexpected custom legalisation");
15398 auto [LHSLo, LHSHi] =
15400 auto [RHSLo, RHSHi] =
15403 N->getOpcode() ==
ISD::ADD ? RISCVISD::ADDD : RISCVISD::SUBD;
15405 LHSLo, LHSHi, RHSLo, RHSHi);
15411 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
15412 "Unexpected custom legalisation");
15418 EVT VT =
N->getValueType(0);
15420 assert(Subtarget.is64Bit() && (VT == MVT::v2i16 || VT == MVT::v4i8) &&
15421 "Unexpected vector type for P-extension shift");
15425 SDValue ShiftAmt =
N->getOperand(1);
15437 if (VT == MVT::i64) {
15438 assert(!Subtarget.is64Bit() && Subtarget.hasStdExtP() &&
15439 "Unexpected custom legalisation");
15444 unsigned WideOpc = 0;
15447 WideOpc = RISCVISD::WSLL;
15449 WideOpc = RISCVISD::WSLA;
15465 if (!ShAmtC || ShAmtC->getZExtValue() >= 32)
15474 uint64_t ShAmtVal = ShAmtC->getZExtValue();
15479 bool IsSRA =
N->getOpcode() ==
ISD::SRA;
15480 LoRes = DAG.
getNode(IsSRA ? RISCVISD::NSRA : RISCVISD::NSRL,
DL,
15481 MVT::i32,
Lo,
Hi, ShAmt);
15490 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
15491 "Unexpected custom legalisation");
15494 if (
N->getOpcode() ==
ISD::SHL && Subtarget.hasStdExtZbs() &&
15520 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
15521 "Unexpected custom legalisation");
15522 assert((Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb() ||
15523 Subtarget.hasVendorXTHeadBb()) &&
15524 "Unexpected custom legalization");
15526 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()))
15535 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
15536 "Unexpected custom legalisation");
15541 switch (
N->getOpcode()) {
15545 Opc = RISCVISD::CTZW;
15549 Opc = RISCVISD::CLZW;
15552 Opc = RISCVISD::CLSW;
15563 MVT VT =
N->getSimpleValueType(0);
15564 assert((VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32) &&
15565 Subtarget.is64Bit() && Subtarget.hasStdExtM() &&
15566 "Unexpected custom legalisation");
15578 if (VT != MVT::i32)
15587 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
15588 "Unexpected custom legalisation");
15610 EVT OType =
N->getValueType(1);
15627 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
15628 "Unexpected custom legalisation");
15645 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1), Res,
15649 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1),
N->getOperand(0),
15656 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1), Res, LHS,
15668 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
15669 "Unexpected custom legalisation");
15671 if (Subtarget.hasStdExtP()) {
15687 assert(!Subtarget.hasStdExtZbb() &&
"Unexpected custom legalisation");
15692 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
15693 "Unexpected custom legalisation");
15695 if (Subtarget.hasStdExtP()) {
15703 if (Subtarget.hasStdExtZbb()) {
15737 EVT VT =
N->getValueType(0);
15741 MVT XLenVT = Subtarget.getXLenVT();
15742 if (VT == MVT::i16 &&
15743 ((Op0VT == MVT::f16 && Subtarget.hasStdExtZfhminOrZhinxmin()) ||
15744 (Op0VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
15747 }
else if (VT == MVT::i32 && Op0VT == MVT::f32 && Subtarget.is64Bit() &&
15748 Subtarget.hasStdExtFOrZfinx()) {
15750 DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Op0);
15752 }
else if (VT == MVT::i64 && Op0VT == MVT::f64 && !Subtarget.is64Bit() &&
15753 Subtarget.hasStdExtDOrZdinx()) {
15755 DAG.
getVTList(MVT::i32, MVT::i32), Op0);
15759 if (!Subtarget.isLittleEndian())
15778 assert(
N->getValueType(0) == MVT::i8 && Subtarget.hasStdExtZbkb() &&
15779 "Unexpected custom legalisation");
15780 MVT XLenVT = Subtarget.getXLenVT();
15788 case RISCVISD::BREV8:
15789 case RISCVISD::ORC_B: {
15790 MVT VT =
N->getSimpleValueType(0);
15791 MVT XLenVT = Subtarget.getXLenVT();
15792 assert((VT == MVT::i16 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
15793 "Unexpected custom legalisation");
15794 assert(((
N->getOpcode() == RISCVISD::BREV8 && Subtarget.hasStdExtZbkb()) ||
15795 (
N->getOpcode() == RISCVISD::ORC_B && Subtarget.hasStdExtZbb())) &&
15796 "Unexpected extension");
15804 case RISCVISD::ASUB:
15805 case RISCVISD::ASUBU:
15806 case RISCVISD::MULHSU:
15807 case RISCVISD::MULHR:
15808 case RISCVISD::MULHRU:
15809 case RISCVISD::MULHRSU: {
15810 MVT VT =
N->getSimpleValueType(0);
15813 unsigned Opcode =
N->getOpcode();
15815 [[maybe_unused]]
bool IsMulH =
15816 Opcode == RISCVISD::MULHSU || Opcode == RISCVISD::MULHR ||
15817 Opcode == RISCVISD::MULHRU || Opcode == RISCVISD::MULHRSU;
15818 assert(VT == MVT::v2i16 || (!IsMulH && VT == MVT::v4i8));
15819 MVT NewVT = MVT::v4i16;
15820 if (VT == MVT::v4i8)
15846 assert(!Subtarget.is64Bit() &&
N->getValueType(0) == MVT::i64 &&
15848 "Unexpected EXTRACT_VECTOR_ELT legalization");
15851 MVT ContainerVT = VecVT;
15857 MVT XLenVT = Subtarget.getXLenVT();
15866 DAG.
getUNDEF(ContainerVT), Vec, Idx, Mask, VL);
15878 DAG.
getNode(RISCVISD::SRL_VL,
DL, ContainerVT, Vec, ThirtyTwoV,
15879 DAG.
getUNDEF(ContainerVT), Mask, VL);
15887 unsigned IntNo =
N->getConstantOperandVal(0);
15891 "Don't know how to custom type legalize this intrinsic!");
15892 case Intrinsic::experimental_get_vector_length: {
15897 case Intrinsic::experimental_cttz_elts: {
15902 case Intrinsic::riscv_orc_b:
15903 case Intrinsic::riscv_brev8:
15904 case Intrinsic::riscv_sha256sig0:
15905 case Intrinsic::riscv_sha256sig1:
15906 case Intrinsic::riscv_sha256sum0:
15907 case Intrinsic::riscv_sha256sum1:
15908 case Intrinsic::riscv_sm3p0:
15909 case Intrinsic::riscv_sm3p1: {
15910 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15914 case Intrinsic::riscv_orc_b:
Opc = RISCVISD::ORC_B;
break;
15915 case Intrinsic::riscv_brev8:
Opc = RISCVISD::BREV8;
break;
15916 case Intrinsic::riscv_sha256sig0:
Opc = RISCVISD::SHA256SIG0;
break;
15917 case Intrinsic::riscv_sha256sig1:
Opc = RISCVISD::SHA256SIG1;
break;
15918 case Intrinsic::riscv_sha256sum0:
Opc = RISCVISD::SHA256SUM0;
break;
15919 case Intrinsic::riscv_sha256sum1:
Opc = RISCVISD::SHA256SUM1;
break;
15920 case Intrinsic::riscv_sm3p0:
Opc = RISCVISD::SM3P0;
break;
15921 case Intrinsic::riscv_sm3p1:
Opc = RISCVISD::SM3P1;
break;
15930 case Intrinsic::riscv_sm4ks:
15931 case Intrinsic::riscv_sm4ed: {
15933 IntNo == Intrinsic::riscv_sm4ks ? RISCVISD::SM4KS : RISCVISD::SM4ED;
15939 DAG.
getNode(
Opc,
DL, MVT::i64, NewOp0, NewOp1,
N->getOperand(3));
15943 case Intrinsic::riscv_mopr: {
15944 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15949 RISCVISD::MOP_R,
DL, MVT::i64, NewOp,
15954 case Intrinsic::riscv_moprr: {
15955 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15962 RISCVISD::MOP_RR,
DL, MVT::i64, NewOp0, NewOp1,
15967 case Intrinsic::riscv_clmulh:
15968 case Intrinsic::riscv_clmulr: {
15969 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15997 case Intrinsic::riscv_vmv_x_s: {
15998 EVT VT =
N->getValueType(0);
15999 MVT XLenVT = Subtarget.getXLenVT();
16000 if (VT.
bitsLT(XLenVT)) {
16003 Subtarget.getXLenVT(),
N->getOperand(1));
16008 assert(VT == MVT::i64 && !Subtarget.is64Bit() &&
16009 "Unexpected custom legalization");
16025 SDValue LShr32 = DAG.
getNode(RISCVISD::SRL_VL,
DL, VecVT, Vec, ThirtyTwoV,
16047 case ISD::VP_REDUCE_ADD:
16048 case ISD::VP_REDUCE_AND:
16049 case ISD::VP_REDUCE_OR:
16050 case ISD::VP_REDUCE_XOR:
16051 case ISD::VP_REDUCE_SMAX:
16052 case ISD::VP_REDUCE_UMAX:
16053 case ISD::VP_REDUCE_SMIN:
16054 case ISD::VP_REDUCE_UMIN:
16122 const EVT VT =
N->getValueType(0);
16123 const unsigned Opc =
N->getOpcode();
16133 if (!
N->getFlags().hasAllowReassociation())
16144 "Inconsistent mappings");
16148 if (!
LHS.hasOneUse() || !
RHS.hasOneUse())
16176 if (0 == std::min(LHSIdx, RHSIdx) && 1 == std::max(LHSIdx, RHSIdx)) {
16179 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
N->getFlags());
16186 if (
LHS.getOpcode() != ReduceOpc)
16200 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
16201 ReduceVec->
getFlags() &
N->getFlags());
16211 auto BinOpToRVVReduce = [](
unsigned Opc) {
16216 return RISCVISD::VECREDUCE_ADD_VL;
16218 return RISCVISD::VECREDUCE_UMAX_VL;
16220 return RISCVISD::VECREDUCE_SMAX_VL;
16222 return RISCVISD::VECREDUCE_UMIN_VL;
16224 return RISCVISD::VECREDUCE_SMIN_VL;
16226 return RISCVISD::VECREDUCE_AND_VL;
16228 return RISCVISD::VECREDUCE_OR_VL;
16230 return RISCVISD::VECREDUCE_XOR_VL;
16232 return RISCVISD::VECREDUCE_FADD_VL;
16234 return RISCVISD::VECREDUCE_FMAX_VL;
16236 return RISCVISD::VECREDUCE_FMIN_VL;
16240 auto IsReduction = [&BinOpToRVVReduce](
SDValue V,
unsigned Opc) {
16243 V.getOperand(0).getOpcode() == BinOpToRVVReduce(
Opc);
16246 unsigned Opc =
N->getOpcode();
16247 unsigned ReduceIdx;
16248 if (IsReduction(
N->getOperand(0),
Opc))
16250 else if (IsReduction(
N->getOperand(1),
Opc))
16256 if (
Opc ==
ISD::FADD && !
N->getFlags().hasAllowReassociation())
16259 SDValue Extract =
N->getOperand(ReduceIdx);
16272 if (ScalarV.
getOpcode() != RISCVISD::VFMV_S_F_VL &&
16273 ScalarV.
getOpcode() != RISCVISD::VMV_S_X_VL &&
16274 ScalarV.
getOpcode() != RISCVISD::VMV_V_X_VL)
16291 SDValue NewStart =
N->getOperand(1 - ReduceIdx);
16324 EVT VT =
N->getValueType(0);
16340 int64_t C0 = N0C->getSExtValue();
16341 int64_t C1 = N1C->getSExtValue();
16342 if (C0 <= 0 || C1 <= 0)
16345 int64_t Diff = std::abs(C0 - C1);
16351 int64_t Bits = std::min(C0, C1);
16383 if (VShift.
slt(1) || VShift.
sgt(3))
16387 EVT VT =
N->getValueType(0);
16407 EVT VT =
N->getValueType(0);
16435 EVT VT =
N->getValueType(0);
16456 Slct.
getOpcode() != RISCVISD::SELECT_CC) ||
16464 bool SwapSelectOps;
16465 unsigned OpOffset = Slct.
getOpcode() == RISCVISD::SELECT_CC ? 2 : 0;
16470 SwapSelectOps =
false;
16471 NonConstantVal = FalseVal;
16473 SwapSelectOps =
true;
16474 NonConstantVal = TrueVal;
16480 FalseVal = DAG.
getNode(
N->getOpcode(),
SDLoc(
N), VT, OtherOp, NonConstantVal);
16485 if (Slct.
getOpcode() == RISCVISD::SELECT_CC)
16528 EVT VT =
N->getValueType(0);
16543 if (!N0C->hasOneUse())
16545 int64_t C0 = N0C->getSExtValue();
16546 int64_t C1 = N1C->getSExtValue();
16548 if (C0 == -1 || C0 == 0 || C0 == 1 ||
isInt<12>(C1))
16555 }
else if ((C1 / C0 + 1) != 0 &&
isInt<12>(C1 / C0 + 1) &&
16559 }
else if ((C1 / C0 - 1) != 0 &&
isInt<12>(C1 / C0 - 1) &&
16587 EVT VT =
N->getValueType(0);
16618 unsigned OuterExtend =
16622 OuterExtend,
SDLoc(
N), VT,
16630 EVT VT =
N->getValueType(0);
16680 EVT VT =
N->getValueType(0);
16690 APInt ImmValMinus1 = N0C->getAPIntValue() - 1;
16700 if (!isIntEqualitySetCC(CCVal) || !SetCCOpVT.
isInteger())
16723 if (!Subtarget.hasStdExtZbb())
16726 EVT VT =
N->getValueType(0);
16728 if (VT != Subtarget.
getXLenVT() && VT != MVT::i32 && VT != MVT::i16)
16740 unsigned ShiftedAmount = 8 - ShAmtCLeft->getZExtValue();
16742 if (ShiftedAmount >= 8)
16746 SDValue RightShiftOperand = N1;
16748 if (ShiftedAmount != 0) {
16752 if (!ShAmtCRight || ShAmtCRight->getZExtValue() != ShiftedAmount)
16761 if (LeftShiftOperand != RightShiftOperand)
16765 Mask <<= ShiftedAmount;
16771 return DAG.
getNode(RISCVISD::ORC_B,
SDLoc(
N), VT, LeftShiftOperand);
16779 EVT VT =
N->getValueType(0);
16811 bool IsAnd =
N->getOpcode() ==
ISD::AND;
16835 EVT VT =
N->getValueType(0);
16859 EVT VT =
N->getValueType(0);
16886 if (CondLHS != True)
16893 if (!CondRHSC || CondRHSC->
getAPIntValue() != (1ULL << ScalarBits))
16905 if (!FalseRHSC || !FalseRHSC->
isZero())
16929 EVT VT =
N->getValueType(0);
16934 if (VecVT != MVT::v4i16 && VecVT != MVT::v2i16 && VecVT != MVT::v8i8 &&
16935 VecVT != MVT::v4i8 && VecVT != MVT::v2i32)
16954 unsigned ShAmtVal =
C->getZExtValue();
16958 bool IsRounding =
false;
16959 if (
Op.getOpcode() ==
ISD::ADD && (EltBits == 16 || EltBits == 32)) {
16964 uint64_t ExpectedRnd = 1ULL << (EltBits - 1);
16965 if (RndC->getZExtValue() == ExpectedRnd &&
16967 Op =
Op.getOperand(0);
16982 if (!(LHSIsSExt || LHSIsZExt) || !(RHSIsSExt || RHSIsZExt))
16988 if (
A.getValueType() != VT ||
B.getValueType() != VT)
16992 switch (
Op.getOpcode()) {
16999 if (LHSIsSExt && RHSIsSExt)
17000 Opc = RISCVISD::ASUB;
17001 else if (LHSIsZExt && RHSIsZExt)
17002 Opc = RISCVISD::ASUBU;
17008 if (ShAmtVal != EltBits || (EltBits != 16 && EltBits != 32))
17011 if (LHSIsSExt && RHSIsSExt) {
17012 Opc = RISCVISD::MULHR;
17013 }
else if (LHSIsZExt && RHSIsZExt) {
17014 Opc = RISCVISD::MULHRU;
17015 }
else if ((LHSIsSExt && RHSIsZExt) || (LHSIsZExt && RHSIsSExt)) {
17016 Opc = RISCVISD::MULHRSU;
17018 if (LHSIsZExt && RHSIsSExt)
17024 if ((LHSIsSExt && RHSIsZExt) || (LHSIsZExt && RHSIsSExt)) {
17025 Opc = RISCVISD::MULHSU;
17027 if (LHSIsZExt && RHSIsSExt)
17041 EVT VT =
N->getValueType(0);
17051 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() && VT == MVT::i1 &&
17094 EVT VT =
N->getValueType(0);
17113 EVT WideVT =
X.getValueType();
17140 auto IsEqualCompZero = [](
SDValue &V) ->
bool {
17149 if (!IsEqualCompZero(N0) || !N0.
hasOneUse())
17151 if (!IsEqualCompZero(N0) || !N0.
hasOneUse())
17158 unsigned CzeroOpcode =
17160 ? RISCVISD::CZERO_EQZ
17161 : RISCVISD::CZERO_NEZ;
17163 EVT VT =
N->getValueType(0);
17190 if (Mask != ExpectedMask)
17207 EVT VT =
N->getValueType(0);
17213 APInt MaskVal, ShiftVal;
17228 APInt InnerMask = MaskVal.
lshr(ShiftAmt);
17229 bool IsNarrowable =
17230 InnerMask == 0xff || InnerMask == 0xffff || InnerMask == 0xffffffff;
17258 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
17300 if (N0.
getOpcode() != RISCVISD::CZERO_EQZ ||
17301 N1.
getOpcode() != RISCVISD::CZERO_NEZ ||
17319 EVT VT =
N->getValueType(0);
17337 if (!Subtarget.hasVendorXqcibm())
17349 if (
N->getValueType(0) != MVT::i32)
17351 unsigned Width, ShAmt;
17368 return DAG.
getNode(RISCVISD::QC_INSB,
DL, MVT::i32,
Ops);
17373 if (!Subtarget.hasVendorXqcibm())
17383 unsigned ShAmt, Width;
17387 if (
N->getValueType(0) != MVT::i32)
17392 if (Width == 1 && Subtarget.hasStdExtZbs())
17404 return DAG.
getNode(RISCVISD::QC_INSB,
DL, MVT::i32,
Ops);
17412 if (!Subtarget.hasVendorXqcibm())
17418 APInt MaskImm, OrImm;
17437 unsigned ShAmt, Width;
17450 return DAG.
getNode(RISCVISD::QC_INSB,
DL, MVT::i32,
Ops);
17493 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
17508 if (N0.
getOpcode() == RISCVISD::SLLW &&
17512 return DAG.
getNode(RISCVISD::ROLW,
DL, MVT::i64,
17523 const APInt &Imm = ConstN00->getAPIntValue();
17524 if ((Imm + 1).isSignedIntN(12))
17548 EVT VT =
N->getValueType(0);
17557 bool IsAdd = (
E & 3) == 1;
17558 E -= IsAdd ? 1 : -1;
17562 Result = DAG.
getNode(AddSubOp,
DL, VT, Result, ShiftVal);
17572 uint64_t MulAmtLowBit = MulAmt & (-MulAmt);
17577 auto PreferSub = [
X, MulAmtLowBit]() {
17586 if (
isPowerOf2_64(MulAmt - MulAmtLowBit) && !(CanSub && PreferSub())) {
17588 ShiftAmt1 = MulAmt - MulAmtLowBit;
17589 }
else if (CanSub) {
17591 ShiftAmt1 = MulAmt + MulAmtLowBit;
17595 EVT VT =
N->getValueType(0);
17605 unsigned ShY,
bool AddX,
unsigned Shift) {
17607 EVT VT =
N->getValueType(0);
17622 ShlAdd = DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, ShlAdd,
17632 uint64_t MulAmt,
unsigned Shift) {
17658 assert(ShX != 0 &&
"MulAmt=4,6,10 handled before");
17665 EVT VT =
N->getValueType(0);
17682 EVT VT =
N->getValueType(0);
17691 bool ShouldExpandMul =
17693 !Subtarget.hasStdExtZmmul();
17694 if (!ShouldExpandMul)
17724 if (Shift >= 1 && Shift <= 3 &&
isPowerOf2_64(MulAmt & (MulAmt - 1))) {
17729 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT,
X,
17736 if (MulAmt > 2 &&
isPowerOf2_64((MulAmt - 1) & (MulAmt - 2))) {
17738 if (ScaleShift >= 1 && ScaleShift < 4) {
17770 if (!Subtarget.hasStdExtZmmul())
17780 EVT VT =
N->getValueType(0);
17787 if (
N->getOperand(0).getOpcode() !=
ISD::AND ||
17788 N->getOperand(0).getOperand(0).getOpcode() !=
ISD::SRL)
17801 if (!V1.
isMask(HalfSize) || V2 != (1ULL | 1ULL << HalfSize) ||
17802 V3 != (HalfSize - 1))
17818 EVT VT =
N->getValueType(0);
17826 unsigned AddSubOpc;
17832 auto IsAddSubWith1 = [&](
SDValue V) ->
bool {
17833 AddSubOpc = V->getOpcode();
17845 if (IsAddSubWith1(N0)) {
17847 return DAG.
getNode(AddSubOpc,
DL, VT, N1, MulVal);
17850 if (IsAddSubWith1(N1)) {
17852 return DAG.
getNode(AddSubOpc,
DL, VT, N0, MulVal);
17867 if (isIndexTypeSigned(IndexType))
17870 if (!
N->hasOneUse())
17873 EVT VT =
N.getValueType();
17912 EVT SrcVT = Src.getValueType();
17916 NewElen = std::max(NewElen, 8U);
17943 EVT OpVT =
X.getValueType();
17951 if (OpSize <= Subtarget.
getXLen() ||
17957 auto IsVectorBitCastCheap = [](
SDValue X) {
17962 if (!IsVectorBitCastCheap(
X) || !IsVectorBitCastCheap(
Y))
17966 Attribute::NoImplicitFloat))
17973 unsigned VecSize = OpSize / 8;
17984 DAG.
getNode(ISD::VP_REDUCE_OR,
DL, XLenVT,
17997 EVT VT =
N->getValueType(0);
18002 if (!isIntEqualitySetCC(
Cond))
18027 if (OpVT == MVT::i64 &&
isUInt<32>(AndRHSInt) &&
18031 if (NewC >= -2048 && NewC <= 2048) {
18037 return DAG.
getSetCC(dl, VT, Shift,
18048 if (N1Width <= TrailingOnes &&
isInt<12>(N1SExt) &&
18059 if (OpVT != MVT::i64 || !Subtarget.
is64Bit())
18079 const APInt &C1 = N1C->getAPIntValue();
18097 EVT VT =
N->getValueType(0);
18099 unsigned Opc = Src.getOpcode();
18104 if (
Opc == RISCVISD::FMV_X_ANYEXTH && SrcVT.
bitsGE(MVT::i16) &&
18105 Subtarget.hasStdExtZfhmin())
18106 return DAG.
getNode(RISCVISD::FMV_X_SIGNEXTH,
DL, VT, Src.getOperand(0));
18112 return DAG.
getNode(RISCVISD::SLLW,
DL, VT, Src.getOperand(0),
18113 Src.getOperand(1));
18132struct CombineResult;
18134enum ExtKind : uint8_t {
18166struct NodeExtensionHelper {
18175 bool SupportsFPExt;
18177 bool SupportsBF16Ext;
18180 bool EnforceOneUse;
18190 case RISCVISD::VSEXT_VL:
18191 case RISCVISD::VZEXT_VL:
18192 case RISCVISD::FP_EXTEND_VL:
18195 return OrigOperand;
18201 return OrigOperand.
getOpcode() == RISCVISD::VMV_V_X_VL ||
18206 unsigned getExtOpc(ExtKind SupportsExt)
const {
18207 switch (SupportsExt) {
18208 case ExtKind::SExt:
18209 return RISCVISD::VSEXT_VL;
18210 case ExtKind::ZExt:
18211 return RISCVISD::VZEXT_VL;
18212 case ExtKind::FPExt:
18213 case ExtKind::BF16Ext:
18214 return RISCVISD::FP_EXTEND_VL;
18222 SDValue getOrCreateExtendedOp(SDNode *Root, SelectionDAG &DAG,
18223 const RISCVSubtarget &Subtarget,
18224 std::optional<ExtKind> SupportsExt)
const {
18225 if (!SupportsExt.has_value())
18226 return OrigOperand;
18228 MVT NarrowVT = getNarrowType(Root, *SupportsExt);
18232 if (
Source.getValueType() == NarrowVT)
18235 unsigned ExtOpc = getExtOpc(*SupportsExt);
18238 SDLoc
DL(OrigOperand);
18239 auto [
Mask, VL] = getMaskAndVL(Root, DAG, Subtarget);
18243 case RISCVISD::VSEXT_VL:
18244 case RISCVISD::VZEXT_VL:
18245 case RISCVISD::FP_EXTEND_VL:
18246 return DAG.
getNode(ExtOpc,
DL, NarrowVT, Source, Mask, VL);
18249 case RISCVISD::VMV_V_X_VL:
18250 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, NarrowVT,
18252 case RISCVISD::VFMV_V_F_VL:
18257 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL, NarrowVT,
18258 DAG.
getUNDEF(NarrowVT), Source, VL);
18271 static MVT getNarrowType(
const SDNode *Root, ExtKind SupportsExt) {
18277 MVT EltVT = SupportsExt == ExtKind::BF16Ext ? MVT::bf16
18278 : SupportsExt == ExtKind::FPExt
18280 : MVT::getIntegerVT(NarrowSize);
18282 assert((
int)NarrowSize >= (SupportsExt == ExtKind::FPExt ? 16 : 8) &&
18283 "Trying to extend something we can't represent");
18290 static unsigned getSExtOpcode(
unsigned Opcode) {
18293 case RISCVISD::ADD_VL:
18294 case RISCVISD::VWADD_W_VL:
18295 case RISCVISD::VWADDU_W_VL:
18297 case RISCVISD::OR_VL:
18298 return RISCVISD::VWADD_VL;
18300 case RISCVISD::SUB_VL:
18301 case RISCVISD::VWSUB_W_VL:
18302 case RISCVISD::VWSUBU_W_VL:
18303 return RISCVISD::VWSUB_VL;
18305 case RISCVISD::MUL_VL:
18306 return RISCVISD::VWMUL_VL;
18314 static unsigned getZExtOpcode(
unsigned Opcode) {
18317 case RISCVISD::ADD_VL:
18318 case RISCVISD::VWADD_W_VL:
18319 case RISCVISD::VWADDU_W_VL:
18321 case RISCVISD::OR_VL:
18322 return RISCVISD::VWADDU_VL;
18324 case RISCVISD::SUB_VL:
18325 case RISCVISD::VWSUB_W_VL:
18326 case RISCVISD::VWSUBU_W_VL:
18327 return RISCVISD::VWSUBU_VL;
18329 case RISCVISD::MUL_VL:
18330 return RISCVISD::VWMULU_VL;
18332 case RISCVISD::SHL_VL:
18333 return RISCVISD::VWSLL_VL;
18341 static unsigned getFPExtOpcode(
unsigned Opcode) {
18343 case RISCVISD::FADD_VL:
18344 case RISCVISD::VFWADD_W_VL:
18345 return RISCVISD::VFWADD_VL;
18346 case RISCVISD::FSUB_VL:
18347 case RISCVISD::VFWSUB_W_VL:
18348 return RISCVISD::VFWSUB_VL;
18349 case RISCVISD::FMUL_VL:
18350 return RISCVISD::VFWMUL_VL;
18351 case RISCVISD::VFMADD_VL:
18352 return RISCVISD::VFWMADD_VL;
18353 case RISCVISD::VFMSUB_VL:
18354 return RISCVISD::VFWMSUB_VL;
18355 case RISCVISD::VFNMADD_VL:
18356 return RISCVISD::VFWNMADD_VL;
18357 case RISCVISD::VFNMSUB_VL:
18358 return RISCVISD::VFWNMSUB_VL;
18366 static unsigned getSUOpcode(
unsigned Opcode) {
18368 "SU is only supported for MUL");
18369 return RISCVISD::VWMULSU_VL;
18374 static unsigned getWOpcode(
unsigned Opcode, ExtKind SupportsExt) {
18377 case RISCVISD::ADD_VL:
18379 case RISCVISD::OR_VL:
18380 return SupportsExt == ExtKind::SExt ? RISCVISD::VWADD_W_VL
18381 : RISCVISD::VWADDU_W_VL;
18383 case RISCVISD::SUB_VL:
18384 return SupportsExt == ExtKind::SExt ? RISCVISD::VWSUB_W_VL
18385 : RISCVISD::VWSUBU_W_VL;
18386 case RISCVISD::FADD_VL:
18387 return RISCVISD::VFWADD_W_VL;
18388 case RISCVISD::FSUB_VL:
18389 return RISCVISD::VFWSUB_W_VL;
18395 using CombineToTry = std::function<std::optional<CombineResult>(
18396 SDNode * ,
const NodeExtensionHelper & ,
18397 const NodeExtensionHelper & , SelectionDAG &,
18398 const RISCVSubtarget &)>;
18401 bool needToPromoteOtherUsers()
const {
return EnforceOneUse; }
18403 void fillUpExtensionSupportForSplat(SDNode *Root, SelectionDAG &DAG,
18404 const RISCVSubtarget &Subtarget) {
18409 "Unexpected Opcode");
18422 unsigned ScalarBits =
Op.getValueSizeInBits();
18424 if (ScalarBits < EltBits) {
18426 assert(
Opc == RISCVISD::VMV_V_X_VL && EltBits == 64 && ScalarBits == 32 &&
18427 !Subtarget.
is64Bit() &&
"Unexpected splat");
18429 SupportsSExt =
true;
18433 SupportsZExt =
true;
18435 EnforceOneUse =
false;
18439 unsigned NarrowSize = EltBits / 2;
18442 if (NarrowSize < 8)
18446 SupportsSExt =
true;
18450 SupportsZExt =
true;
18452 EnforceOneUse =
false;
18455 bool isSupportedFPExtend(MVT NarrowEltVT,
const RISCVSubtarget &Subtarget) {
18456 return (NarrowEltVT == MVT::f32 ||
18460 bool isSupportedBF16Extend(MVT NarrowEltVT,
const RISCVSubtarget &Subtarget) {
18461 return NarrowEltVT == MVT::bf16 &&
18467 void fillUpExtensionSupport(SDNode *Root, SelectionDAG &DAG,
18468 const RISCVSubtarget &Subtarget) {
18469 SupportsZExt =
false;
18470 SupportsSExt =
false;
18471 SupportsFPExt =
false;
18472 SupportsBF16Ext =
false;
18473 EnforceOneUse =
true;
18495 case RISCVISD::VZEXT_VL:
18496 SupportsZExt =
true;
18498 case RISCVISD::VSEXT_VL:
18499 SupportsSExt =
true;
18501 case RISCVISD::FP_EXTEND_VL: {
18504 if (isSupportedFPExtend(NarrowEltVT, Subtarget))
18505 SupportsFPExt =
true;
18506 if (isSupportedBF16Extend(NarrowEltVT, Subtarget))
18507 SupportsBF16Ext =
true;
18512 case RISCVISD::VMV_V_X_VL:
18513 fillUpExtensionSupportForSplat(Root, DAG, Subtarget);
18515 case RISCVISD::VFMV_V_F_VL: {
18526 unsigned ScalarBits =
Op.getOperand(0).getValueSizeInBits();
18527 if (NarrowSize != ScalarBits)
18530 if (isSupportedFPExtend(
Op.getOperand(0).getSimpleValueType(), Subtarget))
18531 SupportsFPExt =
true;
18532 if (isSupportedBF16Extend(
Op.getOperand(0).getSimpleValueType(),
18534 SupportsBF16Ext =
true;
18543 static bool isSupportedRoot(
const SDNode *Root,
18544 const RISCVSubtarget &Subtarget) {
18556 case RISCVISD::ADD_VL:
18557 case RISCVISD::MUL_VL:
18558 case RISCVISD::VWADD_W_VL:
18559 case RISCVISD::VWADDU_W_VL:
18560 case RISCVISD::SUB_VL:
18561 case RISCVISD::VWSUB_W_VL:
18562 case RISCVISD::VWSUBU_W_VL:
18564 case RISCVISD::FADD_VL:
18565 case RISCVISD::FSUB_VL:
18566 case RISCVISD::FMUL_VL:
18567 case RISCVISD::VFWADD_W_VL:
18568 case RISCVISD::VFWSUB_W_VL:
18570 case RISCVISD::OR_VL:
18574 Subtarget.hasStdExtZvbb();
18575 case RISCVISD::SHL_VL:
18576 return Subtarget.hasStdExtZvbb();
18577 case RISCVISD::VFMADD_VL:
18578 case RISCVISD::VFNMSUB_VL:
18579 case RISCVISD::VFNMADD_VL:
18580 case RISCVISD::VFMSUB_VL:
18588 NodeExtensionHelper(SDNode *Root,
unsigned OperandIdx, SelectionDAG &DAG,
18589 const RISCVSubtarget &Subtarget) {
18590 assert(isSupportedRoot(Root, Subtarget) &&
18591 "Trying to build an helper with an "
18592 "unsupported root");
18593 assert(OperandIdx < 2 &&
"Requesting something else than LHS or RHS");
18603 case RISCVISD::VWADD_W_VL:
18604 case RISCVISD::VWADDU_W_VL:
18605 case RISCVISD::VWSUB_W_VL:
18606 case RISCVISD::VWSUBU_W_VL:
18607 case RISCVISD::VFWADD_W_VL:
18608 case RISCVISD::VFWSUB_W_VL:
18610 if (OperandIdx == 1)
18614 fillUpExtensionSupport(Root, DAG, Subtarget);
18620 static std::pair<SDValue, SDValue>
18621 getMaskAndVL(
const SDNode *Root, SelectionDAG &DAG,
18622 const RISCVSubtarget &Subtarget) {
18623 assert(isSupportedRoot(Root, Subtarget) &&
"Unexpected root");
18642 switch (
N->getOpcode()) {
18646 case RISCVISD::ADD_VL:
18647 case RISCVISD::MUL_VL:
18648 case RISCVISD::OR_VL:
18649 case RISCVISD::FADD_VL:
18650 case RISCVISD::FMUL_VL:
18651 case RISCVISD::VFMADD_VL:
18652 case RISCVISD::VFNMSUB_VL:
18653 case RISCVISD::VFNMADD_VL:
18654 case RISCVISD::VFMSUB_VL:
18656 case RISCVISD::VWADD_W_VL:
18657 case RISCVISD::VWADDU_W_VL:
18659 case RISCVISD::SUB_VL:
18660 case RISCVISD::VWSUB_W_VL:
18661 case RISCVISD::VWSUBU_W_VL:
18662 case RISCVISD::VFWADD_W_VL:
18663 case RISCVISD::FSUB_VL:
18664 case RISCVISD::VFWSUB_W_VL:
18666 case RISCVISD::SHL_VL:
18681 getSupportedFoldings(
const SDNode *Root,
const RISCVSubtarget &Subtarget);
18686struct CombineResult {
18688 unsigned TargetOpcode;
18690 std::optional<ExtKind> LHSExt;
18691 std::optional<ExtKind> RHSExt;
18695 NodeExtensionHelper
LHS;
18697 NodeExtensionHelper
RHS;
18699 CombineResult(
unsigned TargetOpcode, SDNode *Root,
18700 const NodeExtensionHelper &
LHS, std::optional<ExtKind> LHSExt,
18701 const NodeExtensionHelper &
RHS, std::optional<ExtKind> RHSExt)
18702 : TargetOpcode(TargetOpcode), LHSExt(LHSExt), RHSExt(RHSExt), Root(Root),
18708 SDValue materialize(SelectionDAG &DAG,
18709 const RISCVSubtarget &Subtarget)
const {
18711 std::tie(Mask, VL) =
18712 NodeExtensionHelper::getMaskAndVL(Root, DAG, Subtarget);
18726 LHS.getOrCreateExtendedOp(Root, DAG, Subtarget, LHSExt),
18727 RHS.getOrCreateExtendedOp(Root, DAG, Subtarget, RHSExt),
18728 Passthru, Mask, VL);
18742static std::optional<CombineResult>
18743canFoldToVWWithSameExtensionImpl(
SDNode *Root,
const NodeExtensionHelper &
LHS,
18744 const NodeExtensionHelper &
RHS,
18747 if ((AllowExtMask & ExtKind::ZExt) &&
LHS.SupportsZExt &&
RHS.SupportsZExt)
18748 return CombineResult(NodeExtensionHelper::getZExtOpcode(Root->
getOpcode()),
18749 Root,
LHS, {ExtKind::ZExt},
RHS,
18751 if ((AllowExtMask & ExtKind::SExt) &&
LHS.SupportsSExt &&
RHS.SupportsSExt)
18752 return CombineResult(NodeExtensionHelper::getSExtOpcode(Root->
getOpcode()),
18753 Root,
LHS, {ExtKind::SExt},
RHS,
18755 if ((AllowExtMask & ExtKind::FPExt) &&
LHS.SupportsFPExt &&
RHS.SupportsFPExt)
18756 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
18757 Root,
LHS, {ExtKind::FPExt},
RHS,
18759 if ((AllowExtMask & ExtKind::BF16Ext) &&
LHS.SupportsBF16Ext &&
18760 RHS.SupportsBF16Ext)
18761 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
18762 Root,
LHS, {ExtKind::BF16Ext},
RHS,
18763 {ExtKind::BF16Ext});
18764 return std::nullopt;
18773static std::optional<CombineResult>
18774canFoldToVWWithSameExtension(
SDNode *Root,
const NodeExtensionHelper &
LHS,
18777 return canFoldToVWWithSameExtensionImpl(
18778 Root,
LHS,
RHS, ExtKind::ZExt | ExtKind::SExt | ExtKind::FPExt, DAG,
18786static std::optional<CombineResult>
18787canFoldToVWWithSameExtZEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
18790 return canFoldToVWWithSameExtensionImpl(Root,
LHS,
RHS, ExtKind::ZExt, DAG,
18798static std::optional<CombineResult>
18799canFoldToVWWithSameExtBF16(
SDNode *Root,
const NodeExtensionHelper &
LHS,
18802 return canFoldToVWWithSameExtensionImpl(Root,
LHS,
RHS, ExtKind::BF16Ext, DAG,
18810static std::optional<CombineResult>
18811canFoldToVW_W(
SDNode *Root,
const NodeExtensionHelper &
LHS,
18814 if (
RHS.SupportsFPExt)
18815 return CombineResult(
18816 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::FPExt),
18817 Root,
LHS, std::nullopt,
RHS, {ExtKind::FPExt});
18824 return CombineResult(
18825 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::ZExt), Root,
18826 LHS, std::nullopt,
RHS, {ExtKind::ZExt});
18828 return CombineResult(
18829 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::SExt), Root,
18830 LHS, std::nullopt,
RHS, {ExtKind::SExt});
18831 return std::nullopt;
18838static std::optional<CombineResult>
18839canFoldToVWWithSEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
18842 if (
LHS.SupportsSExt)
18843 return CombineResult(NodeExtensionHelper::getSExtOpcode(Root->
getOpcode()),
18844 Root,
LHS, {ExtKind::SExt},
RHS,
18846 return std::nullopt;
18853static std::optional<CombineResult>
18854canFoldToVWWithZEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
18857 if (
LHS.SupportsZExt)
18858 return CombineResult(NodeExtensionHelper::getZExtOpcode(Root->
getOpcode()),
18859 Root,
LHS, {ExtKind::ZExt},
RHS,
18861 return std::nullopt;
18868static std::optional<CombineResult>
18869canFoldToVWWithFPEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
18872 if (
LHS.SupportsFPExt)
18873 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
18874 Root,
LHS, {ExtKind::FPExt},
RHS,
18876 return std::nullopt;
18883static std::optional<CombineResult>
18884canFoldToVW_SU(
SDNode *Root,
const NodeExtensionHelper &
LHS,
18888 if (!
LHS.SupportsSExt || !
RHS.SupportsZExt)
18889 return std::nullopt;
18890 return CombineResult(NodeExtensionHelper::getSUOpcode(Root->
getOpcode()),
18891 Root,
LHS, {ExtKind::SExt},
RHS,
18896NodeExtensionHelper::getSupportedFoldings(
const SDNode *Root,
18903 case RISCVISD::ADD_VL:
18904 case RISCVISD::SUB_VL:
18905 case RISCVISD::OR_VL:
18906 case RISCVISD::FADD_VL:
18907 case RISCVISD::FSUB_VL:
18909 Strategies.
push_back(canFoldToVWWithSameExtension);
18913 case RISCVISD::FMUL_VL:
18914 case RISCVISD::VFMADD_VL:
18915 case RISCVISD::VFMSUB_VL:
18916 case RISCVISD::VFNMADD_VL:
18917 case RISCVISD::VFNMSUB_VL:
18918 Strategies.
push_back(canFoldToVWWithSameExtension);
18919 if (Subtarget.hasStdExtZvfbfa() && Root->
getOpcode() != RISCVISD::FMUL_VL)
18922 Strategies.
push_back(canFoldToVWWithSameExtBF16);
18923 else if (Subtarget.hasStdExtZvfbfwma() &&
18924 Root->
getOpcode() == RISCVISD::VFMADD_VL)
18925 Strategies.
push_back(canFoldToVWWithSameExtBF16);
18928 case RISCVISD::MUL_VL:
18930 Strategies.
push_back(canFoldToVWWithSameExtension);
18935 case RISCVISD::SHL_VL:
18937 Strategies.
push_back(canFoldToVWWithSameExtZEXT);
18939 case RISCVISD::VWADD_W_VL:
18940 case RISCVISD::VWSUB_W_VL:
18942 Strategies.
push_back(canFoldToVWWithSEXT);
18944 case RISCVISD::VWADDU_W_VL:
18945 case RISCVISD::VWSUBU_W_VL:
18947 Strategies.
push_back(canFoldToVWWithZEXT);
18949 case RISCVISD::VFWADD_W_VL:
18950 case RISCVISD::VFWSUB_W_VL:
18952 Strategies.
push_back(canFoldToVWWithFPEXT);
18963 assert(
N->getOpcode() == RISCVISD::ADD_VL);
18966 SDValue Passthru =
N->getOperand(2);
19000 if (!NodeExtensionHelper::isSupportedRoot(
N, Subtarget))
19007 Inserted.insert(
N);
19010 while (!Worklist.
empty()) {
19013 NodeExtensionHelper
LHS(Root, 0, DAG, Subtarget);
19014 NodeExtensionHelper
RHS(Root, 1, DAG, Subtarget);
19015 auto AppendUsersIfNeeded =
19016 [&Worklist, &Subtarget, &Inserted,
19017 &ExtensionsToRemove](
const NodeExtensionHelper &
Op) {
19018 if (
Op.needToPromoteOtherUsers()) {
19020 ExtensionsToRemove.
insert(
Op.OrigOperand.getNode());
19023 if (!NodeExtensionHelper::isSupportedRoot(TheUser, Subtarget))
19028 if (Inserted.insert(TheUser).second)
19041 NodeExtensionHelper::getSupportedFoldings(Root, Subtarget);
19043 assert(!FoldingStrategies.
empty() &&
"Nothing to be folded");
19044 bool Matched =
false;
19045 for (
int Attempt = 0;
19046 (Attempt != 1 + NodeExtensionHelper::isCommutative(Root)) && !Matched;
19049 for (NodeExtensionHelper::CombineToTry FoldingStrategy :
19050 FoldingStrategies) {
19051 std::optional<CombineResult> Res =
19052 FoldingStrategy(Root,
LHS,
RHS, DAG, Subtarget);
19056 if (!Res->LHSExt.has_value() &&
19057 ExtensionsToRemove.
contains(
LHS.OrigOperand.getNode()))
19059 if (!Res->RHSExt.has_value() &&
19060 ExtensionsToRemove.
contains(
RHS.OrigOperand.getNode()))
19068 if (Res->LHSExt.has_value())
19069 if (!AppendUsersIfNeeded(
LHS))
19071 if (Res->RHSExt.has_value())
19072 if (!AppendUsersIfNeeded(
RHS))
19084 SDValue InputRootReplacement;
19091 for (CombineResult Res : CombinesToApply) {
19092 SDValue NewValue = Res.materialize(DAG, Subtarget);
19093 if (!InputRootReplacement) {
19095 "First element is expected to be the current node");
19096 InputRootReplacement = NewValue;
19101 for (std::pair<SDValue, SDValue> OldNewValues : ValuesToReplace) {
19102 DCI.
CombineTo(OldNewValues.first.getNode(), OldNewValues.second);
19104 return InputRootReplacement;
19111 unsigned Opc =
N->getOpcode();
19112 assert(
Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWADDU_W_VL ||
19113 Opc == RISCVISD::VWSUB_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL);
19116 SDValue MergeOp =
N->getOperand(1);
19117 unsigned MergeOpc = MergeOp.
getOpcode();
19119 if (MergeOpc != RISCVISD::VMERGE_VL && MergeOpc !=
ISD::VSELECT)
19128 SDValue Passthru =
N->getOperand(2);
19134 if (Mask.getOpcode() != RISCVISD::VMSET_VL)
19142 Z = Z.getOperand(1);
19148 {Y, X, Y, MergeOp->getOperand(0), N->getOperand(4)},
19156 if (!Subtarget.hasStdExtZvabd())
19159 MVT VT =
N->getSimpleValueType(0);
19166 SDValue Passthru =
N->getOperand(2);
19173 if (
Op->getOpcode() != RISCVISD::ABDS_VL &&
19174 Op->getOpcode() != RISCVISD::ABDU_VL)
19180 Diff = Diff ? Diff : IsABD(Op1);
19183 SDValue Acc = Diff == Op0 ? Op1 : Op0;
19186 Acc = DAG.
getNode(RISCVISD::VZEXT_VL,
DL, VT, Acc, Mask, VL);
19188 Diff.
getOpcode() == RISCVISD::ABDS_VL ? RISCVISD::VWABDA_VL
19189 : RISCVISD::VWABDAU_VL,
19197 [[maybe_unused]]
unsigned Opc =
N->getOpcode();
19198 assert(
Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWADDU_W_VL ||
19199 Opc == RISCVISD::VWSUB_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL);
19226 EVT NewMemVT = (MemVT == MVT::i32) ? MVT::i64 : MVT::i128;
19234 if (MemVT == MVT::i32)
19235 Opcode = (Ext ==
ISD::ZEXTLOAD) ? RISCVISD::TH_LWUD : RISCVISD::TH_LWD;
19237 Opcode = RISCVISD::TH_LDD;
19240 Opcode,
SDLoc(LSNode1), DAG.
getVTList({XLenVT, XLenVT, MVT::Other}),
19241 {LSNode1->getChain(), BasePtr,
19242 DAG.getConstant(Imm, SDLoc(LSNode1), XLenVT)},
19253 unsigned Opcode = (MemVT == MVT::i32) ? RISCVISD::TH_SWD : RISCVISD::TH_SDD;
19257 {LSNode1->getChain(), LSNode1->getOperand(1), LSNode2->getOperand(1),
19258 BasePtr, DAG.getConstant(Imm, SDLoc(LSNode1), XLenVT)},
19275 if (!Subtarget.hasVendorXTHeadMemPair())
19287 auto ExtractBaseAndOffset = [](
SDValue Ptr) -> std::pair<SDValue, uint64_t> {
19290 return {Ptr->
getOperand(0), C1->getZExtValue()};
19294 auto [Base1, Offset1] = ExtractBaseAndOffset(LSNode1->
getOperand(OpNum));
19315 auto [Base2, Offset2] = ExtractBaseAndOffset(LSNode2->
getOperand(OpNum));
19318 if (Base1 != Base2)
19322 bool Valid =
false;
19323 if (MemVT == MVT::i32) {
19327 }
else if (MemVT == MVT::i64) {
19363 if (Src->isStrictFPOpcode())
19371 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
19381 EVT VT =
N->getValueType(0);
19384 MVT SrcVT = Src.getSimpleValueType();
19385 MVT SrcContainerVT = SrcVT;
19413 IsSigned ? RISCVISD::VFCVT_RTZ_X_F_VL : RISCVISD::VFCVT_RTZ_XU_F_VL;
19414 FpToInt = DAG.
getNode(
Opc,
DL, ContainerVT, XVal, Mask, VL);
19417 IsSigned ? RISCVISD::VFCVT_RM_X_F_VL : RISCVISD::VFCVT_RM_XU_F_VL;
19418 FpToInt = DAG.
getNode(
Opc,
DL, ContainerVT, XVal, Mask,
19431 if (VT != MVT::i32 && VT != XLenVT)
19436 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
19438 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
19461 EVT DstVT =
N->getValueType(0);
19462 if (DstVT != XLenVT)
19468 if (Src->isStrictFPOpcode())
19476 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
19488 if (SatVT == DstVT)
19489 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
19490 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
19491 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
19496 Src = Src.getOperand(0);
19504 if (
Opc == RISCVISD::FCVT_WU_RV64)
19517 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected extension");
19523 EVT VT =
N->getValueType(0);
19529 return DAG.
getNode(RISCVISD::BREV8,
DL, VT, Src.getOperand(0));
19542 EVT LoadVT = VPLoad->getValueType(0);
19546 N->getOperand(2) != VPLoad->getVectorLength() ||
19547 !
N->getOperand(0).hasOneUse())
19550 SDValue LoadMask = VPLoad->getMask();
19555 if (LoadMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
19556 LoadMask.
getOperand(2) != VPLoad->getVectorLength())
19564 SDValue NumElem = VPLoad->getVectorLength();
19565 uint64_t ElemWidthByte = VPLoad->getValueType(0).getScalarSizeInBits() / 8;
19577 PtrInfo, VPLoad->getMemOperand()->getFlags(),
19581 LoadVT,
DL, VPLoad->getChain(),
Base, Stride, LoadMask,
19582 VPLoad->getVectorLength(), MMO, VPLoad->isExpandingLoad());
19596 if (VPStore->getValue().getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE)
19599 SDValue VPReverse = VPStore->getValue();
19605 VPStore->getVectorLength() != VPReverse.
getOperand(2) ||
19609 SDValue StoreMask = VPStore->getMask();
19614 if (StoreMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
19615 StoreMask.
getOperand(2) != VPStore->getVectorLength())
19623 SDValue NumElem = VPStore->getVectorLength();
19637 PtrInfo, VPStore->getMemOperand()->getFlags(),
19642 VPStore->getOffset(), Stride, StoreMask, VPStore->getVectorLength(),
19643 VPStore->getMemoryVT(), MMO, VPStore->getAddressingMode(),
19644 VPStore->isTruncatingStore(), VPStore->isCompressingStore());
19656 EVT VT =
N->getValueType(0);
19668 if (In.getOpcode() != ISD::VP_SRL || In.getOperand(2) != Mask ||
19669 In.getOperand(3) != VL)
19678 if (
LHS.getOpcode() != ISD::VP_ADD ||
LHS.getOperand(2) != Mask ||
19679 LHS.getOperand(3) != VL)
19686 if (V.getOpcode() != ISD::VP_ADD || V.getOperand(2) != Mask ||
19687 V.getOperand(3) != VL)
19690 Operands[0] =
Other;
19699 if (!FindAdd(LHS0, LHS1) && !FindAdd(LHS1, LHS0))
19706 if (
I == std::end(Operands))
19713 if (
Op.getOpcode() != ISD::VP_ZERO_EXTEND ||
Op.getOperand(1) != Mask ||
19714 Op.getOperand(2) != VL)
19724 Operands[0].getOperand(0), Mask, VL);
19726 Operands[1].getOperand(0), Mask, VL);
19730 return DAG.
getNode(RISCVISD::AVGCEILU_VL,
DL, VT,
19731 {NewOp0, NewOp1, DAG.
getUNDEF(VT), Mask, VL});
19743 case RISCVISD::VFMADD_VL: Opcode = RISCVISD::VFNMSUB_VL;
break;
19744 case RISCVISD::VFNMSUB_VL: Opcode = RISCVISD::VFMADD_VL;
break;
19745 case RISCVISD::VFNMADD_VL: Opcode = RISCVISD::VFMSUB_VL;
break;
19746 case RISCVISD::VFMSUB_VL: Opcode = RISCVISD::VFNMADD_VL;
break;
19747 case RISCVISD::STRICT_VFMADD_VL: Opcode = RISCVISD::STRICT_VFNMSUB_VL;
break;
19748 case RISCVISD::STRICT_VFNMSUB_VL: Opcode = RISCVISD::STRICT_VFMADD_VL;
break;
19749 case RISCVISD::STRICT_VFNMADD_VL: Opcode = RISCVISD::STRICT_VFMSUB_VL;
break;
19750 case RISCVISD::STRICT_VFMSUB_VL: Opcode = RISCVISD::STRICT_VFNMADD_VL;
break;
19760 case RISCVISD::VFMADD_VL: Opcode = RISCVISD::VFMSUB_VL;
break;
19761 case RISCVISD::VFMSUB_VL: Opcode = RISCVISD::VFMADD_VL;
break;
19762 case RISCVISD::VFNMADD_VL: Opcode = RISCVISD::VFNMSUB_VL;
break;
19763 case RISCVISD::VFNMSUB_VL: Opcode = RISCVISD::VFNMADD_VL;
break;
19764 case RISCVISD::STRICT_VFMADD_VL: Opcode = RISCVISD::STRICT_VFMSUB_VL;
break;
19765 case RISCVISD::STRICT_VFMSUB_VL: Opcode = RISCVISD::STRICT_VFMADD_VL;
break;
19766 case RISCVISD::STRICT_VFNMADD_VL: Opcode = RISCVISD::STRICT_VFNMSUB_VL;
break;
19767 case RISCVISD::STRICT_VFNMSUB_VL: Opcode = RISCVISD::STRICT_VFNMADD_VL;
break;
19780 unsigned Offset = IsStrict ? 1 : 0;
19787 auto invertIfNegative = [&Mask, &VL](
SDValue &V) {
19788 if (V.getOpcode() == RISCVISD::FNEG_VL && V.getOperand(1) == Mask &&
19789 V.getOperand(2) == VL) {
19791 V = V.getOperand(0);
19798 bool NegA = invertIfNegative(
A);
19799 bool NegB = invertIfNegative(
B);
19800 bool NegC = invertIfNegative(
C);
19803 if (!NegA && !NegB && !NegC)
19809 {N->getOperand(0), A, B, C, Mask, VL});
19833 EVT VT =
N->getValueType(0);
19840 uint64_t ShAmt =
N->getConstantOperandVal(1);
19853 if (LShAmt < ExtSize) {
19866 if (ShAmt > 32 || VT != MVT::i64)
19896 U->getConstantOperandVal(1) > 32)
19951 if (!
Cond.hasOneUse())
19970 EVT VT =
Cond.getValueType();
20015 LHS =
LHS.getOperand(0);
20025 LHS.getOperand(0).getValueType() == Subtarget.
getXLenVT()) {
20033 RHS =
LHS.getOperand(1);
20034 LHS =
LHS.getOperand(0);
20043 auto isXorImmediate = [](
const SDValue &
Op) ->
bool {
20045 return isInt<12>(XorCnst->getSExtValue());
20049 auto singleBitOp = [&DAG](
const SDValue &VarOp,
20050 const SDValue &ConstOp) ->
bool {
20053 return (XorCnst->getSExtValue() == 1) &&
20058 auto onlyUsedBySelectOrBR = [](
const SDValue &
Op) ->
bool {
20059 for (
const SDNode *UserNode :
Op->users()) {
20060 const unsigned Opcode = UserNode->getOpcode();
20061 if (Opcode != RISCVISD::SELECT_CC && Opcode != RISCVISD::BR_CC)
20066 auto isFoldableXorEq = [isXorImmediate, singleBitOp, onlyUsedBySelectOrBR](
20069 (!isXorImmediate(
LHS.getOperand(1)) ||
20070 singleBitOp(
LHS.getOperand(0),
LHS.getOperand(1)) ||
20071 onlyUsedBySelectOrBR(
LHS));
20074 if (isFoldableXorEq(
LHS,
RHS)) {
20075 RHS =
LHS.getOperand(1);
20076 LHS =
LHS.getOperand(0);
20102 if (Subtarget.hasVendorXAndesPerf()) {
20112 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
20155 bool Commutative =
true;
20156 unsigned Opc = TrueVal.getOpcode();
20166 Commutative =
false;
20176 if (!TrueVal.hasOneUse())
20180 if (FalseVal == TrueVal.getOperand(0))
20182 else if (Commutative && FalseVal == TrueVal.getOperand(1))
20187 EVT VT =
N->getValueType(0);
20189 SDValue OtherOp = TrueVal.getOperand(1 - OpToFold);
20195 assert(IdentityOperand &&
"No identity operand!");
20200 DAG.
getSelect(
DL, OtherOpVT,
N->getOperand(0), OtherOp, IdentityOperand);
20201 return DAG.
getNode(TrueVal.getOpcode(),
DL, VT, FalseVal, NewSel);
20222 CountZeroes =
N->getOperand(2);
20223 ValOnZero =
N->getOperand(1);
20225 CountZeroes =
N->getOperand(1);
20226 ValOnZero =
N->getOperand(2);
20245 if (
Cond->getOperand(0) != CountZeroesArgument)
20264 CountZeroes, BitWidthMinusOne);
20274 EVT VT =
N->getValueType(0);
20275 EVT CondVT =
Cond.getValueType();
20283 (Subtarget.
hasCZEROLike() || Subtarget.hasVendorXTHeadCondMov())) {
20289 const APInt &MaskVal =
LHS.getConstantOperandAPInt(1);
20300 if (!TrueVal.hasOneUse() || !FalseVal.hasOneUse())
20304 if (TrueVal.getOpcode() ==
ISD::SUB && FalseVal.getOpcode() ==
ISD::ADD) {
20312 SDValue A = FalseVal.getOperand(0);
20313 SDValue B = FalseVal.getOperand(1);
20315 return ((TrueVal.getOperand(0) ==
A && TrueVal.getOperand(1) ==
B) ||
20316 (TrueVal.getOperand(1) ==
A && TrueVal.getOperand(0) ==
B));
20324 EVT VT =
N->getValueType(0);
20326 SDValue TrueVal =
N->getOperand(1);
20327 SDValue FalseVal =
N->getOperand(2);
20357 SDValue TrueVal =
N->getOperand(1);
20358 SDValue FalseVal =
N->getOperand(2);
20373 EVT VT =
N->getValueType(0);
20380 const unsigned Opcode =
N->op_begin()->getNode()->getOpcode();
20395 if (
Op.isUndef()) {
20408 if (
Op.getOpcode() != Opcode || !
Op.hasOneUse())
20417 if (
Op.getOperand(0).getValueType() !=
Op.getOperand(1).getValueType())
20441 EVT AVT =
A.getValueType();
20442 EVT BVT =
B.getValueType();
20472 if (AOpt || BOpt) {
20490 EVT OpVT =
A.getValueType();
20512 EVT OpVT =
A.getOperand(0).getValueType();
20514 OpVT !=
B.getOperand(0).getValueType() ||
20543 if (!Subtarget.hasStdExtZvdot4a8i())
20547 EVT VT =
N->getValueType(0);
20572 const unsigned InVecOpcode = InVec->
getOpcode();
20589 InVecLHS, InValLHS, EltNo);
20591 InVecRHS, InValRHS, EltNo);
20603 unsigned Elt = IndexC->getZExtValue();
20609 unsigned NewIdx = Elt % ConcatNumElts;
20611 unsigned ConcatOpIdx = Elt / ConcatNumElts;
20616 ConcatOps[ConcatOpIdx] = ConcatOp;
20628 EVT VT =
N->getValueType(0);
20640 !
SDValue(BaseLd, 0).hasOneUse())
20643 EVT BaseLdVT = BaseLd->getValueType(0);
20651 if (!Ld || !Ld->isSimple() || !
Op.hasOneUse() ||
20653 Ld->getValueType(0) != BaseLdVT)
20662 using PtrDiff = std::pair<std::variant<int64_t, SDValue>,
bool>;
20664 LoadSDNode *Ld2) -> std::optional<PtrDiff> {
20669 if (BIO1.equalBaseIndex(BIO2, DAG))
20674 SDValue P2 = Ld2->getBasePtr();
20675 if (P2.getOpcode() ==
ISD::ADD && P2.getOperand(0) == P1)
20676 return {{P2.getOperand(1),
false}};
20677 if (P1.getOpcode() ==
ISD::ADD && P1.getOperand(0) == P2)
20678 return {{P1.getOperand(1),
true}};
20680 return std::nullopt;
20684 auto BaseDiff = GetPtrDiff(Lds[0], Lds[1]);
20689 for (
auto *It = Lds.
begin() + 1; It != Lds.
end() - 1; It++)
20690 if (GetPtrDiff(*It, *std::next(It)) != BaseDiff)
20698 unsigned WideScalarBitWidth =
20711 auto [StrideVariant, MustNegateStride] = *BaseDiff;
20713 std::holds_alternative<SDValue>(StrideVariant)
20714 ? std::get<SDValue>(StrideVariant)
20717 if (MustNegateStride)
20726 ConstStride && ConstStride->getSExtValue() >= 0)
20730 ConstStride->getSExtValue() * (
N->getNumOperands() - 1);
20736 BaseLd->getPointerInfo(), BaseLd->getMemOperand()->getFlags(), MemSize,
20740 WideVecVT,
DL, BaseLd->getChain(), BaseLd->getBasePtr(), Stride,
20754 EVT VT =
N->getValueType(0);
20772 for (
int MaskIndex : Mask) {
20773 bool SelectMaskVal = (MaskIndex < (int)NumElts);
20776 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
20816 if (
N->getValueType(0).isFixedLengthVector())
20819 SDValue Addend =
N->getOperand(0);
20822 if (
N->getOpcode() == RISCVISD::ADD_VL) {
20823 SDValue AddPassthruOp =
N->getOperand(2);
20824 if (!AddPassthruOp.
isUndef())
20828 auto IsVWMulOpc = [](
unsigned Opc) {
20830 case RISCVISD::VWMUL_VL:
20831 case RISCVISD::VWMULU_VL:
20832 case RISCVISD::VWMULSU_VL:
20847 if (!MulPassthruOp.
isUndef())
20857 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
20858 }(
N, DAG, Subtarget);
20863 if (AddMask != MulMask || AddVL != MulVL)
20866 const auto &TSInfo =
20868 unsigned Opc = TSInfo.getMAccOpcode(MulOp.
getOpcode());
20871 EVT VT =
N->getValueType(0);
20882 if (!
N->getValueType(0).isVector())
20885 SDValue Addend =
N->getOperand(0);
20888 if (
N->getOpcode() == RISCVISD::ADD_VL) {
20889 SDValue AddPassthruOp =
N->getOperand(2);
20890 if (!AddPassthruOp.
isUndef())
20894 auto IsVdota4Opc = [](
unsigned Opc) {
20896 case RISCVISD::VDOTA4_VL:
20897 case RISCVISD::VDOTA4U_VL:
20898 case RISCVISD::VDOTA4SU_VL:
20918 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
20919 }(
N, DAG, Subtarget);
20922 if (AddVL != MulVL)
20925 if (AddMask.getOpcode() != RISCVISD::VMSET_VL ||
20926 AddMask.getOperand(0) != MulVL)
20931 EVT VT =
N->getValueType(0);
20932 Addend = DAG.
getNode(RISCVISD::ADD_VL,
DL, VT, Addend, AccumOp,
20933 DAG.
getUNDEF(VT), AddMask, AddVL);
20951 const EVT IndexVT = Index.getValueType();
20955 if (!isIndexTypeSigned(IndexType))
20987 assert(ShuffleMask.empty());
20989 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
20992 if (Index->getOperand(i)->isUndef())
20994 uint64_t C = Index->getConstantOperandVal(i);
20995 if (
C % ElementSize != 0)
20997 C =
C / ElementSize;
21000 ShuffleMask.push_back(
C);
21001 ActiveLanes.
set(
C);
21003 return ActiveLanes.
all();
21021 if (NumElems % 2 != 0)
21025 const unsigned WiderElementSize = ElementSize * 2;
21026 if (WiderElementSize > ST.getELen()/8)
21029 if (!ST.enableUnalignedVectorMem() && BaseAlign < WiderElementSize)
21032 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
21035 if (Index->getOperand(i)->isUndef())
21039 uint64_t C = Index->getConstantOperandVal(i);
21041 if (
C % WiderElementSize != 0)
21046 if (
C !=
Last + ElementSize)
21065 if (!IsVLMAX || Mask.getOpcode() != RISCVISD::VMSET_VL ||
21066 Mask.getOperand(0) != VL)
21069 auto IsTruncNode = [&](
SDValue V) {
21070 return V.getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL &&
21071 V.getOperand(1) == Mask && V.getOperand(2) == VL;
21078 while (IsTruncNode(
Op)) {
21079 if (!
Op.hasOneUse())
21081 Op =
Op.getOperand(0);
21114 assert(
N->getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL);
21116 MVT VT =
N->getSimpleValueType(0);
21121 auto MatchMinMax = [&VL, &Mask](
SDValue V,
unsigned Opc,
unsigned OpcVL,
21123 if (V.getOpcode() !=
Opc &&
21124 !(V.getOpcode() == OpcVL && V.getOperand(2).isUndef() &&
21125 V.getOperand(3) == Mask && V.getOperand(4) == VL))
21133 Op.getOperand(1).getValueType().isFixedLengthVector() &&
21135 Op.getOperand(1).getOperand(0).getValueType() ==
Op.getValueType() &&
21137 Op =
Op.getOperand(1).getOperand(0);
21140 return V.getOperand(0);
21142 if (
Op.getOpcode() == RISCVISD::VMV_V_X_VL &&
Op.getOperand(0).isUndef() &&
21143 Op.getOperand(2) == VL) {
21146 Op1->getAPIntValue().sextOrTrunc(
Op.getScalarValueSizeInBits());
21156 auto DetectUSatPattern = [&](
SDValue V) {
21168 MatchMinMax(SMinOp,
ISD::SMAX, RISCVISD::SMAX_VL, LoC))
21177 MatchMinMax(SMaxOp,
ISD::SMIN, RISCVISD::SMIN_VL, HiC))
21180 return DAG.
getNode(RISCVISD::SMAX_VL,
DL, V.getValueType(), SMinOp,
21181 V.getOperand(1), DAG.
getUNDEF(V.getValueType()),
21187 auto DetectSSatPattern = [&](
SDValue V) {
21189 unsigned NumSrcBits = V.getScalarValueSizeInBits();
21196 MatchMinMax(SMinOp,
ISD::SMAX, RISCVISD::SMAX_VL, LoC))
21197 if (HiC == SignedMax && LoC == SignedMin)
21202 MatchMinMax(SMaxOp,
ISD::SMIN, RISCVISD::SMIN_VL, HiC))
21203 if (HiC == SignedMax && LoC == SignedMin)
21212 while (Src.getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL &&
21213 Src.getOperand(1) == Mask && Src.getOperand(2) == VL &&
21215 Src = Src.getOperand(0);
21219 if ((Val = DetectUSatPattern(Src)))
21220 ClipOpc = RISCVISD::TRUNCATE_VECTOR_VL_USAT;
21221 else if ((Val = DetectSSatPattern(Src)))
21222 ClipOpc = RISCVISD::TRUNCATE_VECTOR_VL_SSAT;
21231 Val = DAG.
getNode(ClipOpc,
DL, ValVT, Val, Mask, VL);
21232 }
while (ValVT != VT);
21250 unsigned Opc =
N->getOpcode();
21252 "Unexpected opcode");
21253 EVT VT =
N->getValueType(0);
21262 Src = Src.getOperand(0);
21266 Src = Src.getOperand(0);
21270 Src = Src.getOperand(0);
21273 EVT SrcEVT = Src.getValueType();
21295 VectorBitsMax, EltSize, MinSize);
21300 MVT ContainerVT = SrcMVT;
21328 if (!
LHS.hasOneUse())
21331 switch (
LHS.getOpcode()) {
21333 case RISCVISD::VSEXT_VL:
21334 Opcode = RISCVISD::VWMULSU_VL;
21337 case RISCVISD::VZEXT_VL:
21338 Opcode = RISCVISD::VWMULU_VL;
21349 else if (
RHS.getOpcode() == RISCVISD::VMV_V_X_VL &&
21351 ShAmtInt =
RHS.getConstantOperandVal(1);
21364 if (ShAmtInt >= NarrowBits)
21366 MVT VT =
N->getSimpleValueType(0);
21373 switch (
N->getOpcode()) {
21378 case RISCVISD::SHL_VL:
21379 Passthru =
N->getOperand(2);
21380 Mask =
N->getOperand(3);
21381 VL =
N->getOperand(4);
21386 return DAG.
getNode(Opcode,
DL, VT, NarrowOp,
21388 Passthru, Mask, VL);
21394 const MVT XLenVT = Subtarget.getXLenVT();
21400 auto SimplifyDemandedLowBitsHelper = [&](
unsigned OpNo,
unsigned LowBits) {
21411 switch (
N->getOpcode()) {
21414 case RISCVISD::SplitF64: {
21418 if (Op0->
getOpcode() == RISCVISD::BuildPairF64)
21431 APInt V =
C->getValueAPF().bitcastToAPInt();
21460 case RISCVISD::SLLW:
21461 case RISCVISD::SRAW:
21462 case RISCVISD::SRLW:
21463 case RISCVISD::RORW:
21464 case RISCVISD::ROLW: {
21466 if (SimplifyDemandedLowBitsHelper(0, 32) ||
21467 SimplifyDemandedLowBitsHelper(1, 5))
21472 case RISCVISD::ABSW:
21473 case RISCVISD::CLSW:
21474 case RISCVISD::CLZW:
21475 case RISCVISD::CTZW: {
21477 if (SimplifyDemandedLowBitsHelper(0, 32))
21481 case RISCVISD::WMULSU: {
21483 if (!
N->hasAnyUseOfValue(0)) {
21485 N->getOperand(0),
N->getOperand(1));
21490 case RISCVISD::ADDD: {
21491 assert(!Subtarget.is64Bit() && Subtarget.hasStdExtP() &&
21492 "ADDD is only for RV32 with P extension");
21504 return DCI.
CombineTo(
N, Result.getValue(0), Result.getValue(1));
21511 return DCI.
CombineTo(
N, Result.getValue(0), Result.getValue(1));
21515 case RISCVISD::SUBD: {
21516 assert(!Subtarget.is64Bit() && Subtarget.hasStdExtP() &&
21517 "SUBD is only for RV32 with P extension");
21530 return DCI.
CombineTo(
N, Result.getValue(0), Result.getValue(1));
21534 case RISCVISD::WADDAU: {
21535 assert(!Subtarget.is64Bit() && Subtarget.hasStdExtP() &&
21536 "WADDAU is only for RV32 with P extension");
21547 if (Op0Lo.
getOpcode() == RISCVISD::WADDAU &&
21550 RISCVISD::WADDAU,
DL, DAG.
getVTList(MVT::i32, MVT::i32),
21552 return DCI.
CombineTo(
N, Result.getValue(0), Result.getValue(1));
21555 if (Op0Lo.
getOpcode() == RISCVISD::WSUBAU &&
21558 RISCVISD::WSUBAU,
DL, DAG.
getVTList(MVT::i32, MVT::i32),
21560 return DCI.
CombineTo(
N, Result.getValue(0), Result.getValue(1));
21565 case RISCVISD::WSUBAU: {
21566 assert(!Subtarget.is64Bit() && Subtarget.hasStdExtP() &&
21567 "WSUBAU is only for RV32 with P extension");
21579 RISCVISD::WSUBAU,
DL, DAG.
getVTList(MVT::i32, MVT::i32),
21581 return DCI.
CombineTo(
N, Result.getValue(0), Result.getValue(1));
21585 case RISCVISD::FMV_W_X_RV64: {
21590 if (Op0.
getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64)
21594 case RISCVISD::FMV_X_ANYEXTH:
21595 case RISCVISD::FMV_X_ANYEXTW_RV64: {
21598 MVT VT =
N->getSimpleValueType(0);
21609 if ((
N->getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64 &&
21610 Op0->
getOpcode() == RISCVISD::FMV_W_X_RV64) ||
21611 (
N->getOpcode() == RISCVISD::FMV_X_ANYEXTH &&
21612 Op0->
getOpcode() == RISCVISD::FMV_H_X)) {
21614 "Unexpected value type!");
21624 LN0->getBasePtr(), IVT, LN0->getMemOperand());
21637 unsigned FPBits =
N->getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64 ? 32 : 16;
21648 EVT VT =
N->getValueType(0);
21697 EVT VT =
N->getValueType(0);
21715 if (!
C || !
C->getValueAPF().isExactlyValue(+1.0))
21747 EVT VT =
N->getValueType(0);
21761 if (
N->getValueType(0) == MVT::i64 && Subtarget.is64Bit()) {
21766 Src.getOperand(0));
21771 Src.getOperand(0), Src.getOperand(1));
21779 case RISCVISD::TRUNCATE_VECTOR_VL:
21783 case ISD::VP_TRUNCATE:
21791 case RISCVISD::CZERO_EQZ:
21792 case RISCVISD::CZERO_NEZ: {
21795 MVT VT =
N->getSimpleValueType(0);
21797 unsigned Opc =
N->getOpcode();
21800 if (
Opc == RISCVISD::CZERO_EQZ && Val ==
Cond)
21804 Opc == RISCVISD::CZERO_EQZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ;
21822 Val,
Cond.getOperand(0));
21831 const APInt &ShAmt =
Cond.getConstantOperandAPInt(1);
21835 uint64_t AndConst =
And.getConstantOperandVal(1);
21859 case RISCVISD::SELECT_CC: {
21866 SDValue FalseV =
N->getOperand(4);
21868 EVT VT =
N->getValueType(0);
21871 if (TrueV == FalseV)
21902 return DAG.
getNode(RISCVISD::SELECT_CC,
DL,
N->getValueType(0),
21903 {LHS, RHS, CC, TrueV, FalseV});
21905 if (!Subtarget.hasConditionalMoveFusion()) {
21962 case RISCVISD::BR_CC: {
21969 return DAG.
getNode(RISCVISD::BR_CC,
DL,
N->getValueType(0),
21970 N->getOperand(0), LHS, RHS, CC,
N->getOperand(4));
21983 EVT VT =
N->getValueType(0);
22008 const EVT VT =
N->getValueType(0);
22009 SDValue Index = MGN->getIndex();
22010 SDValue ScaleOp = MGN->getScale();
22012 assert(!MGN->isIndexScaled() &&
22013 "Scaled gather/scatter should not be formed");
22018 N->getVTList(), MGN->getMemoryVT(),
DL,
22019 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
22020 MGN->getBasePtr(), Index, ScaleOp},
22021 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
22025 N->getVTList(), MGN->getMemoryVT(),
DL,
22026 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
22027 MGN->getBasePtr(), Index, ScaleOp},
22028 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
22034 if (std::optional<VIDSequence> SimpleVID =
22036 SimpleVID && SimpleVID->StepDenominator == 1) {
22037 const int64_t StepNumerator = SimpleVID->StepNumerator;
22038 const int64_t Addend = SimpleVID->Addend;
22045 assert(MGN->getBasePtr()->getValueType(0) == PtrVT);
22053 VT,
DL, MGN->getChain(), BasePtr,
22055 EVL, MGN->getMemOperand());
22057 MGN->getPassThru());
22067 MGN->getBasePtr(), DAG.
getUNDEF(XLenVT),
22069 MGN->getMemoryVT(), MGN->getMemOperand(),
22078 MGN->getMemOperand()->getBaseAlign(), Subtarget)) {
22080 for (
unsigned i = 0; i < Index->getNumOperands(); i += 2)
22081 NewIndices.
push_back(Index.getOperand(i));
22082 EVT IndexVT = Index.getValueType()
22089 assert(EltCnt.isKnownEven() &&
"Splitting vector, but not in half!");
22091 EltCnt.divideCoefficientBy(2));
22094 EltCnt.divideCoefficientBy(2));
22099 {MGN->getChain(), Passthru, Mask, MGN->getBasePtr(),
22109 SDValue Index = MSN->getIndex();
22110 SDValue ScaleOp = MSN->getScale();
22112 assert(!MSN->isIndexScaled() &&
22113 "Scaled gather/scatter should not be formed");
22118 N->getVTList(), MSN->getMemoryVT(),
DL,
22119 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
22121 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
22125 N->getVTList(), MSN->getMemoryVT(),
DL,
22126 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
22128 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
22130 EVT VT = MSN->getValue()->getValueType(0);
22132 if (!MSN->isTruncatingStore() &&
22136 return DAG.
getMaskedStore(MSN->getChain(),
DL, Shuffle, MSN->getBasePtr(),
22137 DAG.
getUNDEF(XLenVT), MSN->getMask(),
22138 MSN->getMemoryVT(), MSN->getMemOperand(),
22143 case ISD::VP_GATHER: {
22145 SDValue Index = VPGN->getIndex();
22146 SDValue ScaleOp = VPGN->getScale();
22148 assert(!VPGN->isIndexScaled() &&
22149 "Scaled gather/scatter should not be formed");
22154 {VPGN->getChain(), VPGN->getBasePtr(), Index,
22155 ScaleOp, VPGN->getMask(),
22156 VPGN->getVectorLength()},
22157 VPGN->getMemOperand(), IndexType);
22161 {VPGN->getChain(), VPGN->getBasePtr(), Index,
22162 ScaleOp, VPGN->getMask(),
22163 VPGN->getVectorLength()},
22164 VPGN->getMemOperand(), IndexType);
22168 case ISD::VP_SCATTER: {
22170 SDValue Index = VPSN->getIndex();
22171 SDValue ScaleOp = VPSN->getScale();
22173 assert(!VPSN->isIndexScaled() &&
22174 "Scaled gather/scatter should not be formed");
22179 {VPSN->getChain(), VPSN->getValue(),
22180 VPSN->getBasePtr(), Index, ScaleOp,
22181 VPSN->getMask(), VPSN->getVectorLength()},
22182 VPSN->getMemOperand(), IndexType);
22186 {VPSN->getChain(), VPSN->getValue(),
22187 VPSN->getBasePtr(), Index, ScaleOp,
22188 VPSN->getMask(), VPSN->getVectorLength()},
22189 VPSN->getMemOperand(), IndexType);
22192 case RISCVISD::SHL_VL:
22196 case RISCVISD::SRA_VL:
22197 case RISCVISD::SRL_VL: {
22199 if (ShAmt.
getOpcode() == RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL) {
22203 EVT VT =
N->getValueType(0);
22206 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt,
22207 N->getOperand(2),
N->getOperand(3),
N->getOperand(4));
22222 if (ShAmt.
getOpcode() == RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL) {
22225 EVT VT =
N->getValueType(0);
22228 DAG.
getRegister(RISCV::X0, Subtarget.getXLenVT()));
22229 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt);
22233 case RISCVISD::ADD_VL:
22241 case RISCVISD::VWADDU_VL:
22243 case RISCVISD::VWADD_W_VL:
22244 case RISCVISD::VWADDU_W_VL:
22245 case RISCVISD::VWSUB_W_VL:
22246 case RISCVISD::VWSUBU_W_VL:
22248 case RISCVISD::OR_VL:
22249 case RISCVISD::SUB_VL:
22250 case RISCVISD::MUL_VL:
22252 case RISCVISD::VFMADD_VL:
22253 case RISCVISD::VFNMADD_VL:
22254 case RISCVISD::VFMSUB_VL:
22255 case RISCVISD::VFNMSUB_VL:
22256 case RISCVISD::STRICT_VFMADD_VL:
22257 case RISCVISD::STRICT_VFNMADD_VL:
22258 case RISCVISD::STRICT_VFMSUB_VL:
22259 case RISCVISD::STRICT_VFNMSUB_VL:
22261 case RISCVISD::FADD_VL:
22262 case RISCVISD::FSUB_VL:
22263 case RISCVISD::FMUL_VL:
22264 case RISCVISD::VFWADD_W_VL:
22265 case RISCVISD::VFWSUB_W_VL:
22277 SDValue Chain = Store->getChain();
22278 EVT MemVT = Store->getMemoryVT();
22279 SDValue Val = Store->getValue();
22282 bool IsScalarizable =
22284 Store->isSimple() &&
22314 NewVT, *Store->getMemOperand())) {
22316 return DAG.
getStore(Chain,
DL, NewV, Store->getBasePtr(),
22317 Store->getPointerInfo(), Store->getBaseAlign(),
22318 Store->getMemOperand()->getFlags());
22328 L->hasNUsesOfValue(1, 0) && L->hasNUsesOfValue(1, 1) &&
22330 L->getMemoryVT() == MemVT) {
22333 NewVT, *Store->getMemOperand()) &&
22335 NewVT, *L->getMemOperand())) {
22337 L->getPointerInfo(), L->getBaseAlign(),
22338 L->getMemOperand()->getFlags());
22339 return DAG.
getStore(Chain,
DL, NewL, Store->getBasePtr(),
22340 Store->getPointerInfo(), Store->getBaseAlign(),
22341 Store->getMemOperand()->getFlags());
22348 if ((Val.
getOpcode() == RISCVISD::VMV_X_S ||
22354 MVT VecVT = Src.getSimpleValueType();
22361 Store->getChain(),
DL, Src, Store->getBasePtr(), Store->getOffset(),
22364 Store->getMemOperand(), Store->getAddressingMode(),
22365 Store->isTruncatingStore(),
false);
22372 EVT VT =
N->getValueType(0);
22397 case RISCVISD::VFMV_V_F_VL: {
22398 const MVT VT =
N->getSimpleValueType(0);
22399 SDValue Passthru =
N->getOperand(0);
22400 SDValue Scalar =
N->getOperand(1);
22405 return DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL, VT, Passthru, Scalar, VL);
22408 case RISCVISD::VMV_V_X_VL: {
22409 const MVT VT =
N->getSimpleValueType(0);
22410 SDValue Passthru =
N->getOperand(0);
22411 SDValue Scalar =
N->getOperand(1);
22416 unsigned ScalarSize = Scalar.getValueSizeInBits();
22418 if (ScalarSize > EltWidth && Passthru.
isUndef())
22419 if (SimplifyDemandedLowBitsHelper(1, EltWidth))
22426 (!Const || Const->isZero() ||
22427 !Const->getAPIntValue().sextOrTrunc(EltWidth).isSignedIntN(5)))
22428 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, VT, Passthru, Scalar, VL);
22432 case RISCVISD::VFMV_S_F_VL: {
22437 if (
N->getOperand(0).isUndef() &&
22440 Src.getOperand(0).getValueType().isScalableVector()) {
22441 EVT VT =
N->getValueType(0);
22461 case RISCVISD::VMV_S_X_VL: {
22462 const MVT VT =
N->getSimpleValueType(0);
22463 SDValue Passthru =
N->getOperand(0);
22464 SDValue Scalar =
N->getOperand(1);
22470 unsigned ScalarSize = Scalar.getValueSizeInBits();
22472 if (ScalarSize > EltWidth && SimplifyDemandedLowBitsHelper(1, EltWidth))
22475 if (Scalar.getOpcode() == RISCVISD::VMV_X_S && Passthru.
isUndef() &&
22476 Scalar.getOperand(0).getValueType() ==
N->getValueType(0))
22477 return Scalar.getOperand(0);
22484 DAG.
getNode(
N->getOpcode(),
DL, M1VT, M1Passthru, Scalar, VL);
22493 Const && !Const->isZero() &&
isInt<5>(Const->getSExtValue()) &&
22495 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru, Scalar, VL);
22499 case RISCVISD::VMV_X_S: {
22501 MVT VecVT =
N->getOperand(0).getSimpleValueType();
22503 if (M1VT.
bitsLT(VecVT)) {
22505 return DAG.
getNode(RISCVISD::VMV_X_S,
DL,
N->getValueType(0), Vec);
22513 unsigned IntNo =
N->getConstantOperandVal(IntOpNo);
22518 case Intrinsic::riscv_vcpop:
22519 case Intrinsic::riscv_vcpop_mask:
22520 case Intrinsic::riscv_vfirst:
22521 case Intrinsic::riscv_vfirst_mask: {
22523 if (IntNo == Intrinsic::riscv_vcpop_mask ||
22524 IntNo == Intrinsic::riscv_vfirst_mask)
22525 VL =
N->getOperand(3);
22530 EVT VT =
N->getValueType(0);
22531 if (IntNo == Intrinsic::riscv_vfirst ||
22532 IntNo == Intrinsic::riscv_vfirst_mask)
22536 case Intrinsic::riscv_vsseg2_mask:
22537 case Intrinsic::riscv_vsseg3_mask:
22538 case Intrinsic::riscv_vsseg4_mask:
22539 case Intrinsic::riscv_vsseg5_mask:
22540 case Intrinsic::riscv_vsseg6_mask:
22541 case Intrinsic::riscv_vsseg7_mask:
22542 case Intrinsic::riscv_vsseg8_mask: {
22544 unsigned NF = Tuple.getValueType().getRISCVVectorTupleNumFields();
22546 if (Subtarget.hasOptimizedSegmentLoadStore(NF) || !Tuple.hasOneUse() ||
22547 Tuple.getOpcode() != RISCVISD::TUPLE_INSERT ||
22548 !Tuple.getOperand(0).isUndef())
22556 "Type mismatch without bitcast?");
22557 unsigned Stride = SEW / 8 * NF;
22558 unsigned Offset = SEW / 8 * Idx;
22585 case ISD::EXPERIMENTAL_VP_REVERSE:
22587 case ISD::VP_STORE:
22590 assert(Subtarget.useRVVForFixedLengthVectors());
22592 EVT VT =
N->getValueType(0);
22603 for (
unsigned i = 0; i < NF; ++i)
22604 Result = DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VT, Result,
Splat,
22610 if ((SrcVT == MVT::v1i1 || SrcVT == MVT::v2i1 || SrcVT == MVT::v4i1) &&
22631 case RISCVISD::VRGATHER_VX_VL: {
22634 EVT VT =
N->getValueType(0);
22637 SDValue Passthru =
N->getOperand(2);
22644 Src = Src.getOperand(1);
22646 switch (Src.getOpcode()) {
22649 case RISCVISD::VMV_V_X_VL:
22650 case RISCVISD::VFMV_V_F_VL:
22658 case RISCVISD::VMV_S_X_VL:
22659 case RISCVISD::VFMV_S_F_VL:
22675 case RISCVISD::TUPLE_EXTRACT: {
22676 EVT VT =
N->getValueType(0);
22678 unsigned Idx =
N->getConstantOperandVal(1);
22683 switch (Tuple.getConstantOperandVal(1)) {
22686 case Intrinsic::riscv_vlseg2_mask:
22687 case Intrinsic::riscv_vlseg3_mask:
22688 case Intrinsic::riscv_vlseg4_mask:
22689 case Intrinsic::riscv_vlseg5_mask:
22690 case Intrinsic::riscv_vlseg6_mask:
22691 case Intrinsic::riscv_vlseg7_mask:
22692 case Intrinsic::riscv_vlseg8_mask:
22693 NF = Tuple.getValueType().getRISCVVectorTupleNumFields();
22697 if (!NF || Subtarget.hasOptimizedSegmentLoadStore(NF))
22702 "Type mismatch without bitcast?");
22703 unsigned Stride = SEW / 8 * NF;
22704 unsigned Offset = SEW / 8 * Idx;
22710 Passthru = DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL, VT, Passthru,
22714 Tuple.getOperand(0),
22736 return Result.getValue(0);
22738 case RISCVISD::TUPLE_INSERT: {
22740 if (
N->getOperand(1).isUndef())
22741 return N->getOperand(0);
22744 case RISCVISD::VMERGE_VL: {
22748 SDValue Passthru =
N->getOperand(3);
22760 return DAG.
getNode(RISCVISD::VMV_V_V_VL,
SDLoc(
N),
N->getValueType(0),
22761 Passthru, True, VL);
22763 case RISCVISD::VMV_V_V_VL: {
22765 SDValue Passthru =
N->getOperand(0);
22778 MVT VT =
N->getSimpleValueType(0);
22782 case RISCVISD::VSLIDEDOWN_VL:
22783 case RISCVISD::VSLIDEUP_VL:
22784 if (
N->getOperand(1)->isUndef())
22785 return N->getOperand(0);
22787 case RISCVISD::VSLIDE1UP_VL:
22788 case RISCVISD::VFSLIDE1UP_VL: {
22792 MVT VT =
N->getSimpleValueType(0);
22796 if (!
N->getOperand(0).isUndef() ||
22815 return getVSlideup(DAG, Subtarget,
DL, VT, SrcVec,
N->getOperand(1),
22825 EVT XVT,
unsigned KeptBits)
const {
22830 if (XVT != MVT::i32 && XVT != MVT::i64)
22834 if (KeptBits == 32 || KeptBits == 64)
22838 return Subtarget.hasStdExtZbb() &&
22839 ((KeptBits == 8 && XVT == MVT::i64 && !Subtarget.is64Bit()) ||
22847 "Expected shift op");
22871 if (Ty.isScalarInteger() &&
22874 return isUsedByLdSt(N0.
getNode(),
N);
22880 if (C2 && Subtarget.hasShlAdd(C2->getZExtValue()) &&
N->hasOneUse() &&
22881 N->user_begin()->getOpcode() ==
ISD::ADD &&
22882 !isUsedByLdSt(*
N->user_begin(),
nullptr) &&
22887 const APInt &C1Int = C1->getAPIntValue();
22888 APInt ShiftedC1Int = C1Int << C2->getAPIntValue();
22909 ShiftedC1Int, Ty.getSizeInBits(), Subtarget,
22914 if (C1Cost < ShiftedC1Cost)
22937 EVT VT =
Op.getValueType();
22941 unsigned Opcode =
Op.getOpcode();
22949 const APInt &Mask =
C->getAPIntValue();
22958 auto IsLegalMask = [ShrunkMask, ExpandedMask](
const APInt &Mask) ->
bool {
22959 return ShrunkMask.
isSubsetOf(Mask) && Mask.isSubsetOf(ExpandedMask);
22961 auto UseMask = [Mask,
Op, &TLO](
const APInt &NewMask) ->
bool {
22962 if (NewMask == Mask)
22967 Op.getOperand(0), NewC);
22980 APInt NewMask =
APInt(Mask.getBitWidth(), 0xffff);
22981 if (IsLegalMask(NewMask))
22982 return UseMask(NewMask);
22985 if (VT == MVT::i64) {
22987 if (IsLegalMask(NewMask))
22988 return UseMask(NewMask);
23003 APInt NewMask = ShrunkMask;
23004 if (MinSignedBits <= 12)
23006 else if (!
C->isOpaque() && MinSignedBits <= 32 && !ShrunkMask.
isSignedIntN(32))
23012 assert(IsLegalMask(NewMask));
23013 return UseMask(NewMask);
23017 static const uint64_t GREVMasks[] = {
23018 0x5555555555555555ULL, 0x3333333333333333ULL, 0x0F0F0F0F0F0F0F0FULL,
23019 0x00FF00FF00FF00FFULL, 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL};
23021 for (
unsigned Stage = 0; Stage != 6; ++Stage) {
23022 unsigned Shift = 1 << Stage;
23023 if (ShAmt & Shift) {
23025 uint64_t Res = ((x & Mask) << Shift) | ((x >> Shift) & Mask);
23037 const APInt &DemandedElts,
23039 unsigned Depth)
const {
23041 unsigned Opc =
Op.getOpcode();
23046 "Should use MaskedValueIsZero if you don't know whether Op"
23047 " is a target node!");
23052 case RISCVISD::SELECT_CC: {
23063 case RISCVISD::VCPOP_VL: {
23068 case RISCVISD::CZERO_EQZ:
23069 case RISCVISD::CZERO_NEZ:
23075 case RISCVISD::REMUW: {
23085 case RISCVISD::DIVUW: {
23095 case RISCVISD::SLLW: {
23104 case RISCVISD::SRLW: {
23113 case RISCVISD::SRAW: {
23122 case RISCVISD::SHL_ADD: {
23125 unsigned ShAmt =
Op.getConstantOperandVal(1);
23132 case RISCVISD::CTZW: {
23139 case RISCVISD::CLZW: {
23146 case RISCVISD::CLSW: {
23153 unsigned MinRedundantSignBits = NumSignBits < 33 ? 0 : NumSignBits - 33;
23158 Known =
Range.toKnownBits();
23161 case RISCVISD::BREV8:
23162 case RISCVISD::ORC_B: {
23166 bool IsGORC =
Op.getOpcode() == RISCVISD::ORC_B;
23174 case RISCVISD::READ_VLENB: {
23177 const unsigned MinVLenB = Subtarget.getRealMinVLen() / 8;
23178 const unsigned MaxVLenB = Subtarget.getRealMaxVLen() / 8;
23179 assert(MinVLenB > 0 &&
"READ_VLENB without vector extension enabled?");
23182 if (MaxVLenB == MinVLenB)
23186 case RISCVISD::FCLASS: {
23199 case Intrinsic::riscv_vsetvli:
23200 case Intrinsic::riscv_vsetvlimax: {
23201 bool HasAVL = IntNo == Intrinsic::riscv_vsetvli;
23202 unsigned VSEW =
Op.getConstantOperandVal(HasAVL + 1);
23207 uint64_t MaxVL = Subtarget.getRealMaxVLen() / SEW;
23208 MaxVL = (Fractional) ? MaxVL / LMul : MaxVL * LMul;
23212 MaxVL = std::min(MaxVL,
Op.getConstantOperandVal(1));
23214 unsigned KnownZeroFirstBit =
Log2_32(MaxVL) + 1;
23227 unsigned Depth)
const {
23228 switch (
Op.getOpcode()) {
23231 case RISCVISD::SELECT_CC: {
23234 if (Tmp == 1)
return 1;
23237 return std::min(Tmp, Tmp2);
23239 case RISCVISD::CZERO_EQZ:
23240 case RISCVISD::CZERO_NEZ:
23244 case RISCVISD::NEGW_MAX: {
23249 if (Tmp < 33)
return 1;
23252 case RISCVISD::SRAW: {
23259 return std::max(Tmp, 33U);
23261 case RISCVISD::SLLW:
23262 case RISCVISD::SRLW:
23263 case RISCVISD::DIVW:
23264 case RISCVISD::DIVUW:
23265 case RISCVISD::REMUW:
23266 case RISCVISD::ROLW:
23267 case RISCVISD::RORW:
23268 case RISCVISD::ABSW:
23269 case RISCVISD::FCVT_W_RV64:
23270 case RISCVISD::FCVT_WU_RV64:
23271 case RISCVISD::STRICT_FCVT_W_RV64:
23272 case RISCVISD::STRICT_FCVT_WU_RV64:
23275 case RISCVISD::VMV_X_S: {
23281 unsigned XLen = Subtarget.getXLen();
23282 unsigned EltBits =
Op.getOperand(0).getScalarValueSizeInBits();
23283 if (EltBits <= XLen)
23284 return XLen - EltBits + 1;
23288 unsigned IntNo =
Op.getConstantOperandVal(1);
23292 case Intrinsic::riscv_masked_atomicrmw_xchg:
23293 case Intrinsic::riscv_masked_atomicrmw_add:
23294 case Intrinsic::riscv_masked_atomicrmw_sub:
23295 case Intrinsic::riscv_masked_atomicrmw_nand:
23296 case Intrinsic::riscv_masked_atomicrmw_max:
23297 case Intrinsic::riscv_masked_atomicrmw_min:
23298 case Intrinsic::riscv_masked_atomicrmw_umax:
23299 case Intrinsic::riscv_masked_atomicrmw_umin:
23300 case Intrinsic::riscv_masked_cmpxchg:
23307 assert(Subtarget.hasStdExtZalrsc());
23308 return Op.getValueSizeInBits() - 31;
23320 unsigned Depth)
const {
23323 switch (
Op.getOpcode()) {
23324 case RISCVISD::BREV8:
23325 case RISCVISD::ORC_B: {
23327 bool IsGORC =
Op.getOpcode() == RISCVISD::ORC_B;
23335 OriginalDemandedElts, Known2, TLO,
Depth + 1))
23347 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
23355 switch (
Op.getOpcode()) {
23356 case RISCVISD::SLLW:
23357 case RISCVISD::SRAW:
23358 case RISCVISD::SRLW:
23359 case RISCVISD::RORW:
23360 case RISCVISD::ROLW:
23364 case RISCVISD::SELECT_CC:
23366 assert(
Op.getOperand(0).getValueType().isInteger() &&
23367 "RISCVISD::SELECT_CC only compares integers");
23376 assert(Ld &&
"Unexpected null LoadSDNode");
23385 if (!CNode || CNode->isMachineConstantPoolEntry() ||
23386 CNode->getOffset() != 0)
23393 if (Ptr.
getOpcode() == RISCVISD::LLA) {
23394 auto *CNode = GetSupportedConstantPool(Ptr.
getOperand(0));
23395 if (!CNode || CNode->getTargetFlags() != 0)
23398 return CNode->getConstVal();
23402 if (Ptr.
getOpcode() != RISCVISD::ADD_LO ||
23406 auto *CNodeLo = GetSupportedConstantPool(Ptr.
getOperand(1));
23413 if (CNodeLo->getConstVal() != CNodeHi->getConstVal())
23416 return CNodeLo->getConstVal();
23421 assert(
MI.getOpcode() == RISCV::ReadCounterWide &&
"Unexpected instruction");
23453 Register ReadAgainReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
23456 int64_t LoCounter =
MI.getOperand(2).getImm();
23457 int64_t HiCounter =
MI.getOperand(3).getImm();
23467 BuildMI(LoopMBB,
DL,
TII->get(RISCV::CSRRS), ReadAgainReg)
23479 MI.eraseFromParent();
23487 assert(
MI.getOpcode() == RISCV::SplitF64Pseudo &&
"Unexpected instruction");
23494 Register SrcReg =
MI.getOperand(2).getReg();
23499 TII.storeRegToStackSlot(*BB,
MI, SrcReg,
MI.getOperand(2).isKill(), FI, SrcRC,
23519 MI.eraseFromParent();
23526 assert(
MI.getOpcode() == RISCV::BuildPairF64Pseudo &&
23527 "Unexpected instruction");
23532 Register DstReg =
MI.getOperand(0).getReg();
23535 bool KillLo =
MI.getOperand(1).isKill();
23536 bool KillHi =
MI.getOperand(2).isKill();
23564 TII.loadRegFromStackSlot(*BB,
MI, DstReg, FI, DstRC,
Register());
23565 MI.eraseFromParent();
23570 unsigned RelOpcode,
unsigned EqOpcode,
23573 Register DstReg =
MI.getOperand(0).getReg();
23574 Register Src1Reg =
MI.getOperand(1).getReg();
23575 Register Src2Reg =
MI.getOperand(2).getReg();
23601 MI.eraseFromParent();
23652 F->insert(It, FirstMBB);
23653 F->insert(It, SecondMBB);
23654 F->insert(It, SinkMBB);
23704 First.eraseFromParent();
23744 if (
MI.getOpcode() != RISCV::Select_GPR_Using_CC_GPR &&
23745 MI.getOperand(1).isReg() &&
MI.getOperand(2).isReg() &&
23746 Next != BB->
end() &&
Next->getOpcode() ==
MI.getOpcode() &&
23747 Next->getOperand(5).getReg() ==
MI.getOperand(0).getReg() &&
23748 Next->getOperand(5).isKill())
23753 if (
MI.getOperand(2).isReg())
23754 RHS =
MI.getOperand(2).getReg();
23759 SelectDests.
insert(
MI.getOperand(0).getReg());
23765 SequenceMBBI !=
E; ++SequenceMBBI) {
23766 if (SequenceMBBI->isDebugInstr())
23768 if (RISCVInstrInfo::isSelectPseudo(*SequenceMBBI)) {
23769 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
23770 !SequenceMBBI->getOperand(2).isReg() ||
23771 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
23772 SequenceMBBI->getOperand(3).getImm() != CC ||
23773 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
23774 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
23776 LastSelectPseudo = &*SequenceMBBI;
23778 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
23781 if (SequenceMBBI->hasUnmodeledSideEffects() ||
23782 SequenceMBBI->mayLoadOrStore() ||
23783 SequenceMBBI->usesCustomInsertionHook() ||
23784 TII.isFrameInstr(*SequenceMBBI) ||
23785 SequenceMBBI->isStackAligningInlineAsm())
23788 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
23802 F->insert(
I, IfFalseMBB);
23803 F->insert(
I, TailMBB);
23806 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
23812 TailMBB->
push_back(DebugInstr->removeFromParent());
23816 TailMBB->
splice(TailMBB->
end(), HeadMBB,
23826 if (
MI.getOperand(2).isImm())
23829 .
addImm(
MI.getOperand(2).getImm())
23841 auto SelectMBBI =
MI.getIterator();
23842 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
23844 while (SelectMBBI != SelectEnd) {
23845 auto Next = std::next(SelectMBBI);
23846 if (RISCVInstrInfo::isSelectPseudo(*SelectMBBI)) {
23849 TII.get(RISCV::PHI), SelectMBBI->getOperand(0).getReg())
23850 .
addReg(SelectMBBI->getOperand(4).getReg())
23852 .
addReg(SelectMBBI->getOperand(5).getReg())
23859 F->getProperties().resetNoPHIs();
23868 assert(
Inverse &&
"Unexpected LMUL and SEW pair for instruction");
23870 RISCV::lookupMaskedIntrinsicByUnmasked(
Inverse->Pseudo);
23871 assert(
Masked &&
"Could not find masked instruction for LMUL and SEW pair");
23877 unsigned CVTXOpc) {
23896 .
add(
MI.getOperand(1))
23897 .
add(
MI.getOperand(2))
23898 .
add(
MI.getOperand(3))
23900 .
add(
MI.getOperand(4))
23901 .
add(
MI.getOperand(5))
23902 .
add(
MI.getOperand(6))
23917 .
add(
MI.getOperand(0))
23918 .
add(
MI.getOperand(1))
23920 .
add(
MI.getOperand(3))
23922 .
add(
MI.getOperand(4))
23923 .
add(
MI.getOperand(5))
23924 .
add(
MI.getOperand(6))
23934 MI.eraseFromParent();
23940 unsigned CmpOpc, F2IOpc, I2FOpc, FSGNJOpc, FSGNJXOpc;
23942 switch (
MI.getOpcode()) {
23945 case RISCV::PseudoFROUND_H:
23946 CmpOpc = RISCV::FLT_H;
23947 F2IOpc = RISCV::FCVT_W_H;
23948 I2FOpc = RISCV::FCVT_H_W;
23949 FSGNJOpc = RISCV::FSGNJ_H;
23950 FSGNJXOpc = RISCV::FSGNJX_H;
23951 RC = &RISCV::FPR16RegClass;
23953 case RISCV::PseudoFROUND_H_INX:
23954 CmpOpc = RISCV::FLT_H_INX;
23955 F2IOpc = RISCV::FCVT_W_H_INX;
23956 I2FOpc = RISCV::FCVT_H_W_INX;
23957 FSGNJOpc = RISCV::FSGNJ_H_INX;
23958 FSGNJXOpc = RISCV::FSGNJX_H_INX;
23959 RC = &RISCV::GPRF16RegClass;
23961 case RISCV::PseudoFROUND_S:
23962 CmpOpc = RISCV::FLT_S;
23963 F2IOpc = RISCV::FCVT_W_S;
23964 I2FOpc = RISCV::FCVT_S_W;
23965 FSGNJOpc = RISCV::FSGNJ_S;
23966 FSGNJXOpc = RISCV::FSGNJX_S;
23967 RC = &RISCV::FPR32RegClass;
23969 case RISCV::PseudoFROUND_S_INX:
23970 CmpOpc = RISCV::FLT_S_INX;
23971 F2IOpc = RISCV::FCVT_W_S_INX;
23972 I2FOpc = RISCV::FCVT_S_W_INX;
23973 FSGNJOpc = RISCV::FSGNJ_S_INX;
23974 FSGNJXOpc = RISCV::FSGNJX_S_INX;
23975 RC = &RISCV::GPRF32RegClass;
23977 case RISCV::PseudoFROUND_D:
23979 CmpOpc = RISCV::FLT_D;
23980 F2IOpc = RISCV::FCVT_L_D;
23981 I2FOpc = RISCV::FCVT_D_L;
23982 FSGNJOpc = RISCV::FSGNJ_D;
23983 FSGNJXOpc = RISCV::FSGNJX_D;
23984 RC = &RISCV::FPR64RegClass;
23986 case RISCV::PseudoFROUND_D_INX:
23988 CmpOpc = RISCV::FLT_D_INX;
23989 F2IOpc = RISCV::FCVT_L_D_INX;
23990 I2FOpc = RISCV::FCVT_D_L_INX;
23991 FSGNJOpc = RISCV::FSGNJ_D_INX;
23992 FSGNJXOpc = RISCV::FSGNJX_D_INX;
23993 RC = &RISCV::GPRRegClass;
24005 F->insert(
I, CvtMBB);
24006 F->insert(
I, DoneMBB);
24014 MBB->addSuccessor(CvtMBB);
24015 MBB->addSuccessor(DoneMBB);
24017 Register DstReg =
MI.getOperand(0).getReg();
24018 Register SrcReg =
MI.getOperand(1).getReg();
24019 Register MaxReg =
MI.getOperand(2).getReg();
24020 int64_t FRM =
MI.getOperand(3).getImm();
24066 MI.eraseFromParent();
24073 switch (
MI.getOpcode()) {
24076 case RISCV::ReadCounterWide:
24077 assert(!Subtarget.is64Bit() &&
24078 "ReadCounterWide is only to be used on riscv32");
24080 case RISCV::Select_GPR_Using_CC_GPR:
24081 case RISCV::Select_GPR_Using_CC_Imm5_Zibi:
24082 case RISCV::Select_GPR_Using_CC_SImm5_CV:
24083 case RISCV::Select_GPRNoX0_Using_CC_SImm5NonZero_QC:
24084 case RISCV::Select_GPRNoX0_Using_CC_UImm5NonZero_QC:
24085 case RISCV::Select_GPRNoX0_Using_CC_SImm16NonZero_QC:
24086 case RISCV::Select_GPRNoX0_Using_CC_UImm16NonZero_QC:
24087 case RISCV::Select_GPR_Using_CC_UImmLog2XLen_NDS:
24088 case RISCV::Select_GPR_Using_CC_UImm7_NDS:
24089 case RISCV::Select_FPR16_Using_CC_GPR:
24090 case RISCV::Select_FPR16INX_Using_CC_GPR:
24091 case RISCV::Select_FPR32_Using_CC_GPR:
24092 case RISCV::Select_FPR32INX_Using_CC_GPR:
24093 case RISCV::Select_FPR64_Using_CC_GPR:
24094 case RISCV::Select_FPR64INX_Using_CC_GPR:
24095 case RISCV::Select_FPR64IN32X_Using_CC_GPR:
24097 case RISCV::BuildPairF64Pseudo:
24099 case RISCV::SplitF64Pseudo:
24101 case RISCV::PseudoQuietFLE_H:
24103 case RISCV::PseudoQuietFLE_H_INX:
24104 return emitQuietFCMP(
MI, BB, RISCV::FLE_H_INX, RISCV::FEQ_H_INX, Subtarget);
24105 case RISCV::PseudoQuietFLT_H:
24107 case RISCV::PseudoQuietFLT_H_INX:
24108 return emitQuietFCMP(
MI, BB, RISCV::FLT_H_INX, RISCV::FEQ_H_INX, Subtarget);
24109 case RISCV::PseudoQuietFLE_S:
24111 case RISCV::PseudoQuietFLE_S_INX:
24112 return emitQuietFCMP(
MI, BB, RISCV::FLE_S_INX, RISCV::FEQ_S_INX, Subtarget);
24113 case RISCV::PseudoQuietFLT_S:
24115 case RISCV::PseudoQuietFLT_S_INX:
24116 return emitQuietFCMP(
MI, BB, RISCV::FLT_S_INX, RISCV::FEQ_S_INX, Subtarget);
24117 case RISCV::PseudoQuietFLE_D:
24119 case RISCV::PseudoQuietFLE_D_INX:
24120 return emitQuietFCMP(
MI, BB, RISCV::FLE_D_INX, RISCV::FEQ_D_INX, Subtarget);
24121 case RISCV::PseudoQuietFLE_D_IN32X:
24124 case RISCV::PseudoQuietFLT_D:
24126 case RISCV::PseudoQuietFLT_D_INX:
24127 return emitQuietFCMP(
MI, BB, RISCV::FLT_D_INX, RISCV::FEQ_D_INX, Subtarget);
24128 case RISCV::PseudoQuietFLT_D_IN32X:
24132 case RISCV::PseudoVFROUND_NOEXCEPT_V_M1_MASK:
24134 case RISCV::PseudoVFROUND_NOEXCEPT_V_M2_MASK:
24136 case RISCV::PseudoVFROUND_NOEXCEPT_V_M4_MASK:
24138 case RISCV::PseudoVFROUND_NOEXCEPT_V_M8_MASK:
24140 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF2_MASK:
24142 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF4_MASK:
24144 case RISCV::PseudoFROUND_H:
24145 case RISCV::PseudoFROUND_H_INX:
24146 case RISCV::PseudoFROUND_S:
24147 case RISCV::PseudoFROUND_S_INX:
24148 case RISCV::PseudoFROUND_D:
24149 case RISCV::PseudoFROUND_D_INX:
24150 case RISCV::PseudoFROUND_D_IN32X:
24152 case RISCV::PROBED_STACKALLOC_DYN:
24154 case TargetOpcode::STATEPOINT:
24160 MI.addOperand(*
MI.getMF(),
24166 case TargetOpcode::STACKMAP:
24167 case TargetOpcode::PATCHPOINT:
24168 if (!Subtarget.is64Bit())
24170 "supported on 64-bit targets");
24180 if (
auto *FRMDef =
MI.findRegisterDefOperand(RISCV::FRM,
nullptr)) {
24181 FRMDef->setIsDead(
false);
24185 int Idx = RISCV::getNamedOperandIdx(
MI.getOpcode(), RISCV::OpName::frm);
24195 if (
MI.readsRegister(RISCV::FRM,
nullptr))
24201void RISCVTargetLowering::analyzeInputArgs(
24205 for (
const auto &[Idx, In] :
enumerate(Ins)) {
24211 LLVM_DEBUG(
dbgs() <<
"InputArg #" << Idx <<
" has unhandled type "
24218void RISCVTargetLowering::analyzeOutputArgs(
24222 for (
const auto &[Idx, Out] :
enumerate(Outs)) {
24223 MVT ArgVT = Out.VT;
24224 ISD::ArgFlagsTy ArgFlags = Out.Flags;
24228 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << Idx <<
" has unhandled type "
24245 return DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, Val);
24279 if (In.isOrigArg()) {
24284 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
24285 (
BitWidth < 32 && In.Flags.isZExt())) {
24306 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, LocVT, Val);
24307 if (LocVT == MVT::i64 && VA.
getValVT() == MVT::f32)
24308 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Val);
24339 LocVT,
DL, Chain, FIN,
24360 Register LoVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
24373 Register HiVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
24383 return DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64,
Lo,
Hi);
24395 switch (CallConv) {
24404#define CC_VLS_CASE(ABI_VLEN) case CallingConv::RISCV_VLSCall_##ABI_VLEN:
24420 if (Subtarget.hasStdExtE())
24422 if (!Subtarget.hasStdExtFOrZfinx() || !Subtarget.hasStdExtDOrZdinx())
24424 "(Zdinx/D) instruction set extensions");
24428 if (Func.hasFnAttribute(
"interrupt")) {
24429 if (!Func.arg_empty())
24431 "Functions with the interrupt attribute cannot have arguments!");
24442 "SiFive-CLIC-preemptible",
24443 "SiFive-CLIC-stack-swap",
24444 "SiFive-CLIC-preemptible-stack-swap",
24448 "Function interrupt attribute argument not supported!");
24450 if (Kind.starts_with(
"qci-") && !Subtarget.hasVendorXqciint())
24452 "'qci-*' interrupt kinds require Xqciint extension");
24454 if (Kind.starts_with(
"SiFive-CLIC-") && !Subtarget.hasVendorXSfmclic())
24456 "'SiFive-CLIC-*' interrupt kinds require XSfmclic extension");
24458 if (Kind ==
"rnmi" && !Subtarget.hasStdExtSmrnmi())
24461 if (Kind.starts_with(
"SiFive-CLIC-preemptible") && TFI->
hasFP(MF))
24463 "have a frame pointer");
24467 MVT XLenVT = Subtarget.getXLenVT();
24468 unsigned XLenInBytes = Subtarget.getXLen() / 8;
24470 std::vector<SDValue> OutChains;
24479 analyzeInputArgs(MF, CCInfo, Ins,
false,
24483 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
24504 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
24505 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
24507 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
24509 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
24522 if (Ins[InsIdx].Flags.isByVal())
24539 int VarArgsSaveSize = XLenInBytes * (ArgRegs.
size() - Idx);
24544 if (VarArgsSaveSize == 0) {
24548 int VaArgOffset = -VarArgsSaveSize;
24556 XLenInBytes, VaArgOffset -
static_cast<int>(XLenInBytes),
true);
24557 VarArgsSaveSize += XLenInBytes;
24564 for (
unsigned I = Idx;
I < ArgRegs.
size(); ++
I) {
24565 const Register Reg = RegInfo.createVirtualRegister(RC);
24566 RegInfo.addLiveIn(ArgRegs[
I], Reg);
24569 Chain,
DL, ArgValue, FIN,
24571 OutChains.push_back(Store);
24587 if (!OutChains.empty()) {
24588 OutChains.push_back(Chain);
24598bool RISCVTargetLowering::isEligibleForTailCallOptimization(
24602 auto CalleeCC = CLI.CallConv;
24603 auto &Outs = CLI.Outs;
24605 auto CallerCC = Caller.getCallingConv();
24613 if (Caller.hasFnAttribute(
"interrupt"))
24618 if (CCInfo.
getStackSize() > RVFI->getArgumentStackSize())
24623 auto IsCallerStructRet = Caller.hasStructRetAttr();
24624 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
24625 if (IsCallerStructRet != IsCalleeStructRet)
24629 for (
unsigned i = 0, j = 0, e = Outs.
size(); i != e; ++i) {
24630 if (!Outs[i].Flags.isByVal())
24632 if (j++ >= RVFI->getIncomingByValArgsSize())
24634 if (RVFI->getIncomingByValArgs(i).getValueType() != Outs[i].ArgVT)
24640 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
24641 if (CalleeCC != CallerCC) {
24642 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
24643 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
24649 const MachineRegisterInfo &MRI = MF.
getRegInfo();
24650 const SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
24677 MVT XLenVT = Subtarget.getXLenVT();
24692 if (Subtarget.hasStdExtE())
24696 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
24702 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
24708 "call site marked musttail");
24715 for (
unsigned i = 0, j = 0, e = Outs.
size(); i != e; ++i) {
24717 if (!Flags.isByVal())
24721 unsigned Size = Flags.getByValSize();
24722 Align Alignment = Flags.getNonZeroByValAlign();
24739 DAG.
getMemcpy(Chain,
DL, Dst, Arg, SizeNode, Alignment,
24741 false,
nullptr, std::nullopt,
24755 bool AfterFormalArgLoads =
false;
24761 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
24764 SDValue ArgValue = OutVals[OutIdx];
24772 RISCVISD::SplitF64,
DL, DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
24777 if (!Subtarget.isLittleEndian())
24788 if (!StackPtr.getNode())
24800 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
24818 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
24819 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
24825 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
24826 SDValue PartValue = OutVals[OutIdx + 1];
24827 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
24841 DAG.
getStore(Chain,
DL, ArgValue, SpillSlot,
24843 for (
const auto &Part : Parts) {
24844 SDValue PartValue = Part.first;
24845 SDValue PartOffset = Part.second;
24852 ArgValue = SpillSlot;
24858 if (Flags.isByVal()) {
24862 ArgValue = ByValArgs[j++];
24870 if (
Options.EmitCallSiteInfo)
24871 CSInfo.ArgRegPairs.emplace_back(VA.
getLocReg(), i);
24879 if (!StackPtr.getNode())
24887 if (!AfterFormalArgLoads) {
24889 AfterFormalArgLoads =
true;
24899 DAG.
getStore(Chain,
DL, ArgValue, DstAddr, DstInfo));
24904 if (!MemOpChains.
empty())
24910 for (
auto &Reg : RegsToPass) {
24911 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
24918 validateCCReservedRegs(RegsToPass, MF);
24922 "Return address register required, but has been reserved."});
24927 bool CalleeIsLargeExternalSymbol =
false;
24933 CalleeIsLargeExternalSymbol =
true;
24944 Ops.push_back(Chain);
24945 Ops.push_back(Callee);
24949 for (
auto &Reg : RegsToPass)
24950 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
24954 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
24955 assert(Mask &&
"Missing call preserved mask for calling convention");
24960 Ops.push_back(Glue);
24963 "Unexpected CFI type for a direct call");
24971 bool NeedSWGuarded =
false;
24973 Subtarget.hasStdExtZicfilp() &&
24975 NeedSWGuarded =
true;
24980 NeedSWGuarded ? RISCVISD::SW_GUARDED_TAIL : RISCVISD::TAIL;
24989 unsigned CallOpc = NeedSWGuarded ? RISCVISD::SW_GUARDED_CALL : RISCVISD::CALL;
25005 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_RISCV);
25008 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
25009 auto &VA = RVLocs[i];
25017 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
25018 assert(VA.needsCustom());
25027 if (!Subtarget.isLittleEndian())
25030 RetValue = DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64,
Lo,
Hi);
25043 const Type *RetTy)
const {
25045 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
25047 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
25048 MVT VT = Outs[i].VT;
25051 true, Outs[i].OrigTy))
25082 for (
unsigned i = 0, e = RVLocs.
size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
25083 SDValue Val = OutVals[OutIdx];
25092 DAG.
getVTList(MVT::i32, MVT::i32), Val);
25097 if (!Subtarget.isLittleEndian())
25101 Register RegHi = RVLocs[++i].getLocReg();
25103 if (Subtarget.isRegisterReservedByUser(RegLo) ||
25104 Subtarget.isRegisterReservedByUser(RegHi))
25107 "Return value register required, but has been reserved."});
25120 if (Subtarget.isRegisterReservedByUser(VA.
getLocReg()))
25123 "Return value register required, but has been reserved."});
25142 unsigned RetOpc = RISCVISD::RET_GLUE;
25145 if (Func.hasFnAttribute(
"interrupt")) {
25146 if (!Func.getReturnType()->isVoidTy())
25148 "Functions with the interrupt attribute must have void return type!");
25154 if (Kind ==
"supervisor")
25155 RetOpc = RISCVISD::SRET_GLUE;
25156 else if (Kind ==
"rnmi") {
25157 assert(Subtarget.hasFeature(RISCV::FeatureStdExtSmrnmi) &&
25158 "Need Smrnmi extension for rnmi");
25159 RetOpc = RISCVISD::MNRET_GLUE;
25160 }
else if (Kind ==
"qci-nest" || Kind ==
"qci-nonest") {
25161 assert(Subtarget.hasFeature(RISCV::FeatureVendorXqciint) &&
25162 "Need Xqciint for qci-(no)nest");
25163 RetOpc = RISCVISD::QC_C_MILEAVERET_GLUE;
25165 RetOpc = RISCVISD::MRET_GLUE;
25168 return DAG.
getNode(RetOpc,
DL, MVT::Other, RetOps);
25171void RISCVTargetLowering::validateCCReservedRegs(
25172 const SmallVectorImpl<std::pair<llvm::Register, llvm::SDValue>> &Regs,
25180 F,
"Argument register required, but has been reserved."});
25186 if (
N->getNumValues() != 1)
25188 if (!
N->hasNUsesOfValue(1, 0))
25191 SDNode *Copy = *
N->user_begin();
25205 if (Copy->getOperand(Copy->getNumOperands() - 1).getValueType() == MVT::Glue)
25209 bool HasRet =
false;
25211 if (
Node->getOpcode() != RISCVISD::RET_GLUE)
25218 Chain = Copy->getOperand(0);
25230 if (Constraint.
size() == 1) {
25231 switch (Constraint[0]) {
25248 if (Constraint ==
"vr" || Constraint ==
"vd" || Constraint ==
"vm")
25250 if (Constraint ==
"cr" || Constraint ==
"cR" || Constraint ==
"cf")
25256std::pair<unsigned, const TargetRegisterClass *>
25262 if (Constraint.
size() == 1) {
25263 switch (Constraint[0]) {
25268 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
25269 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
25270 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
25271 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
25272 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
25273 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
25274 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
25276 if (VT == MVT::f16) {
25277 if (Subtarget.hasStdExtZfhmin())
25278 return std::make_pair(0U, &RISCV::FPR16RegClass);
25279 if (Subtarget.hasStdExtZhinxmin())
25280 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
25281 }
else if (VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) {
25282 return std::make_pair(0U, &RISCV::FPR16RegClass);
25283 }
else if (VT == MVT::f32) {
25284 if (Subtarget.hasStdExtF())
25285 return std::make_pair(0U, &RISCV::FPR32RegClass);
25286 if (Subtarget.hasStdExtZfinx())
25287 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
25288 }
else if (VT == MVT::f64) {
25289 if (Subtarget.hasStdExtD())
25290 return std::make_pair(0U, &RISCV::FPR64RegClass);
25291 if (Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
25292 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
25293 if (Subtarget.hasStdExtZdinx() && Subtarget.is64Bit())
25294 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
25298 if (((VT == MVT::i64 || VT == MVT::f64) && !Subtarget.is64Bit()) ||
25299 (VT == MVT::i128 && Subtarget.is64Bit()))
25300 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
25305 }
else if (Constraint ==
"vr") {
25308 for (
const auto *RC :
25309 {&RISCV::ZZZ_VMRegClass, &RISCV::ZZZ_VRMF8RegClass,
25310 &RISCV::ZZZ_VRMF4RegClass, &RISCV::ZZZ_VRMF2RegClass,
25311 &RISCV::VRRegClass, &RISCV::VRM2RegClass, &RISCV::VRM4RegClass,
25312 &RISCV::VRM8RegClass, &RISCV::VRN2M1RegClass, &RISCV::VRN3M1RegClass,
25313 &RISCV::VRN4M1RegClass, &RISCV::VRN5M1RegClass,
25314 &RISCV::VRN6M1RegClass, &RISCV::VRN7M1RegClass,
25315 &RISCV::VRN8M1RegClass, &RISCV::VRN2M2RegClass,
25316 &RISCV::VRN3M2RegClass, &RISCV::VRN4M2RegClass,
25317 &RISCV::VRN2M4RegClass}) {
25319 return std::make_pair(0U, RC);
25323 if (
TRI->isTypeLegalForClass(*RC, ContainerVT))
25324 return std::make_pair(0U, RC);
25327 }
else if (Constraint ==
"vd") {
25330 for (
const auto *RC :
25331 {&RISCV::ZZZ_VMNoV0RegClass, &RISCV::ZZZ_VRMF8NoV0RegClass,
25332 &RISCV::ZZZ_VRMF4NoV0RegClass, &RISCV::ZZZ_VRMF2NoV0RegClass,
25333 &RISCV::VRNoV0RegClass, &RISCV::VRM2NoV0RegClass,
25334 &RISCV::VRM4NoV0RegClass, &RISCV::VRM8NoV0RegClass,
25335 &RISCV::VRN2M1NoV0RegClass, &RISCV::VRN3M1NoV0RegClass,
25336 &RISCV::VRN4M1NoV0RegClass, &RISCV::VRN5M1NoV0RegClass,
25337 &RISCV::VRN6M1NoV0RegClass, &RISCV::VRN7M1NoV0RegClass,
25338 &RISCV::VRN8M1NoV0RegClass, &RISCV::VRN2M2NoV0RegClass,
25339 &RISCV::VRN3M2NoV0RegClass, &RISCV::VRN4M2NoV0RegClass,
25340 &RISCV::VRN2M4NoV0RegClass}) {
25342 return std::make_pair(0U, RC);
25346 if (
TRI->isTypeLegalForClass(*RC, ContainerVT))
25347 return std::make_pair(0U, RC);
25350 }
else if (Constraint ==
"vm") {
25351 if (
TRI->isTypeLegalForClass(RISCV::VMV0RegClass, VT.
SimpleTy))
25352 return std::make_pair(0U, &RISCV::VMV0RegClass);
25358 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, ContainerVT))
25359 return std::make_pair(0U, &RISCV::VMV0RegClass);
25361 }
else if (Constraint ==
"cr") {
25362 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
25363 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
25364 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
25365 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
25366 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
25367 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
25369 return std::make_pair(0U, &RISCV::GPRCRegClass);
25370 }
else if (Constraint ==
"cR") {
25371 if (((VT == MVT::i64 || VT == MVT::f64) && !Subtarget.is64Bit()) ||
25372 (VT == MVT::i128 && Subtarget.is64Bit()))
25373 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
25374 }
else if (Constraint ==
"cf") {
25375 if (VT == MVT::f16) {
25376 if (Subtarget.hasStdExtZfhmin())
25377 return std::make_pair(0U, &RISCV::FPR16CRegClass);
25378 if (Subtarget.hasStdExtZhinxmin())
25379 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
25380 }
else if (VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) {
25381 return std::make_pair(0U, &RISCV::FPR16CRegClass);
25382 }
else if (VT == MVT::f32) {
25383 if (Subtarget.hasStdExtF())
25384 return std::make_pair(0U, &RISCV::FPR32CRegClass);
25385 if (Subtarget.hasStdExtZfinx())
25386 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
25387 }
else if (VT == MVT::f64) {
25388 if (Subtarget.hasStdExtD())
25389 return std::make_pair(0U, &RISCV::FPR64CRegClass);
25390 if (Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
25391 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
25392 if (Subtarget.hasStdExtZdinx() && Subtarget.is64Bit())
25393 return std::make_pair(0U, &RISCV::GPRCRegClass);
25402 .
Case(
"{zero}", RISCV::X0)
25403 .
Case(
"{ra}", RISCV::X1)
25404 .
Case(
"{sp}", RISCV::X2)
25405 .
Case(
"{gp}", RISCV::X3)
25406 .
Case(
"{tp}", RISCV::X4)
25407 .
Case(
"{t0}", RISCV::X5)
25408 .
Case(
"{t1}", RISCV::X6)
25409 .
Case(
"{t2}", RISCV::X7)
25410 .
Cases({
"{s0}",
"{fp}"}, RISCV::X8)
25411 .Case(
"{s1}", RISCV::X9)
25412 .
Case(
"{a0}", RISCV::X10)
25413 .
Case(
"{a1}", RISCV::X11)
25414 .
Case(
"{a2}", RISCV::X12)
25415 .
Case(
"{a3}", RISCV::X13)
25416 .
Case(
"{a4}", RISCV::X14)
25417 .
Case(
"{a5}", RISCV::X15)
25418 .
Case(
"{a6}", RISCV::X16)
25419 .
Case(
"{a7}", RISCV::X17)
25420 .
Case(
"{s2}", RISCV::X18)
25421 .
Case(
"{s3}", RISCV::X19)
25422 .
Case(
"{s4}", RISCV::X20)
25423 .
Case(
"{s5}", RISCV::X21)
25424 .
Case(
"{s6}", RISCV::X22)
25425 .
Case(
"{s7}", RISCV::X23)
25426 .
Case(
"{s8}", RISCV::X24)
25427 .
Case(
"{s9}", RISCV::X25)
25428 .
Case(
"{s10}", RISCV::X26)
25429 .
Case(
"{s11}", RISCV::X27)
25430 .
Case(
"{t3}", RISCV::X28)
25431 .
Case(
"{t4}", RISCV::X29)
25432 .
Case(
"{t5}", RISCV::X30)
25433 .
Case(
"{t6}", RISCV::X31)
25435 if (XRegFromAlias != RISCV::NoRegister)
25436 return std::make_pair(XRegFromAlias, &RISCV::GPRRegClass);
25445 if (Subtarget.hasStdExtF()) {
25447 .
Cases({
"{f0}",
"{ft0}"}, RISCV::F0_F)
25448 .Cases({
"{f1}",
"{ft1}"}, RISCV::F1_F)
25449 .Cases({
"{f2}",
"{ft2}"}, RISCV::F2_F)
25450 .Cases({
"{f3}",
"{ft3}"}, RISCV::F3_F)
25451 .Cases({
"{f4}",
"{ft4}"}, RISCV::F4_F)
25452 .Cases({
"{f5}",
"{ft5}"}, RISCV::F5_F)
25453 .Cases({
"{f6}",
"{ft6}"}, RISCV::F6_F)
25454 .Cases({
"{f7}",
"{ft7}"}, RISCV::F7_F)
25455 .Cases({
"{f8}",
"{fs0}"}, RISCV::F8_F)
25456 .Cases({
"{f9}",
"{fs1}"}, RISCV::F9_F)
25457 .Cases({
"{f10}",
"{fa0}"}, RISCV::F10_F)
25458 .Cases({
"{f11}",
"{fa1}"}, RISCV::F11_F)
25459 .Cases({
"{f12}",
"{fa2}"}, RISCV::F12_F)
25460 .Cases({
"{f13}",
"{fa3}"}, RISCV::F13_F)
25461 .Cases({
"{f14}",
"{fa4}"}, RISCV::F14_F)
25462 .Cases({
"{f15}",
"{fa5}"}, RISCV::F15_F)
25463 .Cases({
"{f16}",
"{fa6}"}, RISCV::F16_F)
25464 .Cases({
"{f17}",
"{fa7}"}, RISCV::F17_F)
25465 .Cases({
"{f18}",
"{fs2}"}, RISCV::F18_F)
25466 .Cases({
"{f19}",
"{fs3}"}, RISCV::F19_F)
25467 .Cases({
"{f20}",
"{fs4}"}, RISCV::F20_F)
25468 .Cases({
"{f21}",
"{fs5}"}, RISCV::F21_F)
25469 .Cases({
"{f22}",
"{fs6}"}, RISCV::F22_F)
25470 .Cases({
"{f23}",
"{fs7}"}, RISCV::F23_F)
25471 .Cases({
"{f24}",
"{fs8}"}, RISCV::F24_F)
25472 .Cases({
"{f25}",
"{fs9}"}, RISCV::F25_F)
25473 .Cases({
"{f26}",
"{fs10}"}, RISCV::F26_F)
25474 .Cases({
"{f27}",
"{fs11}"}, RISCV::F27_F)
25475 .Cases({
"{f28}",
"{ft8}"}, RISCV::F28_F)
25476 .Cases({
"{f29}",
"{ft9}"}, RISCV::F29_F)
25477 .Cases({
"{f30}",
"{ft10}"}, RISCV::F30_F)
25478 .Cases({
"{f31}",
"{ft11}"}, RISCV::F31_F)
25480 if (FReg != RISCV::NoRegister) {
25481 assert(RISCV::F0_F <= FReg && FReg <= RISCV::F31_F &&
"Unknown fp-reg");
25482 if (Subtarget.hasStdExtD() && (VT == MVT::f64 || VT == MVT::Other)) {
25483 unsigned RegNo = FReg - RISCV::F0_F;
25484 unsigned DReg = RISCV::F0_D + RegNo;
25485 return std::make_pair(DReg, &RISCV::FPR64RegClass);
25487 if (VT == MVT::f32 || VT == MVT::Other)
25488 return std::make_pair(FReg, &RISCV::FPR32RegClass);
25489 if (Subtarget.hasStdExtZfhmin() && VT == MVT::f16) {
25490 unsigned RegNo = FReg - RISCV::F0_F;
25491 unsigned HReg = RISCV::F0_H + RegNo;
25492 return std::make_pair(HReg, &RISCV::FPR16RegClass);
25497 if (Subtarget.hasVInstructions()) {
25499 .
Case(
"{v0}", RISCV::V0)
25500 .
Case(
"{v1}", RISCV::V1)
25501 .
Case(
"{v2}", RISCV::V2)
25502 .
Case(
"{v3}", RISCV::V3)
25503 .
Case(
"{v4}", RISCV::V4)
25504 .
Case(
"{v5}", RISCV::V5)
25505 .
Case(
"{v6}", RISCV::V6)
25506 .
Case(
"{v7}", RISCV::V7)
25507 .
Case(
"{v8}", RISCV::V8)
25508 .
Case(
"{v9}", RISCV::V9)
25509 .
Case(
"{v10}", RISCV::V10)
25510 .
Case(
"{v11}", RISCV::V11)
25511 .
Case(
"{v12}", RISCV::V12)
25512 .
Case(
"{v13}", RISCV::V13)
25513 .
Case(
"{v14}", RISCV::V14)
25514 .
Case(
"{v15}", RISCV::V15)
25515 .
Case(
"{v16}", RISCV::V16)
25516 .
Case(
"{v17}", RISCV::V17)
25517 .
Case(
"{v18}", RISCV::V18)
25518 .
Case(
"{v19}", RISCV::V19)
25519 .
Case(
"{v20}", RISCV::V20)
25520 .
Case(
"{v21}", RISCV::V21)
25521 .
Case(
"{v22}", RISCV::V22)
25522 .
Case(
"{v23}", RISCV::V23)
25523 .
Case(
"{v24}", RISCV::V24)
25524 .
Case(
"{v25}", RISCV::V25)
25525 .
Case(
"{v26}", RISCV::V26)
25526 .
Case(
"{v27}", RISCV::V27)
25527 .
Case(
"{v28}", RISCV::V28)
25528 .
Case(
"{v29}", RISCV::V29)
25529 .
Case(
"{v30}", RISCV::V30)
25530 .
Case(
"{v31}", RISCV::V31)
25532 if (VReg != RISCV::NoRegister) {
25533 if (
TRI->isTypeLegalForClass(RISCV::ZZZ_VMRegClass, VT.
SimpleTy))
25534 return std::make_pair(VReg, &RISCV::ZZZ_VMRegClass);
25535 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, VT.
SimpleTy))
25536 return std::make_pair(VReg, &RISCV::VRRegClass);
25537 for (
const auto *RC :
25538 {&RISCV::VRM2RegClass, &RISCV::VRM4RegClass, &RISCV::VRM8RegClass}) {
25539 if (
TRI->isTypeLegalForClass(*RC, VT.
SimpleTy)) {
25540 VReg =
TRI->getMatchingSuperReg(VReg, RISCV::sub_vrm1_0, RC);
25541 return std::make_pair(VReg, RC);
25553 if (ConstraintCode.
size() == 1) {
25554 switch (ConstraintCode[0]) {
25569 if (Constraint.
size() == 1) {
25570 switch (Constraint[0]) {
25577 Subtarget.getXLenVT()));
25608 if (Subtarget.hasStdExtZtso()) {
25610 return Builder.CreateFence(Ord);
25615 return Builder.CreateFence(Ord);
25624 if (Subtarget.hasStdExtZtso()) {
25626 return Builder.CreateFence(Ord);
25632 if (Subtarget.enableTrailingSeqCstFence() &&
isa<StoreInst>(Inst) &&
25651 if (Subtarget.hasForcedAtomics())
25656 if (Subtarget.hasStdExtZacas() &&
25657 (
Size >= 32 || Subtarget.hasStdExtZabha()))
25663 if (
Size < 32 && !Subtarget.hasStdExtZabha())
25675 return Intrinsic::riscv_masked_atomicrmw_xchg;
25677 return Intrinsic::riscv_masked_atomicrmw_add;
25679 return Intrinsic::riscv_masked_atomicrmw_sub;
25681 return Intrinsic::riscv_masked_atomicrmw_nand;
25683 return Intrinsic::riscv_masked_atomicrmw_max;
25685 return Intrinsic::riscv_masked_atomicrmw_min;
25687 return Intrinsic::riscv_masked_atomicrmw_umax;
25689 return Intrinsic::riscv_masked_atomicrmw_umin;
25705 Builder.CreateNot(Mask,
"Inv_Mask"),
25712 unsigned XLen = Subtarget.getXLen();
25715 Type *Tys[] = {Builder.getIntNTy(XLen), AlignedAddr->
getType()};
25721 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
25722 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
25723 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
25736 unsigned ValWidth =
25739 Builder.CreateSub(Builder.getIntN(XLen, XLen - ValWidth), ShiftAmt);
25740 Result = Builder.CreateCall(LrwOpScwLoop,
25741 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
25744 Builder.CreateCall(LrwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
25748 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
25756 if (Subtarget.hasForcedAtomics())
25760 if (!(Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas()) &&
25769 unsigned XLen = Subtarget.getXLen();
25770 Value *Ordering = Builder.getIntN(XLen,
static_cast<uint64_t>(Ord));
25771 Intrinsic::ID CmpXchgIntrID = Intrinsic::riscv_masked_cmpxchg;
25773 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
25774 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
25775 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
25777 Type *Tys[] = {Builder.getIntNTy(XLen), AlignedAddr->
getType()};
25778 Value *Result = Builder.CreateIntrinsic(
25779 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, Ordering});
25781 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
25786 EVT DataVT)
const {
25802 return Subtarget.hasStdExtZfhmin();
25804 return Subtarget.hasStdExtF();
25806 return Subtarget.hasStdExtD();
25835 if (!Subtarget.hasVendorXTHeadMemIdx())
25841 Base =
Op->getOperand(0);
25843 int64_t RHSC = RHS->getSExtValue();
25849 bool isLegalIndexedOffset =
false;
25850 for (
unsigned i = 0; i < 4; i++)
25851 if (
isInt<5>(RHSC >> i) && ((RHSC % (1LL << i)) == 0)) {
25852 isLegalIndexedOffset =
true;
25856 if (!isLegalIndexedOffset)
25873 VT = LD->getMemoryVT();
25874 Ptr = LD->getBasePtr();
25876 VT = ST->getMemoryVT();
25877 Ptr = ST->getBasePtr();
25893 if (Subtarget.hasVendorXCVmem() && !Subtarget.is64Bit()) {
25898 Base = LS->getBasePtr();
25902 if (
Base ==
Op->getOperand(0))
25904 else if (
Base ==
Op->getOperand(1))
25916 VT = LD->getMemoryVT();
25917 Ptr = LD->getBasePtr();
25919 VT = ST->getMemoryVT();
25920 Ptr = ST->getBasePtr();
25944 return VT.
isVector() ? Subtarget.hasVInstructionsF16()
25945 : Subtarget.hasStdExtZfhOrZhinx();
25947 return Subtarget.hasStdExtFOrZfinx();
25949 return Subtarget.hasStdExtDOrZdinx();
25964 if (Subtarget.hasStdExtZaamo() || Subtarget.hasForcedAtomics())
25968 assert(Subtarget.hasStdExtZalrsc());
25982 const Constant *PersonalityFn)
const {
25987 const Constant *PersonalityFn)
const {
25994 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
25995 Type.getSizeInBits() < Subtarget.getXLen()))
26002 bool IsSigned)
const {
26003 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
26017 const bool HasZmmul = Subtarget.hasStdExtZmmul();
26022 const APInt &Imm = ConstNode->getAPIntValue();
26025 if (Subtarget.hasVendorXqciac() && Imm.isSignedIntN(12))
26029 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
26030 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
26034 if (Subtarget.hasShlAdd(3) && !Imm.isSignedIntN(12) &&
26035 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
26036 (Imm - 8).isPowerOf2()))
26041 if (!Imm.isSignedIntN(12) && Imm.countr_zero() < 12 &&
26042 ConstNode->hasOneUse()) {
26043 APInt ImmS = Imm.ashr(Imm.countr_zero());
26044 if ((ImmS + 1).isPowerOf2() || (ImmS - 1).isPowerOf2() ||
26045 (1 - ImmS).isPowerOf2())
26068 if (C1.
isSignedIntN(12) && !(C1 * C2).isSignedIntN(12))
26077 unsigned *
Fast)
const {
26078 if (!VT.
isVector() || Subtarget.hasStdExtP()) {
26080 *
Fast = Subtarget.enableUnalignedScalarMem();
26081 return Subtarget.enableUnalignedScalarMem();
26097 *
Fast = Subtarget.enableUnalignedVectorMem();
26098 return Subtarget.enableUnalignedVectorMem();
26103 const AttributeList &FuncAttributes)
const {
26104 if (!Subtarget.hasVInstructions())
26107 if (FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat))
26119 const unsigned MinVLenInBytes =
26120 std::min(Subtarget.getRealMinVLen() / 8, 1024U);
26122 if (
Op.size() < MinVLenInBytes)
26137 MVT PreferredVT = (
Op.isMemset() && !
Op.isZeroMemset()) ? MVT::i8 : ELenVT;
26141 if (PreferredVT != MVT::i8 && !Subtarget.enableUnalignedVectorMem()) {
26143 if (
Op.isFixedDstAlign())
26144 RequiredAlign = std::min(RequiredAlign,
Op.getDstAlign());
26146 RequiredAlign = std::min(RequiredAlign,
Op.getSrcAlign());
26154 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
26155 bool IsABIRegCopy = CC.has_value();
26158 MVT PairVT = Subtarget.is64Bit() ? MVT::i128 : MVT::i64;
26159 if ((ValueVT == PairVT ||
26160 (!Subtarget.is64Bit() && Subtarget.hasStdExtZdinx() &&
26161 ValueVT == MVT::f64)) &&
26162 NumParts == 1 && PartVT == MVT::Untyped) {
26164 MVT XLenVT = Subtarget.getXLenVT();
26165 if (ValueVT == MVT::f64)
26170 Parts[0] = DAG.
getNode(RISCVISD::BuildGPRPair,
DL, PartVT,
Lo,
Hi);
26174 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
26175 PartVT == MVT::f32) {
26190 [[maybe_unused]]
unsigned ValLMUL =
26194 [[maybe_unused]]
unsigned PartLMUL =
26197 assert(ValNF == PartNF && ValLMUL == PartLMUL &&
26198 "RISC-V vector tuple type only accepts same register class type "
26217 if (PartVTBitSize % ValueVTBitSize == 0) {
26218 assert(PartVTBitSize >= ValueVTBitSize);
26225 if (ValueEltVT != PartEltVT) {
26226 if (PartVTBitSize > ValueVTBitSize) {
26228 assert(
Count != 0 &&
"The number of element should not be zero.");
26229 EVT SameEltTypeVT =
26247 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
26248 bool IsABIRegCopy = CC.has_value();
26250 MVT PairVT = Subtarget.is64Bit() ? MVT::i128 : MVT::i64;
26251 if ((ValueVT == PairVT ||
26252 (!Subtarget.is64Bit() && Subtarget.hasStdExtZdinx() &&
26253 ValueVT == MVT::f64)) &&
26254 NumParts == 1 && PartVT == MVT::Untyped) {
26256 MVT XLenVT = Subtarget.getXLenVT();
26265 if (ValueVT == MVT::f64)
26270 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
26271 PartVT == MVT::f32) {
26287 unsigned ValueVTBitSize =
26293 if (PartVTBitSize % ValueVTBitSize == 0) {
26294 assert(PartVTBitSize >= ValueVTBitSize);
26295 EVT SameEltTypeVT = ValueVT;
26302 if (ValueEltVT != PartEltVT) {
26304 assert(
Count != 0 &&
"The number of element should not be zero.");
26323 bool OptSize = Attr.hasFnAttr(Attribute::MinSize);
26324 return OptSize && !VT.
isVector() &&
26336 unsigned Opc =
N->getOpcode();
26345 M, Intrinsic::thread_pointer, IRB.
getPtrTy());
26354 if (Subtarget.isTargetFuchsia())
26360 if (Subtarget.isTargetAndroid())
26365 if (M->getStackProtectorGuard() ==
"tls") {
26367 int Offset = M->getStackProtectorGuardOffset();
26375 Align Alignment)
const {
26376 if (!Subtarget.hasVInstructions())
26380 if (DataType.isFixedLengthVector() && !Subtarget.useRVVForFixedLengthVectors())
26387 if (!Subtarget.enableUnalignedVectorMem() &&
26395 Align Alignment)
const {
26396 if (!Subtarget.hasVInstructions())
26403 if (!Subtarget.enableUnalignedVectorMem() &&
26415 "Invalid call instruction for a KCFI check");
26417 MBBI->getOpcode()));
26420 Target.setIsRenamable(
false);
26428#define GET_REGISTER_MATCHER
26429#include "RISCVGenAsmMatcher.inc"
26440 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
26441 if (!ReservedRegs.
test(Reg) && !Subtarget.isRegisterReservedByUser(Reg))
26449 const MDNode *NontemporalInfo =
I.getMetadata(LLVMContext::MD_nontemporal);
26451 if (NontemporalInfo ==
nullptr)
26459 int NontemporalLevel = 5;
26460 const MDNode *RISCVNontemporalInfo =
26461 I.getMetadata(
"riscv-nontemporal-domain");
26462 if (RISCVNontemporalInfo !=
nullptr)
26469 assert((1 <= NontemporalLevel && NontemporalLevel <= 5) &&
26470 "RISC-V target doesn't support this non-temporal domain.");
26472 NontemporalLevel -= 2;
26474 if (NontemporalLevel & 0b1)
26476 if (NontemporalLevel & 0b10)
26489 return TargetFlags;
26502 return Subtarget.hasStdExtZvbb();
26507 return Subtarget.hasCPOPLike() && (VT == MVT::i32 || VT == MVT::i64);
26517 if (Subtarget.hasStdExtZalasr()) {
26518 if (Subtarget.hasStdExtZtso()) {
26548 if (
Op == Instruction::Add ||
Op == Instruction::Sub ||
26549 Op == Instruction::And ||
Op == Instruction::Or ||
26550 Op == Instruction::Xor ||
Op == Instruction::InsertElement ||
26551 Op == Instruction::ShuffleVector ||
Op == Instruction::Load ||
26552 Op == Instruction::Freeze ||
Op == Instruction::Store)
26557 if (RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(
II->getIntrinsicID())) {
26564 for (
unsigned i = 0; i <
II->arg_size(); ++i)
26565 if (
II->getArgOperand(i)->getType()->isRISCVVectorTupleTy())
26570 if (
II->getIntrinsicID() == Intrinsic::vector_extract)
26586RISCVTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
26594 if (!Subtarget.hasShortForwardBranchIALU())
26596 EVT VT =
N->getValueType(0);
26597 if (!(VT == MVT::i32 || (VT == MVT::i64 && Subtarget.
is64Bit())))
26601 if (Divisor.
sgt(2048) || Divisor.
slt(-2048))
26606bool RISCVTargetLowering::shouldFoldSelectWithSingleBitTest(
26607 EVT VT,
const APInt &AndMask)
const {
26608 if (Subtarget.
hasCZEROLike() || Subtarget.hasVendorXTHeadCondMov())
26614 return Subtarget.getMinimumJumpTableEntries();
26621 if (Subtarget.hasStdExtZicfilp()) {
26628 return DAG.
getNode(RISCVISD::SW_GUARDED_BRIND, dl, MVT::Other, Chain, Addr);
26645std::pair<const TargetRegisterClass *, uint8_t>
26665#define GET_RISCVVIntrinsicsTable_IMPL
26666#include "RISCVGenSearchableTables.inc"
26681 Align StackAlign)
const {
26685 unsigned StackProbeSize =
26689 return StackProbeSize ? StackProbeSize : StackAlign.
value();
26706 EVT VT =
Op.getValueType();
26717 Chain = DAG.
getNode(RISCVISD::PROBED_ALLOCA, dl, MVT::Other, Chain, SP);
26727 Register TargetReg =
MI.getOperand(0).getReg();
26730 bool IsRV64 = Subtarget.is64Bit();
26731 Align StackAlign = Subtarget.getFrameLowering()->getStackAlign();
26738 MF.
insert(MBBInsertPoint, LoopTestMBB);
26740 MF.
insert(MBBInsertPoint, ExitMBB);
26756 TII->get(IsRV64 ? RISCV::SD : RISCV::SW))
26777 MBB->addSuccessor(LoopTestMBB);
26779 MI.eraseFromParent();
26781 return ExitMBB->
begin()->getParent();
26785 if (Subtarget.hasStdExtFOrZfinx()) {
26786 static const MCPhysReg RCRegs[] = {RISCV::FRM, RISCV::FFLAGS};
26793 EVT VT =
Y.getValueType();
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)
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")
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)
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
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
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 SDValue combineVdota4Accum(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
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 compressShuffleOfShuffles(ShuffleVectorSDNode *SVN, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
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 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 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 combineNarrowableShiftedLoad(SDNode *N, 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 SDValue performVWABDACombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
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 foldReduceOperandViaVDOTA4(SDValue InVec, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
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.
bool ult(const APInt &RHS) const
Unsigned less than comparison.
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.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
An arbitrary precision integer that knows its signedness.
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...
This class represents a range of values.
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.
Tracks which library functions to use for a particular subtarget.
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 void computeMaxCallFrameSize(MachineFunction &MF, std::vector< MachineBasicBlock::iterator > *FrameSDOps=nullptr)
Computes the maximum size of a callframe.
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 MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
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 & 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 the unique 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-...
SDValue getIncomingByValArgs(unsigned Idx)
void setArgumentStackSize(unsigned size)
void setVarArgsFrameIndex(int Index)
int getVarArgsFrameIndex() const
void setVarArgsSaveSize(int Size)
void addSExt32Register(Register Reg)
void addIncomingByValArgs(SDValue Val)
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
bool isLittleEndian() const
unsigned getRealMaxVLen() const
const RISCVRegisterInfo * getRegisterInfo() const override
const RISCVInstrInfo * getInstrInfo() const override
bool hasBEXTILike() const
const RISCVTargetLowering * getTargetLowering() const override
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
Value * getIRStackGuard(IRBuilderBase &IRB, const LibcallLoweringInfo &Libcalls) const override
If the target has a standard location for the stack protector cookie, returns the address of that loc...
static unsigned getSubregIndexByMVT(MVT VT, unsigned Index)
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...
TargetLowering::AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
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
void finalizeLowering(MachineFunction &MF) const override
Execute target specific actions to finalize target lowering.
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 ...
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),...
TargetLowering::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *CI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
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.
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.
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.
void getTgtMemIntrinsic(SmallVectorImpl< IntrinsicInfo > &Infos, 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...
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.
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
unsigned getResNo() const
get the index which selects a specific result in the SDNode
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)
LLVM_ABI SDValue getStackArgumentTokenFactor(SDValue Chain)
Compute a TokenFactor to force all the incoming stack arguments to be loaded from the stack.
const TargetSubtargetInfo & getSubtarget() const
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)
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,...
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false, SDNodeFlags Flags={})
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
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...
virtual void finalizeLowering(MachineFunction &MF) const
Execute target specific actions to finalize target lowering.
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 Value * getIRStackGuard(IRBuilderBase &IRB, const LibcallLoweringInfo &Libcalls) const
If the target has a standard location for the stack protector guard, returns the address of that loca...
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.
virtual EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const
For types supported by the target, this is an identity function.
unsigned MaxStoresPerMemmoveOptSize
Likewise for functions with the OptSize attribute.
virtual bool shouldFoldSelectWithSingleBitTest(EVT VT, const APInt &AndMask) const
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
@ ZeroOrNegativeOneBooleanContent
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....
void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
If Opc/OrigVT is specified as being promoted, the promotion code defaults to trying a larger integer/...
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.
bool parametersInCSRMatch(const MachineRegisterInfo &MRI, const uint32_t *CallerPreservedMask, const SmallVectorImpl< CCValAssign > &ArgLocs, const SmallVectorImpl< SDValue > &OutVals) const
Check whether parameters to a call that are passed in callee saved registers are the same as from the...
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.
void setTypeIdForCallsiteInfo(const CallBase *CB, MachineFunction &MF, MachineFunction::CallSiteInfo &CSInfo) const
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
bool shouldAssumeDSOLocal(const GlobalValue *GV) const
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.
@ PARTIAL_REDUCE_SMLA
PARTIAL_REDUCE_[U|S]MLA(Accumulator, Input1, Input2) The partial reduction nodes sign or zero extend ...
@ 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.
@ CLMUL
Carry-less multiplication operations.
@ 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.
@ SSUBO
Same for subtraction.
@ 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.
@ CTLS
Count leading redundant sign bits.
@ 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.
@ VECTOR_SPLICE_LEFT
VECTOR_SPLICE_LEFT(VEC1, VEC2, OFFSET) - Shifts CONCAT_VECTORS(VEC1, VEC2) left by OFFSET elements an...
@ 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],...
@ VECTOR_SPLICE_RIGHT
VECTOR_SPLICE_RIGHT(VEC1, VEC2, OFFSET) - Shifts CONCAT_VECTORS(VEC1,VEC2) right by OFFSET elements a...
@ 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.
@ 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....
@ CLEAR_CACHE
llvm.clear_cache intrinsic Operands: Input Chain, Start Addres, End Address Outputs: Output Chain
@ 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
const PseudoInfo * getBaseInfo(unsigned BaseInstr, uint8_t VLMul, uint8_t SEW, bool IsAltFmt=false)
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.
Opcode_match m_Opc(unsigned Opcode)
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)
And< Preds... > m_AllOf(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.
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.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
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,...
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
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)
auto dyn_cast_or_null(const Y &Val)
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.
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.
EVT changeVectorElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
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.
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).
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)