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"),
98 !Subtarget.hasStdExtF()) {
99 errs() <<
"Hard-float 'f' ABI can't be used for a target that "
100 "doesn't support the F instruction set extension (ignoring "
104 !Subtarget.hasStdExtD()) {
105 errs() <<
"Hard-float 'd' ABI can't be used for a target that "
106 "doesn't support the D instruction set extension (ignoring "
125 MVT XLenVT = Subtarget.getXLenVT();
130 if (Subtarget.hasStdExtZfhmin())
132 if (Subtarget.hasStdExtZfbfmin() || Subtarget.hasVendorXAndesBFHCvt())
134 if (Subtarget.hasStdExtF())
136 if (Subtarget.hasStdExtD())
138 if (Subtarget.hasStdExtZhinxmin())
140 if (Subtarget.hasStdExtZfinx())
142 if (Subtarget.hasStdExtZdinx()) {
143 if (Subtarget.is64Bit())
150 MVT::nxv1i1, MVT::nxv2i1, MVT::nxv4i1, MVT::nxv8i1,
151 MVT::nxv16i1, MVT::nxv32i1, MVT::nxv64i1};
153 MVT::nxv1i8, MVT::nxv2i8, MVT::nxv4i8, MVT::nxv8i8, MVT::nxv16i8,
154 MVT::nxv32i8, MVT::nxv64i8, MVT::nxv1i16, MVT::nxv2i16, MVT::nxv4i16,
155 MVT::nxv8i16, MVT::nxv16i16, MVT::nxv32i16, MVT::nxv1i32, MVT::nxv2i32,
156 MVT::nxv4i32, MVT::nxv8i32, MVT::nxv16i32, MVT::nxv1i64, MVT::nxv2i64,
157 MVT::nxv4i64, MVT::nxv8i64};
159 MVT::nxv1f16, MVT::nxv2f16, MVT::nxv4f16,
160 MVT::nxv8f16, MVT::nxv16f16, MVT::nxv32f16};
162 MVT::nxv1bf16, MVT::nxv2bf16, MVT::nxv4bf16,
163 MVT::nxv8bf16, MVT::nxv16bf16, MVT::nxv32bf16};
165 MVT::nxv1f32, MVT::nxv2f32, MVT::nxv4f32, MVT::nxv8f32, MVT::nxv16f32};
167 MVT::nxv1f64, MVT::nxv2f64, MVT::nxv4f64, MVT::nxv8f64};
169 MVT::riscv_nxv1i8x2, MVT::riscv_nxv1i8x3, MVT::riscv_nxv1i8x4,
170 MVT::riscv_nxv1i8x5, MVT::riscv_nxv1i8x6, MVT::riscv_nxv1i8x7,
171 MVT::riscv_nxv1i8x8, MVT::riscv_nxv2i8x2, MVT::riscv_nxv2i8x3,
172 MVT::riscv_nxv2i8x4, MVT::riscv_nxv2i8x5, MVT::riscv_nxv2i8x6,
173 MVT::riscv_nxv2i8x7, MVT::riscv_nxv2i8x8, MVT::riscv_nxv4i8x2,
174 MVT::riscv_nxv4i8x3, MVT::riscv_nxv4i8x4, MVT::riscv_nxv4i8x5,
175 MVT::riscv_nxv4i8x6, MVT::riscv_nxv4i8x7, MVT::riscv_nxv4i8x8,
176 MVT::riscv_nxv8i8x2, MVT::riscv_nxv8i8x3, MVT::riscv_nxv8i8x4,
177 MVT::riscv_nxv8i8x5, MVT::riscv_nxv8i8x6, MVT::riscv_nxv8i8x7,
178 MVT::riscv_nxv8i8x8, MVT::riscv_nxv16i8x2, MVT::riscv_nxv16i8x3,
179 MVT::riscv_nxv16i8x4, MVT::riscv_nxv32i8x2};
181 if (Subtarget.hasVInstructions()) {
182 auto addRegClassForRVV = [
this](
MVT VT) {
186 if (VT.getVectorMinNumElements() < MinElts)
189 unsigned Size = VT.getSizeInBits().getKnownMinValue();
192 RC = &RISCV::VRRegClass;
194 RC = &RISCV::VRM2RegClass;
196 RC = &RISCV::VRM4RegClass;
198 RC = &RISCV::VRM8RegClass;
205 for (
MVT VT : BoolVecVTs)
206 addRegClassForRVV(VT);
207 for (
MVT VT : IntVecVTs) {
208 if (VT.getVectorElementType() == MVT::i64 &&
209 !Subtarget.hasVInstructionsI64())
211 addRegClassForRVV(VT);
214 if (Subtarget.hasVInstructionsF16Minimal() ||
215 Subtarget.hasVendorXAndesVPackFPH())
216 for (
MVT VT : F16VecVTs)
217 addRegClassForRVV(VT);
219 if (Subtarget.hasVInstructionsBF16Minimal() ||
220 Subtarget.hasVendorXAndesVBFHCvt())
221 for (
MVT VT : BF16VecVTs)
222 addRegClassForRVV(VT);
224 if (Subtarget.hasVInstructionsF32())
225 for (
MVT VT : F32VecVTs)
226 addRegClassForRVV(VT);
228 if (Subtarget.hasVInstructionsF64())
229 for (
MVT VT : F64VecVTs)
230 addRegClassForRVV(VT);
232 if (Subtarget.useRVVForFixedLengthVectors()) {
233 auto addRegClassForFixedVectors = [
this](
MVT VT) {
240 if (useRVVForFixedLengthVectorVT(VT))
241 addRegClassForFixedVectors(VT);
244 if (useRVVForFixedLengthVectorVT(VT))
245 addRegClassForFixedVectors(VT);
305 if (!(Subtarget.hasVendorXCValu() && !Subtarget.is64Bit())) {
315 if (!Subtarget.hasVendorXTHeadBb() && !Subtarget.hasVendorXqcibm() &&
316 !Subtarget.hasVendorXAndesPerf())
321 if (!Subtarget.hasStdExtZbb() && !Subtarget.hasStdExtP() &&
322 !Subtarget.hasVendorXTHeadBb() && !Subtarget.hasVendorXqcibm() &&
323 !Subtarget.hasVendorXAndesPerf() &&
324 !(Subtarget.hasVendorXCValu() && !Subtarget.is64Bit()))
327 if (Subtarget.hasStdExtZilsd() && !Subtarget.is64Bit()) {
332 if (Subtarget.is64Bit()) {
339 if (!Subtarget.hasStdExtZbb())
345 if (!Subtarget.hasStdExtZmmul()) {
347 }
else if (Subtarget.is64Bit()) {
354 if (!Subtarget.hasStdExtM()) {
357 }
else if (Subtarget.is64Bit()) {
359 {MVT::i8, MVT::i16, MVT::i32},
Custom);
369 if (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) {
370 if (Subtarget.is64Bit())
372 }
else if (Subtarget.hasVendorXTHeadBb()) {
373 if (Subtarget.is64Bit())
376 }
else if (Subtarget.hasVendorXCVbitmanip() && !Subtarget.is64Bit()) {
385 if ((Subtarget.hasVendorXCVbitmanip() || Subtarget.hasVendorXqcibm()) &&
386 !Subtarget.is64Bit()) {
392 if (Subtarget.hasStdExtZbkb())
396 if (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtP() ||
397 (Subtarget.hasVendorXCValu() && !Subtarget.is64Bit())) {
402 if (Subtarget.hasCTZLike()) {
403 if (Subtarget.is64Bit())
408 if (Subtarget.hasStdExtP() && Subtarget.is64Bit())
412 if (!Subtarget.hasCPOPLike()) {
415 if (Subtarget.is64Bit())
422 if (Subtarget.hasCLZLike()) {
426 if (Subtarget.is64Bit() &&
427 (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtP()))
433 if (Subtarget.hasStdExtP() ||
434 (Subtarget.hasVendorXCValu() && !Subtarget.is64Bit())) {
436 if (Subtarget.is64Bit())
438 }
else if (Subtarget.hasShortForwardBranchOpt()) {
441 }
else if (Subtarget.is64Bit()) {
445 if (!Subtarget.useMIPSCCMovInsn() && !Subtarget.hasVendorXTHeadCondMov())
448 if (Subtarget.hasVendorXqcia() && !Subtarget.is64Bit()) {
457 static const unsigned FPLegalNodeTypes[] = {
458 ISD::FMINNUM, ISD::FMAXNUM, ISD::FMINIMUMNUM,
459 ISD::FMAXIMUMNUM, ISD::LRINT, ISD::LLRINT,
471 static const unsigned FPOpToExpand[] = {
472 ISD::FSIN, ISD::FCOS, ISD::FSINCOS, ISD::FPOW,
475 static const unsigned FPRndMode[] = {
476 ISD::FCEIL, ISD::FFLOOR, ISD::FTRUNC, ISD::FRINT, ISD::FROUND,
479 static const unsigned ZfhminZfbfminPromoteOps[] = {
480 ISD::FMINNUM, ISD::FMAXNUM, ISD::FMAXIMUMNUM,
487 ISD::FTRUNC, ISD::FRINT, ISD::FROUND,
490 if (Subtarget.hasStdExtZfbfmin()) {
505 if (Subtarget.hasStdExtZfhminOrZhinxmin()) {
506 if (Subtarget.hasStdExtZfhOrZhinx()) {
513 if (Subtarget.hasStdExtZfa())
518 for (
auto Op : {ISD::LROUND, ISD::LLROUND, ISD::LRINT, ISD::LLRINT,
539 ISD::FNEARBYINT, MVT::f16,
540 Subtarget.hasStdExtZfh() && Subtarget.hasStdExtZfa() ?
Legal :
Promote);
542 ISD::FCOS, ISD::FSIN, ISD::FSINCOS, ISD::FEXP,
543 ISD::FEXP2, ISD::FEXP10, ISD::FLOG, ISD::FLOG2,
544 ISD::FLOG10, ISD::FLDEXP, ISD::FFREXP, ISD::FMODF},
556 if (Subtarget.is64Bit())
560 if (Subtarget.hasStdExtFOrZfinx()) {
582 if (Subtarget.hasStdExtZfa()) {
591 if (Subtarget.hasStdExtFOrZfinx() && Subtarget.is64Bit())
594 if (Subtarget.hasStdExtDOrZdinx()) {
597 if (!Subtarget.is64Bit())
600 if (Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
601 !Subtarget.is64Bit()) {
606 if (Subtarget.hasStdExtZfa()) {
612 if (Subtarget.is64Bit())
641 if (Subtarget.is64Bit()) {
648 if (Subtarget.hasStdExtFOrZfinx()) {
674 if (Subtarget.is64Bit())
684 if (Subtarget.is64Bit()) {
691 if (Subtarget.is64Bit())
694 if (Subtarget.hasVendorXMIPSCBOP())
696 else if (Subtarget.hasStdExtZicbop())
699 if (Subtarget.hasStdExtZalrsc()) {
701 if (Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas())
705 }
else if (Subtarget.hasForcedAtomics()) {
720 if (Subtarget.hasVInstructions()) {
729 {MVT::i8, MVT::i16},
Custom);
730 if (Subtarget.is64Bit())
740 static const unsigned IntegerVPOps[] = {
741 ISD::VP_ADD, ISD::VP_SUB, ISD::VP_MUL,
742 ISD::VP_SDIV, ISD::VP_UDIV, ISD::VP_SREM,
743 ISD::VP_UREM, ISD::VP_AND, ISD::VP_OR,
744 ISD::VP_XOR, ISD::VP_SRA, ISD::VP_SRL,
745 ISD::VP_SHL, ISD::VP_REDUCE_ADD, ISD::VP_REDUCE_AND,
746 ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR, ISD::VP_REDUCE_SMAX,
747 ISD::VP_REDUCE_SMIN, ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN,
748 ISD::VP_MERGE, ISD::VP_SELECT, ISD::VP_FP_TO_SINT,
749 ISD::VP_FP_TO_UINT, ISD::VP_SETCC, ISD::VP_SIGN_EXTEND,
750 ISD::VP_ZERO_EXTEND, ISD::VP_TRUNCATE, ISD::VP_SMIN,
751 ISD::VP_SMAX, ISD::VP_UMIN, ISD::VP_UMAX,
752 ISD::VP_ABS, ISD::EXPERIMENTAL_VP_REVERSE, ISD::EXPERIMENTAL_VP_SPLICE,
753 ISD::VP_SADDSAT, ISD::VP_UADDSAT, ISD::VP_SSUBSAT,
754 ISD::VP_USUBSAT, ISD::VP_CTTZ_ELTS, ISD::VP_CTTZ_ELTS_ZERO_UNDEF,
755 ISD::EXPERIMENTAL_VP_SPLAT};
757 static const unsigned FloatingPointVPOps[] = {
758 ISD::VP_FADD, ISD::VP_FSUB, ISD::VP_FMUL,
759 ISD::VP_FDIV, ISD::VP_FNEG, ISD::VP_FABS,
760 ISD::VP_FMA, ISD::VP_REDUCE_FADD, ISD::VP_REDUCE_SEQ_FADD,
761 ISD::VP_REDUCE_FMIN, ISD::VP_REDUCE_FMAX, ISD::VP_MERGE,
762 ISD::VP_SELECT, ISD::VP_SINT_TO_FP, ISD::VP_UINT_TO_FP,
763 ISD::VP_SETCC, ISD::VP_FP_ROUND, ISD::VP_FP_EXTEND,
764 ISD::VP_SQRT, ISD::VP_FMINNUM, ISD::VP_FMAXNUM,
765 ISD::VP_FCEIL, ISD::VP_FFLOOR, ISD::VP_FROUND,
766 ISD::VP_FROUNDEVEN, ISD::VP_FCOPYSIGN, ISD::VP_FROUNDTOZERO,
767 ISD::VP_FRINT, ISD::VP_FNEARBYINT, ISD::VP_IS_FPCLASS,
768 ISD::VP_FMINIMUM, ISD::VP_FMAXIMUM, ISD::VP_LRINT,
769 ISD::VP_LLRINT, ISD::VP_REDUCE_FMINIMUM,
770 ISD::VP_REDUCE_FMAXIMUM, ISD::EXPERIMENTAL_VP_SPLAT};
772 static const unsigned IntegerVecReduceOps[] = {
773 ISD::VECREDUCE_ADD, ISD::VECREDUCE_AND, ISD::VECREDUCE_OR,
774 ISD::VECREDUCE_XOR, ISD::VECREDUCE_SMAX, ISD::VECREDUCE_SMIN,
775 ISD::VECREDUCE_UMAX, ISD::VECREDUCE_UMIN};
777 static const unsigned FloatingPointVecReduceOps[] = {
778 ISD::VECREDUCE_FADD, ISD::VECREDUCE_SEQ_FADD, ISD::VECREDUCE_FMIN,
779 ISD::VECREDUCE_FMAX, ISD::VECREDUCE_FMINIMUM, ISD::VECREDUCE_FMAXIMUM};
781 static const unsigned FloatingPointLibCallOps[] = {
782 ISD::FREM, ISD::FPOW, ISD::FCOS, ISD::FSIN, ISD::FSINCOS, ISD::FEXP,
783 ISD::FEXP2, ISD::FEXP10, ISD::FLOG, ISD::FLOG2, ISD::FLOG10};
785 if (!Subtarget.is64Bit()) {
794 ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR,
795 ISD::VP_REDUCE_SMAX, ISD::VP_REDUCE_SMIN,
796 ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN},
800 for (
MVT VT : BoolVecVTs) {
826 {ISD::VECREDUCE_AND, ISD::VECREDUCE_OR, ISD::VECREDUCE_XOR}, VT,
830 {ISD::VP_REDUCE_AND, ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR}, VT,
854 ISD::VP_TRUNCATE, ISD::VP_SETCC},
871 for (
MVT VT : IntVecVTs) {
882 if (VT.getVectorElementType() == MVT::i64 && !Subtarget.hasStdExtV())
932 {ISD::VP_LOAD, ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
933 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER, ISD::VP_SCATTER},
958 if (Subtarget.hasStdExtZvkb()) {
966 if (Subtarget.hasStdExtZvbb()) {
970 ISD::VP_CTTZ_ZERO_UNDEF, ISD::VP_CTPOP},
976 ISD::VP_CTTZ_ZERO_UNDEF, ISD::VP_CTPOP},
985 ISD::VP_CTLZ_ZERO_UNDEF, ISD::VP_CTTZ_ZERO_UNDEF},
993 for (
MVT VT : VecTupleVTs) {
1014 static const unsigned ZvfhminZvfbfminPromoteOps[] = {
1042 ISD::VECREDUCE_FMIN,
1043 ISD::VECREDUCE_FMAX,
1044 ISD::VECREDUCE_FMINIMUM,
1045 ISD::VECREDUCE_FMAXIMUM};
1048 static const unsigned ZvfhminZvfbfminPromoteVPOps[] = {
1054 ISD::VP_REDUCE_FMIN,
1055 ISD::VP_REDUCE_FMAX,
1063 ISD::VP_FROUNDTOZERO,
1069 ISD::VP_REDUCE_FMINIMUM,
1070 ISD::VP_REDUCE_FMAXIMUM};
1073 const auto SetCommonVFPActions = [&](
MVT VT) {
1089 {ISD::FMINNUM, ISD::FMAXNUM, ISD::FMAXIMUMNUM, ISD::FMINIMUMNUM}, VT,
1094 ISD::FROUNDEVEN, ISD::FRINT, ISD::FNEARBYINT,
1111 {ISD::VP_LOAD, ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1112 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER, ISD::VP_SCATTER},
1148 const auto SetCommonVFPExtLoadTruncStoreActions =
1150 for (
auto SmallVT : SmallerVTs) {
1158 const auto SetCommonPromoteToF32Actions = [&](
MVT VT) {
1186 ISD::MGATHER, ISD::MSCATTER, ISD::VP_LOAD,
1187 ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1188 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1211 if (Subtarget.hasVInstructionsF16()) {
1212 for (
MVT VT : F16VecVTs) {
1215 SetCommonVFPActions(VT);
1217 }
else if (Subtarget.hasVInstructionsF16Minimal()) {
1218 for (
MVT VT : F16VecVTs) {
1221 SetCommonPromoteToF32Actions(VT);
1225 if (Subtarget.hasVInstructionsBF16Minimal()) {
1226 for (
MVT VT : BF16VecVTs) {
1229 SetCommonPromoteToF32Actions(VT);
1233 if (Subtarget.hasVInstructionsF32()) {
1234 for (
MVT VT : F32VecVTs) {
1237 SetCommonVFPActions(VT);
1238 SetCommonVFPExtLoadTruncStoreActions(VT, F16VecVTs);
1239 SetCommonVFPExtLoadTruncStoreActions(VT, BF16VecVTs);
1243 if (Subtarget.hasVInstructionsF64()) {
1244 for (
MVT VT : F64VecVTs) {
1247 SetCommonVFPActions(VT);
1248 SetCommonVFPExtLoadTruncStoreActions(VT, F16VecVTs);
1249 SetCommonVFPExtLoadTruncStoreActions(VT, BF16VecVTs);
1250 SetCommonVFPExtLoadTruncStoreActions(VT, F32VecVTs);
1254 if (Subtarget.useRVVForFixedLengthVectors()) {
1256 if (!useRVVForFixedLengthVectorVT(VT))
1301 {ISD::VECREDUCE_AND, ISD::VECREDUCE_OR, ISD::VECREDUCE_XOR}, VT,
1305 {ISD::VP_REDUCE_AND, ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR}, VT,
1332 ISD::VP_SETCC, ISD::VP_TRUNCATE},
1356 {ISD::MLOAD, ISD::MSTORE, ISD::MGATHER, ISD::MSCATTER}, VT,
Custom);
1359 ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1360 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1392 ISD::VECREDUCE_SMIN, ISD::VECREDUCE_UMAX,
1393 ISD::VECREDUCE_UMIN},
1398 if (Subtarget.hasStdExtZvkb())
1401 if (Subtarget.hasStdExtZvbb()) {
1425 if (!useRVVForFixedLengthVectorVT(VT))
1448 ISD::MGATHER, ISD::MSCATTER},
1451 ISD::VP_SCATTER, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1452 ISD::EXPERIMENTAL_VP_STRIDED_STORE},
1461 !Subtarget.hasVInstructionsF16()) {
1471 if (Subtarget.hasStdExtZfhmin()) {
1497 if (Subtarget.hasStdExtZfbfmin()) {
1523 ISD::FMA, ISD::FMINNUM, ISD::FMAXNUM,
1525 ISD::FMAXIMUM, ISD::FMINIMUM},
1529 ISD::FROUNDEVEN, ISD::FRINT, ISD::LRINT,
1530 ISD::LLRINT, ISD::LROUND, ISD::LLROUND,
1556 if (Subtarget.is64Bit())
1558 if (Subtarget.hasStdExtZfhminOrZhinxmin())
1560 if (Subtarget.hasStdExtZfbfmin())
1562 if (Subtarget.hasStdExtFOrZfinx())
1564 if (Subtarget.hasStdExtDOrZdinx())
1569 if (Subtarget.hasStdExtZaamo())
1572 if (Subtarget.hasForcedAtomics()) {
1575 {ISD::ATOMIC_CMP_SWAP, ISD::ATOMIC_SWAP, ISD::ATOMIC_LOAD_ADD,
1576 ISD::ATOMIC_LOAD_SUB, ISD::ATOMIC_LOAD_AND, ISD::ATOMIC_LOAD_OR,
1577 ISD::ATOMIC_LOAD_XOR, ISD::ATOMIC_LOAD_NAND, ISD::ATOMIC_LOAD_MIN,
1578 ISD::ATOMIC_LOAD_MAX, ISD::ATOMIC_LOAD_UMIN, ISD::ATOMIC_LOAD_UMAX},
1582 if (Subtarget.hasVendorXTHeadMemIdx()) {
1591 if (Subtarget.is64Bit()) {
1598 if (Subtarget.hasVendorXCVmem() && !Subtarget.is64Bit()) {
1609 if (Subtarget.hasStdExtZvqdotq() && Subtarget.getELen() >= 64) {
1610 static const unsigned MLAOps[] = {ISD::PARTIAL_REDUCE_SMLA,
1611 ISD::PARTIAL_REDUCE_UMLA,
1612 ISD::PARTIAL_REDUCE_SUMLA};
1619 if (Subtarget.useRVVForFixedLengthVectors()) {
1621 if (VT.getVectorElementType() != MVT::i32 ||
1622 !useRVVForFixedLengthVectorVT(VT))
1632 if (Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh()) {
1638 const Align FunctionAlignment(Subtarget.hasStdExtZca() ? 2 : 4);
1650 if (Subtarget.hasStdExtFOrZfinx())
1653 if (Subtarget.hasStdExtZbb())
1656 if ((Subtarget.hasStdExtZbs() && Subtarget.is64Bit()) ||
1657 Subtarget.hasVInstructions())
1660 if (Subtarget.hasStdExtZbkb())
1663 if (Subtarget.hasStdExtFOrZfinx())
1666 if (Subtarget.hasVInstructions())
1669 ISD::VP_GATHER, ISD::VP_SCATTER,
ISD::SRA,
1672 ISD::VP_STORE, ISD::VP_TRUNCATE, ISD::EXPERIMENTAL_VP_REVERSE,
1678 if (Subtarget.hasVendorXTHeadMemPair())
1680 if (Subtarget.useRVVForFixedLengthVectors())
1702 Subtarget.getMaxStoresPerMemmove(
true);
1714 if (Subtarget.hasVInstructions() &&
1725bool RISCVTargetLowering::shouldExpandGetVectorLength(
EVT TripCountVT,
1727 bool IsScalable)
const {
1734 if (TripCountVT != MVT::i32 && TripCountVT != Subtarget.
getXLenVT())
1752 return !Subtarget.hasVInstructions() ||
1760 auto &
DL =
I.getDataLayout();
1762 auto SetRVVLoadStoreInfo = [&](
unsigned PtrOp,
bool IsStore,
1763 bool IsUnitStrided,
bool UsePtrVal =
false) {
1768 Info.ptrVal =
I.getArgOperand(PtrOp);
1770 Info.fallbackAddressSpace =
1771 I.getArgOperand(PtrOp)->getType()->getPointerAddressSpace();
1775 MemTy =
I.getArgOperand(0)->getType();
1778 MemTy =
I.getType();
1793 Info.align =
DL.getABITypeAlign(MemTy);
1803 if (
I.hasMetadata(LLVMContext::MD_nontemporal))
1810 case Intrinsic::riscv_masked_atomicrmw_xchg:
1811 case Intrinsic::riscv_masked_atomicrmw_add:
1812 case Intrinsic::riscv_masked_atomicrmw_sub:
1813 case Intrinsic::riscv_masked_atomicrmw_nand:
1814 case Intrinsic::riscv_masked_atomicrmw_max:
1815 case Intrinsic::riscv_masked_atomicrmw_min:
1816 case Intrinsic::riscv_masked_atomicrmw_umax:
1817 case Intrinsic::riscv_masked_atomicrmw_umin:
1818 case Intrinsic::riscv_masked_cmpxchg:
1825 Info.memVT = MVT::i32;
1826 Info.ptrVal =
I.getArgOperand(0);
1828 Info.align =
Align(4);
1832 case Intrinsic::riscv_seg2_load_mask:
1833 case Intrinsic::riscv_seg3_load_mask:
1834 case Intrinsic::riscv_seg4_load_mask:
1835 case Intrinsic::riscv_seg5_load_mask:
1836 case Intrinsic::riscv_seg6_load_mask:
1837 case Intrinsic::riscv_seg7_load_mask:
1838 case Intrinsic::riscv_seg8_load_mask:
1839 case Intrinsic::riscv_sseg2_load_mask:
1840 case Intrinsic::riscv_sseg3_load_mask:
1841 case Intrinsic::riscv_sseg4_load_mask:
1842 case Intrinsic::riscv_sseg5_load_mask:
1843 case Intrinsic::riscv_sseg6_load_mask:
1844 case Intrinsic::riscv_sseg7_load_mask:
1845 case Intrinsic::riscv_sseg8_load_mask:
1846 return SetRVVLoadStoreInfo( 0,
false,
1848 case Intrinsic::riscv_seg2_store_mask:
1849 case Intrinsic::riscv_seg3_store_mask:
1850 case Intrinsic::riscv_seg4_store_mask:
1851 case Intrinsic::riscv_seg5_store_mask:
1852 case Intrinsic::riscv_seg6_store_mask:
1853 case Intrinsic::riscv_seg7_store_mask:
1854 case Intrinsic::riscv_seg8_store_mask:
1856 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1859 case Intrinsic::riscv_sseg2_store_mask:
1860 case Intrinsic::riscv_sseg3_store_mask:
1861 case Intrinsic::riscv_sseg4_store_mask:
1862 case Intrinsic::riscv_sseg5_store_mask:
1863 case Intrinsic::riscv_sseg6_store_mask:
1864 case Intrinsic::riscv_sseg7_store_mask:
1865 case Intrinsic::riscv_sseg8_store_mask:
1867 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
1870 case Intrinsic::riscv_vlm:
1871 return SetRVVLoadStoreInfo( 0,
1875 case Intrinsic::riscv_vle:
1876 case Intrinsic::riscv_vle_mask:
1877 case Intrinsic::riscv_vleff:
1878 case Intrinsic::riscv_vleff_mask:
1879 return SetRVVLoadStoreInfo( 1,
1883 case Intrinsic::riscv_vsm:
1884 case Intrinsic::riscv_vse:
1885 case Intrinsic::riscv_vse_mask:
1886 return SetRVVLoadStoreInfo( 1,
1890 case Intrinsic::riscv_vlse:
1891 case Intrinsic::riscv_vlse_mask:
1892 case Intrinsic::riscv_vloxei:
1893 case Intrinsic::riscv_vloxei_mask:
1894 case Intrinsic::riscv_vluxei:
1895 case Intrinsic::riscv_vluxei_mask:
1896 return SetRVVLoadStoreInfo( 1,
1899 case Intrinsic::riscv_vsse:
1900 case Intrinsic::riscv_vsse_mask:
1901 case Intrinsic::riscv_vsoxei:
1902 case Intrinsic::riscv_vsoxei_mask:
1903 case Intrinsic::riscv_vsuxei:
1904 case Intrinsic::riscv_vsuxei_mask:
1905 return SetRVVLoadStoreInfo( 1,
1908 case Intrinsic::riscv_vlseg2:
1909 case Intrinsic::riscv_vlseg3:
1910 case Intrinsic::riscv_vlseg4:
1911 case Intrinsic::riscv_vlseg5:
1912 case Intrinsic::riscv_vlseg6:
1913 case Intrinsic::riscv_vlseg7:
1914 case Intrinsic::riscv_vlseg8:
1915 case Intrinsic::riscv_vlseg2ff:
1916 case Intrinsic::riscv_vlseg3ff:
1917 case Intrinsic::riscv_vlseg4ff:
1918 case Intrinsic::riscv_vlseg5ff:
1919 case Intrinsic::riscv_vlseg6ff:
1920 case Intrinsic::riscv_vlseg7ff:
1921 case Intrinsic::riscv_vlseg8ff:
1922 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1925 case Intrinsic::riscv_vlseg2_mask:
1926 case Intrinsic::riscv_vlseg3_mask:
1927 case Intrinsic::riscv_vlseg4_mask:
1928 case Intrinsic::riscv_vlseg5_mask:
1929 case Intrinsic::riscv_vlseg6_mask:
1930 case Intrinsic::riscv_vlseg7_mask:
1931 case Intrinsic::riscv_vlseg8_mask:
1932 case Intrinsic::riscv_vlseg2ff_mask:
1933 case Intrinsic::riscv_vlseg3ff_mask:
1934 case Intrinsic::riscv_vlseg4ff_mask:
1935 case Intrinsic::riscv_vlseg5ff_mask:
1936 case Intrinsic::riscv_vlseg6ff_mask:
1937 case Intrinsic::riscv_vlseg7ff_mask:
1938 case Intrinsic::riscv_vlseg8ff_mask:
1939 return SetRVVLoadStoreInfo(
I.arg_size() - 5,
1942 case Intrinsic::riscv_vlsseg2:
1943 case Intrinsic::riscv_vlsseg3:
1944 case Intrinsic::riscv_vlsseg4:
1945 case Intrinsic::riscv_vlsseg5:
1946 case Intrinsic::riscv_vlsseg6:
1947 case Intrinsic::riscv_vlsseg7:
1948 case Intrinsic::riscv_vlsseg8:
1949 case Intrinsic::riscv_vloxseg2:
1950 case Intrinsic::riscv_vloxseg3:
1951 case Intrinsic::riscv_vloxseg4:
1952 case Intrinsic::riscv_vloxseg5:
1953 case Intrinsic::riscv_vloxseg6:
1954 case Intrinsic::riscv_vloxseg7:
1955 case Intrinsic::riscv_vloxseg8:
1956 case Intrinsic::riscv_vluxseg2:
1957 case Intrinsic::riscv_vluxseg3:
1958 case Intrinsic::riscv_vluxseg4:
1959 case Intrinsic::riscv_vluxseg5:
1960 case Intrinsic::riscv_vluxseg6:
1961 case Intrinsic::riscv_vluxseg7:
1962 case Intrinsic::riscv_vluxseg8:
1963 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
1966 case Intrinsic::riscv_vlsseg2_mask:
1967 case Intrinsic::riscv_vlsseg3_mask:
1968 case Intrinsic::riscv_vlsseg4_mask:
1969 case Intrinsic::riscv_vlsseg5_mask:
1970 case Intrinsic::riscv_vlsseg6_mask:
1971 case Intrinsic::riscv_vlsseg7_mask:
1972 case Intrinsic::riscv_vlsseg8_mask:
1973 case Intrinsic::riscv_vloxseg2_mask:
1974 case Intrinsic::riscv_vloxseg3_mask:
1975 case Intrinsic::riscv_vloxseg4_mask:
1976 case Intrinsic::riscv_vloxseg5_mask:
1977 case Intrinsic::riscv_vloxseg6_mask:
1978 case Intrinsic::riscv_vloxseg7_mask:
1979 case Intrinsic::riscv_vloxseg8_mask:
1980 case Intrinsic::riscv_vluxseg2_mask:
1981 case Intrinsic::riscv_vluxseg3_mask:
1982 case Intrinsic::riscv_vluxseg4_mask:
1983 case Intrinsic::riscv_vluxseg5_mask:
1984 case Intrinsic::riscv_vluxseg6_mask:
1985 case Intrinsic::riscv_vluxseg7_mask:
1986 case Intrinsic::riscv_vluxseg8_mask:
1987 return SetRVVLoadStoreInfo(
I.arg_size() - 6,
1990 case Intrinsic::riscv_vsseg2:
1991 case Intrinsic::riscv_vsseg3:
1992 case Intrinsic::riscv_vsseg4:
1993 case Intrinsic::riscv_vsseg5:
1994 case Intrinsic::riscv_vsseg6:
1995 case Intrinsic::riscv_vsseg7:
1996 case Intrinsic::riscv_vsseg8:
1997 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
2000 case Intrinsic::riscv_vsseg2_mask:
2001 case Intrinsic::riscv_vsseg3_mask:
2002 case Intrinsic::riscv_vsseg4_mask:
2003 case Intrinsic::riscv_vsseg5_mask:
2004 case Intrinsic::riscv_vsseg6_mask:
2005 case Intrinsic::riscv_vsseg7_mask:
2006 case Intrinsic::riscv_vsseg8_mask:
2007 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
2010 case Intrinsic::riscv_vssseg2:
2011 case Intrinsic::riscv_vssseg3:
2012 case Intrinsic::riscv_vssseg4:
2013 case Intrinsic::riscv_vssseg5:
2014 case Intrinsic::riscv_vssseg6:
2015 case Intrinsic::riscv_vssseg7:
2016 case Intrinsic::riscv_vssseg8:
2017 case Intrinsic::riscv_vsoxseg2:
2018 case Intrinsic::riscv_vsoxseg3:
2019 case Intrinsic::riscv_vsoxseg4:
2020 case Intrinsic::riscv_vsoxseg5:
2021 case Intrinsic::riscv_vsoxseg6:
2022 case Intrinsic::riscv_vsoxseg7:
2023 case Intrinsic::riscv_vsoxseg8:
2024 case Intrinsic::riscv_vsuxseg2:
2025 case Intrinsic::riscv_vsuxseg3:
2026 case Intrinsic::riscv_vsuxseg4:
2027 case Intrinsic::riscv_vsuxseg5:
2028 case Intrinsic::riscv_vsuxseg6:
2029 case Intrinsic::riscv_vsuxseg7:
2030 case Intrinsic::riscv_vsuxseg8:
2031 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
2034 case Intrinsic::riscv_vssseg2_mask:
2035 case Intrinsic::riscv_vssseg3_mask:
2036 case Intrinsic::riscv_vssseg4_mask:
2037 case Intrinsic::riscv_vssseg5_mask:
2038 case Intrinsic::riscv_vssseg6_mask:
2039 case Intrinsic::riscv_vssseg7_mask:
2040 case Intrinsic::riscv_vssseg8_mask:
2041 case Intrinsic::riscv_vsoxseg2_mask:
2042 case Intrinsic::riscv_vsoxseg3_mask:
2043 case Intrinsic::riscv_vsoxseg4_mask:
2044 case Intrinsic::riscv_vsoxseg5_mask:
2045 case Intrinsic::riscv_vsoxseg6_mask:
2046 case Intrinsic::riscv_vsoxseg7_mask:
2047 case Intrinsic::riscv_vsoxseg8_mask:
2048 case Intrinsic::riscv_vsuxseg2_mask:
2049 case Intrinsic::riscv_vsuxseg3_mask:
2050 case Intrinsic::riscv_vsuxseg4_mask:
2051 case Intrinsic::riscv_vsuxseg5_mask:
2052 case Intrinsic::riscv_vsuxseg6_mask:
2053 case Intrinsic::riscv_vsuxseg7_mask:
2054 case Intrinsic::riscv_vsuxseg8_mask:
2055 return SetRVVLoadStoreInfo(
I.arg_size() - 5,
2109 if (Subtarget.is64Bit() || !SrcTy->isIntegerTy() || !DstTy->
isIntegerTy())
2111 unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
2113 return (SrcBits == 64 && DestBits == 32);
2124 return (SrcBits == 64 && DestBits == 32);
2130 if (Subtarget.hasVInstructions() &&
2135 if (SrcBits == DestBits * 2) {
2147 EVT MemVT = LD->getMemoryVT();
2148 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
2158 return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
2166 return Subtarget.hasCTZLike();
2170 return Subtarget.hasCLZLike();
2181 if (!Subtarget.hasBEXTILike())
2186 return !Mask->getValue().isSignedIntN(12) && Mask->getValue().isPowerOf2();
2190 EVT VT =
Y.getValueType();
2195 return (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
2200 EVT VT =
Y.getValueType();
2205 return Subtarget.hasStdExtZvkb();
2210 if (Subtarget.hasStdExtZbs())
2211 return X.getValueType().isScalarInteger();
2214 if (Subtarget.hasVendorXTHeadBs())
2215 return C !=
nullptr;
2217 return C &&
C->getAPIntValue().ule(10);
2221 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
2227 if (!VT.
isVector() || !Subtarget.hasVInstructions())
2238 assert(Ty->isIntegerTy());
2240 unsigned BitSize = Ty->getIntegerBitWidth();
2241 if (BitSize > Subtarget.getXLen())
2245 int64_t Val = Imm.getSExtValue();
2253 if (!Subtarget.enableUnalignedScalarMem())
2263 return Seq.
size() <= Subtarget.getMaxBuildIntsCost();
2269 unsigned OldShiftOpcode,
unsigned NewShiftOpcode,
2276 if (XC && OldShiftOpcode ==
ISD::SRL && XC->isOne())
2324 if (!Subtarget.hasStdExtZfa())
2327 bool IsSupportedVT =
false;
2328 if (VT == MVT::f16) {
2329 IsSupportedVT = Subtarget.hasStdExtZfh() || Subtarget.hasStdExtZvfh();
2330 }
else if (VT == MVT::f32) {
2331 IsSupportedVT =
true;
2332 }
else if (VT == MVT::f64) {
2333 assert(Subtarget.hasStdExtD() &&
"Expect D extension");
2334 IsSupportedVT =
true;
2344 bool ForCodeSize)
const {
2345 bool IsLegalVT =
false;
2347 IsLegalVT = Subtarget.hasStdExtZfhminOrZhinxmin();
2348 else if (VT == MVT::f32)
2349 IsLegalVT = Subtarget.hasStdExtFOrZfinx();
2350 else if (VT == MVT::f64)
2351 IsLegalVT = Subtarget.hasStdExtDOrZdinx();
2352 else if (VT == MVT::bf16)
2353 IsLegalVT = Subtarget.hasStdExtZfbfmin();
2369 return Imm.isZero();
2373 if (Imm.isNegZero())
2378 const int FmvCost = Subtarget.hasStdExtZfinx() ? 0 : 1;
2381 Subtarget.getXLen(), Subtarget);
2387 unsigned Index)
const {
2404 if (EltVT == MVT::i1)
2410 unsigned MinVLen = Subtarget.getRealMinVLen();
2417 if (Index + ResElts <= MinVLMAX && Index < 31)
2426 return (ResElts * 2) == SrcElts && (Index == 0 || Index == ResElts);
2434 if (VT == MVT::f16 && Subtarget.hasStdExtFOrZfinx() &&
2435 !Subtarget.hasStdExtZfhminOrZhinxmin())
2445 std::optional<MVT> RegisterVT)
const {
2447 if (VT == (Subtarget.is64Bit() ? MVT::i128 : MVT::i64) && RegisterVT &&
2448 *RegisterVT == MVT::Untyped)
2459 if (VT == MVT::f16 && Subtarget.hasStdExtFOrZfinx() &&
2460 !Subtarget.hasStdExtZfhminOrZhinxmin())
2468 unsigned &NumIntermediates,
MVT &RegisterVT)
const {
2470 Context, CC, VT, IntermediateVT, NumIntermediates, RegisterVT);
2488 !Subtarget.hasVendorXAndesPerf()) {
2494 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
2508 int64_t
C = RHSC->getSExtValue();
2518 if ((Subtarget.hasVendorXqcicm() || Subtarget.hasVendorXqcicli()) &&
2544 if ((Subtarget.hasVendorXqcicm() || Subtarget.hasVendorXqcicli()) &&
2579 if (VT.
SimpleTy >= MVT::riscv_nxv1i8x2 &&
2580 VT.
SimpleTy <= MVT::riscv_nxv1i8x8)
2582 if (VT.
SimpleTy >= MVT::riscv_nxv2i8x2 &&
2583 VT.
SimpleTy <= MVT::riscv_nxv2i8x8)
2585 if (VT.
SimpleTy >= MVT::riscv_nxv4i8x2 &&
2586 VT.
SimpleTy <= MVT::riscv_nxv4i8x8)
2588 if (VT.
SimpleTy >= MVT::riscv_nxv8i8x2 &&
2589 VT.
SimpleTy <= MVT::riscv_nxv8i8x8)
2591 if (VT.
SimpleTy >= MVT::riscv_nxv16i8x2 &&
2592 VT.
SimpleTy <= MVT::riscv_nxv16i8x4)
2594 if (VT.
SimpleTy == MVT::riscv_nxv32i8x2)
2604 switch (KnownSize) {
2632 return RISCV::VRRegClassID;
2634 return RISCV::VRM2RegClassID;
2636 return RISCV::VRM4RegClassID;
2638 return RISCV::VRM8RegClassID;
2646 static_assert(RISCV::sub_vrm1_7 == RISCV::sub_vrm1_0 + 7,
2647 "Unexpected subreg numbering");
2648 return RISCV::sub_vrm1_0 + Index;
2651 static_assert(RISCV::sub_vrm2_3 == RISCV::sub_vrm2_0 + 3,
2652 "Unexpected subreg numbering");
2653 return RISCV::sub_vrm2_0 + Index;
2656 static_assert(RISCV::sub_vrm4_1 == RISCV::sub_vrm4_0 + 1,
2657 "Unexpected subreg numbering");
2658 return RISCV::sub_vrm4_0 + Index;
2666 unsigned RegsPerField =
2669 switch (RegsPerField) {
2672 return RISCV::VRN2M1RegClassID;
2674 return RISCV::VRN3M1RegClassID;
2676 return RISCV::VRN4M1RegClassID;
2678 return RISCV::VRN5M1RegClassID;
2680 return RISCV::VRN6M1RegClassID;
2682 return RISCV::VRN7M1RegClassID;
2684 return RISCV::VRN8M1RegClassID;
2688 return RISCV::VRN2M2RegClassID;
2690 return RISCV::VRN3M2RegClassID;
2692 return RISCV::VRN4M2RegClassID;
2696 return RISCV::VRN2M4RegClassID;
2704 return RISCV::VRRegClassID;
2713std::pair<unsigned, unsigned>
2715 MVT VecVT,
MVT SubVecVT,
unsigned InsertExtractIdx,
2717 static_assert((RISCV::VRM8RegClassID > RISCV::VRM4RegClassID &&
2718 RISCV::VRM4RegClassID > RISCV::VRM2RegClassID &&
2719 RISCV::VRM2RegClassID > RISCV::VRRegClassID),
2720 "Register classes not ordered");
2727 if (VecRegClassID == SubRegClassID)
2728 return {RISCV::NoSubRegister, 0};
2731 "Only allow scalable vector subvector.");
2733 "Invalid vector tuple insert/extract for vector and subvector with "
2744 unsigned SubRegIdx = RISCV::NoSubRegister;
2745 for (
const unsigned RCID :
2746 {RISCV::VRM4RegClassID, RISCV::VRM2RegClassID, RISCV::VRRegClassID})
2747 if (VecRegClassID > RCID && SubRegClassID <= RCID) {
2751 SubRegIdx =
TRI->composeSubRegIndices(SubRegIdx,
2756 return {SubRegIdx, InsertExtractIdx};
2761bool RISCVTargetLowering::mergeStoresAfterLegalization(
EVT VT)
const {
2771 return Subtarget.is64Bit() ? Subtarget.hasVInstructionsI64() :
true;
2775 return Subtarget.hasVInstructions();
2777 return Subtarget.hasVInstructionsI64();
2779 return Subtarget.hasVInstructionsF16Minimal();
2781 return Subtarget.hasVInstructionsBF16Minimal();
2783 return Subtarget.hasVInstructionsF32();
2785 return Subtarget.hasVInstructionsF64();
2799 "Unexpected opcode");
2801 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
2803 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
2806 return Op.getOperand(
II->VLOperand + 1 + HasChain);
2880bool RISCVTargetLowering::useRVVForFixedLengthVectorVT(
MVT VT)
const {
2881 return ::useRVVForFixedLengthVectorVT(VT, Subtarget);
2890 "Expected legal fixed length vector!");
2893 unsigned MaxELen = Subtarget.
getELen();
2927 return ::getContainerForFixedLengthVector(*
this, VT,
getSubtarget());
2934 "Expected to convert into a scalable vector!");
2935 assert(V.getValueType().isFixedLengthVector() &&
2936 "Expected a fixed length vector operand!");
2945 "Expected to convert into a fixed length vector!");
2946 assert(V.getValueType().isScalableVector() &&
2947 "Expected a scalable vector operand!");
2966 return DAG.
getNode(RISCVISD::VMSET_VL,
DL, MaskVT, VL);
2969static std::pair<SDValue, SDValue>
2978static std::pair<SDValue, SDValue>
2991static std::pair<SDValue, SDValue>
3008std::pair<unsigned, unsigned>
3016 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
3020 unsigned VectorBitsMin = Subtarget.getRealMinVLen();
3024 return std::make_pair(MinVLMAX, MaxVLMAX);
3036 EVT VT,
unsigned DefinedValues)
const {
3045 unsigned DLenFactor = Subtarget.getDLenFactor();
3050 std::tie(LMul, Fractional) =
3053 Cost = LMul <= DLenFactor ? (DLenFactor / LMul) : 1;
3055 Cost = (LMul * DLenFactor);
3069 bool Log2CostModel =
3071 if (Log2CostModel && LMULCost.isValid()) {
3072 unsigned Log =
Log2_64(LMULCost.getValue());
3074 return LMULCost * Log;
3076 return LMULCost * LMULCost;
3107 Op.getValueType() == MVT::bf16) {
3108 bool IsStrict =
Op->isStrictFPOpcode();
3113 {Op.getOperand(0), Op.getOperand(1)});
3115 {
Op.getValueType(), MVT::Other},
3121 DAG.
getNode(
Op.getOpcode(),
DL, MVT::f32,
Op.getOperand(0)),
3136 MVT DstVT =
Op.getSimpleValueType();
3145 Src.getValueType() == MVT::bf16) {
3151 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
3152 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
3153 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
3160 Opc,
DL, DstVT, Src,
3163 if (
Opc == RISCVISD::FCVT_WU_RV64)
3174 MVT SrcVT = Src.getSimpleValueType();
3180 if (SatVT != DstEltVT)
3183 MVT DstContainerVT = DstVT;
3184 MVT SrcContainerVT = SrcVT;
3190 "Expected same element count");
3199 {Src, Src, DAG.getCondCode(ISD::SETNE),
3200 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
3204 if (DstEltSize > (2 * SrcEltSize)) {
3207 Src = DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, InterVT, Src, Mask, VL);
3210 MVT CvtContainerVT = DstContainerVT;
3211 MVT CvtEltVT = DstEltVT;
3212 if (SrcEltSize > (2 * DstEltSize)) {
3218 IsSigned ? RISCVISD::VFCVT_RTZ_X_F_VL : RISCVISD::VFCVT_RTZ_XU_F_VL;
3221 while (CvtContainerVT != DstContainerVT) {
3225 unsigned ClipOpc = IsSigned ? RISCVISD::TRUNCATE_VECTOR_VL_SSAT
3226 : RISCVISD::TRUNCATE_VECTOR_VL_USAT;
3227 Res = DAG.
getNode(ClipOpc,
DL, CvtContainerVT, Res, Mask, VL);
3231 RISCVISD::VMV_V_X_VL,
DL, DstContainerVT, DAG.
getUNDEF(DstContainerVT),
3233 Res = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, DstContainerVT, IsNan, SplatZero,
3234 Res, DAG.
getUNDEF(DstContainerVT), VL);
3244 bool IsStrict =
Op->isStrictFPOpcode();
3245 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
3255 {
Op.getOperand(0), SrcVal});
3256 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
3257 {Ext.getValue(1), Ext.getValue(0)});
3260 DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, SrcVal));
3269 case ISD::FROUNDEVEN:
3271 case ISD::VP_FROUNDEVEN:
3275 case ISD::VP_FROUNDTOZERO:
3279 case ISD::VP_FFLOOR:
3291 case ISD::VP_FROUND:
3301 case ISD::VP_LLRINT:
3315 MVT VT =
Op.getSimpleValueType();
3325 MVT ContainerVT = VT;
3332 if (
Op->isVPOpcode()) {
3333 Mask =
Op.getOperand(1);
3337 VL =
Op.getOperand(2);
3343 SDValue Abs = DAG.
getNode(RISCVISD::FABS_VL,
DL, ContainerVT, Src, Mask, VL);
3356 DAG.
getUNDEF(ContainerVT), MaxValNode, VL);
3361 DAG.
getNode(RISCVISD::SETCC_VL,
DL, SetccVT,
3370 switch (
Op.getOpcode()) {
3378 case ISD::VP_FFLOOR:
3380 case ISD::FROUNDEVEN:
3381 case ISD::VP_FROUND:
3382 case ISD::VP_FROUNDEVEN:
3383 case ISD::VP_FROUNDTOZERO: {
3386 Truncated = DAG.
getNode(RISCVISD::VFCVT_RM_X_F_VL,
DL, IntVT, Src, Mask,
3391 Truncated = DAG.
getNode(RISCVISD::VFCVT_RTZ_X_F_VL,
DL, IntVT, Src,
3394 case ISD::FNEARBYINT:
3395 case ISD::VP_FNEARBYINT:
3396 Truncated = DAG.
getNode(RISCVISD::VFROUND_NOEXCEPT_VL,
DL, ContainerVT, Src,
3402 if (Truncated.
getOpcode() != RISCVISD::VFROUND_NOEXCEPT_VL)
3403 Truncated = DAG.
getNode(RISCVISD::SINT_TO_FP_VL,
DL, ContainerVT, Truncated,
3407 Truncated = DAG.
getNode(RISCVISD::FCOPYSIGN_VL,
DL, ContainerVT, Truncated,
3408 Src, Src, Mask, VL);
3423 MVT VT =
Op.getSimpleValueType();
3427 MVT ContainerVT = VT;
3439 MVT MaskVT = Mask.getSimpleValueType();
3442 {Chain, Src, Src, DAG.getCondCode(ISD::SETUNE),
3443 DAG.getUNDEF(MaskVT), Mask, VL});
3445 Src = DAG.
getNode(RISCVISD::STRICT_FADD_VL,
DL,
3447 {Chain, Src, Src, Src, Unorder, VL});
3451 SDValue Abs = DAG.
getNode(RISCVISD::FABS_VL,
DL, ContainerVT, Src, Mask, VL);
3464 DAG.
getUNDEF(ContainerVT), MaxValNode, VL);
3468 RISCVISD::SETCC_VL,
DL, MaskVT,
3476 switch (
Op.getOpcode()) {
3486 RISCVISD::STRICT_VFCVT_RM_X_F_VL,
DL, DAG.
getVTList(IntVT, MVT::Other),
3487 {Chain, Src, Mask, DAG.getTargetConstant(FRM, DL, XLenVT), VL});
3492 DAG.
getNode(RISCVISD::STRICT_VFCVT_RTZ_X_F_VL,
DL,
3493 DAG.
getVTList(IntVT, MVT::Other), Chain, Src, Mask, VL);
3496 Truncated = DAG.
getNode(RISCVISD::STRICT_VFROUND_NOEXCEPT_VL,
DL,
3497 DAG.
getVTList(ContainerVT, MVT::Other), Chain, Src,
3505 Truncated = DAG.
getNode(RISCVISD::STRICT_SINT_TO_FP_VL,
DL,
3506 DAG.
getVTList(ContainerVT, MVT::Other), Chain,
3507 Truncated, Mask, VL);
3512 Truncated = DAG.
getNode(RISCVISD::FCOPYSIGN_VL,
DL, ContainerVT, Truncated,
3513 Src, Src, Mask, VL);
3523 MVT VT =
Op.getSimpleValueType();
3544 return DAG.
getNode(RISCVISD::FROUND,
DL, VT, Src, MaxValNode,
3552 MVT DstVT =
Op.getSimpleValueType();
3554 MVT SrcVT = Src.getSimpleValueType();
3559 MVT DstContainerVT = DstVT;
3560 MVT SrcContainerVT = SrcVT;
3572 if (SrcElemType == MVT::f16 || SrcElemType == MVT::bf16) {
3574 Src = DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, F32VT, Src, Mask, VL);
3578 DAG.
getNode(RISCVISD::VFCVT_RM_X_F_VL,
DL, DstContainerVT, Src, Mask,
3598 return DAG.
getNode(RISCVISD::VSLIDEDOWN_VL,
DL, VT,
Ops);
3610 return DAG.
getNode(RISCVISD::VSLIDEUP_VL,
DL, VT,
Ops);
3635 return std::nullopt;
3653 unsigned EltSizeInBits) {
3656 return std::nullopt;
3657 bool IsInteger =
Op.getValueType().isInteger();
3659 std::optional<unsigned> SeqStepDenom;
3660 std::optional<APInt> SeqStepNum;
3661 std::optional<APInt> SeqAddend;
3662 std::optional<std::pair<APInt, unsigned>> PrevElt;
3663 assert(EltSizeInBits >=
Op.getValueType().getScalarSizeInBits());
3668 const unsigned OpSize =
Op.getScalarValueSizeInBits();
3669 for (
auto [Idx, Elt] :
enumerate(
Op->op_values())) {
3670 if (Elt.isUndef()) {
3671 Elts[Idx] = std::nullopt;
3675 Elts[Idx] = Elt->getAsAPIntVal().trunc(OpSize).zext(EltSizeInBits);
3680 return std::nullopt;
3681 Elts[Idx] = *ExactInteger;
3685 for (
auto [Idx, Elt] :
enumerate(Elts)) {
3694 unsigned IdxDiff = Idx - PrevElt->second;
3695 APInt ValDiff = *Elt - PrevElt->first;
3703 int64_t Remainder = ValDiff.
srem(IdxDiff);
3708 return std::nullopt;
3709 ValDiff = ValDiff.
sdiv(IdxDiff);
3714 SeqStepNum = ValDiff;
3715 else if (ValDiff != SeqStepNum)
3716 return std::nullopt;
3719 SeqStepDenom = IdxDiff;
3720 else if (IdxDiff != *SeqStepDenom)
3721 return std::nullopt;
3725 if (!PrevElt || PrevElt->first != *Elt)
3726 PrevElt = std::make_pair(*Elt, Idx);
3730 if (!SeqStepNum || !SeqStepDenom)
3731 return std::nullopt;
3735 for (
auto [Idx, Elt] :
enumerate(Elts)) {
3739 (
APInt(EltSizeInBits, Idx,
false,
true) *
3741 .sdiv(*SeqStepDenom);
3743 APInt Addend = *Elt - ExpectedVal;
3746 else if (Addend != SeqAddend)
3747 return std::nullopt;
3750 assert(SeqAddend &&
"Must have an addend if we have a step");
3752 return VIDSequence{SeqStepNum->getSExtValue(), *SeqStepDenom,
3753 SeqAddend->getSExtValue()};
3768 if (EltTy == MVT::i1 ||
3771 MVT SrcVT = Src.getSimpleValueType();
3787 MVT ContainerVT = VT;
3791 MVT SrcContainerVT = SrcVT;
3806 SDValue Gather = DAG.
getNode(RISCVISD::VRGATHER_VX_VL,
DL, ContainerVT, Src,
3807 Idx, DAG.
getUNDEF(ContainerVT), Mask, VL);
3815 MVT VT =
Op.getSimpleValueType();
3824 int64_t StepNumerator = SimpleVID->StepNumerator;
3825 unsigned StepDenominator = SimpleVID->StepDenominator;
3826 int64_t Addend = SimpleVID->Addend;
3828 assert(StepNumerator != 0 &&
"Invalid step");
3829 bool Negate =
false;
3830 int64_t SplatStepVal = StepNumerator;
3834 if (StepNumerator != 1 && StepNumerator !=
INT64_MIN &&
3836 Negate = StepNumerator < 0;
3838 SplatStepVal =
Log2_64(std::abs(StepNumerator));
3848 (SplatStepVal >= 0 || StepDenominator == 1) &&
isInt<32>(Addend)) {
3851 MVT VIDContainerVT =
3859 if ((StepOpcode ==
ISD::MUL && SplatStepVal != 1) ||
3860 (StepOpcode ==
ISD::SHL && SplatStepVal != 0)) {
3862 VID = DAG.
getNode(StepOpcode,
DL, VIDVT, VID, SplatStep);
3864 if (StepDenominator != 1) {
3869 if (Addend != 0 || Negate) {
3895 MVT VT =
Op.getSimpleValueType();
3904 unsigned NumElts =
Op.getNumOperands();
3907 unsigned MostCommonCount = 0;
3909 unsigned NumUndefElts =
3917 unsigned NumScalarLoads = 0;
3923 unsigned &
Count = ValueCounts[V];
3926 NumScalarLoads += !CFP->isExactlyValue(+0.0);
3931 if (++
Count >= MostCommonCount) {
3933 MostCommonCount =
Count;
3937 assert(DominantValue &&
"Not expecting an all-undef BUILD_VECTOR");
3938 unsigned NumDefElts = NumElts - NumUndefElts;
3939 unsigned DominantValueCountThreshold = NumDefElts <= 2 ? 0 : NumDefElts - 2;
3945 ((MostCommonCount > DominantValueCountThreshold) ||
3957 if (
SDValue LastOp =
Op->getOperand(
Op->getNumOperands() - 1);
3958 !LastOp.isUndef() && ValueCounts[LastOp] == 1 &&
3959 LastOp != DominantValue) {
3962 VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1DOWN_VL : RISCVISD::VSLIDE1DOWN_VL;
3968 Processed.
insert(LastOp);
3974 if (V.isUndef() || !Processed.
insert(V).second)
3976 if (ValueCounts[V] == 1) {
3984 return DAG.getConstant(V == V1, DL, XLenVT);
4000 MVT VT =
Op.getSimpleValueType();
4009 unsigned NumElts =
Op.getNumOperands();
4030 unsigned NumViaIntegerBits = std::clamp(NumElts, 8u, Subtarget.
getXLen());
4031 NumViaIntegerBits = std::min(NumViaIntegerBits, Subtarget.
getELen());
4039 unsigned IntegerViaVecElts =
divideCeil(NumElts, NumViaIntegerBits);
4040 MVT IntegerViaVecVT =
4045 unsigned BitPos = 0, IntegerEltIdx = 0;
4048 for (
unsigned I = 0;
I < NumElts;) {
4050 bool BitValue = !V.isUndef() && V->getAsZExtVal();
4051 Bits |= ((
uint64_t)BitValue << BitPos);
4057 if (
I % NumViaIntegerBits == 0 ||
I == NumElts) {
4058 if (NumViaIntegerBits <= 32)
4061 Elts[IntegerEltIdx] = Elt;
4070 if (NumElts < NumViaIntegerBits) {
4074 assert(IntegerViaVecVT == MVT::v1i8 &&
"Unexpected mask vector type");
4089 : RISCVISD::VMV_V_X_VL;
4109 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32) &&
4110 "Unexpected sequence type");
4114 unsigned ViaVecLen =
4122 const auto &SeqV =
OpIdx.value();
4123 if (!SeqV.isUndef())
4125 ((SeqV->getAsZExtVal() & EltMask) << (
OpIdx.index() * EltBitSize));
4131 if (ViaIntVT == MVT::i32)
4154 BV->getRepeatedSequence(Sequence) &&
4155 (Sequence.size() * EltBitSize) <= Subtarget.
getELen()) {
4156 unsigned SeqLen = Sequence.size();
4158 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32 ||
4159 ViaIntVT == MVT::i64) &&
4160 "Unexpected sequence type");
4165 const unsigned RequiredVL = NumElts / SeqLen;
4166 const unsigned ViaVecLen =
4168 NumElts : RequiredVL;
4171 unsigned EltIdx = 0;
4176 for (
const auto &SeqV : Sequence) {
4177 if (!SeqV.isUndef())
4179 ((SeqV->getAsZExtVal() & EltMask) << (EltIdx * EltBitSize));
4186 if (ViaIntVT == MVT::i32)
4193 (!Subtarget.
is64Bit() && ViaIntVT == MVT::i64)) &&
4194 "Unexpected bitcast sequence");
4198 MVT ViaContainerVT =
4201 DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ViaContainerVT,
4205 if (ViaVecLen != RequiredVL)
4224 Source, DAG, Subtarget);
4225 SDValue Res = DAG.
getNode(RISCVISD::VSEXT_VL,
DL, ContainerVT, Source, Mask, VL);
4244 return RISCV::PACKH;
4246 return Subtarget.
is64Bit() ? RISCV::PACKW : RISCV::PACK;
4261 MVT VT =
Op.getSimpleValueType();
4269 if (!Subtarget.hasStdExtZbb() || !Subtarget.hasStdExtZba())
4274 if (ElemSizeInBits >= std::min(Subtarget.
getELen(), Subtarget.
getXLen()) ||
4288 if (Subtarget.hasStdExtZbkb())
4293 ElemDL, XLenVT,
A,
B),
4305 NewOperands.
reserve(NumElts / 2);
4307 NewOperands.
push_back(pack(
Op.getOperand(i),
Op.getOperand(i + 1)));
4311 return DAG.
getNode(ISD::BITCAST,
DL, VT,
4317 MVT VT =
Op.getSimpleValueType();
4328 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) || EltVT == MVT::bf16) {
4333 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4334 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin())) {
4344 NewOps[
I] = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Elem);
4394 [](
const SDUse &U) { return U.get().isUndef(); })) {
4435 auto OneVRegOfOps =
ArrayRef(BuildVectorOps).slice(i, ElemsPerVReg);
4439 unsigned InsertIdx = (i / ElemsPerVReg) * NumOpElts;
4461 unsigned NumUndefElts =
4463 unsigned NumDefElts = NumElts - NumUndefElts;
4464 if (NumDefElts >= 8 && NumDefElts > NumElts / 2 &&
4471 for (
const auto &[Idx, U] :
enumerate(
Op->ops())) {
4473 if (Idx < NumElts / 2) {
4480 bool SelectMaskVal = (Idx < NumElts / 2);
4483 assert(SubVecAOps.
size() == NumElts && SubVecBOps.
size() == NumElts &&
4484 MaskVals.
size() == NumElts);
4519 unsigned UndefCount = 0;
4526 LinearBudget -= PerSlideCost;
4529 LinearBudget -= PerSlideCost;
4532 LinearBudget -= PerSlideCost;
4535 if (LinearBudget < 0)
4540 "Illegal type which will result in reserved encoding");
4556 bool SlideUp =
false;
4581 if (EVecEltVT != ContainerEltVT)
4602 std::reverse(Operands.
begin(), Operands.
end());
4630 Vec = getVSlide(ContainerVT, DAG.
getUNDEF(ContainerVT), Vec,
Offset, Mask,
4637 Opcode = SlideUp ? RISCVISD::VFSLIDE1UP_VL : RISCVISD::VFSLIDE1DOWN_VL;
4639 Opcode = SlideUp ? RISCVISD::VSLIDE1UP_VL : RISCVISD::VSLIDE1DOWN_VL;
4648 Vec = getVSlide(ContainerVT, DAG.
getUNDEF(ContainerVT), Vec,
Offset, Mask,
4664 if ((LoC >> 31) == HiC)
4665 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4677 auto InterVec = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, InterVT,
4679 return DAG.
getNode(ISD::BITCAST,
DL, VT, InterVec);
4686 Hi.getConstantOperandVal(1) == 31)
4687 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4692 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4695 return DAG.
getNode(RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL,
DL, VT, Passthru,
Lo,
4705 assert(Scalar.getValueType() == MVT::i64 &&
"Unexpected VT!");
4717 bool HasPassthru = Passthru && !Passthru.
isUndef();
4718 if (!HasPassthru && !Passthru)
4725 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
4726 EltVT == MVT::bf16) {
4727 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4728 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
4729 Scalar = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Scalar);
4731 Scalar = DAG.
getNode(ISD::BITCAST,
DL, MVT::i16, Scalar);
4733 Passthru = DAG.
getNode(ISD::BITCAST,
DL, IVT, Passthru);
4738 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL, VT, Passthru, Scalar, VL);
4742 if (Scalar.getValueType().bitsLE(XLenVT)) {
4749 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4750 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru, Scalar, VL);
4753 assert(XLenVT == MVT::i32 && Scalar.getValueType() == MVT::i64 &&
4754 "Unexpected scalar for splat lowering!");
4757 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, VT, Passthru,
4783 MVT ExtractedContainerVT = ExtractedVT;
4786 DAG, ExtractedContainerVT, Subtarget);
4788 ExtractedVal, DAG, Subtarget);
4790 if (ExtractedContainerVT.
bitsLE(VT))
4802 if (!Scalar.getValueType().bitsLE(XLenVT))
4805 VT,
DL, DAG, Subtarget);
4813 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4854 Src && Src.
getValueType().getVectorNumElements() == (NumElts * 2))
4871 !Subtarget.hasVendorXRivosVizip())
4874 int Size = Mask.size();
4876 assert(
Size == (
int)NumElts &&
"Unexpected mask size");
4882 EvenSrc = StartIndexes[0];
4883 OddSrc = StartIndexes[1];
4886 if (EvenSrc != 0 && OddSrc != 0)
4896 int HalfNumElts = NumElts / 2;
4897 return ((EvenSrc % HalfNumElts) == 0) && ((OddSrc % HalfNumElts) == 0);
4902 std::array<std::pair<int, int>, 2> &SrcInfo) {
4907 if (SrcInfo[0].second == 0 && SrcInfo[1].second == 0)
4911 if ((SrcInfo[0].second > 0 && SrcInfo[1].second < 0) ||
4912 SrcInfo[1].second == 0)
4914 assert(SrcInfo[0].first != -1 &&
"Must find one slide");
4922 if (SrcInfo[1].first == -1)
4924 return SrcInfo[0].second < 0 && SrcInfo[1].second > 0 &&
4925 SrcInfo[1].second - SrcInfo[0].second == (int)NumElts;
4930 bool RequiredPolarity) {
4931 int NumElts = Mask.size();
4932 for (
const auto &[Idx, M] :
enumerate(Mask)) {
4935 int Src = M >= NumElts;
4936 int Diff = (int)Idx - (M % NumElts);
4937 bool C = Src == SrcInfo[1].first && Diff == SrcInfo[1].second;
4938 assert(
C != (Src == SrcInfo[0].first && Diff == SrcInfo[0].second) &&
4939 "Must match exactly one of the two slides");
4940 if (RequiredPolarity != (
C == (Idx / Factor) % 2))
4951static bool isZipEven(
const std::array<std::pair<int, int>, 2> &SrcInfo,
4953 Factor = SrcInfo[1].second;
4955 Mask.size() % Factor == 0 &&
4966static bool isZipOdd(
const std::array<std::pair<int, int>, 2> &SrcInfo,
4968 Factor = -SrcInfo[1].second;
4970 Mask.size() % Factor == 0 &&
4983 ElementCount SrcEC = Src.getValueType().getVectorElementCount();
4990 unsigned Shift = Index * EltBits;
5015 std::optional<int> SplatIdx;
5017 if (M == -1 ||
I == (
unsigned)M)
5019 if (SplatIdx && *SplatIdx != M)
5028 for (
int MaskIndex : Mask) {
5029 bool SelectMaskVal = MaskIndex == *SplatIdx;
5032 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
5057 auto findNonEXTRACT_SUBVECTORParent =
5058 [](
SDValue Parent) -> std::pair<SDValue, uint64_t> {
5063 Parent.getOperand(0).getSimpleValueType().isFixedLengthVector()) {
5064 Offset += Parent.getConstantOperandVal(1);
5065 Parent = Parent.getOperand(0);
5067 return std::make_pair(Parent,
Offset);
5070 auto [V1Src, V1IndexOffset] = findNonEXTRACT_SUBVECTORParent(V1);
5071 auto [V2Src, V2IndexOffset] = findNonEXTRACT_SUBVECTORParent(V2);
5080 for (
size_t i = 0; i != NewMask.
size(); ++i) {
5081 if (NewMask[i] == -1)
5084 if (
static_cast<size_t>(NewMask[i]) < NewMask.
size()) {
5085 NewMask[i] = NewMask[i] + V1IndexOffset;
5089 NewMask[i] = NewMask[i] - NewMask.
size() + V2IndexOffset;
5095 if (NewMask[0] <= 0)
5099 for (
unsigned i = 1; i != NewMask.
size(); ++i)
5100 if (NewMask[i - 1] + 1 != NewMask[i])
5104 MVT SrcVT = Src.getSimpleValueType();
5133 int NumSubElts, Index;
5138 bool OpsSwapped = Mask[Index] < (int)NumElts;
5139 SDValue InPlace = OpsSwapped ? V2 : V1;
5140 SDValue ToInsert = OpsSwapped ? V1 : V2;
5151 if (NumSubElts + Index >= (
int)NumElts)
5162 Res = DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, ContainerVT, InPlace, ToInsert,
5165 Res =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, InPlace, ToInsert,
5177 bool OpsSwapped =
false;
5192 const unsigned E = Mask.size() - ((
Offset > 0) ?
Offset : 0);
5193 for (
unsigned i = S; i !=
E; ++i)
5194 if (Mask[i] >= 0 && (
unsigned)Mask[i] !=
Base + i +
Offset)
5200 bool IsVSlidedown = isSlideMask(Mask, OpsSwapped ? 0 : NumElts, 1);
5201 if (!IsVSlidedown && !isSlideMask(Mask, OpsSwapped ? 0 : NumElts, -1))
5204 const int InsertIdx = Mask[IsVSlidedown ? (NumElts - 1) : 0];
5206 if (InsertIdx < 0 || InsertIdx / NumElts != (
unsigned)OpsSwapped)
5223 IsVSlidedown ? RISCVISD::VSLIDE1DOWN_VL : RISCVISD::VSLIDE1UP_VL,
DL,
5229 auto OpCode = IsVSlidedown ?
5230 (VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1DOWN_VL : RISCVISD::VSLIDE1DOWN_VL) :
5231 (VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1UP_VL : RISCVISD::VSLIDE1UP_VL);
5234 auto Vec = DAG.
getNode(OpCode,
DL, ContainerVT,
5237 Splat, TrueMask, VL);
5249 for (
unsigned i = 0; i < Mask.size(); i++)
5250 LaneIsUndef[i % Factor] &= (Mask[i] == -1);
5253 for (
unsigned i = 0; i < Factor; i++) {
5264 for (
unsigned i = 0; i < Mask.size() / Factor; i++) {
5265 unsigned j = i * Factor + Index;
5266 if (Mask[j] != -1 && (
unsigned)Mask[j] != i)
5275 assert(RISCVISD::RI_VZIPEVEN_VL ==
Opc || RISCVISD::RI_VZIPODD_VL ==
Opc ||
5276 RISCVISD::RI_VZIP2A_VL ==
Opc || RISCVISD::RI_VZIP2B_VL ==
Opc ||
5277 RISCVISD::RI_VUNZIP2A_VL ==
Opc || RISCVISD::RI_VUNZIP2B_VL ==
Opc);
5285 MVT ContainerVT = IntVT;
5292 MVT InnerVT = ContainerVT;
5296 (RISCVISD::RI_VUNZIP2A_VL ==
Opc || RISCVISD::RI_VUNZIP2B_VL ==
Opc)) {
5308 if (InnerVT.
bitsLT(ContainerVT))
5323 MVT VT = V.getSimpleValueType();
5338 EC.multiplyCoefficientBy(Factor));
5357 MVT VecContainerVT = VecVT;
5374 MVT WideContainerVT = WideVT;
5380 EvenV = DAG.
getBitcast(VecContainerVT, EvenV);
5387 if (Subtarget.hasStdExtZvbb()) {
5391 Interleaved = DAG.
getNode(RISCVISD::VWSLL_VL,
DL, WideContainerVT, OddV,
5392 OffsetVec, Passthru, Mask, VL);
5393 Interleaved = DAG.
getNode(RISCVISD::VWADDU_W_VL,
DL, WideContainerVT,
5394 Interleaved, EvenV, Passthru, Mask, VL);
5401 Interleaved = DAG.
getNode(RISCVISD::VWADDU_VL,
DL, WideContainerVT, EvenV,
5402 OddV, Passthru, Mask, VL);
5408 OddV, AllOnesVec, Passthru, Mask, VL);
5415 Interleaved = DAG.
getNode(RISCVISD::ADD_VL,
DL, WideContainerVT,
5416 Interleaved, OddsMul, Passthru, Mask, VL);
5423 Interleaved = DAG.
getBitcast(ResultContainerVT, Interleaved);
5469 if (ViaEltSize > NumElts)
5477 if (ViaEltSize > NumElts)
5483 if (ViaEltSize > NumElts)
5490 MVT &RotateVT,
unsigned &RotateAmt) {
5493 unsigned NumSubElts;
5495 NumElts, NumSubElts, RotateAmt))
5498 NumElts / NumSubElts);
5566 unsigned NumOfSrcRegs = NumElts / NumOpElts;
5567 unsigned NumOfDestRegs = NumElts / NumOpElts;
5576 Mask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs,
5578 [&](
ArrayRef<int> SrcSubMask,
unsigned SrcVecIdx,
unsigned DstVecIdx) {
5579 Operands.
emplace_back().emplace_back(SrcVecIdx, UINT_MAX,
5582 [&](
ArrayRef<int> SrcSubMask,
unsigned Idx1,
unsigned Idx2,
bool NewReg) {
5587 assert(Operands.
size() == NumOfDestRegs &&
"Whole vector must be processed");
5592 unsigned NumShuffles = std::accumulate(
5593 Operands.
begin(), Operands.
end(), 0u,
5599 for (const auto &P : Data) {
5600 unsigned Idx2 = std::get<1>(P);
5601 ArrayRef<int> Mask = std::get<2>(P);
5602 if (Idx2 != UINT_MAX)
5604 else if (ShuffleVectorInst::isIdentityMask(Mask, Mask.size()))
5609 if ((NumOfDestRegs > 2 && NumShuffles > NumOfDestRegs) ||
5610 (NumOfDestRegs <= 2 && NumShuffles >= 4))
5612 auto ExtractValue = [&, &DAG = DAG](
SDValue SrcVec,
unsigned ExtractIdx) {
5613 SDValue SubVec = DAG.getExtractSubvector(
DL, M1VT, SrcVec, ExtractIdx);
5617 auto PerformShuffle = [&, &DAG = DAG](
SDValue SubVec1,
SDValue SubVec2,
5619 SDValue SubVec = DAG.getVectorShuffle(OneRegVT,
DL, SubVec1, SubVec2, Mask);
5622 SDValue Vec = DAG.getUNDEF(ContainerVT);
5628 const auto &[Idx1, Idx2,
_] =
Data[
I];
5636 V = ExtractValue(Idx1 >= NumOfSrcRegs ? V2 : V1,
5637 (Idx1 % NumOfSrcRegs) * NumOpElts);
5638 if (Idx2 != UINT_MAX) {
5641 V = ExtractValue(Idx2 >= NumOfSrcRegs ? V2 : V1,
5642 (Idx2 % NumOfSrcRegs) * NumOpElts);
5646 for (
const auto &[Idx1, Idx2, Mask] :
Data) {
5648 SDValue V2 = Idx2 == UINT_MAX ? V1 : Values.
at(Idx2);
5649 V = PerformShuffle(V1, V2, Mask);
5653 unsigned InsertIdx =
I * NumOpElts;
5655 Vec = DAG.getInsertSubvector(
DL, Vec, V, InsertIdx);
5665 bool SawUndef =
false;
5666 for (
const auto &[Idx, M] :
enumerate(Mask)) {
5673 if (Idx > (
unsigned)M)
5706 for (
int Idx : Mask) {
5709 unsigned SrcIdx = Idx % Mask.size();
5710 int Src = (
uint32_t)Idx < Mask.size() ? 0 : 1;
5711 if (Srcs[SrcIdx] == -1)
5714 else if (Srcs[SrcIdx] != Src)
5720 for (
int Lane : Srcs) {
5733 for (
unsigned I = 0;
I < Mask.size();
I++) {
5737 NewMask[
I] = Mask[
I] % Mask.size();
5751 if ((M / Span) != (
int)(
I / Span))
5753 int SpanIdx =
I % Span;
5763 return all_of(Mask, [&](
const auto &Idx) {
return Idx == -1 || Idx < Span; });
5775 int SpanIdx =
I % Span;
5776 if (Mask[SpanIdx] != M)
5790 MVT VT =
Op.getSimpleValueType();
5798 if (ElementSize > 32)
5821 MVT VT =
Op.getSimpleValueType();
5849 auto [TrueMask, VL] = TrueMaskVL;
5864 V.getOperand(0).getSimpleValueType().getVectorNumElements();
5865 V = V.getOperand(
Offset / OpElements);
5895 MVT SplatVT = ContainerVT;
5898 if (SVT == MVT::bf16 ||
5899 (SVT == MVT::f16 && !Subtarget.hasStdExtZfh())) {
5908 V = DAG.
getLoad(SVT,
DL, Ld->getChain(), NewAddr,
5909 Ld->getPointerInfo().getWithOffset(
Offset),
5910 Ld->getBaseAlign(), Ld->getMemOperand()->
getFlags());
5913 Ld->getPointerInfo().getWithOffset(
Offset), SVT,
5915 Ld->getMemOperand()->getFlags());
5919 : RISCVISD::VMV_V_X_VL;
5927 assert(Lane < (
int)NumElts &&
"Unexpected lane!");
5930 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
5952 if (Subtarget.hasStdExtZvkb())
5968 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
5969 for (
unsigned Factor = 2; Factor <= MaxFactor; Factor <<= 1) {
5972 1 <
count_if(Mask, [](
int Idx) {
return Idx != -1; })) {
5976 [&Mask](
int Idx) {
return Idx < (int)Mask.size(); }) &&
5977 1 <
count_if(Mask, [&Mask](
int Idx) {
5978 return Idx >= (int)Mask.size();
6008 if (Subtarget.hasVendorXRivosVizip() &&
6010 1 <
count_if(Mask, [](
int Idx) {
return Idx != -1; })) {
6012 Index == 0 ? RISCVISD::RI_VUNZIP2A_VL : RISCVISD::RI_VUNZIP2B_VL;
6028 [&Mask](
int Idx) {
return Idx < (int)Mask.size(); }) &&
6030 [&Mask](
int Idx) {
return Idx >= (int)Mask.size(); })) {
6034 if (NumElts < MinVLMAX) {
6058 int EvenSrc, OddSrc;
6068 bool LaneIsUndef[2] = {
true,
true};
6069 for (
const auto &[Idx, M] :
enumerate(Mask))
6070 LaneIsUndef[Idx % 2] &= (M == -1);
6072 int Size = Mask.size();
6074 if (LaneIsUndef[0]) {
6077 assert(EvenSrc >= 0 &&
"Undef source?");
6078 EvenV = (EvenSrc /
Size) == 0 ? V1 : V2;
6082 if (LaneIsUndef[1]) {
6085 assert(OddSrc >= 0 &&
"Undef source?");
6086 OddV = (OddSrc /
Size) == 0 ? V1 : V2;
6092 if (Subtarget.hasVendorXRivosVizip()) {
6095 return lowerVZIP(RISCVISD::RI_VZIP2A_VL, EvenV, OddV,
DL, DAG, Subtarget);
6106 std::array<std::pair<int, int>, 2> SrcInfo;
6113 auto GetSourceFor = [&](
const std::pair<int, int> &
Info) {
6114 int SrcIdx =
Info.first;
6115 assert(SrcIdx == 0 || SrcIdx == 1);
6116 SDValue &Src = Sources[SrcIdx];
6118 SDValue SrcV = SrcIdx == 0 ? V1 : V2;
6123 auto GetSlide = [&](
const std::pair<int, int> &Src,
SDValue Mask,
6125 auto [TrueMask, VL] = TrueMaskVL;
6126 SDValue SrcV = GetSourceFor(Src);
6127 int SlideAmt = Src.second;
6128 if (SlideAmt == 0) {
6130 assert(Mask == TrueMask);
6137 return getVSlideup(DAG, Subtarget,
DL, ContainerVT, Passthru, SrcV,
6142 if (SrcInfo[1].first == -1) {
6144 Res = GetSlide(SrcInfo[0], TrueMask, Res);
6148 if (Subtarget.hasVendorXRivosVizip()) {
6149 bool TryWiden =
false;
6153 SDValue Src1 = SrcInfo[0].first == 0 ? V1 : V2;
6154 SDValue Src2 = SrcInfo[1].first == 0 ? V1 : V2;
6155 return lowerVZIP(RISCVISD::RI_VZIPEVEN_VL, Src1, Src2,
DL, DAG,
6160 if (
isZipOdd(SrcInfo, Mask, Factor)) {
6162 SDValue Src1 = SrcInfo[1].first == 0 ? V1 : V2;
6163 SDValue Src2 = SrcInfo[0].first == 0 ? V1 : V2;
6164 return lowerVZIP(RISCVISD::RI_VZIPODD_VL, Src1, Src2,
DL, DAG,
6182 for (
const auto &[Idx, M] :
enumerate(Mask)) {
6184 (SrcInfo[1].second > 0 && Idx < (
unsigned)SrcInfo[1].second)) {
6188 int Src = M >= (int)NumElts;
6189 int Diff = (int)Idx - (M % NumElts);
6190 bool C = Src == SrcInfo[1].first && Diff == SrcInfo[1].second;
6191 assert(
C ^ (Src == SrcInfo[0].first && Diff == SrcInfo[0].second) &&
6192 "Must match exactly one of the two slides");
6195 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
6202 Res = GetSlide(SrcInfo[0], TrueMask, Res);
6203 Res = GetSlide(SrcInfo[1], SelectMask, Res);
6208 assert(!V1.
isUndef() &&
"Unexpected shuffle canonicalization");
6223 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
6224 for (
unsigned Factor = 4; Factor <= MaxFactor; Factor <<= 1) {
6239 if (NumElts > MinVLMAX) {
6240 unsigned MaxIdx = 0;
6244 MaxIdx = std::max(std::max((
unsigned)
I, (
unsigned)M), MaxIdx);
6246 unsigned NewNumElts =
6248 if (NewNumElts != NumElts) {
6252 Mask.take_front(NewNumElts));
6269 for (
auto Idx : Mask) {
6272 assert(Idx >= 0 && (
unsigned)Idx < NumElts);
6282 any_of(Mask, [&](
const auto &Idx) {
return Idx > 255; })) {
6292 unsigned GatherVVOpc = RISCVISD::VRGATHER_VV_VL;
6298 GatherVVOpc = RISCVISD::VRGATHEREI16_VV_VL;
6307 GatherVVOpc = RISCVISD::VRGATHEREI16_VV_VL;
6311 MVT IndexContainerVT =
6316 for (
int MaskIndex : Mask) {
6317 bool IsLHSIndex = MaskIndex < (int)NumElts && MaskIndex >= 0;
6327 if (NumElts <= MinVLMAX) {
6329 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
6335 auto [InnerTrueMask, InnerVL] =
6347 for (
int i = 0; i <
N; i++) {
6351 DAG.
getNode(GatherVVOpc,
DL, M1VT, SubV1, SubIndex,
6352 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6369 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6371 for (
int i = 0; i <
N; i++)
6387 for (
int i = 0; i <
N; i++) {
6390 DAG.
getUNDEF(IndexContainerVT), LHSIndices,
6391 SlideAmt, TrueMask, VL);
6395 DAG.
getNode(GatherVVOpc,
DL, M1VT, SubV1, SubIndex,
6396 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6406 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
6416 for (
int MaskIndex : Mask) {
6417 bool IsLHSOrUndefIndex = MaskIndex < (int)NumElts;
6418 ShuffleMaskLHS.
push_back(IsLHSOrUndefIndex && MaskIndex >= 0
6420 ShuffleMaskRHS.
push_back(IsLHSOrUndefIndex ? -1 : (MaskIndex - NumElts));
6451 for (
int MaskIndex : Mask) {
6452 bool SelectMaskVal = (MaskIndex < (int)NumElts) ^ !SwapOps;
6456 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
6474 const unsigned NumElts = M.size();
6481 std::array<std::pair<int, int>, 2> SrcInfo;
6492RISCVTargetLowering::lowerCTLZ_CTTZ_ZERO_UNDEF(
SDValue Op,
6494 MVT VT =
Op.getSimpleValueType();
6498 MVT ContainerVT = VT;
6501 if (
Op->isVPOpcode()) {
6502 Mask =
Op.getOperand(1);
6506 VL =
Op.getOperand(2);
6512 MVT FloatEltVT = (EltSize >= 32) ? MVT::f64 :
MVT::f32;
6514 FloatEltVT = MVT::f32;
6521 "Expected legal float type!");
6528 }
else if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF) {
6531 Src = DAG.
getNode(ISD::VP_AND,
DL, VT, Src, Neg, Mask, VL);
6536 if (FloatVT.
bitsGT(VT)) {
6537 if (
Op->isVPOpcode())
6538 FloatVal = DAG.
getNode(ISD::VP_UINT_TO_FP,
DL, FloatVT, Src, Mask, VL);
6547 if (!
Op->isVPOpcode())
6551 MVT ContainerFloatVT =
6553 FloatVal = DAG.
getNode(RISCVISD::VFCVT_RM_F_XU_VL,
DL, ContainerFloatVT,
6554 Src, Mask, RTZRM, VL);
6561 unsigned ShiftAmt = FloatEltVT == MVT::f64 ? 52 : 23;
6565 if (
Op->isVPOpcode()) {
6574 else if (IntVT.
bitsGT(VT))
6579 unsigned ExponentBias = FloatEltVT == MVT::f64 ? 1023 : 127;
6584 if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF)
6585 return DAG.
getNode(ISD::VP_SUB,
DL, VT, Exp,
6590 unsigned Adjust = ExponentBias + (EltSize - 1);
6592 if (
Op->isVPOpcode())
6602 else if (
Op.getOpcode() == ISD::VP_CTLZ)
6603 Res = DAG.
getNode(ISD::VP_UMIN,
DL, VT, Res,
6611 MVT XLenVT = Subtarget.getXLenVT();
6613 MVT SrcVT =
Source.getSimpleValueType();
6622 SrcVT = ContainerVT;
6634 SDValue Res = DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Source, Mask, EVL);
6635 if (
Op->getOpcode() == ISD::VP_CTTZ_ELTS_ZERO_UNDEF)
6653 assert(Load &&
Load->getMemoryVT().isVector() &&
"Expected vector load");
6656 Load->getMemoryVT(),
6657 *
Load->getMemOperand()))
6661 MVT VT =
Op.getSimpleValueType();
6663 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
6664 "Unexpected unaligned RVV load type");
6668 "Expecting equally-sized RVV vector types to be legal");
6670 Load->getPointerInfo(),
Load->getBaseAlign(),
6671 Load->getMemOperand()->getFlags());
6682 assert(Store &&
Store->getValue().getValueType().isVector() &&
6683 "Expected vector store");
6686 Store->getMemoryVT(),
6687 *
Store->getMemOperand()))
6694 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
6695 "Unexpected unaligned RVV store type");
6699 "Expecting equally-sized RVV vector types to be legal");
6700 StoredVal = DAG.
getBitcast(NewVT, StoredVal);
6702 Store->getPointerInfo(),
Store->getBaseAlign(),
6703 Store->getMemOperand()->getFlags());
6708 assert(
Op.getValueType() == MVT::i64 &&
"Unexpected VT");
6737 unsigned ShiftAmt, AddOpc;
6748 MVT VT =
Op.getSimpleValueType();
6752 bool Negate =
false;
6756 if (Index < 0 &&
Imm.isNegative()) {
6773 return DAG.
getNode(ISD::FNEG,
DL, VT, Const);
6779 unsigned IsData =
Op.getConstantOperandVal(4);
6782 if (Subtarget.hasVendorXMIPSCBOP() && !IsData)
6783 return Op.getOperand(0);
6795 if (Subtarget.hasStdExtZtso()) {
6803 return DAG.
getNode(ISD::MEMBARRIER, dl, MVT::Other,
Op.getOperand(0));
6811 return DAG.
getNode(ISD::MEMBARRIER, dl, MVT::Other,
Op.getOperand(0));
6819 MVT VT =
Op.getSimpleValueType();
6820 MVT XLenVT = Subtarget.getXLenVT();
6821 unsigned Check =
Op.getConstantOperandVal(1);
6822 unsigned TDCMask = 0;
6850 MVT VT0 =
Op.getOperand(0).getSimpleValueType();
6855 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6857 VL =
Op.getOperand(3);
6860 VL,
Op->getFlags());
6875 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6877 MVT MaskContainerVT =
6880 VL =
Op.getOperand(3);
6884 SDValue FPCLASS = DAG.
getNode(RISCVISD::FCLASS_VL,
DL, ContainerDstVT, Op0,
6885 Mask, VL,
Op->getFlags());
6887 TDCMaskV = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerDstVT,
6888 DAG.
getUNDEF(ContainerDstVT), TDCMaskV, VL);
6891 DAG.
getNode(RISCVISD::SETCC_VL,
DL, ContainerVT,
6897 TDCMaskV, DAG.
getUNDEF(ContainerDstVT), Mask, VL);
6900 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerDstVT,
6901 DAG.
getUNDEF(ContainerDstVT), SplatZero, VL);
6921 MVT VT =
Op.getSimpleValueType();
6947 Op.getOpcode() == ISD::FMAXIMUM ? RISCVISD::FMAX : RISCVISD::FMIN;
6955 MVT ContainerVT = VT;
6963 if (
Op->isVPOpcode()) {
6964 Mask =
Op.getOperand(2);
6968 VL =
Op.getOperand(3);
6975 SDValue XIsNonNan = DAG.
getNode(RISCVISD::SETCC_VL,
DL, Mask.getValueType(),
6976 {X, X, DAG.getCondCode(ISD::SETOEQ),
6977 DAG.getUNDEF(ContainerVT), Mask, VL});
6978 NewY = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, XIsNonNan,
Y,
X,
6984 SDValue YIsNonNan = DAG.
getNode(RISCVISD::SETCC_VL,
DL, Mask.getValueType(),
6985 {Y, Y, DAG.getCondCode(ISD::SETOEQ),
6986 DAG.getUNDEF(ContainerVT), Mask, VL});
6987 NewX = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, YIsNonNan,
X,
Y,
6992 Op.getOpcode() == ISD::FMAXIMUM ||
Op->getOpcode() == ISD::VP_FMAXIMUM
6993 ? RISCVISD::VFMAX_VL
6994 : RISCVISD::VFMIN_VL;
6996 DAG.
getUNDEF(ContainerVT), Mask, VL);
7004 bool IsFABS =
Op.getOpcode() == ISD::FABS;
7005 assert((IsFABS ||
Op.getOpcode() == ISD::FNEG) &&
7006 "Wrong opcode for lowering FABS or FNEG.");
7009 MVT VT =
Op.getSimpleValueType();
7010 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
7014 DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT,
Op.getOperand(0));
7017 Mask = Mask.sext(Subtarget.
getXLen());
7022 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, Logic);
7030 MVT VT =
Op.getSimpleValueType();
7031 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
7041 if (SignSize == Subtarget.
getXLen())
7042 return DAG.
getNode(ISD::BITCAST,
DL, XLenVT, Sign);
7045 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Sign);
7047 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, XLenVT, Sign);
7049 assert(XLenVT == MVT::i32 &&
"Unexpected type");
7052 return DAG.
getNode(RISCVISD::SplitF64,
DL, {MVT::i32, MVT::i32}, Sign)
7082 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, CopiedSign);
7087#define OP_CASE(NODE) \
7089 return RISCVISD::NODE##_VL;
7090#define VP_CASE(NODE) \
7091 case ISD::VP_##NODE: \
7092 return RISCVISD::NODE##_VL;
7094 switch (
Op.getOpcode()) {
7173 case ISD::VP_CTLZ_ZERO_UNDEF:
7174 return RISCVISD::CTLZ_VL;
7176 case ISD::VP_CTTZ_ZERO_UNDEF:
7177 return RISCVISD::CTTZ_VL;
7180 return RISCVISD::VFMADD_VL;
7182 return RISCVISD::STRICT_VFMADD_VL;
7185 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7186 return RISCVISD::VMAND_VL;
7187 return RISCVISD::AND_VL;
7190 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7191 return RISCVISD::VMOR_VL;
7192 return RISCVISD::OR_VL;
7195 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7196 return RISCVISD::VMXOR_VL;
7197 return RISCVISD::XOR_VL;
7200 return RISCVISD::VZEXT_VL;
7202 return RISCVISD::VSEXT_VL;
7204 return RISCVISD::SETCC_VL;
7206 return RISCVISD::VMERGE_VL;
7207 case ISD::VP_SELECT:
7209 return RISCVISD::VMERGE_VL;
7211 return RISCVISD::SRA_VL;
7213 return RISCVISD::SRL_VL;
7215 return RISCVISD::FSQRT_VL;
7216 case ISD::VP_SIGN_EXTEND:
7217 return RISCVISD::VSEXT_VL;
7218 case ISD::VP_ZERO_EXTEND:
7219 return RISCVISD::VZEXT_VL;
7220 case ISD::VP_FP_TO_SINT:
7221 return RISCVISD::VFCVT_RTZ_X_F_VL;
7222 case ISD::VP_FP_TO_UINT:
7223 return RISCVISD::VFCVT_RTZ_XU_F_VL;
7225 case ISD::FMINIMUMNUM:
7226 case ISD::VP_FMINNUM:
7227 return RISCVISD::VFMIN_VL;
7229 case ISD::FMAXIMUMNUM:
7230 case ISD::VP_FMAXNUM:
7231 return RISCVISD::VFMAX_VL;
7235 case ISD::VP_LLRINT:
7236 return RISCVISD::VFCVT_RM_X_F_VL;
7245 return (
Op.getValueType() == MVT::nxv32f16 &&
7248 Op.getValueType() == MVT::nxv32bf16;
7258 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7259 if (!
Op.getOperand(j).getValueType().isVector()) {
7260 LoOperands[j] =
Op.getOperand(j);
7261 HiOperands[j] =
Op.getOperand(j);
7264 std::tie(LoOperands[j], HiOperands[j]) =
7269 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
7271 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
7284 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7286 std::tie(LoOperands[j], HiOperands[j]) =
7290 if (!
Op.getOperand(j).getValueType().isVector()) {
7291 LoOperands[j] =
Op.getOperand(j);
7292 HiOperands[j] =
Op.getOperand(j);
7295 std::tie(LoOperands[j], HiOperands[j]) =
7300 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
7302 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
7312 auto [EVLLo, EVLHi] =
7313 DAG.
SplitEVL(
Op.getOperand(3),
Op.getOperand(1).getValueType(),
DL);
7317 {Op.getOperand(0), Lo, MaskLo, EVLLo},
Op->getFlags());
7319 {ResLo, Hi, MaskHi, EVLHi},
Op->getFlags());
7336 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7337 if (!
Op.getOperand(j).getValueType().isVector()) {
7338 LoOperands[j] =
Op.getOperand(j);
7339 HiOperands[j] =
Op.getOperand(j);
7342 std::tie(LoOperands[j], HiOperands[j]) =
7347 DAG.
getNode(
Op.getOpcode(),
DL, LoVTs, LoOperands,
Op->getFlags());
7350 DAG.
getNode(
Op.getOpcode(),
DL, HiVTs, HiOperands,
Op->getFlags());
7358RISCVTargetLowering::lowerXAndesBfHCvtBFloat16Load(
SDValue Op,
7360 assert(Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh() &&
7361 "Unexpected bfloat16 load lowering");
7365 EVT MemVT =
LD->getMemoryVT();
7370 LD->getMemOperand());
7378 DAG.
getNode(RISCVISD::NDS_FMV_BF16_X,
DL, MVT::bf16, OrSixteenOne);
7383RISCVTargetLowering::lowerXAndesBfHCvtBFloat16Store(
SDValue Op,
7385 assert(Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh() &&
7386 "Unexpected bfloat16 store lowering");
7391 Subtarget.getXLenVT(),
ST->getValue());
7393 ST->getChain(),
DL, FMV,
ST->getBasePtr(),
7395 ST->getMemOperand());
7400 switch (
Op.getOpcode()) {
7403 "Unimplemented RISCVTargetLowering::LowerOperation Case");
7406 case ISD::ATOMIC_FENCE:
7409 return lowerGlobalAddress(
Op, DAG);
7411 return lowerBlockAddress(
Op, DAG);
7413 return lowerConstantPool(
Op, DAG);
7415 return lowerJumpTable(
Op, DAG);
7417 return lowerGlobalTLSAddress(
Op, DAG);
7421 return lowerConstantFP(
Op, DAG);
7423 return lowerSELECT(
Op, DAG);
7425 return lowerBRCOND(
Op, DAG);
7427 return lowerVASTART(
Op, DAG);
7429 return lowerFRAMEADDR(
Op, DAG);
7431 return lowerRETURNADDR(
Op, DAG);
7433 return lowerShiftLeftParts(
Op, DAG);
7435 return lowerShiftRightParts(
Op, DAG,
true);
7437 return lowerShiftRightParts(
Op, DAG,
false);
7440 if (
Op.getValueType().isFixedLengthVector()) {
7441 assert(Subtarget.hasStdExtZvkb());
7442 return lowerToScalableOp(
Op, DAG);
7444 assert(Subtarget.hasVendorXTHeadBb() &&
7445 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
7446 "Unexpected custom legalization");
7451 case ISD::BITCAST: {
7453 EVT VT =
Op.getValueType();
7456 MVT XLenVT = Subtarget.getXLenVT();
7457 if (Op0VT == MVT::i16 &&
7458 ((VT == MVT::f16 && Subtarget.hasStdExtZfhminOrZhinxmin()) ||
7459 (VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
7461 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, NewOp0);
7463 if (VT == MVT::f32 && Op0VT == MVT::i32 && Subtarget.is64Bit() &&
7464 Subtarget.hasStdExtFOrZfinx()) {
7466 return DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, NewOp0);
7468 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit() &&
7469 Subtarget.hasStdExtDOrZdinx()) {
7472 return DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64,
Lo,
Hi);
7484 "Unexpected types");
7516 return LowerINTRINSIC_WO_CHAIN(
Op, DAG);
7518 return LowerINTRINSIC_W_CHAIN(
Op, DAG);
7520 return LowerINTRINSIC_VOID(
Op, DAG);
7522 return LowerIS_FPCLASS(
Op, DAG);
7524 MVT VT =
Op.getSimpleValueType();
7526 assert(Subtarget.hasStdExtZvbb());
7527 return lowerToScalableOp(
Op, DAG);
7530 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected custom legalization");
7534 return DAG.
getNode(RISCVISD::BREV8,
DL, VT, BSwap);
7540 if (!
Op.getSimpleValueType().isVector())
7542 return lowerVectorTruncLike(
Op, DAG);
7545 if (
Op.getOperand(0).getValueType().isVector() &&
7546 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7547 return lowerVectorMaskExt(
Op, DAG, 1);
7548 if (
Op.getValueType().isScalableVector())
7550 return lowerToScalableOp(
Op, DAG);
7552 if (
Op.getOperand(0).getValueType().isVector() &&
7553 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7554 return lowerVectorMaskExt(
Op, DAG, -1);
7555 if (
Op.getValueType().isScalableVector())
7557 return lowerToScalableOp(
Op, DAG);
7559 return lowerSPLAT_VECTOR_PARTS(
Op, DAG);
7561 return lowerINSERT_VECTOR_ELT(
Op, DAG);
7563 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
7565 MVT VT =
Op.getSimpleValueType();
7573 MVT ContainerVT = VT;
7580 V = DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL, ContainerVT,
7581 DAG.
getUNDEF(ContainerVT), Scalar, VL);
7584 V = DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, ContainerVT,
7585 DAG.
getUNDEF(ContainerVT), Scalar, VL);
7592 MVT XLenVT = Subtarget.getXLenVT();
7593 MVT VT =
Op.getSimpleValueType();
7612 }
else if (
Log2 > 3) {
7616 }
else if ((Val % 8) == 0) {
7634 if (
Op.getValueType() == MVT::f16 && Subtarget.is64Bit() &&
7635 Op.getOperand(1).getValueType() == MVT::i32) {
7639 DAG.
getNode(ISD::FPOWI,
DL, MVT::f32, Op0,
Op.getOperand(1));
7650 case ISD::FP_EXTEND:
7652 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
7655 return lowerStrictFPExtendOrRoundLike(
Op, DAG);
7658 if (
Op.getValueType().isVector() &&
7659 ((
Op.getValueType().getScalarType() == MVT::f16 &&
7660 (Subtarget.hasVInstructionsF16Minimal() &&
7661 !Subtarget.hasVInstructionsF16())) ||
7662 Op.getValueType().getScalarType() == MVT::bf16)) {
7678 Op1.getValueType().isVector() &&
7679 ((Op1.getValueType().getScalarType() == MVT::f16 &&
7680 (Subtarget.hasVInstructionsF16Minimal() &&
7681 !Subtarget.hasVInstructionsF16())) ||
7682 Op1.getValueType().getScalarType() == MVT::bf16)) {
7688 Op1.getValueType().getVectorElementCount());
7691 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), WidenVec);
7701 MVT VT =
Op.getSimpleValueType();
7704 bool IsStrict =
Op->isStrictFPOpcode();
7705 SDValue Src =
Op.getOperand(0 + IsStrict);
7706 MVT SrcVT = Src.getSimpleValueType();
7717 "Unexpected vector element types");
7721 if (EltSize > (2 * SrcEltSize)) {
7733 Op.getOperand(0), Ext);
7737 assert(SrcEltVT == MVT::f16 &&
"Unexpected FP_TO_[US]INT lowering");
7742 auto [FExt, Chain] =
7744 return DAG.
getNode(
Op.getOpcode(),
DL,
Op->getVTList(), Chain, FExt);
7751 if (SrcEltSize > (2 * EltSize)) {
7754 assert(EltVT == MVT::f16 &&
"Unexpected [US]_TO_FP lowering");
7759 Op.getOperand(0), Src);
7774 Op.getOperand(0), Src);
7788 unsigned RVVOpc = 0;
7789 switch (
Op.getOpcode()) {
7793 RVVOpc = RISCVISD::VFCVT_RTZ_X_F_VL;
7796 RVVOpc = RISCVISD::VFCVT_RTZ_XU_F_VL;
7799 RVVOpc = RISCVISD::SINT_TO_FP_VL;
7802 RVVOpc = RISCVISD::UINT_TO_FP_VL;
7805 RVVOpc = RISCVISD::STRICT_VFCVT_RTZ_X_F_VL;
7808 RVVOpc = RISCVISD::STRICT_VFCVT_RTZ_XU_F_VL;
7811 RVVOpc = RISCVISD::STRICT_SINT_TO_FP_VL;
7814 RVVOpc = RISCVISD::STRICT_UINT_TO_FP_VL;
7821 "Expected same element count");
7828 Op.getOperand(0), Src, Mask, VL);
7832 Src = DAG.
getNode(RVVOpc,
DL, ContainerVT, Src, Mask, VL);
7838 case ISD::FP_TO_BF16: {
7841 assert(!Subtarget.isSoftFPABI() &&
"Unexpected custom legalization");
7847 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
7848 if (Subtarget.is64Bit())
7849 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Res);
7852 case ISD::BF16_TO_FP: {
7853 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalization");
7854 MVT VT =
Op.getSimpleValueType();
7859 SDValue Res = Subtarget.is64Bit()
7860 ? DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32,
Op)
7864 return DAG.
getNode(ISD::FP_EXTEND,
DL, VT, Res);
7867 case ISD::STRICT_FP_TO_FP16:
7868 case ISD::FP_TO_FP16: {
7871 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalisation");
7874 bool IsStrict =
Op->isStrictFPOpcode();
7875 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7879 std::tie(Res, Chain) =
7880 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
7881 if (Subtarget.is64Bit())
7882 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Res);
7888 case ISD::STRICT_FP16_TO_FP:
7889 case ISD::FP16_TO_FP: {
7892 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalisation");
7895 bool IsStrict =
Op->isStrictFPOpcode();
7896 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7898 SDValue Arg = Subtarget.is64Bit()
7899 ? DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, Op0)
7902 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
7903 CallOptions,
DL, Chain);
7911 case ISD::FNEARBYINT:
7914 case ISD::FROUNDEVEN:
7921 case ISD::LLROUND: {
7922 if (
Op.getValueType().isVector())
7924 assert(
Op.getOperand(0).getValueType() == MVT::f16 &&
7925 "Unexpected custom legalisation");
7928 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), Ext);
7934 assert(
Op.getOperand(1).getValueType() == MVT::f16 &&
7935 "Unexpected custom legalisation");
7938 {
Op.getOperand(0),
Op.getOperand(1)});
7939 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
7940 {Ext.getValue(1), Ext.getValue(0)});
7942 case ISD::VECREDUCE_ADD:
7943 case ISD::VECREDUCE_UMAX:
7944 case ISD::VECREDUCE_SMAX:
7945 case ISD::VECREDUCE_UMIN:
7946 case ISD::VECREDUCE_SMIN:
7947 return lowerVECREDUCE(
Op, DAG);
7948 case ISD::VECREDUCE_AND:
7949 case ISD::VECREDUCE_OR:
7950 case ISD::VECREDUCE_XOR:
7951 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7952 return lowerVectorMaskVecReduction(
Op, DAG,
false);
7953 return lowerVECREDUCE(
Op, DAG);
7954 case ISD::VECREDUCE_FADD:
7955 case ISD::VECREDUCE_SEQ_FADD:
7956 case ISD::VECREDUCE_FMIN:
7957 case ISD::VECREDUCE_FMAX:
7958 case ISD::VECREDUCE_FMAXIMUM:
7959 case ISD::VECREDUCE_FMINIMUM:
7960 return lowerFPVECREDUCE(
Op, DAG);
7961 case ISD::VP_REDUCE_ADD:
7962 case ISD::VP_REDUCE_UMAX:
7963 case ISD::VP_REDUCE_SMAX:
7964 case ISD::VP_REDUCE_UMIN:
7965 case ISD::VP_REDUCE_SMIN:
7966 case ISD::VP_REDUCE_FADD:
7967 case ISD::VP_REDUCE_SEQ_FADD:
7968 case ISD::VP_REDUCE_FMIN:
7969 case ISD::VP_REDUCE_FMAX:
7970 case ISD::VP_REDUCE_FMINIMUM:
7971 case ISD::VP_REDUCE_FMAXIMUM:
7974 return lowerVPREDUCE(
Op, DAG);
7975 case ISD::VP_REDUCE_AND:
7976 case ISD::VP_REDUCE_OR:
7977 case ISD::VP_REDUCE_XOR:
7978 if (
Op.getOperand(1).getValueType().getVectorElementType() == MVT::i1)
7979 return lowerVectorMaskVecReduction(
Op, DAG,
true);
7980 return lowerVPREDUCE(
Op, DAG);
7981 case ISD::VP_CTTZ_ELTS:
7982 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
7983 return lowerVPCttzElements(
Op, DAG);
7987 DAG.
getUNDEF(ContainerVT), DAG, Subtarget);
7990 return lowerINSERT_SUBVECTOR(
Op, DAG);
7992 return lowerEXTRACT_SUBVECTOR(
Op, DAG);
7994 return lowerVECTOR_DEINTERLEAVE(
Op, DAG);
7996 return lowerVECTOR_INTERLEAVE(
Op, DAG);
7998 return lowerSTEP_VECTOR(
Op, DAG);
8000 return lowerVECTOR_REVERSE(
Op, DAG);
8002 return lowerVECTOR_SPLICE(
Op, DAG);
8004 MVT VT =
Op.getSimpleValueType();
8006 if (!Subtarget.is64Bit() && EltVT == MVT::i64)
8011 MVT VT =
Op.getSimpleValueType();
8013 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
8014 EltVT == MVT::bf16) {
8017 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
8018 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
8019 Elt = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, Subtarget.getXLenVT(),
8022 Elt = DAG.
getNode(ISD::BITCAST,
DL, MVT::i16,
Op.getOperand(0));
8024 return DAG.
getNode(ISD::BITCAST,
DL, VT,
8028 if (EltVT == MVT::i1)
8029 return lowerVectorMaskSplat(
Op, DAG);
8038 MVT VT =
Op.getSimpleValueType();
8039 MVT ContainerVT = VT;
8051 if (
Op.getNumOperands() > 2 &&
8055 size_t HalfNumOps =
Op.getNumOperands() / 2;
8057 Op->ops().take_front(HalfNumOps));
8059 Op->ops().drop_front(HalfNumOps));
8063 unsigned NumOpElts =
8064 Op.getOperand(0).getSimpleValueType().getVectorMinNumElements();
8077 EVT VT = Load->getValueType(0);
8078 if (VT == MVT::f64) {
8079 assert(Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
8080 !Subtarget.is64Bit() &&
"Unexpected custom legalisation");
8084 SDValue BasePtr = Load->getBasePtr();
8085 SDValue Chain = Load->getChain();
8088 DAG.
getLoad(MVT::i32,
DL, Chain, BasePtr, Load->getPointerInfo(),
8089 Load->getBaseAlign(), Load->getMemOperand()->getFlags());
8092 MVT::i32,
DL, Chain, BasePtr, Load->getPointerInfo().getWithOffset(4),
8093 Load->getBaseAlign(), Load->getMemOperand()->getFlags());
8101 if (VT == MVT::bf16)
8102 return lowerXAndesBfHCvtBFloat16Load(
Op, DAG);
8107 MVT XLenVT = Subtarget.getXLenVT();
8110 unsigned NumElts = Sz / (NF * 8);
8111 int Log2LMUL =
Log2_64(NumElts) - 3;
8114 Flag.setNoUnsignedWrap(
true);
8116 SDValue BasePtr = Load->getBasePtr();
8124 for (
unsigned i = 0; i < NF; ++i) {
8129 Ret = DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VT, Ret, LoadVal,
8137 if (
auto V = expandUnalignedRVVLoad(
Op, DAG))
8139 if (
Op.getValueType().isFixedLengthVector())
8140 return lowerFixedLengthVectorLoadToRVV(
Op, DAG);
8145 SDValue StoredVal = Store->getValue();
8147 if (VT == MVT::f64) {
8148 assert(Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
8149 !Subtarget.is64Bit() &&
"Unexpected custom legalisation");
8153 SDValue BasePtr = Store->getBasePtr();
8154 SDValue Chain = Store->getChain();
8156 DAG.
getVTList(MVT::i32, MVT::i32), StoredVal);
8159 Store->getPointerInfo(), Store->getBaseAlign(),
8160 Store->getMemOperand()->getFlags());
8163 Store->getPointerInfo().getWithOffset(4),
8164 Store->getBaseAlign(),
8165 Store->getMemOperand()->getFlags());
8168 if (VT == MVT::i64) {
8169 assert(Subtarget.hasStdExtZilsd() && !Subtarget.is64Bit() &&
8170 "Unexpected custom legalisation");
8171 if (Store->isTruncatingStore())
8174 if (!Subtarget.enableUnalignedScalarMem() && Store->getAlign() < 8)
8185 {Store->getChain(), Lo, Hi, Store->getBasePtr()}, MVT::i64,
8186 Store->getMemOperand());
8189 if (VT == MVT::bf16)
8190 return lowerXAndesBfHCvtBFloat16Store(
Op, DAG);
8195 MVT XLenVT = Subtarget.getXLenVT();
8198 unsigned NumElts = Sz / (NF * 8);
8199 int Log2LMUL =
Log2_64(NumElts) - 3;
8202 Flag.setNoUnsignedWrap(
true);
8204 SDValue Chain = Store->getChain();
8205 SDValue BasePtr = Store->getBasePtr();
8212 for (
unsigned i = 0; i < NF; ++i) {
8214 DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL,
8217 Ret = DAG.
getStore(Chain,
DL, Extract, BasePtr,
8219 Store->getBaseAlign(),
8220 Store->getMemOperand()->getFlags());
8221 Chain = Ret.getValue(0);
8227 if (
auto V = expandUnalignedRVVStore(
Op, DAG))
8229 if (
Op.getOperand(1).getValueType().isFixedLengthVector())
8230 return lowerFixedLengthVectorStoreToRVV(
Op, DAG);
8235 return lowerMaskedLoad(
Op, DAG);
8236 case ISD::VP_LOAD_FF:
8237 return lowerLoadFF(
Op, DAG);
8240 return lowerMaskedStore(
Op, DAG);
8242 return lowerVectorCompress(
Op, DAG);
8251 EVT VT =
Op.getValueType();
8262 MVT OpVT =
Op.getOperand(0).getSimpleValueType();
8264 MVT VT =
Op.getSimpleValueType();
8269 "Unexpected CondCode");
8302 return DAG.
getSetCC(
DL, VT, RHS, LHS, CCVal);
8308 return lowerToScalableOp(
Op, DAG);
8325 return lowerToScalableOp(
Op, DAG);
8329 if (
Op.getSimpleValueType().isFixedLengthVector())
8330 return lowerToScalableOp(
Op, DAG);
8332 assert(
Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.is64Bit() &&
8333 "Unexpected custom legalisation");
8337 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
8348 case ISD::FMINIMUMNUM:
8349 case ISD::FMAXIMUMNUM:
8365 return lowerToScalableOp(
Op, DAG);
8369 EVT VT =
Op->getValueType(0);
8384 return lowerABS(
Op, DAG);
8389 if (Subtarget.hasStdExtZvbb())
8390 return lowerToScalableOp(
Op, DAG);
8392 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8394 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
8398 return lowerToScalableOp(
Op, DAG);
8407 return lowerToScalableOp(
Op, DAG);
8410 return lowerVectorStrictFSetcc(
Op, DAG);
8420 case ISD::VP_GATHER:
8421 return lowerMaskedGather(
Op, DAG);
8423 case ISD::VP_SCATTER:
8424 return lowerMaskedScatter(
Op, DAG);
8426 return lowerGET_ROUNDING(
Op, DAG);
8427 case ISD::SET_ROUNDING:
8428 return lowerSET_ROUNDING(
Op, DAG);
8429 case ISD::GET_FPENV:
8430 return lowerGET_FPENV(
Op, DAG);
8431 case ISD::SET_FPENV:
8432 return lowerSET_FPENV(
Op, DAG);
8433 case ISD::RESET_FPENV:
8434 return lowerRESET_FPENV(
Op, DAG);
8435 case ISD::GET_FPMODE:
8436 return lowerGET_FPMODE(
Op, DAG);
8437 case ISD::SET_FPMODE:
8438 return lowerSET_FPMODE(
Op, DAG);
8439 case ISD::RESET_FPMODE:
8440 return lowerRESET_FPMODE(
Op, DAG);
8442 return lowerEH_DWARF_CFA(
Op, DAG);
8444 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
8445 return lowerVPMergeMask(
Op, DAG);
8447 case ISD::VP_SELECT:
8455 case ISD::VP_UADDSAT:
8456 case ISD::VP_USUBSAT:
8457 case ISD::VP_SADDSAT:
8458 case ISD::VP_SSUBSAT:
8460 case ISD::VP_LLRINT:
8461 return lowerVPOp(
Op, DAG);
8465 return lowerLogicVPOp(
Op, DAG);
8474 case ISD::VP_FMINNUM:
8475 case ISD::VP_FMAXNUM:
8476 case ISD::VP_FCOPYSIGN:
8483 return lowerVPOp(
Op, DAG);
8484 case ISD::VP_IS_FPCLASS:
8485 return LowerIS_FPCLASS(
Op, DAG);
8486 case ISD::VP_SIGN_EXTEND:
8487 case ISD::VP_ZERO_EXTEND:
8488 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
8489 return lowerVPExtMaskOp(
Op, DAG);
8490 return lowerVPOp(
Op, DAG);
8491 case ISD::VP_TRUNCATE:
8492 return lowerVectorTruncLike(
Op, DAG);
8493 case ISD::VP_FP_EXTEND:
8494 case ISD::VP_FP_ROUND:
8495 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
8496 case ISD::VP_SINT_TO_FP:
8497 case ISD::VP_UINT_TO_FP:
8498 if (
Op.getValueType().isVector() &&
8499 ((
Op.getValueType().getScalarType() == MVT::f16 &&
8500 (Subtarget.hasVInstructionsF16Minimal() &&
8501 !Subtarget.hasVInstructionsF16())) ||
8502 Op.getValueType().getScalarType() == MVT::bf16)) {
8515 case ISD::VP_FP_TO_SINT:
8516 case ISD::VP_FP_TO_UINT:
8518 Op1.getValueType().isVector() &&
8519 ((Op1.getValueType().getScalarType() == MVT::f16 &&
8520 (Subtarget.hasVInstructionsF16Minimal() &&
8521 !Subtarget.hasVInstructionsF16())) ||
8522 Op1.getValueType().getScalarType() == MVT::bf16)) {
8528 Op1.getValueType().getVectorElementCount());
8532 {WidenVec, Op.getOperand(1), Op.getOperand(2)});
8534 return lowerVPFPIntConvOp(
Op, DAG);
8538 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
8539 return lowerVPSetCCMaskOp(
Op, DAG);
8545 case ISD::VP_BITREVERSE:
8547 return lowerVPOp(
Op, DAG);
8549 case ISD::VP_CTLZ_ZERO_UNDEF:
8550 if (Subtarget.hasStdExtZvbb())
8551 return lowerVPOp(
Op, DAG);
8552 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8554 case ISD::VP_CTTZ_ZERO_UNDEF:
8555 if (Subtarget.hasStdExtZvbb())
8556 return lowerVPOp(
Op, DAG);
8557 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8559 return lowerVPOp(
Op, DAG);
8560 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
8561 return lowerVPStridedLoad(
Op, DAG);
8562 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
8563 return lowerVPStridedStore(
Op, DAG);
8565 case ISD::VP_FFLOOR:
8567 case ISD::VP_FNEARBYINT:
8568 case ISD::VP_FROUND:
8569 case ISD::VP_FROUNDEVEN:
8570 case ISD::VP_FROUNDTOZERO:
8574 case ISD::VP_FMAXIMUM:
8575 case ISD::VP_FMINIMUM:
8579 case ISD::EXPERIMENTAL_VP_SPLICE:
8580 return lowerVPSpliceExperimental(
Op, DAG);
8581 case ISD::EXPERIMENTAL_VP_REVERSE:
8582 return lowerVPReverseExperimental(
Op, DAG);
8583 case ISD::EXPERIMENTAL_VP_SPLAT:
8584 return lowerVPSplatExperimental(
Op, DAG);
8587 "llvm.clear_cache only needs custom lower on Linux targets");
8590 return emitFlushICache(DAG,
Op.getOperand(0),
Op.getOperand(1),
8591 Op.getOperand(2), Flags,
DL);
8593 case ISD::DYNAMIC_STACKALLOC:
8594 return lowerDYNAMIC_STACKALLOC(
Op, DAG);
8595 case ISD::INIT_TRAMPOLINE:
8596 return lowerINIT_TRAMPOLINE(
Op, DAG);
8597 case ISD::ADJUST_TRAMPOLINE:
8598 return lowerADJUST_TRAMPOLINE(
Op, DAG);
8599 case ISD::PARTIAL_REDUCE_UMLA:
8600 case ISD::PARTIAL_REDUCE_SMLA:
8601 case ISD::PARTIAL_REDUCE_SUMLA:
8602 return lowerPARTIAL_REDUCE_MLA(
Op, DAG);
8609 MakeLibCallOptions CallOptions;
8610 std::pair<SDValue, SDValue> CallResult =
8611 makeLibCall(DAG, RTLIB::RISCV_FLUSH_ICACHE, MVT::isVoid,
8612 {Start, End, Flags}, CallOptions,
DL, InChain);
8615 return CallResult.second;
8620 if (!Subtarget.is64Bit())
8628 std::unique_ptr<MCCodeEmitter> CodeEmitter(
8656 const bool HasCFBranch =
8657 Subtarget.hasStdExtZicfilp() &&
8659 "cf-protection-branch");
8660 const unsigned StaticChainIdx = HasCFBranch ? 5 : 4;
8661 const unsigned StaticChainOffset = StaticChainIdx * 4;
8662 const unsigned FunctionAddressOffset = StaticChainOffset + 8;
8666 auto GetEncoding = [&](
const MCInst &MC) {
8669 CodeEmitter->encodeInstruction(MC, CB, Fixups, *STI);
8676 SmallVector<uint32_t> Encodings;
8681 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X7).addImm(0)),
8685 GetEncoding(MCInstBuilder(RISCV::LD)
8688 .addImm(FunctionAddressOffset)),
8691 GetEncoding(MCInstBuilder(RISCV::LD)
8694 .addImm(StaticChainOffset)),
8697 GetEncoding(MCInstBuilder(RISCV::JALR)
8705 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X0).addImm(0)),
8708 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X28).addImm(0)),
8712 GetEncoding(MCInstBuilder(RISCV::LD)
8715 .addImm(FunctionAddressOffset - 4)),
8718 GetEncoding(MCInstBuilder(RISCV::LD)
8721 .addImm(StaticChainOffset - 4)),
8724 GetEncoding(MCInstBuilder(RISCV::JALR)
8736 Root, dl, DAG.
getConstant(Encoding, dl, MVT::i64), Addr,
8737 MachinePointerInfo(TrmpAddr, Idx * 4), MVT::i32));
8741 SDValue FunctionAddress =
Op.getOperand(2);
8745 struct OffsetValuePair {
8749 } OffsetValues[] = {
8750 {StaticChainOffset, StaticChain},
8751 {FunctionAddressOffset, FunctionAddress},
8753 for (
auto &OffsetValue : OffsetValues) {
8756 DAG.
getConstant(OffsetValue.Offset, dl, MVT::i64));
8757 OffsetValue.Addr = Addr;
8759 DAG.
getStore(Root, dl, OffsetValue.Value, Addr,
8760 MachinePointerInfo(TrmpAddr, OffsetValue.Offset)));
8763 assert(OutChains.
size() == StaticChainIdx + 2 &&
8764 "Size of OutChains mismatch");
8769 SDValue EndOfTrmp = OffsetValues[0].Addr;
8780 if (!Subtarget.is64Bit())
8783 return Op.getOperand(0);
8792 MVT VT =
Op.getSimpleValueType();
8798 MVT ArgVT =
A.getSimpleValueType();
8799 assert(ArgVT ==
B.getSimpleValueType() &&
8809 MVT ContainerVT = VT;
8818 switch (
Op.getOpcode()) {
8819 case ISD::PARTIAL_REDUCE_SMLA:
8820 Opc = RISCVISD::VQDOT_VL;
8822 case ISD::PARTIAL_REDUCE_UMLA:
8823 Opc = RISCVISD::VQDOTU_VL;
8825 case ISD::PARTIAL_REDUCE_SUMLA:
8826 Opc = RISCVISD::VQDOTSU_VL;
8852 N->getOffset(), Flags);
8881template <
class NodeTy>
8883 bool IsLocal,
bool IsExternWeak)
const {
8893 if (IsLocal && !Subtarget.allowTaggedGlobals())
8897 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
8920 if (Subtarget.hasVendorXqcili()) {
8924 return DAG.
getNode(RISCVISD::QC_E_LI,
DL, Ty, Addr);
8931 return DAG.
getNode(RISCVISD::ADD_LO,
DL, Ty, MNHi, AddrLo);
8955 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
8963 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
8971 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
8972 const GlobalValue *GV =
N->getGlobal();
8980 return getAddr(
N, DAG);
8987 return getAddr(
N, DAG);
8994 return getAddr(
N, DAG);
8999 bool UseGOT)
const {
9002 const GlobalValue *GV =
N->getGlobal();
9003 MVT XLenVT = Subtarget.getXLenVT();
9040 DAG.
getNode(RISCVISD::ADD_TPREL,
DL, Ty, MNHi, TPReg, AddrAdd);
9041 return DAG.
getNode(RISCVISD::ADD_LO,
DL, Ty, MNAdd, AddrLo);
9049 const GlobalValue *GV =
N->getGlobal();
9060 Args.emplace_back(Load, CallTy);
9063 TargetLowering::CallLoweringInfo CLI(DAG);
9077 const GlobalValue *GV =
N->getGlobal();
9093 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
9107 Addr = getStaticTLSAddr(
N, DAG,
false);
9110 Addr = getStaticTLSAddr(
N, DAG,
true);
9115 : getDynamicTLSAddr(
N, DAG);
9132 if (
LHS == LHS2 &&
RHS == RHS2) {
9137 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
9145 return std::nullopt;
9157 MVT VT =
N->getSimpleValueType(0);
9184 uint64_t TrueM1 = TrueC->getZExtValue() - 1;
9186 unsigned ShAmount =
Log2_64(TrueM1);
9188 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, CondV,
9204 if (~TrueVal == FalseVal) {
9244 if (Subtarget.hasShortForwardBranchOpt())
9247 unsigned SelOpNo = 0;
9257 unsigned ConstSelOpNo = 1;
9258 unsigned OtherSelOpNo = 2;
9265 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
9270 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
9276 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
9278 std::swap(NewConstOps[0], NewConstOps[1]);
9290 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
9292 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
9295 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
9296 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
9305 MVT VT =
Op.getSimpleValueType();
9306 MVT XLenVT = Subtarget.getXLenVT();
9327 return DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV);
9330 return DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV);
9334 auto getNotOperand = [](
const SDValue &
Op) -> std::optional<const SDValue> {
9335 using namespace llvm::SDPatternMatch;
9340 return std::nullopt;
9346 auto NotOperand = (TrueV.
getOperand(0) == FalseV)
9348 : getNotOperand(TrueV.getOperand(0));
9351 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, *NotOperand, CondV);
9357 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV));
9364 auto NotOperand = (FalseV.
getOperand(0) == TrueV)
9366 : getNotOperand(FalseV.getOperand(0));
9369 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, *NotOperand, CondV);
9375 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV));
9392 int64_t TrueImm =
TrueVal.getSExtValue();
9393 int64_t FalseImm =
FalseVal.getSExtValue();
9412 if ((TrueVal - FalseVal).isPowerOf2() &&
FalseVal.isSignedIntN(12)) {
9417 if ((FalseVal - TrueVal).isPowerOf2() &&
TrueVal.isSignedIntN(12)) {
9424 auto getCost = [&](
const APInt &Delta,
const APInt &Addend) {
9426 Delta, Subtarget.getXLen(), Subtarget,
true);
9428 if (Addend.isSignedIntN(12))
9431 Addend, Subtarget.getXLen(), Subtarget,
true);
9432 return AddendCost + DeltaCost;
9434 bool IsCZERO_NEZ =
getCost(FalseVal - TrueVal, TrueVal) <=
9435 getCost(TrueVal - FalseVal, FalseVal);
9437 IsCZERO_NEZ ? FalseVal - TrueVal : TrueVal - FalseVal,
DL, VT);
9439 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9440 DL, VT, LHSVal, CondV);
9448 SDValue ConstVal = IsCZERO_NEZ ? TrueV : FalseV;
9449 SDValue RegV = IsCZERO_NEZ ? FalseV : TrueV;
9452 if (RawConstVal == -0x800) {
9455 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9456 DL, VT, XorOp, CondV);
9464 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9465 DL, VT, SubOp, CondV);
9472 if (!Subtarget.hasConditionalMoveFusion())
9475 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV),
9476 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV),
9480 if (
Op.hasOneUse()) {
9481 unsigned UseOpc =
Op->user_begin()->getOpcode();
9483 SDNode *BinOp = *
Op->user_begin();
9490 return lowerSELECT(NewSel, DAG);
9544 if (TrueVal - 1 == FalseVal)
9546 if (TrueVal + 1 == FalseVal)
9553 RHS == TrueV &&
LHS == FalseV) {
9584 MVT XLenVT = Subtarget.getXLenVT();
9595 return DAG.
getNode(RISCVISD::BR_CC,
DL,
Op.getValueType(),
Op.getOperand(0),
9596 LHS,
RHS, TargetCC,
Op.getOperand(2));
9599 return DAG.
getNode(RISCVISD::BR_CC,
DL,
Op.getValueType(),
Op.getOperand(0),
9606 RISCVMachineFunctionInfo *FuncInfo = MF.
getInfo<RISCVMachineFunctionInfo>();
9616 MachinePointerInfo(SV));
9621 const RISCVRegisterInfo &RI = *Subtarget.getRegisterInfo();
9626 int XLenInBytes = Subtarget.getXLen() / 8;
9628 EVT VT =
Op.getValueType();
9631 unsigned Depth =
Op.getConstantOperandVal(0);
9633 int Offset = -(XLenInBytes * 2);
9645 const RISCVRegisterInfo &RI = *Subtarget.getRegisterInfo();
9649 MVT XLenVT = Subtarget.getXLenVT();
9650 int XLenInBytes = Subtarget.getXLen() / 8;
9652 EVT VT =
Op.getValueType();
9654 unsigned Depth =
Op.getConstantOperandVal(0);
9656 int Off = -XLenInBytes;
9657 SDValue FrameAddr = lowerFRAMEADDR(
Op, DAG);
9661 MachinePointerInfo());
9676 EVT VT =
Lo.getValueType();
9715 EVT VT =
Lo.getValueType();
9766 MVT VT =
Op.getSimpleValueType();
9771 return DAG.
getNode(RISCVISD::VMSET_VL,
DL, VT, VL);
9775 return DAG.
getNode(RISCVISD::VMCLR_VL,
DL, VT, VL);
9792 MVT VecVT =
Op.getSimpleValueType();
9794 "Unexpected SPLAT_VECTOR_PARTS lowering");
9800 MVT ContainerVT = VecVT;
9820 int64_t ExtTrueVal)
const {
9822 MVT VecVT =
Op.getSimpleValueType();
9825 assert(Src.getValueType().isVector() &&
9826 Src.getValueType().getVectorElementType() == MVT::i1);
9846 MVT XLenVT = Subtarget.getXLenVT();
9852 if (
Xor.getOpcode() == RISCVISD::VMXOR_VL) {
9864 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9865 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
9866 SplatTrueVal = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9867 DAG.
getUNDEF(ContainerVT), SplatTrueVal, VL);
9869 DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, CC, SplatTrueVal,
9870 SplatZero, DAG.
getUNDEF(ContainerVT), VL);
9880 bool IsVPTrunc =
Op.getOpcode() == ISD::VP_TRUNCATE;
9882 EVT MaskVT =
Op.getValueType();
9885 "Unexpected type for vector mask lowering");
9887 MVT VecVT = Src.getSimpleValueType();
9891 VL =
Op.getOperand(2);
9894 MVT ContainerVT = VecVT;
9900 MVT MaskContainerVT =
9907 std::tie(Mask, VL) =
9914 SplatOne = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9915 DAG.
getUNDEF(ContainerVT), SplatOne, VL);
9916 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9917 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
9920 SDValue Trunc = DAG.
getNode(RISCVISD::AND_VL,
DL, ContainerVT, Src, SplatOne,
9921 DAG.
getUNDEF(ContainerVT), Mask, VL);
9922 Trunc = DAG.
getNode(RISCVISD::SETCC_VL,
DL, MaskContainerVT,
9932 unsigned Opc =
Op.getOpcode();
9933 bool IsVPTrunc =
Opc == ISD::VP_TRUNCATE;
9936 MVT VT =
Op.getSimpleValueType();
9938 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
9942 return lowerVectorMaskTruncLike(
Op, DAG);
9950 MVT SrcVT = Src.getSimpleValueType();
9955 "Unexpected vector truncate lowering");
9957 MVT ContainerVT = SrcVT;
9961 VL =
Op.getOperand(2);
9974 std::tie(Mask, VL) =
9980 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL_SSAT;
9982 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL_USAT;
9984 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL;
9990 }
while (SrcEltVT != DstEltVT);
9999RISCVTargetLowering::lowerStrictFPExtendOrRoundLike(
SDValue Op,
10004 MVT VT =
Op.getSimpleValueType();
10005 MVT SrcVT = Src.getSimpleValueType();
10006 MVT ContainerVT = VT;
10025 ? RISCVISD::STRICT_FP_EXTEND_VL
10026 : RISCVISD::STRICT_VFNCVT_ROD_VL;
10029 Chain, Src, Mask, VL);
10030 Chain = Src.getValue(1);
10034 ? RISCVISD::STRICT_FP_EXTEND_VL
10035 : RISCVISD::STRICT_FP_ROUND_VL;
10037 Chain, Src, Mask, VL);
10048RISCVTargetLowering::lowerVectorFPExtendOrRoundLike(
SDValue Op,
10051 Op.getOpcode() == ISD::VP_FP_ROUND ||
Op.getOpcode() == ISD::VP_FP_EXTEND;
10053 Op.getOpcode() == ISD::VP_FP_EXTEND ||
Op.getOpcode() == ISD::FP_EXTEND;
10058 MVT VT =
Op.getSimpleValueType();
10060 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
10063 MVT SrcVT = Src.getSimpleValueType();
10065 bool IsDirectExtend =
10073 bool IsDirectConv = IsDirectExtend || IsDirectTrunc;
10080 MVT ContainerVT = VT;
10083 Mask =
Op.getOperand(1);
10084 VL =
Op.getOperand(2);
10098 std::tie(Mask, VL) =
10101 unsigned ConvOpc = IsExtend ? RISCVISD::FP_EXTEND_VL : RISCVISD::FP_ROUND_VL;
10103 if (IsDirectConv) {
10104 Src = DAG.
getNode(ConvOpc,
DL, ContainerVT, Src, Mask, VL);
10110 unsigned InterConvOpc =
10111 IsExtend ? RISCVISD::FP_EXTEND_VL : RISCVISD::VFNCVT_ROD_VL;
10115 DAG.
getNode(InterConvOpc,
DL, InterVT, Src, Mask, VL);
10117 DAG.
getNode(ConvOpc,
DL, ContainerVT, IntermediateConv, Mask, VL);
10128static std::optional<MVT>
10134 const unsigned MinVLMAX = VectorBitsMin / EltSize;
10136 if (MaxIdx < MinVLMAX)
10138 else if (MaxIdx < MinVLMAX * 2)
10141 else if (MaxIdx < MinVLMAX * 4)
10146 return std::nullopt;
10154 return isUInt<5>(IdxC->getZExtValue());
10166 MVT VecVT =
Op.getSimpleValueType();
10167 MVT XLenVT = Subtarget.getXLenVT();
10182 if ((ValVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
10183 ValVT == MVT::bf16) {
10188 DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Val), Idx);
10192 MVT ContainerVT = VecVT;
10202 std::optional<unsigned> AlignedIdx;
10204 const unsigned OrigIdx = IdxC->getZExtValue();
10207 DL, DAG, Subtarget)) {
10208 ContainerVT = *ShrunkVT;
10216 if (
auto VLEN = Subtarget.getRealVLen(); VLEN && ContainerVT.
bitsGT(M1VT)) {
10219 unsigned RemIdx = OrigIdx % ElemsPerVReg;
10220 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
10223 ContainerVT = M1VT;
10230 bool IsLegalInsert = Subtarget.is64Bit() || Val.
getValueType() != MVT::i64;
10238 IsLegalInsert =
true;
10247 if (IsLegalInsert) {
10249 VecVT.
isFloatingPoint() ? RISCVISD::VFMV_S_F_VL : RISCVISD::VMV_S_X_VL;
10253 Vec = DAG.
getNode(
Opc,
DL, ContainerVT, Vec, Val, VL);
10263 if (Subtarget.hasVendorXRivosVisni() && VecVT.
isInteger() &&
10268 Vec = DAG.
getNode(RISCVISD::RI_VINSERT_VL,
DL, ContainerVT, Vec, Val, Idx,
10284 std::tie(ValLo, ValHi) = DAG.
SplitScalar(Val,
DL, MVT::i32, MVT::i32);
10285 MVT I32ContainerVT =
10295 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10296 Vec, Vec, ValLo, I32Mask, InsertI64VL);
10300 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10301 Tail, ValInVec, ValHi, I32Mask, InsertI64VL);
10303 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
10314 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10316 DAG.
getUNDEF(I32ContainerVT), ValLo,
10317 I32Mask, InsertI64VL);
10318 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10319 DAG.
getUNDEF(I32ContainerVT), ValInVec, ValHi,
10320 I32Mask, InsertI64VL);
10322 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
10335 Idx, Mask, InsertVL, Policy);
10353 EVT EltVT =
Op.getValueType();
10355 MVT XLenVT = Subtarget.getXLenVT();
10360 MVT ContainerVT = VecVT;
10367 DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Vec, Mask, VL);
10374 if (NumElts >= 8) {
10376 unsigned WidenVecLen;
10379 unsigned MaxEEW = Subtarget.getELen();
10384 "the number of elements should be power of 2");
10388 ExtractBitIdx = Idx;
10390 WideEltVT = LargestEltVT;
10393 ExtractElementIdx = DAG.
getNode(
10402 Vec = DAG.
getNode(ISD::BITCAST,
DL, WideVT, Vec);
10404 Vec, ExtractElementIdx);
10419 if ((EltVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
10420 EltVT == MVT::bf16) {
10426 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, EltVT, IntExtract);
10430 MVT ContainerVT = VecVT;
10440 const auto VLen = Subtarget.getRealVLen();
10442 IdxC && VLen && VecVT.
getSizeInBits().getKnownMinValue() > *VLen) {
10444 unsigned OrigIdx = IdxC->getZExtValue();
10447 unsigned RemIdx = OrigIdx % ElemsPerVReg;
10448 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
10449 unsigned ExtractIdx =
10453 ContainerVT = M1VT;
10458 std::optional<uint64_t> MaxIdx;
10462 MaxIdx = IdxC->getZExtValue();
10464 if (
auto SmallerVT =
10466 ContainerVT = *SmallerVT;
10473 if (Subtarget.hasVendorXRivosVisni() && EltVT.
isInteger() &&
10501 DAG.
getUNDEF(ContainerVT), Vec, Idx, Mask, VL);
10520 "Unexpected opcode");
10527 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
10532 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
10533 if (!
II || !
II->hasScalarOperand())
10536 unsigned SplatOp =
II->ScalarOperand + 1 + HasChain;
10537 assert(SplatOp <
Op.getNumOperands());
10540 SDValue &ScalarOp = Operands[SplatOp];
10549 if (OpVT.
bitsLT(XLenVT)) {
10556 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
10557 return DAG.
getNode(
Op->getOpcode(),
DL,
Op->getVTList(), Operands);
10566 assert(
II->ScalarOperand > 0 &&
"Unexpected splat operand!");
10567 MVT VT =
Op.getOperand(SplatOp - 1).getSimpleValueType();
10570 assert(XLenVT == MVT::i32 && OpVT == MVT::i64 &&
10577 return DAG.
getNode(
Op->getOpcode(),
DL,
Op->getVTList(), Operands);
10581 case Intrinsic::riscv_vslide1up:
10582 case Intrinsic::riscv_vslide1down:
10583 case Intrinsic::riscv_vslide1up_mask:
10584 case Intrinsic::riscv_vslide1down_mask: {
10586 unsigned NumOps =
Op.getNumOperands();
10587 bool IsMasked =
NumOps == 7;
10593 std::tie(ScalarLo, ScalarHi) =
10602 const auto [MinVLMAX, MaxVLMAX] =
10606 if (AVLInt <= MinVLMAX) {
10608 }
else if (AVLInt >= 2 * MaxVLMAX) {
10640 Passthru = DAG.
getBitcast(I32VT, Operands[1]);
10642 if (IntNo == Intrinsic::riscv_vslide1up ||
10643 IntNo == Intrinsic::riscv_vslide1up_mask) {
10644 Vec = DAG.
getNode(RISCVISD::VSLIDE1UP_VL,
DL, I32VT, Passthru, Vec,
10645 ScalarHi, I32Mask, I32VL);
10646 Vec = DAG.
getNode(RISCVISD::VSLIDE1UP_VL,
DL, I32VT, Passthru, Vec,
10647 ScalarLo, I32Mask, I32VL);
10649 Vec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32VT, Passthru, Vec,
10650 ScalarLo, I32Mask, I32VL);
10651 Vec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32VT, Passthru, Vec,
10652 ScalarHi, I32Mask, I32VL);
10662 SDValue MaskedOff = Operands[1];
10670 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, Mask, Vec, MaskedOff,
10674 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, Mask, Vec, MaskedOff,
10683 return DAG.
getNode(
Op->getOpcode(),
DL,
Op->getVTList(), Operands);
10701 const unsigned ElementWidth = 8;
10706 [[maybe_unused]]
unsigned MinVF =
10709 [[maybe_unused]]
unsigned VF =
N->getConstantOperandVal(2);
10713 bool Fractional = VF < LMul1VF;
10714 unsigned LMulVal = Fractional ? LMul1VF / VF : VF / LMul1VF;
10735 MVT ContainerVT = OpVT;
10743 SDValue Res = DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Op0, Mask, VL);
10751 return DAG.
getSelect(
DL, XLenVT, Setcc, VL, Res);
10762 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
10766 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
10767 if (!
II || !
II->hasScalarOperand())
10770 unsigned SplatOp =
II->ScalarOperand + 1;
10771 assert(SplatOp <
Op.getNumOperands());
10773 SDValue &ScalarOp = Operands[SplatOp];
10783 if (OpVT.
bitsLT(XLenVT)) {
10786 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
10796 for (
SDValue &V : Operands) {
10797 EVT ValType = V.getValueType();
10798 if (ValType.isVector() && ValType.isFloatingPoint()) {
10801 ValType.getVectorElementCount());
10804 if (ValType.isFixedLengthVector()) {
10806 DAG, V.getSimpleValueType(), Subtarget);
10822 unsigned IntNo =
Op.getConstantOperandVal(0);
10824 MVT XLenVT = Subtarget.getXLenVT();
10829 case Intrinsic::riscv_tuple_insert: {
10834 return DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL,
Op.getValueType(), Vec,
10837 case Intrinsic::riscv_tuple_extract: {
10841 return DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL,
Op.getValueType(), Vec,
10844 case Intrinsic::thread_pointer: {
10848 case Intrinsic::riscv_orc_b:
10849 case Intrinsic::riscv_brev8:
10850 case Intrinsic::riscv_sha256sig0:
10851 case Intrinsic::riscv_sha256sig1:
10852 case Intrinsic::riscv_sha256sum0:
10853 case Intrinsic::riscv_sha256sum1:
10854 case Intrinsic::riscv_sm3p0:
10855 case Intrinsic::riscv_sm3p1: {
10858 case Intrinsic::riscv_orc_b:
Opc = RISCVISD::ORC_B;
break;
10859 case Intrinsic::riscv_brev8:
Opc = RISCVISD::BREV8;
break;
10860 case Intrinsic::riscv_sha256sig0:
Opc = RISCVISD::SHA256SIG0;
break;
10861 case Intrinsic::riscv_sha256sig1:
Opc = RISCVISD::SHA256SIG1;
break;
10862 case Intrinsic::riscv_sha256sum0:
Opc = RISCVISD::SHA256SUM0;
break;
10863 case Intrinsic::riscv_sha256sum1:
Opc = RISCVISD::SHA256SUM1;
break;
10864 case Intrinsic::riscv_sm3p0:
Opc = RISCVISD::SM3P0;
break;
10865 case Intrinsic::riscv_sm3p1:
Opc = RISCVISD::SM3P1;
break;
10870 case Intrinsic::riscv_sm4ks:
10871 case Intrinsic::riscv_sm4ed: {
10873 IntNo == Intrinsic::riscv_sm4ks ? RISCVISD::SM4KS : RISCVISD::SM4ED;
10878 case Intrinsic::riscv_zip:
10879 case Intrinsic::riscv_unzip: {
10881 IntNo == Intrinsic::riscv_zip ? RISCVISD::ZIP : RISCVISD::UNZIP;
10884 case Intrinsic::riscv_mopr:
10885 return DAG.
getNode(RISCVISD::MOP_R,
DL, XLenVT,
Op.getOperand(1),
10888 case Intrinsic::riscv_moprr: {
10889 return DAG.
getNode(RISCVISD::MOP_RR,
DL, XLenVT,
Op.getOperand(1),
10890 Op.getOperand(2),
Op.getOperand(3));
10892 case Intrinsic::riscv_clmul:
10893 return DAG.
getNode(RISCVISD::CLMUL,
DL, XLenVT,
Op.getOperand(1),
10895 case Intrinsic::riscv_clmulh:
10896 case Intrinsic::riscv_clmulr: {
10898 IntNo == Intrinsic::riscv_clmulh ? RISCVISD::CLMULH : RISCVISD::CLMULR;
10901 case Intrinsic::experimental_get_vector_length:
10903 case Intrinsic::experimental_cttz_elts:
10905 case Intrinsic::riscv_vmv_x_s: {
10909 case Intrinsic::riscv_vfmv_f_s:
10911 case Intrinsic::riscv_vmv_v_x:
10913 Op.getOperand(3),
Op.getSimpleValueType(),
DL, DAG,
10915 case Intrinsic::riscv_vfmv_v_f:
10916 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL,
Op.getValueType(),
10917 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
10918 case Intrinsic::riscv_vmv_s_x: {
10921 if (
Scalar.getValueType().bitsLE(XLenVT)) {
10923 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL,
Op.getValueType(),
10924 Op.getOperand(1), Scalar,
Op.getOperand(3));
10927 assert(
Scalar.getValueType() == MVT::i64 &&
"Unexpected scalar VT!");
10944 MVT VT =
Op.getSimpleValueType();
10949 if (
Op.getOperand(1).isUndef())
10950 return SplattedVal;
10959 DAG.
getNode(RISCVISD::SETCC_VL,
DL, MaskVT,
10962 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, SelectCond, SplattedVal,
10965 case Intrinsic::riscv_vfmv_s_f:
10966 return DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL,
Op.getSimpleValueType(),
10967 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
10969 case Intrinsic::riscv_vaesdf_vv:
10970 case Intrinsic::riscv_vaesdf_vs:
10971 case Intrinsic::riscv_vaesdm_vv:
10972 case Intrinsic::riscv_vaesdm_vs:
10973 case Intrinsic::riscv_vaesef_vv:
10974 case Intrinsic::riscv_vaesef_vs:
10975 case Intrinsic::riscv_vaesem_vv:
10976 case Intrinsic::riscv_vaesem_vs:
10977 case Intrinsic::riscv_vaeskf1:
10978 case Intrinsic::riscv_vaeskf2:
10979 case Intrinsic::riscv_vaesz_vs:
10980 case Intrinsic::riscv_vsm4k:
10981 case Intrinsic::riscv_vsm4r_vv:
10982 case Intrinsic::riscv_vsm4r_vs: {
10983 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
10984 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
10985 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
10990 case Intrinsic::riscv_vsm3c:
10991 case Intrinsic::riscv_vsm3me: {
10992 if (!
isValidEGW(8,
Op.getSimpleValueType(), Subtarget) ||
10993 !
isValidEGW(8,
Op->getOperand(1).getSimpleValueType(), Subtarget))
10998 case Intrinsic::riscv_vsha2ch:
10999 case Intrinsic::riscv_vsha2cl:
11000 case Intrinsic::riscv_vsha2ms: {
11001 if (
Op->getSimpleValueType(0).getScalarSizeInBits() == 64 &&
11002 !Subtarget.hasStdExtZvknhb())
11004 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
11005 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
11006 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
11010 case Intrinsic::riscv_sf_vc_v_x:
11011 case Intrinsic::riscv_sf_vc_v_i:
11012 case Intrinsic::riscv_sf_vc_v_xv:
11013 case Intrinsic::riscv_sf_vc_v_iv:
11014 case Intrinsic::riscv_sf_vc_v_vv:
11015 case Intrinsic::riscv_sf_vc_v_fv:
11016 case Intrinsic::riscv_sf_vc_v_xvv:
11017 case Intrinsic::riscv_sf_vc_v_ivv:
11018 case Intrinsic::riscv_sf_vc_v_vvv:
11019 case Intrinsic::riscv_sf_vc_v_fvv:
11020 case Intrinsic::riscv_sf_vc_v_xvw:
11021 case Intrinsic::riscv_sf_vc_v_ivw:
11022 case Intrinsic::riscv_sf_vc_v_vvw:
11023 case Intrinsic::riscv_sf_vc_v_fvw: {
11024 MVT VT =
Op.getSimpleValueType();
11061 MVT VT =
Op.getSimpleValueType();
11065 if (VT.isFloatingPoint()) {
11067 VT.getVectorElementCount());
11070 if (VT.isFixedLengthVector())
11080 if (VT.isFixedLengthVector())
11082 if (VT.isFloatingPoint())
11105 case Intrinsic::riscv_seg2_load_mask:
11106 case Intrinsic::riscv_seg3_load_mask:
11107 case Intrinsic::riscv_seg4_load_mask:
11108 case Intrinsic::riscv_seg5_load_mask:
11109 case Intrinsic::riscv_seg6_load_mask:
11110 case Intrinsic::riscv_seg7_load_mask:
11111 case Intrinsic::riscv_seg8_load_mask:
11114 case Intrinsic::riscv_sseg2_load_mask:
11115 case Intrinsic::riscv_sseg3_load_mask:
11116 case Intrinsic::riscv_sseg4_load_mask:
11117 case Intrinsic::riscv_sseg5_load_mask:
11118 case Intrinsic::riscv_sseg6_load_mask:
11119 case Intrinsic::riscv_sseg7_load_mask:
11120 case Intrinsic::riscv_sseg8_load_mask:
11128 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
11129 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
11130 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
11131 Intrinsic::riscv_vlseg8_mask};
11133 Intrinsic::riscv_vlsseg2_mask, Intrinsic::riscv_vlsseg3_mask,
11134 Intrinsic::riscv_vlsseg4_mask, Intrinsic::riscv_vlsseg5_mask,
11135 Intrinsic::riscv_vlsseg6_mask, Intrinsic::riscv_vlsseg7_mask,
11136 Intrinsic::riscv_vlsseg8_mask};
11139 unsigned NF =
Op->getNumValues() - 1;
11140 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
11142 MVT VT =
Op->getSimpleValueType(0);
11150 SDValue VL =
Op.getOperand(
Op.getNumOperands() - 1);
11151 SDValue Mask =
Op.getOperand(
Op.getNumOperands() - 2);
11152 MVT MaskVT = Mask.getSimpleValueType();
11153 MVT MaskContainerVT =
11158 IsStrided ? VlssegInts[NF - 2] : VlsegInts[NF - 2],
DL, XLenVT);
11174 Ops.insert(std::next(
Ops.begin(), 4),
Op.getOperand(3));
11178 Load->getMemoryVT(), Load->getMemOperand());
11180 for (
unsigned int RetIdx = 0; RetIdx < NF; RetIdx++) {
11182 Result.getValue(0),
11186 Results.push_back(Result.getValue(1));
11192 unsigned IntNo =
Op.getConstantOperandVal(1);
11196 case Intrinsic::riscv_seg2_load_mask:
11197 case Intrinsic::riscv_seg3_load_mask:
11198 case Intrinsic::riscv_seg4_load_mask:
11199 case Intrinsic::riscv_seg5_load_mask:
11200 case Intrinsic::riscv_seg6_load_mask:
11201 case Intrinsic::riscv_seg7_load_mask:
11202 case Intrinsic::riscv_seg8_load_mask:
11203 case Intrinsic::riscv_sseg2_load_mask:
11204 case Intrinsic::riscv_sseg3_load_mask:
11205 case Intrinsic::riscv_sseg4_load_mask:
11206 case Intrinsic::riscv_sseg5_load_mask:
11207 case Intrinsic::riscv_sseg6_load_mask:
11208 case Intrinsic::riscv_sseg7_load_mask:
11209 case Intrinsic::riscv_sseg8_load_mask:
11212 case Intrinsic::riscv_sf_vc_v_x_se:
11214 case Intrinsic::riscv_sf_vc_v_i_se:
11216 case Intrinsic::riscv_sf_vc_v_xv_se:
11218 case Intrinsic::riscv_sf_vc_v_iv_se:
11220 case Intrinsic::riscv_sf_vc_v_vv_se:
11222 case Intrinsic::riscv_sf_vc_v_fv_se:
11224 case Intrinsic::riscv_sf_vc_v_xvv_se:
11226 case Intrinsic::riscv_sf_vc_v_ivv_se:
11228 case Intrinsic::riscv_sf_vc_v_vvv_se:
11230 case Intrinsic::riscv_sf_vc_v_fvv_se:
11232 case Intrinsic::riscv_sf_vc_v_xvw_se:
11234 case Intrinsic::riscv_sf_vc_v_ivw_se:
11236 case Intrinsic::riscv_sf_vc_v_vvw_se:
11238 case Intrinsic::riscv_sf_vc_v_fvw_se:
11251 case Intrinsic::riscv_seg2_store_mask:
11252 case Intrinsic::riscv_seg3_store_mask:
11253 case Intrinsic::riscv_seg4_store_mask:
11254 case Intrinsic::riscv_seg5_store_mask:
11255 case Intrinsic::riscv_seg6_store_mask:
11256 case Intrinsic::riscv_seg7_store_mask:
11257 case Intrinsic::riscv_seg8_store_mask:
11260 case Intrinsic::riscv_sseg2_store_mask:
11261 case Intrinsic::riscv_sseg3_store_mask:
11262 case Intrinsic::riscv_sseg4_store_mask:
11263 case Intrinsic::riscv_sseg5_store_mask:
11264 case Intrinsic::riscv_sseg6_store_mask:
11265 case Intrinsic::riscv_sseg7_store_mask:
11266 case Intrinsic::riscv_sseg8_store_mask:
11275 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
11276 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
11277 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
11278 Intrinsic::riscv_vsseg8_mask};
11280 Intrinsic::riscv_vssseg2_mask, Intrinsic::riscv_vssseg3_mask,
11281 Intrinsic::riscv_vssseg4_mask, Intrinsic::riscv_vssseg5_mask,
11282 Intrinsic::riscv_vssseg6_mask, Intrinsic::riscv_vssseg7_mask,
11283 Intrinsic::riscv_vssseg8_mask};
11287 unsigned NF =
Op->getNumOperands() - (IsStrided ? 6 : 5);
11288 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
11290 MVT VT =
Op->getOperand(2).getSimpleValueType();
11296 SDValue VL =
Op.getOperand(
Op.getNumOperands() - 1);
11297 SDValue Mask =
Op.getOperand(
Op.getNumOperands() - 2);
11298 MVT MaskVT = Mask.getSimpleValueType();
11299 MVT MaskContainerVT =
11304 IsStrided ? VsssegInts[NF - 2] : VssegInts[NF - 2],
DL, XLenVT);
11310 for (
unsigned i = 0; i < NF; i++)
11312 RISCVISD::TUPLE_INSERT,
DL, VecTupTy, StoredVal,
11318 FixedIntrinsic->getChain(),
11327 Ops.insert(std::next(
Ops.begin(), 4),
11328 Op.getOperand(
Op.getNumOperands() - 3));
11332 FixedIntrinsic->getMemoryVT(), FixedIntrinsic->getMemOperand());
11337 unsigned IntNo =
Op.getConstantOperandVal(1);
11341 case Intrinsic::riscv_seg2_store_mask:
11342 case Intrinsic::riscv_seg3_store_mask:
11343 case Intrinsic::riscv_seg4_store_mask:
11344 case Intrinsic::riscv_seg5_store_mask:
11345 case Intrinsic::riscv_seg6_store_mask:
11346 case Intrinsic::riscv_seg7_store_mask:
11347 case Intrinsic::riscv_seg8_store_mask:
11348 case Intrinsic::riscv_sseg2_store_mask:
11349 case Intrinsic::riscv_sseg3_store_mask:
11350 case Intrinsic::riscv_sseg4_store_mask:
11351 case Intrinsic::riscv_sseg5_store_mask:
11352 case Intrinsic::riscv_sseg6_store_mask:
11353 case Intrinsic::riscv_sseg7_store_mask:
11354 case Intrinsic::riscv_sseg8_store_mask:
11357 case Intrinsic::riscv_sf_vc_xv_se:
11359 case Intrinsic::riscv_sf_vc_iv_se:
11361 case Intrinsic::riscv_sf_vc_vv_se:
11363 case Intrinsic::riscv_sf_vc_fv_se:
11365 case Intrinsic::riscv_sf_vc_xvv_se:
11367 case Intrinsic::riscv_sf_vc_ivv_se:
11369 case Intrinsic::riscv_sf_vc_vvv_se:
11371 case Intrinsic::riscv_sf_vc_fvv_se:
11373 case Intrinsic::riscv_sf_vc_xvw_se:
11375 case Intrinsic::riscv_sf_vc_ivw_se:
11377 case Intrinsic::riscv_sf_vc_vvw_se:
11379 case Intrinsic::riscv_sf_vc_fvw_se:
11387 switch (ISDOpcode) {
11390 case ISD::VP_REDUCE_ADD:
11391 case ISD::VECREDUCE_ADD:
11392 return RISCVISD::VECREDUCE_ADD_VL;
11393 case ISD::VP_REDUCE_UMAX:
11394 case ISD::VECREDUCE_UMAX:
11395 return RISCVISD::VECREDUCE_UMAX_VL;
11396 case ISD::VP_REDUCE_SMAX:
11397 case ISD::VECREDUCE_SMAX:
11398 return RISCVISD::VECREDUCE_SMAX_VL;
11399 case ISD::VP_REDUCE_UMIN:
11400 case ISD::VECREDUCE_UMIN:
11401 return RISCVISD::VECREDUCE_UMIN_VL;
11402 case ISD::VP_REDUCE_SMIN:
11403 case ISD::VECREDUCE_SMIN:
11404 return RISCVISD::VECREDUCE_SMIN_VL;
11405 case ISD::VP_REDUCE_AND:
11406 case ISD::VECREDUCE_AND:
11407 return RISCVISD::VECREDUCE_AND_VL;
11408 case ISD::VP_REDUCE_OR:
11409 case ISD::VECREDUCE_OR:
11410 return RISCVISD::VECREDUCE_OR_VL;
11411 case ISD::VP_REDUCE_XOR:
11412 case ISD::VECREDUCE_XOR:
11413 return RISCVISD::VECREDUCE_XOR_VL;
11414 case ISD::VP_REDUCE_FADD:
11415 return RISCVISD::VECREDUCE_FADD_VL;
11416 case ISD::VP_REDUCE_SEQ_FADD:
11417 return RISCVISD::VECREDUCE_SEQ_FADD_VL;
11418 case ISD::VP_REDUCE_FMAX:
11419 case ISD::VP_REDUCE_FMAXIMUM:
11420 return RISCVISD::VECREDUCE_FMAX_VL;
11421 case ISD::VP_REDUCE_FMIN:
11422 case ISD::VP_REDUCE_FMINIMUM:
11423 return RISCVISD::VECREDUCE_FMIN_VL;
11432 SDValue Vec =
Op.getOperand(IsVP ? 1 : 0);
11434 assert((
Op.getOpcode() == ISD::VECREDUCE_AND ||
11435 Op.getOpcode() == ISD::VECREDUCE_OR ||
11436 Op.getOpcode() == ISD::VECREDUCE_XOR ||
11437 Op.getOpcode() == ISD::VP_REDUCE_AND ||
11438 Op.getOpcode() == ISD::VP_REDUCE_OR ||
11439 Op.getOpcode() == ISD::VP_REDUCE_XOR) &&
11440 "Unexpected reduction lowering");
11442 MVT XLenVT = Subtarget.getXLenVT();
11444 MVT ContainerVT = VecVT;
11452 Mask =
Op.getOperand(2);
11453 VL =
Op.getOperand(3);
11455 std::tie(Mask, VL) =
11460 switch (
Op.getOpcode()) {
11463 case ISD::VECREDUCE_AND:
11464 case ISD::VP_REDUCE_AND: {
11468 Vec = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Vec, TrueMask, VL);
11471 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11475 case ISD::VECREDUCE_OR:
11476 case ISD::VP_REDUCE_OR:
11478 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11481 case ISD::VECREDUCE_XOR:
11482 case ISD::VP_REDUCE_XOR: {
11485 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11506 return DAG.
getNode(BaseOpc,
DL,
Op.getValueType(), SetCC,
Op.getOperand(0));
11512 return (RegisterAVL && RegisterAVL->getReg() == RISCV::X0) ||
11513 (ImmAVL && ImmAVL->getZExtValue() >= 1);
11529 auto InnerVT = VecVT.
bitsLE(M1VT) ? VecVT : M1VT;
11533 auto InnerVL = NonZeroAVL ? VL : DAG.
getConstant(1,
DL, XLenVT);
11536 if (M1VT != InnerVT)
11541 SDValue Ops[] = {PassThru, Vec, InitialValue, Mask, VL, Policy};
11559 VecEVT =
Lo.getValueType();
11572 MVT ContainerVT = VecVT;
11591 Mask, VL,
DL, DAG, Subtarget);
11597static std::tuple<unsigned, SDValue, SDValue>
11601 auto Flags =
Op->getFlags();
11602 unsigned Opcode =
Op.getOpcode();
11606 case ISD::VECREDUCE_FADD: {
11610 return std::make_tuple(RISCVISD::VECREDUCE_FADD_VL,
Op.getOperand(0), Zero);
11612 case ISD::VECREDUCE_SEQ_FADD:
11613 return std::make_tuple(RISCVISD::VECREDUCE_SEQ_FADD_VL,
Op.getOperand(1),
11615 case ISD::VECREDUCE_FMINIMUM:
11616 case ISD::VECREDUCE_FMAXIMUM:
11617 case ISD::VECREDUCE_FMIN:
11618 case ISD::VECREDUCE_FMAX: {
11621 (Opcode == ISD::VECREDUCE_FMIN || Opcode == ISD::VECREDUCE_FMINIMUM)
11622 ? RISCVISD::VECREDUCE_FMIN_VL
11623 : RISCVISD::VECREDUCE_FMAX_VL;
11624 return std::make_tuple(RVVOpc,
Op.getOperand(0), Front);
11632 MVT VecEltVT =
Op.getSimpleValueType();
11634 unsigned RVVOpcode;
11635 SDValue VectorVal, ScalarVal;
11636 std::tie(RVVOpcode, VectorVal, ScalarVal) =
11640 MVT ContainerVT = VecVT;
11646 MVT ResVT =
Op.getSimpleValueType();
11649 VL,
DL, DAG, Subtarget);
11650 if (
Op.getOpcode() != ISD::VECREDUCE_FMINIMUM &&
11651 Op.getOpcode() != ISD::VECREDUCE_FMAXIMUM)
11654 if (
Op->getFlags().hasNoNaNs())
11660 {VectorVal, VectorVal, DAG.getCondCode(ISD::SETNE),
11661 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
11662 MVT XLenVT = Subtarget.getXLenVT();
11663 SDValue CPop = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, IsNan, Mask, VL);
11667 DL, ResVT, NoNaNs, Res,
11674 unsigned Opc =
Op.getOpcode();
11678 MVT XLenVT = Subtarget.getXLenVT();
11697 Vec, Mask, VL,
DL, DAG, Subtarget);
11698 if ((
Opc != ISD::VP_REDUCE_FMINIMUM &&
Opc != ISD::VP_REDUCE_FMAXIMUM) ||
11699 Op->getFlags().hasNoNaNs())
11706 RISCVISD::SETCC_VL,
DL, PredVT,
11708 SDValue VCPop = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, IsNaN, Mask, VL);
11716 DL, ResVT, NoNaNs, Res,
11728 MVT XLenVT = Subtarget.getXLenVT();
11729 unsigned OrigIdx =
Op.getConstantOperandVal(2);
11730 const RISCVRegisterInfo *
TRI = Subtarget.getRegisterInfo();
11732 if (OrigIdx == 0 && Vec.
isUndef())
11743 assert(OrigIdx % 8 == 0 &&
"Invalid index");
11746 "Unexpected mask vector lowering");
11776 const auto VLen = Subtarget.getRealVLen();
11778 MVT ContainerVT = VecVT;
11800 if (OrigIdx == 0) {
11802 DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, ContainerVT, Vec, SubVec, VL);
11805 SubVec =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, Vec, SubVec,
11806 SlideupAmt, Mask, VL, Policy);
11814 MVT ContainerVecVT = VecVT;
11820 MVT ContainerSubVecVT = SubVecVT;
11826 unsigned SubRegIdx;
11827 ElementCount RemIdx;
11836 ContainerVecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
11837 SubRegIdx = Decompose.first;
11839 (OrigIdx % Vscale));
11843 ContainerVecVT, ContainerSubVecVT, OrigIdx,
TRI);
11844 SubRegIdx = Decompose.first;
11850 Subtarget.expandVScale(SubVecVT.
getSizeInBits()).getKnownMinValue()));
11851 bool ExactlyVecRegSized =
11853 .isKnownMultipleOf(Subtarget.expandVScale(VecRegSize));
11868 if (RemIdx.
isZero() && (ExactlyVecRegSized || Vec.
isUndef())) {
11872 if (SubRegIdx == RISCV::NoSubRegister) {
11894 MVT InterSubVT = ContainerVecVT;
11895 SDValue AlignedExtract = Vec;
11917 if (Subtarget.expandVScale(EndIndex) ==
11924 SubVec = DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, InterSubVT, AlignedExtract,
11932 SubVec =
getVSlideup(DAG, Subtarget,
DL, InterSubVT, AlignedExtract, SubVec,
11933 SlideupAmt, Mask, VL, Policy);
11938 if (ContainerVecVT.
bitsGT(InterSubVT))
11946 return DAG.
getBitcast(
Op.getSimpleValueType(), SubVec);
11952 MVT SubVecVT =
Op.getSimpleValueType();
11956 MVT XLenVT = Subtarget.getXLenVT();
11957 unsigned OrigIdx =
Op.getConstantOperandVal(1);
11958 const RISCVRegisterInfo *
TRI = Subtarget.getRegisterInfo();
11973 assert(OrigIdx % 8 == 0 &&
"Invalid index");
11976 "Unexpected mask vector lowering");
12002 const auto VLen = Subtarget.getRealVLen();
12010 MVT ContainerVT = VecVT;
12018 if (
auto ShrunkVT =
12020 ContainerVT = *ShrunkVT;
12032 DAG.
getUNDEF(ContainerVT), Vec, SlidedownAmt, Mask, VL);
12043 MVT ContainerSubVecVT = SubVecVT;
12047 unsigned SubRegIdx;
12048 ElementCount RemIdx;
12057 VecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
12058 SubRegIdx = Decompose.first;
12060 (OrigIdx % Vscale));
12064 VecVT, ContainerSubVecVT, OrigIdx,
TRI);
12065 SubRegIdx = Decompose.first;
12092 MVT InterSubVT = VecVT;
12097 assert(SubRegIdx != RISCV::NoSubRegister);
12116 Vec, SlidedownAmt, Mask, VL);
12124 return DAG.
getBitcast(
Op.getSimpleValueType(), Slidedown);
12131 MVT VT =
N.getSimpleValueType();
12135 assert(
Op.getSimpleValueType() == VT &&
12136 "Operands and result must be same type");
12140 unsigned NumVals =
N->getNumValues();
12143 NumVals,
N.getValueType().changeVectorElementType(MVT::i8)));
12146 for (
unsigned I = 0;
I < NumVals;
I++) {
12152 if (TruncVals.
size() > 1)
12154 return TruncVals.
front();
12160 MVT VecVT =
Op.getSimpleValueType();
12162 const unsigned Factor =
Op->getNumValues();
12173 for (
unsigned i = 0U; i < Factor; ++i)
12182 for (
unsigned i = 0U; i < Factor; ++i)
12192 for (
unsigned i = 0; i != Factor; ++i) {
12195 Ops[i * 2 + 1] = OpHi;
12206 for (
unsigned i = 0; i != Factor; ++i)
12213 if (Subtarget.hasVendorXRivosVizip() && Factor == 2) {
12214 MVT VT =
Op->getSimpleValueType(0);
12239 lowerVZIP(RISCVISD::RI_VUNZIP2A_VL, V1, V2,
DL, DAG, Subtarget);
12241 lowerVZIP(RISCVISD::RI_VUNZIP2B_VL, V1, V2,
DL, DAG, Subtarget);
12274 EvenSplat = DAG.
getBitcast(MVT::nxv64i1, EvenSplat);
12278 OddSplat = DAG.
getBitcast(MVT::nxv64i1, OddSplat);
12283 EvenMask, DAG.
getUNDEF(ConcatVT));
12295 MVT XLenVT = Subtarget.getXLenVT();
12317 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
12318 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
12319 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
12320 Intrinsic::riscv_vlseg8_mask};
12344 for (
unsigned i = 0U; i < Factor; ++i)
12345 Res[i] = DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL, VecVT, Load,
12354 MVT VecVT =
Op.getSimpleValueType();
12367 for (
unsigned i = 0U; i < Factor; ++i)
12375 for (
unsigned i = 0U; i < Factor; ++i)
12381 MVT XLenVT = Subtarget.getXLenVT();
12388 for (
unsigned i = 0; i != Factor; ++i) {
12391 Ops[i + Factor] = OpHi;
12402 for (
unsigned i = 0; i != Factor; ++i) {
12403 unsigned IdxLo = 2 * i;
12404 unsigned IdxHi = 2 * i + 1;
12406 Res[IdxLo / Factor].getValue(IdxLo % Factor),
12407 Res[IdxHi / Factor].getValue(IdxHi % Factor));
12425 EVT PtrVT =
StackPtr.getValueType();
12431 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
12432 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
12433 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
12434 Intrinsic::riscv_vsseg8_mask,
12442 for (
unsigned i = 0; i < Factor; i++)
12444 DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VecTupTy, StoredVal,
12467 for (
unsigned i = 0; i != Factor; ++i) {
12471 Loads[i] = DAG.
getLoad(VecVT,
DL, Chain, StackPtr, PtrInfo);
12479 if (Subtarget.hasVendorXRivosVizip() && !
Op.getOperand(0).isUndef() &&
12480 !
Op.getOperand(1).isUndef()) {
12500 Op.getOperand(0),
Op.getOperand(1));
12524 DAG.
getNode(RISCVISD::ADD_VL,
DL, IdxVT, Idx, VLMax, Idx, OddMask, VL);
12529 Interleaved = DAG.
getNode(RISCVISD::VRGATHEREI16_VV_VL,
DL, ConcatVT,
12546 MVT VT =
Op.getSimpleValueType();
12548 MVT XLenVT = Subtarget.getXLenVT();
12551 uint64_t StepValImm =
Op.getConstantOperandVal(0);
12552 if (StepValImm != 1) {
12561 VL, VT,
DL, DAG, Subtarget);
12576 MVT VecVT =
Op.getSimpleValueType();
12585 MVT ContainerVT = VecVT;
12592 MVT XLenVT = Subtarget.getXLenVT();
12638 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
12639 unsigned MaxVLMAX =
12644 unsigned GatherOpc = RISCVISD::VRGATHER_VV_VL;
12649 if (MaxVLMAX > 256 && EltSize == 8) {
12665 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
12673 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
12698 DAG.
getUNDEF(ContainerVT), Mask, VL);
12709 MVT XLenVT = Subtarget.getXLenVT();
12710 MVT VecVT =
Op.getSimpleValueType();
12715 SDValue DownOffset, UpOffset;
12716 if (ImmValue >= 0) {
12731 DAG, Subtarget,
DL, VecVT, DAG.
getUNDEF(VecVT), V1, DownOffset, TrueMask,
12732 Subtarget.hasVLDependentLatency() ? UpOffset
12734 return getVSlideup(DAG, Subtarget,
DL, VecVT, SlideDown, V2, UpOffset,
12740RISCVTargetLowering::lowerFixedLengthVectorLoadToRVV(
SDValue Op,
12746 Load->getMemoryVT(),
12747 *
Load->getMemOperand()) &&
12748 "Expecting a correctly-aligned load");
12750 MVT VT =
Op.getSimpleValueType();
12751 MVT XLenVT = Subtarget.getXLenVT();
12756 const auto [MinVLMAX, MaxVLMAX] =
12760 MachineMemOperand *MMO =
Load->getMemOperand();
12773 IsMaskOp ? Intrinsic::riscv_vlm : Intrinsic::riscv_vle,
DL, XLenVT);
12777 Ops.push_back(
Load->getBasePtr());
12779 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
12782 Load->getMemoryVT(),
Load->getMemOperand());
12789RISCVTargetLowering::lowerFixedLengthVectorStoreToRVV(
SDValue Op,
12795 Store->getMemoryVT(),
12796 *
Store->getMemOperand()) &&
12797 "Expecting a correctly-aligned store");
12801 MVT XLenVT = Subtarget.getXLenVT();
12817 const auto [MinVLMAX, MaxVLMAX] =
12821 MachineMemOperand *MMO =
Store->getMemOperand();
12831 IsMaskOp ? Intrinsic::riscv_vsm : Intrinsic::riscv_vse,
DL, XLenVT);
12834 {Store->getChain(), IntID, NewValue, Store->getBasePtr(), VL},
12835 Store->getMemoryVT(),
Store->getMemOperand());
12841 MVT VT =
Op.getSimpleValueType();
12844 EVT MemVT = MemSD->getMemoryVT();
12845 MachineMemOperand *MMO = MemSD->getMemOperand();
12846 SDValue Chain = MemSD->getChain();
12850 bool IsExpandingLoad =
false;
12852 Mask = VPLoad->getMask();
12854 VL = VPLoad->getVectorLength();
12857 Mask = MLoad->getMask();
12858 PassThru = MLoad->getPassThru();
12859 IsExpandingLoad = MLoad->isExpandingLoad();
12864 MVT XLenVT = Subtarget.getXLenVT();
12866 MVT ContainerVT = VT;
12880 if (!IsUnmasked && IsExpandingLoad) {
12883 DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Mask,
12887 unsigned IntID = IsUnmasked || IsExpandingLoad ? Intrinsic::riscv_vle
12888 : Intrinsic::riscv_vle_mask;
12890 if (IntID == Intrinsic::riscv_vle)
12893 Ops.push_back(PassThru);
12894 Ops.push_back(BasePtr);
12895 if (IntID == Intrinsic::riscv_vle_mask)
12896 Ops.push_back(Mask);
12898 if (IntID == Intrinsic::riscv_vle_mask)
12901 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
12905 Chain =
Result.getValue(1);
12907 MVT IndexVT = ContainerVT;
12912 bool UseVRGATHEREI16 =
false;
12920 UseVRGATHEREI16 =
true;
12926 DAG.
getUNDEF(IndexVT), Mask, ExpandingVL);
12928 DAG.
getNode(UseVRGATHEREI16 ? RISCVISD::VRGATHEREI16_VV_VL
12929 : RISCVISD::VRGATHER_VV_VL,
12930 DL, ContainerVT, Result, Iota, PassThru, Mask, ExpandingVL);
12941 MVT VT =
Op->getSimpleValueType(0);
12944 EVT MemVT = VPLoadFF->getMemoryVT();
12945 MachineMemOperand *MMO = VPLoadFF->getMemOperand();
12946 SDValue Chain = VPLoadFF->getChain();
12950 SDValue VL = VPLoadFF->getVectorLength();
12952 MVT XLenVT = Subtarget.getXLenVT();
12954 MVT ContainerVT = VT;
12961 unsigned IntID = Intrinsic::riscv_vleff_mask;
12971 SDVTList VTs = DAG.
getVTList({ContainerVT,
Op->getValueType(1), MVT::Other});
12976 Chain =
Result.getValue(2);
12989 EVT MemVT = MemSD->getMemoryVT();
12990 MachineMemOperand *MMO = MemSD->getMemOperand();
12991 SDValue Chain = MemSD->getChain();
12995 bool IsCompressingStore =
false;
12997 Val = VPStore->getValue();
12998 Mask = VPStore->getMask();
12999 VL = VPStore->getVectorLength();
13002 Val = MStore->getValue();
13003 Mask = MStore->getMask();
13004 IsCompressingStore = MStore->isCompressingStore();
13011 MVT XLenVT = Subtarget.getXLenVT();
13013 MVT ContainerVT = VT;
13018 if (!IsUnmasked || IsCompressingStore) {
13027 if (IsCompressingStore) {
13030 DAG.
getUNDEF(ContainerVT), Val, Mask, VL);
13032 DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Mask,
13037 IsUnmasked ? Intrinsic::riscv_vse : Intrinsic::riscv_vse_mask;
13039 Ops.push_back(Val);
13040 Ops.push_back(BasePtr);
13042 Ops.push_back(Mask);
13057 MVT XLenVT = Subtarget.getXLenVT();
13058 MVT ContainerVT = VT;
13071 Passthru, Val, Mask, VL);
13081 unsigned Opc =
Op.getOpcode();
13088 MVT VT =
Op.getSimpleValueType();
13096 SDVTList VTList =
Op->getVTList();
13121 MVT ContainerInVT = InVT;
13139 RISCVISD::STRICT_FSETCC_VL,
DL, DAG.
getVTList(MaskVT, MVT::Other),
13140 {Chain, Op1, Op1, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
13143 RISCVISD::STRICT_FSETCC_VL,
DL, DAG.
getVTList(MaskVT, MVT::Other),
13144 {Chain, Op2, Op2, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
13147 DAG.
getNode(RISCVISD::VMAND_VL,
DL, MaskVT, OrderMask1, OrderMask2, VL);
13150 Res = DAG.
getNode(RISCVISD::STRICT_FSETCCS_VL,
DL,
13152 {Chain, Op1, Op2, CC, Mask, Mask, VL});
13155 : RISCVISD::STRICT_FSETCCS_VL;
13157 {Chain, Op1, Op2, CC, DAG.getUNDEF(MaskVT), Mask, VL});
13170 MVT VT =
Op.getSimpleValueType();
13174 "Unexpected type for ISD::ABS");
13176 MVT ContainerVT = VT;
13183 if (
Op->getOpcode() == ISD::VP_ABS) {
13184 Mask =
Op->getOperand(1);
13188 VL =
Op->getOperand(2);
13193 RISCVISD::VMV_V_X_VL,
DL, ContainerVT, DAG.
getUNDEF(ContainerVT),
13196 DAG.
getUNDEF(ContainerVT), Mask, VL);
13198 DAG.
getUNDEF(ContainerVT), Mask, VL);
13207 const auto &TSInfo =
13211 bool HasPassthruOp = TSInfo.hasPassthruOp(NewOpc);
13212 bool HasMask = TSInfo.hasMaskOp(NewOpc);
13214 MVT VT =
Op.getSimpleValueType();
13219 for (
const SDValue &V :
Op->op_values()) {
13223 if (!
V.getValueType().isVector()) {
13229 assert(useRVVForFixedLengthVectorVT(
V.getSimpleValueType()) &&
13230 "Only fixed length vectors are supported!");
13232 V.getSimpleValueType().getVectorElementType());
13241 Ops.push_back(Mask);
13246 if (
Op->isStrictFPOpcode()) {
13265 const auto &TSInfo =
13269 bool HasPassthruOp = TSInfo.hasPassthruOp(RISCVISDOpc);
13272 MVT VT =
Op.getSimpleValueType();
13275 MVT ContainerVT = VT;
13284 if (HasPassthruOp) {
13287 if (*MaskIdx ==
OpIdx.index())
13291 if (
Op.getOpcode() == ISD::VP_MERGE) {
13293 Ops.push_back(
Ops.back());
13295 assert(
Op.getOpcode() == ISD::VP_SELECT);
13302 if (RISCVISDOpc == RISCVISD::VFCVT_RM_X_F_VL &&
13305 Subtarget.getXLenVT()));
13307 if (!
V.getValueType().isFixedLengthVector()) {
13312 MVT OpVT =
V.getSimpleValueType();
13314 assert(useRVVForFixedLengthVectorVT(OpVT) &&
13315 "Only fixed length vectors are supported!");
13330 MVT VT =
Op.getSimpleValueType();
13336 MVT ContainerVT = VT;
13343 MVT XLenVT = Subtarget.getXLenVT();
13346 DAG.
getUNDEF(ContainerVT), Zero, VL);
13349 Op.getOpcode() == ISD::VP_ZERO_EXTEND ? 1 : -1,
DL, XLenVT);
13351 DAG.
getUNDEF(ContainerVT), SplatValue, VL);
13354 ZeroSplat, DAG.
getUNDEF(ContainerVT), VL);
13363 MVT VT =
Op.getSimpleValueType();
13371 MVT ContainerVT = VT;
13379 SDValue AllOneMask = DAG.
getNode(RISCVISD::VMSET_VL,
DL, ContainerVT, VL);
13381 switch (Condition) {
13386 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, Op2, VL);
13391 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, Op2, VL);
13393 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, AllOneMask, VL);
13401 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, AllOneMask, VL);
13402 Result = DAG.
getNode(RISCVISD::VMAND_VL,
DL, ContainerVT, Temp, Op2, VL);
13410 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op2, AllOneMask, VL);
13411 Result = DAG.
getNode(RISCVISD::VMAND_VL,
DL, ContainerVT, Op1, Temp, VL);
13419 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, AllOneMask, VL);
13420 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, Op2, VL);
13428 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op2, AllOneMask, VL);
13429 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, Op1, VL);
13449 MVT DstVT =
Op.getSimpleValueType();
13450 MVT SrcVT = Src.getSimpleValueType();
13463 if (DstEltSize >= SrcEltSize) {
13467 unsigned RISCVISDExtOpc = RISCVISDOpc == RISCVISD::SINT_TO_FP_VL
13468 ? RISCVISD::VSEXT_VL
13469 : RISCVISD::VZEXT_VL;
13472 if (SrcEltSize == 1) {
13474 MVT XLenVT = Subtarget.getXLenVT();
13479 RISCVISDExtOpc == RISCVISD::VZEXT_VL ? 1 : -1,
DL, XLenVT);
13482 Src = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, IntVT, Src, OneSplat,
13483 ZeroSplat, DAG.
getUNDEF(IntVT), VL);
13484 }
else if (DstEltSize > (2 * SrcEltSize)) {
13488 Src = DAG.
getNode(RISCVISDExtOpc,
DL, IntVT, Src, Mask, VL);
13494 "Wrong input/output vector types");
13497 if (DstEltSize > (2 * SrcEltSize)) {
13502 DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, InterimFVT, Src, Mask, VL);
13513 MVT InterimFVT = DstVT;
13514 if (SrcEltSize > (2 * DstEltSize)) {
13515 assert(SrcEltSize == (4 * DstEltSize) &&
"Unexpected types!");
13522 if (InterimFVT != DstVT) {
13524 Result = DAG.
getNode(RISCVISD::FP_ROUND_VL,
DL, DstVT, Src, Mask, VL);
13528 "Wrong input/output vector types");
13532 if (DstEltSize == 1) {
13535 assert(SrcEltSize >= 16 &&
"Unexpected FP type!");
13542 MVT XLenVT = Subtarget.getXLenVT();
13544 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, InterimIVT,
13545 DAG.
getUNDEF(InterimIVT), SplatZero, VL);
13555 while (InterimIVT != DstVT) {
13567 MVT VT =
Op.getSimpleValueType();
13576 MVT VT =
Op.getSimpleValueType();
13577 MVT XLenVT = Subtarget.getXLenVT();
13590 MVT ContainerVT = VT;
13610 TrueVal = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, PromotedVT, TrueVal, SplatOne,
13611 SplatZero, DAG.
getUNDEF(PromotedVT), VL);
13614 SplatOne, SplatZero, DAG.
getUNDEF(PromotedVT), VLMax);
13618 TrueVal, FalseVal, FalseVal, VL);
13623 RISCVISD::SETCC_VL,
DL, ContainerVT,
13633RISCVTargetLowering::lowerVPSpliceExperimental(
SDValue Op,
13635 using namespace SDPatternMatch;
13646 const MVT XLenVT = Subtarget.getXLenVT();
13647 MVT VT =
Op.getSimpleValueType();
13648 MVT ContainerVT = VT;
13658 if (IsMaskVector) {
13668 Op1 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, Op1, SplatOneOp1,
13669 SplatZeroOp1, DAG.
getUNDEF(ContainerVT), EVL1);
13677 Op2 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, Op2, SplatOneOp2,
13678 SplatZeroOp2, DAG.
getUNDEF(ContainerVT), EVL2);
13681 auto getVectorFirstEle = [](
SDValue Vec) {
13694 if (
auto FirstEle = getVectorFirstEle(
Op->getOperand(0))) {
13697 if ((EltVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
13698 EltVT == MVT::bf16) {
13706 : RISCVISD::VSLIDE1UP_VL,
13707 DL, ContainerVT, DAG.
getUNDEF(ContainerVT), Op2,
13708 FirstEle, Mask, EVL2);
13718 SDValue DownOffset, UpOffset;
13719 if (ImmValue >= 0) {
13733 DAG.
getUNDEF(ContainerVT), Op1, DownOffset, Mask,
13734 Subtarget.hasVLDependentLatency() ? UpOffset : EVL2);
13738 if (IsMaskVector) {
13742 {Result, DAG.getConstant(0, DL, ContainerVT),
13743 DAG.getCondCode(ISD::SETNE), DAG.getUNDEF(getMaskTypeFor(ContainerVT)),
13758 MVT VT =
Op.getSimpleValueType();
13760 MVT ContainerVT = VT;
13771 DAG.
getNode(
C->isZero() ? RISCVISD::VMCLR_VL : RISCVISD::VMSET_VL,
DL,
13794RISCVTargetLowering::lowerVPReverseExperimental(
SDValue Op,
13797 MVT VT =
Op.getSimpleValueType();
13798 MVT XLenVT = Subtarget.getXLenVT();
13804 MVT ContainerVT = VT;
13812 MVT GatherVT = ContainerVT;
13816 if (IsMaskVector) {
13826 Op1 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, IndicesVT, Op1, SplatOne,
13827 SplatZero, DAG.
getUNDEF(IndicesVT), EVL);
13832 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
13833 unsigned MaxVLMAX =
13836 unsigned GatherOpc = RISCVISD::VRGATHER_VV_VL;
13842 if (MaxVLMAX > 256 && EltSize == 8) {
13870 DAG.
getUNDEF(GatherVT), Result, Diff, Mask, EVL);
13872 if (IsMaskVector) {
13875 DAG.
getNode(RISCVISD::SETCC_VL,
DL, ContainerVT,
13888 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
13895 DAG.
getUNDEF(IndicesVT), VecLen, EVL);
13896 SDValue VRSUB = DAG.
getNode(RISCVISD::SUB_VL,
DL, IndicesVT, VecLenSplat, VID,
13897 DAG.
getUNDEF(IndicesVT), Mask, EVL);
13899 DAG.
getUNDEF(GatherVT), Mask, EVL);
13901 if (IsMaskVector) {
13904 RISCVISD::SETCC_VL,
DL, ContainerVT,
13916 MVT VT =
Op.getSimpleValueType();
13918 return lowerVPOp(
Op, DAG);
13925 MVT ContainerVT = VT;
13943 MVT XLenVT = Subtarget.getXLenVT();
13944 MVT VT =
Op.getSimpleValueType();
13945 MVT ContainerVT = VT;
13949 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
13957 : Intrinsic::riscv_vlse_mask,
13960 DAG.
getUNDEF(ContainerVT), VPNode->getBasePtr(),
13961 VPNode->getStride()};
13967 Ops.push_back(Mask);
13969 Ops.push_back(VPNode->getVectorLength());
13973 Ops.push_back(Policy);
13978 VPNode->getMemoryVT(), VPNode->getMemOperand());
13990 MVT XLenVT = Subtarget.getXLenVT();
13993 SDValue StoreVal = VPNode->getValue();
13995 MVT ContainerVT = VT;
14006 : Intrinsic::riscv_vsse_mask,
14009 VPNode->getBasePtr(), VPNode->getStride()};
14015 Ops.push_back(Mask);
14017 Ops.push_back(VPNode->getVectorLength());
14020 Ops, VPNode->getMemoryVT(),
14021 VPNode->getMemOperand());
14033 MVT VT =
Op.getSimpleValueType();
14036 EVT MemVT = MemSD->getMemoryVT();
14037 MachineMemOperand *MMO = MemSD->getMemOperand();
14038 SDValue Chain = MemSD->getChain();
14045 Index = VPGN->getIndex();
14046 Mask = VPGN->getMask();
14048 VL = VPGN->getVectorLength();
14054 Index = MGN->getIndex();
14055 Mask = MGN->getMask();
14056 PassThru = MGN->getPassThru();
14060 MVT IndexVT =
Index.getSimpleValueType();
14061 MVT XLenVT = Subtarget.getXLenVT();
14064 "Unexpected VTs!");
14065 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
14068 "Unexpected extending MGATHER/VP_GATHER");
14074 MVT ContainerVT = VT;
14098 IsUnmasked ? Intrinsic::riscv_vluxei : Intrinsic::riscv_vluxei_mask;
14103 Ops.push_back(PassThru);
14104 Ops.push_back(BasePtr);
14105 Ops.push_back(Index);
14107 Ops.push_back(Mask);
14112 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
14115 Chain =
Result.getValue(1);
14133 EVT MemVT = MemSD->getMemoryVT();
14134 MachineMemOperand *MMO = MemSD->getMemOperand();
14135 SDValue Chain = MemSD->getChain();
14138 [[maybe_unused]]
bool IsTruncatingStore =
false;
14142 Index = VPSN->getIndex();
14143 Mask = VPSN->getMask();
14144 Val = VPSN->getValue();
14145 VL = VPSN->getVectorLength();
14147 IsTruncatingStore =
false;
14151 Index = MSN->getIndex();
14152 Mask = MSN->getMask();
14153 Val = MSN->getValue();
14154 IsTruncatingStore = MSN->isTruncatingStore();
14158 MVT IndexVT =
Index.getSimpleValueType();
14159 MVT XLenVT = Subtarget.getXLenVT();
14162 "Unexpected VTs!");
14163 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
14166 assert(!IsTruncatingStore &&
"Unexpected truncating MSCATTER/VP_SCATTER");
14172 MVT ContainerVT = VT;
14196 IsUnmasked ? Intrinsic::riscv_vsoxei : Intrinsic::riscv_vsoxei_mask;
14198 Ops.push_back(Val);
14199 Ops.push_back(BasePtr);
14200 Ops.push_back(Index);
14202 Ops.push_back(Mask);
14211 const MVT XLenVT = Subtarget.getXLenVT();
14215 SDVTList VTs = DAG.
getVTList(XLenVT, MVT::Other);
14222 static const int Table =
14241 const MVT XLenVT = Subtarget.getXLenVT();
14251 static const unsigned Table =
14266 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14272 const MVT XLenVT = Subtarget.getXLenVT();
14276 SDVTList VTs = DAG.
getVTList(XLenVT, MVT::Other);
14277 return DAG.
getNode(RISCVISD::READ_CSR,
DL, VTs, Chain, SysRegNo);
14282 const MVT XLenVT = Subtarget.getXLenVT();
14289 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14295 const MVT XLenVT = Subtarget.getXLenVT();
14301 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14315 SDValue Result = DAG.
getNode(RISCVISD::READ_CSR,
DL, VTs, Chain, SysRegNo);
14316 Chain = Result.getValue(1);
14322 const MVT XLenVT = Subtarget.getXLenVT();
14332 Chain = DAG.
getNode(RISCVISD::CLEAR_CSR,
DL, MVT::Other, Chain, SysRegNo,
14334 return DAG.
getNode(RISCVISD::SET_CSR,
DL, MVT::Other, Chain, SysRegNo,
14340 const MVT XLenVT = Subtarget.getXLenVT();
14347 return DAG.
getNode(RISCVISD::CLEAR_CSR,
DL, MVT::Other, Chain, SysRegNo,
14355 bool isRISCV64 = Subtarget.is64Bit();
14369 return RISCVISD::SLLW;
14371 return RISCVISD::SRAW;
14373 return RISCVISD::SRLW;
14375 return RISCVISD::DIVW;
14377 return RISCVISD::DIVUW;
14379 return RISCVISD::REMUW;
14381 return RISCVISD::ROLW;
14383 return RISCVISD::RORW;
14419 switch (
N->getOpcode()) {
14421 llvm_unreachable(
"Don't know how to custom type legalize this operation!");
14426 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14427 "Unexpected custom legalisation");
14428 bool IsStrict =
N->isStrictFPOpcode();
14431 SDValue Op0 = IsStrict ?
N->getOperand(1) :
N->getOperand(0);
14440 !Subtarget.hasStdExtZfhOrZhinx()) {
14445 unsigned Opc = IsSigned ? RISCVISD::STRICT_FCVT_W_RV64
14446 : RISCVISD::STRICT_FCVT_WU_RV64;
14449 Opc,
DL, VTs, Chain, Op0,
14458 !Subtarget.hasStdExtZfhOrZhinx()) ||
14460 Op0 = DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, Op0);
14462 unsigned Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
14483 std::tie(Result, Chain) =
14484 makeLibCall(DAG, LC,
N->getValueType(0), Op0, CallOptions,
DL, Chain);
14490 case ISD::LROUND: {
14499 if (Op0.
getValueType() == MVT::f16 && !Subtarget.hasStdExtZfhOrZhinx())
14500 Op0 = DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, Op0);
14503 DAG.
getNode(RISCVISD::FCVT_W_RV64,
DL, MVT::i64, Op0,
14511 RTLIB::Libcall LC =
14512 Op0.
getValueType() == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
14521 case ISD::READCYCLECOUNTER:
14522 case ISD::READSTEADYCOUNTER: {
14523 assert(!Subtarget.is64Bit() &&
"READCYCLECOUNTER/READSTEADYCOUNTER only "
14524 "has custom type legalization on riscv32");
14526 SDValue LoCounter, HiCounter;
14527 MVT XLenVT = Subtarget.getXLenVT();
14528 if (
N->getOpcode() == ISD::READCYCLECOUNTER) {
14537 N->getOperand(0), LoCounter, HiCounter);
14552 if (
N->getValueType(0) == MVT::i64) {
14553 assert(Subtarget.hasStdExtZilsd() && !Subtarget.is64Bit() &&
14554 "Unexpected custom legalisation");
14556 if (!Subtarget.enableUnalignedScalarMem() && Ld->
getAlign() < 8)
14561 RISCVISD::LD_RV32,
DL,
14562 DAG.
getVTList({MVT::i32, MVT::i32, MVT::Other}),
14563 {Ld->getChain(), Ld->getBasePtr()}, MVT::i64, Ld->
getMemOperand());
14567 Results.append({Pair, Result.getValue(2)});
14571 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14572 "Unexpected custom legalisation");
14583 unsigned Size =
N->getSimpleValueType(0).getSizeInBits();
14584 unsigned XLen = Subtarget.getXLen();
14587 assert(
Size == (XLen * 2) &&
"Unexpected custom legalisation");
14595 if (LHSIsU == RHSIsU)
14599 MVT XLenVT = Subtarget.getXLenVT();
14612 if (RHSIsU && LHSIsS && !RHSIsS)
14613 Results.push_back(MakeMULPair(LHS, RHS));
14614 else if (LHSIsU && RHSIsS && !LHSIsS)
14615 Results.push_back(MakeMULPair(RHS, LHS));
14623 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14624 "Unexpected custom legalisation");
14630 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14631 "Unexpected custom legalisation");
14634 if (
N->getOpcode() ==
ISD::SHL && Subtarget.hasStdExtZbs() &&
14659 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14660 "Unexpected custom legalisation");
14661 assert((Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb() ||
14662 Subtarget.hasVendorXTHeadBb()) &&
14663 "Unexpected custom legalization");
14665 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()))
14673 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14674 "Unexpected custom legalisation");
14682 if (IsCTZ && !Subtarget.hasStdExtZbb()) {
14683 assert(Subtarget.hasStdExtP());
14699 unsigned Opc = IsCTZ ? RISCVISD::CTZW : RISCVISD::CLZW;
14707 MVT VT =
N->getSimpleValueType(0);
14708 assert((VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32) &&
14709 Subtarget.is64Bit() && Subtarget.hasStdExtM() &&
14710 "Unexpected custom legalisation");
14722 if (VT != MVT::i32)
14730 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14731 "Unexpected custom legalisation");
14752 EVT OType =
N->getValueType(1);
14764 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14765 "Unexpected custom legalisation");
14782 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1), Res,
14786 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1),
N->getOperand(0),
14793 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1), Res, LHS,
14803 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14804 !Subtarget.hasStdExtZbb() &&
"Unexpected custom legalisation");
14812 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14813 "Unexpected custom legalisation");
14818 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14819 "Unexpected custom legalisation");
14821 if (Subtarget.hasStdExtP()) {
14829 if (Subtarget.hasStdExtZbb()) {
14862 case ISD::BITCAST: {
14863 EVT VT =
N->getValueType(0);
14867 MVT XLenVT = Subtarget.getXLenVT();
14868 if (VT == MVT::i16 &&
14869 ((Op0VT == MVT::f16 && Subtarget.hasStdExtZfhminOrZhinxmin()) ||
14870 (Op0VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
14873 }
else if (VT == MVT::i32 && Op0VT == MVT::f32 && Subtarget.is64Bit() &&
14874 Subtarget.hasStdExtFOrZfinx()) {
14876 DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Op0);
14878 }
else if (VT == MVT::i64 && Op0VT == MVT::f64 && !Subtarget.is64Bit() &&
14879 Subtarget.hasStdExtDOrZdinx()) {
14881 DAG.
getVTList(MVT::i32, MVT::i32), Op0);
14900 assert(
N->getValueType(0) == MVT::i8 && Subtarget.hasStdExtZbkb() &&
14901 "Unexpected custom legalisation");
14902 MVT XLenVT = Subtarget.getXLenVT();
14910 case RISCVISD::BREV8:
14911 case RISCVISD::ORC_B: {
14912 MVT VT =
N->getSimpleValueType(0);
14913 MVT XLenVT = Subtarget.getXLenVT();
14914 assert((VT == MVT::i16 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
14915 "Unexpected custom legalisation");
14916 assert(((
N->getOpcode() == RISCVISD::BREV8 && Subtarget.hasStdExtZbkb()) ||
14917 (
N->getOpcode() == RISCVISD::ORC_B && Subtarget.hasStdExtZbb())) &&
14918 "Unexpected extension");
14944 assert(!Subtarget.is64Bit() &&
N->getValueType(0) == MVT::i64 &&
14946 "Unexpected EXTRACT_VECTOR_ELT legalization");
14949 MVT ContainerVT = VecVT;
14955 MVT XLenVT = Subtarget.getXLenVT();
14964 DAG.
getUNDEF(ContainerVT), Vec, Idx, Mask, VL);
14976 DAG.
getNode(RISCVISD::SRL_VL,
DL, ContainerVT, Vec, ThirtyTwoV,
14977 DAG.
getUNDEF(ContainerVT), Mask, VL);
14985 unsigned IntNo =
N->getConstantOperandVal(0);
14989 "Don't know how to custom type legalize this intrinsic!");
14990 case Intrinsic::experimental_get_vector_length: {
14995 case Intrinsic::experimental_cttz_elts: {
15001 case Intrinsic::riscv_orc_b:
15002 case Intrinsic::riscv_brev8:
15003 case Intrinsic::riscv_sha256sig0:
15004 case Intrinsic::riscv_sha256sig1:
15005 case Intrinsic::riscv_sha256sum0:
15006 case Intrinsic::riscv_sha256sum1:
15007 case Intrinsic::riscv_sm3p0:
15008 case Intrinsic::riscv_sm3p1: {
15009 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15013 case Intrinsic::riscv_orc_b:
Opc = RISCVISD::ORC_B;
break;
15014 case Intrinsic::riscv_brev8:
Opc = RISCVISD::BREV8;
break;
15015 case Intrinsic::riscv_sha256sig0:
Opc = RISCVISD::SHA256SIG0;
break;
15016 case Intrinsic::riscv_sha256sig1:
Opc = RISCVISD::SHA256SIG1;
break;
15017 case Intrinsic::riscv_sha256sum0:
Opc = RISCVISD::SHA256SUM0;
break;
15018 case Intrinsic::riscv_sha256sum1:
Opc = RISCVISD::SHA256SUM1;
break;
15019 case Intrinsic::riscv_sm3p0:
Opc = RISCVISD::SM3P0;
break;
15020 case Intrinsic::riscv_sm3p1:
Opc = RISCVISD::SM3P1;
break;
15029 case Intrinsic::riscv_sm4ks:
15030 case Intrinsic::riscv_sm4ed: {
15032 IntNo == Intrinsic::riscv_sm4ks ? RISCVISD::SM4KS : RISCVISD::SM4ED;
15038 DAG.
getNode(
Opc,
DL, MVT::i64, NewOp0, NewOp1,
N->getOperand(3));
15042 case Intrinsic::riscv_mopr: {
15043 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15048 RISCVISD::MOP_R,
DL, MVT::i64, NewOp,
15053 case Intrinsic::riscv_moprr: {
15054 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15061 RISCVISD::MOP_RR,
DL, MVT::i64, NewOp0, NewOp1,
15066 case Intrinsic::riscv_clmul: {
15067 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15078 case Intrinsic::riscv_clmulh:
15079 case Intrinsic::riscv_clmulr: {
15080 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15100 unsigned Opc = IntNo == Intrinsic::riscv_clmulh ? RISCVISD::CLMULH
15101 : RISCVISD::CLMULR;
15108 case Intrinsic::riscv_vmv_x_s: {
15109 EVT VT =
N->getValueType(0);
15110 MVT XLenVT = Subtarget.getXLenVT();
15111 if (VT.
bitsLT(XLenVT)) {
15114 Subtarget.getXLenVT(),
N->getOperand(1));
15119 assert(VT == MVT::i64 && !Subtarget.is64Bit() &&
15120 "Unexpected custom legalization");
15136 SDValue LShr32 = DAG.
getNode(RISCVISD::SRL_VL,
DL, VecVT, Vec, ThirtyTwoV,
15147 case ISD::VECREDUCE_ADD:
15148 case ISD::VECREDUCE_AND:
15149 case ISD::VECREDUCE_OR:
15150 case ISD::VECREDUCE_XOR:
15151 case ISD::VECREDUCE_SMAX:
15152 case ISD::VECREDUCE_UMAX:
15153 case ISD::VECREDUCE_SMIN:
15154 case ISD::VECREDUCE_UMIN:
15158 case ISD::VP_REDUCE_ADD:
15159 case ISD::VP_REDUCE_AND:
15160 case ISD::VP_REDUCE_OR:
15161 case ISD::VP_REDUCE_XOR:
15162 case ISD::VP_REDUCE_SMAX:
15163 case ISD::VP_REDUCE_UMAX:
15164 case ISD::VP_REDUCE_SMIN:
15165 case ISD::VP_REDUCE_UMIN:
15186 return ISD::VECREDUCE_ADD;
15188 return ISD::VECREDUCE_UMAX;
15190 return ISD::VECREDUCE_SMAX;
15192 return ISD::VECREDUCE_UMIN;
15194 return ISD::VECREDUCE_SMIN;
15196 return ISD::VECREDUCE_AND;
15198 return ISD::VECREDUCE_OR;
15200 return ISD::VECREDUCE_XOR;
15203 return ISD::VECREDUCE_FADD;
15205 return ISD::VECREDUCE_FMAX;
15207 return ISD::VECREDUCE_FMIN;
15233 const EVT VT =
N->getValueType(0);
15234 const unsigned Opc =
N->getOpcode();
15244 if (!
N->getFlags().hasAllowReassociation())
15255 "Inconsistent mappings");
15259 if (!
LHS.hasOneUse() || !
RHS.hasOneUse())
15287 if (0 == std::min(LHSIdx, RHSIdx) && 1 == std::max(LHSIdx, RHSIdx)) {
15290 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
N->getFlags());
15297 if (
LHS.getOpcode() != ReduceOpc)
15311 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
15312 ReduceVec->
getFlags() &
N->getFlags());
15322 auto BinOpToRVVReduce = [](
unsigned Opc) {
15327 return RISCVISD::VECREDUCE_ADD_VL;
15329 return RISCVISD::VECREDUCE_UMAX_VL;
15331 return RISCVISD::VECREDUCE_SMAX_VL;
15333 return RISCVISD::VECREDUCE_UMIN_VL;
15335 return RISCVISD::VECREDUCE_SMIN_VL;
15337 return RISCVISD::VECREDUCE_AND_VL;
15339 return RISCVISD::VECREDUCE_OR_VL;
15341 return RISCVISD::VECREDUCE_XOR_VL;
15343 return RISCVISD::VECREDUCE_FADD_VL;
15345 return RISCVISD::VECREDUCE_FMAX_VL;
15347 return RISCVISD::VECREDUCE_FMIN_VL;
15351 auto IsReduction = [&BinOpToRVVReduce](
SDValue V,
unsigned Opc) {
15354 V.getOperand(0).getOpcode() == BinOpToRVVReduce(
Opc);
15357 unsigned Opc =
N->getOpcode();
15358 unsigned ReduceIdx;
15359 if (IsReduction(
N->getOperand(0),
Opc))
15361 else if (IsReduction(
N->getOperand(1),
Opc))
15367 if (
Opc ==
ISD::FADD && !
N->getFlags().hasAllowReassociation())
15370 SDValue Extract =
N->getOperand(ReduceIdx);
15383 if (ScalarV.
getOpcode() != RISCVISD::VFMV_S_F_VL &&
15384 ScalarV.
getOpcode() != RISCVISD::VMV_S_X_VL &&
15385 ScalarV.
getOpcode() != RISCVISD::VMV_V_X_VL)
15402 SDValue NewStart =
N->getOperand(1 - ReduceIdx);
15435 EVT VT =
N->getValueType(0);
15451 int64_t C0 = N0C->getSExtValue();
15452 int64_t C1 = N1C->getSExtValue();
15453 if (C0 <= 0 || C1 <= 0)
15456 int64_t Diff = std::abs(C0 - C1);
15462 int64_t Bits = std::min(C0, C1);
15494 if (VShift.
slt(1) || VShift.
sgt(3))
15498 EVT VT =
N->getValueType(0);
15518 EVT VT =
N->getValueType(0);
15546 EVT VT =
N->getValueType(0);
15567 Slct.
getOpcode() != RISCVISD::SELECT_CC) ||
15575 bool SwapSelectOps;
15576 unsigned OpOffset = Slct.
getOpcode() == RISCVISD::SELECT_CC ? 2 : 0;
15581 SwapSelectOps =
false;
15582 NonConstantVal = FalseVal;
15584 SwapSelectOps =
true;
15585 NonConstantVal = TrueVal;
15591 FalseVal = DAG.
getNode(
N->getOpcode(),
SDLoc(
N), VT, OtherOp, NonConstantVal);
15596 if (Slct.
getOpcode() == RISCVISD::SELECT_CC)
15639 EVT VT =
N->getValueType(0);
15654 if (!N0C->hasOneUse())
15656 int64_t C0 = N0C->getSExtValue();
15657 int64_t C1 = N1C->getSExtValue();
15659 if (C0 == -1 || C0 == 0 || C0 == 1 ||
isInt<12>(C1))
15666 }
else if ((C1 / C0 + 1) != 0 &&
isInt<12>(C1 / C0 + 1) &&
15670 }
else if ((C1 / C0 - 1) != 0 &&
isInt<12>(C1 / C0 - 1) &&
15698 EVT VT =
N->getValueType(0);
15729 unsigned OuterExtend =
15733 OuterExtend,
SDLoc(
N), VT,
15741 EVT VT =
N->getValueType(0);
15791 EVT VT =
N->getValueType(0);
15801 APInt ImmValMinus1 = N0C->getAPIntValue() - 1;
15811 if (!isIntEqualitySetCC(CCVal) || !SetCCOpVT.
isInteger())
15834 if (!Subtarget.hasStdExtZbb())
15837 EVT VT =
N->getValueType(0);
15839 if (VT != Subtarget.
getXLenVT() && VT != MVT::i32 && VT != MVT::i16)
15851 unsigned ShiftedAmount = 8 - ShAmtCLeft->getZExtValue();
15853 if (ShiftedAmount >= 8)
15857 SDValue RightShiftOperand = N1;
15859 if (ShiftedAmount != 0) {
15863 if (!ShAmtCRight || ShAmtCRight->getZExtValue() != ShiftedAmount)
15872 if (LeftShiftOperand != RightShiftOperand)
15876 Mask <<= ShiftedAmount;
15882 return DAG.
getNode(RISCVISD::ORC_B,
SDLoc(
N), VT, LeftShiftOperand);
15890 EVT VT =
N->getValueType(0);
15922 bool IsAnd =
N->getOpcode() ==
ISD::AND;
15946 EVT VT =
N->getValueType(0);
15970 EVT VT =
N->getValueType(0);
15997 if (CondLHS != True)
16004 if (!CondRHSC || CondRHSC->
getAPIntValue() != (1ULL << ScalarBits))
16016 if (!FalseRHSC || !FalseRHSC->
isZero())
16036 EVT VT =
N->getValueType(0);
16043 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() && VT == MVT::i1 &&
16086 EVT VT =
N->getValueType(0);
16105 EVT WideVT =
X.getValueType();
16132 auto IsEqualCompZero = [](
SDValue &V) ->
bool {
16141 if (!IsEqualCompZero(N0) || !N0.
hasOneUse())
16143 if (!IsEqualCompZero(N0) || !N0.
hasOneUse())
16150 unsigned CzeroOpcode =
16152 ? RISCVISD::CZERO_EQZ
16153 : RISCVISD::CZERO_NEZ;
16155 EVT VT =
N->getValueType(0);
16167 if (N0.
getOpcode() != ISD::ATOMIC_LOAD)
16182 if (Mask != ExpectedMask)
16208 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
16248 if (N0.
getOpcode() != RISCVISD::CZERO_EQZ ||
16249 N1.
getOpcode() != RISCVISD::CZERO_NEZ ||
16267 EVT VT =
N->getValueType(0);
16285 if (!Subtarget.hasVendorXqcibm())
16297 if (
N->getValueType(0) != MVT::i32)
16299 unsigned Width, ShAmt;
16316 return DAG.
getNode(RISCVISD::QC_INSB,
DL, MVT::i32,
Ops);
16321 if (!Subtarget.hasVendorXqcibm())
16331 unsigned ShAmt, Width;
16335 if (
N->getValueType(0) != MVT::i32)
16340 if (Width == 1 && Subtarget.hasStdExtZbs())
16352 return DAG.
getNode(RISCVISD::QC_INSB,
DL, MVT::i32,
Ops);
16360 if (!Subtarget.hasVendorXqcibm())
16366 APInt MaskImm, OrImm;
16385 unsigned ShAmt, Width;
16398 return DAG.
getNode(RISCVISD::QC_INSB,
DL, MVT::i32,
Ops);
16440 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
16455 if (N0.
getOpcode() == RISCVISD::SLLW &&
16459 return DAG.
getNode(RISCVISD::ROLW,
DL, MVT::i64,
16470 const APInt &Imm = ConstN00->getAPIntValue();
16471 if ((Imm + 1).isSignedIntN(12))
16495 EVT VT =
N->getValueType(0);
16504 bool IsAdd = (
E & 3) == 1;
16505 E -= IsAdd ? 1 : -1;
16509 Result = DAG.
getNode(AddSubOp,
DL, VT, Result, ShiftVal);
16519 uint64_t MulAmtLowBit = MulAmt & (-MulAmt);
16524 ShiftAmt1 = MulAmt + MulAmtLowBit;
16527 ShiftAmt1 = MulAmt - MulAmtLowBit;
16531 EVT VT =
N->getValueType(0);
16541 unsigned ShY,
bool AddX,
unsigned Shift) {
16543 EVT VT =
N->getValueType(0);
16555 ShlAdd = DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, ShlAdd,
16565 uint64_t MulAmt,
unsigned Shift) {
16592 assert(ShX != 0 &&
"MulAmt=4,6,10 handled before");
16604 EVT VT =
N->getValueType(0);
16613 bool ShouldExpandMul =
16615 !Subtarget.hasStdExtZmmul();
16616 if (!ShouldExpandMul)
16646 if (Shift >= 1 && Shift <= 3 &&
isPowerOf2_64(MulAmt & (MulAmt - 1))) {
16651 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT,
X,
16658 if (MulAmt > 2 &&
isPowerOf2_64((MulAmt - 1) & (MulAmt - 2))) {
16660 if (ScaleShift >= 1 && ScaleShift < 4) {
16692 if (!Subtarget.hasStdExtZmmul())
16702 EVT VT =
N->getValueType(0);
16709 if (
N->getOperand(0).getOpcode() !=
ISD::AND ||
16710 N->getOperand(0).getOperand(0).getOpcode() !=
ISD::SRL)
16723 if (!V1.
isMask(HalfSize) || V2 != (1ULL | 1ULL << HalfSize) ||
16724 V3 != (HalfSize - 1))
16734 return DAG.
getNode(ISD::BITCAST,
DL, VT, Sra);
16740 EVT VT =
N->getValueType(0);
16748 unsigned AddSubOpc;
16754 auto IsAddSubWith1 = [&](
SDValue V) ->
bool {
16755 AddSubOpc = V->getOpcode();
16767 if (IsAddSubWith1(N0)) {
16769 return DAG.
getNode(AddSubOpc,
DL, VT, N1, MulVal);
16772 if (IsAddSubWith1(N1)) {
16774 return DAG.
getNode(AddSubOpc,
DL, VT, N0, MulVal);
16789 if (isIndexTypeSigned(IndexType))
16792 if (!
N->hasOneUse())
16795 EVT VT =
N.getValueType();
16834 EVT SrcVT = Src.getValueType();
16838 NewElen = std::max(NewElen, 8U);
16865 EVT OpVT =
X.getValueType();
16873 if (OpSize <= Subtarget.
getXLen() ||
16879 auto IsVectorBitCastCheap = [](
SDValue X) {
16882 X.getOpcode() == ISD::LOAD;
16884 if (!IsVectorBitCastCheap(
X) || !IsVectorBitCastCheap(
Y))
16888 Attribute::NoImplicitFloat))
16895 unsigned VecSize = OpSize / 8;
16907 DAG.
getNode(ISD::VP_REDUCE_OR,
DL, XLenVT,
16920 EVT VT =
N->getValueType(0);
16925 if (!isIntEqualitySetCC(
Cond))
16950 if (OpVT == MVT::i64 &&
isUInt<32>(AndRHSInt) &&
16954 if (NewC >= -2048 && NewC <= 2048) {
16960 return DAG.
getSetCC(dl, VT, Shift,
16970 if (OpVT != MVT::i64 || !Subtarget.
is64Bit())
16990 const APInt &C1 = N1C->getAPIntValue();
17008 EVT VT =
N->getValueType(0);
17010 unsigned Opc = Src.getOpcode();
17015 if (
Opc == RISCVISD::FMV_X_ANYEXTH && SrcVT.
bitsGE(MVT::i16) &&
17016 Subtarget.hasStdExtZfhmin())
17017 return DAG.
getNode(RISCVISD::FMV_X_SIGNEXTH,
DL, VT, Src.getOperand(0));
17023 return DAG.
getNode(RISCVISD::SLLW,
DL, VT, Src.getOperand(0),
17024 Src.getOperand(1));
17043struct CombineResult;
17045enum ExtKind : uint8_t {
17077struct NodeExtensionHelper {
17086 bool SupportsFPExt;
17088 bool SupportsBF16Ext;
17091 bool EnforceOneUse;
17101 case RISCVISD::VSEXT_VL:
17102 case RISCVISD::VZEXT_VL:
17103 case RISCVISD::FP_EXTEND_VL:
17106 return OrigOperand;
17112 return OrigOperand.
getOpcode() == RISCVISD::VMV_V_X_VL ||
17117 unsigned getExtOpc(ExtKind SupportsExt)
const {
17118 switch (SupportsExt) {
17119 case ExtKind::SExt:
17120 return RISCVISD::VSEXT_VL;
17121 case ExtKind::ZExt:
17122 return RISCVISD::VZEXT_VL;
17123 case ExtKind::FPExt:
17124 case ExtKind::BF16Ext:
17125 return RISCVISD::FP_EXTEND_VL;
17133 SDValue getOrCreateExtendedOp(SDNode *Root, SelectionDAG &DAG,
17134 const RISCVSubtarget &Subtarget,
17135 std::optional<ExtKind> SupportsExt)
const {
17136 if (!SupportsExt.has_value())
17137 return OrigOperand;
17139 MVT NarrowVT = getNarrowType(Root, *SupportsExt);
17143 if (
Source.getValueType() == NarrowVT)
17146 unsigned ExtOpc = getExtOpc(*SupportsExt);
17149 SDLoc
DL(OrigOperand);
17150 auto [
Mask, VL] = getMaskAndVL(Root, DAG, Subtarget);
17154 case RISCVISD::VSEXT_VL:
17155 case RISCVISD::VZEXT_VL:
17156 case RISCVISD::FP_EXTEND_VL:
17157 return DAG.
getNode(ExtOpc,
DL, NarrowVT, Source, Mask, VL);
17160 case RISCVISD::VMV_V_X_VL:
17161 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, NarrowVT,
17163 case RISCVISD::VFMV_V_F_VL:
17165 assert(
Source.getOpcode() == ISD::FP_EXTEND &&
"Unexpected source");
17168 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL, NarrowVT,
17169 DAG.
getUNDEF(NarrowVT), Source, VL);
17182 static MVT getNarrowType(
const SDNode *Root, ExtKind SupportsExt) {
17188 MVT EltVT = SupportsExt == ExtKind::BF16Ext ? MVT::bf16
17189 : SupportsExt == ExtKind::FPExt
17191 : MVT::getIntegerVT(NarrowSize);
17193 assert((
int)NarrowSize >= (SupportsExt == ExtKind::FPExt ? 16 : 8) &&
17194 "Trying to extend something we can't represent");
17201 static unsigned getSExtOpcode(
unsigned Opcode) {
17204 case RISCVISD::ADD_VL:
17205 case RISCVISD::VWADD_W_VL:
17206 case RISCVISD::VWADDU_W_VL:
17208 case RISCVISD::OR_VL:
17209 return RISCVISD::VWADD_VL;
17211 case RISCVISD::SUB_VL:
17212 case RISCVISD::VWSUB_W_VL:
17213 case RISCVISD::VWSUBU_W_VL:
17214 return RISCVISD::VWSUB_VL;
17216 case RISCVISD::MUL_VL:
17217 return RISCVISD::VWMUL_VL;
17225 static unsigned getZExtOpcode(
unsigned Opcode) {
17228 case RISCVISD::ADD_VL:
17229 case RISCVISD::VWADD_W_VL:
17230 case RISCVISD::VWADDU_W_VL:
17232 case RISCVISD::OR_VL:
17233 return RISCVISD::VWADDU_VL;
17235 case RISCVISD::SUB_VL:
17236 case RISCVISD::VWSUB_W_VL:
17237 case RISCVISD::VWSUBU_W_VL:
17238 return RISCVISD::VWSUBU_VL;
17240 case RISCVISD::MUL_VL:
17241 return RISCVISD::VWMULU_VL;
17243 case RISCVISD::SHL_VL:
17244 return RISCVISD::VWSLL_VL;
17252 static unsigned getFPExtOpcode(
unsigned Opcode) {
17254 case RISCVISD::FADD_VL:
17255 case RISCVISD::VFWADD_W_VL:
17256 return RISCVISD::VFWADD_VL;
17257 case RISCVISD::FSUB_VL:
17258 case RISCVISD::VFWSUB_W_VL:
17259 return RISCVISD::VFWSUB_VL;
17260 case RISCVISD::FMUL_VL:
17261 return RISCVISD::VFWMUL_VL;
17262 case RISCVISD::VFMADD_VL:
17263 return RISCVISD::VFWMADD_VL;
17264 case RISCVISD::VFMSUB_VL:
17265 return RISCVISD::VFWMSUB_VL;
17266 case RISCVISD::VFNMADD_VL:
17267 return RISCVISD::VFWNMADD_VL;
17268 case RISCVISD::VFNMSUB_VL:
17269 return RISCVISD::VFWNMSUB_VL;
17277 static unsigned getSUOpcode(
unsigned Opcode) {
17279 "SU is only supported for MUL");
17280 return RISCVISD::VWMULSU_VL;
17285 static unsigned getWOpcode(
unsigned Opcode, ExtKind SupportsExt) {
17288 case RISCVISD::ADD_VL:
17290 case RISCVISD::OR_VL:
17291 return SupportsExt == ExtKind::SExt ? RISCVISD::VWADD_W_VL
17292 : RISCVISD::VWADDU_W_VL;
17294 case RISCVISD::SUB_VL:
17295 return SupportsExt == ExtKind::SExt ? RISCVISD::VWSUB_W_VL
17296 : RISCVISD::VWSUBU_W_VL;
17297 case RISCVISD::FADD_VL:
17298 return RISCVISD::VFWADD_W_VL;
17299 case RISCVISD::FSUB_VL:
17300 return RISCVISD::VFWSUB_W_VL;
17306 using CombineToTry = std::function<std::optional<CombineResult>(
17307 SDNode * ,
const NodeExtensionHelper & ,
17308 const NodeExtensionHelper & , SelectionDAG &,
17309 const RISCVSubtarget &)>;
17312 bool needToPromoteOtherUsers()
const {
return EnforceOneUse; }
17314 void fillUpExtensionSupportForSplat(SDNode *Root, SelectionDAG &DAG,
17315 const RISCVSubtarget &Subtarget) {
17320 "Unexpected Opcode");
17333 unsigned ScalarBits =
Op.getValueSizeInBits();
17335 if (ScalarBits < EltBits) {
17337 assert(
Opc == RISCVISD::VMV_V_X_VL && EltBits == 64 && ScalarBits == 32 &&
17338 !Subtarget.
is64Bit() &&
"Unexpected splat");
17340 SupportsSExt =
true;
17344 SupportsZExt =
true;
17346 EnforceOneUse =
false;
17350 unsigned NarrowSize = EltBits / 2;
17353 if (NarrowSize < 8)
17357 SupportsSExt =
true;
17361 SupportsZExt =
true;
17363 EnforceOneUse =
false;
17366 bool isSupportedFPExtend(MVT NarrowEltVT,
const RISCVSubtarget &Subtarget) {
17367 return (NarrowEltVT == MVT::f32 ||
17371 bool isSupportedBF16Extend(MVT NarrowEltVT,
const RISCVSubtarget &Subtarget) {
17372 return NarrowEltVT == MVT::bf16 && Subtarget.hasStdExtZvfbfwma();
17377 void fillUpExtensionSupport(SDNode *Root, SelectionDAG &DAG,
17378 const RISCVSubtarget &Subtarget) {
17379 SupportsZExt =
false;
17380 SupportsSExt =
false;
17381 SupportsFPExt =
false;
17382 SupportsBF16Ext =
false;
17383 EnforceOneUse =
true;
17405 case RISCVISD::VZEXT_VL:
17406 SupportsZExt =
true;
17408 case RISCVISD::VSEXT_VL:
17409 SupportsSExt =
true;
17411 case RISCVISD::FP_EXTEND_VL: {
17414 if (isSupportedFPExtend(NarrowEltVT, Subtarget))
17415 SupportsFPExt =
true;
17416 if (isSupportedBF16Extend(NarrowEltVT, Subtarget))
17417 SupportsBF16Ext =
true;
17422 case RISCVISD::VMV_V_X_VL:
17423 fillUpExtensionSupportForSplat(Root, DAG, Subtarget);
17425 case RISCVISD::VFMV_V_F_VL: {
17432 if (
Op.getOpcode() != ISD::FP_EXTEND)
17436 unsigned ScalarBits =
Op.getOperand(0).getValueSizeInBits();
17437 if (NarrowSize != ScalarBits)
17440 if (isSupportedFPExtend(
Op.getOperand(0).getSimpleValueType(), Subtarget))
17441 SupportsFPExt =
true;
17442 if (isSupportedBF16Extend(
Op.getOperand(0).getSimpleValueType(),
17444 SupportsBF16Ext =
true;
17453 static bool isSupportedRoot(
const SDNode *Root,
17454 const RISCVSubtarget &Subtarget) {
17466 case RISCVISD::ADD_VL:
17467 case RISCVISD::MUL_VL:
17468 case RISCVISD::VWADD_W_VL:
17469 case RISCVISD::VWADDU_W_VL:
17470 case RISCVISD::SUB_VL:
17471 case RISCVISD::VWSUB_W_VL:
17472 case RISCVISD::VWSUBU_W_VL:
17474 case RISCVISD::FADD_VL:
17475 case RISCVISD::FSUB_VL:
17476 case RISCVISD::FMUL_VL:
17477 case RISCVISD::VFWADD_W_VL:
17478 case RISCVISD::VFWSUB_W_VL:
17480 case RISCVISD::OR_VL:
17484 Subtarget.hasStdExtZvbb();
17485 case RISCVISD::SHL_VL:
17486 return Subtarget.hasStdExtZvbb();
17487 case RISCVISD::VFMADD_VL:
17488 case RISCVISD::VFNMSUB_VL:
17489 case RISCVISD::VFNMADD_VL:
17490 case RISCVISD::VFMSUB_VL:
17498 NodeExtensionHelper(SDNode *Root,
unsigned OperandIdx, SelectionDAG &DAG,
17499 const RISCVSubtarget &Subtarget) {
17500 assert(isSupportedRoot(Root, Subtarget) &&
17501 "Trying to build an helper with an "
17502 "unsupported root");
17503 assert(OperandIdx < 2 &&
"Requesting something else than LHS or RHS");
17513 case RISCVISD::VWADD_W_VL:
17514 case RISCVISD::VWADDU_W_VL:
17515 case RISCVISD::VWSUB_W_VL:
17516 case RISCVISD::VWSUBU_W_VL:
17517 case RISCVISD::VFWADD_W_VL:
17518 case RISCVISD::VFWSUB_W_VL:
17520 if (OperandIdx == 1)
17524 fillUpExtensionSupport(Root, DAG, Subtarget);
17530 static std::pair<SDValue, SDValue>
17531 getMaskAndVL(
const SDNode *Root, SelectionDAG &DAG,
17532 const RISCVSubtarget &Subtarget) {
17533 assert(isSupportedRoot(Root, Subtarget) &&
"Unexpected root");
17552 switch (
N->getOpcode()) {
17556 case RISCVISD::ADD_VL:
17557 case RISCVISD::MUL_VL:
17558 case RISCVISD::OR_VL:
17559 case RISCVISD::FADD_VL:
17560 case RISCVISD::FMUL_VL:
17561 case RISCVISD::VFMADD_VL:
17562 case RISCVISD::VFNMSUB_VL:
17563 case RISCVISD::VFNMADD_VL:
17564 case RISCVISD::VFMSUB_VL:
17566 case RISCVISD::VWADD_W_VL:
17567 case RISCVISD::VWADDU_W_VL:
17569 case RISCVISD::SUB_VL:
17570 case RISCVISD::VWSUB_W_VL:
17571 case RISCVISD::VWSUBU_W_VL:
17572 case RISCVISD::VFWADD_W_VL:
17573 case RISCVISD::FSUB_VL:
17574 case RISCVISD::VFWSUB_W_VL:
17576 case RISCVISD::SHL_VL:
17595struct CombineResult {
17597 unsigned TargetOpcode;
17599 std::optional<ExtKind> LHSExt;
17600 std::optional<ExtKind> RHSExt;
17604 NodeExtensionHelper
LHS;
17606 NodeExtensionHelper
RHS;
17608 CombineResult(
unsigned TargetOpcode, SDNode *Root,
17609 const NodeExtensionHelper &
LHS, std::optional<ExtKind> LHSExt,
17610 const NodeExtensionHelper &
RHS, std::optional<ExtKind> RHSExt)
17611 : TargetOpcode(TargetOpcode), LHSExt(LHSExt), RHSExt(RHSExt), Root(Root),
17617 SDValue materialize(SelectionDAG &DAG,
17618 const RISCVSubtarget &Subtarget)
const {
17620 std::tie(Mask, VL) =
17621 NodeExtensionHelper::getMaskAndVL(Root, DAG, Subtarget);
17635 LHS.getOrCreateExtendedOp(Root, DAG, Subtarget, LHSExt),
17636 RHS.getOrCreateExtendedOp(Root, DAG, Subtarget, RHSExt),
17637 Passthru, Mask, VL);
17651static std::optional<CombineResult>
17652canFoldToVWWithSameExtensionImpl(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17653 const NodeExtensionHelper &
RHS,
17656 if ((AllowExtMask & ExtKind::ZExt) &&
LHS.SupportsZExt &&
RHS.SupportsZExt)
17657 return CombineResult(NodeExtensionHelper::getZExtOpcode(Root->
getOpcode()),
17658 Root,
LHS, {ExtKind::ZExt},
RHS,
17660 if ((AllowExtMask & ExtKind::SExt) &&
LHS.SupportsSExt &&
RHS.SupportsSExt)
17661 return CombineResult(NodeExtensionHelper::getSExtOpcode(Root->
getOpcode()),
17662 Root,
LHS, {ExtKind::SExt},
RHS,
17664 if ((AllowExtMask & ExtKind::FPExt) &&
LHS.SupportsFPExt &&
RHS.SupportsFPExt)
17665 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
17666 Root,
LHS, {ExtKind::FPExt},
RHS,
17668 if ((AllowExtMask & ExtKind::BF16Ext) &&
LHS.SupportsBF16Ext &&
17669 RHS.SupportsBF16Ext)
17670 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
17671 Root,
LHS, {ExtKind::BF16Ext},
RHS,
17672 {ExtKind::BF16Ext});
17673 return std::nullopt;
17682static std::optional<CombineResult>
17683canFoldToVWWithSameExtension(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17686 return canFoldToVWWithSameExtensionImpl(
17687 Root,
LHS,
RHS, ExtKind::ZExt | ExtKind::SExt | ExtKind::FPExt, DAG,
17695static std::optional<CombineResult>
17696canFoldToVWWithSameExtZEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17699 return canFoldToVWWithSameExtensionImpl(Root,
LHS,
RHS, ExtKind::ZExt, DAG,
17707static std::optional<CombineResult>
17708canFoldToVWWithSameExtBF16(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17711 return canFoldToVWWithSameExtensionImpl(Root,
LHS,
RHS, ExtKind::BF16Ext, DAG,
17719static std::optional<CombineResult>
17720canFoldToVW_W(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17723 if (
RHS.SupportsFPExt)
17724 return CombineResult(
17725 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::FPExt),
17726 Root,
LHS, std::nullopt,
RHS, {ExtKind::FPExt});
17733 return CombineResult(
17734 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::ZExt), Root,
17735 LHS, std::nullopt,
RHS, {ExtKind::ZExt});
17737 return CombineResult(
17738 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::SExt), Root,
17739 LHS, std::nullopt,
RHS, {ExtKind::SExt});
17740 return std::nullopt;
17747static std::optional<CombineResult>
17748canFoldToVWWithSEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17751 if (
LHS.SupportsSExt)
17752 return CombineResult(NodeExtensionHelper::getSExtOpcode(Root->
getOpcode()),
17753 Root,
LHS, {ExtKind::SExt},
RHS,
17755 return std::nullopt;
17762static std::optional<CombineResult>
17763canFoldToVWWithZEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17766 if (
LHS.SupportsZExt)
17767 return CombineResult(NodeExtensionHelper::getZExtOpcode(Root->
getOpcode()),
17768 Root,
LHS, {ExtKind::ZExt},
RHS,
17770 return std::nullopt;
17777static std::optional<CombineResult>
17778canFoldToVWWithFPEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17781 if (
LHS.SupportsFPExt)
17782 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
17783 Root,
LHS, {ExtKind::FPExt},
RHS,
17785 return std::nullopt;
17792static std::optional<CombineResult>
17793canFoldToVW_SU(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17797 if (!
LHS.SupportsSExt || !
RHS.SupportsZExt)
17798 return std::nullopt;
17799 return CombineResult(NodeExtensionHelper::getSUOpcode(Root->
getOpcode()),
17800 Root,
LHS, {ExtKind::SExt},
RHS,
17805NodeExtensionHelper::getSupportedFoldings(
const SDNode *Root) {
17811 case RISCVISD::ADD_VL:
17812 case RISCVISD::SUB_VL:
17813 case RISCVISD::OR_VL:
17814 case RISCVISD::FADD_VL:
17815 case RISCVISD::FSUB_VL:
17817 Strategies.
push_back(canFoldToVWWithSameExtension);
17821 case RISCVISD::FMUL_VL:
17822 case RISCVISD::VFMADD_VL:
17823 case RISCVISD::VFMSUB_VL:
17824 case RISCVISD::VFNMADD_VL:
17825 case RISCVISD::VFNMSUB_VL:
17826 Strategies.
push_back(canFoldToVWWithSameExtension);
17827 if (Root->
getOpcode() == RISCVISD::VFMADD_VL)
17828 Strategies.
push_back(canFoldToVWWithSameExtBF16);
17831 case RISCVISD::MUL_VL:
17833 Strategies.
push_back(canFoldToVWWithSameExtension);
17838 case RISCVISD::SHL_VL:
17840 Strategies.
push_back(canFoldToVWWithSameExtZEXT);
17842 case RISCVISD::VWADD_W_VL:
17843 case RISCVISD::VWSUB_W_VL:
17845 Strategies.
push_back(canFoldToVWWithSEXT);
17847 case RISCVISD::VWADDU_W_VL:
17848 case RISCVISD::VWSUBU_W_VL:
17850 Strategies.
push_back(canFoldToVWWithZEXT);
17852 case RISCVISD::VFWADD_W_VL:
17853 case RISCVISD::VFWSUB_W_VL:
17855 Strategies.
push_back(canFoldToVWWithFPEXT);
17866 assert(
N->getOpcode() == RISCVISD::ADD_VL);
17869 SDValue Passthru =
N->getOperand(2);
17903 if (!NodeExtensionHelper::isSupportedRoot(
N, Subtarget))
17910 Inserted.insert(
N);
17913 while (!Worklist.
empty()) {
17916 NodeExtensionHelper
LHS(Root, 0, DAG, Subtarget);
17917 NodeExtensionHelper
RHS(Root, 1, DAG, Subtarget);
17918 auto AppendUsersIfNeeded =
17919 [&Worklist, &Subtarget, &Inserted,
17920 &ExtensionsToRemove](
const NodeExtensionHelper &
Op) {
17921 if (
Op.needToPromoteOtherUsers()) {
17923 ExtensionsToRemove.
insert(
Op.OrigOperand.getNode());
17926 if (!NodeExtensionHelper::isSupportedRoot(TheUser, Subtarget))
17931 if (Inserted.insert(TheUser).second)
17944 NodeExtensionHelper::getSupportedFoldings(Root);
17946 assert(!FoldingStrategies.
empty() &&
"Nothing to be folded");
17947 bool Matched =
false;
17948 for (
int Attempt = 0;
17949 (Attempt != 1 + NodeExtensionHelper::isCommutative(Root)) && !Matched;
17952 for (NodeExtensionHelper::CombineToTry FoldingStrategy :
17953 FoldingStrategies) {
17954 std::optional<CombineResult> Res =
17955 FoldingStrategy(Root,
LHS,
RHS, DAG, Subtarget);
17959 if (!Res->LHSExt.has_value() &&
17960 ExtensionsToRemove.
contains(
LHS.OrigOperand.getNode()))
17962 if (!Res->RHSExt.has_value() &&
17963 ExtensionsToRemove.
contains(
RHS.OrigOperand.getNode()))
17971 if (Res->LHSExt.has_value())
17972 if (!AppendUsersIfNeeded(
LHS))
17974 if (Res->RHSExt.has_value())
17975 if (!AppendUsersIfNeeded(
RHS))
17987 SDValue InputRootReplacement;
17994 for (CombineResult Res : CombinesToApply) {
17995 SDValue NewValue = Res.materialize(DAG, Subtarget);
17996 if (!InputRootReplacement) {
17998 "First element is expected to be the current node");
17999 InputRootReplacement = NewValue;
18004 for (std::pair<SDValue, SDValue> OldNewValues : ValuesToReplace) {
18008 return InputRootReplacement;
18015 unsigned Opc =
N->getOpcode();
18016 assert(
Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWADDU_W_VL ||
18017 Opc == RISCVISD::VWSUB_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL);
18020 SDValue MergeOp =
N->getOperand(1);
18021 unsigned MergeOpc = MergeOp.
getOpcode();
18023 if (MergeOpc != RISCVISD::VMERGE_VL && MergeOpc !=
ISD::VSELECT)
18032 SDValue Passthru =
N->getOperand(2);
18038 if (Mask.getOpcode() != RISCVISD::VMSET_VL)
18046 Z = Z.getOperand(1);
18052 {Y, X, Y, MergeOp->getOperand(0), N->getOperand(4)},
18059 [[maybe_unused]]
unsigned Opc =
N->getOpcode();
18060 assert(
Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWADDU_W_VL ||
18061 Opc == RISCVISD::VWSUB_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL);
18088 EVT NewMemVT = (MemVT == MVT::i32) ? MVT::i64 : MVT::i128;
18093 if (LSNode1->
getOpcode() == ISD::LOAD) {
18096 if (MemVT == MVT::i32)
18097 Opcode = (Ext ==
ISD::ZEXTLOAD) ? RISCVISD::TH_LWUD : RISCVISD::TH_LWD;
18099 Opcode = RISCVISD::TH_LDD;
18102 Opcode,
SDLoc(LSNode1), DAG.
getVTList({XLenVT, XLenVT, MVT::Other}),
18103 {LSNode1->getChain(), BasePtr,
18104 DAG.getConstant(Imm, SDLoc(LSNode1), XLenVT)},
18115 unsigned Opcode = (MemVT == MVT::i32) ? RISCVISD::TH_SWD : RISCVISD::TH_SDD;
18119 {LSNode1->getChain(), LSNode1->getOperand(1), LSNode2->getOperand(1),
18120 BasePtr, DAG.getConstant(Imm, SDLoc(LSNode1), XLenVT)},
18137 if (!Subtarget.hasVendorXTHeadMemPair())
18142 unsigned OpNum = LSNode1->
getOpcode() == ISD::LOAD ? 1 : 2;
18149 auto ExtractBaseAndOffset = [](
SDValue Ptr) -> std::pair<SDValue, uint64_t> {
18152 return {
Ptr->getOperand(0), C1->getZExtValue()};
18156 auto [Base1, Offset1] = ExtractBaseAndOffset(LSNode1->
getOperand(OpNum));
18177 auto [Base2, Offset2] = ExtractBaseAndOffset(LSNode2->
getOperand(OpNum));
18180 if (Base1 != Base2)
18184 bool Valid =
false;
18185 if (MemVT == MVT::i32) {
18189 }
else if (MemVT == MVT::i64) {
18225 if (Src->isStrictFPOpcode())
18233 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
18243 EVT VT =
N->getValueType(0);
18246 MVT SrcVT = Src.getSimpleValueType();
18247 MVT SrcContainerVT = SrcVT;
18275 IsSigned ? RISCVISD::VFCVT_RTZ_X_F_VL : RISCVISD::VFCVT_RTZ_XU_F_VL;
18276 FpToInt = DAG.
getNode(
Opc,
DL, ContainerVT, XVal, Mask, VL);
18279 IsSigned ? RISCVISD::VFCVT_RM_X_F_VL : RISCVISD::VFCVT_RM_XU_F_VL;
18280 FpToInt = DAG.
getNode(
Opc,
DL, ContainerVT, XVal, Mask,
18293 if (VT != MVT::i32 && VT != XLenVT)
18298 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
18300 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
18323 EVT DstVT =
N->getValueType(0);
18324 if (DstVT != XLenVT)
18330 if (Src->isStrictFPOpcode())
18338 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
18350 if (SatVT == DstVT)
18351 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
18352 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
18353 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
18358 Src = Src.getOperand(0);
18366 if (
Opc == RISCVISD::FCVT_WU_RV64)
18379 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected extension");
18385 EVT VT =
N->getValueType(0);
18391 return DAG.
getNode(RISCVISD::BREV8,
DL, VT, Src.getOperand(0));
18404 EVT LoadVT = VPLoad->getValueType(0);
18408 N->getOperand(2) != VPLoad->getVectorLength() ||
18409 !
N->getOperand(0).hasOneUse())
18416 SDValue LoadMask = VPLoad->getMask();
18421 if (LoadMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
18423 LoadMask.
getOperand(2) != VPLoad->getVectorLength())
18431 SDValue NumElem = VPLoad->getVectorLength();
18432 uint64_t ElemWidthByte = VPLoad->getValueType(0).getScalarSizeInBits() / 8;
18444 PtrInfo, VPLoad->getMemOperand()->getFlags(),
18448 LoadVT,
DL, VPLoad->getChain(),
Base, Stride, LoadMask,
18449 VPLoad->getVectorLength(), MMO, VPLoad->isExpandingLoad());
18463 if (VPStore->getValue().getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE)
18466 SDValue VPReverse = VPStore->getValue();
18472 VPStore->getVectorLength() != VPReverse.
getOperand(2) ||
18476 SDValue StoreMask = VPStore->getMask();
18481 if (StoreMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
18483 StoreMask.
getOperand(2) != VPStore->getVectorLength())
18491 SDValue NumElem = VPStore->getVectorLength();
18505 PtrInfo, VPStore->getMemOperand()->getFlags(),
18510 VPStore->getOffset(), Stride, StoreMask, VPStore->getVectorLength(),
18511 VPStore->getMemoryVT(), MMO, VPStore->getAddressingMode(),
18512 VPStore->isTruncatingStore(), VPStore->isCompressingStore());
18524 EVT VT =
N->getValueType(0);
18536 if (In.getOpcode() != ISD::VP_SRL || In.getOperand(2) != Mask ||
18537 In.getOperand(3) != VL)
18546 if (
LHS.getOpcode() != ISD::VP_ADD ||
LHS.getOperand(2) != Mask ||
18547 LHS.getOperand(3) != VL)
18554 if (V.getOpcode() != ISD::VP_ADD || V.getOperand(2) != Mask ||
18555 V.getOperand(3) != VL)
18558 Operands[0] =
Other;
18567 if (!FindAdd(LHS0, LHS1) && !FindAdd(LHS1, LHS0))
18574 if (
I == std::end(Operands))
18581 if (
Op.getOpcode() != ISD::VP_ZERO_EXTEND ||
Op.getOperand(1) != Mask ||
18582 Op.getOperand(2) != VL)
18592 Operands[0].getOperand(0), Mask, VL);
18594 Operands[1].getOperand(0), Mask, VL);
18598 return DAG.
getNode(RISCVISD::AVGCEILU_VL,
DL, VT,
18599 {NewOp0, NewOp1, DAG.
getUNDEF(VT), Mask, VL});
18611 case RISCVISD::VFMADD_VL: Opcode = RISCVISD::VFNMSUB_VL;
break;
18612 case RISCVISD::VFNMSUB_VL: Opcode = RISCVISD::VFMADD_VL;
break;
18613 case RISCVISD::VFNMADD_VL: Opcode = RISCVISD::VFMSUB_VL;
break;
18614 case RISCVISD::VFMSUB_VL: Opcode = RISCVISD::VFNMADD_VL;
break;
18615 case RISCVISD::STRICT_VFMADD_VL: Opcode = RISCVISD::STRICT_VFNMSUB_VL;
break;
18616 case RISCVISD::STRICT_VFNMSUB_VL: Opcode = RISCVISD::STRICT_VFMADD_VL;
break;
18617 case RISCVISD::STRICT_VFNMADD_VL: Opcode = RISCVISD::STRICT_VFMSUB_VL;
break;
18618 case RISCVISD::STRICT_VFMSUB_VL: Opcode = RISCVISD::STRICT_VFNMADD_VL;
break;
18628 case RISCVISD::VFMADD_VL: Opcode = RISCVISD::VFMSUB_VL;
break;
18629 case RISCVISD::VFMSUB_VL: Opcode = RISCVISD::VFMADD_VL;
break;
18630 case RISCVISD::VFNMADD_VL: Opcode = RISCVISD::VFNMSUB_VL;
break;
18631 case RISCVISD::VFNMSUB_VL: Opcode = RISCVISD::VFNMADD_VL;
break;
18632 case RISCVISD::STRICT_VFMADD_VL: Opcode = RISCVISD::STRICT_VFMSUB_VL;
break;
18633 case RISCVISD::STRICT_VFMSUB_VL: Opcode = RISCVISD::STRICT_VFMADD_VL;
break;
18634 case RISCVISD::STRICT_VFNMADD_VL: Opcode = RISCVISD::STRICT_VFNMSUB_VL;
break;
18635 case RISCVISD::STRICT_VFNMSUB_VL: Opcode = RISCVISD::STRICT_VFNMADD_VL;
break;
18648 unsigned Offset = IsStrict ? 1 : 0;
18655 auto invertIfNegative = [&Mask, &VL](
SDValue &V) {
18656 if (V.getOpcode() == RISCVISD::FNEG_VL && V.getOperand(1) == Mask &&
18657 V.getOperand(2) == VL) {
18659 V = V.getOperand(0);
18666 bool NegA = invertIfNegative(
A);
18667 bool NegB = invertIfNegative(
B);
18668 bool NegC = invertIfNegative(
C);
18671 if (!NegA && !NegB && !NegC)
18677 {N->getOperand(0), A, B, C, Mask, VL});
18701 EVT VT =
N->getValueType(0);
18708 uint64_t ShAmt =
N->getConstantOperandVal(1);
18721 if (LShAmt < ExtSize) {
18734 if (ShAmt > 32 || VT != MVT::i64)
18764 U->getConstantOperandVal(1) > 32)
18819 if (!
Cond.hasOneUse())
18838 EVT VT =
Cond.getValueType();
18883 LHS =
LHS.getOperand(0);
18893 LHS.getOperand(0).getValueType() == Subtarget.
getXLenVT()) {
18901 RHS =
LHS.getOperand(1);
18902 LHS =
LHS.getOperand(0);
18911 auto isXorImmediate = [](
const SDValue &
Op) ->
bool {
18913 return isInt<12>(XorCnst->getSExtValue());
18917 auto singleBitOp = [&DAG](
const SDValue &VarOp,
18918 const SDValue &ConstOp) ->
bool {
18921 return (XorCnst->getSExtValue() == 1) &&
18926 auto onlyUsedBySelectOrBR = [](
const SDValue &
Op) ->
bool {
18927 for (
const SDNode *UserNode :
Op->users()) {
18928 const unsigned Opcode = UserNode->getOpcode();
18929 if (Opcode != RISCVISD::SELECT_CC && Opcode != RISCVISD::BR_CC)
18934 auto isFoldableXorEq = [isXorImmediate, singleBitOp, onlyUsedBySelectOrBR](
18937 (!isXorImmediate(
LHS.getOperand(1)) ||
18938 singleBitOp(
LHS.getOperand(0),
LHS.getOperand(1)) ||
18939 onlyUsedBySelectOrBR(
LHS));
18942 if (isFoldableXorEq(
LHS,
RHS)) {
18943 RHS =
LHS.getOperand(1);
18944 LHS =
LHS.getOperand(0);
18970 if (Subtarget.hasVendorXAndesPerf()) {
18980 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
19023 bool Commutative =
true;
19024 unsigned Opc = TrueVal.getOpcode();
19034 Commutative =
false;
19044 if (!TrueVal.hasOneUse())
19048 if (FalseVal == TrueVal.getOperand(0))
19050 else if (Commutative && FalseVal == TrueVal.getOperand(1))
19055 EVT VT =
N->getValueType(0);
19057 SDValue OtherOp = TrueVal.getOperand(1 - OpToFold);
19063 assert(IdentityOperand &&
"No identity operand!");
19068 DAG.
getSelect(
DL, OtherOpVT,
N->getOperand(0), OtherOp, IdentityOperand);
19069 return DAG.
getNode(TrueVal.getOpcode(),
DL, VT, FalseVal, NewSel);
19090 CountZeroes =
N->getOperand(2);
19091 ValOnZero =
N->getOperand(1);
19093 CountZeroes =
N->getOperand(1);
19094 ValOnZero =
N->getOperand(2);
19113 if (
Cond->getOperand(0) != CountZeroesArgument)
19132 CountZeroes, BitWidthMinusOne);
19142 EVT VT =
N->getValueType(0);
19143 EVT CondVT =
Cond.getValueType();
19151 (Subtarget.
hasCZEROLike() || Subtarget.hasVendorXTHeadCondMov())) {
19157 const APInt &MaskVal =
LHS.getConstantOperandAPInt(1);
19168 if (!TrueVal.hasOneUse() || !FalseVal.hasOneUse())
19172 if (TrueVal.getOpcode() ==
ISD::SUB && FalseVal.getOpcode() ==
ISD::ADD) {
19180 SDValue A = FalseVal.getOperand(0);
19181 SDValue B = FalseVal.getOperand(1);
19183 return ((TrueVal.getOperand(0) ==
A && TrueVal.getOperand(1) ==
B) ||
19184 (TrueVal.getOperand(1) ==
A && TrueVal.getOperand(0) ==
B));
19192 EVT VT =
N->getValueType(0);
19194 SDValue TrueVal =
N->getOperand(1);
19195 SDValue FalseVal =
N->getOperand(2);
19225 SDValue TrueVal =
N->getOperand(1);
19226 SDValue FalseVal =
N->getOperand(2);
19241 EVT VT =
N->getValueType(0);
19248 const unsigned Opcode =
N->op_begin()->getNode()->getOpcode();
19263 if (
Op.isUndef()) {
19276 if (
Op.getOpcode() != Opcode || !
Op.hasOneUse())
19285 if (
Op.getOperand(0).getValueType() !=
Op.getOperand(1).getValueType())
19309 EVT AVT =
A.getValueType();
19310 EVT BVT =
B.getValueType();
19340 if (AOpt || BOpt) {
19358 EVT OpVT =
A.getValueType();
19366 IsSigned ? ISD::PARTIAL_REDUCE_SMLA : ISD::PARTIAL_REDUCE_UMLA;
19380 EVT OpVT =
A.getOperand(0).getValueType();
19382 OpVT !=
B.getOperand(0).getValueType() ||
19388 Opc = ISD::PARTIAL_REDUCE_SMLA;
19391 Opc = ISD::PARTIAL_REDUCE_UMLA;
19394 Opc = ISD::PARTIAL_REDUCE_SUMLA;
19397 Opc = ISD::PARTIAL_REDUCE_SUMLA;
19411 if (!Subtarget.hasStdExtZvqdotq())
19415 EVT VT =
N->getValueType(0);
19418 return DAG.
getNode(ISD::VECREDUCE_ADD,
DL, VT, V);
19440 const unsigned InVecOpcode = InVec->
getOpcode();
19457 InVecLHS, InValLHS, EltNo);
19459 InVecRHS, InValRHS, EltNo);
19471 unsigned Elt = IndexC->getZExtValue();
19477 unsigned NewIdx = Elt % ConcatNumElts;
19479 unsigned ConcatOpIdx = Elt / ConcatNumElts;
19484 ConcatOps[ConcatOpIdx] = ConcatOp;
19496 EVT VT =
N->getValueType(0);
19508 !
SDValue(BaseLd, 0).hasOneUse())
19511 EVT BaseLdVT = BaseLd->getValueType(0);
19519 if (!Ld || !Ld->isSimple() || !
Op.hasOneUse() ||
19521 Ld->getValueType(0) != BaseLdVT)
19530 using PtrDiff = std::pair<std::variant<int64_t, SDValue>,
bool>;
19532 LoadSDNode *Ld2) -> std::optional<PtrDiff> {
19537 if (BIO1.equalBaseIndex(BIO2, DAG))
19542 SDValue P2 = Ld2->getBasePtr();
19545 if (P1.getOpcode() ==
ISD::ADD && P1.getOperand(0) == P2)
19546 return {{P1.getOperand(1),
true}};
19548 return std::nullopt;
19552 auto BaseDiff = GetPtrDiff(Lds[0], Lds[1]);
19557 for (
auto *It = Lds.
begin() + 1; It != Lds.
end() - 1; It++)
19558 if (GetPtrDiff(*It, *std::next(It)) != BaseDiff)
19566 unsigned WideScalarBitWidth =
19579 auto [StrideVariant, MustNegateStride] = *BaseDiff;
19581 std::holds_alternative<SDValue>(StrideVariant)
19582 ? std::get<SDValue>(StrideVariant)
19585 if (MustNegateStride)
19594 ConstStride && ConstStride->getSExtValue() >= 0)
19598 ConstStride->getSExtValue() * (
N->getNumOperands() - 1);
19604 BaseLd->getPointerInfo(), BaseLd->getMemOperand()->getFlags(), MemSize,
19608 WideVecVT,
DL, BaseLd->getChain(), BaseLd->getBasePtr(), Stride,
19622 EVT VT =
N->getValueType(0);
19639 for (
int MaskIndex : Mask) {
19640 bool SelectMaskVal = (MaskIndex < (int)NumElts);
19643 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
19680 if (
N->getValueType(0).isFixedLengthVector())
19683 SDValue Addend =
N->getOperand(0);
19686 if (
N->getOpcode() == RISCVISD::ADD_VL) {
19687 SDValue AddPassthruOp =
N->getOperand(2);
19688 if (!AddPassthruOp.
isUndef())
19692 auto IsVWMulOpc = [](
unsigned Opc) {
19694 case RISCVISD::VWMUL_VL:
19695 case RISCVISD::VWMULU_VL:
19696 case RISCVISD::VWMULSU_VL:
19711 if (!MulPassthruOp.
isUndef())
19721 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
19722 }(
N, DAG, Subtarget);
19727 if (AddMask != MulMask || AddVL != MulVL)
19730 const auto &TSInfo =
19732 unsigned Opc = TSInfo.getMAccOpcode(MulOp.
getOpcode());
19735 EVT VT =
N->getValueType(0);
19746 if (!
N->getValueType(0).isVector())
19749 SDValue Addend =
N->getOperand(0);
19752 if (
N->getOpcode() == RISCVISD::ADD_VL) {
19753 SDValue AddPassthruOp =
N->getOperand(2);
19754 if (!AddPassthruOp.
isUndef())
19758 auto IsVqdotqOpc = [](
unsigned Opc) {
19760 case RISCVISD::VQDOT_VL:
19761 case RISCVISD::VQDOTU_VL:
19762 case RISCVISD::VQDOTSU_VL:
19782 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
19783 }(
N, DAG, Subtarget);
19786 if (AddVL != MulVL)
19789 if (AddMask.getOpcode() != RISCVISD::VMSET_VL ||
19790 AddMask.getOperand(0) != MulVL)
19795 EVT VT =
N->getValueType(0);
19796 Addend = DAG.
getNode(RISCVISD::ADD_VL,
DL, VT, Addend, AccumOp,
19797 DAG.
getUNDEF(VT), AddMask, AddVL);
19815 const EVT IndexVT = Index.getValueType();
19819 if (!isIndexTypeSigned(IndexType))
19851 assert(ShuffleMask.empty());
19853 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
19856 if (Index->getOperand(i)->isUndef())
19858 uint64_t C = Index->getConstantOperandVal(i);
19859 if (
C % ElementSize != 0)
19861 C =
C / ElementSize;
19864 ShuffleMask.push_back(
C);
19865 ActiveLanes.
set(
C);
19867 return ActiveLanes.
all();
19885 if (NumElems % 2 != 0)
19889 const unsigned WiderElementSize = ElementSize * 2;
19890 if (WiderElementSize > ST.getELen()/8)
19893 if (!ST.enableUnalignedVectorMem() && BaseAlign < WiderElementSize)
19896 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
19899 if (Index->getOperand(i)->isUndef())
19903 uint64_t C = Index->getConstantOperandVal(i);
19905 if (
C % WiderElementSize != 0)
19910 if (
C !=
Last + ElementSize)
19929 if (!IsVLMAX || Mask.getOpcode() != RISCVISD::VMSET_VL ||
19930 Mask.getOperand(0) != VL)
19933 auto IsTruncNode = [&](
SDValue V) {
19934 return V.getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL &&
19935 V.getOperand(1) == Mask && V.getOperand(2) == VL;
19942 while (IsTruncNode(
Op)) {
19943 if (!
Op.hasOneUse())
19945 Op =
Op.getOperand(0);
19978 assert(
N->getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL);
19980 MVT VT =
N->getSimpleValueType(0);
19985 auto MatchMinMax = [&VL, &Mask](
SDValue V,
unsigned Opc,
unsigned OpcVL,
19987 if (V.getOpcode() !=
Opc &&
19988 !(V.getOpcode() == OpcVL && V.getOperand(2).isUndef() &&
19989 V.getOperand(3) == Mask && V.getOperand(4) == VL))
19997 Op.getOperand(1).getValueType().isFixedLengthVector() &&
19999 Op.getOperand(1).getOperand(0).getValueType() ==
Op.getValueType() &&
20001 Op =
Op.getOperand(1).getOperand(0);
20004 return V.getOperand(0);
20006 if (
Op.getOpcode() == RISCVISD::VMV_V_X_VL &&
Op.getOperand(0).isUndef() &&
20007 Op.getOperand(2) == VL) {
20010 Op1->getAPIntValue().sextOrTrunc(
Op.getScalarValueSizeInBits());
20020 auto DetectUSatPattern = [&](
SDValue V) {
20032 MatchMinMax(SMinOp,
ISD::SMAX, RISCVISD::SMAX_VL, LoC))
20041 MatchMinMax(SMaxOp,
ISD::SMIN, RISCVISD::SMIN_VL, HiC))
20044 return DAG.
getNode(RISCVISD::SMAX_VL,
DL, V.getValueType(), SMinOp,
20045 V.getOperand(1), DAG.
getUNDEF(V.getValueType()),
20051 auto DetectSSatPattern = [&](
SDValue V) {
20053 unsigned NumSrcBits = V.getScalarValueSizeInBits();
20060 MatchMinMax(SMinOp,
ISD::SMAX, RISCVISD::SMAX_VL, LoC))
20061 if (HiC == SignedMax && LoC == SignedMin)
20066 MatchMinMax(SMaxOp,
ISD::SMIN, RISCVISD::SMIN_VL, HiC))
20067 if (HiC == SignedMax && LoC == SignedMin)
20076 while (Src.getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL &&
20077 Src.getOperand(1) == Mask && Src.getOperand(2) == VL &&
20079 Src = Src.getOperand(0);
20083 if ((Val = DetectUSatPattern(Src)))
20084 ClipOpc = RISCVISD::TRUNCATE_VECTOR_VL_USAT;
20085 else if ((Val = DetectSSatPattern(Src)))
20086 ClipOpc = RISCVISD::TRUNCATE_VECTOR_VL_SSAT;
20095 Val = DAG.
getNode(ClipOpc,
DL, ValVT, Val, Mask, VL);
20096 }
while (ValVT != VT);
20114 unsigned Opc =
N->getOpcode();
20116 "Unexpected opcode");
20117 EVT VT =
N->getValueType(0);
20126 Src = Src.getOperand(0);
20128 if (Src.getOpcode() != ISD::BITCAST)
20130 Src = Src.getOperand(0);
20131 }
else if (
Opc == ISD::VECREDUCE_ADD) {
20134 Src = Src.getOperand(0);
20137 EVT SrcEVT = Src.getValueType();
20152 if (
Opc == ISD::VECREDUCE_ADD) {
20159 VectorBitsMax, EltSize, MinSize);
20164 MVT ContainerVT = SrcMVT;
20192 if (!
LHS.hasOneUse())
20195 switch (
LHS.getOpcode()) {
20197 case RISCVISD::VSEXT_VL:
20198 Opcode = RISCVISD::VWMULSU_VL;
20201 case RISCVISD::VZEXT_VL:
20202 Opcode = RISCVISD::VWMULU_VL;
20213 else if (
RHS.getOpcode() == RISCVISD::VMV_V_X_VL &&
20215 ShAmtInt =
RHS.getConstantOperandVal(1);
20228 if (ShAmtInt >= NarrowBits)
20230 MVT VT =
N->getSimpleValueType(0);
20237 switch (
N->getOpcode()) {
20242 case RISCVISD::SHL_VL:
20243 Passthru =
N->getOperand(2);
20244 Mask =
N->getOperand(3);
20245 VL =
N->getOperand(4);
20250 return DAG.
getNode(Opcode,
DL, VT, NarrowOp,
20252 Passthru, Mask, VL);
20258 const MVT XLenVT = Subtarget.getXLenVT();
20264 auto SimplifyDemandedLowBitsHelper = [&](
unsigned OpNo,
unsigned LowBits) {
20275 switch (
N->getOpcode()) {
20278 case RISCVISD::SplitF64: {
20282 if (Op0->
getOpcode() == RISCVISD::BuildPairF64)
20295 APInt V =
C->getValueAPF().bitcastToAPInt();
20324 case RISCVISD::SLLW:
20325 case RISCVISD::SRAW:
20326 case RISCVISD::SRLW:
20327 case RISCVISD::RORW:
20328 case RISCVISD::ROLW: {
20330 if (SimplifyDemandedLowBitsHelper(0, 32) ||
20331 SimplifyDemandedLowBitsHelper(1, 5))
20336 case RISCVISD::ABSW:
20337 case RISCVISD::CLZW:
20338 case RISCVISD::CTZW: {
20340 if (SimplifyDemandedLowBitsHelper(0, 32))
20344 case RISCVISD::FMV_W_X_RV64: {
20349 if (Op0.
getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64)
20353 case RISCVISD::FMV_X_ANYEXTH:
20354 case RISCVISD::FMV_X_ANYEXTW_RV64: {
20357 MVT VT =
N->getSimpleValueType(0);
20368 if ((
N->getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64 &&
20369 Op0->
getOpcode() == RISCVISD::FMV_W_X_RV64) ||
20370 (
N->getOpcode() == RISCVISD::FMV_X_ANYEXTH &&
20371 Op0->
getOpcode() == RISCVISD::FMV_H_X)) {
20373 "Unexpected value type!");
20383 LN0->getBasePtr(), IVT, LN0->getMemOperand());
20396 unsigned FPBits =
N->getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64 ? 32 : 16;
20407 EVT VT =
N->getValueType(0);
20456 EVT VT =
N->getValueType(0);
20473 if (!
C || !
C->getValueAPF().isExactlyValue(+1.0))
20488 case ISD::FMINNUM: {
20503 if (
N->getValueType(0) == MVT::i64 && Subtarget.is64Bit()) {
20508 Src.getOperand(0));
20513 Src.getOperand(0), Src.getOperand(1));
20521 case RISCVISD::TRUNCATE_VECTOR_VL:
20525 case ISD::VP_TRUNCATE:
20533 case RISCVISD::CZERO_EQZ:
20534 case RISCVISD::CZERO_NEZ: {
20538 unsigned Opc =
N->getOpcode();
20541 if (
Opc == RISCVISD::CZERO_EQZ && Val ==
Cond)
20545 Opc == RISCVISD::CZERO_EQZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ;
20553 return DAG.
getNode(InvOpc,
SDLoc(
N),
N->getValueType(0), Val, NewCond);
20563 N->getValueType(0), Val,
Cond.getOperand(0));
20567 case RISCVISD::SELECT_CC: {
20574 SDValue FalseV =
N->getOperand(4);
20576 EVT VT =
N->getValueType(0);
20579 if (TrueV == FalseV)
20610 return DAG.
getNode(RISCVISD::SELECT_CC,
DL,
N->getValueType(0),
20611 {LHS, RHS, CC, TrueV, FalseV});
20613 if (!Subtarget.hasConditionalMoveFusion()) {
20670 case RISCVISD::BR_CC: {
20677 return DAG.
getNode(RISCVISD::BR_CC,
DL,
N->getValueType(0),
20678 N->getOperand(0), LHS, RHS, CC,
N->getOperand(4));
20691 EVT VT =
N->getValueType(0);
20703 if (In2.
getOpcode() != ISD::FP_EXTEND &&
20712 DAG.
getNode(ISD::FNEG,
DL, VT, NewFPExtRound));
20714 case ISD::MGATHER: {
20716 const EVT VT =
N->getValueType(0);
20717 SDValue Index = MGN->getIndex();
20718 SDValue ScaleOp = MGN->getScale();
20720 assert(!MGN->isIndexScaled() &&
20721 "Scaled gather/scatter should not be formed");
20726 N->getVTList(), MGN->getMemoryVT(),
DL,
20727 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
20728 MGN->getBasePtr(), Index, ScaleOp},
20729 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
20733 N->getVTList(), MGN->getMemoryVT(),
DL,
20734 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
20735 MGN->getBasePtr(), Index, ScaleOp},
20736 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
20742 if (std::optional<VIDSequence> SimpleVID =
20744 SimpleVID && SimpleVID->StepDenominator == 1) {
20745 const int64_t StepNumerator = SimpleVID->StepNumerator;
20746 const int64_t Addend = SimpleVID->Addend;
20753 assert(MGN->getBasePtr()->getValueType(0) == PtrVT);
20761 VT,
DL, MGN->getChain(), BasePtr,
20763 EVL, MGN->getMemOperand());
20765 MGN->getPassThru());
20775 MGN->getBasePtr(), DAG.
getUNDEF(XLenVT),
20777 MGN->getMemoryVT(), MGN->getMemOperand(),
20786 MGN->getMemOperand()->getBaseAlign(), Subtarget)) {
20788 for (
unsigned i = 0; i < Index->getNumOperands(); i += 2)
20789 NewIndices.
push_back(Index.getOperand(i));
20790 EVT IndexVT = Index.getValueType()
20797 assert(EltCnt.isKnownEven() &&
"Splitting vector, but not in half!");
20799 EltCnt.divideCoefficientBy(2));
20802 EltCnt.divideCoefficientBy(2));
20807 {MGN->getChain(), Passthru, Mask, MGN->getBasePtr(),
20815 case ISD::MSCATTER:{
20817 SDValue Index = MSN->getIndex();
20818 SDValue ScaleOp = MSN->getScale();
20820 assert(!MSN->isIndexScaled() &&
20821 "Scaled gather/scatter should not be formed");
20826 N->getVTList(), MSN->getMemoryVT(),
DL,
20827 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
20829 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
20833 N->getVTList(), MSN->getMemoryVT(),
DL,
20834 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
20836 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
20838 EVT VT = MSN->getValue()->getValueType(0);
20840 if (!MSN->isTruncatingStore() &&
20844 return DAG.
getMaskedStore(MSN->getChain(),
DL, Shuffle, MSN->getBasePtr(),
20845 DAG.
getUNDEF(XLenVT), MSN->getMask(),
20846 MSN->getMemoryVT(), MSN->getMemOperand(),
20851 case ISD::VP_GATHER: {
20853 SDValue Index = VPGN->getIndex();
20854 SDValue ScaleOp = VPGN->getScale();
20856 assert(!VPGN->isIndexScaled() &&
20857 "Scaled gather/scatter should not be formed");
20862 {VPGN->getChain(), VPGN->getBasePtr(), Index,
20863 ScaleOp, VPGN->getMask(),
20864 VPGN->getVectorLength()},
20865 VPGN->getMemOperand(), IndexType);
20869 {VPGN->getChain(), VPGN->getBasePtr(), Index,
20870 ScaleOp, VPGN->getMask(),
20871 VPGN->getVectorLength()},
20872 VPGN->getMemOperand(), IndexType);
20876 case ISD::VP_SCATTER: {
20878 SDValue Index = VPSN->getIndex();
20879 SDValue ScaleOp = VPSN->getScale();
20881 assert(!VPSN->isIndexScaled() &&
20882 "Scaled gather/scatter should not be formed");
20887 {VPSN->getChain(), VPSN->getValue(),
20888 VPSN->getBasePtr(), Index, ScaleOp,
20889 VPSN->getMask(), VPSN->getVectorLength()},
20890 VPSN->getMemOperand(), IndexType);
20894 {VPSN->getChain(), VPSN->getValue(),
20895 VPSN->getBasePtr(), Index, ScaleOp,
20896 VPSN->getMask(), VPSN->getVectorLength()},
20897 VPSN->getMemOperand(), IndexType);
20900 case RISCVISD::SHL_VL:
20904 case RISCVISD::SRA_VL:
20905 case RISCVISD::SRL_VL: {
20907 if (ShAmt.
getOpcode() == RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL) {
20911 EVT VT =
N->getValueType(0);
20914 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt,
20915 N->getOperand(2),
N->getOperand(3),
N->getOperand(4));
20930 if (ShAmt.
getOpcode() == RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL) {
20933 EVT VT =
N->getValueType(0);
20936 DAG.
getRegister(RISCV::X0, Subtarget.getXLenVT()));
20937 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt);
20941 case RISCVISD::ADD_VL:
20949 case RISCVISD::VWADD_W_VL:
20950 case RISCVISD::VWADDU_W_VL:
20951 case RISCVISD::VWSUB_W_VL:
20952 case RISCVISD::VWSUBU_W_VL:
20954 case RISCVISD::OR_VL:
20955 case RISCVISD::SUB_VL:
20956 case RISCVISD::MUL_VL:
20958 case RISCVISD::VFMADD_VL:
20959 case RISCVISD::VFNMADD_VL:
20960 case RISCVISD::VFMSUB_VL:
20961 case RISCVISD::VFNMSUB_VL:
20962 case RISCVISD::STRICT_VFMADD_VL:
20963 case RISCVISD::STRICT_VFNMADD_VL:
20964 case RISCVISD::STRICT_VFMSUB_VL:
20965 case RISCVISD::STRICT_VFNMSUB_VL:
20967 case RISCVISD::FADD_VL:
20968 case RISCVISD::FSUB_VL:
20969 case RISCVISD::FMUL_VL:
20970 case RISCVISD::VFWADD_W_VL:
20971 case RISCVISD::VFWSUB_W_VL:
20979 if (
N->getOpcode() != ISD::STORE)
20983 SDValue Chain = Store->getChain();
20984 EVT MemVT = Store->getMemoryVT();
20985 SDValue Val = Store->getValue();
20988 bool IsScalarizable =
20990 Store->isSimple() &&
21020 NewVT, *Store->getMemOperand())) {
21022 return DAG.
getStore(Chain,
DL, NewV, Store->getBasePtr(),
21023 Store->getPointerInfo(), Store->getBaseAlign(),
21024 Store->getMemOperand()->getFlags());
21034 L->hasNUsesOfValue(1, 0) && L->hasNUsesOfValue(1, 1) &&
21036 L->getMemoryVT() == MemVT) {
21039 NewVT, *Store->getMemOperand()) &&
21041 NewVT, *L->getMemOperand())) {
21043 L->getPointerInfo(), L->getBaseAlign(),
21044 L->getMemOperand()->getFlags());
21045 return DAG.
getStore(Chain,
DL, NewL, Store->getBasePtr(),
21046 Store->getPointerInfo(), Store->getBaseAlign(),
21047 Store->getMemOperand()->getFlags());
21054 if ((Val.
getOpcode() == RISCVISD::VMV_X_S ||
21060 MVT VecVT = Src.getSimpleValueType();
21067 Store->getChain(),
DL, Src, Store->getBasePtr(), Store->getOffset(),
21070 Store->getMemOperand(), Store->getAddressingMode(),
21071 Store->isTruncatingStore(),
false);
21078 EVT VT =
N->getValueType(0);
21103 case RISCVISD::VFMV_V_F_VL: {
21104 const MVT VT =
N->getSimpleValueType(0);
21105 SDValue Passthru =
N->getOperand(0);
21106 SDValue Scalar =
N->getOperand(1);
21111 return DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL, VT, Passthru, Scalar, VL);
21114 case RISCVISD::VMV_V_X_VL: {
21115 const MVT VT =
N->getSimpleValueType(0);
21116 SDValue Passthru =
N->getOperand(0);
21117 SDValue Scalar =
N->getOperand(1);
21122 unsigned ScalarSize = Scalar.getValueSizeInBits();
21124 if (ScalarSize > EltWidth && Passthru.
isUndef())
21125 if (SimplifyDemandedLowBitsHelper(1, EltWidth))
21132 (!Const || Const->isZero() ||
21133 !Const->getAPIntValue().sextOrTrunc(EltWidth).isSignedIntN(5)))
21134 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, VT, Passthru, Scalar, VL);
21138 case RISCVISD::VFMV_S_F_VL: {
21143 if (
N->getOperand(0).isUndef() &&
21146 Src.getOperand(0).getValueType().isScalableVector()) {
21147 EVT VT =
N->getValueType(0);
21167 case RISCVISD::VMV_S_X_VL: {
21168 const MVT VT =
N->getSimpleValueType(0);
21169 SDValue Passthru =
N->getOperand(0);
21170 SDValue Scalar =
N->getOperand(1);
21176 unsigned ScalarSize = Scalar.getValueSizeInBits();
21178 if (ScalarSize > EltWidth && SimplifyDemandedLowBitsHelper(1, EltWidth))
21181 if (Scalar.getOpcode() == RISCVISD::VMV_X_S && Passthru.
isUndef() &&
21182 Scalar.getOperand(0).getValueType() ==
N->getValueType(0))
21183 return Scalar.getOperand(0);
21190 DAG.
getNode(
N->getOpcode(),
DL, M1VT, M1Passthru, Scalar, VL);
21199 Const && !Const->isZero() &&
isInt<5>(Const->getSExtValue()) &&
21201 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru, Scalar, VL);
21205 case RISCVISD::VMV_X_S: {
21207 MVT VecVT =
N->getOperand(0).getSimpleValueType();
21209 if (M1VT.
bitsLT(VecVT)) {
21211 return DAG.
getNode(RISCVISD::VMV_X_S,
DL,
N->getSimpleValueType(0), Vec);
21219 unsigned IntNo =
N->getConstantOperandVal(IntOpNo);
21224 case Intrinsic::riscv_vcpop:
21225 case Intrinsic::riscv_vcpop_mask:
21226 case Intrinsic::riscv_vfirst:
21227 case Intrinsic::riscv_vfirst_mask: {
21229 if (IntNo == Intrinsic::riscv_vcpop_mask ||
21230 IntNo == Intrinsic::riscv_vfirst_mask)
21231 VL =
N->getOperand(3);
21236 EVT VT =
N->getValueType(0);
21237 if (IntNo == Intrinsic::riscv_vfirst ||
21238 IntNo == Intrinsic::riscv_vfirst_mask)
21242 case Intrinsic::riscv_vsseg2_mask:
21243 case Intrinsic::riscv_vsseg3_mask:
21244 case Intrinsic::riscv_vsseg4_mask:
21245 case Intrinsic::riscv_vsseg5_mask:
21246 case Intrinsic::riscv_vsseg6_mask:
21247 case Intrinsic::riscv_vsseg7_mask:
21248 case Intrinsic::riscv_vsseg8_mask: {
21250 unsigned NF = Tuple.getValueType().getRISCVVectorTupleNumFields();
21252 if (Subtarget.hasOptimizedSegmentLoadStore(NF) || !Tuple.hasOneUse() ||
21253 Tuple.getOpcode() != RISCVISD::TUPLE_INSERT ||
21254 !Tuple.getOperand(0).isUndef())
21262 "Type mismatch without bitcast?");
21263 unsigned Stride = SEW / 8 * NF;
21264 unsigned Offset = SEW / 8 * Idx;
21291 case ISD::EXPERIMENTAL_VP_REVERSE:
21293 case ISD::VP_STORE:
21295 case ISD::BITCAST: {
21296 assert(Subtarget.useRVVForFixedLengthVectors());
21298 EVT VT =
N->getValueType(0);
21309 for (
unsigned i = 0; i < NF; ++i)
21310 Result = DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VT, Result,
Splat,
21316 if ((SrcVT == MVT::v1i1 || SrcVT == MVT::v2i1 || SrcVT == MVT::v4i1) &&
21329 case ISD::VECREDUCE_ADD:
21337 case RISCVISD::VRGATHER_VX_VL: {
21340 EVT VT =
N->getValueType(0);
21343 SDValue Passthru =
N->getOperand(2);
21350 Src = Src.getOperand(1);
21352 switch (Src.getOpcode()) {
21355 case RISCVISD::VMV_V_X_VL:
21356 case RISCVISD::VFMV_V_F_VL:
21364 case RISCVISD::VMV_S_X_VL:
21365 case RISCVISD::VFMV_S_F_VL:
21381 case RISCVISD::TUPLE_EXTRACT: {
21382 EVT VT =
N->getValueType(0);
21384 unsigned Idx =
N->getConstantOperandVal(1);
21389 switch (Tuple.getConstantOperandVal(1)) {
21392 case Intrinsic::riscv_vlseg2_mask:
21393 case Intrinsic::riscv_vlseg3_mask:
21394 case Intrinsic::riscv_vlseg4_mask:
21395 case Intrinsic::riscv_vlseg5_mask:
21396 case Intrinsic::riscv_vlseg6_mask:
21397 case Intrinsic::riscv_vlseg7_mask:
21398 case Intrinsic::riscv_vlseg8_mask:
21399 NF = Tuple.getValueType().getRISCVVectorTupleNumFields();
21403 if (!NF || Subtarget.hasOptimizedSegmentLoadStore(NF))
21408 "Type mismatch without bitcast?");
21409 unsigned Stride = SEW / 8 * NF;
21410 unsigned Offset = SEW / 8 * Idx;
21413 Tuple.getOperand(0),
21435 return Result.getValue(0);
21437 case RISCVISD::TUPLE_INSERT: {
21439 if (
N->getOperand(1).isUndef())
21440 return N->getOperand(0);
21443 case RISCVISD::VSLIDE1UP_VL:
21444 case RISCVISD::VFSLIDE1UP_VL: {
21448 MVT VT =
N->getSimpleValueType(0);
21452 if (!
N->getOperand(0).isUndef() ||
21471 return getVSlideup(DAG, Subtarget,
DL, VT, SrcVec,
N->getOperand(1),
21481 EVT XVT,
unsigned KeptBits)
const {
21486 if (XVT != MVT::i32 && XVT != MVT::i64)
21490 if (KeptBits == 32 || KeptBits == 64)
21494 return Subtarget.hasStdExtZbb() &&
21495 ((KeptBits == 8 && XVT == MVT::i64 && !Subtarget.is64Bit()) ||
21503 "Expected shift op");
21527 if (Ty.isScalarInteger() &&
21530 return isUsedByLdSt(N0.
getNode(),
N);
21536 if (C2 && Subtarget.hasShlAdd(C2->getZExtValue()) &&
N->hasOneUse() &&
21537 N->user_begin()->getOpcode() ==
ISD::ADD &&
21538 !isUsedByLdSt(*
N->user_begin(),
nullptr) &&
21543 const APInt &C1Int = C1->getAPIntValue();
21544 APInt ShiftedC1Int = C1Int << C2->getAPIntValue();
21565 ShiftedC1Int, Ty.getSizeInBits(), Subtarget,
21570 if (C1Cost < ShiftedC1Cost)
21593 EVT VT =
Op.getValueType();
21597 unsigned Opcode =
Op.getOpcode();
21605 const APInt &Mask =
C->getAPIntValue();
21614 auto IsLegalMask = [ShrunkMask, ExpandedMask](
const APInt &Mask) ->
bool {
21615 return ShrunkMask.
isSubsetOf(Mask) && Mask.isSubsetOf(ExpandedMask);
21617 auto UseMask = [Mask,
Op, &TLO](
const APInt &NewMask) ->
bool {
21618 if (NewMask == Mask)
21623 Op.getOperand(0), NewC);
21636 APInt NewMask =
APInt(Mask.getBitWidth(), 0xffff);
21637 if (IsLegalMask(NewMask))
21638 return UseMask(NewMask);
21641 if (VT == MVT::i64) {
21643 if (IsLegalMask(NewMask))
21644 return UseMask(NewMask);
21659 APInt NewMask = ShrunkMask;
21660 if (MinSignedBits <= 12)
21662 else if (!
C->isOpaque() && MinSignedBits <= 32 && !ShrunkMask.
isSignedIntN(32))
21668 assert(IsLegalMask(NewMask));
21669 return UseMask(NewMask);
21673 static const uint64_t GREVMasks[] = {
21674 0x5555555555555555ULL, 0x3333333333333333ULL, 0x0F0F0F0F0F0F0F0FULL,
21675 0x00FF00FF00FF00FFULL, 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL};
21677 for (
unsigned Stage = 0; Stage != 6; ++Stage) {
21678 unsigned Shift = 1 << Stage;
21679 if (ShAmt & Shift) {
21681 uint64_t Res = ((x & Mask) << Shift) | ((x >> Shift) & Mask);
21693 const APInt &DemandedElts,
21695 unsigned Depth)
const {
21697 unsigned Opc =
Op.getOpcode();
21702 "Should use MaskedValueIsZero if you don't know whether Op"
21703 " is a target node!");
21708 case RISCVISD::SELECT_CC: {
21719 case RISCVISD::VCPOP_VL: {
21724 case RISCVISD::CZERO_EQZ:
21725 case RISCVISD::CZERO_NEZ:
21731 case RISCVISD::REMUW: {
21741 case RISCVISD::DIVUW: {
21751 case RISCVISD::SLLW: {
21760 case RISCVISD::SRLW: {
21769 case RISCVISD::SRAW: {
21778 case RISCVISD::SHL_ADD: {
21781 unsigned ShAmt =
Op.getConstantOperandVal(1);
21788 case RISCVISD::CTZW: {
21795 case RISCVISD::CLZW: {
21802 case RISCVISD::BREV8:
21803 case RISCVISD::ORC_B: {
21807 bool IsGORC =
Op.getOpcode() == RISCVISD::ORC_B;
21815 case RISCVISD::READ_VLENB: {
21818 const unsigned MinVLenB = Subtarget.getRealMinVLen() / 8;
21819 const unsigned MaxVLenB = Subtarget.getRealMaxVLen() / 8;
21820 assert(MinVLenB > 0 &&
"READ_VLENB without vector extension enabled?");
21823 if (MaxVLenB == MinVLenB)
21827 case RISCVISD::FCLASS: {
21840 case Intrinsic::riscv_vsetvli:
21841 case Intrinsic::riscv_vsetvlimax: {
21842 bool HasAVL = IntNo == Intrinsic::riscv_vsetvli;
21843 unsigned VSEW =
Op.getConstantOperandVal(HasAVL + 1);
21848 uint64_t MaxVL = Subtarget.getRealMaxVLen() / SEW;
21849 MaxVL = (Fractional) ? MaxVL / LMul : MaxVL * LMul;
21853 MaxVL = std::min(MaxVL,
Op.getConstantOperandVal(1));
21855 unsigned KnownZeroFirstBit =
Log2_32(MaxVL) + 1;
21868 unsigned Depth)
const {
21869 switch (
Op.getOpcode()) {
21872 case RISCVISD::SELECT_CC: {
21875 if (Tmp == 1)
return 1;
21878 return std::min(Tmp, Tmp2);
21880 case RISCVISD::CZERO_EQZ:
21881 case RISCVISD::CZERO_NEZ:
21885 case RISCVISD::NEGW_MAX: {
21890 if (Tmp < 33)
return 1;
21893 case RISCVISD::SRAW: {
21900 return std::max(Tmp, 33U);
21902 case RISCVISD::SLLW:
21903 case RISCVISD::SRLW:
21904 case RISCVISD::DIVW:
21905 case RISCVISD::DIVUW:
21906 case RISCVISD::REMUW:
21907 case RISCVISD::ROLW:
21908 case RISCVISD::RORW:
21909 case RISCVISD::ABSW:
21910 case RISCVISD::FCVT_W_RV64:
21911 case RISCVISD::FCVT_WU_RV64:
21912 case RISCVISD::STRICT_FCVT_W_RV64:
21913 case RISCVISD::STRICT_FCVT_WU_RV64:
21916 case RISCVISD::VMV_X_S: {
21922 unsigned XLen = Subtarget.getXLen();
21923 unsigned EltBits =
Op.getOperand(0).getScalarValueSizeInBits();
21924 if (EltBits <= XLen)
21925 return XLen - EltBits + 1;
21929 unsigned IntNo =
Op.getConstantOperandVal(1);
21933 case Intrinsic::riscv_masked_atomicrmw_xchg:
21934 case Intrinsic::riscv_masked_atomicrmw_add:
21935 case Intrinsic::riscv_masked_atomicrmw_sub:
21936 case Intrinsic::riscv_masked_atomicrmw_nand:
21937 case Intrinsic::riscv_masked_atomicrmw_max:
21938 case Intrinsic::riscv_masked_atomicrmw_min:
21939 case Intrinsic::riscv_masked_atomicrmw_umax:
21940 case Intrinsic::riscv_masked_atomicrmw_umin:
21941 case Intrinsic::riscv_masked_cmpxchg:
21948 assert(Subtarget.hasStdExtZalrsc());
21949 return Op.getValueSizeInBits() - 31;
21961 unsigned Depth)
const {
21964 switch (
Op.getOpcode()) {
21965 case RISCVISD::BREV8:
21966 case RISCVISD::ORC_B: {
21968 bool IsGORC =
Op.getOpcode() == RISCVISD::ORC_B;
21976 OriginalDemandedElts, Known2, TLO,
Depth + 1))
21988 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
21996 switch (
Op.getOpcode()) {
21997 case RISCVISD::SLLW:
21998 case RISCVISD::SRAW:
21999 case RISCVISD::SRLW:
22000 case RISCVISD::RORW:
22001 case RISCVISD::ROLW:
22005 case RISCVISD::SELECT_CC:
22007 assert(
Op.getOperand(0).getValueType().isInteger() &&
22008 "RISCVISD::SELECT_CC only compares integers");
22017 assert(Ld &&
"Unexpected null LoadSDNode");
22026 if (!CNode || CNode->isMachineConstantPoolEntry() ||
22027 CNode->getOffset() != 0)
22034 if (
Ptr.getOpcode() == RISCVISD::LLA) {
22035 auto *CNode = GetSupportedConstantPool(
Ptr.getOperand(0));
22036 if (!CNode || CNode->getTargetFlags() != 0)
22039 return CNode->getConstVal();
22043 if (
Ptr.getOpcode() != RISCVISD::ADD_LO ||
22044 Ptr.getOperand(0).getOpcode() != RISCVISD::HI)
22047 auto *CNodeLo = GetSupportedConstantPool(
Ptr.getOperand(1));
22048 auto *CNodeHi = GetSupportedConstantPool(
Ptr.getOperand(0).getOperand(0));
22054 if (CNodeLo->getConstVal() != CNodeHi->getConstVal())
22057 return CNodeLo->getConstVal();
22062 assert(
MI.getOpcode() == RISCV::ReadCounterWide &&
"Unexpected instruction");
22094 Register ReadAgainReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
22097 int64_t LoCounter =
MI.getOperand(2).getImm();
22098 int64_t HiCounter =
MI.getOperand(3).getImm();
22108 BuildMI(LoopMBB,
DL,
TII->get(RISCV::CSRRS), ReadAgainReg)
22120 MI.eraseFromParent();
22128 assert(
MI.getOpcode() == RISCV::SplitF64Pseudo &&
"Unexpected instruction");
22136 Register SrcReg =
MI.getOperand(2).getReg();
22141 TII.storeRegToStackSlot(*BB,
MI, SrcReg,
MI.getOperand(2).isKill(), FI, SrcRC,
22156 MI.eraseFromParent();
22163 assert(
MI.getOpcode() == RISCV::BuildPairF64Pseudo &&
22164 "Unexpected instruction");
22170 Register DstReg =
MI.getOperand(0).getReg();
22192 TII.loadRegFromStackSlot(*BB,
MI, DstReg, FI, DstRC, RI,
Register());
22193 MI.eraseFromParent();
22198 unsigned RelOpcode,
unsigned EqOpcode,
22201 Register DstReg =
MI.getOperand(0).getReg();
22202 Register Src1Reg =
MI.getOperand(1).getReg();
22203 Register Src2Reg =
MI.getOperand(2).getReg();
22205 Register SavedFFlags =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22229 MI.eraseFromParent();
22280 F->insert(It, FirstMBB);
22281 F->insert(It, SecondMBB);
22282 F->insert(It, SinkMBB);
22332 First.eraseFromParent();
22372 if (
MI.getOpcode() != RISCV::Select_GPR_Using_CC_GPR &&
22373 MI.getOperand(1).isReg() &&
MI.getOperand(2).isReg() &&
22374 Next != BB->
end() &&
Next->getOpcode() ==
MI.getOpcode() &&
22375 Next->getOperand(5).getReg() ==
MI.getOperand(0).getReg() &&
22376 Next->getOperand(5).isKill())
22381 if (
MI.getOperand(2).isReg())
22382 RHS =
MI.getOperand(2).getReg();
22387 SelectDests.
insert(
MI.getOperand(0).getReg());
22393 SequenceMBBI !=
E; ++SequenceMBBI) {
22394 if (SequenceMBBI->isDebugInstr())
22396 if (RISCVInstrInfo::isSelectPseudo(*SequenceMBBI)) {
22397 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
22398 !SequenceMBBI->getOperand(2).isReg() ||
22399 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
22400 SequenceMBBI->getOperand(3).getImm() != CC ||
22401 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
22402 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
22404 LastSelectPseudo = &*SequenceMBBI;
22406 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
22409 if (SequenceMBBI->hasUnmodeledSideEffects() ||
22410 SequenceMBBI->mayLoadOrStore() ||
22411 SequenceMBBI->usesCustomInsertionHook() ||
22412 TII.isFrameInstr(*SequenceMBBI) ||
22413 SequenceMBBI->isStackAligningInlineAsm())
22416 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
22430 F->insert(
I, IfFalseMBB);
22431 F->insert(
I, TailMBB);
22434 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
22440 TailMBB->
push_back(DebugInstr->removeFromParent());
22444 TailMBB->
splice(TailMBB->
end(), HeadMBB,
22454 if (
MI.getOperand(2).isImm())
22457 .
addImm(
MI.getOperand(2).getImm())
22469 auto SelectMBBI =
MI.getIterator();
22470 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
22472 while (SelectMBBI != SelectEnd) {
22473 auto Next = std::next(SelectMBBI);
22474 if (RISCVInstrInfo::isSelectPseudo(*SelectMBBI)) {
22477 TII.get(RISCV::PHI), SelectMBBI->getOperand(0).getReg())
22478 .
addReg(SelectMBBI->getOperand(4).getReg())
22480 .
addReg(SelectMBBI->getOperand(5).getReg())
22487 F->getProperties().resetNoPHIs();
22495 RISCVVInversePseudosTable::getBaseInfo(MCOpcode, LMul, SEW);
22496 assert(
Inverse &&
"Unexpected LMUL and SEW pair for instruction");
22498 RISCV::lookupMaskedIntrinsicByUnmasked(
Inverse->Pseudo);
22499 assert(
Masked &&
"Could not find masked instruction for LMUL and SEW pair");
22505 unsigned CVTXOpc) {
22511 Register SavedFFLAGS =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22524 .
add(
MI.getOperand(1))
22525 .
add(
MI.getOperand(2))
22526 .
add(
MI.getOperand(3))
22528 .
add(
MI.getOperand(4))
22529 .
add(
MI.getOperand(5))
22530 .
add(
MI.getOperand(6))
22545 .
add(
MI.getOperand(0))
22546 .
add(
MI.getOperand(1))
22548 .
add(
MI.getOperand(3))
22550 .
add(
MI.getOperand(4))
22551 .
add(
MI.getOperand(5))
22552 .
add(
MI.getOperand(6))
22562 MI.eraseFromParent();
22568 unsigned CmpOpc, F2IOpc, I2FOpc, FSGNJOpc, FSGNJXOpc;
22570 switch (
MI.getOpcode()) {
22573 case RISCV::PseudoFROUND_H:
22574 CmpOpc = RISCV::FLT_H;
22575 F2IOpc = RISCV::FCVT_W_H;
22576 I2FOpc = RISCV::FCVT_H_W;
22577 FSGNJOpc = RISCV::FSGNJ_H;
22578 FSGNJXOpc = RISCV::FSGNJX_H;
22579 RC = &RISCV::FPR16RegClass;
22581 case RISCV::PseudoFROUND_H_INX:
22582 CmpOpc = RISCV::FLT_H_INX;
22583 F2IOpc = RISCV::FCVT_W_H_INX;
22584 I2FOpc = RISCV::FCVT_H_W_INX;
22585 FSGNJOpc = RISCV::FSGNJ_H_INX;
22586 FSGNJXOpc = RISCV::FSGNJX_H_INX;
22587 RC = &RISCV::GPRF16RegClass;
22589 case RISCV::PseudoFROUND_S:
22590 CmpOpc = RISCV::FLT_S;
22591 F2IOpc = RISCV::FCVT_W_S;
22592 I2FOpc = RISCV::FCVT_S_W;
22593 FSGNJOpc = RISCV::FSGNJ_S;
22594 FSGNJXOpc = RISCV::FSGNJX_S;
22595 RC = &RISCV::FPR32RegClass;
22597 case RISCV::PseudoFROUND_S_INX:
22598 CmpOpc = RISCV::FLT_S_INX;
22599 F2IOpc = RISCV::FCVT_W_S_INX;
22600 I2FOpc = RISCV::FCVT_S_W_INX;
22601 FSGNJOpc = RISCV::FSGNJ_S_INX;
22602 FSGNJXOpc = RISCV::FSGNJX_S_INX;
22603 RC = &RISCV::GPRF32RegClass;
22605 case RISCV::PseudoFROUND_D:
22607 CmpOpc = RISCV::FLT_D;
22608 F2IOpc = RISCV::FCVT_L_D;
22609 I2FOpc = RISCV::FCVT_D_L;
22610 FSGNJOpc = RISCV::FSGNJ_D;
22611 FSGNJXOpc = RISCV::FSGNJX_D;
22612 RC = &RISCV::FPR64RegClass;
22614 case RISCV::PseudoFROUND_D_INX:
22616 CmpOpc = RISCV::FLT_D_INX;
22617 F2IOpc = RISCV::FCVT_L_D_INX;
22618 I2FOpc = RISCV::FCVT_D_L_INX;
22619 FSGNJOpc = RISCV::FSGNJ_D_INX;
22620 FSGNJXOpc = RISCV::FSGNJX_D_INX;
22621 RC = &RISCV::GPRRegClass;
22633 F->insert(
I, CvtMBB);
22634 F->insert(
I, DoneMBB);
22642 MBB->addSuccessor(CvtMBB);
22643 MBB->addSuccessor(DoneMBB);
22645 Register DstReg =
MI.getOperand(0).getReg();
22646 Register SrcReg =
MI.getOperand(1).getReg();
22647 Register MaxReg =
MI.getOperand(2).getReg();
22648 int64_t FRM =
MI.getOperand(3).getImm();
22653 Register FabsReg =
MRI.createVirtualRegister(RC);
22657 Register CmpReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22672 Register F2IReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22694 MI.eraseFromParent();
22701 switch (
MI.getOpcode()) {
22704 case RISCV::ReadCounterWide:
22705 assert(!Subtarget.is64Bit() &&
22706 "ReadCounterWide is only to be used on riscv32");
22708 case RISCV::Select_GPR_Using_CC_GPR:
22709 case RISCV::Select_GPR_Using_CC_Imm5_Zibi:
22710 case RISCV::Select_GPR_Using_CC_SImm5_CV:
22711 case RISCV::Select_GPRNoX0_Using_CC_SImm5NonZero_QC:
22712 case RISCV::Select_GPRNoX0_Using_CC_UImm5NonZero_QC:
22713 case RISCV::Select_GPRNoX0_Using_CC_SImm16NonZero_QC:
22714 case RISCV::Select_GPRNoX0_Using_CC_UImm16NonZero_QC:
22715 case RISCV::Select_GPR_Using_CC_UImmLog2XLen_NDS:
22716 case RISCV::Select_GPR_Using_CC_UImm7_NDS:
22717 case RISCV::Select_FPR16_Using_CC_GPR:
22718 case RISCV::Select_FPR16INX_Using_CC_GPR:
22719 case RISCV::Select_FPR32_Using_CC_GPR:
22720 case RISCV::Select_FPR32INX_Using_CC_GPR:
22721 case RISCV::Select_FPR64_Using_CC_GPR:
22722 case RISCV::Select_FPR64INX_Using_CC_GPR:
22723 case RISCV::Select_FPR64IN32X_Using_CC_GPR:
22725 case RISCV::BuildPairF64Pseudo:
22727 case RISCV::SplitF64Pseudo:
22729 case RISCV::PseudoQuietFLE_H:
22731 case RISCV::PseudoQuietFLE_H_INX:
22732 return emitQuietFCMP(
MI, BB, RISCV::FLE_H_INX, RISCV::FEQ_H_INX, Subtarget);
22733 case RISCV::PseudoQuietFLT_H:
22735 case RISCV::PseudoQuietFLT_H_INX:
22736 return emitQuietFCMP(
MI, BB, RISCV::FLT_H_INX, RISCV::FEQ_H_INX, Subtarget);
22737 case RISCV::PseudoQuietFLE_S:
22739 case RISCV::PseudoQuietFLE_S_INX:
22740 return emitQuietFCMP(
MI, BB, RISCV::FLE_S_INX, RISCV::FEQ_S_INX, Subtarget);
22741 case RISCV::PseudoQuietFLT_S:
22743 case RISCV::PseudoQuietFLT_S_INX:
22744 return emitQuietFCMP(
MI, BB, RISCV::FLT_S_INX, RISCV::FEQ_S_INX, Subtarget);
22745 case RISCV::PseudoQuietFLE_D:
22747 case RISCV::PseudoQuietFLE_D_INX:
22748 return emitQuietFCMP(
MI, BB, RISCV::FLE_D_INX, RISCV::FEQ_D_INX, Subtarget);
22749 case RISCV::PseudoQuietFLE_D_IN32X:
22752 case RISCV::PseudoQuietFLT_D:
22754 case RISCV::PseudoQuietFLT_D_INX:
22755 return emitQuietFCMP(
MI, BB, RISCV::FLT_D_INX, RISCV::FEQ_D_INX, Subtarget);
22756 case RISCV::PseudoQuietFLT_D_IN32X:
22760 case RISCV::PseudoVFROUND_NOEXCEPT_V_M1_MASK:
22762 case RISCV::PseudoVFROUND_NOEXCEPT_V_M2_MASK:
22764 case RISCV::PseudoVFROUND_NOEXCEPT_V_M4_MASK:
22766 case RISCV::PseudoVFROUND_NOEXCEPT_V_M8_MASK:
22768 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF2_MASK:
22770 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF4_MASK:
22772 case RISCV::PseudoFROUND_H:
22773 case RISCV::PseudoFROUND_H_INX:
22774 case RISCV::PseudoFROUND_S:
22775 case RISCV::PseudoFROUND_S_INX:
22776 case RISCV::PseudoFROUND_D:
22777 case RISCV::PseudoFROUND_D_INX:
22778 case RISCV::PseudoFROUND_D_IN32X:
22780 case RISCV::PROBED_STACKALLOC_DYN:
22782 case TargetOpcode::STATEPOINT:
22788 MI.addOperand(*
MI.getMF(),
22794 case TargetOpcode::STACKMAP:
22795 case TargetOpcode::PATCHPOINT:
22796 if (!Subtarget.is64Bit())
22798 "supported on 64-bit targets");
22808 if (
auto *FRMDef =
MI.findRegisterDefOperand(RISCV::FRM,
nullptr)) {
22809 FRMDef->setIsDead(
false);
22813 int Idx = RISCV::getNamedOperandIdx(
MI.getOpcode(), RISCV::OpName::frm);
22823 if (
MI.readsRegister(RISCV::FRM,
nullptr))
22829void RISCVTargetLowering::analyzeInputArgs(
22833 for (
const auto &[Idx, In] :
enumerate(Ins)) {
22839 LLVM_DEBUG(
dbgs() <<
"InputArg #" << Idx <<
" has unhandled type "
22846void RISCVTargetLowering::analyzeOutputArgs(
22850 for (
const auto &[Idx, Out] :
enumerate(Outs)) {
22851 MVT ArgVT = Out.VT;
22852 ISD::ArgFlagsTy ArgFlags = Out.Flags;
22856 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << Idx <<
" has unhandled type "
22873 return DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, Val);
22907 if (In.isOrigArg()) {
22912 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
22913 (
BitWidth < 32 && In.Flags.isZExt())) {
22934 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, LocVT, Val);
22935 if (LocVT == MVT::i64 && VA.
getValVT() == MVT::f32)
22936 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Val);
22948 Val = DAG.
getNode(ISD::BITCAST,
DL, LocVT, Val);
22984 ExtType,
DL, LocVT, Chain, FIN,
23001 Register LoVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
23014 Register HiVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
23018 return DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64,
Lo,
Hi);
23029 switch (CallConv) {
23038#define CC_VLS_CASE(ABI_VLEN) case CallingConv::RISCV_VLSCall_##ABI_VLEN:
23054 if (Subtarget.hasStdExtE())
23056 if (!Subtarget.hasStdExtFOrZfinx() || !Subtarget.hasStdExtDOrZdinx())
23058 "(Zdinx/D) instruction set extensions");
23062 if (Func.hasFnAttribute(
"interrupt")) {
23063 if (!Func.arg_empty())
23065 "Functions with the interrupt attribute cannot have arguments!");
23076 "SiFive-CLIC-preemptible",
23077 "SiFive-CLIC-stack-swap",
23078 "SiFive-CLIC-preemptible-stack-swap",
23082 "Function interrupt attribute argument not supported!");
23084 if (Kind.starts_with(
"qci-") && !Subtarget.hasVendorXqciint())
23086 "'qci-*' interrupt kinds require Xqciint extension");
23088 if (Kind.starts_with(
"SiFive-CLIC-") && !Subtarget.hasVendorXSfmclic())
23090 "'SiFive-CLIC-*' interrupt kinds require XSfmclic extension");
23092 if (Kind ==
"rnmi" && !Subtarget.hasStdExtSmrnmi())
23095 if (Kind.starts_with(
"SiFive-CLIC-preemptible") && TFI->
hasFP(MF))
23097 "have a frame pointer");
23101 MVT XLenVT = Subtarget.getXLenVT();
23102 unsigned XLenInBytes = Subtarget.getXLen() / 8;
23104 std::vector<SDValue> OutChains;
23113 analyzeInputArgs(MF, CCInfo, Ins,
false,
23117 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
23138 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
23139 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
23141 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
23143 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
23172 int VarArgsSaveSize = XLenInBytes * (ArgRegs.
size() - Idx);
23177 if (VarArgsSaveSize == 0) {
23181 int VaArgOffset = -VarArgsSaveSize;
23189 XLenInBytes, VaArgOffset -
static_cast<int>(XLenInBytes),
true);
23190 VarArgsSaveSize += XLenInBytes;
23197 for (
unsigned I = Idx;
I < ArgRegs.
size(); ++
I) {
23198 const Register Reg = RegInfo.createVirtualRegister(RC);
23199 RegInfo.addLiveIn(ArgRegs[
I], Reg);
23202 Chain,
DL, ArgValue, FIN,
23204 OutChains.push_back(Store);
23218 if (!OutChains.empty()) {
23219 OutChains.push_back(Chain);
23229bool RISCVTargetLowering::isEligibleForTailCallOptimization(
23233 auto CalleeCC = CLI.CallConv;
23234 auto &Outs = CLI.Outs;
23236 auto CallerCC = Caller.getCallingConv();
23243 if (Caller.hasFnAttribute(
"interrupt"))
23258 for (
auto &VA : ArgLocs)
23264 auto IsCallerStructRet = Caller.hasStructRetAttr();
23265 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
23266 if (IsCallerStructRet || IsCalleeStructRet)
23271 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
23272 if (CalleeCC != CallerCC) {
23273 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
23274 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
23281 for (
auto &Arg : Outs)
23282 if (Arg.Flags.isByVal())
23308 MVT XLenVT = Subtarget.getXLenVT();
23323 if (Subtarget.hasStdExtE())
23327 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
23333 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
23339 "call site marked musttail");
23346 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
23348 if (!Flags.isByVal())
23352 unsigned Size = Flags.getByValSize();
23353 Align Alignment = Flags.getNonZeroByValAlign();
23360 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
23362 false,
nullptr, IsTailCall,
23374 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
23377 SDValue ArgValue = OutVals[OutIdx];
23385 RISCVISD::SplitF64,
DL, DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
23397 if (!StackPtr.getNode())
23409 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
23427 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
23428 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
23434 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
23435 SDValue PartValue = OutVals[OutIdx + 1];
23436 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
23450 DAG.
getStore(Chain,
DL, ArgValue, SpillSlot,
23452 for (
const auto &Part : Parts) {
23453 SDValue PartValue = Part.first;
23454 SDValue PartOffset = Part.second;
23461 ArgValue = SpillSlot;
23467 if (Flags.isByVal())
23468 ArgValue = ByValArgs[j++];
23475 if (
Options.EmitCallSiteInfo)
23479 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
23480 "for passing parameters");
23483 if (!StackPtr.getNode())
23497 if (!MemOpChains.
empty())
23503 for (
auto &Reg : RegsToPass) {
23504 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
23511 validateCCReservedRegs(RegsToPass, MF);
23515 "Return address register required, but has been reserved."});
23520 bool CalleeIsLargeExternalSymbol =
false;
23526 CalleeIsLargeExternalSymbol =
true;
23537 Ops.push_back(Chain);
23538 Ops.push_back(Callee);
23542 for (
auto &Reg : RegsToPass)
23543 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
23547 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
23548 assert(Mask &&
"Missing call preserved mask for calling convention");
23553 Ops.push_back(Glue);
23556 "Unexpected CFI type for a direct call");
23564 bool NeedSWGuarded =
false;
23566 Subtarget.hasStdExtZicfilp() &&
23568 NeedSWGuarded =
true;
23573 NeedSWGuarded ? RISCVISD::SW_GUARDED_TAIL : RISCVISD::TAIL;
23582 unsigned CallOpc = NeedSWGuarded ? RISCVISD::SW_GUARDED_CALL : RISCVISD::CALL;
23598 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_RISCV);
23601 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
23602 auto &VA = RVLocs[i];
23610 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
23611 assert(VA.needsCustom());
23616 RetValue = DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64, RetValue,
23630 const Type *RetTy)
const {
23632 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
23634 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
23635 MVT VT = Outs[i].VT;
23638 true, Outs[i].OrigTy))
23669 for (
unsigned i = 0, e = RVLocs.
size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
23670 SDValue Val = OutVals[OutIdx];
23679 DAG.
getVTList(MVT::i32, MVT::i32), Val);
23683 Register RegHi = RVLocs[++i].getLocReg();
23685 if (Subtarget.isRegisterReservedByUser(RegLo) ||
23686 Subtarget.isRegisterReservedByUser(RegHi))
23689 "Return value register required, but has been reserved."});
23702 if (Subtarget.isRegisterReservedByUser(VA.
getLocReg()))
23705 "Return value register required, but has been reserved."});
23724 unsigned RetOpc = RISCVISD::RET_GLUE;
23727 if (Func.hasFnAttribute(
"interrupt")) {
23728 if (!Func.getReturnType()->isVoidTy())
23730 "Functions with the interrupt attribute must have void return type!");
23736 if (Kind ==
"supervisor")
23737 RetOpc = RISCVISD::SRET_GLUE;
23738 else if (Kind ==
"rnmi") {
23739 assert(Subtarget.hasFeature(RISCV::FeatureStdExtSmrnmi) &&
23740 "Need Smrnmi extension for rnmi");
23741 RetOpc = RISCVISD::MNRET_GLUE;
23742 }
else if (Kind ==
"qci-nest" || Kind ==
"qci-nonest") {
23743 assert(Subtarget.hasFeature(RISCV::FeatureVendorXqciint) &&
23744 "Need Xqciint for qci-(no)nest");
23745 RetOpc = RISCVISD::QC_C_MILEAVERET_GLUE;
23747 RetOpc = RISCVISD::MRET_GLUE;
23750 return DAG.
getNode(RetOpc,
DL, MVT::Other, RetOps);
23753void RISCVTargetLowering::validateCCReservedRegs(
23754 const SmallVectorImpl<std::pair<llvm::Register, llvm::SDValue>> &Regs,
23762 F,
"Argument register required, but has been reserved."});
23768 if (
N->getNumValues() != 1)
23770 if (!
N->hasNUsesOfValue(1, 0))
23773 SDNode *Copy = *
N->user_begin();
23775 if (Copy->getOpcode() == ISD::BITCAST) {
23787 if (Copy->getOperand(Copy->getNumOperands() - 1).getValueType() == MVT::Glue)
23791 bool HasRet =
false;
23793 if (
Node->getOpcode() != RISCVISD::RET_GLUE)
23800 Chain = Copy->getOperand(0);
23812 if (Constraint.
size() == 1) {
23813 switch (Constraint[0]) {
23830 if (Constraint ==
"vr" || Constraint ==
"vd" || Constraint ==
"vm")
23832 if (Constraint ==
"cr" || Constraint ==
"cR" || Constraint ==
"cf")
23838std::pair<unsigned, const TargetRegisterClass *>
23844 if (Constraint.
size() == 1) {
23845 switch (Constraint[0]) {
23850 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
23851 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
23852 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
23853 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
23854 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23855 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23856 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
23858 if (VT == MVT::f16) {
23859 if (Subtarget.hasStdExtZfhmin())
23860 return std::make_pair(0U, &RISCV::FPR16RegClass);
23861 if (Subtarget.hasStdExtZhinxmin())
23862 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
23863 }
else if (VT == MVT::f32) {
23864 if (Subtarget.hasStdExtF())
23865 return std::make_pair(0U, &RISCV::FPR32RegClass);
23866 if (Subtarget.hasStdExtZfinx())
23867 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
23868 }
else if (VT == MVT::f64) {
23869 if (Subtarget.hasStdExtD())
23870 return std::make_pair(0U, &RISCV::FPR64RegClass);
23871 if (Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23872 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23873 if (Subtarget.hasStdExtZdinx() && Subtarget.is64Bit())
23874 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
23878 if (((VT == MVT::i64 || VT == MVT::f64) && !Subtarget.is64Bit()) ||
23879 (VT == MVT::i128 && Subtarget.is64Bit()))
23880 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23885 }
else if (Constraint ==
"vr") {
23886 for (
const auto *RC :
23887 {&RISCV::VRRegClass, &RISCV::VRM2RegClass, &RISCV::VRM4RegClass,
23888 &RISCV::VRM8RegClass, &RISCV::VRN2M1RegClass, &RISCV::VRN3M1RegClass,
23889 &RISCV::VRN4M1RegClass, &RISCV::VRN5M1RegClass,
23890 &RISCV::VRN6M1RegClass, &RISCV::VRN7M1RegClass,
23891 &RISCV::VRN8M1RegClass, &RISCV::VRN2M2RegClass,
23892 &RISCV::VRN3M2RegClass, &RISCV::VRN4M2RegClass,
23893 &RISCV::VRN2M4RegClass}) {
23895 return std::make_pair(0U, RC);
23899 if (
TRI->isTypeLegalForClass(*RC, ContainerVT))
23900 return std::make_pair(0U, RC);
23903 }
else if (Constraint ==
"vd") {
23904 for (
const auto *RC :
23905 {&RISCV::VRNoV0RegClass, &RISCV::VRM2NoV0RegClass,
23906 &RISCV::VRM4NoV0RegClass, &RISCV::VRM8NoV0RegClass,
23907 &RISCV::VRN2M1NoV0RegClass, &RISCV::VRN3M1NoV0RegClass,
23908 &RISCV::VRN4M1NoV0RegClass, &RISCV::VRN5M1NoV0RegClass,
23909 &RISCV::VRN6M1NoV0RegClass, &RISCV::VRN7M1NoV0RegClass,
23910 &RISCV::VRN8M1NoV0RegClass, &RISCV::VRN2M2NoV0RegClass,
23911 &RISCV::VRN3M2NoV0RegClass, &RISCV::VRN4M2NoV0RegClass,
23912 &RISCV::VRN2M4NoV0RegClass}) {
23914 return std::make_pair(0U, RC);
23918 if (
TRI->isTypeLegalForClass(*RC, ContainerVT))
23919 return std::make_pair(0U, RC);
23922 }
else if (Constraint ==
"vm") {
23923 if (
TRI->isTypeLegalForClass(RISCV::VMV0RegClass, VT.
SimpleTy))
23924 return std::make_pair(0U, &RISCV::VMV0RegClass);
23930 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, ContainerVT))
23931 return std::make_pair(0U, &RISCV::VMV0RegClass);
23933 }
else if (Constraint ==
"cr") {
23934 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
23935 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
23936 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
23937 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
23938 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23939 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23941 return std::make_pair(0U, &RISCV::GPRCRegClass);
23942 }
else if (Constraint ==
"cR") {
23943 if (((VT == MVT::i64 || VT == MVT::f64) && !Subtarget.is64Bit()) ||
23944 (VT == MVT::i128 && Subtarget.is64Bit()))
23945 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23946 }
else if (Constraint ==
"cf") {
23947 if (VT == MVT::f16) {
23948 if (Subtarget.hasStdExtZfhmin())
23949 return std::make_pair(0U, &RISCV::FPR16CRegClass);
23950 if (Subtarget.hasStdExtZhinxmin())
23951 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
23952 }
else if (VT == MVT::f32) {
23953 if (Subtarget.hasStdExtF())
23954 return std::make_pair(0U, &RISCV::FPR32CRegClass);
23955 if (Subtarget.hasStdExtZfinx())
23956 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
23957 }
else if (VT == MVT::f64) {
23958 if (Subtarget.hasStdExtD())
23959 return std::make_pair(0U, &RISCV::FPR64CRegClass);
23960 if (Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23961 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23962 if (Subtarget.hasStdExtZdinx() && Subtarget.is64Bit())
23963 return std::make_pair(0U, &RISCV::GPRCRegClass);
23972 .
Case(
"{zero}", RISCV::X0)
23973 .
Case(
"{ra}", RISCV::X1)
23974 .
Case(
"{sp}", RISCV::X2)
23975 .
Case(
"{gp}", RISCV::X3)
23976 .
Case(
"{tp}", RISCV::X4)
23977 .
Case(
"{t0}", RISCV::X5)
23978 .
Case(
"{t1}", RISCV::X6)
23979 .
Case(
"{t2}", RISCV::X7)
23980 .
Cases({
"{s0}",
"{fp}"}, RISCV::X8)
23981 .Case(
"{s1}", RISCV::X9)
23982 .
Case(
"{a0}", RISCV::X10)
23983 .
Case(
"{a1}", RISCV::X11)
23984 .
Case(
"{a2}", RISCV::X12)
23985 .
Case(
"{a3}", RISCV::X13)
23986 .
Case(
"{a4}", RISCV::X14)
23987 .
Case(
"{a5}", RISCV::X15)
23988 .
Case(
"{a6}", RISCV::X16)
23989 .
Case(
"{a7}", RISCV::X17)
23990 .
Case(
"{s2}", RISCV::X18)
23991 .
Case(
"{s3}", RISCV::X19)
23992 .
Case(
"{s4}", RISCV::X20)
23993 .
Case(
"{s5}", RISCV::X21)
23994 .
Case(
"{s6}", RISCV::X22)
23995 .
Case(
"{s7}", RISCV::X23)
23996 .
Case(
"{s8}", RISCV::X24)
23997 .
Case(
"{s9}", RISCV::X25)
23998 .
Case(
"{s10}", RISCV::X26)
23999 .
Case(
"{s11}", RISCV::X27)
24000 .
Case(
"{t3}", RISCV::X28)
24001 .
Case(
"{t4}", RISCV::X29)
24002 .
Case(
"{t5}", RISCV::X30)
24003 .
Case(
"{t6}", RISCV::X31)
24005 if (XRegFromAlias != RISCV::NoRegister)
24006 return std::make_pair(XRegFromAlias, &RISCV::GPRRegClass);
24015 if (Subtarget.hasStdExtF()) {
24017 .
Cases({
"{f0}",
"{ft0}"}, RISCV::F0_F)
24018 .Cases({
"{f1}",
"{ft1}"}, RISCV::F1_F)
24019 .Cases({
"{f2}",
"{ft2}"}, RISCV::F2_F)
24020 .Cases({
"{f3}",
"{ft3}"}, RISCV::F3_F)
24021 .Cases({
"{f4}",
"{ft4}"}, RISCV::F4_F)
24022 .Cases({
"{f5}",
"{ft5}"}, RISCV::F5_F)
24023 .Cases({
"{f6}",
"{ft6}"}, RISCV::F6_F)
24024 .Cases({
"{f7}",
"{ft7}"}, RISCV::F7_F)
24025 .Cases({
"{f8}",
"{fs0}"}, RISCV::F8_F)
24026 .Cases({
"{f9}",
"{fs1}"}, RISCV::F9_F)
24027 .Cases({
"{f10}",
"{fa0}"}, RISCV::F10_F)
24028 .Cases({
"{f11}",
"{fa1}"}, RISCV::F11_F)
24029 .Cases({
"{f12}",
"{fa2}"}, RISCV::F12_F)
24030 .Cases({
"{f13}",
"{fa3}"}, RISCV::F13_F)
24031 .Cases({
"{f14}",
"{fa4}"}, RISCV::F14_F)
24032 .Cases({
"{f15}",
"{fa5}"}, RISCV::F15_F)
24033 .Cases({
"{f16}",
"{fa6}"}, RISCV::F16_F)
24034 .Cases({
"{f17}",
"{fa7}"}, RISCV::F17_F)
24035 .Cases({
"{f18}",
"{fs2}"}, RISCV::F18_F)
24036 .Cases({
"{f19}",
"{fs3}"}, RISCV::F19_F)
24037 .Cases({
"{f20}",
"{fs4}"}, RISCV::F20_F)
24038 .Cases({
"{f21}",
"{fs5}"}, RISCV::F21_F)
24039 .Cases({
"{f22}",
"{fs6}"}, RISCV::F22_F)
24040 .Cases({
"{f23}",
"{fs7}"}, RISCV::F23_F)
24041 .Cases({
"{f24}",
"{fs8}"}, RISCV::F24_F)
24042 .Cases({
"{f25}",
"{fs9}"}, RISCV::F25_F)
24043 .Cases({
"{f26}",
"{fs10}"}, RISCV::F26_F)
24044 .Cases({
"{f27}",
"{fs11}"}, RISCV::F27_F)
24045 .Cases({
"{f28}",
"{ft8}"}, RISCV::F28_F)
24046 .Cases({
"{f29}",
"{ft9}"}, RISCV::F29_F)
24047 .Cases({
"{f30}",
"{ft10}"}, RISCV::F30_F)
24048 .Cases({
"{f31}",
"{ft11}"}, RISCV::F31_F)
24050 if (FReg != RISCV::NoRegister) {
24051 assert(RISCV::F0_F <= FReg && FReg <= RISCV::F31_F &&
"Unknown fp-reg");
24052 if (Subtarget.hasStdExtD() && (VT == MVT::f64 || VT == MVT::Other)) {
24053 unsigned RegNo = FReg - RISCV::F0_F;
24054 unsigned DReg = RISCV::F0_D + RegNo;
24055 return std::make_pair(DReg, &RISCV::FPR64RegClass);
24057 if (VT == MVT::f32 || VT == MVT::Other)
24058 return std::make_pair(FReg, &RISCV::FPR32RegClass);
24059 if (Subtarget.hasStdExtZfhmin() && VT == MVT::f16) {
24060 unsigned RegNo = FReg - RISCV::F0_F;
24061 unsigned HReg = RISCV::F0_H + RegNo;
24062 return std::make_pair(HReg, &RISCV::FPR16RegClass);
24067 if (Subtarget.hasVInstructions()) {
24069 .
Case(
"{v0}", RISCV::V0)
24070 .
Case(
"{v1}", RISCV::V1)
24071 .
Case(
"{v2}", RISCV::V2)
24072 .
Case(
"{v3}", RISCV::V3)
24073 .
Case(
"{v4}", RISCV::V4)
24074 .
Case(
"{v5}", RISCV::V5)
24075 .
Case(
"{v6}", RISCV::V6)
24076 .
Case(
"{v7}", RISCV::V7)
24077 .
Case(
"{v8}", RISCV::V8)
24078 .
Case(
"{v9}", RISCV::V9)
24079 .
Case(
"{v10}", RISCV::V10)
24080 .
Case(
"{v11}", RISCV::V11)
24081 .
Case(
"{v12}", RISCV::V12)
24082 .
Case(
"{v13}", RISCV::V13)
24083 .
Case(
"{v14}", RISCV::V14)
24084 .
Case(
"{v15}", RISCV::V15)
24085 .
Case(
"{v16}", RISCV::V16)
24086 .
Case(
"{v17}", RISCV::V17)
24087 .
Case(
"{v18}", RISCV::V18)
24088 .
Case(
"{v19}", RISCV::V19)
24089 .
Case(
"{v20}", RISCV::V20)
24090 .
Case(
"{v21}", RISCV::V21)
24091 .
Case(
"{v22}", RISCV::V22)
24092 .
Case(
"{v23}", RISCV::V23)
24093 .
Case(
"{v24}", RISCV::V24)
24094 .
Case(
"{v25}", RISCV::V25)
24095 .
Case(
"{v26}", RISCV::V26)
24096 .
Case(
"{v27}", RISCV::V27)
24097 .
Case(
"{v28}", RISCV::V28)
24098 .
Case(
"{v29}", RISCV::V29)
24099 .
Case(
"{v30}", RISCV::V30)
24100 .
Case(
"{v31}", RISCV::V31)
24102 if (VReg != RISCV::NoRegister) {
24103 if (
TRI->isTypeLegalForClass(RISCV::VMRegClass, VT.
SimpleTy))
24104 return std::make_pair(VReg, &RISCV::VMRegClass);
24105 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, VT.
SimpleTy))
24106 return std::make_pair(VReg, &RISCV::VRRegClass);
24107 for (
const auto *RC :
24108 {&RISCV::VRM2RegClass, &RISCV::VRM4RegClass, &RISCV::VRM8RegClass}) {
24109 if (
TRI->isTypeLegalForClass(*RC, VT.
SimpleTy)) {
24110 VReg =
TRI->getMatchingSuperReg(VReg, RISCV::sub_vrm1_0, RC);
24111 return std::make_pair(VReg, RC);
24123 if (ConstraintCode.
size() == 1) {
24124 switch (ConstraintCode[0]) {
24139 if (Constraint.
size() == 1) {
24140 switch (Constraint[0]) {
24147 Subtarget.getXLenVT()));
24178 if (Subtarget.hasStdExtZtso()) {
24180 return Builder.CreateFence(Ord);
24185 return Builder.CreateFence(Ord);
24194 if (Subtarget.hasStdExtZtso()) {
24196 return Builder.CreateFence(Ord);
24202 if (Subtarget.enableTrailingSeqCstFence() &&
isa<StoreInst>(Inst) &&
24221 if (Subtarget.hasForcedAtomics())
24226 if (Subtarget.hasStdExtZacas() &&
24227 (
Size >= 32 || Subtarget.hasStdExtZabha()))
24233 if (
Size < 32 && !Subtarget.hasStdExtZabha())
24245 return Intrinsic::riscv_masked_atomicrmw_xchg;
24247 return Intrinsic::riscv_masked_atomicrmw_add;
24249 return Intrinsic::riscv_masked_atomicrmw_sub;
24251 return Intrinsic::riscv_masked_atomicrmw_nand;
24253 return Intrinsic::riscv_masked_atomicrmw_max;
24255 return Intrinsic::riscv_masked_atomicrmw_min;
24257 return Intrinsic::riscv_masked_atomicrmw_umax;
24259 return Intrinsic::riscv_masked_atomicrmw_umin;
24275 Builder.CreateNot(Mask,
"Inv_Mask"),
24282 unsigned XLen = Subtarget.getXLen();
24285 Type *Tys[] = {Builder.getIntNTy(XLen), AlignedAddr->
getType()};
24291 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
24292 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
24293 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
24306 unsigned ValWidth =
24309 Builder.CreateSub(Builder.getIntN(XLen, XLen - ValWidth), ShiftAmt);
24310 Result = Builder.CreateCall(LrwOpScwLoop,
24311 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
24314 Builder.CreateCall(LrwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
24318 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
24326 if (Subtarget.hasForcedAtomics())
24330 if (!(Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas()) &&
24339 unsigned XLen = Subtarget.getXLen();
24340 Value *Ordering = Builder.getIntN(XLen,
static_cast<uint64_t>(Ord));
24341 Intrinsic::ID CmpXchgIntrID = Intrinsic::riscv_masked_cmpxchg;
24343 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
24344 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
24345 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
24347 Type *Tys[] = {Builder.getIntNTy(XLen), AlignedAddr->
getType()};
24348 Value *Result = Builder.CreateIntrinsic(
24349 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, Ordering});
24351 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
24356 EVT DataVT)
const {
24372 return Subtarget.hasStdExtZfhmin();
24374 return Subtarget.hasStdExtF();
24376 return Subtarget.hasStdExtD();
24406 assert(Subtarget.getRealMinVLen() >= 64 &&
"zve32* unsupported");
24408 "RVVBitsPerBlock changed, audit needed");
24417 if (!Subtarget.hasVendorXTHeadMemIdx())
24423 Base =
Op->getOperand(0);
24425 int64_t RHSC = RHS->getSExtValue();
24431 bool isLegalIndexedOffset =
false;
24432 for (
unsigned i = 0; i < 4; i++)
24433 if (
isInt<5>(RHSC >> i) && ((RHSC % (1LL << i)) == 0)) {
24434 isLegalIndexedOffset =
true;
24438 if (!isLegalIndexedOffset)
24455 VT = LD->getMemoryVT();
24456 Ptr = LD->getBasePtr();
24458 VT = ST->getMemoryVT();
24459 Ptr = ST->getBasePtr();
24475 if (Subtarget.hasVendorXCVmem() && !Subtarget.is64Bit()) {
24480 Base = LS->getBasePtr();
24484 if (
Base ==
Op->getOperand(0))
24486 else if (
Base ==
Op->getOperand(1))
24498 VT = LD->getMemoryVT();
24499 Ptr = LD->getBasePtr();
24501 VT = ST->getMemoryVT();
24502 Ptr = ST->getBasePtr();
24526 return VT.
isVector() ? Subtarget.hasVInstructionsF16()
24527 : Subtarget.hasStdExtZfhOrZhinx();
24529 return Subtarget.hasStdExtFOrZfinx();
24531 return Subtarget.hasStdExtDOrZdinx();
24546 if (Subtarget.hasStdExtZaamo() || Subtarget.hasForcedAtomics())
24550 assert(Subtarget.hasStdExtZalrsc());
24552 case ISD::ATOMIC_LOAD_MIN:
24553 case ISD::ATOMIC_LOAD_MAX:
24554 case ISD::ATOMIC_LOAD_UMIN:
24555 case ISD::ATOMIC_LOAD_UMAX:
24564 const Constant *PersonalityFn)
const {
24569 const Constant *PersonalityFn)
const {
24576 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
24577 Type.getSizeInBits() < Subtarget.getXLen()))
24584 bool IsSigned)
const {
24585 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
24599 const bool HasZmmul = Subtarget.hasStdExtZmmul();
24604 const APInt &Imm = ConstNode->getAPIntValue();
24607 if (Subtarget.hasVendorXqciac() && Imm.isSignedIntN(12))
24611 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
24612 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
24616 if (Subtarget.hasShlAdd(3) && !Imm.isSignedIntN(12) &&
24617 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
24618 (Imm - 8).isPowerOf2()))
24623 if (!Imm.isSignedIntN(12) && Imm.countr_zero() < 12 &&
24624 ConstNode->hasOneUse()) {
24625 APInt ImmS = Imm.ashr(Imm.countr_zero());
24626 if ((ImmS + 1).isPowerOf2() || (ImmS - 1).isPowerOf2() ||
24627 (1 - ImmS).isPowerOf2())
24650 if (C1.
isSignedIntN(12) && !(C1 * C2).isSignedIntN(12))
24659 unsigned *
Fast)
const {
24662 *
Fast = Subtarget.enableUnalignedScalarMem();
24663 return Subtarget.enableUnalignedScalarMem();
24679 *
Fast = Subtarget.enableUnalignedVectorMem();
24680 return Subtarget.enableUnalignedVectorMem();
24685 const AttributeList &FuncAttributes)
const {
24686 if (!Subtarget.hasVInstructions())
24689 if (FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat))
24701 const unsigned MinVLenInBytes =
24702 std::min(Subtarget.getRealMinVLen() / 8, 1024U);
24704 if (
Op.size() < MinVLenInBytes)
24719 MVT PreferredVT = (
Op.isMemset() && !
Op.isZeroMemset()) ? MVT::i8 : ELenVT;
24723 if (PreferredVT != MVT::i8 && !Subtarget.enableUnalignedVectorMem()) {
24725 if (
Op.isFixedDstAlign())
24726 RequiredAlign = std::min(RequiredAlign,
Op.getDstAlign());
24728 RequiredAlign = std::min(RequiredAlign,
Op.getSrcAlign());
24736 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
24737 bool IsABIRegCopy = CC.has_value();
24740 MVT PairVT = Subtarget.is64Bit() ? MVT::i128 : MVT::i64;
24741 if ((ValueVT == PairVT ||
24742 (!Subtarget.is64Bit() && Subtarget.hasStdExtZdinx() &&
24743 ValueVT == MVT::f64)) &&
24744 NumParts == 1 && PartVT == MVT::Untyped) {
24746 MVT XLenVT = Subtarget.getXLenVT();
24747 if (ValueVT == MVT::f64)
24752 Parts[0] = DAG.
getNode(RISCVISD::BuildGPRPair,
DL, PartVT,
Lo,
Hi);
24756 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
24757 PartVT == MVT::f32) {
24760 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::i16, Val);
24764 Val = DAG.
getNode(ISD::BITCAST,
DL, PartVT, Val);
24772 [[maybe_unused]]
unsigned ValLMUL =
24776 [[maybe_unused]]
unsigned PartLMUL =
24779 assert(ValNF == PartNF && ValLMUL == PartLMUL &&
24780 "RISC-V vector tuple type only accepts same register class type "
24801 if (PartVTBitSize % ValueVTBitSize == 0) {
24802 assert(PartVTBitSize >= ValueVTBitSize);
24809 if (ValueEltVT != PartEltVT) {
24810 if (PartVTBitSize > ValueVTBitSize) {
24812 assert(
Count != 0 &&
"The number of element should not be zero.");
24813 EVT SameEltTypeVT =
24817 Val = DAG.
getNode(ISD::BITCAST,
DL, PartVT, Val);
24831 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
24832 bool IsABIRegCopy = CC.has_value();
24834 MVT PairVT = Subtarget.is64Bit() ? MVT::i128 : MVT::i64;
24835 if ((ValueVT == PairVT ||
24836 (!Subtarget.is64Bit() && Subtarget.hasStdExtZdinx() &&
24837 ValueVT == MVT::f64)) &&
24838 NumParts == 1 && PartVT == MVT::Untyped) {
24840 MVT XLenVT = Subtarget.getXLenVT();
24849 if (ValueVT == MVT::f64)
24854 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
24855 PartVT == MVT::f32) {
24859 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::i32, Val);
24861 Val = DAG.
getNode(ISD::BITCAST,
DL, ValueVT, Val);
24877 if (PartVTBitSize % ValueVTBitSize == 0) {
24878 assert(PartVTBitSize >= ValueVTBitSize);
24879 EVT SameEltTypeVT = ValueVT;
24886 if (ValueEltVT != PartEltVT) {
24888 assert(
Count != 0 &&
"The number of element should not be zero.");
24891 Val = DAG.
getNode(ISD::BITCAST,
DL, SameEltTypeVT, Val);
24907 bool OptSize = Attr.hasFnAttr(Attribute::MinSize);
24908 return OptSize && !VT.
isVector() &&
24915 unsigned Opc =
N->getOpcode();
24924 M, Intrinsic::thread_pointer, IRB.
getPtrTy());
24932 if (Subtarget.isTargetFuchsia())
24938 if (Subtarget.isTargetAndroid())
24943 if (M->getStackProtectorGuard() ==
"tls") {
24945 int Offset = M->getStackProtectorGuardOffset();
24953 Align Alignment)
const {
24954 if (!Subtarget.hasVInstructions())
24958 if (DataType.isFixedLengthVector() && !Subtarget.useRVVForFixedLengthVectors())
24965 if (!Subtarget.enableUnalignedVectorMem() &&
24977 "Invalid call instruction for a KCFI check");
24979 MBBI->getOpcode()));
24982 Target.setIsRenamable(
false);
24990#define GET_REGISTER_MATCHER
24991#include "RISCVGenAsmMatcher.inc"
25002 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
25003 if (!ReservedRegs.
test(Reg) && !Subtarget.isRegisterReservedByUser(Reg))
25011 const MDNode *NontemporalInfo =
I.getMetadata(LLVMContext::MD_nontemporal);
25013 if (NontemporalInfo ==
nullptr)
25021 int NontemporalLevel = 5;
25022 const MDNode *RISCVNontemporalInfo =
25023 I.getMetadata(
"riscv-nontemporal-domain");
25024 if (RISCVNontemporalInfo !=
nullptr)
25031 assert((1 <= NontemporalLevel && NontemporalLevel <= 5) &&
25032 "RISC-V target doesn't support this non-temporal domain.");
25034 NontemporalLevel -= 2;
25036 if (NontemporalLevel & 0b1)
25038 if (NontemporalLevel & 0b10)
25051 return TargetFlags;
25064 return Subtarget.hasStdExtZvbb();
25069 return Subtarget.hasCPOPLike() && (VT == MVT::i32 || VT == MVT::i64);
25079 if (Subtarget.hasStdExtZalasr()) {
25080 if (Subtarget.hasStdExtZtso()) {
25110 if (
Op == Instruction::Add ||
Op == Instruction::Sub ||
25111 Op == Instruction::And ||
Op == Instruction::Or ||
25112 Op == Instruction::Xor ||
Op == Instruction::InsertElement ||
25113 Op == Instruction::ShuffleVector ||
Op == Instruction::Load ||
25114 Op == Instruction::Freeze ||
Op == Instruction::Store)
25119 if (RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(
II->getIntrinsicID())) {
25124 for (
unsigned i = 0; i <
II->arg_size(); ++i)
25125 if (
II->getArgOperand(i)->getType()->isRISCVVectorTupleTy())
25141 if (AI->getAllocatedType()->isScalableTy())
25149RISCVTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
25157 if (!Subtarget.hasShortForwardBranchOpt())
25159 EVT VT =
N->getValueType(0);
25160 if (!(VT == MVT::i32 || (VT == MVT::i64 && Subtarget.
is64Bit())))
25164 if (Divisor.
sgt(2048) || Divisor.
slt(-2048))
25169bool RISCVTargetLowering::shouldFoldSelectWithSingleBitTest(
25170 EVT VT,
const APInt &AndMask)
const {
25171 if (Subtarget.
hasCZEROLike() || Subtarget.hasVendorXTHeadCondMov())
25177 return Subtarget.getMinimumJumpTableEntries();
25184 if (Subtarget.hasStdExtZicfilp()) {
25191 return DAG.
getNode(RISCVISD::SW_GUARDED_BRIND, dl, MVT::Other, Chain, Addr);
25208std::pair<const TargetRegisterClass *, uint8_t>
25228#define GET_RISCVVIntrinsicsTable_IMPL
25229#include "RISCVGenSearchableTables.inc"
25244 Align StackAlign)
const {
25248 unsigned StackProbeSize =
25252 return StackProbeSize ? StackProbeSize : StackAlign.
value();
25269 EVT VT =
Op.getValueType();
25280 Chain = DAG.
getNode(RISCVISD::PROBED_ALLOCA, dl, MVT::Other, Chain, SP);
25290 Register TargetReg =
MI.getOperand(0).getReg();
25293 bool IsRV64 = Subtarget.is64Bit();
25294 Align StackAlign = Subtarget.getFrameLowering()->getStackAlign();
25301 MF.
insert(MBBInsertPoint, LoopTestMBB);
25303 MF.
insert(MBBInsertPoint, ExitMBB);
25319 TII->get(IsRV64 ? RISCV::SD : RISCV::SW))
25340 MBB->addSuccessor(LoopTestMBB);
25342 MI.eraseFromParent();
25344 return ExitMBB->
begin()->getParent();
25348 if (Subtarget.hasStdExtFOrZfinx()) {
25349 static const MCPhysReg RCRegs[] = {RISCV::FRM, RISCV::FFLAGS};
25356 EVT VT =
Y.getValueType();
unsigned const MachineRegisterInfo * MRI
static MCRegister MatchRegisterName(StringRef Name)
static EVT getContainerForFixedLengthVector(SelectionDAG &DAG, EVT VT)
static SDValue performSHLCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
If the operand is a bitwise AND with a constant RHS, and the shift has a constant RHS and is the only...
static SDValue performORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const AArch64Subtarget *Subtarget, const AArch64TargetLowering &TLI)
static SDValue performANDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG)
static SDValue tryWidenMaskForShuffle(SDValue Op, SelectionDAG &DAG)
static SDValue performSETCCCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
static SDValue convertToScalableVector(SelectionDAG &DAG, EVT VT, SDValue V)
static SDValue convertFromScalableVector(SelectionDAG &DAG, EVT VT, SDValue V)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isConstant(const MachineInstr &MI)
AMDGPU Register Bank Select
static bool isZeroOrAllOnes(SDValue N, bool AllOnes)
static SDValue combineSelectAndUseCommutative(SDNode *N, bool AllOnes, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp, TargetLowering::DAGCombinerInfo &DCI, bool AllOnes=false)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static MCRegister MatchRegisterAltName(StringRef Name)
Maps from the set of all alternative registernames to a register number.
Function Alias Analysis Results
static SDValue getTargetNode(ConstantPoolSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, unsigned Flags)
static constexpr unsigned long long mask(BlockVerifier::State S)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static MachineBasicBlock * emitSelectPseudo(MachineInstr &MI, MachineBasicBlock *BB, unsigned Opcode)
static SDValue unpackFromRegLoc(const CSKYSubtarget &Subtarget, SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
static InstructionCost getCost(Instruction &Inst, TTI::TargetCostKind CostKind, TargetTransformInfo &TTI, TargetLibraryInfo &TLI)
const HexagonInstrInfo * TII
This file defines an InstructionCost class that is used when calculating the cost of an instruction,...
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define CC_VLS_CASE(ABIVlen)
static Align getPrefTypeAlign(EVT VT, SelectionDAG &DAG)
static std::optional< bool > matchSetCC(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue Val)
static SDValue customLegalizeToWOpWithSExt(SDNode *N, SelectionDAG &DAG)
static SDValue foldBinOpIntoSelectIfProfitable(SDNode *BO, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue customLegalizeToWOp(SDNode *N, SelectionDAG &DAG, int NumOp, unsigned ExtOpc=ISD::ANY_EXTEND)
static bool combine_CC(SDValue &LHS, SDValue &RHS, SDValue &CC, const SDLoc &DL, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static MachineBasicBlock * emitBuildPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static Intrinsic::ID getIntrinsicForMaskedAtomicRMWBinOp(unsigned GRLen, AtomicRMWInst::BinOp BinOp)
static void translateSetCCForBranch(const SDLoc &DL, SDValue &LHS, SDValue &RHS, ISD::CondCode &CC, SelectionDAG &DAG)
static bool isSplat(Value *V)
Return true if V is a splat of a value (which is used when multiplying a matrix with a scalar).
Register const TargetRegisterInfo * TRI
Promote Memory to Register
This file provides utility analysis objects describing memory locations.
static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const MipsSubtarget &Subtarget)
static SDValue performSUBCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const MipsSubtarget &Subtarget)
static SDValue performSELECTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const MipsSubtarget &Subtarget)
static SDValue performMULCombine(SDNode *N, SelectionDAG &DAG, const TargetLowering::DAGCombinerInfo &DCI, const MipsSETargetLowering *TL, const MipsSubtarget &Subtarget)
static SDValue performXORCombine(SDNode *N, SelectionDAG &DAG, const MipsSubtarget &Subtarget)
static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG)
static SDValue performSRACombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const MipsSubtarget &Subtarget)
MachineInstr unsigned OpIdx
uint64_t IntrinsicInst * II
static CodeModel::Model getCodeModel(const PPCSubtarget &S, const TargetMachine &TM, const MachineOperand &MO)
static StringRef getName(Value *V)
static constexpr MCPhysReg SPReg
static StringRef getExtensionType(StringRef Ext)
static SDValue performCONCAT_VECTORSCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue SplitVectorReductionOp(SDValue Op, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static MachineBasicBlock * emitQuietFCMP(MachineInstr &MI, MachineBasicBlock *BB, unsigned RelOpcode, unsigned EqOpcode, const RISCVSubtarget &Subtarget)
static void processVCIXOperands(SDValue OrigOp, MutableArrayRef< SDValue > Operands, SelectionDAG &DAG)
static bool isLowSourceShuffle(ArrayRef< int > Mask, int Span)
Is this mask only using elements from the first span of the input?
static bool isZipOdd(const std::array< std::pair< int, int >, 2 > &SrcInfo, ArrayRef< int > Mask, unsigned &Factor)
Given a shuffle which can be represented as a pair of two slides, see if it is a zipodd idiom.
static SDValue lowerVZIP(unsigned Opc, SDValue Op0, SDValue Op1, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerBuildVectorOfConstants(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue performVECREDUCECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue lowerVECTOR_SHUFFLEAsVSlide1(const SDLoc &DL, MVT VT, SDValue V1, SDValue V2, ArrayRef< int > Mask, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
Match v(f)slide1up/down idioms.
static SDValue combineTruncToVnclip(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::optional< APInt > getExactInteger(const APFloat &APF, uint32_t BitWidth)
static SDValue performVP_TRUNCATECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isInterleaveShuffle(ArrayRef< int > Mask, MVT VT, int &EvenSrc, int &OddSrc, const RISCVSubtarget &Subtarget)
Is this shuffle interleaving contiguous elements from one vector into the even elements and contiguou...
static bool narrowIndex(SDValue &N, ISD::MemIndexType IndexType, SelectionDAG &DAG)
According to the property that indexed load/store instructions zero-extend their indices,...
static SDValue getSingleShuffleSrc(MVT VT, SDValue V1, SDValue V2)
static unsigned getPACKOpcode(unsigned DestBW, const RISCVSubtarget &Subtarget)
static SDValue splatSplitI64WithVL(const SDLoc &DL, MVT VT, SDValue Passthru, SDValue Scalar, SDValue VL, SelectionDAG &DAG)
static bool isLegalBitRotate(ArrayRef< int > Mask, EVT VT, const RISCVSubtarget &Subtarget, MVT &RotateVT, unsigned &RotateAmt)
static SDValue splatPartsI64WithVL(const SDLoc &DL, MVT VT, SDValue Passthru, SDValue Lo, SDValue Hi, SDValue VL, SelectionDAG &DAG)
static SDValue getWideningInterleave(SDValue EvenV, SDValue OddV, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue getAllOnesMask(MVT VecVT, SDValue VL, const SDLoc &DL, SelectionDAG &DAG)
Creates an all ones mask suitable for masking a vector of type VecTy with vector length VL.
static SDValue simplifyOp_VL(SDNode *N)
static SDValue lowerScalarSplat(SDValue Passthru, SDValue Scalar, SDValue VL, MVT VT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isAlternating(const std::array< std::pair< int, int >, 2 > &SrcInfo, ArrayRef< int > Mask, unsigned Factor, bool RequiredPolarity)
static cl::opt< int > FPImmCost(DEBUG_TYPE "-fpimm-cost", cl::Hidden, cl::desc("Give the maximum number of instructions that we will " "use for creating a floating-point immediate value"), cl::init(3))
static const RISCV::RISCVMaskedPseudoInfo * lookupMaskedIntrinsic(uint16_t MCOpcode, RISCVVType::VLMUL LMul, unsigned SEW)
static SDValue expandMul(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue performVWADDSUBW_VLCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static bool matchIndexAsWiderOp(EVT VT, SDValue Index, SDValue Mask, Align BaseAlign, const RISCVSubtarget &ST)
Match the index of a gather or scatter operation as an operation with twice the element width and hal...
static SDValue combineOp_VLToVWOp_VL(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
Combine a binary or FMA operation to its equivalent VW or VW_W form.
static SDValue combineVFMADD_VLWithVFNEG_VL(SDNode *N, SelectionDAG &DAG)
static SDValue combineOrOfCZERO(SDNode *N, SDValue N0, SDValue N1, SelectionDAG &DAG)
static SDValue useInversedSetcc(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static cl::opt< bool > ReassocShlAddiAdd("reassoc-shl-addi-add", cl::Hidden, cl::desc("Swap add and addi in cases where the add may " "be combined with a shift"), cl::init(true))
static SDValue lowerDisjointIndicesShuffle(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Given a shuffle where the indices are disjoint between the two sources, e.g.:
static SDValue combineVWADDSUBWSelect(SDNode *N, SelectionDAG &DAG)
static MachineBasicBlock * EmitLoweredCascadedSelect(MachineInstr &First, MachineInstr &Second, MachineBasicBlock *ThisMBB, const RISCVSubtarget &Subtarget)
static SDValue performINSERT_VECTOR_ELTCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue lowerFABSorFNEG(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerFMAXIMUM_FMINIMUM(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue foldReduceOperandViaVQDOT(SDValue InVec, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue reverseZExtICmpCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue SplitStrictFPVectorOp(SDValue Op, SelectionDAG &DAG)
static void promoteVCIXScalar(SDValue Op, MutableArrayRef< SDValue > Operands, SelectionDAG &DAG)
static SDValue tryDemorganOfBooleanCondition(SDValue Cond, SelectionDAG &DAG)
static SDValue performMemPairCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue combineDeMorganOfBoolean(SDNode *N, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLEAsVSlidedown(const SDLoc &DL, MVT VT, SDValue V1, SDValue V2, ArrayRef< int > Mask, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
static SDValue reduceANDOfAtomicLoad(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static unsigned getRVVReductionOp(unsigned ISDOpcode)
static SDValue combineSubShiftToOrcB(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerShuffleViaVRegSplitting(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static cl::opt< unsigned > NumRepeatedDivisors(DEBUG_TYPE "-fp-repeated-divisors", cl::Hidden, cl::desc("Set the minimum number of repetitions of a divisor to allow " "transformation to multiplications by the reciprocal"), cl::init(2))
static SDValue foldSelectOfCTTZOrCTLZ(SDNode *N, SelectionDAG &DAG)
static SDValue lowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerFixedVectorSegLoadIntrinsics(unsigned IntNo, SDValue Op, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
static SDValue combineVectorMulToSraBitcast(SDNode *N, SelectionDAG &DAG)
static bool isLocalRepeatingShuffle(ArrayRef< int > Mask, int Span)
Is this mask local (i.e.
static bool legalizeScatterGatherIndexType(SDLoc DL, SDValue &Index, ISD::MemIndexType &IndexType, RISCVTargetLowering::DAGCombinerInfo &DCI)
static bool isSpanSplatShuffle(ArrayRef< int > Mask, int Span)
Return true for a mask which performs an arbitrary shuffle within the first span, and then repeats th...
static SDValue getVSlidedown(SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const SDLoc &DL, EVT VT, SDValue Passthru, SDValue Op, SDValue Offset, SDValue Mask, SDValue VL, unsigned Policy=RISCVVType::TAIL_UNDISTURBED_MASK_UNDISTURBED)
static SDValue combineOrToBitfieldInsert(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue getVCIXISDNodeVOID(SDValue Op, SelectionDAG &DAG, unsigned Type)
static unsigned getRISCVVLOp(SDValue Op)
Get a RISC-V target specified VL op for a given SDNode.
static unsigned getVecReduceOpcode(unsigned Opc)
Given a binary operator, return the associative generic ISD::VECREDUCE_OP which corresponds to it.
static std::pair< SDValue, SDValue > getDefaultVLOps(uint64_t NumElts, MVT ContainerVT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isPromotedOpNeedingSplit(SDValue Op, const RISCVSubtarget &Subtarget)
static SDValue performFP_TO_INT_SATCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue lowerReductionSeq(unsigned RVVOpcode, MVT ResVT, SDValue StartValue, SDValue Vec, SDValue Mask, SDValue VL, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Helper to lower a reduction sequence of the form: scalar = reduce_op vec, scalar_start.
static SDValue expandMulToAddOrSubOfShl(SDNode *N, SelectionDAG &DAG, uint64_t MulAmt)
static SDValue performVP_REVERSECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerGetVectorLength(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::pair< SDValue, SDValue > getDefaultScalableVLOps(MVT VecVT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue getVLOperand(SDValue Op)
static SDValue performVECTOR_SHUFFLECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue performVP_STORECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static MachineBasicBlock * emitFROUND(MachineInstr &MI, MachineBasicBlock *MBB, const RISCVSubtarget &Subtarget)
static SDValue getLargeExternalSymbol(ExternalSymbolSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG)
static SDValue lowerCttzElts(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
const uint64_t ModeMask64
static SDValue lowerVectorIntrinsicScalars(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static cl::opt< unsigned > ExtensionMaxWebSize(DEBUG_TYPE "-ext-max-web-size", cl::Hidden, cl::desc("Give the maximum size (in number of nodes) of the web of " "instructions that we will consider for VW expansion"), cl::init(18))
static SDValue combineShlAddIAddImpl(SDNode *N, SDValue AddI, SDValue Other, SelectionDAG &DAG)
static SDValue getDeinterleaveShiftAndTrunc(const SDLoc &DL, MVT VT, SDValue Src, unsigned Factor, unsigned Index, SelectionDAG &DAG)
static SDValue combineBinOpOfZExt(SDNode *N, SelectionDAG &DAG)
static bool matchSelectAddSub(SDValue TrueVal, SDValue FalseVal, bool &SwapCC)
static SDValue performSIGN_EXTEND_INREGCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue combineXorToBitfieldInsert(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue combineANDOfSETCCToCZERO(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::optional< MVT > getSmallestVTForIndex(MVT VecVT, unsigned MaxIdx, SDLoc DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool useRVVForFixedLengthVectorVT(MVT VT, const RISCVSubtarget &Subtarget)
static bool isValidVisniInsertExtractIndex(SDValue Idx)
static Value * useTpOffset(IRBuilderBase &IRB, unsigned Offset)
static SDValue combineAddOfBooleanXor(SDNode *N, SelectionDAG &DAG)
static SDValue getZeroPaddedAdd(const SDLoc &DL, SDValue A, SDValue B, SelectionDAG &DAG)
Given fixed length vectors A and B with equal element types, but possibly different number of element...
const uint32_t ModeMask32
static SDValue combineTruncOfSraSext(SDNode *N, SelectionDAG &DAG)
static SDValue getVSlideup(SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const SDLoc &DL, EVT VT, SDValue Passthru, SDValue Op, SDValue Offset, SDValue Mask, SDValue VL, unsigned Policy=RISCVVType::TAIL_UNDISTURBED_MASK_UNDISTURBED)
static MachineBasicBlock * emitSplitF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const RISCVSubtarget &Subtarget)
static SDValue combineVqdotAccum(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static MachineBasicBlock * emitVFROUND_NOEXCEPT_MASK(MachineInstr &MI, MachineBasicBlock *BB, unsigned CVTXOpc)
static SDValue SplitVectorOp(SDValue Op, SelectionDAG &DAG)
static SDValue combineToVCPOP(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static unsigned negateFMAOpcode(unsigned Opcode, bool NegMul, bool NegAcc)
static SDValue lowerScalarInsert(SDValue Scalar, SDValue VL, MVT VT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerBuildVectorViaVID(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue transformAddShlImm(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue tryFoldSelectIntoOp(SDNode *N, SelectionDAG &DAG, SDValue TrueVal, SDValue FalseVal, bool Swapped)
static SDValue lowerBitreverseShuffle(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerConstant(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool matchIndexAsShuffle(EVT VT, SDValue Index, SDValue Mask, SmallVector< int > &ShuffleMask)
Match the index vector of a scatter or gather node as the shuffle mask which performs the rearrangeme...
static SDValue performVFMADD_VLCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue lowerFixedVectorSegStoreIntrinsics(unsigned IntNo, SDValue Op, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
static SDValue combineBinOpToReduce(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue SplitVPOp(SDValue Op, SelectionDAG &DAG)
static SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue widenVectorOpsToi8(SDValue N, const SDLoc &DL, SelectionDAG &DAG)
static SDValue lowerINT_TO_FP(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerVectorFTRUNC_FCEIL_FFLOOR_FROUND(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerFTRUNC_FCEIL_FFLOOR_FROUND(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::optional< VIDSequence > isSimpleVIDSequence(SDValue Op, unsigned EltSizeInBits)
static SDValue getVCIXISDNodeWCHAIN(SDValue Op, SelectionDAG &DAG, unsigned Type)
static SDValue lowerVectorXRINT_XROUND(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static uint64_t computeGREVOrGORC(uint64_t x, unsigned ShAmt, bool IsGORC)
static SDValue lowerVECTOR_SHUFFLEAsRotate(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isSimm12Constant(SDValue V)
static RISCVFPRndMode::RoundingMode matchRoundingOp(unsigned Opc)
static SDValue lowerVectorStrictFTRUNC_FCEIL_FFLOOR_FROUND(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue combineTruncSelectToSMaxUSat(SDNode *N, SelectionDAG &DAG)
static bool isElementRotate(const std::array< std::pair< int, int >, 2 > &SrcInfo, unsigned NumElts)
static SDValue performBITREVERSECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue transformAddImmMulImm(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue combineSubOfBoolean(SDNode *N, SelectionDAG &DAG)
static SDValue matchSplatAsGather(SDValue SplatVal, MVT VT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isValidEGW(int EGS, EVT VT, const RISCVSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLEAsVRGatherVX(ShuffleVectorSDNode *SVN, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
Match a single source shuffle which is an identity except that some particular element is repeated.
static bool isNonZeroAVL(SDValue AVL)
static SDValue lowerFP_TO_INT(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue getShlAddShlAdd(SDNode *N, SelectionDAG &DAG, unsigned ShX, unsigned ShY, bool AddX, unsigned Shift)
static MVT getQDOTXResultType(MVT OpVT)
static SDValue lowerVECTOR_SHUFFLEAsVSlideup(const SDLoc &DL, MVT VT, SDValue V1, SDValue V2, ArrayRef< int > Mask, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
static SDValue getLargeGlobalAddress(GlobalAddressSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG)
static MachineBasicBlock * emitReadCounterWidePseudo(MachineInstr &MI, MachineBasicBlock *BB)
static SDValue getWideningSpread(SDValue V, unsigned Factor, unsigned Index, const SDLoc &DL, SelectionDAG &DAG)
static cl::opt< bool > AllowSplatInVW_W(DEBUG_TYPE "-form-vw-w-with-splat", cl::Hidden, cl::desc("Allow the formation of VW_W operations (e.g., " "VWADD_W) with splat constants"), cl::init(false))
static SDValue unpackF64OnRV32DSoftABI(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const CCValAssign &HiVA, const SDLoc &DL)
static SDValue foldConcatVector(SDValue V1, SDValue V2)
If concat_vector(V1,V2) could be folded away to some existing vector source, return it.
static SDValue tryMemPairCombine(SelectionDAG &DAG, LSBaseSDNode *LSNode1, LSBaseSDNode *LSNode2, SDValue BasePtr, uint64_t Imm)
static std::tuple< unsigned, SDValue, SDValue > getRVVFPReductionOpAndOperands(SDValue Op, SelectionDAG &DAG, EVT EltVT, const RISCVSubtarget &Subtarget)
static SDValue performFP_TO_INTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue combineBinOpOfExtractToReduceTree(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Perform two related transforms whose purpose is to incrementally recognize an explode_vector followed...
static SDValue lowerBuildVectorViaPacking(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Double the element size of the build vector to reduce the number of vslide1down in the build vector c...
static SDValue performTRUNCATECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerSelectToBinOp(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue combineShlAddIAdd(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerBuildVectorViaDominantValues(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Try and optimize BUILD_VECTORs with "dominant values" - these are values which constitute a large pro...
static bool isCompressMask(ArrayRef< int > Mask)
static SDValue expandMulToNAFSequence(SDNode *N, SelectionDAG &DAG, uint64_t MulAmt)
static SDValue combineToVWMACC(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isZipEven(const std::array< std::pair< int, int >, 2 > &SrcInfo, ArrayRef< int > Mask, unsigned &Factor)
Given a shuffle which can be represented as a pair of two slides, see if it is a zipeven idiom.
static SDValue expandMulToShlAddShlAdd(SDNode *N, SelectionDAG &DAG, uint64_t MulAmt, unsigned Shift)
static SDValue combineVectorSizedSetCCEquality(EVT VT, SDValue X, SDValue Y, ISD::CondCode CC, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Try to map an integer comparison with size > XLEN to vector instructions before type legalization spl...
static SDValue performBUILD_VECTORCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
If we have a build_vector where each lane is binop X, C, where C is a constant (but not necessarily t...
static SDValue combineOrAndToBitfieldInsert(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static LLT getMaskTypeFor(LLT VecTy)
Return the type of the mask type suitable for masking the provided vector type.
static unsigned getRISCVWOpcode(unsigned Opcode)
const SmallVectorImpl< MachineOperand > & Cond
Contains matchers for matching SelectionDAG nodes and values.
static bool isCommutative(Instruction *I, Value *ValWithUses)
static Type * getValueType(Value *V)
Returns the type of the given value/instruction V.
This file defines the SmallSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static constexpr int Concat[]
static constexpr roundingMode rmNearestTiesToEven
static LLVM_ABI unsigned int semanticsPrecision(const fltSemantics &)
opStatus convertFromAPInt(const APInt &Input, bool IsSigned, roundingMode RM)
opStatus convertToInteger(MutableArrayRef< integerPart > Input, unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const
static APFloat getNaN(const fltSemantics &Sem, bool Negative=false, uint64_t payload=0)
Factory for NaN values.
Class for arbitrary precision integers.
bool isNegatedPowerOf2() const
Check if this APInt's negated value is a power of two greater than zero.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
uint64_t getZExtValue() const
Get zero extended value.
void setBitsFrom(unsigned loBit)
Set the top bits starting from loBit.
unsigned getActiveBits() const
Compute the number of active bits in the value.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
bool sgt(const APInt &RHS) const
Signed greater than comparison.
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
bool ugt(const APInt &RHS) const
Unsigned greater than comparison.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
unsigned getBitWidth() const
Return the number of bits in the APInt.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
bool isNegative() const
Determine sign of this APInt.
LLVM_ABI APInt sdiv(const APInt &RHS) const
Signed division function for APInt.
void clearAllBits()
Set every bit to 0.
unsigned countr_zero() const
Count the number of trailing zero bits.
bool isSignedIntN(unsigned N) const
Check if this APInt has an N-bits signed integer value.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
unsigned getSignificantBits() const
Get the minimum bit size for this signed APInt.
LLVM_ABI void insertBits(const APInt &SubBits, unsigned bitPosition)
Insert the bits from a smaller APInt starting at bitPosition.
bool isShiftedMask() const
Return true if this APInt value contains a non-empty sequence of ones with the remainder zero.
LLVM_ABI APInt srem(const APInt &RHS) const
Function for signed remainder operation.
bool isMask(unsigned numBits) const
bool isNonNegative() const
Determine if this APInt Value is non-negative (>= 0)
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
bool slt(const APInt &RHS) const
Signed less than comparison.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
void setLowBits(unsigned loBits)
Set the bottom loBits bits.
LLVM_ABI APInt extractBits(unsigned numBits, unsigned bitPosition) const
Return an APInt with the extracted bits [bitPosition,bitPosition+numBits).
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)
Constructs an APInt value that has a contiguous range of bits set.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
int64_t getSExtValue() const
Get sign extended value.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
An arbitrary precision integer that knows its signedness.
an instruction to allocate memory on the stack
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
An instruction that atomically checks whether a specified value is in a memory location,...
Value * getCompareOperand()
an instruction that atomically reads a memory location, combines it with another value,...
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ USubCond
Subtract only if no unsigned overflow.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ UMax
*p = old >unsigned v ? old : v
@ UDecWrap
Decrement one until a minimum value or zero.
bool isFloatingPointOperation() const
BinOp getOperation() const
AtomicOrdering getOrdering() const
Returns the ordering constraint of this rmw instruction.
This is an SDNode representing atomic operations.
const SDValue & getBasePtr() const
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
static LLVM_ABI BaseIndexOffset match(const SDNode *N, const SelectionDAG &DAG)
Parses tree in N for base, index, offset addresses.
LLVM Basic Block Representation.
LLVM_ABI const Module * getModule() const
Return the module owning the function this basic block belongs to, or nullptr if the function does no...
bool test(unsigned Idx) const
bool all() const
all - Returns true if all bits are set.
CCState - This class holds information needed while lowering arguments and return values.
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
LLVM_ABI void AnalyzeCallOperands(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeCallOperands - Analyze the outgoing arguments to a call, incorporating info about the passed v...
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
LLVM_ABI bool isIndirectCall() const
Return true if the callsite is an indirect call.
This class represents a function call, abstracting a target machine's calling convention.
bool isExactlyValue(double V) const
We don't rely on operator== working on double values, as it returns true for things that are clearly ...
This is the shared class of boolean and integer constants.
bool isMinusOne() const
This function will return true iff every bit in this constant is set to true.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
int64_t getSExtValue() const
This is an important base class in LLVM.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
unsigned getPointerSizeInBits(unsigned AS=0) const
The size in bits of the pointer representation in a given address space.
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
const ValueT & at(const_arg_type_t< KeyT > Val) const
at - Return the entry for the specified key, or abort if no such entry exists.
Implements a dense probed hash-table based set.
Diagnostic information for unsupported feature in backend.
static constexpr ElementCount getScalable(ScalarTy MinVal)
static constexpr ElementCount getFixed(ScalarTy MinVal)
Tagged union holding either a T or a Error.
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
uint64_t getFnAttributeAsParsedInteger(StringRef Kind, uint64_t Default=0) const
For a string attribute Kind, parse attribute as an integer.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
AttributeList getAttributes() const
Return the attribute list for this Function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Argument * getArg(unsigned i) const
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Helper struct to store a base, index and offset that forms an address.
int64_t getOffset() const
bool hasExternalWeakLinkage() const
Module * getParent()
Get the module that this global value is contained inside of...
Common base class shared among various IRBuilders.
Value * CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
BasicBlock * GetInsertBlock() const
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
static InstructionCost getInvalid(CostType Val=0)
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
Base class for LoadSDNode and StoreSDNode.
bool isIndexed() const
Return true if this is a pre/post inc/dec load/store.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
static constexpr LocationSize beforeOrAfterPointer()
Any location before or after the base pointer (but still within the underlying object).
Context object for machine code objects.
Base class for the full range of assembler expressions which are needed for parsing.
MCContext & getContext() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
const MDOperand & getOperand(unsigned I) const
static MVT getFloatingPointVT(unsigned BitWidth)
static auto integer_fixedlen_vector_valuetypes()
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
bool isRISCVVectorTuple() const
Return true if this is a RISCV vector tuple type where the runtime length is machine dependent.
uint64_t getScalarSizeInBits() const
MVT changeVectorElementType(MVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
bool bitsLE(MVT VT) const
Return true if this has no more bits than VT.
unsigned getVectorNumElements() const
static MVT getRISCVVectorTupleVT(unsigned Sz, unsigned NFields)
bool isVector() const
Return true if this is a vector value type.
bool isInteger() const
Return true if this is an integer or a vector integer type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
static MVT getScalableVectorVT(MVT VT, unsigned NumElements)
unsigned getRISCVVectorTupleNumFields() const
Given a RISC-V vector tuple type, return the num_fields.
MVT changeTypeToInteger()
Return the type converted to an equivalently sized integer or vector with integer element type.
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
bool bitsLT(MVT VT) const
Return true if this has less bits than VT.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
LLVM_ABI const fltSemantics & getFltSemantics() const
Returns an APFloat semantics tag appropriate for the value type.
bool bitsGT(MVT VT) const
Return true if this has more bits than VT.
bool isFixedLengthVector() const
ElementCount getVectorElementCount() const
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool bitsGE(MVT VT) const
Return true if this has no less bits than VT.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
bool isValid() const
Return true if this is a valid simple valuetype.
static MVT getIntegerVT(unsigned BitWidth)
MVT getDoubleNumVectorElementsVT() const
MVT getHalfNumVectorElementsVT() const
Return a VT for a vector type with the same element type but half the number of elements.
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
static auto integer_scalable_vector_valuetypes()
MVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
static auto fp_fixedlen_vector_valuetypes()
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
void push_back(MachineInstr *MI)
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
Instructions::iterator instr_iterator
instr_iterator instr_end()
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
LLVM_ABI void collectDebugValues(SmallVectorImpl< MachineInstr * > &DbgValues)
Scan instructions immediately following MI and collect any matching DBG_VALUEs.
void setFlag(MIFlag Flag)
Set a MI flag.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
@ EK_Custom32
EK_Custom32 - Each entry is a 32-bit value that is custom lowered by the TargetLowering::LowerCustomJ...
A description of a memory reference used in the backend.
const MDNode * getRanges() const
Return the range tag for the memory reference.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MONonTemporal
The memory access is non-temporal.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
const MachinePointerInfo & getPointerInfo() const
Flags getFlags() const
Return the raw flags of the source value,.
AAMDNodes getAAInfo() const
Return the AA tags for the memory reference.
Align getBaseAlign() const
Return the minimum known alignment in bytes of the base address, without the offset.
MachineOperand class - Representation of each machine instruction operand.
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
This is an abstract virtual class for memory operations.
bool isSimple() const
Returns true if the memory operation is neither atomic or volatile.
AtomicOrdering getSuccessOrdering() const
Return the atomic ordering requirements for this memory operation.
MachineMemOperand * getMemOperand() const
Return a MachineMemOperand object describing the memory reference performed by operation.
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
A Module instance is used to store all the information related to an LLVM module.
Metadata * getModuleFlag(StringRef Key) const
Return the corresponding value if Key appears in module flags, otherwise return null.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
A RISCV-specific constant pool value.
static RISCVConstantPoolValue * Create(const GlobalValue *GV)
RISCVMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private RISCV-...
void setVarArgsFrameIndex(int Index)
int getVarArgsFrameIndex() const
void setVarArgsSaveSize(int Size)
void addSExt32Register(Register Reg)
unsigned getMaxLMULForFixedLengthVectors() const
bool hasVInstructionsI64() const
bool hasVInstructionsF64() const
bool hasStdExtZfhOrZhinx() const
bool hasShlAdd(int64_t ShAmt) const
unsigned getRealMinVLen() const
bool useRVVForFixedLengthVectors() const
bool hasVInstructionsBF16Minimal() const
bool hasVInstructionsF16Minimal() const
bool hasConditionalMoveFusion() const
bool hasVInstructionsF16() const
unsigned getMaxBuildIntsCost() const
bool hasVInstructions() const
bool isRegisterReservedByUser(Register i) const override
std::optional< unsigned > getRealVLen() const
bool useConstantPoolForLargeInts() const
unsigned getRealMaxVLen() const
const RISCVRegisterInfo * getRegisterInfo() const override
const RISCVInstrInfo * getInstrInfo() const override
bool hasBEXTILike() const
const RISCVTargetLowering * getTargetLowering() const override
bool hasVInstructionsF32() const
bool hasCZEROLike() const
static std::pair< unsigned, unsigned > computeVLMAXBounds(MVT ContainerVT, const RISCVSubtarget &Subtarget)
static std::pair< unsigned, unsigned > decomposeSubvectorInsertExtractToSubRegs(MVT VecVT, MVT SubVecVT, unsigned InsertExtractIdx, const RISCVRegisterInfo *TRI)
ArrayRef< MCPhysReg > getRoundingControlRegisters() const override
Returns a 0 terminated array of rounding control registers that can be attached into strict FP call.
static MVT getM1VT(MVT VT)
Given a vector (either fixed or scalable), return the scalable vector corresponding to a vector regis...
InstructionCost getVRGatherVVCost(MVT VT) const
Return the cost of a vrgather.vv instruction for the type VT.
bool getIndexedAddressParts(SDNode *Op, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const
static unsigned getSubregIndexByMVT(MVT VT, unsigned Index)
Value * getIRStackGuard(IRBuilderBase &IRB) const override
If the target has a standard location for the stack protector cookie, returns the address of that loc...
bool shouldConvertFpToSat(unsigned Op, EVT FPVT, EVT VT) const override
Should we generate fp_to_si_sat and fp_to_ui_sat from type FPVT to type VT from min(max(fptoi)) satur...
InlineAsm::ConstraintCode getInlineAsmMemConstraint(StringRef ConstraintCode) const override
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
bool mayBeEmittedAsTailCall(const CallInst *CI) const override
Return true if the target may be able emit the call instruction as a tail call.
RISCVTargetLowering(const TargetMachine &TM, const RISCVSubtarget &STI)
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
Instruction * emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
Inserts in the IR a target-specific intrinsic specifying a fence.
bool isTruncateFree(Type *SrcTy, Type *DstTy) const override
Return true if it's free to truncate a value of type FromTy to type ToTy.
bool shouldRemoveExtendFromGSIndex(SDValue Extend, EVT DataVT) const override
Value * emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI, Value *AlignedAddr, Value *Incr, Value *Mask, Value *ShiftAmt, AtomicOrdering Ord) const override
Perform a masked atomicrmw using a target-specific intrinsic.
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const override
Returns true if the target allows unaligned memory accesses of the specified type.
const Constant * getTargetConstantFromLoad(LoadSDNode *LD) const override
This method returns the constant pool value that will be loaded by LD.
const RISCVSubtarget & getSubtarget() const
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
void computeKnownBitsForTargetNode(const SDValue Op, KnownBits &Known, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
Determine which of the bits specified in Mask are known to be either zero or one and return them in t...
bool preferScalarizeSplat(SDNode *N) const override
bool shouldExtendTypeInLibCall(EVT Type) const override
Returns true if arguments should be extended in lib calls.
bool isLegalAddImmediate(int64_t Imm) const override
Return true if the specified immediate is legal add immediate, that is the target has add instruction...
bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const override
Returns true if arguments should be sign-extended in lib calls.
const MCExpr * LowerCustomJumpTableEntry(const MachineJumpTableInfo *MJTI, const MachineBasicBlock *MBB, unsigned uid, MCContext &Ctx) const override
InstructionCost getVRGatherVICost(MVT VT) const
Return the cost of a vrgather.vi (or vx) instruction for the type VT.
bool shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const override
Return true if it is beneficial to convert a load of a constant to just the constant itself.
bool targetShrinkDemandedConstant(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, TargetLoweringOpt &TLO) const override
bool shouldExpandBuildVectorWithShuffles(EVT VT, unsigned DefinedValues) const override
MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Return the register type for a given MVT, ensuring vectors are treated as a series of gpr sized integ...
bool decomposeMulByConstant(LLVMContext &Context, EVT VT, SDValue C) const override
Return true if it is profitable to transform an integer multiplication-by-constant into simpler opera...
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, LLVMContext &Context, const Type *RetTy) const override
This hook should be implemented to check whether the return values described by the Outs array can fi...
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
bool hasAndNotCompare(SDValue Y) const override
Return true if the target should transform: (X & Y) == Y ---> (~X & Y) == 0 (X & Y) !...
bool shouldScalarizeBinop(SDValue VecOp) const override
Try to convert an extract element of a vector binary operation into an extract element followed by a ...
ISD::NodeType getExtendForAtomicRMWArg(unsigned Op) const override
Returns how the platform's atomic rmw operations expect their input argument to be extended (ZERO_EXT...
bool isDesirableToCommuteWithShift(const SDNode *N, CombineLevel Level) const override
Return true if it is profitable to move this shift by a constant amount through its operand,...
bool areTwoSDNodeTargetMMOFlagsMergeable(const MemSDNode &NodeX, const MemSDNode &NodeY) const override
Return true if it is valid to merge the TargetMMOFlags in two SDNodes.
bool hasBitTest(SDValue X, SDValue Y) const override
Return true if the target has a bit-test instruction: (X & (1 << Y)) ==/!= 0 This knowledge can be us...
static unsigned computeVLMAX(unsigned VectorBits, unsigned EltSize, unsigned MinSize)
bool shouldExpandCttzElements(EVT VT) const override
Return true if the @llvm.experimental.cttz.elts intrinsic should be expanded using generic code in Se...
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
Value * emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, AtomicCmpXchgInst *CI, Value *AlignedAddr, Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const override
Perform a masked cmpxchg using a target-specific intrinsic.
bool isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize) const override
Returns true if the target can instruction select the specified FP immediate natively.
InstructionCost getLMULCost(MVT VT) const
Return the cost of LMUL for linear operations.
unsigned getJumpTableEncoding() const override
Return the entry encoding for a jump table in the current function.
bool isMulAddWithConstProfitable(SDValue AddNode, SDValue ConstNode) const override
Return true if it may be profitable to transform (mul (add x, c1), c2) -> (add (mul x,...
InstructionCost getVSlideVICost(MVT VT) const
Return the cost of a vslidedown.vi or vslideup.vi instruction for the type VT.
bool fallBackToDAGISel(const Instruction &Inst) const override
EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
bool isCtpopFast(EVT VT) const override
Return true if ctpop instruction is fast.
unsigned ComputeNumSignBitsForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
This method can be implemented by targets that want to expose additional information about sign bits ...
MVT getContainerForFixedLengthVector(MVT VT) const
static unsigned getRegClassIDForVecVT(MVT VT)
Register getExceptionPointerRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
TargetLowering::AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return true if EXTRACT_SUBVECTOR is cheap for extracting this result type from this source type with ...
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
MachineBasicBlock * emitDynamicProbedAlloc(MachineInstr &MI, MachineBasicBlock *MBB) const
MachineMemOperand::Flags getTargetMMOFlags(const Instruction &I) const override
This callback is used to inspect load/store instructions and add target-specific MachineMemOperand fl...
SDValue computeVLMax(MVT VecVT, const SDLoc &DL, SelectionDAG &DAG) const
bool signExtendConstant(const ConstantInt *CI) const override
Return true if this constant should be sign extended when promoting to a larger type.
bool shouldTransformSignedTruncationCheck(EVT XVT, unsigned KeptBits) const override
Should we tranform the IR-optimal check for whether given truncation down into KeptBits would be trun...
bool shouldProduceAndByConstByHoistingConstFromShiftsLHSOfAnd(SDValue X, ConstantSDNode *XC, ConstantSDNode *CC, SDValue Y, unsigned OldShiftOpcode, unsigned NewShiftOpcode, SelectionDAG &DAG) const override
Given the pattern (X & (C l>>/<< Y)) ==/!= 0 return true if it should be transformed into: ((X <</l>>...
bool hasInlineStackProbe(const MachineFunction &MF) const override
True if stack clash protection is enabled for this functions.
bool hasAndNot(SDValue Y) const override
Return true if the target has a bitwise and-not operation: X = ~A & B This can be used to simplify se...
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Returns the register with the specified architectural or ABI name.
InstructionCost getVSlideVXCost(MVT VT) const
Return the cost of a vslidedown.vx or vslideup.vx instruction for the type VT.
bool shouldFoldMaskToVariableShiftPair(SDValue Y) const override
There are two ways to clear extreme bits (either low or high): Mask: x & (-1 << y) (the instcombine c...
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override
Return true if result of the specified node is used by a return node only.
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const override
Return true if an FMA operation is faster than a pair of fmul and fadd instructions.
TargetLowering::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *CI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
Register getExceptionSelectorRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
unsigned getCustomCtpopCost(EVT VT, ISD::CondCode Cond) const override
Return the maximum number of "x & (x - 1)" operations that can be done instead of deferring to a cust...
void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override
This method should be implemented by targets that mark instructions with the 'hasPostISelHook' flag.
bool isShuffleMaskLegal(ArrayRef< int > M, EVT VT) const override
Return true if the given shuffle mask can be codegen'd directly, or if it should be stack expanded.
bool isCheapToSpeculateCttz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic cttz.
bool isLegalICmpImmediate(int64_t Imm) const override
Return true if the specified immediate is legal icmp immediate, that is the target has icmp instructi...
ISD::NodeType getExtendForAtomicCmpSwapArg() const override
Returns how the platform's atomic compare and swap expects its comparison value to be extended (ZERO_...
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower the incoming (formal) arguments, described by the Ins array,...
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I, MachineFunction &MF, unsigned Intrinsic) const override
Given an intrinsic, checks if on the target the intrinsic will need to map to a MemIntrinsicNode (tou...
unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const override
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
bool isLegalElementTypeForRVV(EVT ScalarTy) const
bool isVScaleKnownToBeAPowerOfTwo() const override
Return true only if vscale must be a power of two.
int getLegalZfaFPImm(const APFloat &Imm, EVT VT) const
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
Lower the specified operand into the Ops vector.
bool splitValueIntoRegisterParts(SelectionDAG &DAG, const SDLoc &DL, SDValue Val, SDValue *Parts, unsigned NumParts, MVT PartVT, std::optional< CallingConv::ID > CC) const override
Target-specific splitting of values into parts that fit a register storing a legal type.
Instruction * emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Return the number of registers for a given MVT, ensuring vectors are treated as a series of gpr sized...
ConstraintType getConstraintType(StringRef Constraint) const override
getConstraintType - Given a constraint letter, return the type of constraint it is for this target.
MachineInstr * EmitKCFICheck(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator &MBBI, const TargetInstrInfo *TII) const override
bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool PoisonOnly, bool ConsiderFlags, unsigned Depth) const override
Return true if Op can create undef or poison from non-undef & non-poison operands.
bool isIntDivCheap(EVT VT, AttributeList Attr) const override
Return true if integer divide is usually cheaper than a sequence of several shifts,...
SDValue expandIndirectJTBranch(const SDLoc &dl, SDValue Value, SDValue Addr, int JTI, SelectionDAG &DAG) const override
Expands target specific indirect branch for the case of JumpTable expansion.
static unsigned getRegClassIDForLMUL(RISCVVType::VLMUL LMul)
unsigned getNumRegisters(LLVMContext &Context, EVT VT, std::optional< MVT > RegisterVT=std::nullopt) const override
Return the number of registers for a given MVT, for inline assembly.
bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
Returns true by value, base pointer and offset pointer and addressing mode by reference if this node ...
bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
Returns true by value, base pointer and offset pointer and addressing mode by reference if the node's...
SDValue joinRegisterPartsIntoValue(SelectionDAG &DAG, const SDLoc &DL, const SDValue *Parts, unsigned NumParts, MVT PartVT, EVT ValueVT, std::optional< CallingConv::ID > CC) const override
Target-specific combining of register parts into its original value.
bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const override
Return if the target supports combining a chain like:
bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override
Return true if sign-extension from FromTy to ToTy is cheaper than zero-extension.
bool isLegalStridedLoadStore(EVT DataType, Align Alignment) const
Return true if a stride load store of the given result type and alignment is legal.
static bool isSpreadMask(ArrayRef< int > Mask, unsigned Factor, unsigned &Index)
Match a mask which "spreads" the leading elements of a vector evenly across the result.
static RISCVVType::VLMUL getLMUL(MVT VT)
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth) const override
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
bool shouldFoldSelectWithIdentityConstant(unsigned BinOpcode, EVT VT, unsigned SelectOpcode, SDValue X, SDValue Y) const override
Return true if pulling a binary operation into a select with an identity constant is profitable.
unsigned getStackProbeSize(const MachineFunction &MF, Align StackAlign) const
bool shouldInsertFencesForAtomic(const Instruction *I) const override
Whether AtomicExpandPass should automatically insert fences and reduce ordering for this atomic.
Wrapper class representing virtual and physical registers.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
ArrayRef< SDUse > ops() const
const APInt & getAsAPIntVal() const
Helper method returns the APInt value of a ConstantSDNode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
iterator_range< use_iterator > uses()
SDNodeFlags getFlags() const
size_t use_size() const
Return the number of uses of this node.
MVT getSimpleValueType(unsigned ResNo) const
Return the type of a specified result as a simple type.
static bool hasPredecessorHelper(const SDNode *N, SmallPtrSetImpl< const SDNode * > &Visited, SmallVectorImpl< const SDNode * > &Worklist, unsigned int MaxSteps=0, bool TopologicalPrune=false)
Returns true if N is a predecessor of any node in Worklist.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
const SDValue & getOperand(unsigned Num) const
std::optional< APInt > bitcastToAPInt() const
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
void setCFIType(uint32_t Type)
bool isUndef() const
Returns true if the node type is UNDEF or POISON.
iterator_range< user_iterator > users()
Represents a use of a SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
const APInt & getConstantOperandAPInt(unsigned i) const
uint64_t getScalarValueSizeInBits() const
uint64_t getConstantOperandVal(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getOpcode() const
unsigned getNumOperands() const
virtual bool isTargetStrictFPOpcode(unsigned Opcode) const
Returns true if a node with the given target-specific opcode has strict floating-point semantics.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI Align getReducedAlign(EVT VT, bool UseABI)
In most cases this function returns the ABI alignment for a given type, except for illegal vector typ...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
SDValue getExtractVectorElt(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Extract element at Idx from Vec.
LLVM_ABI unsigned ComputeMaxSignificantBits(SDValue Op, unsigned Depth=0) const
Get the upper bound on bit size for this Value Op as a signed integer.
LLVM_ABI SDValue getMaskedGather(SDVTList VTs, EVT MemVT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType, ISD::LoadExtType ExtTy)
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL)
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDValue getNeutralElement(unsigned Opcode, const SDLoc &DL, EVT VT, SDNodeFlags Flags)
Get the (commutative) neutral element for the given opcode, if it exists.
LLVM_ABI SDValue getAtomicLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT MemVT, EVT VT, SDValue Chain, SDValue Ptr, MachineMemOperand *MMO)
LLVM_ABI SDValue getVScale(const SDLoc &DL, EVT VT, APInt MulImm, bool ConstantFold=true)
Return a node that represents the runtime scaling 'MulImm * RuntimeVL'.
LLVM_ABI SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
LLVM_ABI SDValue getStridedLoadVP(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, const SDLoc &DL, SDValue Chain, SDValue Ptr, SDValue Offset, SDValue Stride, SDValue Mask, SDValue EVL, EVT MemVT, MachineMemOperand *MMO, bool IsExpanding=false)
LLVM_ABI SDValue makeEquivalentMemoryOrdering(SDValue OldChain, SDValue NewMemOpChain)
If an existing load has uses of its chain, create a token factor node with that chain and the new mem...
LLVM_ABI SDValue getJumpTableDebugInfo(int JTI, SDValue Chain, const SDLoc &DL)
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false)
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
bool isSafeToSpeculativelyExecute(unsigned Opcode) const
Some opcodes may create immediate undefined behavior when used with some values (integer division-by-...
LLVM_ABI SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
SDValue getExtractSubvector(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Return the VT typed sub-vector of Vec at Idx.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getElementCount(const SDLoc &DL, EVT VT, ElementCount EC, bool ConstantFold=true)
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
SDValue getInsertSubvector(const SDLoc &DL, SDValue Vec, SDValue SubVec, unsigned Idx)
Insert SubVec at the Idx element of Vec.
LLVM_ABI SDValue getStepVector(const SDLoc &DL, EVT ResVT, const APInt &StepVal)
Returns a vector of type ResVT whose elements contain the linear sequence <0, Step,...
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
LLVM_ABI bool shouldOptForSize() const
std::pair< SDValue, SDValue > SplitVectorOperand(const SDNode *N, unsigned OpNo)
Split the node's operand with EXTRACT_SUBVECTOR and return the low/high part.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
LLVM_ABI SDValue getVPZExtOrTrunc(const SDLoc &DL, EVT VT, SDValue Op, SDValue Mask, SDValue EVL)
Convert a vector-predicated Op, which must be an integer vector, to the vector-type VT,...
const TargetLowering & getTargetLoweringInfo() const
LLVM_ABI SDValue getStridedStoreVP(SDValue Chain, const SDLoc &DL, SDValue Val, SDValue Ptr, SDValue Offset, SDValue Stride, SDValue Mask, SDValue EVL, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
bool NewNodesMustHaveLegalTypes
When true, additional steps are taken to ensure that getConstant() and similar functions return DAG n...
LLVM_ABI std::pair< EVT, EVT > GetSplitDestVTs(const EVT &VT) const
Compute the VTs needed for the low/hi parts of a type which is split (or expanded) into two not neces...
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
LLVM_ABI SDValue getGatherVP(SDVTList VTs, EVT VT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType)
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI bool isSplatValue(SDValue V, const APInt &DemandedElts, APInt &UndefElts, unsigned Depth=0) const
Test whether V has a splatted value for all the demanded elements.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
const SelectionDAGTargetInfo & getSelectionDAGInfo() const
LLVM_ABI SDValue getStoreVP(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, SDValue Offset, SDValue Mask, SDValue EVL, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags=SDNodeFlags())
Returns sum of the base pointer and offset.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue getSplatVector(EVT VT, const SDLoc &DL, SDValue Op)
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI bool SignBitIsZero(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero.
SDValue getInsertVectorElt(const SDLoc &DL, SDValue Vec, SDValue Elt, unsigned Idx)
Insert Elt into Vec at offset Idx.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDValue > Ops, SDNodeFlags Flags=SDNodeFlags())
LLVM_ABI SDValue getMaskedStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Base, SDValue Offset, SDValue Mask, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
LLVM_ABI std::pair< SDValue, SDValue > getStrictFPExtendOrRound(SDValue Op, SDValue Chain, const SDLoc &DL, EVT VT)
Convert Op, which must be a STRICT operation of float type, to the float type VT, by either extending...
LLVM_ABI std::pair< SDValue, SDValue > SplitEVL(SDValue N, EVT VecVT, const SDLoc &DL)
Split the explicit vector length parameter of a VP operation.
LLVM_ABI SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either any-extending or truncat...
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getScatterVP(SDVTList VTs, EVT VT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
LLVM_ABI SDValue getFPExtendOrRound(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of float type, to the float type VT, by either extending or rounding (by tr...
LLVM_ABI bool isKnownNeverNaN(SDValue Op, const APInt &DemandedElts, bool SNaN=false, unsigned Depth=0) const
Test whether the given SDValue (or all elements of it, if it is a vector) is known to never be NaN in...
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI SDValue getBoolConstant(bool V, const SDLoc &DL, EVT VT, EVT OpVT)
Create a true or false constant of type VT using the target's BooleanContent for type OpVT.
SDValue getTargetBlockAddress(const BlockAddress *BA, EVT VT, int64_t Offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
void addCallSiteInfo(const SDNode *Node, CallSiteInfo &&CallInfo)
Set CallSiteInfo to be associated with Node.
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Base, SDValue Offset, SDValue Mask, SDValue Src0, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, ISD::LoadExtType, bool IsExpanding=false)
SDValue getSplat(EVT VT, const SDLoc &DL, SDValue Op)
Returns a node representing a splat of one value into all lanes of the provided vector type.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
LLVM_ABI SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a logical NOT operation as (XOR Val, BooleanOne).
LLVM_ABI SDValue getMaskedScatter(SDVTList VTs, EVT MemVT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType, bool IsTruncating=false)
static LLVM_ABI bool isSelectMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from its source vectors without lane crossings.
static LLVM_ABI bool isBitRotateMask(ArrayRef< int > Mask, unsigned EltSizeInBits, unsigned MinSubElts, unsigned MaxSubElts, unsigned &NumSubElts, unsigned &RotateAmt)
Checks if the shuffle is a bit rotation of the first operand across multiple subelements,...
static LLVM_ABI bool isSingleSourceMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector.
static LLVM_ABI bool isDeInterleaveMaskOfFactor(ArrayRef< int > Mask, unsigned Factor, unsigned &Index)
Check if the mask is a DE-interleave mask of the given factor Factor like: <Index,...
static LLVM_ABI bool isIdentityMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector without lane crossin...
static LLVM_ABI bool isReverseMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask swaps the order of elements from exactly one source vector.
static LLVM_ABI bool isInsertSubvectorMask(ArrayRef< int > Mask, int NumSrcElts, int &NumSubElts, int &Index)
Return true if this shuffle mask is an insert subvector mask.
static LLVM_ABI bool isInterleaveMask(ArrayRef< int > Mask, unsigned Factor, unsigned NumInputElts, SmallVectorImpl< unsigned > &StartIndexes)
Return true if the mask interleaves one or more input vectors together.
This SDNode is used to implement the code generator support for the llvm IR shufflevector instruction...
int getSplatIndex() const
ArrayRef< int > getMask() const
static LLVM_ABI bool isSplatMask(ArrayRef< int > Mask)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
iterator erase(const_iterator CI)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
pointer data()
Return a pointer to the vector's buffer, even if empty().
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
StringRef - Represent a constant reference to a string, i.e.
constexpr size_t size() const
size - Get the string size.
LLVM_ABI std::string lower() const
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
StringSwitch & Cases(std::initializer_list< StringLiteral > CaseStrings, T Value)
Information about stack frame layout on the target.
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
TargetInstrInfo - Interface to description of machine instruction set.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
void setMaxDivRemBitWidthSupported(unsigned SizeInBits)
Set the size in bits of the maximum div/rem the backend supports.
bool PredictableSelectIsExpensive
Tells the code generator that select is more expensive than a branch if the branch is usually predict...
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
unsigned MaxStoresPerMemcpyOptSize
Likewise for functions with the OptSize attribute.
MachineBasicBlock * emitPatchPoint(MachineInstr &MI, MachineBasicBlock *MBB) const
Replace/modify any TargetFrameIndex operands with a targte-dependent sequence of memory operands that...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
virtual unsigned getMinimumJumpTableEntries() const
Return lower limit for number of blocks in a jump table.
const TargetMachine & getTargetMachine() const
unsigned MaxLoadsPerMemcmp
Specify maximum number of load instructions per memcmp call.
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
unsigned MaxGluedStoresPerMemcpy
Specify max number of store instructions to glue in inlined memcpy.
virtual bool isZExtFree(Type *FromTy, Type *ToTy) const
Return true if any actual instruction that defines a value of type FromTy implicitly zero-extends the...
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
void setOperationPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
Convenience method to set an operation to Promote and specify the type in a single call.
unsigned getMinCmpXchgSizeInBits() const
Returns the size of the smallest cmpxchg or ll/sc instruction the backend supports.
virtual unsigned getNumRegisters(LLVMContext &Context, EVT VT, std::optional< MVT > RegisterVT=std::nullopt) const
Return the number of registers that this ValueType will eventually require.
void setIndexedLoadAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed load does or does not work with the specified type and indicate w...
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
virtual unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
bool isOperationCustom(unsigned Op, EVT VT) const
Return true if the operation uses custom lowering, regardless of whether the type is legal or not.
unsigned MaxStoresPerMemsetOptSize
Likewise for functions with the OptSize attribute.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
unsigned MaxStoresPerMemmove
Specify maximum number of store instructions per memmove call.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
virtual bool isTruncateFree(Type *FromTy, Type *ToTy) const
Return true if it's free to truncate a value of type FromTy to type ToTy.
unsigned MaxStoresPerMemmoveOptSize
Likewise for functions with the OptSize attribute.
virtual bool shouldFoldSelectWithSingleBitTest(EVT VT, const APInt &AndMask) const
virtual Value * getIRStackGuard(IRBuilderBase &IRB) const
If the target has a standard location for the stack protector guard, returns the address of that loca...
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
bool EnableExtLdPromotion
void setIndexedStoreAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed store does or does not work with the specified type and indicate ...
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
unsigned getMaxDivRemBitWidthSupported() const
Returns the size in bits of the maximum div/rem the backend supports.
bool isOperationLegal(unsigned Op, EVT VT) const
Return true if the specified operation is legal on this target.
unsigned MaxStoresPerMemset
Specify maximum number of store instructions per memset call.
void setPartialReduceMLAAction(unsigned Opc, MVT AccVT, MVT InputVT, LegalizeAction Action)
Indicate how a PARTIAL_REDUCE_U/SMLA node with Acc type AccVT and Input type InputVT should be treate...
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
unsigned MaxLoadsPerMemcmpOptSize
Likewise for functions with the OptSize attribute.
virtual bool isBinOp(unsigned Opcode) const
Return true if the node is a math/logic binary operator.
void setMinCmpXchgSizeInBits(unsigned SizeInBits)
Sets the minimum cmpxchg or ll/sc size supported by the backend.
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
void setCondCodeAction(ArrayRef< ISD::CondCode > CCs, MVT VT, LegalizeAction Action)
Indicate that the specified condition code is or isn't supported on the target and indicate what to d...
virtual std::pair< const TargetRegisterClass *, uint8_t > findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const
Return the largest legal super-reg register class of the register class for the specified type and it...
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
std::vector< ArgListEntry > ArgListTy
bool allowsMemoryAccessForAlignment(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
This function returns true if the memory access is aligned or if the target allows this specific unal...
unsigned MaxStoresPerMemcpy
Specify maximum number of store instructions per memcpy call.
bool isOperationLegalOrCustomOrPromote(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual MVT getVPExplicitVectorLengthTy() const
Returns the type to be used for the EVL/AVL operand of VP nodes: ISD::VP_ADD, ISD::VP_SUB,...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
SDValue expandAddSubSat(SDNode *Node, SelectionDAG &DAG) const
Method for building the DAG expansion of ISD::[US][ADD|SUB]SAT.
SDValue buildSDIVPow2WithCMov(SDNode *N, const APInt &Divisor, SelectionDAG &DAG, SmallVectorImpl< SDNode * > &Created) const
Build sdiv by power-of-2 with conditional move instructions Ref: "Hacker's Delight" by Henry Warren 1...
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
virtual SDValue expandIndirectJTBranch(const SDLoc &dl, SDValue Value, SDValue Addr, int JTI, SelectionDAG &DAG) const
Expands target specific indirect branch for the case of JumpTable expansion.
virtual InlineAsm::ConstraintCode getInlineAsmMemConstraint(StringRef ConstraintCode) const
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
virtual SDValue LowerToTLSEmulatedModel(const GlobalAddressSDNode *GA, SelectionDAG &DAG) const
Lower TLS global address SDNode for target independent emulated TLS model.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
bool isPositionIndependent() const
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
virtual bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0) const
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
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.
virtual bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool PoisonOnly, bool ConsiderFlags, unsigned Depth) const
Return true if Op can create undef or poison from non-undef & non-poison operands.
Primary interface to the complete machine description for the target machine.
TLSModel::Model getTLSModel(const GlobalValue *GV) const
Returns the TLS model which should be used for the given global variable.
const Triple & getTargetTriple() const
bool useTLSDESC() const
Returns true if this target uses TLS Descriptors.
const MCSubtargetInfo * getMCSubtargetInfo() const
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
virtual TargetLoweringObjectFile * getObjFileLowering() const
unsigned EmitCallGraphSection
Emit section containing call graph metadata.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual bool isRegisterReservedByUser(Register R) const
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
Target - Wrapper for Target specific information.
bool isOSBinFormatCOFF() const
Tests whether the OS uses the COFF binary format.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
LLVM_ABI Type * getStructElementType(unsigned N) const
LLVM_ABI bool isScalableTy(SmallPtrSetImpl< const Type * > &Visited) const
Return true if this is a type whose size is a known multiple of vscale.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
bool isStructTy() const
True if this is an instance of StructType.
LLVM_ABI bool isRISCVVectorTupleTy() const
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isTargetExtTy() const
Return true if this is a target extension type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
A Use represents the edge between a Value definition and its users.
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
User * getUser() const
Returns the User that contains this Use.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
std::pair< iterator, bool > insert(const ValueT &V)
constexpr bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
constexpr ScalarTy getFixedValue() const
static constexpr bool isKnownLE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
constexpr LeafTy multiplyCoefficientBy(ScalarTy RHS) const
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
constexpr bool isZero() const
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ RISCV_VectorCall
Calling convention used for RISC-V V-extension.
@ PreserveMost
Used for runtime calls that preserves most registers.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ SPIR_KERNEL
Used for SPIR kernel functions.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
@ GRAAL
Used by GraalVM. Two additional registers are reserved.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI bool isConstantSplatVectorAllOnes(const SDNode *N, bool BuildVectorOnly=false)
Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where all of the elements are ~0 ...
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ 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.
@ 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.
@ ADD
Simple integer binary arithmetic operators.
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ FADD
Simple binary floating point operators.
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ 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.
@ 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...
@ CTTZ_ZERO_UNDEF
Bit counting operators with an undefined result for zero inputs.
@ 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).
@ 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.
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
@ GET_ROUNDING
Returns current rounding mode: -1 Undefined 0 Round to 0 1 Round to nearest, ties to even 2 Round to ...
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ SSHLSAT
RESULT = [US]SHLSAT(LHS, RHS) - Perform saturation left shift.
@ 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...
@ 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.
@ EH_DWARF_CFA
EH_DWARF_CFA - This node represents the pointer to the DWARF Canonical Frame Address (CFA),...
@ 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.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ 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.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
@ STRICT_FADD
Constrained versions of the binary floating point operators.
@ SPLAT_VECTOR_PARTS
SPLAT_VECTOR_PARTS(SCALAR1, SCALAR2, ...) - Returns a vector with the scalar values joined together a...
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ VECTOR_SPLICE
VECTOR_SPLICE(VEC1, VEC2, IMM) - Returns a subvector of the same type as VEC1/VEC2 from CONCAT_VECTOR...
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ VECTOR_COMPRESS
VECTOR_COMPRESS(Vec, Mask, Passthru) consecutively place vector elements based on mask e....
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ 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 ...
@ 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...
@ 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)
BinaryOp_match< LHS, RHS, Instruction::Or > m_Or(const LHS &L, const RHS &R)
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
ThreeOps_match< Val_t, Elt_t, Idx_t, Instruction::InsertElement > m_InsertElt(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx)
Matches InsertElementInst.
unsigned getBrCond(CondCode CC, unsigned SelectOpc=0)
static RISCVVType::VLMUL getLMul(uint64_t TSFlags)
static int getFRMOpNum(const MCInstrDesc &Desc)
static unsigned getSEWOpNum(const MCInstrDesc &Desc)
int getLoadFPImm(APFloat FPImm)
getLoadFPImm - Return a 5-bit binary encoding of the floating-point immediate value.
InstSeq generateInstSeq(int64_t Val, const MCSubtargetInfo &STI)
int getIntMatCost(const APInt &Val, unsigned Size, const MCSubtargetInfo &STI, bool CompressionCost, bool FreeZeroes)
InstSeq generateTwoRegInstSeq(int64_t Val, const MCSubtargetInfo &STI, unsigned &ShiftAmt, unsigned &AddOpc)
SmallVector< Inst, 8 > InstSeq
static VLMUL encodeLMUL(unsigned LMUL, bool Fractional)
static unsigned decodeVSEW(unsigned VSEW)
@ TAIL_UNDISTURBED_MASK_UNDISTURBED
LLVM_ABI std::pair< unsigned, bool > decodeVLMUL(VLMUL VLMul)
static unsigned encodeSEW(unsigned SEW)
static constexpr unsigned FPMASK_Negative_Zero
static constexpr unsigned FPMASK_Positive_Subnormal
static constexpr unsigned FPMASK_Positive_Normal
static constexpr unsigned FPMASK_Negative_Subnormal
static constexpr unsigned FPMASK_Negative_Normal
static constexpr unsigned FPMASK_Positive_Infinity
static constexpr unsigned FPMASK_Negative_Infinity
static constexpr unsigned FPMASK_Quiet_NaN
ArrayRef< MCPhysReg > getArgGPRs(const RISCVABI::ABI ABI)
static constexpr unsigned FPMASK_Signaling_NaN
static constexpr unsigned FPMASK_Positive_Zero
static constexpr unsigned RVVBitsPerBlock
static constexpr unsigned RVVBytesPerBlock
LLVM_ABI Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
@ Kill
The last use of a register.
BinaryOpc_match< LHS, RHS > m_Srl(const LHS &L, const RHS &R)
auto m_SpecificVT(EVT RefVT, const Pattern &P)
Match a specific ValueType.
Or< Preds... > m_AnyOf(const Preds &...preds)
auto m_Node(unsigned Opcode, const OpndPreds &...preds)
bool sd_match(SDNode *N, const SelectionDAG *DAG, Pattern &&P)
ConstantInt_match m_ConstInt()
Match any integer constants or splat of an integer constant.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
@ System
Synchronized with respect to all concurrently executing threads.
initializer< Ty > init(const Ty &Val)
uint32_t read32le(const void *P)
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
FunctionAddr VTableAddr Value
bool CC_RISCV_FastCC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
bool CC_RISCV_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static const MachineMemOperand::Flags MONontemporalBit1
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
MCCodeEmitter * createRISCVMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
static const MachineMemOperand::Flags MONontemporalBit0
bool RISCVCCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
RISCVCCAssignFn - This target-specific function extends the default CCValAssign with additional infor...
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI bool widenShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Try to transform a shuffle mask by replacing elements with the scaled index for an equivalent mask of...
LLVM_ABI Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
LLVM_ABI bool isNullOrNullSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndefs=false)
Return true if the value is a constant 0 integer or a splatted vector of a constant 0 integer (with n...
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
bool isReleaseOrStronger(AtomicOrdering AO)
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere.
constexpr bool has_single_bit(T Value) noexcept
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
FunctionAddr VTableAddr Count
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
bool CC_RISCV(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
int isShifted359(T Value, int &Shift)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI bool isOneOrOneSplat(SDValue V, bool AllowUndefs=false)
Return true if the value is a constant 1 integer or a splatted vector of a constant 1 integer (with n...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
auto drop_end(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the last N elements excluded.
AtomicOrdering
Atomic ordering for LLVM's memory model.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
LLVM_ABI void narrowShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Replace each shuffle mask index with the scaled sequential indices for an equivalent mask of narrowed...
LLVM_ABI bool isMaskedSlidePair(ArrayRef< int > Mask, int NumElts, std::array< std::pair< int, int >, 2 > &SrcInfo)
Does this shuffle mask represent either one slide shuffle or a pair of two slide shuffles,...
@ Xor
Bitwise or logical XOR of integers.
@ SMin
Signed integer min implemented in terms of select(cmp()).
@ Sub
Subtraction of integers.
unsigned getKillRegState(bool B)
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
FunctionAddr VTableAddr Next
DWARFExpression::Operation Op
RoundingMode
Rounding mode.
@ TowardZero
roundTowardZero.
@ NearestTiesToEven
roundTiesToEven.
@ TowardPositive
roundTowardPositive.
@ NearestTiesToAway
roundTiesToAway.
@ TowardNegative
roundTowardNegative.
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
bool isAcquireOrStronger(AtomicOrdering AO)
constexpr unsigned BitWidth
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
LLVM_ABI void processShuffleMasks(ArrayRef< int > Mask, unsigned NumOfSrcRegs, unsigned NumOfDestRegs, unsigned NumOfUsedRegs, function_ref< void()> NoInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned)> SingleInputAction, function_ref< void(ArrayRef< int >, unsigned, unsigned, bool)> ManyInputsAction)
Splits and processes shuffle mask depending on the number of input and output registers.
unsigned Log2(Align A)
Returns the log2 of the alignment.
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
@ Increment
Incrementally increasing token ID.
@ Default
The result values are uniform if and only if all operands are uniform.
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
LLVM_ABI bool isNeutralConstant(unsigned Opc, SDNodeFlags Flags, SDValue V, unsigned OperandNo)
Returns true if V is a neutral element of Opc with Flags.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
uint64_t getScalarStoreSize() const
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
bool isByteSized() const
Return true if the bit size is a multiple of 8.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
unsigned getRISCVVectorTupleNumFields() const
Given a RISCV vector tuple type, return the num_fields.
uint64_t getScalarSizeInBits() const
EVT getHalfSizedIntegerVT(LLVMContext &Context) const
Finds the smallest simple value type that is greater than or equal to half the width of this EVT.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
bool isRISCVVectorTuple() const
Return true if this is a vector value type.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isFixedLengthVector() const
EVT getRoundIntegerType(LLVMContext &Context) const
Rounds the bit-width of the given integer EVT up to the nearest power of two (and at least to eight),...
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
bool bitsGE(EVT VT) const
Return true if this has no less bits than VT.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
EVT changeVectorElementType(EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
bool isInteger() const
Return true if this is an integer or a vector integer type.
static LLVM_ABI KnownBits ashr(const KnownBits &LHS, const KnownBits &RHS, bool ShAmtNonZero=false, bool Exact=false)
Compute known bits for ashr(LHS, RHS).
static LLVM_ABI KnownBits urem(const KnownBits &LHS, const KnownBits &RHS)
Compute known bits for urem(LHS, RHS).
bool isUnknown() const
Returns true if we don't know any bits.
unsigned countMaxTrailingZeros() const
Returns the maximum number of trailing zero bits possible.
KnownBits trunc(unsigned BitWidth) const
Return known bits for a truncation of the value we're tracking.
unsigned getBitWidth() const
Get the bit width of this value.
KnownBits zext(unsigned BitWidth) const
Return known bits for a zero extension of the value we're tracking.
void resetAll()
Resets the known state of all bits.
static LLVM_ABI KnownBits lshr(const KnownBits &LHS, const KnownBits &RHS, bool ShAmtNonZero=false, bool Exact=false)
Compute known bits for lshr(LHS, RHS).
unsigned countMaxActiveBits() const
Returns the maximum number of bits needed to represent all possible unsigned values with these known ...
KnownBits intersectWith(const KnownBits &RHS) const
Returns KnownBits information that is known to be true for both this and RHS.
KnownBits sext(unsigned BitWidth) const
Return known bits for a sign extension of the value we're tracking.
static KnownBits add(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false)
Compute knownbits resulting from addition of LHS and RHS.
APInt getMaxValue() const
Return the maximal unsigned value possible given these KnownBits.
static LLVM_ABI KnownBits udiv(const KnownBits &LHS, const KnownBits &RHS, bool Exact=false)
Compute known bits for udiv(LHS, RHS).
unsigned countMaxLeadingZeros() const
Returns the maximum number of leading zero bits possible.
static LLVM_ABI KnownBits shl(const KnownBits &LHS, const KnownBits &RHS, bool NUW=false, bool NSW=false, bool ShAmtNonZero=false)
Compute known bits for shl(LHS, RHS).
SmallVector< ArgRegPair, 1 > ArgRegPairs
Vector of call argument and its forwarding register.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Register getFrameRegister(const MachineFunction &MF) const override
These are IR-level optimization flags that may be propagated to SDNodes.
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This structure contains all information that is necessary for lowering calls.
SmallVector< ISD::InputArg, 32 > Ins
const ConstantInt * CFIType
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
bool isAfterLegalizeDAG() const
LLVM_ABI void AddToWorklist(SDNode *N)
bool isCalledByLegalizer() const
LLVM_ABI bool recursivelyDeleteUnusedNodes(SDNode *N)
bool isBeforeLegalize() const
LLVM_ABI SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
This structure is used to pass arguments to makeLibCall function.
MakeLibCallOptions & setTypeListBeforeSoften(ArrayRef< EVT > OpsVT, EVT RetVT)
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...
bool CombineTo(SDValue O, SDValue N)