41#include "llvm/IR/IntrinsicsRISCV.h"
55#define DEBUG_TYPE "riscv-lower"
61 cl::desc(
"Give the maximum size (in number of nodes) of the web of "
62 "instructions that we will consider for VW expansion"),
67 cl::desc(
"Allow the formation of VW_W operations (e.g., "
68 "VWADD_W) with splat constants"),
73 cl::desc(
"Set the minimum number of repetitions of a divisor to allow "
74 "transformation to multiplications by the reciprocal"),
79 cl::desc(
"Give the maximum number of instructions that we will "
80 "use for creating a floating-point immediate value"),
85 cl::desc(
"Swap add and addi in cases where the add may "
86 "be combined with a shift"),
97 !Subtarget.hasStdExtF()) {
98 errs() <<
"Hard-float 'f' ABI can't be used for a target that "
99 "doesn't support the F instruction set extension (ignoring "
103 !Subtarget.hasStdExtD()) {
104 errs() <<
"Hard-float 'd' ABI can't be used for a target that "
105 "doesn't support the D instruction set extension (ignoring "
124 MVT XLenVT = Subtarget.getXLenVT();
129 if (Subtarget.hasStdExtZfhmin())
131 if (Subtarget.hasStdExtZfbfmin() || Subtarget.hasVendorXAndesBFHCvt())
133 if (Subtarget.hasStdExtF())
135 if (Subtarget.hasStdExtD())
137 if (Subtarget.hasStdExtZhinxmin())
139 if (Subtarget.hasStdExtZfinx())
141 if (Subtarget.hasStdExtZdinx()) {
142 if (Subtarget.is64Bit())
149 MVT::nxv1i1, MVT::nxv2i1, MVT::nxv4i1, MVT::nxv8i1,
150 MVT::nxv16i1, MVT::nxv32i1, MVT::nxv64i1};
152 MVT::nxv1i8, MVT::nxv2i8, MVT::nxv4i8, MVT::nxv8i8, MVT::nxv16i8,
153 MVT::nxv32i8, MVT::nxv64i8, MVT::nxv1i16, MVT::nxv2i16, MVT::nxv4i16,
154 MVT::nxv8i16, MVT::nxv16i16, MVT::nxv32i16, MVT::nxv1i32, MVT::nxv2i32,
155 MVT::nxv4i32, MVT::nxv8i32, MVT::nxv16i32, MVT::nxv1i64, MVT::nxv2i64,
156 MVT::nxv4i64, MVT::nxv8i64};
158 MVT::nxv1f16, MVT::nxv2f16, MVT::nxv4f16,
159 MVT::nxv8f16, MVT::nxv16f16, MVT::nxv32f16};
161 MVT::nxv1bf16, MVT::nxv2bf16, MVT::nxv4bf16,
162 MVT::nxv8bf16, MVT::nxv16bf16, MVT::nxv32bf16};
164 MVT::nxv1f32, MVT::nxv2f32, MVT::nxv4f32, MVT::nxv8f32, MVT::nxv16f32};
166 MVT::nxv1f64, MVT::nxv2f64, MVT::nxv4f64, MVT::nxv8f64};
168 MVT::riscv_nxv1i8x2, MVT::riscv_nxv1i8x3, MVT::riscv_nxv1i8x4,
169 MVT::riscv_nxv1i8x5, MVT::riscv_nxv1i8x6, MVT::riscv_nxv1i8x7,
170 MVT::riscv_nxv1i8x8, MVT::riscv_nxv2i8x2, MVT::riscv_nxv2i8x3,
171 MVT::riscv_nxv2i8x4, MVT::riscv_nxv2i8x5, MVT::riscv_nxv2i8x6,
172 MVT::riscv_nxv2i8x7, MVT::riscv_nxv2i8x8, MVT::riscv_nxv4i8x2,
173 MVT::riscv_nxv4i8x3, MVT::riscv_nxv4i8x4, MVT::riscv_nxv4i8x5,
174 MVT::riscv_nxv4i8x6, MVT::riscv_nxv4i8x7, MVT::riscv_nxv4i8x8,
175 MVT::riscv_nxv8i8x2, MVT::riscv_nxv8i8x3, MVT::riscv_nxv8i8x4,
176 MVT::riscv_nxv8i8x5, MVT::riscv_nxv8i8x6, MVT::riscv_nxv8i8x7,
177 MVT::riscv_nxv8i8x8, MVT::riscv_nxv16i8x2, MVT::riscv_nxv16i8x3,
178 MVT::riscv_nxv16i8x4, MVT::riscv_nxv32i8x2};
180 if (Subtarget.hasVInstructions()) {
181 auto addRegClassForRVV = [
this](
MVT VT) {
185 if (VT.getVectorMinNumElements() < MinElts)
188 unsigned Size = VT.getSizeInBits().getKnownMinValue();
191 RC = &RISCV::VRRegClass;
193 RC = &RISCV::VRM2RegClass;
195 RC = &RISCV::VRM4RegClass;
197 RC = &RISCV::VRM8RegClass;
204 for (
MVT VT : BoolVecVTs)
205 addRegClassForRVV(VT);
206 for (
MVT VT : IntVecVTs) {
207 if (VT.getVectorElementType() == MVT::i64 &&
208 !Subtarget.hasVInstructionsI64())
210 addRegClassForRVV(VT);
213 if (Subtarget.hasVInstructionsF16Minimal() ||
214 Subtarget.hasVendorXAndesVPackFPH())
215 for (
MVT VT : F16VecVTs)
216 addRegClassForRVV(VT);
218 if (Subtarget.hasVInstructionsBF16Minimal() ||
219 Subtarget.hasVendorXAndesVBFHCvt())
220 for (
MVT VT : BF16VecVTs)
221 addRegClassForRVV(VT);
223 if (Subtarget.hasVInstructionsF32())
224 for (
MVT VT : F32VecVTs)
225 addRegClassForRVV(VT);
227 if (Subtarget.hasVInstructionsF64())
228 for (
MVT VT : F64VecVTs)
229 addRegClassForRVV(VT);
231 if (Subtarget.useRVVForFixedLengthVectors()) {
232 auto addRegClassForFixedVectors = [
this](
MVT VT) {
239 if (useRVVForFixedLengthVectorVT(VT))
240 addRegClassForFixedVectors(VT);
243 if (useRVVForFixedLengthVectorVT(VT))
244 addRegClassForFixedVectors(VT);
304 if (!(Subtarget.hasVendorXCValu() && !Subtarget.is64Bit())) {
314 if (!Subtarget.hasVendorXTHeadBb() && !Subtarget.hasVendorXqcibm() &&
315 !Subtarget.hasVendorXAndesPerf())
320 if (!Subtarget.hasStdExtZbb() && !Subtarget.hasVendorXTHeadBb() &&
321 !Subtarget.hasVendorXqcibm() && !Subtarget.hasVendorXAndesPerf() &&
322 !(Subtarget.hasVendorXCValu() && !Subtarget.is64Bit()))
325 if (Subtarget.hasStdExtZilsd() && !Subtarget.is64Bit()) {
330 if (Subtarget.is64Bit()) {
337 if (!Subtarget.hasStdExtZbb())
343 if (!Subtarget.hasStdExtZmmul()) {
345 }
else if (Subtarget.is64Bit()) {
352 if (!Subtarget.hasStdExtM()) {
355 }
else if (Subtarget.is64Bit()) {
357 {MVT::i8, MVT::i16, MVT::i32},
Custom);
367 if (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) {
368 if (Subtarget.is64Bit())
370 }
else if (Subtarget.hasVendorXTHeadBb()) {
371 if (Subtarget.is64Bit())
374 }
else if (Subtarget.hasVendorXCVbitmanip() && !Subtarget.is64Bit()) {
383 (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb() ||
384 Subtarget.hasVendorXTHeadBb())
388 if ((Subtarget.hasVendorXCVbitmanip() || Subtarget.hasVendorXqcibm()) &&
389 !Subtarget.is64Bit()) {
395 if (Subtarget.hasStdExtZbkb())
399 if (Subtarget.hasStdExtZbb() ||
400 (Subtarget.hasVendorXCValu() && !Subtarget.is64Bit())) {
405 if (Subtarget.hasStdExtZbb() ||
406 (Subtarget.hasVendorXCVbitmanip() && !Subtarget.is64Bit())) {
407 if (Subtarget.is64Bit())
413 if (Subtarget.is64Bit())
420 if (Subtarget.hasStdExtZbb() || Subtarget.hasVendorXTHeadBb() ||
421 (Subtarget.hasVendorXCVbitmanip() && !Subtarget.is64Bit())) {
424 if (Subtarget.is64Bit())
430 if (Subtarget.hasVendorXCValu() && !Subtarget.is64Bit()) {
432 }
else if (Subtarget.hasShortForwardBranchOpt()) {
435 }
else if (Subtarget.is64Bit()) {
439 if (!Subtarget.useCCMovInsn() && !Subtarget.hasVendorXTHeadCondMov() &&
440 !Subtarget.hasVendorXqcicm() && !Subtarget.hasVendorXqcics())
443 if (Subtarget.hasVendorXqcia() && !Subtarget.is64Bit()) {
452 static const unsigned FPLegalNodeTypes[] = {
453 ISD::FMINNUM, ISD::FMAXNUM, ISD::FMINIMUMNUM,
454 ISD::FMAXIMUMNUM, ISD::LRINT, ISD::LLRINT,
466 static const unsigned FPOpToExpand[] = {
467 ISD::FSIN, ISD::FCOS, ISD::FSINCOS, ISD::FPOW,
470 static const unsigned FPRndMode[] = {
471 ISD::FCEIL, ISD::FFLOOR, ISD::FTRUNC, ISD::FRINT, ISD::FROUND,
474 static const unsigned ZfhminZfbfminPromoteOps[] = {
475 ISD::FMINNUM, ISD::FMAXNUM, ISD::FMAXIMUMNUM,
482 ISD::FTRUNC, ISD::FRINT, ISD::FROUND,
485 if (Subtarget.hasStdExtZfbfmin()) {
500 if (Subtarget.hasStdExtZfhminOrZhinxmin()) {
501 if (Subtarget.hasStdExtZfhOrZhinx()) {
508 if (Subtarget.hasStdExtZfa())
513 for (
auto Op : {ISD::LROUND, ISD::LLROUND, ISD::LRINT, ISD::LLRINT,
534 ISD::FNEARBYINT, MVT::f16,
535 Subtarget.hasStdExtZfh() && Subtarget.hasStdExtZfa() ?
Legal :
Promote);
537 ISD::FCOS, ISD::FSIN, ISD::FSINCOS, ISD::FEXP,
538 ISD::FEXP2, ISD::FEXP10, ISD::FLOG, ISD::FLOG2,
539 ISD::FLOG10, ISD::FLDEXP, ISD::FFREXP},
551 if (Subtarget.is64Bit())
555 if (Subtarget.hasStdExtFOrZfinx()) {
577 if (Subtarget.hasStdExtZfa()) {
586 if (Subtarget.hasStdExtFOrZfinx() && Subtarget.is64Bit())
589 if (Subtarget.hasStdExtDOrZdinx()) {
592 if (!Subtarget.is64Bit())
595 if (Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
596 !Subtarget.is64Bit()) {
601 if (Subtarget.hasStdExtZfa()) {
607 if (Subtarget.is64Bit())
636 if (Subtarget.is64Bit()) {
643 if (Subtarget.hasStdExtFOrZfinx()) {
669 if (Subtarget.is64Bit())
679 if (Subtarget.is64Bit()) {
686 if (Subtarget.is64Bit())
689 if (Subtarget.hasVendorXMIPSCBOP())
691 else if (Subtarget.hasStdExtZicbop())
694 if (Subtarget.hasStdExtA()) {
696 if (Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas())
700 }
else if (Subtarget.hasForcedAtomics()) {
715 if (Subtarget.hasVInstructions()) {
724 {MVT::i8, MVT::i16},
Custom);
725 if (Subtarget.is64Bit())
735 static const unsigned IntegerVPOps[] = {
736 ISD::VP_ADD, ISD::VP_SUB, ISD::VP_MUL,
737 ISD::VP_SDIV, ISD::VP_UDIV, ISD::VP_SREM,
738 ISD::VP_UREM, ISD::VP_AND, ISD::VP_OR,
739 ISD::VP_XOR, ISD::VP_SRA, ISD::VP_SRL,
740 ISD::VP_SHL, ISD::VP_REDUCE_ADD, ISD::VP_REDUCE_AND,
741 ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR, ISD::VP_REDUCE_SMAX,
742 ISD::VP_REDUCE_SMIN, ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN,
743 ISD::VP_MERGE, ISD::VP_SELECT, ISD::VP_FP_TO_SINT,
744 ISD::VP_FP_TO_UINT, ISD::VP_SETCC, ISD::VP_SIGN_EXTEND,
745 ISD::VP_ZERO_EXTEND, ISD::VP_TRUNCATE, ISD::VP_SMIN,
746 ISD::VP_SMAX, ISD::VP_UMIN, ISD::VP_UMAX,
747 ISD::VP_ABS, ISD::EXPERIMENTAL_VP_REVERSE, ISD::EXPERIMENTAL_VP_SPLICE,
748 ISD::VP_SADDSAT, ISD::VP_UADDSAT, ISD::VP_SSUBSAT,
749 ISD::VP_USUBSAT, ISD::VP_CTTZ_ELTS, ISD::VP_CTTZ_ELTS_ZERO_UNDEF,
750 ISD::EXPERIMENTAL_VP_SPLAT};
752 static const unsigned FloatingPointVPOps[] = {
753 ISD::VP_FADD, ISD::VP_FSUB, ISD::VP_FMUL,
754 ISD::VP_FDIV, ISD::VP_FNEG, ISD::VP_FABS,
755 ISD::VP_FMA, ISD::VP_REDUCE_FADD, ISD::VP_REDUCE_SEQ_FADD,
756 ISD::VP_REDUCE_FMIN, ISD::VP_REDUCE_FMAX, ISD::VP_MERGE,
757 ISD::VP_SELECT, ISD::VP_SINT_TO_FP, ISD::VP_UINT_TO_FP,
758 ISD::VP_SETCC, ISD::VP_FP_ROUND, ISD::VP_FP_EXTEND,
759 ISD::VP_SQRT, ISD::VP_FMINNUM, ISD::VP_FMAXNUM,
760 ISD::VP_FCEIL, ISD::VP_FFLOOR, ISD::VP_FROUND,
761 ISD::VP_FROUNDEVEN, ISD::VP_FCOPYSIGN, ISD::VP_FROUNDTOZERO,
762 ISD::VP_FRINT, ISD::VP_FNEARBYINT, ISD::VP_IS_FPCLASS,
763 ISD::VP_FMINIMUM, ISD::VP_FMAXIMUM, ISD::VP_LRINT,
764 ISD::VP_LLRINT, ISD::VP_REDUCE_FMINIMUM,
765 ISD::VP_REDUCE_FMAXIMUM, ISD::EXPERIMENTAL_VP_SPLAT};
767 static const unsigned IntegerVecReduceOps[] = {
768 ISD::VECREDUCE_ADD, ISD::VECREDUCE_AND, ISD::VECREDUCE_OR,
769 ISD::VECREDUCE_XOR, ISD::VECREDUCE_SMAX, ISD::VECREDUCE_SMIN,
770 ISD::VECREDUCE_UMAX, ISD::VECREDUCE_UMIN};
772 static const unsigned FloatingPointVecReduceOps[] = {
773 ISD::VECREDUCE_FADD, ISD::VECREDUCE_SEQ_FADD, ISD::VECREDUCE_FMIN,
774 ISD::VECREDUCE_FMAX, ISD::VECREDUCE_FMINIMUM, ISD::VECREDUCE_FMAXIMUM};
776 static const unsigned FloatingPointLibCallOps[] = {
777 ISD::FREM, ISD::FPOW, ISD::FCOS, ISD::FSIN, ISD::FSINCOS, ISD::FEXP,
778 ISD::FEXP2, ISD::FEXP10, ISD::FLOG, ISD::FLOG2, ISD::FLOG10};
780 if (!Subtarget.is64Bit()) {
789 ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR,
790 ISD::VP_REDUCE_SMAX, ISD::VP_REDUCE_SMIN,
791 ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN},
795 for (
MVT VT : BoolVecVTs) {
821 {ISD::VECREDUCE_AND, ISD::VECREDUCE_OR, ISD::VECREDUCE_XOR}, VT,
825 {ISD::VP_REDUCE_AND, ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR}, VT,
849 ISD::VP_TRUNCATE, ISD::VP_SETCC},
866 for (
MVT VT : IntVecVTs) {
877 if (VT.getVectorElementType() == MVT::i64 && !Subtarget.hasStdExtV())
927 {ISD::VP_LOAD, ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
928 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER, ISD::VP_SCATTER},
953 if (Subtarget.hasStdExtZvkb()) {
961 if (Subtarget.hasStdExtZvbb()) {
965 ISD::VP_CTTZ_ZERO_UNDEF, ISD::VP_CTPOP},
971 ISD::VP_CTTZ_ZERO_UNDEF, ISD::VP_CTPOP},
980 ISD::VP_CTLZ_ZERO_UNDEF, ISD::VP_CTTZ_ZERO_UNDEF},
988 for (
MVT VT : VecTupleVTs) {
1009 static const unsigned ZvfhminZvfbfminPromoteOps[] = {
1037 ISD::VECREDUCE_FMIN,
1038 ISD::VECREDUCE_FMAX,
1039 ISD::VECREDUCE_FMINIMUM,
1040 ISD::VECREDUCE_FMAXIMUM};
1043 static const unsigned ZvfhminZvfbfminPromoteVPOps[] = {
1049 ISD::VP_REDUCE_FMIN,
1050 ISD::VP_REDUCE_FMAX,
1058 ISD::VP_FROUNDTOZERO,
1064 ISD::VP_REDUCE_FMINIMUM,
1065 ISD::VP_REDUCE_FMAXIMUM};
1068 const auto SetCommonVFPActions = [&](
MVT VT) {
1084 {ISD::FMINNUM, ISD::FMAXNUM, ISD::FMAXIMUMNUM, ISD::FMINIMUMNUM}, VT,
1089 ISD::FROUNDEVEN, ISD::FRINT, ISD::FNEARBYINT,
1106 {ISD::VP_LOAD, ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1107 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER, ISD::VP_SCATTER},
1143 const auto SetCommonVFPExtLoadTruncStoreActions =
1145 for (
auto SmallVT : SmallerVTs) {
1153 const auto SetCommonPromoteToF32Actions = [&](
MVT VT) {
1181 ISD::MGATHER, ISD::MSCATTER, ISD::VP_LOAD,
1182 ISD::VP_STORE, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1183 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1206 if (Subtarget.hasVInstructionsF16()) {
1207 for (
MVT VT : F16VecVTs) {
1210 SetCommonVFPActions(VT);
1212 }
else if (Subtarget.hasVInstructionsF16Minimal()) {
1213 for (
MVT VT : F16VecVTs) {
1216 SetCommonPromoteToF32Actions(VT);
1220 if (Subtarget.hasVInstructionsBF16Minimal()) {
1221 for (
MVT VT : BF16VecVTs) {
1224 SetCommonPromoteToF32Actions(VT);
1228 if (Subtarget.hasVInstructionsF32()) {
1229 for (
MVT VT : F32VecVTs) {
1232 SetCommonVFPActions(VT);
1233 SetCommonVFPExtLoadTruncStoreActions(VT, F16VecVTs);
1234 SetCommonVFPExtLoadTruncStoreActions(VT, BF16VecVTs);
1238 if (Subtarget.hasVInstructionsF64()) {
1239 for (
MVT VT : F64VecVTs) {
1242 SetCommonVFPActions(VT);
1243 SetCommonVFPExtLoadTruncStoreActions(VT, F16VecVTs);
1244 SetCommonVFPExtLoadTruncStoreActions(VT, BF16VecVTs);
1245 SetCommonVFPExtLoadTruncStoreActions(VT, F32VecVTs);
1249 if (Subtarget.useRVVForFixedLengthVectors()) {
1251 if (!useRVVForFixedLengthVectorVT(VT))
1296 {ISD::VECREDUCE_AND, ISD::VECREDUCE_OR, ISD::VECREDUCE_XOR}, VT,
1300 {ISD::VP_REDUCE_AND, ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR}, VT,
1327 ISD::VP_SETCC, ISD::VP_TRUNCATE},
1351 {ISD::MLOAD, ISD::MSTORE, ISD::MGATHER, ISD::MSCATTER}, VT,
Custom);
1354 ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1355 ISD::EXPERIMENTAL_VP_STRIDED_STORE, ISD::VP_GATHER,
1387 ISD::VECREDUCE_SMIN, ISD::VECREDUCE_UMAX,
1388 ISD::VECREDUCE_UMIN},
1393 if (Subtarget.hasStdExtZvkb())
1396 if (Subtarget.hasStdExtZvbb()) {
1420 if (!useRVVForFixedLengthVectorVT(VT))
1443 ISD::MGATHER, ISD::MSCATTER},
1446 ISD::VP_SCATTER, ISD::EXPERIMENTAL_VP_STRIDED_LOAD,
1447 ISD::EXPERIMENTAL_VP_STRIDED_STORE},
1456 !Subtarget.hasVInstructionsF16()) {
1466 if (Subtarget.hasStdExtZfhmin()) {
1492 if (Subtarget.hasStdExtZfbfmin()) {
1518 ISD::FMA, ISD::FMINNUM, ISD::FMAXNUM,
1520 ISD::FMAXIMUM, ISD::FMINIMUM},
1524 ISD::FROUNDEVEN, ISD::FRINT, ISD::LRINT,
1525 ISD::LLRINT, ISD::LROUND, ISD::LLROUND,
1551 if (Subtarget.is64Bit())
1553 if (Subtarget.hasStdExtZfhminOrZhinxmin())
1555 if (Subtarget.hasStdExtZfbfmin())
1557 if (Subtarget.hasStdExtFOrZfinx())
1559 if (Subtarget.hasStdExtDOrZdinx())
1564 if (Subtarget.hasStdExtA())
1567 if (Subtarget.hasForcedAtomics()) {
1570 {ISD::ATOMIC_CMP_SWAP, ISD::ATOMIC_SWAP, ISD::ATOMIC_LOAD_ADD,
1571 ISD::ATOMIC_LOAD_SUB, ISD::ATOMIC_LOAD_AND, ISD::ATOMIC_LOAD_OR,
1572 ISD::ATOMIC_LOAD_XOR, ISD::ATOMIC_LOAD_NAND, ISD::ATOMIC_LOAD_MIN,
1573 ISD::ATOMIC_LOAD_MAX, ISD::ATOMIC_LOAD_UMIN, ISD::ATOMIC_LOAD_UMAX},
1577 if (Subtarget.hasVendorXTHeadMemIdx()) {
1586 if (Subtarget.is64Bit()) {
1593 if (Subtarget.hasVendorXCVmem() && !Subtarget.is64Bit()) {
1604 if (Subtarget.hasStdExtZvqdotq() && Subtarget.getELen() >= 64) {
1605 static const unsigned MLAOps[] = {ISD::PARTIAL_REDUCE_SMLA,
1606 ISD::PARTIAL_REDUCE_UMLA,
1607 ISD::PARTIAL_REDUCE_SUMLA};
1614 if (Subtarget.useRVVForFixedLengthVectors()) {
1616 if (VT.getVectorElementType() != MVT::i32 ||
1617 !useRVVForFixedLengthVectorVT(VT))
1627 if (Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh()) {
1633 const Align FunctionAlignment(Subtarget.hasStdExtZca() ? 2 : 4);
1645 if (Subtarget.hasStdExtFOrZfinx())
1648 if (Subtarget.hasStdExtZbb())
1651 if ((Subtarget.hasStdExtZbs() && Subtarget.is64Bit()) ||
1652 Subtarget.hasVInstructions())
1655 if (Subtarget.hasStdExtZbkb())
1658 if (Subtarget.hasStdExtFOrZfinx())
1661 if (Subtarget.hasVInstructions())
1664 ISD::VP_GATHER, ISD::VP_SCATTER,
ISD::SRA,
1667 ISD::VP_STORE, ISD::VP_TRUNCATE, ISD::EXPERIMENTAL_VP_REVERSE,
1673 if (Subtarget.hasVendorXTHeadMemPair())
1675 if (Subtarget.useRVVForFixedLengthVectors())
1695 Subtarget.getMaxStoresPerMemmove(
true);
1707 if (Subtarget.hasVInstructions() &&
1718bool RISCVTargetLowering::shouldExpandGetVectorLength(
EVT TripCountVT,
1720 bool IsScalable)
const {
1727 if (TripCountVT != MVT::i32 && TripCountVT != Subtarget.
getXLenVT())
1745 return !Subtarget.hasVInstructions() ||
1753 auto &
DL =
I.getDataLayout();
1755 auto SetRVVLoadStoreInfo = [&](
unsigned PtrOp,
bool IsStore,
1756 bool IsUnitStrided,
bool UsePtrVal =
false) {
1761 Info.ptrVal =
I.getArgOperand(PtrOp);
1763 Info.fallbackAddressSpace =
1764 I.getArgOperand(PtrOp)->getType()->getPointerAddressSpace();
1768 MemTy =
I.getArgOperand(0)->getType();
1771 MemTy =
I.getType();
1786 Info.align =
DL.getABITypeAlign(MemTy);
1796 if (
I.hasMetadata(LLVMContext::MD_nontemporal))
1803 case Intrinsic::riscv_masked_atomicrmw_xchg:
1804 case Intrinsic::riscv_masked_atomicrmw_add:
1805 case Intrinsic::riscv_masked_atomicrmw_sub:
1806 case Intrinsic::riscv_masked_atomicrmw_nand:
1807 case Intrinsic::riscv_masked_atomicrmw_max:
1808 case Intrinsic::riscv_masked_atomicrmw_min:
1809 case Intrinsic::riscv_masked_atomicrmw_umax:
1810 case Intrinsic::riscv_masked_atomicrmw_umin:
1811 case Intrinsic::riscv_masked_cmpxchg:
1818 Info.memVT = MVT::i32;
1819 Info.ptrVal =
I.getArgOperand(0);
1821 Info.align =
Align(4);
1825 case Intrinsic::riscv_seg2_load_mask:
1826 case Intrinsic::riscv_seg3_load_mask:
1827 case Intrinsic::riscv_seg4_load_mask:
1828 case Intrinsic::riscv_seg5_load_mask:
1829 case Intrinsic::riscv_seg6_load_mask:
1830 case Intrinsic::riscv_seg7_load_mask:
1831 case Intrinsic::riscv_seg8_load_mask:
1832 case Intrinsic::riscv_sseg2_load_mask:
1833 case Intrinsic::riscv_sseg3_load_mask:
1834 case Intrinsic::riscv_sseg4_load_mask:
1835 case Intrinsic::riscv_sseg5_load_mask:
1836 case Intrinsic::riscv_sseg6_load_mask:
1837 case Intrinsic::riscv_sseg7_load_mask:
1838 case Intrinsic::riscv_sseg8_load_mask:
1839 return SetRVVLoadStoreInfo( 0,
false,
1841 case Intrinsic::riscv_seg2_store_mask:
1842 case Intrinsic::riscv_seg3_store_mask:
1843 case Intrinsic::riscv_seg4_store_mask:
1844 case Intrinsic::riscv_seg5_store_mask:
1845 case Intrinsic::riscv_seg6_store_mask:
1846 case Intrinsic::riscv_seg7_store_mask:
1847 case Intrinsic::riscv_seg8_store_mask:
1849 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1852 case Intrinsic::riscv_sseg2_store_mask:
1853 case Intrinsic::riscv_sseg3_store_mask:
1854 case Intrinsic::riscv_sseg4_store_mask:
1855 case Intrinsic::riscv_sseg5_store_mask:
1856 case Intrinsic::riscv_sseg6_store_mask:
1857 case Intrinsic::riscv_sseg7_store_mask:
1858 case Intrinsic::riscv_sseg8_store_mask:
1860 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
1863 case Intrinsic::riscv_vlm:
1864 return SetRVVLoadStoreInfo( 0,
1868 case Intrinsic::riscv_vle:
1869 case Intrinsic::riscv_vle_mask:
1870 case Intrinsic::riscv_vleff:
1871 case Intrinsic::riscv_vleff_mask:
1872 return SetRVVLoadStoreInfo( 1,
1876 case Intrinsic::riscv_vsm:
1877 case Intrinsic::riscv_vse:
1878 case Intrinsic::riscv_vse_mask:
1879 return SetRVVLoadStoreInfo( 1,
1883 case Intrinsic::riscv_vlse:
1884 case Intrinsic::riscv_vlse_mask:
1885 case Intrinsic::riscv_vloxei:
1886 case Intrinsic::riscv_vloxei_mask:
1887 case Intrinsic::riscv_vluxei:
1888 case Intrinsic::riscv_vluxei_mask:
1889 return SetRVVLoadStoreInfo( 1,
1892 case Intrinsic::riscv_vsse:
1893 case Intrinsic::riscv_vsse_mask:
1894 case Intrinsic::riscv_vsoxei:
1895 case Intrinsic::riscv_vsoxei_mask:
1896 case Intrinsic::riscv_vsuxei:
1897 case Intrinsic::riscv_vsuxei_mask:
1898 return SetRVVLoadStoreInfo( 1,
1901 case Intrinsic::riscv_vlseg2:
1902 case Intrinsic::riscv_vlseg3:
1903 case Intrinsic::riscv_vlseg4:
1904 case Intrinsic::riscv_vlseg5:
1905 case Intrinsic::riscv_vlseg6:
1906 case Intrinsic::riscv_vlseg7:
1907 case Intrinsic::riscv_vlseg8:
1908 case Intrinsic::riscv_vlseg2ff:
1909 case Intrinsic::riscv_vlseg3ff:
1910 case Intrinsic::riscv_vlseg4ff:
1911 case Intrinsic::riscv_vlseg5ff:
1912 case Intrinsic::riscv_vlseg6ff:
1913 case Intrinsic::riscv_vlseg7ff:
1914 case Intrinsic::riscv_vlseg8ff:
1915 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1918 case Intrinsic::riscv_vlseg2_mask:
1919 case Intrinsic::riscv_vlseg3_mask:
1920 case Intrinsic::riscv_vlseg4_mask:
1921 case Intrinsic::riscv_vlseg5_mask:
1922 case Intrinsic::riscv_vlseg6_mask:
1923 case Intrinsic::riscv_vlseg7_mask:
1924 case Intrinsic::riscv_vlseg8_mask:
1925 case Intrinsic::riscv_vlseg2ff_mask:
1926 case Intrinsic::riscv_vlseg3ff_mask:
1927 case Intrinsic::riscv_vlseg4ff_mask:
1928 case Intrinsic::riscv_vlseg5ff_mask:
1929 case Intrinsic::riscv_vlseg6ff_mask:
1930 case Intrinsic::riscv_vlseg7ff_mask:
1931 case Intrinsic::riscv_vlseg8ff_mask:
1932 return SetRVVLoadStoreInfo(
I.arg_size() - 5,
1935 case Intrinsic::riscv_vlsseg2:
1936 case Intrinsic::riscv_vlsseg3:
1937 case Intrinsic::riscv_vlsseg4:
1938 case Intrinsic::riscv_vlsseg5:
1939 case Intrinsic::riscv_vlsseg6:
1940 case Intrinsic::riscv_vlsseg7:
1941 case Intrinsic::riscv_vlsseg8:
1942 case Intrinsic::riscv_vloxseg2:
1943 case Intrinsic::riscv_vloxseg3:
1944 case Intrinsic::riscv_vloxseg4:
1945 case Intrinsic::riscv_vloxseg5:
1946 case Intrinsic::riscv_vloxseg6:
1947 case Intrinsic::riscv_vloxseg7:
1948 case Intrinsic::riscv_vloxseg8:
1949 case Intrinsic::riscv_vluxseg2:
1950 case Intrinsic::riscv_vluxseg3:
1951 case Intrinsic::riscv_vluxseg4:
1952 case Intrinsic::riscv_vluxseg5:
1953 case Intrinsic::riscv_vluxseg6:
1954 case Intrinsic::riscv_vluxseg7:
1955 case Intrinsic::riscv_vluxseg8:
1956 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
1959 case Intrinsic::riscv_vlsseg2_mask:
1960 case Intrinsic::riscv_vlsseg3_mask:
1961 case Intrinsic::riscv_vlsseg4_mask:
1962 case Intrinsic::riscv_vlsseg5_mask:
1963 case Intrinsic::riscv_vlsseg6_mask:
1964 case Intrinsic::riscv_vlsseg7_mask:
1965 case Intrinsic::riscv_vlsseg8_mask:
1966 case Intrinsic::riscv_vloxseg2_mask:
1967 case Intrinsic::riscv_vloxseg3_mask:
1968 case Intrinsic::riscv_vloxseg4_mask:
1969 case Intrinsic::riscv_vloxseg5_mask:
1970 case Intrinsic::riscv_vloxseg6_mask:
1971 case Intrinsic::riscv_vloxseg7_mask:
1972 case Intrinsic::riscv_vloxseg8_mask:
1973 case Intrinsic::riscv_vluxseg2_mask:
1974 case Intrinsic::riscv_vluxseg3_mask:
1975 case Intrinsic::riscv_vluxseg4_mask:
1976 case Intrinsic::riscv_vluxseg5_mask:
1977 case Intrinsic::riscv_vluxseg6_mask:
1978 case Intrinsic::riscv_vluxseg7_mask:
1979 case Intrinsic::riscv_vluxseg8_mask:
1980 return SetRVVLoadStoreInfo(
I.arg_size() - 6,
1983 case Intrinsic::riscv_vsseg2:
1984 case Intrinsic::riscv_vsseg3:
1985 case Intrinsic::riscv_vsseg4:
1986 case Intrinsic::riscv_vsseg5:
1987 case Intrinsic::riscv_vsseg6:
1988 case Intrinsic::riscv_vsseg7:
1989 case Intrinsic::riscv_vsseg8:
1990 return SetRVVLoadStoreInfo(
I.arg_size() - 3,
1993 case Intrinsic::riscv_vsseg2_mask:
1994 case Intrinsic::riscv_vsseg3_mask:
1995 case Intrinsic::riscv_vsseg4_mask:
1996 case Intrinsic::riscv_vsseg5_mask:
1997 case Intrinsic::riscv_vsseg6_mask:
1998 case Intrinsic::riscv_vsseg7_mask:
1999 case Intrinsic::riscv_vsseg8_mask:
2000 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
2003 case Intrinsic::riscv_vssseg2:
2004 case Intrinsic::riscv_vssseg3:
2005 case Intrinsic::riscv_vssseg4:
2006 case Intrinsic::riscv_vssseg5:
2007 case Intrinsic::riscv_vssseg6:
2008 case Intrinsic::riscv_vssseg7:
2009 case Intrinsic::riscv_vssseg8:
2010 case Intrinsic::riscv_vsoxseg2:
2011 case Intrinsic::riscv_vsoxseg3:
2012 case Intrinsic::riscv_vsoxseg4:
2013 case Intrinsic::riscv_vsoxseg5:
2014 case Intrinsic::riscv_vsoxseg6:
2015 case Intrinsic::riscv_vsoxseg7:
2016 case Intrinsic::riscv_vsoxseg8:
2017 case Intrinsic::riscv_vsuxseg2:
2018 case Intrinsic::riscv_vsuxseg3:
2019 case Intrinsic::riscv_vsuxseg4:
2020 case Intrinsic::riscv_vsuxseg5:
2021 case Intrinsic::riscv_vsuxseg6:
2022 case Intrinsic::riscv_vsuxseg7:
2023 case Intrinsic::riscv_vsuxseg8:
2024 return SetRVVLoadStoreInfo(
I.arg_size() - 4,
2027 case Intrinsic::riscv_vssseg2_mask:
2028 case Intrinsic::riscv_vssseg3_mask:
2029 case Intrinsic::riscv_vssseg4_mask:
2030 case Intrinsic::riscv_vssseg5_mask:
2031 case Intrinsic::riscv_vssseg6_mask:
2032 case Intrinsic::riscv_vssseg7_mask:
2033 case Intrinsic::riscv_vssseg8_mask:
2034 case Intrinsic::riscv_vsoxseg2_mask:
2035 case Intrinsic::riscv_vsoxseg3_mask:
2036 case Intrinsic::riscv_vsoxseg4_mask:
2037 case Intrinsic::riscv_vsoxseg5_mask:
2038 case Intrinsic::riscv_vsoxseg6_mask:
2039 case Intrinsic::riscv_vsoxseg7_mask:
2040 case Intrinsic::riscv_vsoxseg8_mask:
2041 case Intrinsic::riscv_vsuxseg2_mask:
2042 case Intrinsic::riscv_vsuxseg3_mask:
2043 case Intrinsic::riscv_vsuxseg4_mask:
2044 case Intrinsic::riscv_vsuxseg5_mask:
2045 case Intrinsic::riscv_vsuxseg6_mask:
2046 case Intrinsic::riscv_vsuxseg7_mask:
2047 case Intrinsic::riscv_vsuxseg8_mask:
2048 return SetRVVLoadStoreInfo(
I.arg_size() - 5,
2102 if (Subtarget.is64Bit() || !SrcTy->isIntegerTy() || !DstTy->
isIntegerTy())
2104 unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
2106 return (SrcBits == 64 && DestBits == 32);
2117 return (SrcBits == 64 && DestBits == 32);
2123 if (Subtarget.hasVInstructions() &&
2128 if (SrcBits == DestBits * 2) {
2140 EVT MemVT = LD->getMemoryVT();
2141 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
2151 return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
2159 return Subtarget.hasStdExtZbb() ||
2160 (Subtarget.hasVendorXCVbitmanip() && !Subtarget.is64Bit());
2164 return Subtarget.hasStdExtZbb() || Subtarget.hasVendorXTHeadBb() ||
2165 (Subtarget.hasVendorXCVbitmanip() && !Subtarget.is64Bit());
2176 if (!Subtarget.hasBEXTILike())
2181 return !Mask->getValue().isSignedIntN(12) && Mask->getValue().isPowerOf2();
2185 EVT VT =
Y.getValueType();
2190 return (Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
2195 EVT VT =
Y.getValueType();
2200 return Subtarget.hasStdExtZvkb();
2205 if (Subtarget.hasStdExtZbs())
2206 return X.getValueType().isScalarInteger();
2209 if (Subtarget.hasVendorXTHeadBs())
2210 return C !=
nullptr;
2212 return C &&
C->getAPIntValue().ule(10);
2216 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
2222 if (!VT.
isVector() || !Subtarget.hasVInstructions())
2233 assert(Ty->isIntegerTy());
2235 unsigned BitSize = Ty->getIntegerBitWidth();
2236 if (BitSize > Subtarget.getXLen())
2240 int64_t Val = Imm.getSExtValue();
2248 if (!Subtarget.enableUnalignedScalarMem())
2258 return Seq.
size() <= Subtarget.getMaxBuildIntsCost();
2264 unsigned OldShiftOpcode,
unsigned NewShiftOpcode,
2271 if (XC && OldShiftOpcode ==
ISD::SRL && XC->isOne())
2319 if (!Subtarget.hasStdExtZfa())
2322 bool IsSupportedVT =
false;
2323 if (VT == MVT::f16) {
2324 IsSupportedVT = Subtarget.hasStdExtZfh() || Subtarget.hasStdExtZvfh();
2325 }
else if (VT == MVT::f32) {
2326 IsSupportedVT =
true;
2327 }
else if (VT == MVT::f64) {
2328 assert(Subtarget.hasStdExtD() &&
"Expect D extension");
2329 IsSupportedVT =
true;
2339 bool ForCodeSize)
const {
2340 bool IsLegalVT =
false;
2342 IsLegalVT = Subtarget.hasStdExtZfhminOrZhinxmin();
2343 else if (VT == MVT::f32)
2344 IsLegalVT = Subtarget.hasStdExtFOrZfinx();
2345 else if (VT == MVT::f64)
2346 IsLegalVT = Subtarget.hasStdExtDOrZdinx();
2347 else if (VT == MVT::bf16)
2348 IsLegalVT = Subtarget.hasStdExtZfbfmin();
2364 return Imm.isZero();
2368 if (Imm.isNegZero())
2373 const int FmvCost = Subtarget.hasStdExtZfinx() ? 0 : 1;
2376 Subtarget.getXLen(), Subtarget);
2382 unsigned Index)
const {
2399 if (EltVT == MVT::i1)
2405 unsigned MinVLen = Subtarget.getRealMinVLen();
2412 if (Index + ResElts <= MinVLMAX && Index < 31)
2421 return (ResElts * 2) == SrcElts && (Index == 0 || Index == ResElts);
2429 if (VT == MVT::f16 && Subtarget.hasStdExtFOrZfinx() &&
2430 !Subtarget.hasStdExtZfhminOrZhinxmin())
2440 std::optional<MVT> RegisterVT)
const {
2442 if (VT == (Subtarget.is64Bit() ? MVT::i128 : MVT::i64) && RegisterVT &&
2443 *RegisterVT == MVT::Untyped)
2454 if (VT == MVT::f16 && Subtarget.hasStdExtFOrZfinx() &&
2455 !Subtarget.hasStdExtZfhminOrZhinxmin())
2463 unsigned &NumIntermediates,
MVT &RegisterVT)
const {
2465 Context, CC, VT, IntermediateVT, NumIntermediates, RegisterVT);
2483 !Subtarget.hasVendorXAndesPerf()) {
2489 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
2503 int64_t
C = RHSC->getSExtValue();
2558 if (VT.
SimpleTy >= MVT::riscv_nxv1i8x2 &&
2559 VT.
SimpleTy <= MVT::riscv_nxv1i8x8)
2561 if (VT.
SimpleTy >= MVT::riscv_nxv2i8x2 &&
2562 VT.
SimpleTy <= MVT::riscv_nxv2i8x8)
2564 if (VT.
SimpleTy >= MVT::riscv_nxv4i8x2 &&
2565 VT.
SimpleTy <= MVT::riscv_nxv4i8x8)
2567 if (VT.
SimpleTy >= MVT::riscv_nxv8i8x2 &&
2568 VT.
SimpleTy <= MVT::riscv_nxv8i8x8)
2570 if (VT.
SimpleTy >= MVT::riscv_nxv16i8x2 &&
2571 VT.
SimpleTy <= MVT::riscv_nxv16i8x4)
2573 if (VT.
SimpleTy == MVT::riscv_nxv32i8x2)
2583 switch (KnownSize) {
2611 return RISCV::VRRegClassID;
2613 return RISCV::VRM2RegClassID;
2615 return RISCV::VRM4RegClassID;
2617 return RISCV::VRM8RegClassID;
2625 static_assert(RISCV::sub_vrm1_7 == RISCV::sub_vrm1_0 + 7,
2626 "Unexpected subreg numbering");
2627 return RISCV::sub_vrm1_0 + Index;
2630 static_assert(RISCV::sub_vrm2_3 == RISCV::sub_vrm2_0 + 3,
2631 "Unexpected subreg numbering");
2632 return RISCV::sub_vrm2_0 + Index;
2635 static_assert(RISCV::sub_vrm4_1 == RISCV::sub_vrm4_0 + 1,
2636 "Unexpected subreg numbering");
2637 return RISCV::sub_vrm4_0 + Index;
2645 unsigned RegsPerField =
2648 switch (RegsPerField) {
2651 return RISCV::VRN2M1RegClassID;
2653 return RISCV::VRN3M1RegClassID;
2655 return RISCV::VRN4M1RegClassID;
2657 return RISCV::VRN5M1RegClassID;
2659 return RISCV::VRN6M1RegClassID;
2661 return RISCV::VRN7M1RegClassID;
2663 return RISCV::VRN8M1RegClassID;
2667 return RISCV::VRN2M2RegClassID;
2669 return RISCV::VRN3M2RegClassID;
2671 return RISCV::VRN4M2RegClassID;
2675 return RISCV::VRN2M4RegClassID;
2683 return RISCV::VRRegClassID;
2692std::pair<unsigned, unsigned>
2694 MVT VecVT,
MVT SubVecVT,
unsigned InsertExtractIdx,
2696 static_assert((RISCV::VRM8RegClassID > RISCV::VRM4RegClassID &&
2697 RISCV::VRM4RegClassID > RISCV::VRM2RegClassID &&
2698 RISCV::VRM2RegClassID > RISCV::VRRegClassID),
2699 "Register classes not ordered");
2706 if (VecRegClassID == SubRegClassID)
2707 return {RISCV::NoSubRegister, 0};
2710 "Only allow scalable vector subvector.");
2712 "Invalid vector tuple insert/extract for vector and subvector with "
2723 unsigned SubRegIdx = RISCV::NoSubRegister;
2724 for (
const unsigned RCID :
2725 {RISCV::VRM4RegClassID, RISCV::VRM2RegClassID, RISCV::VRRegClassID})
2726 if (VecRegClassID > RCID && SubRegClassID <= RCID) {
2730 SubRegIdx =
TRI->composeSubRegIndices(SubRegIdx,
2735 return {SubRegIdx, InsertExtractIdx};
2740bool RISCVTargetLowering::mergeStoresAfterLegalization(
EVT VT)
const {
2750 return Subtarget.is64Bit() ? Subtarget.hasVInstructionsI64() :
true;
2756 return Subtarget.hasVInstructionsI64();
2758 return Subtarget.hasVInstructionsF16Minimal();
2760 return Subtarget.hasVInstructionsBF16Minimal();
2762 return Subtarget.hasVInstructionsF32();
2764 return Subtarget.hasVInstructionsF64();
2778 "Unexpected opcode");
2780 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
2782 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
2785 return Op.getOperand(
II->VLOperand + 1 + HasChain);
2859bool RISCVTargetLowering::useRVVForFixedLengthVectorVT(
MVT VT)
const {
2860 return ::useRVVForFixedLengthVectorVT(VT, Subtarget);
2869 "Expected legal fixed length vector!");
2872 unsigned MaxELen = Subtarget.
getELen();
2906 return ::getContainerForFixedLengthVector(*
this, VT,
getSubtarget());
2913 "Expected to convert into a scalable vector!");
2914 assert(V.getValueType().isFixedLengthVector() &&
2915 "Expected a fixed length vector operand!");
2924 "Expected to convert into a fixed length vector!");
2925 assert(V.getValueType().isScalableVector() &&
2926 "Expected a scalable vector operand!");
2945 return DAG.
getNode(RISCVISD::VMSET_VL,
DL, MaskVT, VL);
2948static std::pair<SDValue, SDValue>
2957static std::pair<SDValue, SDValue>
2970static std::pair<SDValue, SDValue>
2987std::pair<unsigned, unsigned>
2995 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
2999 unsigned VectorBitsMin = Subtarget.getRealMinVLen();
3003 return std::make_pair(MinVLMAX, MaxVLMAX);
3015 EVT VT,
unsigned DefinedValues)
const {
3024 unsigned DLenFactor = Subtarget.getDLenFactor();
3029 std::tie(LMul, Fractional) =
3032 Cost = LMul <= DLenFactor ? (DLenFactor / LMul) : 1;
3034 Cost = (LMul * DLenFactor);
3048 bool Log2CostModel =
3050 if (Log2CostModel && LMULCost.isValid()) {
3051 unsigned Log =
Log2_64(LMULCost.getValue());
3053 return LMULCost * Log;
3055 return LMULCost * LMULCost;
3086 Op.getValueType() == MVT::bf16) {
3087 bool IsStrict =
Op->isStrictFPOpcode();
3092 {Op.getOperand(0), Op.getOperand(1)});
3094 {
Op.getValueType(), MVT::Other},
3100 DAG.
getNode(
Op.getOpcode(),
DL, MVT::f32,
Op.getOperand(0)),
3115 MVT DstVT =
Op.getSimpleValueType();
3124 Src.getValueType() == MVT::bf16) {
3130 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
3131 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
3132 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
3139 Opc,
DL, DstVT, Src,
3142 if (
Opc == RISCVISD::FCVT_WU_RV64)
3153 MVT SrcVT = Src.getSimpleValueType();
3159 if (SatVT != DstEltVT)
3162 MVT DstContainerVT = DstVT;
3163 MVT SrcContainerVT = SrcVT;
3169 "Expected same element count");
3178 {Src, Src, DAG.getCondCode(ISD::SETNE),
3179 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
3183 if (DstEltSize > (2 * SrcEltSize)) {
3186 Src = DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, InterVT, Src, Mask, VL);
3189 MVT CvtContainerVT = DstContainerVT;
3190 MVT CvtEltVT = DstEltVT;
3191 if (SrcEltSize > (2 * DstEltSize)) {
3197 IsSigned ? RISCVISD::VFCVT_RTZ_X_F_VL : RISCVISD::VFCVT_RTZ_XU_F_VL;
3200 while (CvtContainerVT != DstContainerVT) {
3204 unsigned ClipOpc = IsSigned ? RISCVISD::TRUNCATE_VECTOR_VL_SSAT
3205 : RISCVISD::TRUNCATE_VECTOR_VL_USAT;
3206 Res = DAG.
getNode(ClipOpc,
DL, CvtContainerVT, Res, Mask, VL);
3210 RISCVISD::VMV_V_X_VL,
DL, DstContainerVT, DAG.
getUNDEF(DstContainerVT),
3212 Res = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, DstContainerVT, IsNan, SplatZero,
3213 Res, DAG.
getUNDEF(DstContainerVT), VL);
3223 bool IsStrict =
Op->isStrictFPOpcode();
3224 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
3234 {
Op.getOperand(0), SrcVal});
3235 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
3236 {Ext.getValue(1), Ext.getValue(0)});
3239 DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, SrcVal));
3248 case ISD::FROUNDEVEN:
3250 case ISD::VP_FROUNDEVEN:
3254 case ISD::VP_FROUNDTOZERO:
3258 case ISD::VP_FFLOOR:
3270 case ISD::VP_FROUND:
3280 case ISD::VP_LLRINT:
3294 MVT VT =
Op.getSimpleValueType();
3304 MVT ContainerVT = VT;
3311 if (
Op->isVPOpcode()) {
3312 Mask =
Op.getOperand(1);
3316 VL =
Op.getOperand(2);
3322 SDValue Abs = DAG.
getNode(RISCVISD::FABS_VL,
DL, ContainerVT, Src, Mask, VL);
3335 DAG.
getUNDEF(ContainerVT), MaxValNode, VL);
3340 DAG.
getNode(RISCVISD::SETCC_VL,
DL, SetccVT,
3349 switch (
Op.getOpcode()) {
3357 case ISD::VP_FFLOOR:
3359 case ISD::FROUNDEVEN:
3360 case ISD::VP_FROUND:
3361 case ISD::VP_FROUNDEVEN:
3362 case ISD::VP_FROUNDTOZERO: {
3365 Truncated = DAG.
getNode(RISCVISD::VFCVT_RM_X_F_VL,
DL, IntVT, Src, Mask,
3370 Truncated = DAG.
getNode(RISCVISD::VFCVT_RTZ_X_F_VL,
DL, IntVT, Src,
3373 case ISD::FNEARBYINT:
3374 case ISD::VP_FNEARBYINT:
3375 Truncated = DAG.
getNode(RISCVISD::VFROUND_NOEXCEPT_VL,
DL, ContainerVT, Src,
3381 if (Truncated.
getOpcode() != RISCVISD::VFROUND_NOEXCEPT_VL)
3382 Truncated = DAG.
getNode(RISCVISD::SINT_TO_FP_VL,
DL, ContainerVT, Truncated,
3386 Truncated = DAG.
getNode(RISCVISD::FCOPYSIGN_VL,
DL, ContainerVT, Truncated,
3387 Src, Src, Mask, VL);
3402 MVT VT =
Op.getSimpleValueType();
3406 MVT ContainerVT = VT;
3418 MVT MaskVT = Mask.getSimpleValueType();
3421 {Chain, Src, Src, DAG.getCondCode(ISD::SETUNE),
3422 DAG.getUNDEF(MaskVT), Mask, VL});
3424 Src = DAG.
getNode(RISCVISD::STRICT_FADD_VL,
DL,
3426 {Chain, Src, Src, Src, Unorder, VL});
3430 SDValue Abs = DAG.
getNode(RISCVISD::FABS_VL,
DL, ContainerVT, Src, Mask, VL);
3443 DAG.
getUNDEF(ContainerVT), MaxValNode, VL);
3447 RISCVISD::SETCC_VL,
DL, MaskVT,
3455 switch (
Op.getOpcode()) {
3465 RISCVISD::STRICT_VFCVT_RM_X_F_VL,
DL, DAG.
getVTList(IntVT, MVT::Other),
3466 {Chain, Src, Mask, DAG.getTargetConstant(FRM, DL, XLenVT), VL});
3471 DAG.
getNode(RISCVISD::STRICT_VFCVT_RTZ_X_F_VL,
DL,
3472 DAG.
getVTList(IntVT, MVT::Other), Chain, Src, Mask, VL);
3475 Truncated = DAG.
getNode(RISCVISD::STRICT_VFROUND_NOEXCEPT_VL,
DL,
3476 DAG.
getVTList(ContainerVT, MVT::Other), Chain, Src,
3484 Truncated = DAG.
getNode(RISCVISD::STRICT_SINT_TO_FP_VL,
DL,
3485 DAG.
getVTList(ContainerVT, MVT::Other), Chain,
3486 Truncated, Mask, VL);
3491 Truncated = DAG.
getNode(RISCVISD::FCOPYSIGN_VL,
DL, ContainerVT, Truncated,
3492 Src, Src, Mask, VL);
3502 MVT VT =
Op.getSimpleValueType();
3523 return DAG.
getNode(RISCVISD::FROUND,
DL, VT, Src, MaxValNode,
3531 MVT DstVT =
Op.getSimpleValueType();
3533 MVT SrcVT = Src.getSimpleValueType();
3538 MVT DstContainerVT = DstVT;
3539 MVT SrcContainerVT = SrcVT;
3551 if (SrcElemType == MVT::f16 || SrcElemType == MVT::bf16) {
3553 Src = DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, F32VT, Src, Mask, VL);
3557 DAG.
getNode(RISCVISD::VFCVT_RM_X_F_VL,
DL, DstContainerVT, Src, Mask,
3577 return DAG.
getNode(RISCVISD::VSLIDEDOWN_VL,
DL, VT,
Ops);
3589 return DAG.
getNode(RISCVISD::VSLIDEUP_VL,
DL, VT,
Ops);
3614 return std::nullopt;
3632 unsigned EltSizeInBits) {
3635 return std::nullopt;
3636 bool IsInteger =
Op.getValueType().isInteger();
3638 std::optional<unsigned> SeqStepDenom;
3639 std::optional<APInt> SeqStepNum;
3640 std::optional<APInt> SeqAddend;
3641 std::optional<std::pair<APInt, unsigned>> PrevElt;
3642 assert(EltSizeInBits >=
Op.getValueType().getScalarSizeInBits());
3647 const unsigned OpSize =
Op.getScalarValueSizeInBits();
3648 for (
auto [Idx, Elt] :
enumerate(
Op->op_values())) {
3649 if (Elt.isUndef()) {
3650 Elts[Idx] = std::nullopt;
3654 Elts[Idx] = Elt->getAsAPIntVal().trunc(OpSize).zext(EltSizeInBits);
3659 return std::nullopt;
3660 Elts[Idx] = *ExactInteger;
3664 for (
auto [Idx, Elt] :
enumerate(Elts)) {
3673 unsigned IdxDiff = Idx - PrevElt->second;
3674 APInt ValDiff = *Elt - PrevElt->first;
3682 int64_t Remainder = ValDiff.
srem(IdxDiff);
3687 return std::nullopt;
3688 ValDiff = ValDiff.
sdiv(IdxDiff);
3693 SeqStepNum = ValDiff;
3694 else if (ValDiff != SeqStepNum)
3695 return std::nullopt;
3698 SeqStepDenom = IdxDiff;
3699 else if (IdxDiff != *SeqStepDenom)
3700 return std::nullopt;
3704 if (!PrevElt || PrevElt->first != *Elt)
3705 PrevElt = std::make_pair(*Elt, Idx);
3709 if (!SeqStepNum || !SeqStepDenom)
3710 return std::nullopt;
3714 for (
auto [Idx, Elt] :
enumerate(Elts)) {
3718 (
APInt(EltSizeInBits, Idx,
false,
true) *
3720 .sdiv(*SeqStepDenom);
3722 APInt Addend = *Elt - ExpectedVal;
3725 else if (Addend != SeqAddend)
3726 return std::nullopt;
3729 assert(SeqAddend &&
"Must have an addend if we have a step");
3731 return VIDSequence{SeqStepNum->getSExtValue(), *SeqStepDenom,
3732 SeqAddend->getSExtValue()};
3747 if (EltTy == MVT::i1 ||
3750 MVT SrcVT = Src.getSimpleValueType();
3766 MVT ContainerVT = VT;
3770 MVT SrcContainerVT = SrcVT;
3785 SDValue Gather = DAG.
getNode(RISCVISD::VRGATHER_VX_VL,
DL, ContainerVT, Src,
3786 Idx, DAG.
getUNDEF(ContainerVT), Mask, VL);
3794 MVT VT =
Op.getSimpleValueType();
3803 int64_t StepNumerator = SimpleVID->StepNumerator;
3804 unsigned StepDenominator = SimpleVID->StepDenominator;
3805 int64_t Addend = SimpleVID->Addend;
3807 assert(StepNumerator != 0 &&
"Invalid step");
3808 bool Negate =
false;
3809 int64_t SplatStepVal = StepNumerator;
3813 if (StepNumerator != 1 && StepNumerator !=
INT64_MIN &&
3815 Negate = StepNumerator < 0;
3817 SplatStepVal =
Log2_64(std::abs(StepNumerator));
3827 (SplatStepVal >= 0 || StepDenominator == 1) &&
isInt<32>(Addend)) {
3830 MVT VIDContainerVT =
3838 if ((StepOpcode ==
ISD::MUL && SplatStepVal != 1) ||
3839 (StepOpcode ==
ISD::SHL && SplatStepVal != 0)) {
3841 VID = DAG.
getNode(StepOpcode,
DL, VIDVT, VID, SplatStep);
3843 if (StepDenominator != 1) {
3848 if (Addend != 0 || Negate) {
3874 MVT VT =
Op.getSimpleValueType();
3883 unsigned NumElts =
Op.getNumOperands();
3886 unsigned MostCommonCount = 0;
3888 unsigned NumUndefElts =
3896 unsigned NumScalarLoads = 0;
3902 unsigned &
Count = ValueCounts[V];
3905 NumScalarLoads += !CFP->isExactlyValue(+0.0);
3910 if (++
Count >= MostCommonCount) {
3912 MostCommonCount =
Count;
3916 assert(DominantValue &&
"Not expecting an all-undef BUILD_VECTOR");
3917 unsigned NumDefElts = NumElts - NumUndefElts;
3918 unsigned DominantValueCountThreshold = NumDefElts <= 2 ? 0 : NumDefElts - 2;
3924 ((MostCommonCount > DominantValueCountThreshold) ||
3936 if (
SDValue LastOp =
Op->getOperand(
Op->getNumOperands() - 1);
3937 !LastOp.isUndef() && ValueCounts[LastOp] == 1 &&
3938 LastOp != DominantValue) {
3941 VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1DOWN_VL : RISCVISD::VSLIDE1DOWN_VL;
3947 Processed.
insert(LastOp);
3953 if (V.isUndef() || !Processed.
insert(V).second)
3955 if (ValueCounts[V] == 1) {
3963 return DAG.getConstant(V == V1, DL, XLenVT);
3979 MVT VT =
Op.getSimpleValueType();
3988 unsigned NumElts =
Op.getNumOperands();
4009 unsigned NumViaIntegerBits = std::clamp(NumElts, 8u, Subtarget.
getXLen());
4010 NumViaIntegerBits = std::min(NumViaIntegerBits, Subtarget.
getELen());
4018 unsigned IntegerViaVecElts =
divideCeil(NumElts, NumViaIntegerBits);
4019 MVT IntegerViaVecVT =
4024 unsigned BitPos = 0, IntegerEltIdx = 0;
4027 for (
unsigned I = 0;
I < NumElts;) {
4029 bool BitValue = !V.isUndef() && V->getAsZExtVal();
4030 Bits |= ((
uint64_t)BitValue << BitPos);
4036 if (
I % NumViaIntegerBits == 0 ||
I == NumElts) {
4037 if (NumViaIntegerBits <= 32)
4040 Elts[IntegerEltIdx] = Elt;
4049 if (NumElts < NumViaIntegerBits) {
4053 assert(IntegerViaVecVT == MVT::v1i8 &&
"Unexpected mask vector type");
4068 : RISCVISD::VMV_V_X_VL;
4088 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32) &&
4089 "Unexpected sequence type");
4093 unsigned ViaVecLen =
4101 const auto &SeqV =
OpIdx.value();
4102 if (!SeqV.isUndef())
4104 ((SeqV->getAsZExtVal() & EltMask) << (
OpIdx.index() * EltBitSize));
4110 if (ViaIntVT == MVT::i32)
4133 BV->getRepeatedSequence(Sequence) &&
4134 (Sequence.size() * EltBitSize) <= Subtarget.
getELen()) {
4135 unsigned SeqLen = Sequence.size();
4137 assert((ViaIntVT == MVT::i16 || ViaIntVT == MVT::i32 ||
4138 ViaIntVT == MVT::i64) &&
4139 "Unexpected sequence type");
4144 const unsigned RequiredVL = NumElts / SeqLen;
4145 const unsigned ViaVecLen =
4147 NumElts : RequiredVL;
4150 unsigned EltIdx = 0;
4155 for (
const auto &SeqV : Sequence) {
4156 if (!SeqV.isUndef())
4158 ((SeqV->getAsZExtVal() & EltMask) << (EltIdx * EltBitSize));
4165 if (ViaIntVT == MVT::i32)
4172 (!Subtarget.
is64Bit() && ViaIntVT == MVT::i64)) &&
4173 "Unexpected bitcast sequence");
4177 MVT ViaContainerVT =
4180 DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ViaContainerVT,
4184 if (ViaVecLen != RequiredVL)
4203 Source, DAG, Subtarget);
4204 SDValue Res = DAG.
getNode(RISCVISD::VSEXT_VL,
DL, ContainerVT, Source, Mask, VL);
4223 return RISCV::PACKH;
4225 return Subtarget.
is64Bit() ? RISCV::PACKW : RISCV::PACK;
4240 MVT VT =
Op.getSimpleValueType();
4248 if (!Subtarget.hasStdExtZbb() || !Subtarget.hasStdExtZba())
4253 if (ElemSizeInBits >= std::min(Subtarget.
getELen(), Subtarget.
getXLen()) ||
4267 if (Subtarget.hasStdExtZbkb())
4272 ElemDL, XLenVT,
A,
B),
4284 NewOperands.
reserve(NumElts / 2);
4286 NewOperands.
push_back(pack(
Op.getOperand(i),
Op.getOperand(i + 1)));
4290 return DAG.
getNode(ISD::BITCAST,
DL, VT,
4296 MVT VT =
Op.getSimpleValueType();
4307 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) || EltVT == MVT::bf16) {
4312 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4313 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin())) {
4323 NewOps[
I] = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Elem);
4373 [](
const SDUse &U) { return U.get().isUndef(); })) {
4414 auto OneVRegOfOps =
ArrayRef(BuildVectorOps).slice(i, ElemsPerVReg);
4418 unsigned InsertIdx = (i / ElemsPerVReg) * NumOpElts;
4440 unsigned NumUndefElts =
4442 unsigned NumDefElts = NumElts - NumUndefElts;
4443 if (NumDefElts >= 8 && NumDefElts > NumElts / 2 &&
4450 for (
const auto &[Idx, U] :
enumerate(
Op->ops())) {
4452 if (Idx < NumElts / 2) {
4459 bool SelectMaskVal = (Idx < NumElts / 2);
4462 assert(SubVecAOps.
size() == NumElts && SubVecBOps.
size() == NumElts &&
4463 MaskVals.
size() == NumElts);
4498 unsigned UndefCount = 0;
4505 LinearBudget -= PerSlideCost;
4508 LinearBudget -= PerSlideCost;
4511 LinearBudget -= PerSlideCost;
4514 if (LinearBudget < 0)
4519 "Illegal type which will result in reserved encoding");
4535 bool SlideUp =
false;
4601 Vec = getVSlide(ContainerVT, DAG.
getUNDEF(ContainerVT), Vec,
Offset, Mask,
4608 Opcode = SlideUp ? RISCVISD::VFSLIDE1UP_VL : RISCVISD::VFSLIDE1DOWN_VL;
4610 Opcode = SlideUp ? RISCVISD::VSLIDE1UP_VL : RISCVISD::VSLIDE1DOWN_VL;
4619 Vec = getVSlide(ContainerVT, DAG.
getUNDEF(ContainerVT), Vec,
Offset, Mask,
4635 if ((LoC >> 31) == HiC)
4636 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4648 auto InterVec = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, InterVT,
4650 return DAG.
getNode(ISD::BITCAST,
DL, VT, InterVec);
4657 Hi.getConstantOperandVal(1) == 31)
4658 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4663 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru,
Lo, VL);
4666 return DAG.
getNode(RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL,
DL, VT, Passthru,
Lo,
4676 assert(Scalar.getValueType() == MVT::i64 &&
"Unexpected VT!");
4688 bool HasPassthru = Passthru && !Passthru.
isUndef();
4689 if (!HasPassthru && !Passthru)
4696 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
4697 EltVT == MVT::bf16) {
4698 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
4699 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
4700 Scalar = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Scalar);
4702 Scalar = DAG.
getNode(ISD::BITCAST,
DL, MVT::i16, Scalar);
4704 Passthru = DAG.
getNode(ISD::BITCAST,
DL, IVT, Passthru);
4709 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL, VT, Passthru, Scalar, VL);
4713 if (Scalar.getValueType().bitsLE(XLenVT)) {
4720 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4721 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru, Scalar, VL);
4724 assert(XLenVT == MVT::i32 && Scalar.getValueType() == MVT::i64 &&
4725 "Unexpected scalar for splat lowering!");
4728 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, VT, Passthru,
4754 MVT ExtractedContainerVT = ExtractedVT;
4757 DAG, ExtractedContainerVT, Subtarget);
4759 ExtractedVal, DAG, Subtarget);
4761 if (ExtractedContainerVT.
bitsLE(VT))
4773 if (!Scalar.getValueType().bitsLE(XLenVT))
4776 VT,
DL, DAG, Subtarget);
4784 Scalar = DAG.
getNode(ExtOpc,
DL, XLenVT, Scalar);
4825 Src && Src.
getValueType().getVectorNumElements() == (NumElts * 2))
4842 !Subtarget.hasVendorXRivosVizip())
4845 int Size = Mask.size();
4847 assert(
Size == (
int)NumElts &&
"Unexpected mask size");
4853 EvenSrc = StartIndexes[0];
4854 OddSrc = StartIndexes[1];
4857 if (EvenSrc != 0 && OddSrc != 0)
4867 int HalfNumElts = NumElts / 2;
4868 return ((EvenSrc % HalfNumElts) == 0) && ((OddSrc % HalfNumElts) == 0);
4873 std::array<std::pair<int, int>, 2> &SrcInfo) {
4878 if (SrcInfo[0].second == 0 && SrcInfo[1].second == 0)
4882 if ((SrcInfo[0].second > 0 && SrcInfo[1].second < 0) ||
4883 SrcInfo[1].second == 0)
4885 assert(SrcInfo[0].first != -1 &&
"Must find one slide");
4893 if (SrcInfo[1].first == -1)
4895 return SrcInfo[0].second < 0 && SrcInfo[1].second > 0 &&
4896 SrcInfo[1].second - SrcInfo[0].second == (int)NumElts;
4901 bool RequiredPolarity) {
4902 int NumElts = Mask.size();
4903 for (
const auto &[Idx, M] :
enumerate(Mask)) {
4906 int Src = M >= NumElts;
4907 int Diff = (int)Idx - (M % NumElts);
4908 bool C = Src == SrcInfo[1].first && Diff == SrcInfo[1].second;
4909 assert(
C != (Src == SrcInfo[0].first && Diff == SrcInfo[0].second) &&
4910 "Must match exactly one of the two slides");
4911 if (RequiredPolarity != (
C == (Idx / Factor) % 2))
4922static bool isZipEven(
const std::array<std::pair<int, int>, 2> &SrcInfo,
4924 Factor = SrcInfo[1].second;
4926 Mask.size() % Factor == 0 &&
4937static bool isZipOdd(
const std::array<std::pair<int, int>, 2> &SrcInfo,
4939 Factor = -SrcInfo[1].second;
4941 Mask.size() % Factor == 0 &&
4954 ElementCount SrcEC = Src.getValueType().getVectorElementCount();
4961 unsigned Shift = Index * EltBits;
4986 std::optional<int> SplatIdx;
4988 if (M == -1 ||
I == (
unsigned)M)
4990 if (SplatIdx && *SplatIdx != M)
4999 for (
int MaskIndex : Mask) {
5000 bool SelectMaskVal = MaskIndex == *SplatIdx;
5003 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
5028 auto findNonEXTRACT_SUBVECTORParent =
5029 [](
SDValue Parent) -> std::pair<SDValue, uint64_t> {
5034 Parent.getOperand(0).getSimpleValueType().isFixedLengthVector()) {
5035 Offset += Parent.getConstantOperandVal(1);
5036 Parent = Parent.getOperand(0);
5038 return std::make_pair(Parent,
Offset);
5041 auto [V1Src, V1IndexOffset] = findNonEXTRACT_SUBVECTORParent(V1);
5042 auto [V2Src, V2IndexOffset] = findNonEXTRACT_SUBVECTORParent(V2);
5051 for (
size_t i = 0; i != NewMask.
size(); ++i) {
5052 if (NewMask[i] == -1)
5055 if (
static_cast<size_t>(NewMask[i]) < NewMask.
size()) {
5056 NewMask[i] = NewMask[i] + V1IndexOffset;
5060 NewMask[i] = NewMask[i] - NewMask.
size() + V2IndexOffset;
5066 if (NewMask[0] <= 0)
5070 for (
unsigned i = 1; i != NewMask.
size(); ++i)
5071 if (NewMask[i - 1] + 1 != NewMask[i])
5075 MVT SrcVT = Src.getSimpleValueType();
5104 int NumSubElts, Index;
5109 bool OpsSwapped = Mask[Index] < (int)NumElts;
5110 SDValue InPlace = OpsSwapped ? V2 : V1;
5111 SDValue ToInsert = OpsSwapped ? V1 : V2;
5122 if (NumSubElts + Index >= (
int)NumElts)
5133 Res = DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, ContainerVT, InPlace, ToInsert,
5136 Res =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, InPlace, ToInsert,
5148 bool OpsSwapped =
false;
5163 const unsigned E = Mask.size() - ((
Offset > 0) ?
Offset : 0);
5164 for (
unsigned i = S; i !=
E; ++i)
5165 if (Mask[i] >= 0 && (
unsigned)Mask[i] !=
Base + i +
Offset)
5171 bool IsVSlidedown = isSlideMask(Mask, OpsSwapped ? 0 : NumElts, 1);
5172 if (!IsVSlidedown && !isSlideMask(Mask, OpsSwapped ? 0 : NumElts, -1))
5175 const int InsertIdx = Mask[IsVSlidedown ? (NumElts - 1) : 0];
5177 if (InsertIdx < 0 || InsertIdx / NumElts != (
unsigned)OpsSwapped)
5194 IsVSlidedown ? RISCVISD::VSLIDE1DOWN_VL : RISCVISD::VSLIDE1UP_VL,
DL,
5200 auto OpCode = IsVSlidedown ?
5201 (VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1DOWN_VL : RISCVISD::VSLIDE1DOWN_VL) :
5202 (VT.
isFloatingPoint() ? RISCVISD::VFSLIDE1UP_VL : RISCVISD::VSLIDE1UP_VL);
5205 auto Vec = DAG.
getNode(OpCode,
DL, ContainerVT,
5208 Splat, TrueMask, VL);
5220 for (
unsigned i = 0; i < Mask.size(); i++)
5221 LaneIsUndef[i % Factor] &= (Mask[i] == -1);
5224 for (
unsigned i = 0; i < Factor; i++) {
5235 for (
unsigned i = 0; i < Mask.size() / Factor; i++) {
5236 unsigned j = i * Factor + Index;
5237 if (Mask[j] != -1 && (
unsigned)Mask[j] != i)
5246 assert(RISCVISD::RI_VZIPEVEN_VL ==
Opc || RISCVISD::RI_VZIPODD_VL ==
Opc ||
5247 RISCVISD::RI_VZIP2A_VL ==
Opc || RISCVISD::RI_VZIP2B_VL ==
Opc ||
5248 RISCVISD::RI_VUNZIP2A_VL ==
Opc || RISCVISD::RI_VUNZIP2B_VL ==
Opc);
5256 MVT ContainerVT = IntVT;
5263 MVT InnerVT = ContainerVT;
5267 (RISCVISD::RI_VUNZIP2A_VL ==
Opc || RISCVISD::RI_VUNZIP2B_VL ==
Opc)) {
5279 if (InnerVT.
bitsLT(ContainerVT))
5294 MVT VT = V.getSimpleValueType();
5309 EC.multiplyCoefficientBy(Factor));
5328 MVT VecContainerVT = VecVT;
5345 MVT WideContainerVT = WideVT;
5351 EvenV = DAG.
getBitcast(VecContainerVT, EvenV);
5358 if (Subtarget.hasStdExtZvbb()) {
5362 Interleaved = DAG.
getNode(RISCVISD::VWSLL_VL,
DL, WideContainerVT, OddV,
5363 OffsetVec, Passthru, Mask, VL);
5364 Interleaved = DAG.
getNode(RISCVISD::VWADDU_W_VL,
DL, WideContainerVT,
5365 Interleaved, EvenV, Passthru, Mask, VL);
5372 Interleaved = DAG.
getNode(RISCVISD::VWADDU_VL,
DL, WideContainerVT, EvenV,
5373 OddV, Passthru, Mask, VL);
5379 OddV, AllOnesVec, Passthru, Mask, VL);
5386 Interleaved = DAG.
getNode(RISCVISD::ADD_VL,
DL, WideContainerVT,
5387 Interleaved, OddsMul, Passthru, Mask, VL);
5394 Interleaved = DAG.
getBitcast(ResultContainerVT, Interleaved);
5440 if (ViaEltSize > NumElts)
5448 if (ViaEltSize > NumElts)
5454 if (ViaEltSize > NumElts)
5461 MVT &RotateVT,
unsigned &RotateAmt) {
5464 unsigned NumSubElts;
5466 NumElts, NumSubElts, RotateAmt))
5469 NumElts / NumSubElts);
5537 unsigned NumOfSrcRegs = NumElts / NumOpElts;
5538 unsigned NumOfDestRegs = NumElts / NumOpElts;
5547 Mask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs,
5548 [&]() {
Operands.emplace_back(); },
5549 [&](
ArrayRef<int> SrcSubMask,
unsigned SrcVecIdx,
unsigned DstVecIdx) {
5550 Operands.emplace_back().emplace_back(SrcVecIdx, UINT_MAX,
5553 [&](
ArrayRef<int> SrcSubMask,
unsigned Idx1,
unsigned Idx2,
bool NewReg) {
5558 assert(
Operands.size() == NumOfDestRegs &&
"Whole vector must be processed");
5563 unsigned NumShuffles = std::accumulate(
5570 for (const auto &P : Data) {
5571 unsigned Idx2 = std::get<1>(P);
5572 ArrayRef<int> Mask = std::get<2>(P);
5573 if (Idx2 != UINT_MAX)
5575 else if (ShuffleVectorInst::isIdentityMask(Mask, Mask.size()))
5580 if ((NumOfDestRegs > 2 && NumShuffles > NumOfDestRegs) ||
5581 (NumOfDestRegs <= 2 && NumShuffles >= 4))
5583 auto ExtractValue = [&, &DAG = DAG](
SDValue SrcVec,
unsigned ExtractIdx) {
5584 SDValue SubVec = DAG.getExtractSubvector(
DL, M1VT, SrcVec, ExtractIdx);
5588 auto PerformShuffle = [&, &DAG = DAG](
SDValue SubVec1,
SDValue SubVec2,
5590 SDValue SubVec = DAG.getVectorShuffle(OneRegVT,
DL, SubVec1, SubVec2, Mask);
5593 SDValue Vec = DAG.getUNDEF(ContainerVT);
5599 const auto &[Idx1, Idx2,
_] =
Data[
I];
5607 V = ExtractValue(Idx1 >= NumOfSrcRegs ? V2 : V1,
5608 (Idx1 % NumOfSrcRegs) * NumOpElts);
5609 if (Idx2 != UINT_MAX) {
5612 V = ExtractValue(Idx2 >= NumOfSrcRegs ? V2 : V1,
5613 (Idx2 % NumOfSrcRegs) * NumOpElts);
5617 for (
const auto &[Idx1, Idx2, Mask] :
Data) {
5619 SDValue V2 = Idx2 == UINT_MAX ? V1 : Values.
at(Idx2);
5620 V = PerformShuffle(V1, V2, Mask);
5624 unsigned InsertIdx =
I * NumOpElts;
5626 Vec = DAG.getInsertSubvector(
DL, Vec, V, InsertIdx);
5636 bool SawUndef =
false;
5637 for (
const auto &[Idx, M] :
enumerate(Mask)) {
5644 if (Idx > (
unsigned)M)
5677 for (
int Idx : Mask) {
5680 unsigned SrcIdx = Idx % Mask.size();
5681 int Src = (
uint32_t)Idx < Mask.size() ? 0 : 1;
5682 if (Srcs[SrcIdx] == -1)
5685 else if (Srcs[SrcIdx] != Src)
5691 for (
int Lane : Srcs) {
5704 for (
unsigned I = 0;
I < Mask.size();
I++) {
5708 NewMask[
I] = Mask[
I] % Mask.size();
5722 if ((M / Span) != (
int)(
I / Span))
5724 int SpanIdx =
I % Span;
5734 return all_of(Mask, [&](
const auto &Idx) {
return Idx == -1 || Idx < Span; });
5746 int SpanIdx =
I % Span;
5747 if (Mask[SpanIdx] != M)
5761 MVT VT =
Op.getSimpleValueType();
5769 if (ElementSize > 32)
5792 MVT VT =
Op.getSimpleValueType();
5820 auto [TrueMask, VL] = TrueMaskVL;
5835 V.getOperand(0).getSimpleValueType().getVectorNumElements();
5836 V = V.getOperand(
Offset / OpElements);
5866 MVT SplatVT = ContainerVT;
5869 if (SVT == MVT::bf16 ||
5870 (SVT == MVT::f16 && !Subtarget.hasStdExtZfh())) {
5879 V = DAG.
getLoad(SVT,
DL, Ld->getChain(), NewAddr,
5880 Ld->getPointerInfo().getWithOffset(
Offset),
5881 Ld->getBaseAlign(), Ld->getMemOperand()->
getFlags());
5884 Ld->getPointerInfo().getWithOffset(
Offset), SVT,
5886 Ld->getMemOperand()->getFlags());
5890 : RISCVISD::VMV_V_X_VL;
5898 assert(Lane < (
int)NumElts &&
"Unexpected lane!");
5901 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
5923 if (Subtarget.hasStdExtZvkb())
5939 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
5940 for (
unsigned Factor = 2; Factor <= MaxFactor; Factor <<= 1) {
5943 1 <
count_if(Mask, [](
int Idx) {
return Idx != -1; })) {
5947 [&Mask](
int Idx) {
return Idx < (int)Mask.size(); }) &&
5948 1 <
count_if(Mask, [&Mask](
int Idx) {
5949 return Idx >= (int)Mask.size();
5979 if (Subtarget.hasVendorXRivosVizip() &&
5981 1 <
count_if(Mask, [](
int Idx) {
return Idx != -1; })) {
5983 Index == 0 ? RISCVISD::RI_VUNZIP2A_VL : RISCVISD::RI_VUNZIP2B_VL;
5999 [&Mask](
int Idx) {
return Idx < (int)Mask.size(); }) &&
6001 [&Mask](
int Idx) {
return Idx >= (int)Mask.size(); })) {
6005 if (NumElts < MinVLMAX) {
6029 int EvenSrc, OddSrc;
6039 bool LaneIsUndef[2] = {
true,
true};
6040 for (
const auto &[Idx, M] :
enumerate(Mask))
6041 LaneIsUndef[Idx % 2] &= (M == -1);
6043 int Size = Mask.size();
6045 if (LaneIsUndef[0]) {
6048 assert(EvenSrc >= 0 &&
"Undef source?");
6049 EvenV = (EvenSrc /
Size) == 0 ? V1 : V2;
6053 if (LaneIsUndef[1]) {
6056 assert(OddSrc >= 0 &&
"Undef source?");
6057 OddV = (OddSrc /
Size) == 0 ? V1 : V2;
6063 if (Subtarget.hasVendorXRivosVizip()) {
6066 return lowerVZIP(RISCVISD::RI_VZIP2A_VL, EvenV, OddV,
DL, DAG, Subtarget);
6077 std::array<std::pair<int, int>, 2> SrcInfo;
6084 auto GetSourceFor = [&](
const std::pair<int, int> &
Info) {
6085 int SrcIdx =
Info.first;
6086 assert(SrcIdx == 0 || SrcIdx == 1);
6087 SDValue &Src = Sources[SrcIdx];
6089 SDValue SrcV = SrcIdx == 0 ? V1 : V2;
6094 auto GetSlide = [&](
const std::pair<int, int> &Src,
SDValue Mask,
6096 auto [TrueMask, VL] = TrueMaskVL;
6097 SDValue SrcV = GetSourceFor(Src);
6098 int SlideAmt = Src.second;
6099 if (SlideAmt == 0) {
6101 assert(Mask == TrueMask);
6108 return getVSlideup(DAG, Subtarget,
DL, ContainerVT, Passthru, SrcV,
6113 if (SrcInfo[1].first == -1) {
6115 Res = GetSlide(SrcInfo[0], TrueMask, Res);
6119 if (Subtarget.hasVendorXRivosVizip()) {
6120 bool TryWiden =
false;
6124 SDValue Src1 = SrcInfo[0].first == 0 ? V1 : V2;
6125 SDValue Src2 = SrcInfo[1].first == 0 ? V1 : V2;
6126 return lowerVZIP(RISCVISD::RI_VZIPEVEN_VL, Src1, Src2,
DL, DAG,
6131 if (
isZipOdd(SrcInfo, Mask, Factor)) {
6133 SDValue Src1 = SrcInfo[1].first == 0 ? V1 : V2;
6134 SDValue Src2 = SrcInfo[0].first == 0 ? V1 : V2;
6135 return lowerVZIP(RISCVISD::RI_VZIPODD_VL, Src1, Src2,
DL, DAG,
6153 for (
const auto &[Idx, M] :
enumerate(Mask)) {
6155 (SrcInfo[1].second > 0 && Idx < (
unsigned)SrcInfo[1].second)) {
6159 int Src = M >= (int)NumElts;
6160 int Diff = (int)Idx - (M % NumElts);
6161 bool C = Src == SrcInfo[1].first && Diff == SrcInfo[1].second;
6162 assert(
C ^ (Src == SrcInfo[0].first && Diff == SrcInfo[0].second) &&
6163 "Must match exactly one of the two slides");
6166 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
6173 Res = GetSlide(SrcInfo[0], TrueMask, Res);
6174 Res = GetSlide(SrcInfo[1], SelectMask, Res);
6179 assert(!V1.
isUndef() &&
"Unexpected shuffle canonicalization");
6194 assert(MaxFactor == 2 || MaxFactor == 4 || MaxFactor == 8);
6195 for (
unsigned Factor = 4; Factor <= MaxFactor; Factor <<= 1) {
6210 if (NumElts > MinVLMAX) {
6211 unsigned MaxIdx = 0;
6215 MaxIdx = std::max(std::max((
unsigned)
I, (
unsigned)M), MaxIdx);
6217 unsigned NewNumElts =
6219 if (NewNumElts != NumElts) {
6223 Mask.take_front(NewNumElts));
6240 for (
auto Idx : Mask) {
6243 assert(Idx >= 0 && (
unsigned)Idx < NumElts);
6253 any_of(Mask, [&](
const auto &Idx) {
return Idx > 255; })) {
6263 unsigned GatherVVOpc = RISCVISD::VRGATHER_VV_VL;
6269 GatherVVOpc = RISCVISD::VRGATHEREI16_VV_VL;
6278 GatherVVOpc = RISCVISD::VRGATHEREI16_VV_VL;
6282 MVT IndexContainerVT =
6287 for (
int MaskIndex : Mask) {
6288 bool IsLHSIndex = MaskIndex < (int)NumElts && MaskIndex >= 0;
6298 if (NumElts <= MinVLMAX) {
6300 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
6306 auto [InnerTrueMask, InnerVL] =
6318 for (
int i = 0; i <
N; i++) {
6322 DAG.
getNode(GatherVVOpc,
DL, M1VT, SubV1, SubIndex,
6323 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6340 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6342 for (
int i = 0; i <
N; i++)
6358 for (
int i = 0; i <
N; i++) {
6361 DAG.
getUNDEF(IndexContainerVT), LHSIndices,
6362 SlideAmt, TrueMask, VL);
6366 DAG.
getNode(GatherVVOpc,
DL, M1VT, SubV1, SubIndex,
6367 DAG.
getUNDEF(M1VT), InnerTrueMask, InnerVL);
6377 DAG.
getUNDEF(ContainerVT), TrueMask, VL);
6387 for (
int MaskIndex : Mask) {
6388 bool IsLHSOrUndefIndex = MaskIndex < (int)NumElts;
6389 ShuffleMaskLHS.
push_back(IsLHSOrUndefIndex && MaskIndex >= 0
6391 ShuffleMaskRHS.
push_back(IsLHSOrUndefIndex ? -1 : (MaskIndex - NumElts));
6422 for (
int MaskIndex : Mask) {
6423 bool SelectMaskVal = (MaskIndex < (int)NumElts) ^ !SwapOps;
6427 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
6445 const unsigned NumElts = M.size();
6452 std::array<std::pair<int, int>, 2> SrcInfo;
6463RISCVTargetLowering::lowerCTLZ_CTTZ_ZERO_UNDEF(
SDValue Op,
6465 MVT VT =
Op.getSimpleValueType();
6469 MVT ContainerVT = VT;
6472 if (
Op->isVPOpcode()) {
6473 Mask =
Op.getOperand(1);
6477 VL =
Op.getOperand(2);
6483 MVT FloatEltVT = (EltSize >= 32) ? MVT::f64 :
MVT::f32;
6485 FloatEltVT = MVT::f32;
6492 "Expected legal float type!");
6499 }
else if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF) {
6502 Src = DAG.
getNode(ISD::VP_AND,
DL, VT, Src, Neg, Mask, VL);
6507 if (FloatVT.
bitsGT(VT)) {
6508 if (
Op->isVPOpcode())
6509 FloatVal = DAG.
getNode(ISD::VP_UINT_TO_FP,
DL, FloatVT, Src, Mask, VL);
6518 if (!
Op->isVPOpcode())
6522 MVT ContainerFloatVT =
6524 FloatVal = DAG.
getNode(RISCVISD::VFCVT_RM_F_XU_VL,
DL, ContainerFloatVT,
6525 Src, Mask, RTZRM, VL);
6532 unsigned ShiftAmt = FloatEltVT == MVT::f64 ? 52 : 23;
6536 if (
Op->isVPOpcode()) {
6545 else if (IntVT.
bitsGT(VT))
6550 unsigned ExponentBias = FloatEltVT == MVT::f64 ? 1023 : 127;
6555 if (
Op.getOpcode() == ISD::VP_CTTZ_ZERO_UNDEF)
6556 return DAG.
getNode(ISD::VP_SUB,
DL, VT, Exp,
6561 unsigned Adjust = ExponentBias + (EltSize - 1);
6563 if (
Op->isVPOpcode())
6573 else if (
Op.getOpcode() == ISD::VP_CTLZ)
6574 Res = DAG.
getNode(ISD::VP_UMIN,
DL, VT, Res,
6582 MVT XLenVT = Subtarget.getXLenVT();
6584 MVT SrcVT =
Source.getSimpleValueType();
6593 SrcVT = ContainerVT;
6605 SDValue Res = DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Source, Mask, EVL);
6606 if (
Op->getOpcode() == ISD::VP_CTTZ_ELTS_ZERO_UNDEF)
6624 assert(Load &&
Load->getMemoryVT().isVector() &&
"Expected vector load");
6627 Load->getMemoryVT(),
6628 *
Load->getMemOperand()))
6632 MVT VT =
Op.getSimpleValueType();
6634 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
6635 "Unexpected unaligned RVV load type");
6639 "Expecting equally-sized RVV vector types to be legal");
6641 Load->getPointerInfo(),
Load->getBaseAlign(),
6642 Load->getMemOperand()->getFlags());
6653 assert(Store &&
Store->getValue().getValueType().isVector() &&
6654 "Expected vector store");
6657 Store->getMemoryVT(),
6658 *
Store->getMemOperand()))
6665 assert((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64) &&
6666 "Unexpected unaligned RVV store type");
6670 "Expecting equally-sized RVV vector types to be legal");
6671 StoredVal = DAG.
getBitcast(NewVT, StoredVal);
6673 Store->getPointerInfo(),
Store->getBaseAlign(),
6674 Store->getMemOperand()->getFlags());
6679 assert(
Op.getValueType() == MVT::i64 &&
"Unexpected VT");
6708 unsigned ShiftAmt, AddOpc;
6719 MVT VT =
Op.getSimpleValueType();
6723 bool Negate =
false;
6727 if (Index < 0 &&
Imm.isNegative()) {
6744 return DAG.
getNode(ISD::FNEG,
DL, VT, Const);
6750 unsigned IsData =
Op.getConstantOperandVal(4);
6753 if (Subtarget.hasVendorXMIPSCBOP() && !IsData)
6754 return Op.getOperand(0);
6766 if (Subtarget.hasStdExtZtso()) {
6774 return DAG.
getNode(ISD::MEMBARRIER, dl, MVT::Other,
Op.getOperand(0));
6782 return DAG.
getNode(ISD::MEMBARRIER, dl, MVT::Other,
Op.getOperand(0));
6790 MVT VT =
Op.getSimpleValueType();
6791 MVT XLenVT = Subtarget.getXLenVT();
6792 unsigned Check =
Op.getConstantOperandVal(1);
6793 unsigned TDCMask = 0;
6821 MVT VT0 =
Op.getOperand(0).getSimpleValueType();
6826 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6828 VL =
Op.getOperand(3);
6831 VL,
Op->getFlags());
6846 if (
Op.getOpcode() == ISD::VP_IS_FPCLASS) {
6848 MVT MaskContainerVT =
6851 VL =
Op.getOperand(3);
6855 SDValue FPCLASS = DAG.
getNode(RISCVISD::FCLASS_VL,
DL, ContainerDstVT, Op0,
6856 Mask, VL,
Op->getFlags());
6858 TDCMaskV = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerDstVT,
6859 DAG.
getUNDEF(ContainerDstVT), TDCMaskV, VL);
6862 DAG.
getNode(RISCVISD::SETCC_VL,
DL, ContainerVT,
6868 TDCMaskV, DAG.
getUNDEF(ContainerDstVT), Mask, VL);
6871 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerDstVT,
6872 DAG.
getUNDEF(ContainerDstVT), SplatZero, VL);
6892 MVT VT =
Op.getSimpleValueType();
6918 Op.getOpcode() == ISD::FMAXIMUM ? RISCVISD::FMAX : RISCVISD::FMIN;
6926 MVT ContainerVT = VT;
6934 if (
Op->isVPOpcode()) {
6935 Mask =
Op.getOperand(2);
6939 VL =
Op.getOperand(3);
6946 SDValue XIsNonNan = DAG.
getNode(RISCVISD::SETCC_VL,
DL, Mask.getValueType(),
6947 {X, X, DAG.getCondCode(ISD::SETOEQ),
6948 DAG.getUNDEF(ContainerVT), Mask, VL});
6949 NewY = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, XIsNonNan,
Y,
X,
6955 SDValue YIsNonNan = DAG.
getNode(RISCVISD::SETCC_VL,
DL, Mask.getValueType(),
6956 {Y, Y, DAG.getCondCode(ISD::SETOEQ),
6957 DAG.getUNDEF(ContainerVT), Mask, VL});
6958 NewX = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, YIsNonNan,
X,
Y,
6963 Op.getOpcode() == ISD::FMAXIMUM ||
Op->getOpcode() == ISD::VP_FMAXIMUM
6964 ? RISCVISD::VFMAX_VL
6965 : RISCVISD::VFMIN_VL;
6967 DAG.
getUNDEF(ContainerVT), Mask, VL);
6975 bool IsFABS =
Op.getOpcode() == ISD::FABS;
6976 assert((IsFABS ||
Op.getOpcode() == ISD::FNEG) &&
6977 "Wrong opcode for lowering FABS or FNEG.");
6980 MVT VT =
Op.getSimpleValueType();
6981 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
6985 DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT,
Op.getOperand(0));
6988 Mask = Mask.sext(Subtarget.
getXLen());
6993 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, Logic);
7001 MVT VT =
Op.getSimpleValueType();
7002 assert((VT == MVT::f16 || VT == MVT::bf16) &&
"Unexpected type");
7012 if (SignSize == Subtarget.
getXLen())
7013 return DAG.
getNode(ISD::BITCAST,
DL, XLenVT, Sign);
7016 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Sign);
7018 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, XLenVT, Sign);
7020 assert(XLenVT == MVT::i32 &&
"Unexpected type");
7023 return DAG.
getNode(RISCVISD::SplitF64,
DL, {MVT::i32, MVT::i32}, Sign)
7053 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, CopiedSign);
7058#define OP_CASE(NODE) \
7060 return RISCVISD::NODE##_VL;
7061#define VP_CASE(NODE) \
7062 case ISD::VP_##NODE: \
7063 return RISCVISD::NODE##_VL;
7065 switch (
Op.getOpcode()) {
7144 case ISD::VP_CTLZ_ZERO_UNDEF:
7145 return RISCVISD::CTLZ_VL;
7147 case ISD::VP_CTTZ_ZERO_UNDEF:
7148 return RISCVISD::CTTZ_VL;
7151 return RISCVISD::VFMADD_VL;
7153 return RISCVISD::STRICT_VFMADD_VL;
7156 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7157 return RISCVISD::VMAND_VL;
7158 return RISCVISD::AND_VL;
7161 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7162 return RISCVISD::VMOR_VL;
7163 return RISCVISD::OR_VL;
7166 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
7167 return RISCVISD::VMXOR_VL;
7168 return RISCVISD::XOR_VL;
7171 return RISCVISD::VZEXT_VL;
7173 return RISCVISD::VSEXT_VL;
7175 return RISCVISD::SETCC_VL;
7177 return RISCVISD::VMERGE_VL;
7178 case ISD::VP_SELECT:
7180 return RISCVISD::VMERGE_VL;
7182 return RISCVISD::SRA_VL;
7184 return RISCVISD::SRL_VL;
7186 return RISCVISD::FSQRT_VL;
7187 case ISD::VP_SIGN_EXTEND:
7188 return RISCVISD::VSEXT_VL;
7189 case ISD::VP_ZERO_EXTEND:
7190 return RISCVISD::VZEXT_VL;
7191 case ISD::VP_FP_TO_SINT:
7192 return RISCVISD::VFCVT_RTZ_X_F_VL;
7193 case ISD::VP_FP_TO_UINT:
7194 return RISCVISD::VFCVT_RTZ_XU_F_VL;
7196 case ISD::FMINIMUMNUM:
7197 case ISD::VP_FMINNUM:
7198 return RISCVISD::VFMIN_VL;
7200 case ISD::FMAXIMUMNUM:
7201 case ISD::VP_FMAXNUM:
7202 return RISCVISD::VFMAX_VL;
7206 case ISD::VP_LLRINT:
7207 return RISCVISD::VFCVT_RM_X_F_VL;
7216 return (
Op.getValueType() == MVT::nxv32f16 &&
7219 Op.getValueType() == MVT::nxv32bf16;
7229 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7230 if (!
Op.getOperand(j).getValueType().isVector()) {
7231 LoOperands[j] =
Op.getOperand(j);
7232 HiOperands[j] =
Op.getOperand(j);
7235 std::tie(LoOperands[j], HiOperands[j]) =
7240 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
7242 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
7255 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7257 std::tie(LoOperands[j], HiOperands[j]) =
7261 if (!
Op.getOperand(j).getValueType().isVector()) {
7262 LoOperands[j] =
Op.getOperand(j);
7263 HiOperands[j] =
Op.getOperand(j);
7266 std::tie(LoOperands[j], HiOperands[j]) =
7271 DAG.
getNode(
Op.getOpcode(),
DL, LoVT, LoOperands,
Op->getFlags());
7273 DAG.
getNode(
Op.getOpcode(),
DL, HiVT, HiOperands,
Op->getFlags());
7283 auto [EVLLo, EVLHi] =
7284 DAG.
SplitEVL(
Op.getOperand(3),
Op.getOperand(1).getValueType(),
DL);
7288 {Op.getOperand(0), Lo, MaskLo, EVLLo},
Op->getFlags());
7290 {ResLo, Hi, MaskHi, EVLHi},
Op->getFlags());
7307 for (
unsigned j = 0; j !=
Op.getNumOperands(); ++j) {
7308 if (!
Op.getOperand(j).getValueType().isVector()) {
7309 LoOperands[j] =
Op.getOperand(j);
7310 HiOperands[j] =
Op.getOperand(j);
7313 std::tie(LoOperands[j], HiOperands[j]) =
7318 DAG.
getNode(
Op.getOpcode(),
DL, LoVTs, LoOperands,
Op->getFlags());
7321 DAG.
getNode(
Op.getOpcode(),
DL, HiVTs, HiOperands,
Op->getFlags());
7329RISCVTargetLowering::lowerXAndesBfHCvtBFloat16Load(
SDValue Op,
7331 assert(Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh() &&
7332 "Unexpected bfloat16 load lowering");
7336 EVT MemVT =
LD->getMemoryVT();
7341 LD->getMemOperand());
7349 DAG.
getNode(RISCVISD::NDS_FMV_BF16_X,
DL, MVT::bf16, OrSixteenOne);
7354RISCVTargetLowering::lowerXAndesBfHCvtBFloat16Store(
SDValue Op,
7356 assert(Subtarget.hasVendorXAndesBFHCvt() && !Subtarget.hasStdExtZfh() &&
7357 "Unexpected bfloat16 store lowering");
7362 Subtarget.getXLenVT(),
ST->getValue());
7364 ST->getChain(),
DL, FMV,
ST->getBasePtr(),
7366 ST->getMemOperand());
7371 switch (
Op.getOpcode()) {
7374 "Unimplemented RISCVTargetLowering::LowerOperation Case");
7377 case ISD::ATOMIC_FENCE:
7380 return lowerGlobalAddress(
Op, DAG);
7382 return lowerBlockAddress(
Op, DAG);
7384 return lowerConstantPool(
Op, DAG);
7386 return lowerJumpTable(
Op, DAG);
7388 return lowerGlobalTLSAddress(
Op, DAG);
7392 return lowerConstantFP(
Op, DAG);
7394 return lowerSELECT(
Op, DAG);
7396 return lowerBRCOND(
Op, DAG);
7398 return lowerVASTART(
Op, DAG);
7400 return lowerFRAMEADDR(
Op, DAG);
7402 return lowerRETURNADDR(
Op, DAG);
7404 return lowerShiftLeftParts(
Op, DAG);
7406 return lowerShiftRightParts(
Op, DAG,
true);
7408 return lowerShiftRightParts(
Op, DAG,
false);
7411 if (
Op.getValueType().isFixedLengthVector()) {
7412 assert(Subtarget.hasStdExtZvkb());
7413 return lowerToScalableOp(
Op, DAG);
7415 assert(Subtarget.hasVendorXTHeadBb() &&
7416 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()) &&
7417 "Unexpected custom legalization");
7422 case ISD::BITCAST: {
7424 EVT VT =
Op.getValueType();
7427 MVT XLenVT = Subtarget.getXLenVT();
7428 if (Op0VT == MVT::i16 &&
7429 ((VT == MVT::f16 && Subtarget.hasStdExtZfhminOrZhinxmin()) ||
7430 (VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
7432 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, VT, NewOp0);
7434 if (VT == MVT::f32 && Op0VT == MVT::i32 && Subtarget.is64Bit() &&
7435 Subtarget.hasStdExtFOrZfinx()) {
7437 return DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, NewOp0);
7439 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit() &&
7440 Subtarget.hasStdExtDOrZdinx()) {
7443 return DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64,
Lo,
Hi);
7455 "Unexpected types");
7487 return LowerINTRINSIC_WO_CHAIN(
Op, DAG);
7489 return LowerINTRINSIC_W_CHAIN(
Op, DAG);
7491 return LowerINTRINSIC_VOID(
Op, DAG);
7493 return LowerIS_FPCLASS(
Op, DAG);
7495 MVT VT =
Op.getSimpleValueType();
7497 assert(Subtarget.hasStdExtZvbb());
7498 return lowerToScalableOp(
Op, DAG);
7501 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected custom legalization");
7505 return DAG.
getNode(RISCVISD::BREV8,
DL, VT, BSwap);
7511 if (!
Op.getSimpleValueType().isVector())
7513 return lowerVectorTruncLike(
Op, DAG);
7516 if (
Op.getOperand(0).getValueType().isVector() &&
7517 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7518 return lowerVectorMaskExt(
Op, DAG, 1);
7519 if (
Op.getValueType().isScalableVector())
7521 return lowerToScalableOp(
Op, DAG);
7523 if (
Op.getOperand(0).getValueType().isVector() &&
7524 Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7525 return lowerVectorMaskExt(
Op, DAG, -1);
7526 if (
Op.getValueType().isScalableVector())
7528 return lowerToScalableOp(
Op, DAG);
7530 return lowerSPLAT_VECTOR_PARTS(
Op, DAG);
7532 return lowerINSERT_VECTOR_ELT(
Op, DAG);
7534 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
7536 MVT VT =
Op.getSimpleValueType();
7544 MVT ContainerVT = VT;
7551 V = DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL, ContainerVT,
7552 DAG.
getUNDEF(ContainerVT), Scalar, VL);
7555 V = DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, ContainerVT,
7556 DAG.
getUNDEF(ContainerVT), Scalar, VL);
7563 MVT XLenVT = Subtarget.getXLenVT();
7564 MVT VT =
Op.getSimpleValueType();
7583 }
else if (
Log2 > 3) {
7587 }
else if ((Val % 8) == 0) {
7605 if (
Op.getValueType() == MVT::f16 && Subtarget.is64Bit() &&
7606 Op.getOperand(1).getValueType() == MVT::i32) {
7610 DAG.
getNode(ISD::FPOWI,
DL, MVT::f32, Op0,
Op.getOperand(1));
7621 case ISD::FP_EXTEND:
7623 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
7626 return lowerStrictFPExtendOrRoundLike(
Op, DAG);
7629 if (
Op.getValueType().isVector() &&
7630 ((
Op.getValueType().getScalarType() == MVT::f16 &&
7631 (Subtarget.hasVInstructionsF16Minimal() &&
7632 !Subtarget.hasVInstructionsF16())) ||
7633 Op.getValueType().getScalarType() == MVT::bf16)) {
7649 Op1.getValueType().isVector() &&
7650 ((Op1.getValueType().getScalarType() == MVT::f16 &&
7651 (Subtarget.hasVInstructionsF16Minimal() &&
7652 !Subtarget.hasVInstructionsF16())) ||
7653 Op1.getValueType().getScalarType() == MVT::bf16)) {
7659 Op1.getValueType().getVectorElementCount());
7662 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), WidenVec);
7672 MVT VT =
Op.getSimpleValueType();
7675 bool IsStrict =
Op->isStrictFPOpcode();
7676 SDValue Src =
Op.getOperand(0 + IsStrict);
7677 MVT SrcVT = Src.getSimpleValueType();
7688 "Unexpected vector element types");
7692 if (EltSize > (2 * SrcEltSize)) {
7704 Op.getOperand(0), Ext);
7708 assert(SrcEltVT == MVT::f16 &&
"Unexpected FP_TO_[US]INT lowering");
7713 auto [FExt, Chain] =
7715 return DAG.
getNode(
Op.getOpcode(),
DL,
Op->getVTList(), Chain, FExt);
7722 if (SrcEltSize > (2 * EltSize)) {
7725 assert(EltVT == MVT::f16 &&
"Unexpected [US]_TO_FP lowering");
7730 Op.getOperand(0), Src);
7745 Op.getOperand(0), Src);
7759 unsigned RVVOpc = 0;
7760 switch (
Op.getOpcode()) {
7764 RVVOpc = RISCVISD::VFCVT_RTZ_X_F_VL;
7767 RVVOpc = RISCVISD::VFCVT_RTZ_XU_F_VL;
7770 RVVOpc = RISCVISD::SINT_TO_FP_VL;
7773 RVVOpc = RISCVISD::UINT_TO_FP_VL;
7776 RVVOpc = RISCVISD::STRICT_VFCVT_RTZ_X_F_VL;
7779 RVVOpc = RISCVISD::STRICT_VFCVT_RTZ_XU_F_VL;
7782 RVVOpc = RISCVISD::STRICT_SINT_TO_FP_VL;
7785 RVVOpc = RISCVISD::STRICT_UINT_TO_FP_VL;
7792 "Expected same element count");
7799 Op.getOperand(0), Src, Mask, VL);
7803 Src = DAG.
getNode(RVVOpc,
DL, ContainerVT, Src, Mask, VL);
7809 case ISD::FP_TO_BF16: {
7812 assert(!Subtarget.isSoftFPABI() &&
"Unexpected custom legalization");
7818 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
7819 if (Subtarget.is64Bit())
7820 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Res);
7823 case ISD::BF16_TO_FP: {
7824 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalization");
7825 MVT VT =
Op.getSimpleValueType();
7830 SDValue Res = Subtarget.is64Bit()
7831 ? DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32,
Op)
7835 return DAG.
getNode(ISD::FP_EXTEND,
DL, VT, Res);
7838 case ISD::STRICT_FP_TO_FP16:
7839 case ISD::FP_TO_FP16: {
7842 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalisation");
7845 bool IsStrict =
Op->isStrictFPOpcode();
7846 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7850 std::tie(Res, Chain) =
7851 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
7852 if (Subtarget.is64Bit())
7853 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Res);
7859 case ISD::STRICT_FP16_TO_FP:
7860 case ISD::FP16_TO_FP: {
7863 assert(Subtarget.hasStdExtFOrZfinx() &&
"Unexpected custom legalisation");
7866 bool IsStrict =
Op->isStrictFPOpcode();
7867 SDValue Op0 = IsStrict ?
Op.getOperand(1) :
Op.getOperand(0);
7869 SDValue Arg = Subtarget.is64Bit()
7870 ? DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, Op0)
7873 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
7874 CallOptions,
DL, Chain);
7882 case ISD::FNEARBYINT:
7885 case ISD::FROUNDEVEN:
7892 case ISD::LLROUND: {
7893 if (
Op.getValueType().isVector())
7895 assert(
Op.getOperand(0).getValueType() == MVT::f16 &&
7896 "Unexpected custom legalisation");
7899 return DAG.
getNode(
Op.getOpcode(),
DL,
Op.getValueType(), Ext);
7905 assert(
Op.getOperand(1).getValueType() == MVT::f16 &&
7906 "Unexpected custom legalisation");
7909 {
Op.getOperand(0),
Op.getOperand(1)});
7910 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
7911 {Ext.getValue(1), Ext.getValue(0)});
7913 case ISD::VECREDUCE_ADD:
7914 case ISD::VECREDUCE_UMAX:
7915 case ISD::VECREDUCE_SMAX:
7916 case ISD::VECREDUCE_UMIN:
7917 case ISD::VECREDUCE_SMIN:
7918 return lowerVECREDUCE(
Op, DAG);
7919 case ISD::VECREDUCE_AND:
7920 case ISD::VECREDUCE_OR:
7921 case ISD::VECREDUCE_XOR:
7922 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i1)
7923 return lowerVectorMaskVecReduction(
Op, DAG,
false);
7924 return lowerVECREDUCE(
Op, DAG);
7925 case ISD::VECREDUCE_FADD:
7926 case ISD::VECREDUCE_SEQ_FADD:
7927 case ISD::VECREDUCE_FMIN:
7928 case ISD::VECREDUCE_FMAX:
7929 case ISD::VECREDUCE_FMAXIMUM:
7930 case ISD::VECREDUCE_FMINIMUM:
7931 return lowerFPVECREDUCE(
Op, DAG);
7932 case ISD::VP_REDUCE_ADD:
7933 case ISD::VP_REDUCE_UMAX:
7934 case ISD::VP_REDUCE_SMAX:
7935 case ISD::VP_REDUCE_UMIN:
7936 case ISD::VP_REDUCE_SMIN:
7937 case ISD::VP_REDUCE_FADD:
7938 case ISD::VP_REDUCE_SEQ_FADD:
7939 case ISD::VP_REDUCE_FMIN:
7940 case ISD::VP_REDUCE_FMAX:
7941 case ISD::VP_REDUCE_FMINIMUM:
7942 case ISD::VP_REDUCE_FMAXIMUM:
7945 return lowerVPREDUCE(
Op, DAG);
7946 case ISD::VP_REDUCE_AND:
7947 case ISD::VP_REDUCE_OR:
7948 case ISD::VP_REDUCE_XOR:
7949 if (
Op.getOperand(1).getValueType().getVectorElementType() == MVT::i1)
7950 return lowerVectorMaskVecReduction(
Op, DAG,
true);
7951 return lowerVPREDUCE(
Op, DAG);
7952 case ISD::VP_CTTZ_ELTS:
7953 case ISD::VP_CTTZ_ELTS_ZERO_UNDEF:
7954 return lowerVPCttzElements(
Op, DAG);
7958 DAG.
getUNDEF(ContainerVT), DAG, Subtarget);
7961 return lowerINSERT_SUBVECTOR(
Op, DAG);
7963 return lowerEXTRACT_SUBVECTOR(
Op, DAG);
7965 return lowerVECTOR_DEINTERLEAVE(
Op, DAG);
7967 return lowerVECTOR_INTERLEAVE(
Op, DAG);
7969 return lowerSTEP_VECTOR(
Op, DAG);
7971 return lowerVECTOR_REVERSE(
Op, DAG);
7973 return lowerVECTOR_SPLICE(
Op, DAG);
7975 MVT VT =
Op.getSimpleValueType();
7977 if (!Subtarget.is64Bit() && EltVT == MVT::i64)
7982 MVT VT =
Op.getSimpleValueType();
7984 if ((EltVT == MVT::f16 && !Subtarget.hasStdExtZvfh()) ||
7985 EltVT == MVT::bf16) {
7988 if ((EltVT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()) ||
7989 (EltVT == MVT::f16 && Subtarget.hasStdExtZfhmin()))
7990 Elt = DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, Subtarget.getXLenVT(),
7993 Elt = DAG.
getNode(ISD::BITCAST,
DL, MVT::i16,
Op.getOperand(0));
7995 return DAG.
getNode(ISD::BITCAST,
DL, VT,
7999 if (EltVT == MVT::i1)
8000 return lowerVectorMaskSplat(
Op, DAG);
8009 MVT VT =
Op.getSimpleValueType();
8010 MVT ContainerVT = VT;
8022 if (
Op.getNumOperands() > 2 &&
8026 size_t HalfNumOps =
Op.getNumOperands() / 2;
8028 Op->ops().take_front(HalfNumOps));
8030 Op->ops().drop_front(HalfNumOps));
8034 unsigned NumOpElts =
8035 Op.getOperand(0).getSimpleValueType().getVectorMinNumElements();
8048 EVT VT = Load->getValueType(0);
8049 if (VT == MVT::f64) {
8050 assert(Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
8051 !Subtarget.is64Bit() &&
"Unexpected custom legalisation");
8055 SDValue BasePtr = Load->getBasePtr();
8056 SDValue Chain = Load->getChain();
8059 DAG.
getLoad(MVT::i32,
DL, Chain, BasePtr, Load->getPointerInfo(),
8060 Load->getBaseAlign(), Load->getMemOperand()->getFlags());
8063 MVT::i32,
DL, Chain, BasePtr, Load->getPointerInfo().getWithOffset(4),
8064 Load->getBaseAlign(), Load->getMemOperand()->getFlags());
8072 if (VT == MVT::bf16)
8073 return lowerXAndesBfHCvtBFloat16Load(
Op, DAG);
8078 MVT XLenVT = Subtarget.getXLenVT();
8081 unsigned NumElts = Sz / (NF * 8);
8082 int Log2LMUL =
Log2_64(NumElts) - 3;
8085 Flag.setNoUnsignedWrap(
true);
8087 SDValue BasePtr = Load->getBasePtr();
8095 for (
unsigned i = 0; i < NF; ++i) {
8100 Ret = DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VT, Ret, LoadVal,
8108 if (
auto V = expandUnalignedRVVLoad(
Op, DAG))
8110 if (
Op.getValueType().isFixedLengthVector())
8111 return lowerFixedLengthVectorLoadToRVV(
Op, DAG);
8116 SDValue StoredVal = Store->getValue();
8118 if (VT == MVT::f64) {
8119 assert(Subtarget.hasStdExtZdinx() && !Subtarget.hasStdExtZilsd() &&
8120 !Subtarget.is64Bit() &&
"Unexpected custom legalisation");
8124 SDValue BasePtr = Store->getBasePtr();
8125 SDValue Chain = Store->getChain();
8127 DAG.
getVTList(MVT::i32, MVT::i32), StoredVal);
8130 Store->getPointerInfo(), Store->getBaseAlign(),
8131 Store->getMemOperand()->getFlags());
8134 Store->getPointerInfo().getWithOffset(4),
8135 Store->getBaseAlign(),
8136 Store->getMemOperand()->getFlags());
8139 if (VT == MVT::i64) {
8140 assert(Subtarget.hasStdExtZilsd() && !Subtarget.is64Bit() &&
8141 "Unexpected custom legalisation");
8142 if (Store->isTruncatingStore())
8145 if (!Subtarget.enableUnalignedScalarMem() && Store->getAlign() < 8)
8156 {Store->getChain(), Lo, Hi, Store->getBasePtr()}, MVT::i64,
8157 Store->getMemOperand());
8160 if (VT == MVT::bf16)
8161 return lowerXAndesBfHCvtBFloat16Store(
Op, DAG);
8166 MVT XLenVT = Subtarget.getXLenVT();
8169 unsigned NumElts = Sz / (NF * 8);
8170 int Log2LMUL =
Log2_64(NumElts) - 3;
8173 Flag.setNoUnsignedWrap(
true);
8175 SDValue Chain = Store->getChain();
8176 SDValue BasePtr = Store->getBasePtr();
8183 for (
unsigned i = 0; i < NF; ++i) {
8185 DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL,
8188 Ret = DAG.
getStore(Chain,
DL, Extract, BasePtr,
8190 Store->getBaseAlign(),
8191 Store->getMemOperand()->getFlags());
8192 Chain = Ret.getValue(0);
8198 if (
auto V = expandUnalignedRVVStore(
Op, DAG))
8200 if (
Op.getOperand(1).getValueType().isFixedLengthVector())
8201 return lowerFixedLengthVectorStoreToRVV(
Op, DAG);
8206 return lowerMaskedLoad(
Op, DAG);
8207 case ISD::VP_LOAD_FF:
8208 return lowerLoadFF(
Op, DAG);
8211 return lowerMaskedStore(
Op, DAG);
8213 return lowerVectorCompress(
Op, DAG);
8222 EVT VT =
Op.getValueType();
8233 MVT OpVT =
Op.getOperand(0).getSimpleValueType();
8235 MVT VT =
Op.getSimpleValueType();
8240 "Unexpected CondCode");
8273 return DAG.
getSetCC(
DL, VT, RHS, LHS, CCVal);
8279 return lowerToScalableOp(
Op, DAG);
8296 return lowerToScalableOp(
Op, DAG);
8300 if (
Op.getSimpleValueType().isFixedLengthVector())
8301 return lowerToScalableOp(
Op, DAG);
8303 assert(
Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.is64Bit() &&
8304 "Unexpected custom legalisation");
8308 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
8319 case ISD::FMINIMUMNUM:
8320 case ISD::FMAXIMUMNUM:
8336 return lowerToScalableOp(
Op, DAG);
8340 EVT VT =
Op->getValueType(0);
8355 return lowerABS(
Op, DAG);
8360 if (Subtarget.hasStdExtZvbb())
8361 return lowerToScalableOp(
Op, DAG);
8363 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8365 if (
Op.getValueType() == MVT::f16 ||
Op.getValueType() == MVT::bf16)
8369 return lowerToScalableOp(
Op, DAG);
8378 return lowerToScalableOp(
Op, DAG);
8381 return lowerVectorStrictFSetcc(
Op, DAG);
8391 case ISD::VP_GATHER:
8392 return lowerMaskedGather(
Op, DAG);
8394 case ISD::VP_SCATTER:
8395 return lowerMaskedScatter(
Op, DAG);
8397 return lowerGET_ROUNDING(
Op, DAG);
8398 case ISD::SET_ROUNDING:
8399 return lowerSET_ROUNDING(
Op, DAG);
8400 case ISD::GET_FPENV:
8401 return lowerGET_FPENV(
Op, DAG);
8402 case ISD::SET_FPENV:
8403 return lowerSET_FPENV(
Op, DAG);
8404 case ISD::RESET_FPENV:
8405 return lowerRESET_FPENV(
Op, DAG);
8406 case ISD::GET_FPMODE:
8407 return lowerGET_FPMODE(
Op, DAG);
8408 case ISD::SET_FPMODE:
8409 return lowerSET_FPMODE(
Op, DAG);
8410 case ISD::RESET_FPMODE:
8411 return lowerRESET_FPMODE(
Op, DAG);
8413 return lowerEH_DWARF_CFA(
Op, DAG);
8415 if (
Op.getSimpleValueType().getVectorElementType() == MVT::i1)
8416 return lowerVPMergeMask(
Op, DAG);
8418 case ISD::VP_SELECT:
8426 case ISD::VP_UADDSAT:
8427 case ISD::VP_USUBSAT:
8428 case ISD::VP_SADDSAT:
8429 case ISD::VP_SSUBSAT:
8431 case ISD::VP_LLRINT:
8432 return lowerVPOp(
Op, DAG);
8436 return lowerLogicVPOp(
Op, DAG);
8445 case ISD::VP_FMINNUM:
8446 case ISD::VP_FMAXNUM:
8447 case ISD::VP_FCOPYSIGN:
8454 return lowerVPOp(
Op, DAG);
8455 case ISD::VP_IS_FPCLASS:
8456 return LowerIS_FPCLASS(
Op, DAG);
8457 case ISD::VP_SIGN_EXTEND:
8458 case ISD::VP_ZERO_EXTEND:
8459 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
8460 return lowerVPExtMaskOp(
Op, DAG);
8461 return lowerVPOp(
Op, DAG);
8462 case ISD::VP_TRUNCATE:
8463 return lowerVectorTruncLike(
Op, DAG);
8464 case ISD::VP_FP_EXTEND:
8465 case ISD::VP_FP_ROUND:
8466 return lowerVectorFPExtendOrRoundLike(
Op, DAG);
8467 case ISD::VP_SINT_TO_FP:
8468 case ISD::VP_UINT_TO_FP:
8469 if (
Op.getValueType().isVector() &&
8470 ((
Op.getValueType().getScalarType() == MVT::f16 &&
8471 (Subtarget.hasVInstructionsF16Minimal() &&
8472 !Subtarget.hasVInstructionsF16())) ||
8473 Op.getValueType().getScalarType() == MVT::bf16)) {
8486 case ISD::VP_FP_TO_SINT:
8487 case ISD::VP_FP_TO_UINT:
8489 Op1.getValueType().isVector() &&
8490 ((Op1.getValueType().getScalarType() == MVT::f16 &&
8491 (Subtarget.hasVInstructionsF16Minimal() &&
8492 !Subtarget.hasVInstructionsF16())) ||
8493 Op1.getValueType().getScalarType() == MVT::bf16)) {
8499 Op1.getValueType().getVectorElementCount());
8503 {WidenVec, Op.getOperand(1), Op.getOperand(2)});
8505 return lowerVPFPIntConvOp(
Op, DAG);
8509 if (
Op.getOperand(0).getSimpleValueType().getVectorElementType() == MVT::i1)
8510 return lowerVPSetCCMaskOp(
Op, DAG);
8516 case ISD::VP_BITREVERSE:
8518 return lowerVPOp(
Op, DAG);
8520 case ISD::VP_CTLZ_ZERO_UNDEF:
8521 if (Subtarget.hasStdExtZvbb())
8522 return lowerVPOp(
Op, DAG);
8523 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8525 case ISD::VP_CTTZ_ZERO_UNDEF:
8526 if (Subtarget.hasStdExtZvbb())
8527 return lowerVPOp(
Op, DAG);
8528 return lowerCTLZ_CTTZ_ZERO_UNDEF(
Op, DAG);
8530 return lowerVPOp(
Op, DAG);
8531 case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
8532 return lowerVPStridedLoad(
Op, DAG);
8533 case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
8534 return lowerVPStridedStore(
Op, DAG);
8536 case ISD::VP_FFLOOR:
8538 case ISD::VP_FNEARBYINT:
8539 case ISD::VP_FROUND:
8540 case ISD::VP_FROUNDEVEN:
8541 case ISD::VP_FROUNDTOZERO:
8545 case ISD::VP_FMAXIMUM:
8546 case ISD::VP_FMINIMUM:
8550 case ISD::EXPERIMENTAL_VP_SPLICE:
8551 return lowerVPSpliceExperimental(
Op, DAG);
8552 case ISD::EXPERIMENTAL_VP_REVERSE:
8553 return lowerVPReverseExperimental(
Op, DAG);
8554 case ISD::EXPERIMENTAL_VP_SPLAT:
8555 return lowerVPSplatExperimental(
Op, DAG);
8558 "llvm.clear_cache only needs custom lower on Linux targets");
8561 return emitFlushICache(DAG,
Op.getOperand(0),
Op.getOperand(1),
8562 Op.getOperand(2), Flags,
DL);
8564 case ISD::DYNAMIC_STACKALLOC:
8565 return lowerDYNAMIC_STACKALLOC(
Op, DAG);
8566 case ISD::INIT_TRAMPOLINE:
8567 return lowerINIT_TRAMPOLINE(
Op, DAG);
8568 case ISD::ADJUST_TRAMPOLINE:
8569 return lowerADJUST_TRAMPOLINE(
Op, DAG);
8570 case ISD::PARTIAL_REDUCE_UMLA:
8571 case ISD::PARTIAL_REDUCE_SMLA:
8572 case ISD::PARTIAL_REDUCE_SUMLA:
8573 return lowerPARTIAL_REDUCE_MLA(
Op, DAG);
8580 MakeLibCallOptions CallOptions;
8581 std::pair<SDValue, SDValue> CallResult =
8582 makeLibCall(DAG, RTLIB::RISCV_FLUSH_ICACHE, MVT::isVoid,
8583 {Start, End, Flags}, CallOptions,
DL, InChain);
8586 return CallResult.second;
8591 if (!Subtarget.is64Bit())
8599 std::unique_ptr<MCCodeEmitter> CodeEmitter(
8627 const bool HasCFBranch =
8628 Subtarget.hasStdExtZicfilp() &&
8630 "cf-protection-branch");
8631 const unsigned StaticChainIdx = HasCFBranch ? 5 : 4;
8632 const unsigned StaticChainOffset = StaticChainIdx * 4;
8633 const unsigned FunctionAddressOffset = StaticChainOffset + 8;
8637 auto GetEncoding = [&](
const MCInst &MC) {
8640 CodeEmitter->encodeInstruction(MC, CB, Fixups, *STI);
8647 SmallVector<uint32_t> Encodings;
8652 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X7).addImm(0)),
8656 GetEncoding(MCInstBuilder(RISCV::LD)
8659 .addImm(FunctionAddressOffset)),
8662 GetEncoding(MCInstBuilder(RISCV::LD)
8665 .addImm(StaticChainOffset)),
8668 GetEncoding(MCInstBuilder(RISCV::JALR)
8676 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X0).addImm(0)),
8679 GetEncoding(MCInstBuilder(RISCV::AUIPC).addReg(RISCV::X28).addImm(0)),
8683 GetEncoding(MCInstBuilder(RISCV::LD)
8686 .addImm(FunctionAddressOffset - 4)),
8689 GetEncoding(MCInstBuilder(RISCV::LD)
8692 .addImm(StaticChainOffset - 4)),
8695 GetEncoding(MCInstBuilder(RISCV::JALR)
8707 Root, dl, DAG.
getConstant(Encoding, dl, MVT::i64), Addr,
8708 MachinePointerInfo(TrmpAddr, Idx * 4), MVT::i32));
8712 SDValue FunctionAddress =
Op.getOperand(2);
8716 struct OffsetValuePair {
8720 } OffsetValues[] = {
8721 {StaticChainOffset, StaticChain},
8722 {FunctionAddressOffset, FunctionAddress},
8724 for (
auto &OffsetValue : OffsetValues) {
8727 DAG.
getConstant(OffsetValue.Offset, dl, MVT::i64));
8728 OffsetValue.Addr = Addr;
8730 DAG.
getStore(Root, dl, OffsetValue.Value, Addr,
8731 MachinePointerInfo(TrmpAddr, OffsetValue.Offset)));
8734 assert(OutChains.
size() == StaticChainIdx + 2 &&
8735 "Size of OutChains mismatch");
8740 SDValue EndOfTrmp = OffsetValues[0].Addr;
8751 if (!Subtarget.is64Bit())
8754 return Op.getOperand(0);
8763 MVT VT =
Op.getSimpleValueType();
8769 MVT ArgVT =
A.getSimpleValueType();
8770 assert(ArgVT ==
B.getSimpleValueType() &&
8780 MVT ContainerVT = VT;
8789 switch (
Op.getOpcode()) {
8790 case ISD::PARTIAL_REDUCE_SMLA:
8791 Opc = RISCVISD::VQDOT_VL;
8793 case ISD::PARTIAL_REDUCE_UMLA:
8794 Opc = RISCVISD::VQDOTU_VL;
8796 case ISD::PARTIAL_REDUCE_SUMLA:
8797 Opc = RISCVISD::VQDOTSU_VL;
8823 N->getOffset(), Flags);
8852template <
class NodeTy>
8854 bool IsLocal,
bool IsExternWeak)
const {
8864 if (IsLocal && !Subtarget.allowTaggedGlobals())
8868 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
8891 if (Subtarget.hasVendorXqcili()) {
8895 return DAG.
getNode(RISCVISD::QC_E_LI,
DL, Ty, Addr);
8902 return DAG.
getNode(RISCVISD::ADD_LO,
DL, Ty, MNHi, AddrLo);
8926 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
8934 return DAG.
getNode(RISCVISD::LLA,
DL, Ty, Addr);
8942 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
8943 const GlobalValue *GV =
N->getGlobal();
8951 return getAddr(
N, DAG);
8958 return getAddr(
N, DAG);
8965 return getAddr(
N, DAG);
8970 bool UseGOT)
const {
8973 const GlobalValue *GV =
N->getGlobal();
8974 MVT XLenVT = Subtarget.getXLenVT();
9011 DAG.
getNode(RISCVISD::ADD_TPREL,
DL, Ty, MNHi, TPReg, AddrAdd);
9012 return DAG.
getNode(RISCVISD::ADD_LO,
DL, Ty, MNAdd, AddrLo);
9020 const GlobalValue *GV =
N->getGlobal();
9031 Args.emplace_back(Load, CallTy);
9034 TargetLowering::CallLoweringInfo CLI(DAG);
9048 const GlobalValue *GV =
N->getGlobal();
9064 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
9078 Addr = getStaticTLSAddr(
N, DAG,
false);
9081 Addr = getStaticTLSAddr(
N, DAG,
true);
9086 : getDynamicTLSAddr(
N, DAG);
9103 if (
LHS == LHS2 &&
RHS == RHS2) {
9108 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
9116 return std::nullopt;
9128 MVT VT =
N->getSimpleValueType(0);
9163 if (~TrueVal == FalseVal) {
9203 if (Subtarget.hasShortForwardBranchOpt())
9206 unsigned SelOpNo = 0;
9216 unsigned ConstSelOpNo = 1;
9217 unsigned OtherSelOpNo = 2;
9224 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
9229 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
9235 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
9237 std::swap(NewConstOps[0], NewConstOps[1]);
9249 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
9251 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
9254 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
9255 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
9264 MVT VT =
Op.getSimpleValueType();
9265 MVT XLenVT = Subtarget.getXLenVT();
9286 return DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV);
9289 return DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV);
9293 auto getNotOperand = [](
const SDValue &
Op) -> std::optional<const SDValue> {
9294 using namespace llvm::SDPatternMatch;
9299 return std::nullopt;
9305 auto NotOperand = (TrueV.
getOperand(0) == FalseV)
9307 : getNotOperand(TrueV.getOperand(0));
9310 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, *NotOperand, CondV);
9316 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV));
9323 auto NotOperand = (FalseV.
getOperand(0) == TrueV)
9325 : getNotOperand(FalseV.getOperand(0));
9328 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, *NotOperand, CondV);
9334 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV));
9351 int64_t TrueImm =
TrueVal.getSExtValue();
9352 int64_t FalseImm =
FalseVal.getSExtValue();
9371 if ((TrueVal - FalseVal).isPowerOf2() &&
FalseVal.isSignedIntN(12)) {
9376 if ((FalseVal - TrueVal).isPowerOf2() &&
TrueVal.isSignedIntN(12)) {
9383 auto getCost = [&](
const APInt &Delta,
const APInt &Addend) {
9385 Delta, Subtarget.getXLen(), Subtarget,
true);
9387 if (Addend.isSignedIntN(12))
9390 Addend, Subtarget.getXLen(), Subtarget,
true);
9391 return AddendCost + DeltaCost;
9393 bool IsCZERO_NEZ =
getCost(FalseVal - TrueVal, TrueVal) <=
9394 getCost(TrueVal - FalseVal, FalseVal);
9396 IsCZERO_NEZ ? FalseVal - TrueVal : TrueVal - FalseVal,
DL, VT);
9398 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9399 DL, VT, LHSVal, CondV);
9407 SDValue ConstVal = IsCZERO_NEZ ? TrueV : FalseV;
9408 SDValue RegV = IsCZERO_NEZ ? FalseV : TrueV;
9411 if (RawConstVal == -0x800) {
9414 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9415 DL, VT, XorOp, CondV);
9423 DAG.
getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
9424 DL, VT, SubOp, CondV);
9431 if (!Subtarget.hasConditionalMoveFusion())
9434 DAG.
getNode(RISCVISD::CZERO_EQZ,
DL, VT, TrueV, CondV),
9435 DAG.
getNode(RISCVISD::CZERO_NEZ,
DL, VT, FalseV, CondV),
9439 if (
Op.hasOneUse()) {
9440 unsigned UseOpc =
Op->user_begin()->getOpcode();
9442 SDNode *BinOp = *
Op->user_begin();
9449 return lowerSELECT(NewSel, DAG);
9503 if (TrueVal - 1 == FalseVal)
9505 if (TrueVal + 1 == FalseVal)
9512 RHS == TrueV &&
LHS == FalseV) {
9543 MVT XLenVT = Subtarget.getXLenVT();
9554 return DAG.
getNode(RISCVISD::BR_CC,
DL,
Op.getValueType(),
Op.getOperand(0),
9555 LHS,
RHS, TargetCC,
Op.getOperand(2));
9558 return DAG.
getNode(RISCVISD::BR_CC,
DL,
Op.getValueType(),
Op.getOperand(0),
9565 RISCVMachineFunctionInfo *FuncInfo = MF.
getInfo<RISCVMachineFunctionInfo>();
9575 MachinePointerInfo(SV));
9580 const RISCVRegisterInfo &RI = *Subtarget.getRegisterInfo();
9585 int XLenInBytes = Subtarget.getXLen() / 8;
9587 EVT VT =
Op.getValueType();
9590 unsigned Depth =
Op.getConstantOperandVal(0);
9592 int Offset = -(XLenInBytes * 2);
9604 const RISCVRegisterInfo &RI = *Subtarget.getRegisterInfo();
9608 MVT XLenVT = Subtarget.getXLenVT();
9609 int XLenInBytes = Subtarget.getXLen() / 8;
9611 EVT VT =
Op.getValueType();
9613 unsigned Depth =
Op.getConstantOperandVal(0);
9615 int Off = -XLenInBytes;
9616 SDValue FrameAddr = lowerFRAMEADDR(
Op, DAG);
9620 MachinePointerInfo());
9635 EVT VT =
Lo.getValueType();
9674 EVT VT =
Lo.getValueType();
9725 MVT VT =
Op.getSimpleValueType();
9730 return DAG.
getNode(RISCVISD::VMSET_VL,
DL, VT, VL);
9734 return DAG.
getNode(RISCVISD::VMCLR_VL,
DL, VT, VL);
9751 MVT VecVT =
Op.getSimpleValueType();
9753 "Unexpected SPLAT_VECTOR_PARTS lowering");
9759 MVT ContainerVT = VecVT;
9779 int64_t ExtTrueVal)
const {
9781 MVT VecVT =
Op.getSimpleValueType();
9784 assert(Src.getValueType().isVector() &&
9785 Src.getValueType().getVectorElementType() == MVT::i1);
9805 MVT XLenVT = Subtarget.getXLenVT();
9811 if (
Xor.getOpcode() == RISCVISD::VMXOR_VL) {
9823 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9824 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
9825 SplatTrueVal = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9826 DAG.
getUNDEF(ContainerVT), SplatTrueVal, VL);
9828 DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, CC, SplatTrueVal,
9829 SplatZero, DAG.
getUNDEF(ContainerVT), VL);
9839 bool IsVPTrunc =
Op.getOpcode() == ISD::VP_TRUNCATE;
9841 EVT MaskVT =
Op.getValueType();
9844 "Unexpected type for vector mask lowering");
9846 MVT VecVT = Src.getSimpleValueType();
9850 VL =
Op.getOperand(2);
9853 MVT ContainerVT = VecVT;
9859 MVT MaskContainerVT =
9866 std::tie(Mask, VL) =
9873 SplatOne = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9874 DAG.
getUNDEF(ContainerVT), SplatOne, VL);
9875 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, ContainerVT,
9876 DAG.
getUNDEF(ContainerVT), SplatZero, VL);
9879 SDValue Trunc = DAG.
getNode(RISCVISD::AND_VL,
DL, ContainerVT, Src, SplatOne,
9880 DAG.
getUNDEF(ContainerVT), Mask, VL);
9881 Trunc = DAG.
getNode(RISCVISD::SETCC_VL,
DL, MaskContainerVT,
9891 unsigned Opc =
Op.getOpcode();
9892 bool IsVPTrunc =
Opc == ISD::VP_TRUNCATE;
9895 MVT VT =
Op.getSimpleValueType();
9897 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
9901 return lowerVectorMaskTruncLike(
Op, DAG);
9909 MVT SrcVT = Src.getSimpleValueType();
9914 "Unexpected vector truncate lowering");
9916 MVT ContainerVT = SrcVT;
9920 VL =
Op.getOperand(2);
9933 std::tie(Mask, VL) =
9939 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL_SSAT;
9941 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL_USAT;
9943 NewOpc = RISCVISD::TRUNCATE_VECTOR_VL;
9949 }
while (SrcEltVT != DstEltVT);
9958RISCVTargetLowering::lowerStrictFPExtendOrRoundLike(
SDValue Op,
9963 MVT VT =
Op.getSimpleValueType();
9964 MVT SrcVT = Src.getSimpleValueType();
9965 MVT ContainerVT = VT;
9984 ? RISCVISD::STRICT_FP_EXTEND_VL
9985 : RISCVISD::STRICT_VFNCVT_ROD_VL;
9988 Chain, Src, Mask, VL);
9989 Chain = Src.getValue(1);
9993 ? RISCVISD::STRICT_FP_EXTEND_VL
9994 : RISCVISD::STRICT_FP_ROUND_VL;
9996 Chain, Src, Mask, VL);
10007RISCVTargetLowering::lowerVectorFPExtendOrRoundLike(
SDValue Op,
10010 Op.getOpcode() == ISD::VP_FP_ROUND ||
Op.getOpcode() == ISD::VP_FP_EXTEND;
10012 Op.getOpcode() == ISD::VP_FP_EXTEND ||
Op.getOpcode() == ISD::FP_EXTEND;
10017 MVT VT =
Op.getSimpleValueType();
10019 assert(VT.
isVector() &&
"Unexpected type for vector truncate lowering");
10022 MVT SrcVT = Src.getSimpleValueType();
10024 bool IsDirectExtend =
10032 bool IsDirectConv = IsDirectExtend || IsDirectTrunc;
10039 MVT ContainerVT = VT;
10042 Mask =
Op.getOperand(1);
10043 VL =
Op.getOperand(2);
10057 std::tie(Mask, VL) =
10060 unsigned ConvOpc = IsExtend ? RISCVISD::FP_EXTEND_VL : RISCVISD::FP_ROUND_VL;
10062 if (IsDirectConv) {
10063 Src = DAG.
getNode(ConvOpc,
DL, ContainerVT, Src, Mask, VL);
10069 unsigned InterConvOpc =
10070 IsExtend ? RISCVISD::FP_EXTEND_VL : RISCVISD::VFNCVT_ROD_VL;
10074 DAG.
getNode(InterConvOpc,
DL, InterVT, Src, Mask, VL);
10076 DAG.
getNode(ConvOpc,
DL, ContainerVT, IntermediateConv, Mask, VL);
10087static std::optional<MVT>
10093 const unsigned MinVLMAX = VectorBitsMin / EltSize;
10095 if (MaxIdx < MinVLMAX)
10097 else if (MaxIdx < MinVLMAX * 2)
10100 else if (MaxIdx < MinVLMAX * 4)
10105 return std::nullopt;
10113 return isUInt<5>(IdxC->getZExtValue());
10125 MVT VecVT =
Op.getSimpleValueType();
10126 MVT XLenVT = Subtarget.getXLenVT();
10141 if ((ValVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
10142 ValVT == MVT::bf16) {
10147 DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, XLenVT, Val), Idx);
10151 MVT ContainerVT = VecVT;
10161 std::optional<unsigned> AlignedIdx;
10163 const unsigned OrigIdx = IdxC->getZExtValue();
10166 DL, DAG, Subtarget)) {
10167 ContainerVT = *ShrunkVT;
10175 if (
auto VLEN = Subtarget.getRealVLen(); VLEN && ContainerVT.
bitsGT(M1VT)) {
10178 unsigned RemIdx = OrigIdx % ElemsPerVReg;
10179 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
10182 ContainerVT = M1VT;
10189 bool IsLegalInsert = Subtarget.is64Bit() || Val.
getValueType() != MVT::i64;
10197 IsLegalInsert =
true;
10206 if (IsLegalInsert) {
10208 VecVT.
isFloatingPoint() ? RISCVISD::VFMV_S_F_VL : RISCVISD::VMV_S_X_VL;
10212 Vec = DAG.
getNode(
Opc,
DL, ContainerVT, Vec, Val, VL);
10222 if (Subtarget.hasVendorXRivosVisni() && VecVT.
isInteger() &&
10227 Vec = DAG.
getNode(RISCVISD::RI_VINSERT_VL,
DL, ContainerVT, Vec, Val, Idx,
10243 std::tie(ValLo, ValHi) = DAG.
SplitScalar(Val,
DL, MVT::i32, MVT::i32);
10244 MVT I32ContainerVT =
10254 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10255 Vec, Vec, ValLo, I32Mask, InsertI64VL);
10259 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10260 Tail, ValInVec, ValHi, I32Mask, InsertI64VL);
10262 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
10273 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10275 DAG.
getUNDEF(I32ContainerVT), ValLo,
10276 I32Mask, InsertI64VL);
10277 ValInVec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32ContainerVT,
10278 DAG.
getUNDEF(I32ContainerVT), ValInVec, ValHi,
10279 I32Mask, InsertI64VL);
10281 ValInVec = DAG.
getBitcast(ContainerVT, ValInVec);
10294 Idx, Mask, InsertVL, Policy);
10312 EVT EltVT =
Op.getValueType();
10314 MVT XLenVT = Subtarget.getXLenVT();
10319 MVT ContainerVT = VecVT;
10326 DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Vec, Mask, VL);
10333 if (NumElts >= 8) {
10335 unsigned WidenVecLen;
10338 unsigned MaxEEW = Subtarget.getELen();
10343 "the number of elements should be power of 2");
10347 ExtractBitIdx = Idx;
10349 WideEltVT = LargestEltVT;
10352 ExtractElementIdx = DAG.
getNode(
10361 Vec = DAG.
getNode(ISD::BITCAST,
DL, WideVT, Vec);
10363 Vec, ExtractElementIdx);
10378 if ((EltVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
10379 EltVT == MVT::bf16) {
10385 return DAG.
getNode(RISCVISD::FMV_H_X,
DL, EltVT, IntExtract);
10389 MVT ContainerVT = VecVT;
10399 const auto VLen = Subtarget.getRealVLen();
10401 IdxC && VLen && VecVT.
getSizeInBits().getKnownMinValue() > *VLen) {
10403 unsigned OrigIdx = IdxC->getZExtValue();
10406 unsigned RemIdx = OrigIdx % ElemsPerVReg;
10407 unsigned SubRegIdx = OrigIdx / ElemsPerVReg;
10408 unsigned ExtractIdx =
10412 ContainerVT = M1VT;
10417 std::optional<uint64_t> MaxIdx;
10421 MaxIdx = IdxC->getZExtValue();
10423 if (
auto SmallerVT =
10425 ContainerVT = *SmallerVT;
10432 if (Subtarget.hasVendorXRivosVisni() && EltVT.
isInteger() &&
10460 DAG.
getUNDEF(ContainerVT), Vec, Idx, Mask, VL);
10479 "Unexpected opcode");
10486 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
10491 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
10492 if (!
II || !
II->hasScalarOperand())
10495 unsigned SplatOp =
II->ScalarOperand + 1 + HasChain;
10496 assert(SplatOp <
Op.getNumOperands());
10508 if (OpVT.
bitsLT(XLenVT)) {
10515 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
10525 assert(
II->ScalarOperand > 0 &&
"Unexpected splat operand!");
10526 MVT VT =
Op.getOperand(SplatOp - 1).getSimpleValueType();
10529 assert(XLenVT == MVT::i32 && OpVT == MVT::i64 &&
10540 case Intrinsic::riscv_vslide1up:
10541 case Intrinsic::riscv_vslide1down:
10542 case Intrinsic::riscv_vslide1up_mask:
10543 case Intrinsic::riscv_vslide1down_mask: {
10545 unsigned NumOps =
Op.getNumOperands();
10546 bool IsMasked =
NumOps == 7;
10552 std::tie(ScalarLo, ScalarHi) =
10561 const auto [MinVLMAX, MaxVLMAX] =
10565 if (AVLInt <= MinVLMAX) {
10567 }
else if (AVLInt >= 2 * MaxVLMAX) {
10601 if (IntNo == Intrinsic::riscv_vslide1up ||
10602 IntNo == Intrinsic::riscv_vslide1up_mask) {
10603 Vec = DAG.
getNode(RISCVISD::VSLIDE1UP_VL,
DL, I32VT, Passthru, Vec,
10604 ScalarHi, I32Mask, I32VL);
10605 Vec = DAG.
getNode(RISCVISD::VSLIDE1UP_VL,
DL, I32VT, Passthru, Vec,
10606 ScalarLo, I32Mask, I32VL);
10608 Vec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32VT, Passthru, Vec,
10609 ScalarLo, I32Mask, I32VL);
10610 Vec = DAG.
getNode(RISCVISD::VSLIDE1DOWN_VL,
DL, I32VT, Passthru, Vec,
10611 ScalarHi, I32Mask, I32VL);
10629 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, Mask, Vec, MaskedOff,
10633 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, Mask, Vec, MaskedOff,
10660 const unsigned ElementWidth = 8;
10665 [[maybe_unused]]
unsigned MinVF =
10668 [[maybe_unused]]
unsigned VF =
N->getConstantOperandVal(2);
10672 bool Fractional = VF < LMul1VF;
10673 unsigned LMulVal = Fractional ? LMul1VF / VF : VF / LMul1VF;
10694 MVT ContainerVT = OpVT;
10702 SDValue Res = DAG.
getNode(RISCVISD::VFIRST_VL,
DL, XLenVT, Op0, Mask, VL);
10710 return DAG.
getSelect(
DL, XLenVT, Setcc, VL, Res);
10721 unsigned IntNo =
Op.getConstantOperandVal(HasChain ? 1 : 0);
10725 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntNo);
10726 if (!
II || !
II->hasScalarOperand())
10729 unsigned SplatOp =
II->ScalarOperand + 1;
10730 assert(SplatOp <
Op.getNumOperands());
10742 if (OpVT.
bitsLT(XLenVT)) {
10745 ScalarOp = DAG.
getNode(ExtOpc,
DL, XLenVT, ScalarOp);
10756 EVT ValType = V.getValueType();
10757 if (ValType.isVector() && ValType.isFloatingPoint()) {
10760 ValType.getVectorElementCount());
10763 if (ValType.isFixedLengthVector()) {
10765 DAG, V.getSimpleValueType(), Subtarget);
10781 unsigned IntNo =
Op.getConstantOperandVal(0);
10783 MVT XLenVT = Subtarget.getXLenVT();
10788 case Intrinsic::riscv_tuple_insert: {
10793 return DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL,
Op.getValueType(), Vec,
10796 case Intrinsic::riscv_tuple_extract: {
10800 return DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL,
Op.getValueType(), Vec,
10803 case Intrinsic::thread_pointer: {
10807 case Intrinsic::riscv_orc_b:
10808 case Intrinsic::riscv_brev8:
10809 case Intrinsic::riscv_sha256sig0:
10810 case Intrinsic::riscv_sha256sig1:
10811 case Intrinsic::riscv_sha256sum0:
10812 case Intrinsic::riscv_sha256sum1:
10813 case Intrinsic::riscv_sm3p0:
10814 case Intrinsic::riscv_sm3p1: {
10817 case Intrinsic::riscv_orc_b:
Opc = RISCVISD::ORC_B;
break;
10818 case Intrinsic::riscv_brev8:
Opc = RISCVISD::BREV8;
break;
10819 case Intrinsic::riscv_sha256sig0:
Opc = RISCVISD::SHA256SIG0;
break;
10820 case Intrinsic::riscv_sha256sig1:
Opc = RISCVISD::SHA256SIG1;
break;
10821 case Intrinsic::riscv_sha256sum0:
Opc = RISCVISD::SHA256SUM0;
break;
10822 case Intrinsic::riscv_sha256sum1:
Opc = RISCVISD::SHA256SUM1;
break;
10823 case Intrinsic::riscv_sm3p0:
Opc = RISCVISD::SM3P0;
break;
10824 case Intrinsic::riscv_sm3p1:
Opc = RISCVISD::SM3P1;
break;
10829 case Intrinsic::riscv_sm4ks:
10830 case Intrinsic::riscv_sm4ed: {
10832 IntNo == Intrinsic::riscv_sm4ks ? RISCVISD::SM4KS : RISCVISD::SM4ED;
10837 case Intrinsic::riscv_zip:
10838 case Intrinsic::riscv_unzip: {
10840 IntNo == Intrinsic::riscv_zip ? RISCVISD::ZIP : RISCVISD::UNZIP;
10843 case Intrinsic::riscv_mopr:
10844 return DAG.
getNode(RISCVISD::MOP_R,
DL, XLenVT,
Op.getOperand(1),
10847 case Intrinsic::riscv_moprr: {
10848 return DAG.
getNode(RISCVISD::MOP_RR,
DL, XLenVT,
Op.getOperand(1),
10849 Op.getOperand(2),
Op.getOperand(3));
10851 case Intrinsic::riscv_clmul:
10852 return DAG.
getNode(RISCVISD::CLMUL,
DL, XLenVT,
Op.getOperand(1),
10854 case Intrinsic::riscv_clmulh:
10855 case Intrinsic::riscv_clmulr: {
10857 IntNo == Intrinsic::riscv_clmulh ? RISCVISD::CLMULH : RISCVISD::CLMULR;
10860 case Intrinsic::experimental_get_vector_length:
10862 case Intrinsic::experimental_cttz_elts:
10864 case Intrinsic::riscv_vmv_x_s: {
10868 case Intrinsic::riscv_vfmv_f_s:
10870 case Intrinsic::riscv_vmv_v_x:
10872 Op.getOperand(3),
Op.getSimpleValueType(),
DL, DAG,
10874 case Intrinsic::riscv_vfmv_v_f:
10875 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL,
Op.getValueType(),
10876 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
10877 case Intrinsic::riscv_vmv_s_x: {
10880 if (
Scalar.getValueType().bitsLE(XLenVT)) {
10882 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL,
Op.getValueType(),
10883 Op.getOperand(1), Scalar,
Op.getOperand(3));
10886 assert(
Scalar.getValueType() == MVT::i64 &&
"Unexpected scalar VT!");
10903 MVT VT =
Op.getSimpleValueType();
10908 if (
Op.getOperand(1).isUndef())
10909 return SplattedVal;
10918 DAG.
getNode(RISCVISD::SETCC_VL,
DL, MaskVT,
10921 return DAG.
getNode(RISCVISD::VMERGE_VL,
DL, VT, SelectCond, SplattedVal,
10924 case Intrinsic::riscv_vfmv_s_f:
10925 return DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL,
Op.getSimpleValueType(),
10926 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
10928 case Intrinsic::riscv_vaesdf_vv:
10929 case Intrinsic::riscv_vaesdf_vs:
10930 case Intrinsic::riscv_vaesdm_vv:
10931 case Intrinsic::riscv_vaesdm_vs:
10932 case Intrinsic::riscv_vaesef_vv:
10933 case Intrinsic::riscv_vaesef_vs:
10934 case Intrinsic::riscv_vaesem_vv:
10935 case Intrinsic::riscv_vaesem_vs:
10936 case Intrinsic::riscv_vaeskf1:
10937 case Intrinsic::riscv_vaeskf2:
10938 case Intrinsic::riscv_vaesz_vs:
10939 case Intrinsic::riscv_vsm4k:
10940 case Intrinsic::riscv_vsm4r_vv:
10941 case Intrinsic::riscv_vsm4r_vs: {
10942 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
10943 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
10944 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
10949 case Intrinsic::riscv_vsm3c:
10950 case Intrinsic::riscv_vsm3me: {
10951 if (!
isValidEGW(8,
Op.getSimpleValueType(), Subtarget) ||
10952 !
isValidEGW(8,
Op->getOperand(1).getSimpleValueType(), Subtarget))
10957 case Intrinsic::riscv_vsha2ch:
10958 case Intrinsic::riscv_vsha2cl:
10959 case Intrinsic::riscv_vsha2ms: {
10960 if (
Op->getSimpleValueType(0).getScalarSizeInBits() == 64 &&
10961 !Subtarget.hasStdExtZvknhb())
10963 if (!
isValidEGW(4,
Op.getSimpleValueType(), Subtarget) ||
10964 !
isValidEGW(4,
Op->getOperand(1).getSimpleValueType(), Subtarget) ||
10965 !
isValidEGW(4,
Op->getOperand(2).getSimpleValueType(), Subtarget))
10969 case Intrinsic::riscv_sf_vc_v_x:
10970 case Intrinsic::riscv_sf_vc_v_i:
10971 case Intrinsic::riscv_sf_vc_v_xv:
10972 case Intrinsic::riscv_sf_vc_v_iv:
10973 case Intrinsic::riscv_sf_vc_v_vv:
10974 case Intrinsic::riscv_sf_vc_v_fv:
10975 case Intrinsic::riscv_sf_vc_v_xvv:
10976 case Intrinsic::riscv_sf_vc_v_ivv:
10977 case Intrinsic::riscv_sf_vc_v_vvv:
10978 case Intrinsic::riscv_sf_vc_v_fvv:
10979 case Intrinsic::riscv_sf_vc_v_xvw:
10980 case Intrinsic::riscv_sf_vc_v_ivw:
10981 case Intrinsic::riscv_sf_vc_v_vvw:
10982 case Intrinsic::riscv_sf_vc_v_fvw: {
10983 MVT VT =
Op.getSimpleValueType();
11020 MVT VT =
Op.getSimpleValueType();
11024 if (VT.isFloatingPoint()) {
11026 VT.getVectorElementCount());
11029 if (VT.isFixedLengthVector())
11039 if (VT.isFixedLengthVector())
11041 if (VT.isFloatingPoint())
11064 case Intrinsic::riscv_seg2_load_mask:
11065 case Intrinsic::riscv_seg3_load_mask:
11066 case Intrinsic::riscv_seg4_load_mask:
11067 case Intrinsic::riscv_seg5_load_mask:
11068 case Intrinsic::riscv_seg6_load_mask:
11069 case Intrinsic::riscv_seg7_load_mask:
11070 case Intrinsic::riscv_seg8_load_mask:
11073 case Intrinsic::riscv_sseg2_load_mask:
11074 case Intrinsic::riscv_sseg3_load_mask:
11075 case Intrinsic::riscv_sseg4_load_mask:
11076 case Intrinsic::riscv_sseg5_load_mask:
11077 case Intrinsic::riscv_sseg6_load_mask:
11078 case Intrinsic::riscv_sseg7_load_mask:
11079 case Intrinsic::riscv_sseg8_load_mask:
11087 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
11088 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
11089 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
11090 Intrinsic::riscv_vlseg8_mask};
11092 Intrinsic::riscv_vlsseg2_mask, Intrinsic::riscv_vlsseg3_mask,
11093 Intrinsic::riscv_vlsseg4_mask, Intrinsic::riscv_vlsseg5_mask,
11094 Intrinsic::riscv_vlsseg6_mask, Intrinsic::riscv_vlsseg7_mask,
11095 Intrinsic::riscv_vlsseg8_mask};
11098 unsigned NF =
Op->getNumValues() - 1;
11099 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
11101 MVT VT =
Op->getSimpleValueType(0);
11109 SDValue VL =
Op.getOperand(
Op.getNumOperands() - 1);
11110 SDValue Mask =
Op.getOperand(
Op.getNumOperands() - 2);
11111 MVT MaskVT = Mask.getSimpleValueType();
11112 MVT MaskContainerVT =
11117 IsStrided ? VlssegInts[NF - 2] : VlsegInts[NF - 2],
DL, XLenVT);
11133 Ops.insert(std::next(
Ops.begin(), 4),
Op.getOperand(3));
11137 Load->getMemoryVT(), Load->getMemOperand());
11139 for (
unsigned int RetIdx = 0; RetIdx < NF; RetIdx++) {
11141 Result.getValue(0),
11145 Results.push_back(Result.getValue(1));
11151 unsigned IntNo =
Op.getConstantOperandVal(1);
11155 case Intrinsic::riscv_seg2_load_mask:
11156 case Intrinsic::riscv_seg3_load_mask:
11157 case Intrinsic::riscv_seg4_load_mask:
11158 case Intrinsic::riscv_seg5_load_mask:
11159 case Intrinsic::riscv_seg6_load_mask:
11160 case Intrinsic::riscv_seg7_load_mask:
11161 case Intrinsic::riscv_seg8_load_mask:
11162 case Intrinsic::riscv_sseg2_load_mask:
11163 case Intrinsic::riscv_sseg3_load_mask:
11164 case Intrinsic::riscv_sseg4_load_mask:
11165 case Intrinsic::riscv_sseg5_load_mask:
11166 case Intrinsic::riscv_sseg6_load_mask:
11167 case Intrinsic::riscv_sseg7_load_mask:
11168 case Intrinsic::riscv_sseg8_load_mask:
11171 case Intrinsic::riscv_sf_vc_v_x_se:
11173 case Intrinsic::riscv_sf_vc_v_i_se:
11175 case Intrinsic::riscv_sf_vc_v_xv_se:
11177 case Intrinsic::riscv_sf_vc_v_iv_se:
11179 case Intrinsic::riscv_sf_vc_v_vv_se:
11181 case Intrinsic::riscv_sf_vc_v_fv_se:
11183 case Intrinsic::riscv_sf_vc_v_xvv_se:
11185 case Intrinsic::riscv_sf_vc_v_ivv_se:
11187 case Intrinsic::riscv_sf_vc_v_vvv_se:
11189 case Intrinsic::riscv_sf_vc_v_fvv_se:
11191 case Intrinsic::riscv_sf_vc_v_xvw_se:
11193 case Intrinsic::riscv_sf_vc_v_ivw_se:
11195 case Intrinsic::riscv_sf_vc_v_vvw_se:
11197 case Intrinsic::riscv_sf_vc_v_fvw_se:
11210 case Intrinsic::riscv_seg2_store_mask:
11211 case Intrinsic::riscv_seg3_store_mask:
11212 case Intrinsic::riscv_seg4_store_mask:
11213 case Intrinsic::riscv_seg5_store_mask:
11214 case Intrinsic::riscv_seg6_store_mask:
11215 case Intrinsic::riscv_seg7_store_mask:
11216 case Intrinsic::riscv_seg8_store_mask:
11219 case Intrinsic::riscv_sseg2_store_mask:
11220 case Intrinsic::riscv_sseg3_store_mask:
11221 case Intrinsic::riscv_sseg4_store_mask:
11222 case Intrinsic::riscv_sseg5_store_mask:
11223 case Intrinsic::riscv_sseg6_store_mask:
11224 case Intrinsic::riscv_sseg7_store_mask:
11225 case Intrinsic::riscv_sseg8_store_mask:
11234 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
11235 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
11236 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
11237 Intrinsic::riscv_vsseg8_mask};
11239 Intrinsic::riscv_vssseg2_mask, Intrinsic::riscv_vssseg3_mask,
11240 Intrinsic::riscv_vssseg4_mask, Intrinsic::riscv_vssseg5_mask,
11241 Intrinsic::riscv_vssseg6_mask, Intrinsic::riscv_vssseg7_mask,
11242 Intrinsic::riscv_vssseg8_mask};
11246 unsigned NF =
Op->getNumOperands() - (IsStrided ? 6 : 5);
11247 assert(NF >= 2 && NF <= 8 &&
"Unexpected seg number");
11249 MVT VT =
Op->getOperand(2).getSimpleValueType();
11255 SDValue VL =
Op.getOperand(
Op.getNumOperands() - 1);
11256 SDValue Mask =
Op.getOperand(
Op.getNumOperands() - 2);
11257 MVT MaskVT = Mask.getSimpleValueType();
11258 MVT MaskContainerVT =
11263 IsStrided ? VsssegInts[NF - 2] : VssegInts[NF - 2],
DL, XLenVT);
11269 for (
unsigned i = 0; i < NF; i++)
11271 RISCVISD::TUPLE_INSERT,
DL, VecTupTy, StoredVal,
11277 FixedIntrinsic->getChain(),
11286 Ops.insert(std::next(
Ops.begin(), 4),
11287 Op.getOperand(
Op.getNumOperands() - 3));
11291 FixedIntrinsic->getMemoryVT(), FixedIntrinsic->getMemOperand());
11296 unsigned IntNo =
Op.getConstantOperandVal(1);
11300 case Intrinsic::riscv_seg2_store_mask:
11301 case Intrinsic::riscv_seg3_store_mask:
11302 case Intrinsic::riscv_seg4_store_mask:
11303 case Intrinsic::riscv_seg5_store_mask:
11304 case Intrinsic::riscv_seg6_store_mask:
11305 case Intrinsic::riscv_seg7_store_mask:
11306 case Intrinsic::riscv_seg8_store_mask:
11307 case Intrinsic::riscv_sseg2_store_mask:
11308 case Intrinsic::riscv_sseg3_store_mask:
11309 case Intrinsic::riscv_sseg4_store_mask:
11310 case Intrinsic::riscv_sseg5_store_mask:
11311 case Intrinsic::riscv_sseg6_store_mask:
11312 case Intrinsic::riscv_sseg7_store_mask:
11313 case Intrinsic::riscv_sseg8_store_mask:
11316 case Intrinsic::riscv_sf_vc_xv_se:
11318 case Intrinsic::riscv_sf_vc_iv_se:
11320 case Intrinsic::riscv_sf_vc_vv_se:
11322 case Intrinsic::riscv_sf_vc_fv_se:
11324 case Intrinsic::riscv_sf_vc_xvv_se:
11326 case Intrinsic::riscv_sf_vc_ivv_se:
11328 case Intrinsic::riscv_sf_vc_vvv_se:
11330 case Intrinsic::riscv_sf_vc_fvv_se:
11332 case Intrinsic::riscv_sf_vc_xvw_se:
11334 case Intrinsic::riscv_sf_vc_ivw_se:
11336 case Intrinsic::riscv_sf_vc_vvw_se:
11338 case Intrinsic::riscv_sf_vc_fvw_se:
11346 switch (ISDOpcode) {
11349 case ISD::VP_REDUCE_ADD:
11350 case ISD::VECREDUCE_ADD:
11351 return RISCVISD::VECREDUCE_ADD_VL;
11352 case ISD::VP_REDUCE_UMAX:
11353 case ISD::VECREDUCE_UMAX:
11354 return RISCVISD::VECREDUCE_UMAX_VL;
11355 case ISD::VP_REDUCE_SMAX:
11356 case ISD::VECREDUCE_SMAX:
11357 return RISCVISD::VECREDUCE_SMAX_VL;
11358 case ISD::VP_REDUCE_UMIN:
11359 case ISD::VECREDUCE_UMIN:
11360 return RISCVISD::VECREDUCE_UMIN_VL;
11361 case ISD::VP_REDUCE_SMIN:
11362 case ISD::VECREDUCE_SMIN:
11363 return RISCVISD::VECREDUCE_SMIN_VL;
11364 case ISD::VP_REDUCE_AND:
11365 case ISD::VECREDUCE_AND:
11366 return RISCVISD::VECREDUCE_AND_VL;
11367 case ISD::VP_REDUCE_OR:
11368 case ISD::VECREDUCE_OR:
11369 return RISCVISD::VECREDUCE_OR_VL;
11370 case ISD::VP_REDUCE_XOR:
11371 case ISD::VECREDUCE_XOR:
11372 return RISCVISD::VECREDUCE_XOR_VL;
11373 case ISD::VP_REDUCE_FADD:
11374 return RISCVISD::VECREDUCE_FADD_VL;
11375 case ISD::VP_REDUCE_SEQ_FADD:
11376 return RISCVISD::VECREDUCE_SEQ_FADD_VL;
11377 case ISD::VP_REDUCE_FMAX:
11378 case ISD::VP_REDUCE_FMAXIMUM:
11379 return RISCVISD::VECREDUCE_FMAX_VL;
11380 case ISD::VP_REDUCE_FMIN:
11381 case ISD::VP_REDUCE_FMINIMUM:
11382 return RISCVISD::VECREDUCE_FMIN_VL;
11391 SDValue Vec =
Op.getOperand(IsVP ? 1 : 0);
11393 assert((
Op.getOpcode() == ISD::VECREDUCE_AND ||
11394 Op.getOpcode() == ISD::VECREDUCE_OR ||
11395 Op.getOpcode() == ISD::VECREDUCE_XOR ||
11396 Op.getOpcode() == ISD::VP_REDUCE_AND ||
11397 Op.getOpcode() == ISD::VP_REDUCE_OR ||
11398 Op.getOpcode() == ISD::VP_REDUCE_XOR) &&
11399 "Unexpected reduction lowering");
11401 MVT XLenVT = Subtarget.getXLenVT();
11403 MVT ContainerVT = VecVT;
11411 Mask =
Op.getOperand(2);
11412 VL =
Op.getOperand(3);
11414 std::tie(Mask, VL) =
11419 switch (
Op.getOpcode()) {
11422 case ISD::VECREDUCE_AND:
11423 case ISD::VP_REDUCE_AND: {
11427 Vec = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Vec, TrueMask, VL);
11430 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11434 case ISD::VECREDUCE_OR:
11435 case ISD::VP_REDUCE_OR:
11437 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11440 case ISD::VECREDUCE_XOR:
11441 case ISD::VP_REDUCE_XOR: {
11444 Vec = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Vec, Mask, VL);
11465 return DAG.
getNode(BaseOpc,
DL,
Op.getValueType(), SetCC,
Op.getOperand(0));
11471 return (RegisterAVL && RegisterAVL->getReg() == RISCV::X0) ||
11472 (ImmAVL && ImmAVL->getZExtValue() >= 1);
11488 auto InnerVT = VecVT.
bitsLE(M1VT) ? VecVT : M1VT;
11492 auto InnerVL = NonZeroAVL ? VL : DAG.
getConstant(1,
DL, XLenVT);
11495 if (M1VT != InnerVT)
11500 SDValue Ops[] = {PassThru, Vec, InitialValue, Mask, VL, Policy};
11518 VecEVT =
Lo.getValueType();
11531 MVT ContainerVT = VecVT;
11550 Mask, VL,
DL, DAG, Subtarget);
11556static std::tuple<unsigned, SDValue, SDValue>
11560 auto Flags =
Op->getFlags();
11561 unsigned Opcode =
Op.getOpcode();
11565 case ISD::VECREDUCE_FADD: {
11569 return std::make_tuple(RISCVISD::VECREDUCE_FADD_VL,
Op.getOperand(0), Zero);
11571 case ISD::VECREDUCE_SEQ_FADD:
11572 return std::make_tuple(RISCVISD::VECREDUCE_SEQ_FADD_VL,
Op.getOperand(1),
11574 case ISD::VECREDUCE_FMINIMUM:
11575 case ISD::VECREDUCE_FMAXIMUM:
11576 case ISD::VECREDUCE_FMIN:
11577 case ISD::VECREDUCE_FMAX: {
11580 (Opcode == ISD::VECREDUCE_FMIN || Opcode == ISD::VECREDUCE_FMINIMUM)
11581 ? RISCVISD::VECREDUCE_FMIN_VL
11582 : RISCVISD::VECREDUCE_FMAX_VL;
11583 return std::make_tuple(RVVOpc,
Op.getOperand(0), Front);
11591 MVT VecEltVT =
Op.getSimpleValueType();
11593 unsigned RVVOpcode;
11594 SDValue VectorVal, ScalarVal;
11595 std::tie(RVVOpcode, VectorVal, ScalarVal) =
11599 MVT ContainerVT = VecVT;
11605 MVT ResVT =
Op.getSimpleValueType();
11608 VL,
DL, DAG, Subtarget);
11609 if (
Op.getOpcode() != ISD::VECREDUCE_FMINIMUM &&
11610 Op.getOpcode() != ISD::VECREDUCE_FMAXIMUM)
11613 if (
Op->getFlags().hasNoNaNs())
11619 {VectorVal, VectorVal, DAG.getCondCode(ISD::SETNE),
11620 DAG.getUNDEF(Mask.getValueType()), Mask, VL});
11621 MVT XLenVT = Subtarget.getXLenVT();
11622 SDValue CPop = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, IsNan, Mask, VL);
11626 DL, ResVT, NoNaNs, Res,
11633 unsigned Opc =
Op.getOpcode();
11637 MVT XLenVT = Subtarget.getXLenVT();
11656 Vec, Mask, VL,
DL, DAG, Subtarget);
11657 if ((
Opc != ISD::VP_REDUCE_FMINIMUM &&
Opc != ISD::VP_REDUCE_FMAXIMUM) ||
11658 Op->getFlags().hasNoNaNs())
11665 RISCVISD::SETCC_VL,
DL, PredVT,
11667 SDValue VCPop = DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, IsNaN, Mask, VL);
11675 DL, ResVT, NoNaNs, Res,
11687 MVT XLenVT = Subtarget.getXLenVT();
11688 unsigned OrigIdx =
Op.getConstantOperandVal(2);
11689 const RISCVRegisterInfo *
TRI = Subtarget.getRegisterInfo();
11691 if (OrigIdx == 0 && Vec.
isUndef())
11702 assert(OrigIdx % 8 == 0 &&
"Invalid index");
11705 "Unexpected mask vector lowering");
11735 const auto VLen = Subtarget.getRealVLen();
11737 MVT ContainerVT = VecVT;
11759 if (OrigIdx == 0) {
11761 DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, ContainerVT, Vec, SubVec, VL);
11764 SubVec =
getVSlideup(DAG, Subtarget,
DL, ContainerVT, Vec, SubVec,
11765 SlideupAmt, Mask, VL, Policy);
11773 MVT ContainerVecVT = VecVT;
11779 MVT ContainerSubVecVT = SubVecVT;
11785 unsigned SubRegIdx;
11786 ElementCount RemIdx;
11795 ContainerVecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
11796 SubRegIdx = Decompose.first;
11798 (OrigIdx % Vscale));
11802 ContainerVecVT, ContainerSubVecVT, OrigIdx,
TRI);
11803 SubRegIdx = Decompose.first;
11809 Subtarget.expandVScale(SubVecVT.
getSizeInBits()).getKnownMinValue()));
11810 bool ExactlyVecRegSized =
11812 .isKnownMultipleOf(Subtarget.expandVScale(VecRegSize));
11827 if (RemIdx.
isZero() && (ExactlyVecRegSized || Vec.
isUndef())) {
11831 if (SubRegIdx == RISCV::NoSubRegister) {
11853 MVT InterSubVT = ContainerVecVT;
11854 SDValue AlignedExtract = Vec;
11876 if (Subtarget.expandVScale(EndIndex) ==
11883 SubVec = DAG.
getNode(RISCVISD::VMV_V_V_VL,
DL, InterSubVT, AlignedExtract,
11891 SubVec =
getVSlideup(DAG, Subtarget,
DL, InterSubVT, AlignedExtract, SubVec,
11892 SlideupAmt, Mask, VL, Policy);
11897 if (ContainerVecVT.
bitsGT(InterSubVT))
11905 return DAG.
getBitcast(
Op.getSimpleValueType(), SubVec);
11911 MVT SubVecVT =
Op.getSimpleValueType();
11915 MVT XLenVT = Subtarget.getXLenVT();
11916 unsigned OrigIdx =
Op.getConstantOperandVal(1);
11917 const RISCVRegisterInfo *
TRI = Subtarget.getRegisterInfo();
11932 assert(OrigIdx % 8 == 0 &&
"Invalid index");
11935 "Unexpected mask vector lowering");
11961 const auto VLen = Subtarget.getRealVLen();
11969 MVT ContainerVT = VecVT;
11977 if (
auto ShrunkVT =
11979 ContainerVT = *ShrunkVT;
11991 DAG.
getUNDEF(ContainerVT), Vec, SlidedownAmt, Mask, VL);
12002 MVT ContainerSubVecVT = SubVecVT;
12006 unsigned SubRegIdx;
12007 ElementCount RemIdx;
12016 VecVT, ContainerSubVecVT, OrigIdx / Vscale,
TRI);
12017 SubRegIdx = Decompose.first;
12019 (OrigIdx % Vscale));
12023 VecVT, ContainerSubVecVT, OrigIdx,
TRI);
12024 SubRegIdx = Decompose.first;
12051 MVT InterSubVT = VecVT;
12056 assert(SubRegIdx != RISCV::NoSubRegister);
12075 Vec, SlidedownAmt, Mask, VL);
12083 return DAG.
getBitcast(
Op.getSimpleValueType(), Slidedown);
12090 MVT VT =
N.getSimpleValueType();
12094 assert(
Op.getSimpleValueType() == VT &&
12095 "Operands and result must be same type");
12099 unsigned NumVals =
N->getNumValues();
12102 NumVals,
N.getValueType().changeVectorElementType(MVT::i8)));
12105 for (
unsigned I = 0;
I < NumVals;
I++) {
12111 if (TruncVals.
size() > 1)
12113 return TruncVals.
front();
12119 MVT VecVT =
Op.getSimpleValueType();
12121 const unsigned Factor =
Op->getNumValues();
12132 for (
unsigned i = 0U; i < Factor; ++i)
12141 for (
unsigned i = 0U; i < Factor; ++i)
12151 for (
unsigned i = 0; i != Factor; ++i) {
12154 Ops[i * 2 + 1] = OpHi;
12165 for (
unsigned i = 0; i != Factor; ++i)
12172 if (Subtarget.hasVendorXRivosVizip() && Factor == 2) {
12173 MVT VT =
Op->getSimpleValueType(0);
12198 lowerVZIP(RISCVISD::RI_VUNZIP2A_VL, V1, V2,
DL, DAG, Subtarget);
12200 lowerVZIP(RISCVISD::RI_VUNZIP2B_VL, V1, V2,
DL, DAG, Subtarget);
12233 EvenSplat = DAG.
getBitcast(MVT::nxv64i1, EvenSplat);
12237 OddSplat = DAG.
getBitcast(MVT::nxv64i1, OddSplat);
12242 EvenMask, DAG.
getUNDEF(ConcatVT));
12254 MVT XLenVT = Subtarget.getXLenVT();
12276 Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
12277 Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
12278 Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
12279 Intrinsic::riscv_vlseg8_mask};
12303 for (
unsigned i = 0U; i < Factor; ++i)
12304 Res[i] = DAG.
getNode(RISCVISD::TUPLE_EXTRACT,
DL, VecVT, Load,
12313 MVT VecVT =
Op.getSimpleValueType();
12326 for (
unsigned i = 0U; i < Factor; ++i)
12334 for (
unsigned i = 0U; i < Factor; ++i)
12340 MVT XLenVT = Subtarget.getXLenVT();
12347 for (
unsigned i = 0; i != Factor; ++i) {
12350 Ops[i + Factor] = OpHi;
12361 for (
unsigned i = 0; i != Factor; ++i) {
12362 unsigned IdxLo = 2 * i;
12363 unsigned IdxHi = 2 * i + 1;
12365 Res[IdxLo / Factor].getValue(IdxLo % Factor),
12366 Res[IdxHi / Factor].getValue(IdxHi % Factor));
12384 EVT PtrVT =
StackPtr.getValueType();
12390 Intrinsic::riscv_vsseg2_mask, Intrinsic::riscv_vsseg3_mask,
12391 Intrinsic::riscv_vsseg4_mask, Intrinsic::riscv_vsseg5_mask,
12392 Intrinsic::riscv_vsseg6_mask, Intrinsic::riscv_vsseg7_mask,
12393 Intrinsic::riscv_vsseg8_mask,
12401 for (
unsigned i = 0; i < Factor; i++)
12403 DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VecTupTy, StoredVal,
12426 for (
unsigned i = 0; i != Factor; ++i) {
12430 Loads[i] = DAG.
getLoad(VecVT,
DL, Chain, StackPtr, PtrInfo);
12438 if (Subtarget.hasVendorXRivosVizip() && !
Op.getOperand(0).isUndef() &&
12439 !
Op.getOperand(1).isUndef()) {
12459 Op.getOperand(0),
Op.getOperand(1));
12483 DAG.
getNode(RISCVISD::ADD_VL,
DL, IdxVT, Idx, VLMax, Idx, OddMask, VL);
12488 Interleaved = DAG.
getNode(RISCVISD::VRGATHEREI16_VV_VL,
DL, ConcatVT,
12505 MVT VT =
Op.getSimpleValueType();
12507 MVT XLenVT = Subtarget.getXLenVT();
12510 uint64_t StepValImm =
Op.getConstantOperandVal(0);
12511 if (StepValImm != 1) {
12520 VL, VT,
DL, DAG, Subtarget);
12535 MVT VecVT =
Op.getSimpleValueType();
12544 MVT ContainerVT = VecVT;
12551 MVT XLenVT = Subtarget.getXLenVT();
12597 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
12598 unsigned MaxVLMAX =
12603 unsigned GatherOpc = RISCVISD::VRGATHER_VV_VL;
12608 if (MaxVLMAX > 256 && EltSize == 8) {
12622 LoVT.getVectorMinNumElements());
12627 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
12635 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
12660 DAG.
getUNDEF(ContainerVT), Mask, VL);
12671 MVT XLenVT = Subtarget.getXLenVT();
12672 MVT VecVT =
Op.getSimpleValueType();
12677 SDValue DownOffset, UpOffset;
12678 if (ImmValue >= 0) {
12693 DAG, Subtarget,
DL, VecVT, DAG.
getUNDEF(VecVT), V1, DownOffset, TrueMask,
12694 Subtarget.hasVLDependentLatency() ? UpOffset
12696 return getVSlideup(DAG, Subtarget,
DL, VecVT, SlideDown, V2, UpOffset,
12702RISCVTargetLowering::lowerFixedLengthVectorLoadToRVV(
SDValue Op,
12708 Load->getMemoryVT(),
12709 *
Load->getMemOperand()) &&
12710 "Expecting a correctly-aligned load");
12712 MVT VT =
Op.getSimpleValueType();
12713 MVT XLenVT = Subtarget.getXLenVT();
12718 const auto [MinVLMAX, MaxVLMAX] =
12722 MachineMemOperand *MMO =
Load->getMemOperand();
12735 IsMaskOp ? Intrinsic::riscv_vlm : Intrinsic::riscv_vle,
DL, XLenVT);
12739 Ops.push_back(
Load->getBasePtr());
12741 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
12744 Load->getMemoryVT(),
Load->getMemOperand());
12751RISCVTargetLowering::lowerFixedLengthVectorStoreToRVV(
SDValue Op,
12757 Store->getMemoryVT(),
12758 *
Store->getMemOperand()) &&
12759 "Expecting a correctly-aligned store");
12763 MVT XLenVT = Subtarget.getXLenVT();
12779 const auto [MinVLMAX, MaxVLMAX] =
12783 MachineMemOperand *MMO =
Store->getMemOperand();
12793 IsMaskOp ? Intrinsic::riscv_vsm : Intrinsic::riscv_vse,
DL, XLenVT);
12796 {Store->getChain(), IntID, NewValue, Store->getBasePtr(), VL},
12797 Store->getMemoryVT(),
Store->getMemOperand());
12803 MVT VT =
Op.getSimpleValueType();
12806 EVT MemVT = MemSD->getMemoryVT();
12807 MachineMemOperand *MMO = MemSD->getMemOperand();
12808 SDValue Chain = MemSD->getChain();
12812 bool IsExpandingLoad =
false;
12814 Mask = VPLoad->getMask();
12816 VL = VPLoad->getVectorLength();
12819 Mask = MLoad->getMask();
12820 PassThru = MLoad->getPassThru();
12821 IsExpandingLoad = MLoad->isExpandingLoad();
12826 MVT XLenVT = Subtarget.getXLenVT();
12828 MVT ContainerVT = VT;
12842 if (!IsUnmasked && IsExpandingLoad) {
12845 DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Mask,
12849 unsigned IntID = IsUnmasked || IsExpandingLoad ? Intrinsic::riscv_vle
12850 : Intrinsic::riscv_vle_mask;
12852 if (IntID == Intrinsic::riscv_vle)
12855 Ops.push_back(PassThru);
12856 Ops.push_back(BasePtr);
12857 if (IntID == Intrinsic::riscv_vle_mask)
12858 Ops.push_back(Mask);
12860 if (IntID == Intrinsic::riscv_vle_mask)
12863 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
12867 Chain =
Result.getValue(1);
12869 MVT IndexVT = ContainerVT;
12874 bool UseVRGATHEREI16 =
false;
12882 UseVRGATHEREI16 =
true;
12888 DAG.
getUNDEF(IndexVT), Mask, ExpandingVL);
12890 DAG.
getNode(UseVRGATHEREI16 ? RISCVISD::VRGATHEREI16_VV_VL
12891 : RISCVISD::VRGATHER_VV_VL,
12892 DL, ContainerVT, Result, Iota, PassThru, Mask, ExpandingVL);
12903 MVT VT =
Op->getSimpleValueType(0);
12906 EVT MemVT = VPLoadFF->getMemoryVT();
12907 MachineMemOperand *MMO = VPLoadFF->getMemOperand();
12908 SDValue Chain = VPLoadFF->getChain();
12912 SDValue VL = VPLoadFF->getVectorLength();
12914 MVT XLenVT = Subtarget.getXLenVT();
12916 MVT ContainerVT = VT;
12923 unsigned IntID = Intrinsic::riscv_vleff_mask;
12933 SDVTList VTs = DAG.
getVTList({ContainerVT,
Op->getValueType(1), MVT::Other});
12938 Chain =
Result.getValue(2);
12951 EVT MemVT = MemSD->getMemoryVT();
12952 MachineMemOperand *MMO = MemSD->getMemOperand();
12953 SDValue Chain = MemSD->getChain();
12957 bool IsCompressingStore =
false;
12959 Val = VPStore->getValue();
12960 Mask = VPStore->getMask();
12961 VL = VPStore->getVectorLength();
12964 Val = MStore->getValue();
12965 Mask = MStore->getMask();
12966 IsCompressingStore = MStore->isCompressingStore();
12973 MVT XLenVT = Subtarget.getXLenVT();
12975 MVT ContainerVT = VT;
12980 if (!IsUnmasked || IsCompressingStore) {
12989 if (IsCompressingStore) {
12992 DAG.
getUNDEF(ContainerVT), Val, Mask, VL);
12994 DAG.
getNode(RISCVISD::VCPOP_VL,
DL, XLenVT, Mask,
12999 IsUnmasked ? Intrinsic::riscv_vse : Intrinsic::riscv_vse_mask;
13001 Ops.push_back(Val);
13002 Ops.push_back(BasePtr);
13004 Ops.push_back(Mask);
13019 MVT XLenVT = Subtarget.getXLenVT();
13020 MVT ContainerVT = VT;
13033 Passthru, Val, Mask, VL);
13043 unsigned Opc =
Op.getOpcode();
13050 MVT VT =
Op.getSimpleValueType();
13058 SDVTList VTList =
Op->getVTList();
13083 MVT ContainerInVT = InVT;
13101 RISCVISD::STRICT_FSETCC_VL,
DL, DAG.
getVTList(MaskVT, MVT::Other),
13102 {Chain, Op1, Op1, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
13105 RISCVISD::STRICT_FSETCC_VL,
DL, DAG.
getVTList(MaskVT, MVT::Other),
13106 {Chain, Op2, Op2, DAG.getCondCode(ISD::SETOEQ), DAG.getUNDEF(MaskVT),
13109 DAG.
getNode(RISCVISD::VMAND_VL,
DL, MaskVT, OrderMask1, OrderMask2, VL);
13112 Res = DAG.
getNode(RISCVISD::STRICT_FSETCCS_VL,
DL,
13114 {Chain, Op1, Op2, CC, Mask, Mask, VL});
13117 : RISCVISD::STRICT_FSETCCS_VL;
13119 {Chain, Op1, Op2, CC, DAG.getUNDEF(MaskVT), Mask, VL});
13132 MVT VT =
Op.getSimpleValueType();
13136 "Unexpected type for ISD::ABS");
13138 MVT ContainerVT = VT;
13145 if (
Op->getOpcode() == ISD::VP_ABS) {
13146 Mask =
Op->getOperand(1);
13150 VL =
Op->getOperand(2);
13155 RISCVISD::VMV_V_X_VL,
DL, ContainerVT, DAG.
getUNDEF(ContainerVT),
13158 DAG.
getUNDEF(ContainerVT), Mask, VL);
13160 DAG.
getUNDEF(ContainerVT), Mask, VL);
13169 const auto &TSInfo =
13173 bool HasPassthruOp = TSInfo.hasPassthruOp(NewOpc);
13174 bool HasMask = TSInfo.hasMaskOp(NewOpc);
13176 MVT VT =
Op.getSimpleValueType();
13181 for (
const SDValue &V :
Op->op_values()) {
13185 if (!
V.getValueType().isVector()) {
13191 assert(useRVVForFixedLengthVectorVT(
V.getSimpleValueType()) &&
13192 "Only fixed length vectors are supported!");
13194 V.getSimpleValueType().getVectorElementType());
13203 Ops.push_back(Mask);
13208 if (
Op->isStrictFPOpcode()) {
13227 const auto &TSInfo =
13231 bool HasPassthruOp = TSInfo.hasPassthruOp(RISCVISDOpc);
13234 MVT VT =
Op.getSimpleValueType();
13237 MVT ContainerVT = VT;
13246 if (HasPassthruOp) {
13249 if (*MaskIdx ==
OpIdx.index())
13253 if (
Op.getOpcode() == ISD::VP_MERGE) {
13255 Ops.push_back(
Ops.back());
13257 assert(
Op.getOpcode() == ISD::VP_SELECT);
13264 if (RISCVISDOpc == RISCVISD::VFCVT_RM_X_F_VL &&
13267 Subtarget.getXLenVT()));
13269 if (!
V.getValueType().isFixedLengthVector()) {
13274 MVT OpVT =
V.getSimpleValueType();
13276 assert(useRVVForFixedLengthVectorVT(OpVT) &&
13277 "Only fixed length vectors are supported!");
13292 MVT VT =
Op.getSimpleValueType();
13298 MVT ContainerVT = VT;
13305 MVT XLenVT = Subtarget.getXLenVT();
13308 DAG.
getUNDEF(ContainerVT), Zero, VL);
13311 Op.getOpcode() == ISD::VP_ZERO_EXTEND ? 1 : -1,
DL, XLenVT);
13313 DAG.
getUNDEF(ContainerVT), SplatValue, VL);
13316 ZeroSplat, DAG.
getUNDEF(ContainerVT), VL);
13325 MVT VT =
Op.getSimpleValueType();
13333 MVT ContainerVT = VT;
13341 SDValue AllOneMask = DAG.
getNode(RISCVISD::VMSET_VL,
DL, ContainerVT, VL);
13343 switch (Condition) {
13348 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, Op2, VL);
13353 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, Op2, VL);
13355 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, AllOneMask, VL);
13363 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, AllOneMask, VL);
13364 Result = DAG.
getNode(RISCVISD::VMAND_VL,
DL, ContainerVT, Temp, Op2, VL);
13372 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op2, AllOneMask, VL);
13373 Result = DAG.
getNode(RISCVISD::VMAND_VL,
DL, ContainerVT, Op1, Temp, VL);
13381 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op1, AllOneMask, VL);
13382 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, Op2, VL);
13390 DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Op2, AllOneMask, VL);
13391 Result = DAG.
getNode(RISCVISD::VMXOR_VL,
DL, ContainerVT, Temp, Op1, VL);
13411 MVT DstVT =
Op.getSimpleValueType();
13412 MVT SrcVT = Src.getSimpleValueType();
13425 if (DstEltSize >= SrcEltSize) {
13429 unsigned RISCVISDExtOpc = RISCVISDOpc == RISCVISD::SINT_TO_FP_VL
13430 ? RISCVISD::VSEXT_VL
13431 : RISCVISD::VZEXT_VL;
13434 if (SrcEltSize == 1) {
13436 MVT XLenVT = Subtarget.getXLenVT();
13441 RISCVISDExtOpc == RISCVISD::VZEXT_VL ? 1 : -1,
DL, XLenVT);
13444 Src = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, IntVT, Src, OneSplat,
13445 ZeroSplat, DAG.
getUNDEF(IntVT), VL);
13446 }
else if (DstEltSize > (2 * SrcEltSize)) {
13450 Src = DAG.
getNode(RISCVISDExtOpc,
DL, IntVT, Src, Mask, VL);
13456 "Wrong input/output vector types");
13459 if (DstEltSize > (2 * SrcEltSize)) {
13464 DAG.
getNode(RISCVISD::FP_EXTEND_VL,
DL, InterimFVT, Src, Mask, VL);
13475 MVT InterimFVT = DstVT;
13476 if (SrcEltSize > (2 * DstEltSize)) {
13477 assert(SrcEltSize == (4 * DstEltSize) &&
"Unexpected types!");
13484 if (InterimFVT != DstVT) {
13486 Result = DAG.
getNode(RISCVISD::FP_ROUND_VL,
DL, DstVT, Src, Mask, VL);
13490 "Wrong input/output vector types");
13494 if (DstEltSize == 1) {
13497 assert(SrcEltSize >= 16 &&
"Unexpected FP type!");
13504 MVT XLenVT = Subtarget.getXLenVT();
13506 SplatZero = DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, InterimIVT,
13507 DAG.
getUNDEF(InterimIVT), SplatZero, VL);
13517 while (InterimIVT != DstVT) {
13529 MVT VT =
Op.getSimpleValueType();
13538 MVT VT =
Op.getSimpleValueType();
13539 MVT XLenVT = Subtarget.getXLenVT();
13552 MVT ContainerVT = VT;
13572 TrueVal = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, PromotedVT, TrueVal, SplatOne,
13573 SplatZero, DAG.
getUNDEF(PromotedVT), VL);
13576 SplatOne, SplatZero, DAG.
getUNDEF(PromotedVT), VLMax);
13580 TrueVal, FalseVal, FalseVal, VL);
13585 RISCVISD::SETCC_VL,
DL, ContainerVT,
13595RISCVTargetLowering::lowerVPSpliceExperimental(
SDValue Op,
13597 using namespace SDPatternMatch;
13608 const MVT XLenVT = Subtarget.getXLenVT();
13609 MVT VT =
Op.getSimpleValueType();
13610 MVT ContainerVT = VT;
13620 if (IsMaskVector) {
13630 Op1 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, Op1, SplatOneOp1,
13631 SplatZeroOp1, DAG.
getUNDEF(ContainerVT), EVL1);
13639 Op2 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, ContainerVT, Op2, SplatOneOp2,
13640 SplatZeroOp2, DAG.
getUNDEF(ContainerVT), EVL2);
13643 auto getVectorFirstEle = [](
SDValue Vec) {
13656 if (
auto FirstEle = getVectorFirstEle(
Op->getOperand(0))) {
13659 if ((EltVT == MVT::f16 && !Subtarget.hasVInstructionsF16()) ||
13660 EltVT == MVT::bf16) {
13668 : RISCVISD::VSLIDE1UP_VL,
13669 DL, ContainerVT, DAG.
getUNDEF(ContainerVT), Op2,
13670 FirstEle, Mask, EVL2);
13680 SDValue DownOffset, UpOffset;
13681 if (ImmValue >= 0) {
13695 DAG.
getUNDEF(ContainerVT), Op1, DownOffset, Mask,
13696 Subtarget.hasVLDependentLatency() ? UpOffset : EVL2);
13700 if (IsMaskVector) {
13704 {Result, DAG.getConstant(0, DL, ContainerVT),
13705 DAG.getCondCode(ISD::SETNE), DAG.getUNDEF(getMaskTypeFor(ContainerVT)),
13720 MVT VT =
Op.getSimpleValueType();
13722 MVT ContainerVT = VT;
13733 DAG.
getNode(
C->isZero() ? RISCVISD::VMCLR_VL : RISCVISD::VMSET_VL,
DL,
13756RISCVTargetLowering::lowerVPReverseExperimental(
SDValue Op,
13759 MVT VT =
Op.getSimpleValueType();
13760 MVT XLenVT = Subtarget.getXLenVT();
13766 MVT ContainerVT = VT;
13774 MVT GatherVT = ContainerVT;
13778 if (IsMaskVector) {
13788 Op1 = DAG.
getNode(RISCVISD::VMERGE_VL,
DL, IndicesVT, Op1, SplatOne,
13789 SplatZero, DAG.
getUNDEF(IndicesVT), EVL);
13794 unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
13795 unsigned MaxVLMAX =
13798 unsigned GatherOpc = RISCVISD::VRGATHER_VV_VL;
13804 if (MaxVLMAX > 256 && EltSize == 8) {
13832 DAG.
getUNDEF(GatherVT), Result, Diff, Mask, EVL);
13834 if (IsMaskVector) {
13837 DAG.
getNode(RISCVISD::SETCC_VL,
DL, ContainerVT,
13850 GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
13857 DAG.
getUNDEF(IndicesVT), VecLen, EVL);
13858 SDValue VRSUB = DAG.
getNode(RISCVISD::SUB_VL,
DL, IndicesVT, VecLenSplat, VID,
13859 DAG.
getUNDEF(IndicesVT), Mask, EVL);
13861 DAG.
getUNDEF(GatherVT), Mask, EVL);
13863 if (IsMaskVector) {
13866 RISCVISD::SETCC_VL,
DL, ContainerVT,
13878 MVT VT =
Op.getSimpleValueType();
13880 return lowerVPOp(
Op, DAG);
13887 MVT ContainerVT = VT;
13905 MVT XLenVT = Subtarget.getXLenVT();
13906 MVT VT =
Op.getSimpleValueType();
13907 MVT ContainerVT = VT;
13911 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
13919 : Intrinsic::riscv_vlse_mask,
13922 DAG.
getUNDEF(ContainerVT), VPNode->getBasePtr(),
13923 VPNode->getStride()};
13929 Ops.push_back(Mask);
13931 Ops.push_back(VPNode->getVectorLength());
13935 Ops.push_back(Policy);
13940 VPNode->getMemoryVT(), VPNode->getMemOperand());
13952 MVT XLenVT = Subtarget.getXLenVT();
13955 SDValue StoreVal = VPNode->getValue();
13957 MVT ContainerVT = VT;
13968 : Intrinsic::riscv_vsse_mask,
13971 VPNode->getBasePtr(), VPNode->getStride()};
13977 Ops.push_back(Mask);
13979 Ops.push_back(VPNode->getVectorLength());
13982 Ops, VPNode->getMemoryVT(),
13983 VPNode->getMemOperand());
13995 MVT VT =
Op.getSimpleValueType();
13998 EVT MemVT = MemSD->getMemoryVT();
13999 MachineMemOperand *MMO = MemSD->getMemOperand();
14000 SDValue Chain = MemSD->getChain();
14007 Index = VPGN->getIndex();
14008 Mask = VPGN->getMask();
14010 VL = VPGN->getVectorLength();
14016 Index = MGN->getIndex();
14017 Mask = MGN->getMask();
14018 PassThru = MGN->getPassThru();
14022 MVT IndexVT =
Index.getSimpleValueType();
14023 MVT XLenVT = Subtarget.getXLenVT();
14026 "Unexpected VTs!");
14027 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
14030 "Unexpected extending MGATHER/VP_GATHER");
14036 MVT ContainerVT = VT;
14060 IsUnmasked ? Intrinsic::riscv_vluxei : Intrinsic::riscv_vluxei_mask;
14065 Ops.push_back(PassThru);
14066 Ops.push_back(BasePtr);
14067 Ops.push_back(Index);
14069 Ops.push_back(Mask);
14074 SDVTList VTs = DAG.
getVTList({ContainerVT, MVT::Other});
14077 Chain =
Result.getValue(1);
14095 EVT MemVT = MemSD->getMemoryVT();
14096 MachineMemOperand *MMO = MemSD->getMemOperand();
14097 SDValue Chain = MemSD->getChain();
14100 [[maybe_unused]]
bool IsTruncatingStore =
false;
14104 Index = VPSN->getIndex();
14105 Mask = VPSN->getMask();
14106 Val = VPSN->getValue();
14107 VL = VPSN->getVectorLength();
14109 IsTruncatingStore =
false;
14113 Index = MSN->getIndex();
14114 Mask = MSN->getMask();
14115 Val = MSN->getValue();
14116 IsTruncatingStore = MSN->isTruncatingStore();
14120 MVT IndexVT =
Index.getSimpleValueType();
14121 MVT XLenVT = Subtarget.getXLenVT();
14124 "Unexpected VTs!");
14125 assert(
BasePtr.getSimpleValueType() == XLenVT &&
"Unexpected pointer type");
14128 assert(!IsTruncatingStore &&
"Unexpected truncating MSCATTER/VP_SCATTER");
14134 MVT ContainerVT = VT;
14158 IsUnmasked ? Intrinsic::riscv_vsoxei : Intrinsic::riscv_vsoxei_mask;
14160 Ops.push_back(Val);
14161 Ops.push_back(BasePtr);
14162 Ops.push_back(Index);
14164 Ops.push_back(Mask);
14173 const MVT XLenVT = Subtarget.getXLenVT();
14177 SDVTList VTs = DAG.
getVTList(XLenVT, MVT::Other);
14184 static const int Table =
14203 const MVT XLenVT = Subtarget.getXLenVT();
14213 static const unsigned Table =
14228 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14234 const MVT XLenVT = Subtarget.getXLenVT();
14238 SDVTList VTs = DAG.
getVTList(XLenVT, MVT::Other);
14239 return DAG.
getNode(RISCVISD::READ_CSR,
DL, VTs, Chain, SysRegNo);
14244 const MVT XLenVT = Subtarget.getXLenVT();
14251 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14257 const MVT XLenVT = Subtarget.getXLenVT();
14263 return DAG.
getNode(RISCVISD::WRITE_CSR,
DL, MVT::Other, Chain, SysRegNo,
14277 SDValue Result = DAG.
getNode(RISCVISD::READ_CSR,
DL, VTs, Chain, SysRegNo);
14278 Chain = Result.getValue(1);
14284 const MVT XLenVT = Subtarget.getXLenVT();
14294 Chain = DAG.
getNode(RISCVISD::CLEAR_CSR,
DL, MVT::Other, Chain, SysRegNo,
14296 return DAG.
getNode(RISCVISD::SET_CSR,
DL, MVT::Other, Chain, SysRegNo,
14302 const MVT XLenVT = Subtarget.getXLenVT();
14309 return DAG.
getNode(RISCVISD::CLEAR_CSR,
DL, MVT::Other, Chain, SysRegNo,
14317 bool isRISCV64 = Subtarget.is64Bit();
14331 return RISCVISD::SLLW;
14333 return RISCVISD::SRAW;
14335 return RISCVISD::SRLW;
14337 return RISCVISD::DIVW;
14339 return RISCVISD::DIVUW;
14341 return RISCVISD::REMUW;
14343 return RISCVISD::ROLW;
14345 return RISCVISD::RORW;
14381 switch (
N->getOpcode()) {
14383 llvm_unreachable(
"Don't know how to custom type legalize this operation!");
14388 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14389 "Unexpected custom legalisation");
14390 bool IsStrict =
N->isStrictFPOpcode();
14393 SDValue Op0 = IsStrict ?
N->getOperand(1) :
N->getOperand(0);
14402 !Subtarget.hasStdExtZfhOrZhinx()) {
14407 unsigned Opc = IsSigned ? RISCVISD::STRICT_FCVT_W_RV64
14408 : RISCVISD::STRICT_FCVT_WU_RV64;
14411 Opc,
DL, VTs, Chain, Op0,
14420 !Subtarget.hasStdExtZfhOrZhinx()) ||
14422 Op0 = DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, Op0);
14424 unsigned Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
14445 std::tie(Result, Chain) =
14446 makeLibCall(DAG, LC,
N->getValueType(0), Op0, CallOptions,
DL, Chain);
14452 case ISD::LROUND: {
14461 if (Op0.
getValueType() == MVT::f16 && !Subtarget.hasStdExtZfhOrZhinx())
14462 Op0 = DAG.
getNode(ISD::FP_EXTEND,
DL, MVT::f32, Op0);
14465 DAG.
getNode(RISCVISD::FCVT_W_RV64,
DL, MVT::i64, Op0,
14473 RTLIB::Libcall LC =
14474 Op0.
getValueType() == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
14483 case ISD::READCYCLECOUNTER:
14484 case ISD::READSTEADYCOUNTER: {
14485 assert(!Subtarget.is64Bit() &&
"READCYCLECOUNTER/READSTEADYCOUNTER only "
14486 "has custom type legalization on riscv32");
14488 SDValue LoCounter, HiCounter;
14489 MVT XLenVT = Subtarget.getXLenVT();
14490 if (
N->getOpcode() == ISD::READCYCLECOUNTER) {
14499 N->getOperand(0), LoCounter, HiCounter);
14514 if (
N->getValueType(0) == MVT::i64) {
14515 assert(Subtarget.hasStdExtZilsd() && !Subtarget.is64Bit() &&
14516 "Unexpected custom legalisation");
14518 if (!Subtarget.enableUnalignedScalarMem() && Ld->
getAlign() < 8)
14523 RISCVISD::LD_RV32,
DL,
14524 DAG.
getVTList({MVT::i32, MVT::i32, MVT::Other}),
14525 {Ld->getChain(), Ld->getBasePtr()}, MVT::i64, Ld->
getMemOperand());
14529 Results.append({Pair, Result.getValue(2)});
14533 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14534 "Unexpected custom legalisation");
14545 unsigned Size =
N->getSimpleValueType(0).getSizeInBits();
14546 unsigned XLen = Subtarget.getXLen();
14549 assert(
Size == (XLen * 2) &&
"Unexpected custom legalisation");
14557 if (LHSIsU == RHSIsU)
14561 MVT XLenVT = Subtarget.getXLenVT();
14574 if (RHSIsU && LHSIsS && !RHSIsS)
14575 Results.push_back(MakeMULPair(LHS, RHS));
14576 else if (LHSIsU && RHSIsS && !LHSIsS)
14577 Results.push_back(MakeMULPair(RHS, LHS));
14585 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14586 "Unexpected custom legalisation");
14592 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14593 "Unexpected custom legalisation");
14596 if (
N->getOpcode() ==
ISD::SHL && Subtarget.hasStdExtZbs() &&
14621 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14622 "Unexpected custom legalisation");
14623 assert((Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb() ||
14624 Subtarget.hasVendorXTHeadBb()) &&
14625 "Unexpected custom legalization");
14627 !(Subtarget.hasStdExtZbb() || Subtarget.hasStdExtZbkb()))
14635 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14636 "Unexpected custom legalisation");
14642 unsigned Opc = IsCTZ ? RISCVISD::CTZW : RISCVISD::CLZW;
14650 MVT VT =
N->getSimpleValueType(0);
14651 assert((VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32) &&
14652 Subtarget.is64Bit() && Subtarget.hasStdExtM() &&
14653 "Unexpected custom legalisation");
14665 if (VT != MVT::i32)
14673 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14674 "Unexpected custom legalisation");
14695 EVT OType =
N->getValueType(1);
14707 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14708 "Unexpected custom legalisation");
14725 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1), Res,
14729 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1),
N->getOperand(0),
14736 Overflow = DAG.
getSetCC(
DL,
N->getValueType(1), Res, LHS,
14746 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14747 !Subtarget.hasStdExtZbb() &&
"Unexpected custom legalisation");
14755 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14756 "Unexpected custom legalisation");
14761 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
14762 "Unexpected custom legalisation");
14764 if (Subtarget.hasStdExtZbb()) {
14797 case ISD::BITCAST: {
14798 EVT VT =
N->getValueType(0);
14802 MVT XLenVT = Subtarget.getXLenVT();
14803 if (VT == MVT::i16 &&
14804 ((Op0VT == MVT::f16 && Subtarget.hasStdExtZfhminOrZhinxmin()) ||
14805 (Op0VT == MVT::bf16 && Subtarget.hasStdExtZfbfmin()))) {
14808 }
else if (VT == MVT::i32 && Op0VT == MVT::f32 && Subtarget.is64Bit() &&
14809 Subtarget.hasStdExtFOrZfinx()) {
14811 DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Op0);
14813 }
else if (VT == MVT::i64 && Op0VT == MVT::f64 && !Subtarget.is64Bit() &&
14814 Subtarget.hasStdExtDOrZdinx()) {
14816 DAG.
getVTList(MVT::i32, MVT::i32), Op0);
14835 assert(
N->getValueType(0) == MVT::i8 && Subtarget.hasStdExtZbkb() &&
14836 "Unexpected custom legalisation");
14837 MVT XLenVT = Subtarget.getXLenVT();
14845 case RISCVISD::BREV8:
14846 case RISCVISD::ORC_B: {
14847 MVT VT =
N->getSimpleValueType(0);
14848 MVT XLenVT = Subtarget.getXLenVT();
14849 assert((VT == MVT::i16 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
14850 "Unexpected custom legalisation");
14851 assert(((
N->getOpcode() == RISCVISD::BREV8 && Subtarget.hasStdExtZbkb()) ||
14852 (
N->getOpcode() == RISCVISD::ORC_B && Subtarget.hasStdExtZbb())) &&
14853 "Unexpected extension");
14879 assert(!Subtarget.is64Bit() &&
N->getValueType(0) == MVT::i64 &&
14881 "Unexpected EXTRACT_VECTOR_ELT legalization");
14884 MVT ContainerVT = VecVT;
14890 MVT XLenVT = Subtarget.getXLenVT();
14899 DAG.
getUNDEF(ContainerVT), Vec, Idx, Mask, VL);
14911 DAG.
getNode(RISCVISD::SRL_VL,
DL, ContainerVT, Vec, ThirtyTwoV,
14912 DAG.
getUNDEF(ContainerVT), Mask, VL);
14920 unsigned IntNo =
N->getConstantOperandVal(0);
14924 "Don't know how to custom type legalize this intrinsic!");
14925 case Intrinsic::experimental_get_vector_length: {
14930 case Intrinsic::experimental_cttz_elts: {
14936 case Intrinsic::riscv_orc_b:
14937 case Intrinsic::riscv_brev8:
14938 case Intrinsic::riscv_sha256sig0:
14939 case Intrinsic::riscv_sha256sig1:
14940 case Intrinsic::riscv_sha256sum0:
14941 case Intrinsic::riscv_sha256sum1:
14942 case Intrinsic::riscv_sm3p0:
14943 case Intrinsic::riscv_sm3p1: {
14944 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
14948 case Intrinsic::riscv_orc_b:
Opc = RISCVISD::ORC_B;
break;
14949 case Intrinsic::riscv_brev8:
Opc = RISCVISD::BREV8;
break;
14950 case Intrinsic::riscv_sha256sig0:
Opc = RISCVISD::SHA256SIG0;
break;
14951 case Intrinsic::riscv_sha256sig1:
Opc = RISCVISD::SHA256SIG1;
break;
14952 case Intrinsic::riscv_sha256sum0:
Opc = RISCVISD::SHA256SUM0;
break;
14953 case Intrinsic::riscv_sha256sum1:
Opc = RISCVISD::SHA256SUM1;
break;
14954 case Intrinsic::riscv_sm3p0:
Opc = RISCVISD::SM3P0;
break;
14955 case Intrinsic::riscv_sm3p1:
Opc = RISCVISD::SM3P1;
break;
14964 case Intrinsic::riscv_sm4ks:
14965 case Intrinsic::riscv_sm4ed: {
14967 IntNo == Intrinsic::riscv_sm4ks ? RISCVISD::SM4KS : RISCVISD::SM4ED;
14973 DAG.
getNode(
Opc,
DL, MVT::i64, NewOp0, NewOp1,
N->getOperand(3));
14977 case Intrinsic::riscv_mopr: {
14978 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
14983 RISCVISD::MOP_R,
DL, MVT::i64, NewOp,
14988 case Intrinsic::riscv_moprr: {
14989 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
14996 RISCVISD::MOP_RR,
DL, MVT::i64, NewOp0, NewOp1,
15001 case Intrinsic::riscv_clmul: {
15002 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15013 case Intrinsic::riscv_clmulh:
15014 case Intrinsic::riscv_clmulr: {
15015 if (!Subtarget.is64Bit() ||
N->getValueType(0) != MVT::i32)
15035 unsigned Opc = IntNo == Intrinsic::riscv_clmulh ? RISCVISD::CLMULH
15036 : RISCVISD::CLMULR;
15043 case Intrinsic::riscv_vmv_x_s: {
15044 EVT VT =
N->getValueType(0);
15045 MVT XLenVT = Subtarget.getXLenVT();
15046 if (VT.
bitsLT(XLenVT)) {
15049 Subtarget.getXLenVT(),
N->getOperand(1));
15054 assert(VT == MVT::i64 && !Subtarget.is64Bit() &&
15055 "Unexpected custom legalization");
15071 SDValue LShr32 = DAG.
getNode(RISCVISD::SRL_VL,
DL, VecVT, Vec, ThirtyTwoV,
15082 case ISD::VECREDUCE_ADD:
15083 case ISD::VECREDUCE_AND:
15084 case ISD::VECREDUCE_OR:
15085 case ISD::VECREDUCE_XOR:
15086 case ISD::VECREDUCE_SMAX:
15087 case ISD::VECREDUCE_UMAX:
15088 case ISD::VECREDUCE_SMIN:
15089 case ISD::VECREDUCE_UMIN:
15093 case ISD::VP_REDUCE_ADD:
15094 case ISD::VP_REDUCE_AND:
15095 case ISD::VP_REDUCE_OR:
15096 case ISD::VP_REDUCE_XOR:
15097 case ISD::VP_REDUCE_SMAX:
15098 case ISD::VP_REDUCE_UMAX:
15099 case ISD::VP_REDUCE_SMIN:
15100 case ISD::VP_REDUCE_UMIN:
15121 return ISD::VECREDUCE_ADD;
15123 return ISD::VECREDUCE_UMAX;
15125 return ISD::VECREDUCE_SMAX;
15127 return ISD::VECREDUCE_UMIN;
15129 return ISD::VECREDUCE_SMIN;
15131 return ISD::VECREDUCE_AND;
15133 return ISD::VECREDUCE_OR;
15135 return ISD::VECREDUCE_XOR;
15138 return ISD::VECREDUCE_FADD;
15164 const EVT VT =
N->getValueType(0);
15165 const unsigned Opc =
N->getOpcode();
15172 (
Opc !=
ISD::FADD || !
N->getFlags().hasAllowReassociation()))
15177 "Inconsistent mappings");
15181 if (!
LHS.hasOneUse() || !
RHS.hasOneUse())
15209 if (0 == std::min(LHSIdx, RHSIdx) && 1 == std::max(LHSIdx, RHSIdx)) {
15212 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
N->getFlags());
15219 if (
LHS.getOpcode() != ReduceOpc)
15233 return DAG.
getNode(ReduceOpc,
DL, VT, Vec,
15234 ReduceVec->
getFlags() &
N->getFlags());
15244 auto BinOpToRVVReduce = [](
unsigned Opc) {
15249 return RISCVISD::VECREDUCE_ADD_VL;
15251 return RISCVISD::VECREDUCE_UMAX_VL;
15253 return RISCVISD::VECREDUCE_SMAX_VL;
15255 return RISCVISD::VECREDUCE_UMIN_VL;
15257 return RISCVISD::VECREDUCE_SMIN_VL;
15259 return RISCVISD::VECREDUCE_AND_VL;
15261 return RISCVISD::VECREDUCE_OR_VL;
15263 return RISCVISD::VECREDUCE_XOR_VL;
15265 return RISCVISD::VECREDUCE_FADD_VL;
15267 return RISCVISD::VECREDUCE_FMAX_VL;
15269 return RISCVISD::VECREDUCE_FMIN_VL;
15273 auto IsReduction = [&BinOpToRVVReduce](
SDValue V,
unsigned Opc) {
15276 V.getOperand(0).getOpcode() == BinOpToRVVReduce(
Opc);
15279 unsigned Opc =
N->getOpcode();
15280 unsigned ReduceIdx;
15281 if (IsReduction(
N->getOperand(0),
Opc))
15283 else if (IsReduction(
N->getOperand(1),
Opc))
15289 if (
Opc ==
ISD::FADD && !
N->getFlags().hasAllowReassociation())
15292 SDValue Extract =
N->getOperand(ReduceIdx);
15305 if (ScalarV.
getOpcode() != RISCVISD::VFMV_S_F_VL &&
15306 ScalarV.
getOpcode() != RISCVISD::VMV_S_X_VL &&
15307 ScalarV.
getOpcode() != RISCVISD::VMV_V_X_VL)
15324 SDValue NewStart =
N->getOperand(1 - ReduceIdx);
15351 const bool HasStdExtZba = Subtarget.hasStdExtZba();
15352 const bool HasVendorXAndesPerf = Subtarget.hasVendorXAndesPerf();
15353 const bool HasVendorXqciac = Subtarget.hasVendorXqciac();
15355 if (!HasStdExtZba && !HasVendorXAndesPerf && !HasVendorXqciac)
15359 EVT VT =
N->getValueType(0);
15375 int64_t C0 = N0C->getSExtValue();
15376 int64_t C1 = N1C->getSExtValue();
15377 if (C0 <= 0 || C1 <= 0)
15380 int64_t Diff = std::abs(C0 - C1);
15381 bool IsShXaddDiff = Diff == 1 || Diff == 2 || Diff == 3;
15382 bool HasShXadd = HasStdExtZba || HasVendorXAndesPerf;
15385 if ((!IsShXaddDiff && HasShXadd && !HasVendorXqciac) ||
15386 (IsShXaddDiff && !HasShXadd && HasVendorXqciac))
15390 if (Diff == 0 || Diff > 31)
15395 int64_t Bits = std::min(C0, C1);
15427 if (VShift.
slt(1) || VShift.
sgt(3))
15431 EVT VT =
N->getValueType(0);
15451 EVT VT =
N->getValueType(0);
15479 EVT VT =
N->getValueType(0);
15500 Slct.
getOpcode() != RISCVISD::SELECT_CC) ||
15508 bool SwapSelectOps;
15509 unsigned OpOffset = Slct.
getOpcode() == RISCVISD::SELECT_CC ? 2 : 0;
15514 SwapSelectOps =
false;
15515 NonConstantVal = FalseVal;
15517 SwapSelectOps =
true;
15518 NonConstantVal = TrueVal;
15524 FalseVal = DAG.
getNode(
N->getOpcode(),
SDLoc(
N), VT, OtherOp, NonConstantVal);
15529 if (Slct.
getOpcode() == RISCVISD::SELECT_CC)
15572 EVT VT =
N->getValueType(0);
15587 if (!N0C->hasOneUse())
15589 int64_t C0 = N0C->getSExtValue();
15590 int64_t C1 = N1C->getSExtValue();
15592 if (C0 == -1 || C0 == 0 || C0 == 1 ||
isInt<12>(C1))
15599 }
else if ((C1 / C0 + 1) != 0 &&
isInt<12>(C1 / C0 + 1) &&
15603 }
else if ((C1 / C0 - 1) != 0 &&
isInt<12>(C1 / C0 - 1) &&
15631 EVT VT =
N->getValueType(0);
15662 unsigned OuterExtend =
15666 OuterExtend,
SDLoc(
N), VT,
15674 EVT VT =
N->getValueType(0);
15725 EVT VT =
N->getValueType(0);
15735 APInt ImmValMinus1 = N0C->getAPIntValue() - 1;
15745 if (!isIntEqualitySetCC(CCVal) || !SetCCOpVT.
isInteger())
15768 if (!Subtarget.hasStdExtZbb())
15771 EVT VT =
N->getValueType(0);
15773 if (VT != Subtarget.
getXLenVT() && VT != MVT::i32 && VT != MVT::i16)
15785 unsigned ShiftedAmount = 8 - ShAmtCLeft->getZExtValue();
15787 if (ShiftedAmount >= 8)
15791 SDValue RightShiftOperand = N1;
15793 if (ShiftedAmount != 0) {
15797 if (!ShAmtCRight || ShAmtCRight->getZExtValue() != ShiftedAmount)
15806 if (LeftShiftOperand != RightShiftOperand)
15810 Mask <<= ShiftedAmount;
15816 return DAG.
getNode(RISCVISD::ORC_B,
SDLoc(
N), VT, LeftShiftOperand);
15824 EVT VT =
N->getValueType(0);
15855 bool IsAnd =
N->getOpcode() ==
ISD::AND;
15879 EVT VT =
N->getValueType(0);
15903 EVT VT =
N->getValueType(0);
15930 if (CondLHS != True)
15937 if (!CondRHSC || CondRHSC->
getAPIntValue() != (1ULL << ScalarBits))
15949 if (!FalseRHSC || !FalseRHSC->
isZero())
15969 EVT VT =
N->getValueType(0);
15976 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() && VT == MVT::i1 &&
16019 EVT VT =
N->getValueType(0);
16038 EVT WideVT =
X.getValueType();
16060 if (N0.
getOpcode() != ISD::ATOMIC_LOAD)
16075 if (Mask != ExpectedMask)
16101 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
16139 if (N0.
getOpcode() != RISCVISD::CZERO_EQZ ||
16140 N1.
getOpcode() != RISCVISD::CZERO_NEZ ||
16158 EVT VT =
N->getValueType(0);
16176 if (!Subtarget.hasVendorXqcibm())
16189 if (
N->getValueType(0) != MVT::i32)
16192 unsigned Width, ShAmt;
16209 return DAG.
getNode(RISCVISD::QC_INSB,
DL, MVT::i32,
Ops);
16247 if (Subtarget.
is64Bit() && Subtarget.hasStdExtZbs() &&
16262 if (N0.
getOpcode() == RISCVISD::SLLW &&
16266 return DAG.
getNode(RISCVISD::ROLW,
DL, MVT::i64,
16277 const APInt &Imm = ConstN00->getAPIntValue();
16278 if ((Imm + 1).isSignedIntN(12))
16302 EVT VT =
N->getValueType(0);
16311 bool IsAdd = (
E & 3) == 1;
16312 E -= IsAdd ? 1 : -1;
16316 Result = DAG.
getNode(AddSubOp,
DL, VT, Result, ShiftVal);
16326 uint64_t MulAmtLowBit = MulAmt & (-MulAmt);
16331 ShiftAmt1 = MulAmt + MulAmtLowBit;
16334 ShiftAmt1 = MulAmt - MulAmtLowBit;
16338 EVT VT =
N->getValueType(0);
16352 EVT VT =
N->getValueType(0);
16361 bool ShouldExpandMul =
16363 !Subtarget.hasStdExtZmmul();
16364 if (!ShouldExpandMul)
16376 const bool HasShlAdd = Subtarget.hasStdExtZba() ||
16377 Subtarget.hasVendorXTHeadBa() ||
16378 Subtarget.hasVendorXAndesPerf();
16387 for (
uint64_t Divisor : {3, 5, 9}) {
16388 if (MulAmt % Divisor != 0)
16390 uint64_t MulAmt2 = MulAmt / Divisor;
16398 X.getConstantOperandVal(1) == UINT64_C(0xffffffff)) {
16401 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, Shl,
16415 if (MulAmt2 == 3 || MulAmt2 == 5 || MulAmt2 == 9) {
16420 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, Mul359,
16431 if (ScaleShift >= 1 && ScaleShift < 4) {
16432 unsigned ShiftAmt =
Log2_64((MulAmt & (MulAmt - 1)));
16436 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT,
X,
16446 for (
uint64_t Divisor : {3, 5, 9}) {
16451 if ((
C >> TZ) == Divisor && (TZ == 1 || TZ == 2 || TZ == 3)) {
16456 return DAG.
getNode(RISCVISD::SHL_ADD,
DL, VT, Mul359,
16462 if (MulAmt > 2 &&
isPowerOf2_64((MulAmt - 1) & (MulAmt - 2))) {
16464 if (ScaleShift >= 1 && ScaleShift < 4) {
16465 unsigned ShiftAmt =
Log2_64(((MulAmt - 1) & (MulAmt - 2)));
16491 for (
uint64_t Divisor : {3, 5, 9}) {
16492 if (MulAmt % Divisor != 0)
16494 uint64_t MulAmt2 = MulAmt / Divisor;
16497 for (
uint64_t Divisor2 : {3, 5, 9}) {
16498 if (MulAmt2 % Divisor2 != 0)
16500 uint64_t MulAmt3 = MulAmt2 / Divisor2;
16507 RISCVISD::SHL_ADD,
DL, VT, Mul359A,
16519 if (!Subtarget.hasStdExtZmmul())
16529 EVT VT =
N->getValueType(0);
16536 if (
N->getOperand(0).getOpcode() !=
ISD::AND ||
16537 N->getOperand(0).getOperand(0).getOpcode() !=
ISD::SRL)
16550 if (!V1.
isMask(HalfSize) || V2 != (1ULL | 1ULL << HalfSize) ||
16551 V3 != (HalfSize - 1))
16561 return DAG.
getNode(ISD::BITCAST,
DL, VT, Sra);
16567 EVT VT =
N->getValueType(0);
16575 unsigned AddSubOpc;
16581 auto IsAddSubWith1 = [&](
SDValue V) ->
bool {
16582 AddSubOpc = V->getOpcode();
16594 if (IsAddSubWith1(N0)) {
16596 return DAG.
getNode(AddSubOpc,
DL, VT, N1, MulVal);
16599 if (IsAddSubWith1(N1)) {
16601 return DAG.
getNode(AddSubOpc,
DL, VT, N0, MulVal);
16616 if (isIndexTypeSigned(IndexType))
16619 if (!
N->hasOneUse())
16622 EVT VT =
N.getValueType();
16661 EVT SrcVT = Src.getValueType();
16665 NewElen = std::max(NewElen, 8U);
16692 EVT OpVT =
X.getValueType();
16700 if (OpSize <= Subtarget.
getXLen() ||
16706 auto IsVectorBitCastCheap = [](
SDValue X) {
16709 X.getOpcode() == ISD::LOAD;
16711 if (!IsVectorBitCastCheap(
X) || !IsVectorBitCastCheap(
Y))
16715 Attribute::NoImplicitFloat))
16722 unsigned VecSize = OpSize / 8;
16734 DAG.
getNode(ISD::VP_REDUCE_OR,
DL, XLenVT,
16747 EVT VT =
N->getValueType(0);
16752 if (!isIntEqualitySetCC(
Cond))
16777 if (OpVT == MVT::i64 && AndRHSInt <= 0xffffffff &&
16781 if (NewC >= -2048 && NewC <= 2048) {
16787 return DAG.
getSetCC(dl, VT, Shift,
16797 if (OpVT != MVT::i64 || !Subtarget.
is64Bit())
16817 const APInt &C1 = N1C->getAPIntValue();
16835 EVT VT =
N->getValueType(0);
16837 unsigned Opc = Src.getOpcode();
16842 if (
Opc == RISCVISD::FMV_X_ANYEXTH && SrcVT.
bitsGE(MVT::i16) &&
16843 Subtarget.hasStdExtZfhmin())
16844 return DAG.
getNode(RISCVISD::FMV_X_SIGNEXTH,
DL, VT, Src.getOperand(0));
16850 return DAG.
getNode(RISCVISD::SLLW,
DL, VT, Src.getOperand(0),
16851 Src.getOperand(1));
16870struct CombineResult;
16872enum ExtKind : uint8_t {
16904struct NodeExtensionHelper {
16913 bool SupportsFPExt;
16915 bool SupportsBF16Ext;
16918 bool EnforceOneUse;
16928 case RISCVISD::VSEXT_VL:
16929 case RISCVISD::VZEXT_VL:
16930 case RISCVISD::FP_EXTEND_VL:
16933 return OrigOperand;
16939 return OrigOperand.
getOpcode() == RISCVISD::VMV_V_X_VL ||
16944 unsigned getExtOpc(ExtKind SupportsExt)
const {
16945 switch (SupportsExt) {
16946 case ExtKind::SExt:
16947 return RISCVISD::VSEXT_VL;
16948 case ExtKind::ZExt:
16949 return RISCVISD::VZEXT_VL;
16950 case ExtKind::FPExt:
16951 case ExtKind::BF16Ext:
16952 return RISCVISD::FP_EXTEND_VL;
16960 SDValue getOrCreateExtendedOp(SDNode *Root, SelectionDAG &DAG,
16961 const RISCVSubtarget &Subtarget,
16962 std::optional<ExtKind> SupportsExt)
const {
16963 if (!SupportsExt.has_value())
16964 return OrigOperand;
16966 MVT NarrowVT = getNarrowType(Root, *SupportsExt);
16970 if (
Source.getValueType() == NarrowVT)
16973 unsigned ExtOpc = getExtOpc(*SupportsExt);
16976 SDLoc
DL(OrigOperand);
16977 auto [
Mask, VL] = getMaskAndVL(Root, DAG, Subtarget);
16981 case RISCVISD::VSEXT_VL:
16982 case RISCVISD::VZEXT_VL:
16983 case RISCVISD::FP_EXTEND_VL:
16984 return DAG.
getNode(ExtOpc,
DL, NarrowVT, Source, Mask, VL);
16987 case RISCVISD::VMV_V_X_VL:
16988 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, NarrowVT,
16990 case RISCVISD::VFMV_V_F_VL:
16992 assert(
Source.getOpcode() == ISD::FP_EXTEND &&
"Unexpected source");
16995 return DAG.
getNode(RISCVISD::VFMV_V_F_VL,
DL, NarrowVT,
16996 DAG.
getUNDEF(NarrowVT), Source, VL);
17009 static MVT getNarrowType(
const SDNode *Root, ExtKind SupportsExt) {
17015 MVT EltVT = SupportsExt == ExtKind::BF16Ext ? MVT::bf16
17016 : SupportsExt == ExtKind::FPExt
17018 : MVT::getIntegerVT(NarrowSize);
17020 assert((
int)NarrowSize >= (SupportsExt == ExtKind::FPExt ? 16 : 8) &&
17021 "Trying to extend something we can't represent");
17028 static unsigned getSExtOpcode(
unsigned Opcode) {
17031 case RISCVISD::ADD_VL:
17032 case RISCVISD::VWADD_W_VL:
17033 case RISCVISD::VWADDU_W_VL:
17035 case RISCVISD::OR_VL:
17036 return RISCVISD::VWADD_VL;
17038 case RISCVISD::SUB_VL:
17039 case RISCVISD::VWSUB_W_VL:
17040 case RISCVISD::VWSUBU_W_VL:
17041 return RISCVISD::VWSUB_VL;
17043 case RISCVISD::MUL_VL:
17044 return RISCVISD::VWMUL_VL;
17052 static unsigned getZExtOpcode(
unsigned Opcode) {
17055 case RISCVISD::ADD_VL:
17056 case RISCVISD::VWADD_W_VL:
17057 case RISCVISD::VWADDU_W_VL:
17059 case RISCVISD::OR_VL:
17060 return RISCVISD::VWADDU_VL;
17062 case RISCVISD::SUB_VL:
17063 case RISCVISD::VWSUB_W_VL:
17064 case RISCVISD::VWSUBU_W_VL:
17065 return RISCVISD::VWSUBU_VL;
17067 case RISCVISD::MUL_VL:
17068 return RISCVISD::VWMULU_VL;
17070 case RISCVISD::SHL_VL:
17071 return RISCVISD::VWSLL_VL;
17079 static unsigned getFPExtOpcode(
unsigned Opcode) {
17081 case RISCVISD::FADD_VL:
17082 case RISCVISD::VFWADD_W_VL:
17083 return RISCVISD::VFWADD_VL;
17084 case RISCVISD::FSUB_VL:
17085 case RISCVISD::VFWSUB_W_VL:
17086 return RISCVISD::VFWSUB_VL;
17087 case RISCVISD::FMUL_VL:
17088 return RISCVISD::VFWMUL_VL;
17089 case RISCVISD::VFMADD_VL:
17090 return RISCVISD::VFWMADD_VL;
17091 case RISCVISD::VFMSUB_VL:
17092 return RISCVISD::VFWMSUB_VL;
17093 case RISCVISD::VFNMADD_VL:
17094 return RISCVISD::VFWNMADD_VL;
17095 case RISCVISD::VFNMSUB_VL:
17096 return RISCVISD::VFWNMSUB_VL;
17104 static unsigned getSUOpcode(
unsigned Opcode) {
17106 "SU is only supported for MUL");
17107 return RISCVISD::VWMULSU_VL;
17112 static unsigned getWOpcode(
unsigned Opcode, ExtKind SupportsExt) {
17115 case RISCVISD::ADD_VL:
17117 case RISCVISD::OR_VL:
17118 return SupportsExt == ExtKind::SExt ? RISCVISD::VWADD_W_VL
17119 : RISCVISD::VWADDU_W_VL;
17121 case RISCVISD::SUB_VL:
17122 return SupportsExt == ExtKind::SExt ? RISCVISD::VWSUB_W_VL
17123 : RISCVISD::VWSUBU_W_VL;
17124 case RISCVISD::FADD_VL:
17125 return RISCVISD::VFWADD_W_VL;
17126 case RISCVISD::FSUB_VL:
17127 return RISCVISD::VFWSUB_W_VL;
17133 using CombineToTry = std::function<std::optional<CombineResult>(
17134 SDNode * ,
const NodeExtensionHelper & ,
17135 const NodeExtensionHelper & , SelectionDAG &,
17136 const RISCVSubtarget &)>;
17139 bool needToPromoteOtherUsers()
const {
return EnforceOneUse; }
17141 void fillUpExtensionSupportForSplat(SDNode *Root, SelectionDAG &DAG,
17142 const RISCVSubtarget &Subtarget) {
17147 "Unexpected Opcode");
17160 unsigned ScalarBits =
Op.getValueSizeInBits();
17162 if (ScalarBits < EltBits) {
17164 assert(
Opc == RISCVISD::VMV_V_X_VL && EltBits == 64 && ScalarBits == 32 &&
17165 !Subtarget.
is64Bit() &&
"Unexpected splat");
17167 SupportsSExt =
true;
17171 SupportsZExt =
true;
17173 EnforceOneUse =
false;
17177 unsigned NarrowSize = EltBits / 2;
17180 if (NarrowSize < 8)
17184 SupportsSExt =
true;
17188 SupportsZExt =
true;
17190 EnforceOneUse =
false;
17193 bool isSupportedFPExtend(MVT NarrowEltVT,
const RISCVSubtarget &Subtarget) {
17194 return (NarrowEltVT == MVT::f32 ||
17198 bool isSupportedBF16Extend(MVT NarrowEltVT,
const RISCVSubtarget &Subtarget) {
17199 return NarrowEltVT == MVT::bf16 && Subtarget.hasStdExtZvfbfwma();
17204 void fillUpExtensionSupport(SDNode *Root, SelectionDAG &DAG,
17205 const RISCVSubtarget &Subtarget) {
17206 SupportsZExt =
false;
17207 SupportsSExt =
false;
17208 SupportsFPExt =
false;
17209 SupportsBF16Ext =
false;
17210 EnforceOneUse =
true;
17232 case RISCVISD::VZEXT_VL:
17233 SupportsZExt =
true;
17235 case RISCVISD::VSEXT_VL:
17236 SupportsSExt =
true;
17238 case RISCVISD::FP_EXTEND_VL: {
17241 if (isSupportedFPExtend(NarrowEltVT, Subtarget))
17242 SupportsFPExt =
true;
17243 if (isSupportedBF16Extend(NarrowEltVT, Subtarget))
17244 SupportsBF16Ext =
true;
17249 case RISCVISD::VMV_V_X_VL:
17250 fillUpExtensionSupportForSplat(Root, DAG, Subtarget);
17252 case RISCVISD::VFMV_V_F_VL: {
17259 if (
Op.getOpcode() != ISD::FP_EXTEND)
17263 unsigned ScalarBits =
Op.getOperand(0).getValueSizeInBits();
17264 if (NarrowSize != ScalarBits)
17267 if (isSupportedFPExtend(
Op.getOperand(0).getSimpleValueType(), Subtarget))
17268 SupportsFPExt =
true;
17269 if (isSupportedBF16Extend(
Op.getOperand(0).getSimpleValueType(),
17271 SupportsBF16Ext =
true;
17280 static bool isSupportedRoot(
const SDNode *Root,
17281 const RISCVSubtarget &Subtarget) {
17293 case RISCVISD::ADD_VL:
17294 case RISCVISD::MUL_VL:
17295 case RISCVISD::VWADD_W_VL:
17296 case RISCVISD::VWADDU_W_VL:
17297 case RISCVISD::SUB_VL:
17298 case RISCVISD::VWSUB_W_VL:
17299 case RISCVISD::VWSUBU_W_VL:
17301 case RISCVISD::FADD_VL:
17302 case RISCVISD::FSUB_VL:
17303 case RISCVISD::FMUL_VL:
17304 case RISCVISD::VFWADD_W_VL:
17305 case RISCVISD::VFWSUB_W_VL:
17307 case RISCVISD::OR_VL:
17311 Subtarget.hasStdExtZvbb();
17312 case RISCVISD::SHL_VL:
17313 return Subtarget.hasStdExtZvbb();
17314 case RISCVISD::VFMADD_VL:
17315 case RISCVISD::VFNMSUB_VL:
17316 case RISCVISD::VFNMADD_VL:
17317 case RISCVISD::VFMSUB_VL:
17325 NodeExtensionHelper(SDNode *Root,
unsigned OperandIdx, SelectionDAG &DAG,
17326 const RISCVSubtarget &Subtarget) {
17327 assert(isSupportedRoot(Root, Subtarget) &&
17328 "Trying to build an helper with an "
17329 "unsupported root");
17330 assert(OperandIdx < 2 &&
"Requesting something else than LHS or RHS");
17340 case RISCVISD::VWADD_W_VL:
17341 case RISCVISD::VWADDU_W_VL:
17342 case RISCVISD::VWSUB_W_VL:
17343 case RISCVISD::VWSUBU_W_VL:
17344 case RISCVISD::VFWADD_W_VL:
17345 case RISCVISD::VFWSUB_W_VL:
17346 if (OperandIdx == 1) {
17348 Opc == RISCVISD::VWADDU_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL;
17350 Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWSUB_W_VL;
17352 Opc == RISCVISD::VFWADD_W_VL ||
Opc == RISCVISD::VFWSUB_W_VL;
17355 EnforceOneUse =
false;
17360 fillUpExtensionSupport(Root, DAG, Subtarget);
17366 static std::pair<SDValue, SDValue>
17367 getMaskAndVL(
const SDNode *Root, SelectionDAG &DAG,
17368 const RISCVSubtarget &Subtarget) {
17369 assert(isSupportedRoot(Root, Subtarget) &&
"Unexpected root");
17388 switch (
N->getOpcode()) {
17392 case RISCVISD::ADD_VL:
17393 case RISCVISD::MUL_VL:
17394 case RISCVISD::OR_VL:
17395 case RISCVISD::VWADD_W_VL:
17396 case RISCVISD::VWADDU_W_VL:
17397 case RISCVISD::FADD_VL:
17398 case RISCVISD::FMUL_VL:
17399 case RISCVISD::VFWADD_W_VL:
17400 case RISCVISD::VFMADD_VL:
17401 case RISCVISD::VFNMSUB_VL:
17402 case RISCVISD::VFNMADD_VL:
17403 case RISCVISD::VFMSUB_VL:
17406 case RISCVISD::SUB_VL:
17407 case RISCVISD::VWSUB_W_VL:
17408 case RISCVISD::VWSUBU_W_VL:
17409 case RISCVISD::FSUB_VL:
17410 case RISCVISD::VFWSUB_W_VL:
17412 case RISCVISD::SHL_VL:
17431struct CombineResult {
17433 unsigned TargetOpcode;
17435 std::optional<ExtKind> LHSExt;
17436 std::optional<ExtKind> RHSExt;
17440 NodeExtensionHelper
LHS;
17442 NodeExtensionHelper
RHS;
17444 CombineResult(
unsigned TargetOpcode, SDNode *Root,
17445 const NodeExtensionHelper &
LHS, std::optional<ExtKind> LHSExt,
17446 const NodeExtensionHelper &
RHS, std::optional<ExtKind> RHSExt)
17447 : TargetOpcode(TargetOpcode), LHSExt(LHSExt), RHSExt(RHSExt), Root(Root),
17453 SDValue materialize(SelectionDAG &DAG,
17454 const RISCVSubtarget &Subtarget)
const {
17456 std::tie(Mask, VL) =
17457 NodeExtensionHelper::getMaskAndVL(Root, DAG, Subtarget);
17471 LHS.getOrCreateExtendedOp(Root, DAG, Subtarget, LHSExt),
17472 RHS.getOrCreateExtendedOp(Root, DAG, Subtarget, RHSExt),
17473 Passthru, Mask, VL);
17487static std::optional<CombineResult>
17488canFoldToVWWithSameExtensionImpl(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17489 const NodeExtensionHelper &
RHS,
17492 if ((AllowExtMask & ExtKind::ZExt) &&
LHS.SupportsZExt &&
RHS.SupportsZExt)
17493 return CombineResult(NodeExtensionHelper::getZExtOpcode(Root->
getOpcode()),
17494 Root,
LHS, {ExtKind::ZExt},
RHS,
17496 if ((AllowExtMask & ExtKind::SExt) &&
LHS.SupportsSExt &&
RHS.SupportsSExt)
17497 return CombineResult(NodeExtensionHelper::getSExtOpcode(Root->
getOpcode()),
17498 Root,
LHS, {ExtKind::SExt},
RHS,
17500 if ((AllowExtMask & ExtKind::FPExt) &&
LHS.SupportsFPExt &&
RHS.SupportsFPExt)
17501 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
17502 Root,
LHS, {ExtKind::FPExt},
RHS,
17504 if ((AllowExtMask & ExtKind::BF16Ext) &&
LHS.SupportsBF16Ext &&
17505 RHS.SupportsBF16Ext)
17506 return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->
getOpcode()),
17507 Root,
LHS, {ExtKind::BF16Ext},
RHS,
17508 {ExtKind::BF16Ext});
17509 return std::nullopt;
17518static std::optional<CombineResult>
17519canFoldToVWWithSameExtension(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17522 return canFoldToVWWithSameExtensionImpl(
17523 Root,
LHS,
RHS, ExtKind::ZExt | ExtKind::SExt | ExtKind::FPExt, DAG,
17531static std::optional<CombineResult>
17532canFoldToVW_W(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17535 if (
RHS.SupportsFPExt)
17536 return CombineResult(
17537 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::FPExt),
17538 Root,
LHS, std::nullopt,
RHS, {ExtKind::FPExt});
17545 return CombineResult(
17546 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::ZExt), Root,
17547 LHS, std::nullopt,
RHS, {ExtKind::ZExt});
17549 return CombineResult(
17550 NodeExtensionHelper::getWOpcode(Root->
getOpcode(), ExtKind::SExt), Root,
17551 LHS, std::nullopt,
RHS, {ExtKind::SExt});
17552 return std::nullopt;
17559static std::optional<CombineResult>
17560canFoldToVWWithSEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17563 return canFoldToVWWithSameExtensionImpl(Root,
LHS,
RHS, ExtKind::SExt, DAG,
17571static std::optional<CombineResult>
17572canFoldToVWWithZEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17575 return canFoldToVWWithSameExtensionImpl(Root,
LHS,
RHS, ExtKind::ZExt, DAG,
17583static std::optional<CombineResult>
17584canFoldToVWWithFPEXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17587 return canFoldToVWWithSameExtensionImpl(Root,
LHS,
RHS, ExtKind::FPExt, DAG,
17595static std::optional<CombineResult>
17596canFoldToVWWithBF16EXT(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17599 return canFoldToVWWithSameExtensionImpl(Root,
LHS,
RHS, ExtKind::BF16Ext, DAG,
17607static std::optional<CombineResult>
17608canFoldToVW_SU(
SDNode *Root,
const NodeExtensionHelper &
LHS,
17612 if (!
LHS.SupportsSExt || !
RHS.SupportsZExt)
17613 return std::nullopt;
17614 return CombineResult(NodeExtensionHelper::getSUOpcode(Root->
getOpcode()),
17615 Root,
LHS, {ExtKind::SExt},
RHS,
17620NodeExtensionHelper::getSupportedFoldings(
const SDNode *Root) {
17626 case RISCVISD::ADD_VL:
17627 case RISCVISD::SUB_VL:
17628 case RISCVISD::OR_VL:
17629 case RISCVISD::FADD_VL:
17630 case RISCVISD::FSUB_VL:
17632 Strategies.
push_back(canFoldToVWWithSameExtension);
17636 case RISCVISD::FMUL_VL:
17637 case RISCVISD::VFMADD_VL:
17638 case RISCVISD::VFMSUB_VL:
17639 case RISCVISD::VFNMADD_VL:
17640 case RISCVISD::VFNMSUB_VL:
17641 Strategies.
push_back(canFoldToVWWithSameExtension);
17642 if (Root->
getOpcode() == RISCVISD::VFMADD_VL)
17643 Strategies.
push_back(canFoldToVWWithBF16EXT);
17646 case RISCVISD::MUL_VL:
17648 Strategies.
push_back(canFoldToVWWithSameExtension);
17653 case RISCVISD::SHL_VL:
17655 Strategies.
push_back(canFoldToVWWithZEXT);
17657 case RISCVISD::VWADD_W_VL:
17658 case RISCVISD::VWSUB_W_VL:
17660 Strategies.
push_back(canFoldToVWWithSEXT);
17662 case RISCVISD::VWADDU_W_VL:
17663 case RISCVISD::VWSUBU_W_VL:
17665 Strategies.
push_back(canFoldToVWWithZEXT);
17667 case RISCVISD::VFWADD_W_VL:
17668 case RISCVISD::VFWSUB_W_VL:
17670 Strategies.
push_back(canFoldToVWWithFPEXT);
17681 assert(
N->getOpcode() == RISCVISD::ADD_VL);
17684 SDValue Passthru =
N->getOperand(2);
17718 if (!NodeExtensionHelper::isSupportedRoot(
N, Subtarget))
17724 Inserted.insert(
N);
17727 while (!Worklist.
empty()) {
17730 NodeExtensionHelper
LHS(Root, 0, DAG, Subtarget);
17731 NodeExtensionHelper
RHS(Root, 1, DAG, Subtarget);
17732 auto AppendUsersIfNeeded = [&Worklist, &Subtarget,
17733 &Inserted](
const NodeExtensionHelper &
Op) {
17734 if (
Op.needToPromoteOtherUsers()) {
17737 if (!NodeExtensionHelper::isSupportedRoot(TheUser, Subtarget))
17742 if (Inserted.insert(TheUser).second)
17755 NodeExtensionHelper::getSupportedFoldings(Root);
17757 assert(!FoldingStrategies.
empty() &&
"Nothing to be folded");
17758 bool Matched =
false;
17759 for (
int Attempt = 0;
17760 (Attempt != 1 + NodeExtensionHelper::isCommutative(Root)) && !Matched;
17763 for (NodeExtensionHelper::CombineToTry FoldingStrategy :
17764 FoldingStrategies) {
17765 std::optional<CombineResult> Res =
17766 FoldingStrategy(Root,
LHS,
RHS, DAG, Subtarget);
17773 if (Res->LHSExt.has_value())
17774 if (!AppendUsersIfNeeded(
LHS))
17776 if (Res->RHSExt.has_value())
17777 if (!AppendUsersIfNeeded(
RHS))
17789 SDValue InputRootReplacement;
17796 for (CombineResult Res : CombinesToApply) {
17797 SDValue NewValue = Res.materialize(DAG, Subtarget);
17798 if (!InputRootReplacement) {
17800 "First element is expected to be the current node");
17801 InputRootReplacement = NewValue;
17806 for (std::pair<SDValue, SDValue> OldNewValues : ValuesToReplace) {
17810 return InputRootReplacement;
17817 unsigned Opc =
N->getOpcode();
17818 assert(
Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWADDU_W_VL ||
17819 Opc == RISCVISD::VWSUB_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL);
17822 SDValue MergeOp =
N->getOperand(1);
17823 unsigned MergeOpc = MergeOp.
getOpcode();
17825 if (MergeOpc != RISCVISD::VMERGE_VL && MergeOpc !=
ISD::VSELECT)
17834 SDValue Passthru =
N->getOperand(2);
17840 if (Mask.getOpcode() != RISCVISD::VMSET_VL)
17848 Z = Z.getOperand(1);
17854 {Y, X, Y, MergeOp->getOperand(0), N->getOperand(4)},
17861 [[maybe_unused]]
unsigned Opc =
N->getOpcode();
17862 assert(
Opc == RISCVISD::VWADD_W_VL ||
Opc == RISCVISD::VWADDU_W_VL ||
17863 Opc == RISCVISD::VWSUB_W_VL ||
Opc == RISCVISD::VWSUBU_W_VL);
17890 EVT NewMemVT = (MemVT == MVT::i32) ? MVT::i64 : MVT::i128;
17895 if (LSNode1->
getOpcode() == ISD::LOAD) {
17898 if (MemVT == MVT::i32)
17899 Opcode = (Ext ==
ISD::ZEXTLOAD) ? RISCVISD::TH_LWUD : RISCVISD::TH_LWD;
17901 Opcode = RISCVISD::TH_LDD;
17904 Opcode,
SDLoc(LSNode1), DAG.
getVTList({XLenVT, XLenVT, MVT::Other}),
17905 {LSNode1->getChain(), BasePtr,
17906 DAG.getConstant(Imm, SDLoc(LSNode1), XLenVT)},
17917 unsigned Opcode = (MemVT == MVT::i32) ? RISCVISD::TH_SWD : RISCVISD::TH_SDD;
17921 {LSNode1->getChain(), LSNode1->getOperand(1), LSNode2->getOperand(1),
17922 BasePtr, DAG.getConstant(Imm, SDLoc(LSNode1), XLenVT)},
17939 if (!Subtarget.hasVendorXTHeadMemPair())
17944 unsigned OpNum = LSNode1->
getOpcode() == ISD::LOAD ? 1 : 2;
17951 auto ExtractBaseAndOffset = [](
SDValue Ptr) -> std::pair<SDValue, uint64_t> {
17954 return {
Ptr->getOperand(0), C1->getZExtValue()};
17958 auto [Base1, Offset1] = ExtractBaseAndOffset(LSNode1->
getOperand(OpNum));
17979 auto [Base2, Offset2] = ExtractBaseAndOffset(LSNode2->
getOperand(OpNum));
17982 if (Base1 != Base2)
17986 bool Valid =
false;
17987 if (MemVT == MVT::i32) {
17991 }
else if (MemVT == MVT::i64) {
18027 if (Src->isStrictFPOpcode())
18035 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
18045 EVT VT =
N->getValueType(0);
18048 MVT SrcVT = Src.getSimpleValueType();
18049 MVT SrcContainerVT = SrcVT;
18077 IsSigned ? RISCVISD::VFCVT_RTZ_X_F_VL : RISCVISD::VFCVT_RTZ_XU_F_VL;
18078 FpToInt = DAG.
getNode(
Opc,
DL, ContainerVT, XVal, Mask, VL);
18081 IsSigned ? RISCVISD::VFCVT_RM_X_F_VL : RISCVISD::VFCVT_RM_XU_F_VL;
18082 FpToInt = DAG.
getNode(
Opc,
DL, ContainerVT, XVal, Mask,
18095 if (VT != MVT::i32 && VT != XLenVT)
18100 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
18102 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
18125 EVT DstVT =
N->getValueType(0);
18126 if (DstVT != XLenVT)
18132 if (Src->isStrictFPOpcode())
18140 if (Src.getValueType() == MVT::f16 && !Subtarget.hasStdExtZfh())
18152 if (SatVT == DstVT)
18153 Opc = IsSigned ? RISCVISD::FCVT_X : RISCVISD::FCVT_XU;
18154 else if (DstVT == MVT::i64 && SatVT == MVT::i32)
18155 Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
18160 Src = Src.getOperand(0);
18168 if (
Opc == RISCVISD::FCVT_WU_RV64)
18181 assert(Subtarget.hasStdExtZbkb() &&
"Unexpected extension");
18187 EVT VT =
N->getValueType(0);
18193 return DAG.
getNode(RISCVISD::BREV8,
DL, VT, Src.getOperand(0));
18206 EVT LoadVT = VPLoad->getValueType(0);
18210 N->getOperand(2) != VPLoad->getVectorLength() ||
18211 !
N->getOperand(0).hasOneUse())
18218 SDValue LoadMask = VPLoad->getMask();
18223 if (LoadMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
18225 LoadMask.
getOperand(2) != VPLoad->getVectorLength())
18233 SDValue NumElem = VPLoad->getVectorLength();
18234 uint64_t ElemWidthByte = VPLoad->getValueType(0).getScalarSizeInBits() / 8;
18246 PtrInfo, VPLoad->getMemOperand()->getFlags(),
18250 LoadVT,
DL, VPLoad->getChain(),
Base, Stride, LoadMask,
18251 VPLoad->getVectorLength(), MMO, VPLoad->isExpandingLoad());
18265 if (VPStore->getValue().getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE)
18268 SDValue VPReverse = VPStore->getValue();
18274 VPStore->getVectorLength() != VPReverse.
getOperand(2) ||
18278 SDValue StoreMask = VPStore->getMask();
18283 if (StoreMask.
getOpcode() != ISD::EXPERIMENTAL_VP_REVERSE ||
18285 StoreMask.
getOperand(2) != VPStore->getVectorLength())
18293 SDValue NumElem = VPStore->getVectorLength();
18307 PtrInfo, VPStore->getMemOperand()->getFlags(),
18312 VPStore->getOffset(), Stride, StoreMask, VPStore->getVectorLength(),
18313 VPStore->getMemoryVT(), MMO, VPStore->getAddressingMode(),
18314 VPStore->isTruncatingStore(), VPStore->isCompressingStore());
18326 EVT VT =
N->getValueType(0);
18338 if (In.getOpcode() != ISD::VP_SRL || In.getOperand(2) != Mask ||
18339 In.getOperand(3) != VL)
18348 if (
LHS.getOpcode() != ISD::VP_ADD ||
LHS.getOperand(2) != Mask ||
18349 LHS.getOperand(3) != VL)
18356 if (V.getOpcode() != ISD::VP_ADD || V.getOperand(2) != Mask ||
18357 V.getOperand(3) != VL)
18369 if (!FindAdd(LHS0, LHS1) && !FindAdd(LHS1, LHS0))
18383 if (
Op.getOpcode() != ISD::VP_ZERO_EXTEND ||
Op.getOperand(1) != Mask ||
18384 Op.getOperand(2) != VL)
18394 Operands[0].getOperand(0), Mask, VL);
18396 Operands[1].getOperand(0), Mask, VL);
18400 return DAG.
getNode(RISCVISD::AVGCEILU_VL,
DL, VT,
18401 {NewOp0, NewOp1, DAG.
getUNDEF(VT), Mask, VL});
18413 case RISCVISD::VFMADD_VL: Opcode = RISCVISD::VFNMSUB_VL;
break;
18414 case RISCVISD::VFNMSUB_VL: Opcode = RISCVISD::VFMADD_VL;
break;
18415 case RISCVISD::VFNMADD_VL: Opcode = RISCVISD::VFMSUB_VL;
break;
18416 case RISCVISD::VFMSUB_VL: Opcode = RISCVISD::VFNMADD_VL;
break;
18417 case RISCVISD::STRICT_VFMADD_VL: Opcode = RISCVISD::STRICT_VFNMSUB_VL;
break;
18418 case RISCVISD::STRICT_VFNMSUB_VL: Opcode = RISCVISD::STRICT_VFMADD_VL;
break;
18419 case RISCVISD::STRICT_VFNMADD_VL: Opcode = RISCVISD::STRICT_VFMSUB_VL;
break;
18420 case RISCVISD::STRICT_VFMSUB_VL: Opcode = RISCVISD::STRICT_VFNMADD_VL;
break;
18430 case RISCVISD::VFMADD_VL: Opcode = RISCVISD::VFMSUB_VL;
break;
18431 case RISCVISD::VFMSUB_VL: Opcode = RISCVISD::VFMADD_VL;
break;
18432 case RISCVISD::VFNMADD_VL: Opcode = RISCVISD::VFNMSUB_VL;
break;
18433 case RISCVISD::VFNMSUB_VL: Opcode = RISCVISD::VFNMADD_VL;
break;
18434 case RISCVISD::STRICT_VFMADD_VL: Opcode = RISCVISD::STRICT_VFMSUB_VL;
break;
18435 case RISCVISD::STRICT_VFMSUB_VL: Opcode = RISCVISD::STRICT_VFMADD_VL;
break;
18436 case RISCVISD::STRICT_VFNMADD_VL: Opcode = RISCVISD::STRICT_VFNMSUB_VL;
break;
18437 case RISCVISD::STRICT_VFNMSUB_VL: Opcode = RISCVISD::STRICT_VFNMADD_VL;
break;
18450 unsigned Offset = IsStrict ? 1 : 0;
18457 auto invertIfNegative = [&Mask, &VL](
SDValue &V) {
18458 if (V.getOpcode() == RISCVISD::FNEG_VL && V.getOperand(1) == Mask &&
18459 V.getOperand(2) == VL) {
18461 V = V.getOperand(0);
18468 bool NegA = invertIfNegative(
A);
18469 bool NegB = invertIfNegative(
B);
18470 bool NegC = invertIfNegative(
C);
18473 if (!NegA && !NegB && !NegC)
18479 {N->getOperand(0), A, B, C, Mask, VL});
18503 EVT VT =
N->getValueType(0);
18510 uint64_t ShAmt =
N->getConstantOperandVal(1);
18523 if (LShAmt < ExtSize) {
18536 if (ShAmt > 32 || VT != MVT::i64)
18566 U->getConstantOperandVal(1) > 32)
18621 if (!
Cond.hasOneUse())
18640 EVT VT =
Cond.getValueType();
18685 LHS =
LHS.getOperand(0);
18695 LHS.getOperand(0).getValueType() == Subtarget.
getXLenVT()) {
18703 RHS =
LHS.getOperand(1);
18704 LHS =
LHS.getOperand(0);
18713 auto isXorImmediate = [](
const SDValue &
Op) ->
bool {
18715 return isInt<12>(XorCnst->getSExtValue());
18719 auto singleBitOp = [&DAG](
const SDValue &VarOp,
18720 const SDValue &ConstOp) ->
bool {
18723 return (XorCnst->getSExtValue() == 1) &&
18728 auto onlyUsedBySelectOrBR = [](
const SDValue &
Op) ->
bool {
18729 for (
const SDNode *UserNode :
Op->users()) {
18730 const unsigned Opcode = UserNode->getOpcode();
18731 if (Opcode != RISCVISD::SELECT_CC && Opcode != RISCVISD::BR_CC)
18736 auto isFoldableXorEq = [isXorImmediate, singleBitOp, onlyUsedBySelectOrBR](
18739 (!isXorImmediate(
LHS.getOperand(1)) ||
18740 singleBitOp(
LHS.getOperand(0),
LHS.getOperand(1)) ||
18741 onlyUsedBySelectOrBR(
LHS));
18744 if (isFoldableXorEq(
LHS,
RHS)) {
18745 RHS =
LHS.getOperand(1);
18746 LHS =
LHS.getOperand(0);
18772 if (Subtarget.hasVendorXAndesPerf()) {
18782 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
18825 bool Commutative =
true;
18826 unsigned Opc = TrueVal.getOpcode();
18836 Commutative =
false;
18844 if (!TrueVal.hasOneUse())
18848 if (FalseVal == TrueVal.getOperand(0))
18850 else if (Commutative && FalseVal == TrueVal.getOperand(1))
18855 EVT VT =
N->getValueType(0);
18857 SDValue OtherOp = TrueVal.getOperand(1 - OpToFold);
18863 assert(IdentityOperand &&
"No identity operand!");
18868 DAG.
getSelect(
DL, OtherOpVT,
N->getOperand(0), OtherOp, IdentityOperand);
18869 return DAG.
getNode(TrueVal.getOpcode(),
DL, VT, FalseVal, NewSel);
18890 CountZeroes =
N->getOperand(2);
18891 ValOnZero =
N->getOperand(1);
18893 CountZeroes =
N->getOperand(1);
18894 ValOnZero =
N->getOperand(2);
18913 if (
Cond->getOperand(0) != CountZeroesArgument)
18932 CountZeroes, BitWidthMinusOne);
18942 EVT VT =
N->getValueType(0);
18943 EVT CondVT =
Cond.getValueType();
18951 (Subtarget.
hasCZEROLike() || Subtarget.hasVendorXTHeadCondMov())) {
18957 const APInt &MaskVal =
LHS.getConstantOperandAPInt(1);
18968 if (!TrueVal.hasOneUse() || !FalseVal.hasOneUse())
18972 if (TrueVal.getOpcode() ==
ISD::SUB && FalseVal.getOpcode() ==
ISD::ADD) {
18980 SDValue A = FalseVal.getOperand(0);
18981 SDValue B = FalseVal.getOperand(1);
18983 return ((TrueVal.getOperand(0) ==
A && TrueVal.getOperand(1) ==
B) ||
18984 (TrueVal.getOperand(1) ==
A && TrueVal.getOperand(0) ==
B));
18992 EVT VT =
N->getValueType(0);
18994 SDValue TrueVal =
N->getOperand(1);
18995 SDValue FalseVal =
N->getOperand(2);
19025 SDValue TrueVal =
N->getOperand(1);
19026 SDValue FalseVal =
N->getOperand(2);
19041 EVT VT =
N->getValueType(0);
19048 const unsigned Opcode =
N->op_begin()->getNode()->getOpcode();
19063 if (
Op.isUndef()) {
19076 if (
Op.getOpcode() != Opcode || !
Op.hasOneUse())
19085 if (
Op.getOperand(0).getValueType() !=
Op.getOperand(1).getValueType())
19109 EVT AVT =
A.getValueType();
19110 EVT BVT =
B.getValueType();
19140 if (AOpt || BOpt) {
19158 EVT OpVT =
A.getValueType();
19166 IsSigned ? ISD::PARTIAL_REDUCE_SMLA : ISD::PARTIAL_REDUCE_UMLA;
19180 EVT OpVT =
A.getOperand(0).getValueType();
19182 OpVT !=
B.getOperand(0).getValueType() ||
19188 Opc = ISD::PARTIAL_REDUCE_SMLA;
19191 Opc = ISD::PARTIAL_REDUCE_UMLA;
19194 Opc = ISD::PARTIAL_REDUCE_SUMLA;
19197 Opc = ISD::PARTIAL_REDUCE_SUMLA;
19211 if (!Subtarget.hasStdExtZvqdotq())
19215 EVT VT =
N->getValueType(0);
19218 return DAG.
getNode(ISD::VECREDUCE_ADD,
DL, VT, V);
19240 const unsigned InVecOpcode = InVec->
getOpcode();
19257 InVecLHS, InValLHS, EltNo);
19259 InVecRHS, InValRHS, EltNo);
19271 unsigned Elt = IndexC->getZExtValue();
19277 unsigned NewIdx = Elt % ConcatNumElts;
19279 unsigned ConcatOpIdx = Elt / ConcatNumElts;
19284 ConcatOps[ConcatOpIdx] = ConcatOp;
19296 EVT VT =
N->getValueType(0);
19308 !
SDValue(BaseLd, 0).hasOneUse())
19311 EVT BaseLdVT = BaseLd->getValueType(0);
19319 if (!Ld || !Ld->isSimple() || !
Op.hasOneUse() ||
19321 Ld->getValueType(0) != BaseLdVT)
19330 using PtrDiff = std::pair<std::variant<int64_t, SDValue>,
bool>;
19332 LoadSDNode *Ld2) -> std::optional<PtrDiff> {
19337 if (BIO1.equalBaseIndex(BIO2, DAG))
19342 SDValue P2 = Ld2->getBasePtr();
19345 if (P1.getOpcode() ==
ISD::ADD && P1.getOperand(0) == P2)
19346 return {{P1.getOperand(1),
true}};
19348 return std::nullopt;
19352 auto BaseDiff = GetPtrDiff(Lds[0], Lds[1]);
19357 for (
auto *It = Lds.
begin() + 1; It != Lds.
end() - 1; It++)
19358 if (GetPtrDiff(*It, *std::next(It)) != BaseDiff)
19366 unsigned WideScalarBitWidth =
19379 auto [StrideVariant, MustNegateStride] = *BaseDiff;
19381 std::holds_alternative<SDValue>(StrideVariant)
19382 ? std::get<SDValue>(StrideVariant)
19385 if (MustNegateStride)
19394 ConstStride && ConstStride->getSExtValue() >= 0)
19398 ConstStride->getSExtValue() * (
N->getNumOperands() - 1);
19404 BaseLd->getPointerInfo(), BaseLd->getMemOperand()->getFlags(), MemSize,
19408 WideVecVT,
DL, BaseLd->getChain(), BaseLd->getBasePtr(), Stride,
19422 EVT VT =
N->getValueType(0);
19439 for (
int MaskIndex : Mask) {
19440 bool SelectMaskVal = (MaskIndex < (int)NumElts);
19443 assert(MaskVals.
size() == NumElts &&
"Unexpected select-like shuffle");
19480 if (
N->getValueType(0).isFixedLengthVector())
19483 SDValue Addend =
N->getOperand(0);
19486 if (
N->getOpcode() == RISCVISD::ADD_VL) {
19487 SDValue AddPassthruOp =
N->getOperand(2);
19488 if (!AddPassthruOp.
isUndef())
19492 auto IsVWMulOpc = [](
unsigned Opc) {
19494 case RISCVISD::VWMUL_VL:
19495 case RISCVISD::VWMULU_VL:
19496 case RISCVISD::VWMULSU_VL:
19511 if (!MulPassthruOp.
isUndef())
19521 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
19522 }(
N, DAG, Subtarget);
19527 if (AddMask != MulMask || AddVL != MulVL)
19530 const auto &TSInfo =
19532 unsigned Opc = TSInfo.getMAccOpcode(MulOp.
getOpcode());
19535 EVT VT =
N->getValueType(0);
19546 if (!
N->getValueType(0).isVector())
19549 SDValue Addend =
N->getOperand(0);
19552 if (
N->getOpcode() == RISCVISD::ADD_VL) {
19553 SDValue AddPassthruOp =
N->getOperand(2);
19554 if (!AddPassthruOp.
isUndef())
19558 auto IsVqdotqOpc = [](
unsigned Opc) {
19560 case RISCVISD::VQDOT_VL:
19561 case RISCVISD::VQDOTU_VL:
19562 case RISCVISD::VQDOTSU_VL:
19582 return std::make_pair(
N->getOperand(3),
N->getOperand(4));
19583 }(
N, DAG, Subtarget);
19586 if (AddVL != MulVL)
19589 if (AddMask.getOpcode() != RISCVISD::VMSET_VL ||
19590 AddMask.getOperand(0) != MulVL)
19595 EVT VT =
N->getValueType(0);
19596 Addend = DAG.
getNode(RISCVISD::ADD_VL,
DL, VT, Addend, AccumOp,
19597 DAG.
getUNDEF(VT), AddMask, AddVL);
19615 const EVT IndexVT = Index.getValueType();
19619 if (!isIndexTypeSigned(IndexType))
19649 assert(ShuffleMask.empty());
19651 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
19654 if (Index->getOperand(i)->isUndef())
19656 uint64_t C = Index->getConstantOperandVal(i);
19657 if (
C % ElementSize != 0)
19659 C =
C / ElementSize;
19662 ShuffleMask.push_back(
C);
19663 ActiveLanes.
set(
C);
19665 return ActiveLanes.
all();
19683 if (NumElems % 2 != 0)
19687 const unsigned WiderElementSize = ElementSize * 2;
19688 if (WiderElementSize > ST.getELen()/8)
19691 if (!ST.enableUnalignedVectorMem() && BaseAlign < WiderElementSize)
19694 for (
unsigned i = 0; i < Index->getNumOperands(); i++) {
19697 if (Index->getOperand(i)->isUndef())
19701 uint64_t C = Index->getConstantOperandVal(i);
19703 if (
C % WiderElementSize != 0)
19708 if (
C !=
Last + ElementSize)
19727 if (!IsVLMAX || Mask.getOpcode() != RISCVISD::VMSET_VL ||
19728 Mask.getOperand(0) != VL)
19731 auto IsTruncNode = [&](
SDValue V) {
19732 return V.getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL &&
19733 V.getOperand(1) == Mask && V.getOperand(2) == VL;
19740 while (IsTruncNode(
Op)) {
19741 if (!
Op.hasOneUse())
19743 Op =
Op.getOperand(0);
19776 assert(
N->getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL);
19778 MVT VT =
N->getSimpleValueType(0);
19783 auto MatchMinMax = [&VL, &Mask](
SDValue V,
unsigned Opc,
unsigned OpcVL,
19785 if (V.getOpcode() !=
Opc &&
19786 !(V.getOpcode() == OpcVL && V.getOperand(2).isUndef() &&
19787 V.getOperand(3) == Mask && V.getOperand(4) == VL))
19795 Op.getOperand(1).getValueType().isFixedLengthVector() &&
19797 Op.getOperand(1).getOperand(0).getValueType() ==
Op.getValueType() &&
19799 Op =
Op.getOperand(1).getOperand(0);
19802 return V.getOperand(0);
19804 if (
Op.getOpcode() == RISCVISD::VMV_V_X_VL &&
Op.getOperand(0).isUndef() &&
19805 Op.getOperand(2) == VL) {
19808 Op1->getAPIntValue().sextOrTrunc(
Op.getScalarValueSizeInBits());
19818 auto DetectUSatPattern = [&](
SDValue V) {
19830 MatchMinMax(SMinOp,
ISD::SMAX, RISCVISD::SMAX_VL, LoC))
19839 MatchMinMax(SMaxOp,
ISD::SMIN, RISCVISD::SMIN_VL, HiC))
19842 return DAG.
getNode(RISCVISD::SMAX_VL,
DL, V.getValueType(), SMinOp,
19843 V.getOperand(1), DAG.
getUNDEF(V.getValueType()),
19849 auto DetectSSatPattern = [&](
SDValue V) {
19851 unsigned NumSrcBits = V.getScalarValueSizeInBits();
19858 MatchMinMax(SMinOp,
ISD::SMAX, RISCVISD::SMAX_VL, LoC))
19859 if (HiC == SignedMax && LoC == SignedMin)
19864 MatchMinMax(SMaxOp,
ISD::SMIN, RISCVISD::SMIN_VL, HiC))
19865 if (HiC == SignedMax && LoC == SignedMin)
19874 while (Src.getOpcode() == RISCVISD::TRUNCATE_VECTOR_VL &&
19875 Src.getOperand(1) == Mask && Src.getOperand(2) == VL &&
19877 Src = Src.getOperand(0);
19881 if ((Val = DetectUSatPattern(Src)))
19882 ClipOpc = RISCVISD::TRUNCATE_VECTOR_VL_USAT;
19883 else if ((Val = DetectSSatPattern(Src)))
19884 ClipOpc = RISCVISD::TRUNCATE_VECTOR_VL_SSAT;
19893 Val = DAG.
getNode(ClipOpc,
DL, ValVT, Val, Mask, VL);
19894 }
while (ValVT != VT);
19912 unsigned Opc =
N->getOpcode();
19914 "Unexpected opcode");
19915 EVT VT =
N->getValueType(0);
19924 Src = Src.getOperand(0);
19926 if (Src.getOpcode() != ISD::BITCAST)
19928 Src = Src.getOperand(0);
19929 }
else if (
Opc == ISD::VECREDUCE_ADD) {
19932 Src = Src.getOperand(0);
19935 EVT SrcEVT = Src.getValueType();
19950 if (
Opc == ISD::VECREDUCE_ADD) {
19957 VectorBitsMax, EltSize, MinSize);
19962 MVT ContainerVT = SrcMVT;
19990 if (!
LHS.hasOneUse())
19993 switch (
LHS.getOpcode()) {
19995 case RISCVISD::VSEXT_VL:
19996 Opcode = RISCVISD::VWMULSU_VL;
19999 case RISCVISD::VZEXT_VL:
20000 Opcode = RISCVISD::VWMULU_VL;
20011 else if (
RHS.getOpcode() == RISCVISD::VMV_V_X_VL &&
20013 ShAmtInt =
RHS.getConstantOperandVal(1);
20026 if (ShAmtInt >= NarrowBits)
20028 MVT VT =
N->getSimpleValueType(0);
20035 switch (
N->getOpcode()) {
20040 case RISCVISD::SHL_VL:
20041 Passthru =
N->getOperand(2);
20042 Mask =
N->getOperand(3);
20043 VL =
N->getOperand(4);
20048 return DAG.
getNode(Opcode,
DL, VT, NarrowOp,
20050 Passthru, Mask, VL);
20056 const MVT XLenVT = Subtarget.getXLenVT();
20062 auto SimplifyDemandedLowBitsHelper = [&](
unsigned OpNo,
unsigned LowBits) {
20073 switch (
N->getOpcode()) {
20076 case RISCVISD::SplitF64: {
20080 if (Op0->
getOpcode() == RISCVISD::BuildPairF64)
20093 APInt V =
C->getValueAPF().bitcastToAPInt();
20122 case RISCVISD::SLLW:
20123 case RISCVISD::SRAW:
20124 case RISCVISD::SRLW:
20125 case RISCVISD::RORW:
20126 case RISCVISD::ROLW: {
20128 if (SimplifyDemandedLowBitsHelper(0, 32) ||
20129 SimplifyDemandedLowBitsHelper(1, 5))
20134 case RISCVISD::CLZW:
20135 case RISCVISD::CTZW: {
20137 if (SimplifyDemandedLowBitsHelper(0, 32))
20141 case RISCVISD::FMV_W_X_RV64: {
20146 if (Op0.
getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64)
20150 case RISCVISD::FMV_X_ANYEXTH:
20151 case RISCVISD::FMV_X_ANYEXTW_RV64: {
20154 MVT VT =
N->getSimpleValueType(0);
20165 if ((
N->getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64 &&
20166 Op0->
getOpcode() == RISCVISD::FMV_W_X_RV64) ||
20167 (
N->getOpcode() == RISCVISD::FMV_X_ANYEXTH &&
20168 Op0->
getOpcode() == RISCVISD::FMV_H_X)) {
20170 "Unexpected value type!");
20180 LN0->getBasePtr(), IVT, LN0->getMemOperand());
20193 unsigned FPBits =
N->getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64 ? 32 : 16;
20204 EVT VT =
N->getValueType(0);
20253 EVT VT =
N->getValueType(0);
20270 if (!
C || !
C->getValueAPF().isExactlyValue(+1.0))
20285 case ISD::FMINNUM: {
20300 if (
N->getValueType(0) == MVT::i64 && Subtarget.is64Bit()) {
20305 Src.getOperand(0));
20310 Src.getOperand(0), Src.getOperand(1));
20318 case RISCVISD::TRUNCATE_VECTOR_VL:
20322 case ISD::VP_TRUNCATE:
20330 case RISCVISD::CZERO_EQZ:
20331 case RISCVISD::CZERO_NEZ: {
20335 unsigned Opc =
N->getOpcode();
20338 if (
Opc == RISCVISD::CZERO_EQZ && Val ==
Cond)
20342 Opc == RISCVISD::CZERO_EQZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ;
20350 return DAG.
getNode(InvOpc,
SDLoc(
N),
N->getValueType(0), Val, NewCond);
20360 N->getValueType(0), Val,
Cond.getOperand(0));
20364 case RISCVISD::SELECT_CC: {
20371 SDValue FalseV =
N->getOperand(4);
20373 EVT VT =
N->getValueType(0);
20376 if (TrueV == FalseV)
20407 return DAG.
getNode(RISCVISD::SELECT_CC,
DL,
N->getValueType(0),
20408 {LHS, RHS, CC, TrueV, FalseV});
20410 if (!Subtarget.hasConditionalMoveFusion()) {
20467 case RISCVISD::BR_CC: {
20474 return DAG.
getNode(RISCVISD::BR_CC,
DL,
N->getValueType(0),
20475 N->getOperand(0), LHS, RHS, CC,
N->getOperand(4));
20488 EVT VT =
N->getValueType(0);
20500 if (In2.
getOpcode() != ISD::FP_EXTEND &&
20509 DAG.
getNode(ISD::FNEG,
DL, VT, NewFPExtRound));
20511 case ISD::MGATHER: {
20513 const EVT VT =
N->getValueType(0);
20514 SDValue Index = MGN->getIndex();
20515 SDValue ScaleOp = MGN->getScale();
20517 assert(!MGN->isIndexScaled() &&
20518 "Scaled gather/scatter should not be formed");
20523 N->getVTList(), MGN->getMemoryVT(),
DL,
20524 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
20525 MGN->getBasePtr(), Index, ScaleOp},
20526 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
20530 N->getVTList(), MGN->getMemoryVT(),
DL,
20531 {MGN->getChain(), MGN->getPassThru(), MGN->getMask(),
20532 MGN->getBasePtr(), Index, ScaleOp},
20533 MGN->getMemOperand(), IndexType, MGN->getExtensionType());
20539 if (std::optional<VIDSequence> SimpleVID =
20541 SimpleVID && SimpleVID->StepDenominator == 1) {
20542 const int64_t StepNumerator = SimpleVID->StepNumerator;
20543 const int64_t Addend = SimpleVID->Addend;
20550 assert(MGN->getBasePtr()->getValueType(0) == PtrVT);
20558 VT,
DL, MGN->getChain(), BasePtr,
20560 EVL, MGN->getMemOperand());
20562 MGN->getPassThru());
20572 MGN->getBasePtr(), DAG.
getUNDEF(XLenVT),
20574 MGN->getMemoryVT(), MGN->getMemOperand(),
20583 MGN->getMemOperand()->getBaseAlign(), Subtarget)) {
20585 for (
unsigned i = 0; i < Index->getNumOperands(); i += 2)
20586 NewIndices.
push_back(Index.getOperand(i));
20587 EVT IndexVT = Index.getValueType()
20594 assert(EltCnt.isKnownEven() &&
"Splitting vector, but not in half!");
20596 EltCnt.divideCoefficientBy(2));
20599 EltCnt.divideCoefficientBy(2));
20604 {MGN->getChain(), Passthru, Mask, MGN->getBasePtr(),
20612 case ISD::MSCATTER:{
20614 SDValue Index = MSN->getIndex();
20615 SDValue ScaleOp = MSN->getScale();
20617 assert(!MSN->isIndexScaled() &&
20618 "Scaled gather/scatter should not be formed");
20623 N->getVTList(), MSN->getMemoryVT(),
DL,
20624 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
20626 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
20630 N->getVTList(), MSN->getMemoryVT(),
DL,
20631 {MSN->getChain(), MSN->getValue(), MSN->getMask(), MSN->getBasePtr(),
20633 MSN->getMemOperand(), IndexType, MSN->isTruncatingStore());
20635 EVT VT = MSN->getValue()->getValueType(0);
20637 if (!MSN->isTruncatingStore() &&
20641 return DAG.
getMaskedStore(MSN->getChain(),
DL, Shuffle, MSN->getBasePtr(),
20642 DAG.
getUNDEF(XLenVT), MSN->getMask(),
20643 MSN->getMemoryVT(), MSN->getMemOperand(),
20648 case ISD::VP_GATHER: {
20650 SDValue Index = VPGN->getIndex();
20651 SDValue ScaleOp = VPGN->getScale();
20653 assert(!VPGN->isIndexScaled() &&
20654 "Scaled gather/scatter should not be formed");
20659 {VPGN->getChain(), VPGN->getBasePtr(), Index,
20660 ScaleOp, VPGN->getMask(),
20661 VPGN->getVectorLength()},
20662 VPGN->getMemOperand(), IndexType);
20666 {VPGN->getChain(), VPGN->getBasePtr(), Index,
20667 ScaleOp, VPGN->getMask(),
20668 VPGN->getVectorLength()},
20669 VPGN->getMemOperand(), IndexType);
20673 case ISD::VP_SCATTER: {
20675 SDValue Index = VPSN->getIndex();
20676 SDValue ScaleOp = VPSN->getScale();
20678 assert(!VPSN->isIndexScaled() &&
20679 "Scaled gather/scatter should not be formed");
20684 {VPSN->getChain(), VPSN->getValue(),
20685 VPSN->getBasePtr(), Index, ScaleOp,
20686 VPSN->getMask(), VPSN->getVectorLength()},
20687 VPSN->getMemOperand(), IndexType);
20691 {VPSN->getChain(), VPSN->getValue(),
20692 VPSN->getBasePtr(), Index, ScaleOp,
20693 VPSN->getMask(), VPSN->getVectorLength()},
20694 VPSN->getMemOperand(), IndexType);
20697 case RISCVISD::SHL_VL:
20701 case RISCVISD::SRA_VL:
20702 case RISCVISD::SRL_VL: {
20704 if (ShAmt.
getOpcode() == RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL) {
20708 EVT VT =
N->getValueType(0);
20711 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt,
20712 N->getOperand(2),
N->getOperand(3),
N->getOperand(4));
20727 if (ShAmt.
getOpcode() == RISCVISD::SPLAT_VECTOR_SPLIT_I64_VL) {
20730 EVT VT =
N->getValueType(0);
20733 DAG.
getRegister(RISCV::X0, Subtarget.getXLenVT()));
20734 return DAG.
getNode(
N->getOpcode(),
DL, VT,
N->getOperand(0), ShAmt);
20738 case RISCVISD::ADD_VL:
20746 case RISCVISD::VWADD_W_VL:
20747 case RISCVISD::VWADDU_W_VL:
20748 case RISCVISD::VWSUB_W_VL:
20749 case RISCVISD::VWSUBU_W_VL:
20751 case RISCVISD::OR_VL:
20752 case RISCVISD::SUB_VL:
20753 case RISCVISD::MUL_VL:
20755 case RISCVISD::VFMADD_VL:
20756 case RISCVISD::VFNMADD_VL:
20757 case RISCVISD::VFMSUB_VL:
20758 case RISCVISD::VFNMSUB_VL:
20759 case RISCVISD::STRICT_VFMADD_VL:
20760 case RISCVISD::STRICT_VFNMADD_VL:
20761 case RISCVISD::STRICT_VFMSUB_VL:
20762 case RISCVISD::STRICT_VFNMSUB_VL:
20764 case RISCVISD::FADD_VL:
20765 case RISCVISD::FSUB_VL:
20766 case RISCVISD::FMUL_VL:
20767 case RISCVISD::VFWADD_W_VL:
20768 case RISCVISD::VFWSUB_W_VL:
20776 if (
N->getOpcode() != ISD::STORE)
20780 SDValue Chain = Store->getChain();
20781 EVT MemVT = Store->getMemoryVT();
20782 SDValue Val = Store->getValue();
20785 bool IsScalarizable =
20787 Store->isSimple() &&
20817 NewVT, *Store->getMemOperand())) {
20819 return DAG.
getStore(Chain,
DL, NewV, Store->getBasePtr(),
20820 Store->getPointerInfo(), Store->getBaseAlign(),
20821 Store->getMemOperand()->getFlags());
20831 L->hasNUsesOfValue(1, 0) && L->hasNUsesOfValue(1, 1) &&
20833 L->getMemoryVT() == MemVT) {
20836 NewVT, *Store->getMemOperand()) &&
20838 NewVT, *L->getMemOperand())) {
20840 L->getPointerInfo(), L->getBaseAlign(),
20841 L->getMemOperand()->getFlags());
20842 return DAG.
getStore(Chain,
DL, NewL, Store->getBasePtr(),
20843 Store->getPointerInfo(), Store->getBaseAlign(),
20844 Store->getMemOperand()->getFlags());
20851 if ((Val.
getOpcode() == RISCVISD::VMV_X_S ||
20857 MVT VecVT = Src.getSimpleValueType();
20864 Store->getChain(),
DL, Src, Store->getBasePtr(), Store->getOffset(),
20867 Store->getMemOperand(), Store->getAddressingMode(),
20868 Store->isTruncatingStore(),
false);
20875 EVT VT =
N->getValueType(0);
20900 case RISCVISD::VFMV_V_F_VL: {
20901 const MVT VT =
N->getSimpleValueType(0);
20902 SDValue Passthru =
N->getOperand(0);
20903 SDValue Scalar =
N->getOperand(1);
20908 return DAG.
getNode(RISCVISD::VFMV_S_F_VL,
DL, VT, Passthru, Scalar, VL);
20911 case RISCVISD::VMV_V_X_VL: {
20912 const MVT VT =
N->getSimpleValueType(0);
20913 SDValue Passthru =
N->getOperand(0);
20914 SDValue Scalar =
N->getOperand(1);
20919 unsigned ScalarSize = Scalar.getValueSizeInBits();
20921 if (ScalarSize > EltWidth && Passthru.
isUndef())
20922 if (SimplifyDemandedLowBitsHelper(1, EltWidth))
20929 (!Const || Const->isZero() ||
20930 !Const->getAPIntValue().sextOrTrunc(EltWidth).isSignedIntN(5)))
20931 return DAG.
getNode(RISCVISD::VMV_S_X_VL,
DL, VT, Passthru, Scalar, VL);
20935 case RISCVISD::VFMV_S_F_VL: {
20940 if (
N->getOperand(0).isUndef() &&
20943 Src.getOperand(0).getValueType().isScalableVector()) {
20944 EVT VT =
N->getValueType(0);
20964 case RISCVISD::VMV_S_X_VL: {
20965 const MVT VT =
N->getSimpleValueType(0);
20966 SDValue Passthru =
N->getOperand(0);
20967 SDValue Scalar =
N->getOperand(1);
20973 unsigned ScalarSize = Scalar.getValueSizeInBits();
20975 if (ScalarSize > EltWidth && SimplifyDemandedLowBitsHelper(1, EltWidth))
20978 if (Scalar.getOpcode() == RISCVISD::VMV_X_S && Passthru.
isUndef() &&
20979 Scalar.getOperand(0).getValueType() ==
N->getValueType(0))
20980 return Scalar.getOperand(0);
20987 DAG.
getNode(
N->getOpcode(),
DL, M1VT, M1Passthru, Scalar, VL);
20996 Const && !Const->isZero() &&
isInt<5>(Const->getSExtValue()) &&
20998 return DAG.
getNode(RISCVISD::VMV_V_X_VL,
DL, VT, Passthru, Scalar, VL);
21002 case RISCVISD::VMV_X_S: {
21004 MVT VecVT =
N->getOperand(0).getSimpleValueType();
21006 if (M1VT.
bitsLT(VecVT)) {
21008 return DAG.
getNode(RISCVISD::VMV_X_S,
DL,
N->getSimpleValueType(0), Vec);
21016 unsigned IntNo =
N->getConstantOperandVal(IntOpNo);
21021 case Intrinsic::riscv_vcpop:
21022 case Intrinsic::riscv_vcpop_mask:
21023 case Intrinsic::riscv_vfirst:
21024 case Intrinsic::riscv_vfirst_mask: {
21026 if (IntNo == Intrinsic::riscv_vcpop_mask ||
21027 IntNo == Intrinsic::riscv_vfirst_mask)
21028 VL =
N->getOperand(3);
21033 EVT VT =
N->getValueType(0);
21034 if (IntNo == Intrinsic::riscv_vfirst ||
21035 IntNo == Intrinsic::riscv_vfirst_mask)
21039 case Intrinsic::riscv_vsseg2_mask:
21040 case Intrinsic::riscv_vsseg3_mask:
21041 case Intrinsic::riscv_vsseg4_mask:
21042 case Intrinsic::riscv_vsseg5_mask:
21043 case Intrinsic::riscv_vsseg6_mask:
21044 case Intrinsic::riscv_vsseg7_mask:
21045 case Intrinsic::riscv_vsseg8_mask: {
21047 unsigned NF = Tuple.getValueType().getRISCVVectorTupleNumFields();
21049 if (Subtarget.hasOptimizedSegmentLoadStore(NF) || !Tuple.hasOneUse() ||
21050 Tuple.getOpcode() != RISCVISD::TUPLE_INSERT ||
21051 !Tuple.getOperand(0).isUndef())
21059 "Type mismatch without bitcast?");
21060 unsigned Stride = SEW / 8 * NF;
21061 unsigned Offset = SEW / 8 * Idx;
21088 case ISD::EXPERIMENTAL_VP_REVERSE:
21090 case ISD::VP_STORE:
21092 case ISD::BITCAST: {
21093 assert(Subtarget.useRVVForFixedLengthVectors());
21095 EVT VT =
N->getValueType(0);
21106 for (
unsigned i = 0; i < NF; ++i)
21107 Result = DAG.
getNode(RISCVISD::TUPLE_INSERT,
DL, VT, Result,
Splat,
21113 if ((SrcVT == MVT::v1i1 || SrcVT == MVT::v2i1 || SrcVT == MVT::v4i1) &&
21126 case ISD::VECREDUCE_ADD:
21134 case RISCVISD::VRGATHER_VX_VL: {
21137 EVT VT =
N->getValueType(0);
21140 SDValue Passthru =
N->getOperand(2);
21147 Src = Src.getOperand(1);
21149 switch (Src.getOpcode()) {
21152 case RISCVISD::VMV_V_X_VL:
21153 case RISCVISD::VFMV_V_F_VL:
21161 case RISCVISD::VMV_S_X_VL:
21162 case RISCVISD::VFMV_S_F_VL:
21178 case RISCVISD::TUPLE_EXTRACT: {
21179 EVT VT =
N->getValueType(0);
21181 unsigned Idx =
N->getConstantOperandVal(1);
21186 switch (Tuple.getConstantOperandVal(1)) {
21189 case Intrinsic::riscv_vlseg2_mask:
21190 case Intrinsic::riscv_vlseg3_mask:
21191 case Intrinsic::riscv_vlseg4_mask:
21192 case Intrinsic::riscv_vlseg5_mask:
21193 case Intrinsic::riscv_vlseg6_mask:
21194 case Intrinsic::riscv_vlseg7_mask:
21195 case Intrinsic::riscv_vlseg8_mask:
21196 NF = Tuple.getValueType().getRISCVVectorTupleNumFields();
21200 if (!NF || Subtarget.hasOptimizedSegmentLoadStore(NF))
21205 "Type mismatch without bitcast?");
21206 unsigned Stride = SEW / 8 * NF;
21207 unsigned Offset = SEW / 8 * Idx;
21210 Tuple.getOperand(0),
21232 return Result.getValue(0);
21234 case RISCVISD::TUPLE_INSERT: {
21236 if (
N->getOperand(1).isUndef())
21237 return N->getOperand(0);
21240 case RISCVISD::VSLIDE1UP_VL:
21241 case RISCVISD::VFSLIDE1UP_VL: {
21245 MVT VT =
N->getSimpleValueType(0);
21249 if (!
N->getOperand(0).isUndef() ||
21268 return getVSlideup(DAG, Subtarget,
DL, VT, SrcVec,
N->getOperand(1),
21278 EVT XVT,
unsigned KeptBits)
const {
21283 if (XVT != MVT::i32 && XVT != MVT::i64)
21287 if (KeptBits == 32 || KeptBits == 64)
21291 return Subtarget.hasStdExtZbb() &&
21292 ((KeptBits == 8 && XVT == MVT::i64 && !Subtarget.is64Bit()) ||
21300 "Expected shift op");
21324 if (Ty.isScalarInteger() &&
21327 return isUsedByLdSt(N0.
getNode(),
N);
21333 (Subtarget.hasStdExtZba() || Subtarget.hasVendorXAndesPerf()) && C2 &&
21334 C2->getZExtValue() >= 1 && C2->getZExtValue() <= 3;
21335 bool IsQCShlAdd = Subtarget.hasVendorXqciac() && C2 &&
21336 C2->getZExtValue() >= 4 && C2->getZExtValue() <= 31;
21339 if ((IsShXAdd || IsQCShlAdd) &&
N->hasOneUse() &&
21340 N->user_begin()->getOpcode() ==
ISD::ADD &&
21341 !isUsedByLdSt(*
N->user_begin(),
nullptr) &&
21346 const APInt &C1Int = C1->getAPIntValue();
21347 APInt ShiftedC1Int = C1Int << C2->getAPIntValue();
21368 ShiftedC1Int, Ty.getSizeInBits(), Subtarget,
21373 if (C1Cost < ShiftedC1Cost)
21396 EVT VT =
Op.getValueType();
21400 unsigned Opcode =
Op.getOpcode();
21408 const APInt &Mask =
C->getAPIntValue();
21417 auto IsLegalMask = [ShrunkMask, ExpandedMask](
const APInt &Mask) ->
bool {
21418 return ShrunkMask.
isSubsetOf(Mask) && Mask.isSubsetOf(ExpandedMask);
21420 auto UseMask = [Mask,
Op, &TLO](
const APInt &NewMask) ->
bool {
21421 if (NewMask == Mask)
21426 Op.getOperand(0), NewC);
21439 APInt NewMask =
APInt(Mask.getBitWidth(), 0xffff);
21440 if (IsLegalMask(NewMask))
21441 return UseMask(NewMask);
21444 if (VT == MVT::i64) {
21446 if (IsLegalMask(NewMask))
21447 return UseMask(NewMask);
21462 APInt NewMask = ShrunkMask;
21463 if (MinSignedBits <= 12)
21465 else if (!
C->isOpaque() && MinSignedBits <= 32 && !ShrunkMask.
isSignedIntN(32))
21471 assert(IsLegalMask(NewMask));
21472 return UseMask(NewMask);
21476 static const uint64_t GREVMasks[] = {
21477 0x5555555555555555ULL, 0x3333333333333333ULL, 0x0F0F0F0F0F0F0F0FULL,
21478 0x00FF00FF00FF00FFULL, 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL};
21480 for (
unsigned Stage = 0; Stage != 6; ++Stage) {
21481 unsigned Shift = 1 << Stage;
21482 if (ShAmt & Shift) {
21484 uint64_t Res = ((x & Mask) << Shift) | ((x >> Shift) & Mask);
21496 const APInt &DemandedElts,
21498 unsigned Depth)
const {
21500 unsigned Opc =
Op.getOpcode();
21505 "Should use MaskedValueIsZero if you don't know whether Op"
21506 " is a target node!");
21511 case RISCVISD::SELECT_CC: {
21522 case RISCVISD::VCPOP_VL: {
21527 case RISCVISD::CZERO_EQZ:
21528 case RISCVISD::CZERO_NEZ:
21534 case RISCVISD::REMUW: {
21544 case RISCVISD::DIVUW: {
21554 case RISCVISD::SLLW: {
21563 case RISCVISD::SRLW: {
21572 case RISCVISD::SRAW: {
21581 case RISCVISD::CTZW: {
21588 case RISCVISD::CLZW: {
21595 case RISCVISD::BREV8:
21596 case RISCVISD::ORC_B: {
21600 bool IsGORC =
Op.getOpcode() == RISCVISD::ORC_B;
21608 case RISCVISD::READ_VLENB: {
21611 const unsigned MinVLenB = Subtarget.getRealMinVLen() / 8;
21612 const unsigned MaxVLenB = Subtarget.getRealMaxVLen() / 8;
21613 assert(MinVLenB > 0 &&
"READ_VLENB without vector extension enabled?");
21616 if (MaxVLenB == MinVLenB)
21620 case RISCVISD::FCLASS: {
21633 case Intrinsic::riscv_vsetvli:
21634 case Intrinsic::riscv_vsetvlimax: {
21635 bool HasAVL = IntNo == Intrinsic::riscv_vsetvli;
21636 unsigned VSEW =
Op.getConstantOperandVal(HasAVL + 1);
21641 uint64_t MaxVL = Subtarget.getRealMaxVLen() / SEW;
21642 MaxVL = (Fractional) ? MaxVL / LMul : MaxVL * LMul;
21646 MaxVL = std::min(MaxVL,
Op.getConstantOperandVal(1));
21648 unsigned KnownZeroFirstBit =
Log2_32(MaxVL) + 1;
21661 unsigned Depth)
const {
21662 switch (
Op.getOpcode()) {
21665 case RISCVISD::SELECT_CC: {
21668 if (Tmp == 1)
return 1;
21671 return std::min(Tmp, Tmp2);
21673 case RISCVISD::CZERO_EQZ:
21674 case RISCVISD::CZERO_NEZ:
21678 case RISCVISD::ABSW: {
21683 if (Tmp < 33)
return 1;
21686 case RISCVISD::SRAW: {
21693 return std::max(Tmp, 33U);
21695 case RISCVISD::SLLW:
21696 case RISCVISD::SRLW:
21697 case RISCVISD::DIVW:
21698 case RISCVISD::DIVUW:
21699 case RISCVISD::REMUW:
21700 case RISCVISD::ROLW:
21701 case RISCVISD::RORW:
21702 case RISCVISD::FCVT_W_RV64:
21703 case RISCVISD::FCVT_WU_RV64:
21704 case RISCVISD::STRICT_FCVT_W_RV64:
21705 case RISCVISD::STRICT_FCVT_WU_RV64:
21708 case RISCVISD::VMV_X_S: {
21714 unsigned XLen = Subtarget.getXLen();
21715 unsigned EltBits =
Op.getOperand(0).getScalarValueSizeInBits();
21716 if (EltBits <= XLen)
21717 return XLen - EltBits + 1;
21721 unsigned IntNo =
Op.getConstantOperandVal(1);
21725 case Intrinsic::riscv_masked_atomicrmw_xchg:
21726 case Intrinsic::riscv_masked_atomicrmw_add:
21727 case Intrinsic::riscv_masked_atomicrmw_sub:
21728 case Intrinsic::riscv_masked_atomicrmw_nand:
21729 case Intrinsic::riscv_masked_atomicrmw_max:
21730 case Intrinsic::riscv_masked_atomicrmw_min:
21731 case Intrinsic::riscv_masked_atomicrmw_umax:
21732 case Intrinsic::riscv_masked_atomicrmw_umin:
21733 case Intrinsic::riscv_masked_cmpxchg:
21740 assert(Subtarget.hasStdExtA());
21741 return Op.getValueSizeInBits() - 31;
21753 unsigned Depth)
const {
21756 switch (
Op.getOpcode()) {
21757 case RISCVISD::BREV8:
21758 case RISCVISD::ORC_B: {
21760 bool IsGORC =
Op.getOpcode() == RISCVISD::ORC_B;
21768 OriginalDemandedElts, Known2, TLO,
Depth + 1))
21780 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
21788 switch (
Op.getOpcode()) {
21789 case RISCVISD::SLLW:
21790 case RISCVISD::SRAW:
21791 case RISCVISD::SRLW:
21792 case RISCVISD::RORW:
21793 case RISCVISD::ROLW:
21797 case RISCVISD::SELECT_CC:
21799 assert(
Op.getOperand(0).getValueType().isInteger() &&
21800 "RISCVISD::SELECT_CC only compares integers");
21809 assert(Ld &&
"Unexpected null LoadSDNode");
21818 if (!CNode || CNode->isMachineConstantPoolEntry() ||
21819 CNode->getOffset() != 0)
21826 if (
Ptr.getOpcode() == RISCVISD::LLA) {
21827 auto *CNode = GetSupportedConstantPool(
Ptr.getOperand(0));
21828 if (!CNode || CNode->getTargetFlags() != 0)
21831 return CNode->getConstVal();
21835 if (
Ptr.getOpcode() != RISCVISD::ADD_LO ||
21836 Ptr.getOperand(0).getOpcode() != RISCVISD::HI)
21839 auto *CNodeLo = GetSupportedConstantPool(
Ptr.getOperand(1));
21840 auto *CNodeHi = GetSupportedConstantPool(
Ptr.getOperand(0).getOperand(0));
21846 if (CNodeLo->getConstVal() != CNodeHi->getConstVal())
21849 return CNodeLo->getConstVal();
21854 assert(
MI.getOpcode() == RISCV::ReadCounterWide &&
"Unexpected instruction");
21886 Register ReadAgainReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
21889 int64_t LoCounter =
MI.getOperand(2).getImm();
21890 int64_t HiCounter =
MI.getOperand(3).getImm();
21900 BuildMI(LoopMBB,
DL,
TII->get(RISCV::CSRRS), ReadAgainReg)
21912 MI.eraseFromParent();
21920 assert(
MI.getOpcode() == RISCV::SplitF64Pseudo &&
"Unexpected instruction");
21928 Register SrcReg =
MI.getOperand(2).getReg();
21933 TII.storeRegToStackSlot(*BB,
MI, SrcReg,
MI.getOperand(2).isKill(), FI, SrcRC,
21948 MI.eraseFromParent();
21955 assert(
MI.getOpcode() == RISCV::BuildPairF64Pseudo &&
21956 "Unexpected instruction");
21962 Register DstReg =
MI.getOperand(0).getReg();
21984 TII.loadRegFromStackSlot(*BB,
MI, DstReg, FI, DstRC, RI,
Register());
21985 MI.eraseFromParent();
21990 unsigned RelOpcode,
unsigned EqOpcode,
21993 Register DstReg =
MI.getOperand(0).getReg();
21994 Register Src1Reg =
MI.getOperand(1).getReg();
21995 Register Src2Reg =
MI.getOperand(2).getReg();
21997 Register SavedFFlags =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22021 MI.eraseFromParent();
22072 F->insert(It, FirstMBB);
22073 F->insert(It, SecondMBB);
22074 F->insert(It, SinkMBB);
22124 First.eraseFromParent();
22163 if (
MI.getOpcode() != RISCV::Select_GPR_Using_CC_GPR &&
22164 MI.getOperand(1).isReg() &&
MI.getOperand(2).isReg() &&
22165 Next != BB->
end() &&
Next->getOpcode() ==
MI.getOpcode() &&
22166 Next->getOperand(5).getReg() ==
MI.getOperand(0).getReg() &&
22167 Next->getOperand(5).isKill())
22172 if (
MI.getOperand(2).isReg())
22173 RHS =
MI.getOperand(2).getReg();
22178 SelectDests.
insert(
MI.getOperand(0).getReg());
22182 SequenceMBBI !=
E; ++SequenceMBBI) {
22183 if (SequenceMBBI->isDebugInstr())
22185 if (RISCVInstrInfo::isSelectPseudo(*SequenceMBBI)) {
22186 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
22187 !SequenceMBBI->getOperand(2).isReg() ||
22188 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
22189 SequenceMBBI->getOperand(3).getImm() != CC ||
22190 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
22191 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
22193 LastSelectPseudo = &*SequenceMBBI;
22195 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
22198 if (SequenceMBBI->hasUnmodeledSideEffects() ||
22199 SequenceMBBI->mayLoadOrStore() ||
22200 SequenceMBBI->usesCustomInsertionHook())
22203 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
22218 F->insert(
I, IfFalseMBB);
22219 F->insert(
I, TailMBB);
22222 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
22228 TailMBB->
push_back(DebugInstr->removeFromParent());
22232 TailMBB->
splice(TailMBB->
end(), HeadMBB,
22242 if (
MI.getOperand(2).isImm())
22245 .
addImm(
MI.getOperand(2).getImm())
22257 auto SelectMBBI =
MI.getIterator();
22258 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
22260 while (SelectMBBI != SelectEnd) {
22261 auto Next = std::next(SelectMBBI);
22262 if (RISCVInstrInfo::isSelectPseudo(*SelectMBBI)) {
22265 TII.get(RISCV::PHI), SelectMBBI->getOperand(0).getReg())
22266 .
addReg(SelectMBBI->getOperand(4).getReg())
22268 .
addReg(SelectMBBI->getOperand(5).getReg())
22275 F->getProperties().resetNoPHIs();
22283 RISCVVInversePseudosTable::getBaseInfo(MCOpcode, LMul, SEW);
22284 assert(
Inverse &&
"Unexpected LMUL and SEW pair for instruction");
22286 RISCV::lookupMaskedIntrinsicByUnmasked(
Inverse->Pseudo);
22287 assert(
Masked &&
"Could not find masked instruction for LMUL and SEW pair");
22293 unsigned CVTXOpc) {
22299 Register SavedFFLAGS =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22312 .
add(
MI.getOperand(1))
22313 .
add(
MI.getOperand(2))
22314 .
add(
MI.getOperand(3))
22316 .
add(
MI.getOperand(4))
22317 .
add(
MI.getOperand(5))
22318 .
add(
MI.getOperand(6))
22333 .
add(
MI.getOperand(0))
22334 .
add(
MI.getOperand(1))
22336 .
add(
MI.getOperand(3))
22338 .
add(
MI.getOperand(4))
22339 .
add(
MI.getOperand(5))
22340 .
add(
MI.getOperand(6))
22350 MI.eraseFromParent();
22356 unsigned CmpOpc, F2IOpc, I2FOpc, FSGNJOpc, FSGNJXOpc;
22358 switch (
MI.getOpcode()) {
22361 case RISCV::PseudoFROUND_H:
22362 CmpOpc = RISCV::FLT_H;
22363 F2IOpc = RISCV::FCVT_W_H;
22364 I2FOpc = RISCV::FCVT_H_W;
22365 FSGNJOpc = RISCV::FSGNJ_H;
22366 FSGNJXOpc = RISCV::FSGNJX_H;
22367 RC = &RISCV::FPR16RegClass;
22369 case RISCV::PseudoFROUND_H_INX:
22370 CmpOpc = RISCV::FLT_H_INX;
22371 F2IOpc = RISCV::FCVT_W_H_INX;
22372 I2FOpc = RISCV::FCVT_H_W_INX;
22373 FSGNJOpc = RISCV::FSGNJ_H_INX;
22374 FSGNJXOpc = RISCV::FSGNJX_H_INX;
22375 RC = &RISCV::GPRF16RegClass;
22377 case RISCV::PseudoFROUND_S:
22378 CmpOpc = RISCV::FLT_S;
22379 F2IOpc = RISCV::FCVT_W_S;
22380 I2FOpc = RISCV::FCVT_S_W;
22381 FSGNJOpc = RISCV::FSGNJ_S;
22382 FSGNJXOpc = RISCV::FSGNJX_S;
22383 RC = &RISCV::FPR32RegClass;
22385 case RISCV::PseudoFROUND_S_INX:
22386 CmpOpc = RISCV::FLT_S_INX;
22387 F2IOpc = RISCV::FCVT_W_S_INX;
22388 I2FOpc = RISCV::FCVT_S_W_INX;
22389 FSGNJOpc = RISCV::FSGNJ_S_INX;
22390 FSGNJXOpc = RISCV::FSGNJX_S_INX;
22391 RC = &RISCV::GPRF32RegClass;
22393 case RISCV::PseudoFROUND_D:
22395 CmpOpc = RISCV::FLT_D;
22396 F2IOpc = RISCV::FCVT_L_D;
22397 I2FOpc = RISCV::FCVT_D_L;
22398 FSGNJOpc = RISCV::FSGNJ_D;
22399 FSGNJXOpc = RISCV::FSGNJX_D;
22400 RC = &RISCV::FPR64RegClass;
22402 case RISCV::PseudoFROUND_D_INX:
22404 CmpOpc = RISCV::FLT_D_INX;
22405 F2IOpc = RISCV::FCVT_L_D_INX;
22406 I2FOpc = RISCV::FCVT_D_L_INX;
22407 FSGNJOpc = RISCV::FSGNJ_D_INX;
22408 FSGNJXOpc = RISCV::FSGNJX_D_INX;
22409 RC = &RISCV::GPRRegClass;
22421 F->insert(
I, CvtMBB);
22422 F->insert(
I, DoneMBB);
22430 MBB->addSuccessor(CvtMBB);
22431 MBB->addSuccessor(DoneMBB);
22433 Register DstReg =
MI.getOperand(0).getReg();
22434 Register SrcReg =
MI.getOperand(1).getReg();
22435 Register MaxReg =
MI.getOperand(2).getReg();
22436 int64_t FRM =
MI.getOperand(3).getImm();
22441 Register FabsReg =
MRI.createVirtualRegister(RC);
22445 Register CmpReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22460 Register F2IReg =
MRI.createVirtualRegister(&RISCV::GPRRegClass);
22482 MI.eraseFromParent();
22489 switch (
MI.getOpcode()) {
22492 case RISCV::ReadCounterWide:
22493 assert(!Subtarget.is64Bit() &&
22494 "ReadCounterWide is only to be used on riscv32");
22496 case RISCV::Select_GPR_Using_CC_GPR:
22497 case RISCV::Select_GPR_Using_CC_SImm5_CV:
22498 case RISCV::Select_GPRNoX0_Using_CC_SImm5NonZero_QC:
22499 case RISCV::Select_GPRNoX0_Using_CC_UImm5NonZero_QC:
22500 case RISCV::Select_GPRNoX0_Using_CC_SImm16NonZero_QC:
22501 case RISCV::Select_GPRNoX0_Using_CC_UImm16NonZero_QC:
22502 case RISCV::Select_GPR_Using_CC_UImmLog2XLen_NDS:
22503 case RISCV::Select_GPR_Using_CC_UImm7_NDS:
22504 case RISCV::Select_FPR16_Using_CC_GPR:
22505 case RISCV::Select_FPR16INX_Using_CC_GPR:
22506 case RISCV::Select_FPR32_Using_CC_GPR:
22507 case RISCV::Select_FPR32INX_Using_CC_GPR:
22508 case RISCV::Select_FPR64_Using_CC_GPR:
22509 case RISCV::Select_FPR64INX_Using_CC_GPR:
22510 case RISCV::Select_FPR64IN32X_Using_CC_GPR:
22512 case RISCV::BuildPairF64Pseudo:
22514 case RISCV::SplitF64Pseudo:
22516 case RISCV::PseudoQuietFLE_H:
22518 case RISCV::PseudoQuietFLE_H_INX:
22519 return emitQuietFCMP(
MI, BB, RISCV::FLE_H_INX, RISCV::FEQ_H_INX, Subtarget);
22520 case RISCV::PseudoQuietFLT_H:
22522 case RISCV::PseudoQuietFLT_H_INX:
22523 return emitQuietFCMP(
MI, BB, RISCV::FLT_H_INX, RISCV::FEQ_H_INX, Subtarget);
22524 case RISCV::PseudoQuietFLE_S:
22526 case RISCV::PseudoQuietFLE_S_INX:
22527 return emitQuietFCMP(
MI, BB, RISCV::FLE_S_INX, RISCV::FEQ_S_INX, Subtarget);
22528 case RISCV::PseudoQuietFLT_S:
22530 case RISCV::PseudoQuietFLT_S_INX:
22531 return emitQuietFCMP(
MI, BB, RISCV::FLT_S_INX, RISCV::FEQ_S_INX, Subtarget);
22532 case RISCV::PseudoQuietFLE_D:
22534 case RISCV::PseudoQuietFLE_D_INX:
22535 return emitQuietFCMP(
MI, BB, RISCV::FLE_D_INX, RISCV::FEQ_D_INX, Subtarget);
22536 case RISCV::PseudoQuietFLE_D_IN32X:
22539 case RISCV::PseudoQuietFLT_D:
22541 case RISCV::PseudoQuietFLT_D_INX:
22542 return emitQuietFCMP(
MI, BB, RISCV::FLT_D_INX, RISCV::FEQ_D_INX, Subtarget);
22543 case RISCV::PseudoQuietFLT_D_IN32X:
22547 case RISCV::PseudoVFROUND_NOEXCEPT_V_M1_MASK:
22549 case RISCV::PseudoVFROUND_NOEXCEPT_V_M2_MASK:
22551 case RISCV::PseudoVFROUND_NOEXCEPT_V_M4_MASK:
22553 case RISCV::PseudoVFROUND_NOEXCEPT_V_M8_MASK:
22555 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF2_MASK:
22557 case RISCV::PseudoVFROUND_NOEXCEPT_V_MF4_MASK:
22559 case RISCV::PseudoFROUND_H:
22560 case RISCV::PseudoFROUND_H_INX:
22561 case RISCV::PseudoFROUND_S:
22562 case RISCV::PseudoFROUND_S_INX:
22563 case RISCV::PseudoFROUND_D:
22564 case RISCV::PseudoFROUND_D_INX:
22565 case RISCV::PseudoFROUND_D_IN32X:
22567 case RISCV::PROBED_STACKALLOC_DYN:
22569 case TargetOpcode::STATEPOINT:
22575 MI.addOperand(*
MI.getMF(),
22581 case TargetOpcode::STACKMAP:
22582 case TargetOpcode::PATCHPOINT:
22583 if (!Subtarget.is64Bit())
22585 "supported on 64-bit targets");
22595 if (
auto *FRMDef =
MI.findRegisterDefOperand(RISCV::FRM,
nullptr)) {
22596 FRMDef->setIsDead(
false);
22600 int Idx = RISCV::getNamedOperandIdx(
MI.getOpcode(), RISCV::OpName::frm);
22610 if (
MI.readsRegister(RISCV::FRM,
nullptr))
22616void RISCVTargetLowering::analyzeInputArgs(
22620 for (
const auto &[Idx, In] :
enumerate(Ins)) {
22626 LLVM_DEBUG(
dbgs() <<
"InputArg #" << Idx <<
" has unhandled type "
22633void RISCVTargetLowering::analyzeOutputArgs(
22637 for (
const auto &[Idx, Out] :
enumerate(Outs)) {
22638 MVT ArgVT = Out.VT;
22639 ISD::ArgFlagsTy ArgFlags = Out.Flags;
22643 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << Idx <<
" has unhandled type "
22660 return DAG.
getNode(RISCVISD::FMV_W_X_RV64,
DL, MVT::f32, Val);
22694 if (In.isOrigArg()) {
22699 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
22700 (
BitWidth < 32 && In.Flags.isZExt())) {
22721 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTH,
DL, LocVT, Val);
22722 if (LocVT == MVT::i64 && VA.
getValVT() == MVT::f32)
22723 return DAG.
getNode(RISCVISD::FMV_X_ANYEXTW_RV64,
DL, MVT::i64, Val);
22735 Val = DAG.
getNode(ISD::BITCAST,
DL, LocVT, Val);
22771 ExtType,
DL, LocVT, Chain, FIN,
22788 Register LoVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
22801 Register HiVReg =
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
22805 return DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64,
Lo,
Hi);
22816 switch (CallConv) {
22825#define CC_VLS_CASE(ABI_VLEN) case CallingConv::RISCV_VLSCall_##ABI_VLEN:
22841 if (Subtarget.hasStdExtE())
22843 if (!Subtarget.hasStdExtFOrZfinx() || !Subtarget.hasStdExtDOrZdinx())
22845 "(Zdinx/D) instruction set extensions");
22849 if (Func.hasFnAttribute(
"interrupt")) {
22850 if (!Func.arg_empty())
22852 "Functions with the interrupt attribute cannot have arguments!");
22863 "SiFive-CLIC-preemptible",
22864 "SiFive-CLIC-stack-swap",
22865 "SiFive-CLIC-preemptible-stack-swap",
22869 "Function interrupt attribute argument not supported!");
22871 if (Kind.starts_with(
"qci-") && !Subtarget.hasVendorXqciint())
22873 "'qci-*' interrupt kinds require Xqciint extension");
22875 if (Kind.starts_with(
"SiFive-CLIC-") && !Subtarget.hasVendorXSfmclic())
22877 "'SiFive-CLIC-*' interrupt kinds require XSfmclic extension");
22879 if (Kind ==
"rnmi" && !Subtarget.hasStdExtSmrnmi())
22882 if (Kind.starts_with(
"SiFive-CLIC-preemptible") && TFI->
hasFP(MF))
22884 "have a frame pointer");
22888 MVT XLenVT = Subtarget.getXLenVT();
22889 unsigned XLenInBytes = Subtarget.getXLen() / 8;
22891 std::vector<SDValue> OutChains;
22900 analyzeInputArgs(MF, CCInfo, Ins,
false,
22904 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
22925 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
22926 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
22928 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
22930 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
22959 int VarArgsSaveSize = XLenInBytes * (ArgRegs.
size() - Idx);
22964 if (VarArgsSaveSize == 0) {
22968 int VaArgOffset = -VarArgsSaveSize;
22976 XLenInBytes, VaArgOffset -
static_cast<int>(XLenInBytes),
true);
22977 VarArgsSaveSize += XLenInBytes;
22984 for (
unsigned I = Idx;
I < ArgRegs.
size(); ++
I) {
22985 const Register Reg = RegInfo.createVirtualRegister(RC);
22986 RegInfo.addLiveIn(ArgRegs[
I], Reg);
22989 Chain,
DL, ArgValue, FIN,
22991 OutChains.push_back(Store);
23005 if (!OutChains.empty()) {
23006 OutChains.push_back(Chain);
23016bool RISCVTargetLowering::isEligibleForTailCallOptimization(
23020 auto CalleeCC = CLI.CallConv;
23021 auto &Outs = CLI.Outs;
23023 auto CallerCC = Caller.getCallingConv();
23030 if (Caller.hasFnAttribute(
"interrupt"))
23045 for (
auto &VA : ArgLocs)
23051 auto IsCallerStructRet = Caller.hasStructRetAttr();
23052 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
23053 if (IsCallerStructRet || IsCalleeStructRet)
23058 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
23059 if (CalleeCC != CallerCC) {
23060 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
23061 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
23068 for (
auto &Arg : Outs)
23069 if (Arg.Flags.isByVal())
23095 MVT XLenVT = Subtarget.getXLenVT();
23110 if (Subtarget.hasStdExtE())
23114 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
23120 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
23126 "call site marked musttail");
23133 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
23135 if (!Flags.isByVal())
23139 unsigned Size = Flags.getByValSize();
23140 Align Alignment = Flags.getNonZeroByValAlign();
23147 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
23149 false,
nullptr, IsTailCall,
23161 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
23164 SDValue ArgValue = OutVals[OutIdx];
23172 RISCVISD::SplitF64,
DL, DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
23184 if (!StackPtr.getNode())
23196 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
23214 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
23215 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
23221 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
23222 SDValue PartValue = OutVals[OutIdx + 1];
23223 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
23237 DAG.
getStore(Chain,
DL, ArgValue, SpillSlot,
23239 for (
const auto &Part : Parts) {
23240 SDValue PartValue = Part.first;
23241 SDValue PartOffset = Part.second;
23248 ArgValue = SpillSlot;
23254 if (Flags.isByVal())
23255 ArgValue = ByValArgs[j++];
23262 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
23263 "for passing parameters");
23266 if (!StackPtr.getNode())
23280 if (!MemOpChains.
empty())
23286 for (
auto &Reg : RegsToPass) {
23287 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
23294 validateCCReservedRegs(RegsToPass, MF);
23298 "Return address register required, but has been reserved."});
23303 bool CalleeIsLargeExternalSymbol =
false;
23309 CalleeIsLargeExternalSymbol =
true;
23320 Ops.push_back(Chain);
23321 Ops.push_back(Callee);
23325 for (
auto &Reg : RegsToPass)
23326 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
23330 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
23331 assert(Mask &&
"Missing call preserved mask for calling convention");
23336 Ops.push_back(Glue);
23339 "Unexpected CFI type for a direct call");
23347 bool NeedSWGuarded =
false;
23349 Subtarget.hasStdExtZicfilp() &&
23351 NeedSWGuarded =
true;
23356 NeedSWGuarded ? RISCVISD::SW_GUARDED_TAIL : RISCVISD::TAIL;
23367 unsigned CallOpc = NeedSWGuarded ? RISCVISD::SW_GUARDED_CALL : RISCVISD::CALL;
23385 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_RISCV);
23388 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
23389 auto &VA = RVLocs[i];
23397 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
23398 assert(VA.needsCustom());
23403 RetValue = DAG.
getNode(RISCVISD::BuildPairF64,
DL, MVT::f64, RetValue,
23417 const Type *RetTy)
const {
23419 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
23421 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
23422 MVT VT = Outs[i].VT;
23425 true, Outs[i].OrigTy))
23457 for (
unsigned i = 0, e = RVLocs.size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
23458 SDValue Val = OutVals[OutIdx];
23467 DAG.
getVTList(MVT::i32, MVT::i32), Val);
23471 Register RegHi = RVLocs[++i].getLocReg();
23477 "Return value register required, but has been reserved."});
23493 "Return value register required, but has been reserved."});
23512 unsigned RetOpc = RISCVISD::RET_GLUE;
23515 if (Func.hasFnAttribute(
"interrupt")) {
23516 if (!Func.getReturnType()->isVoidTy())
23518 "Functions with the interrupt attribute must have void return type!");
23524 if (Kind ==
"supervisor")
23525 RetOpc = RISCVISD::SRET_GLUE;
23526 else if (Kind ==
"rnmi") {
23527 assert(STI.hasFeature(RISCV::FeatureStdExtSmrnmi) &&
23528 "Need Smrnmi extension for rnmi");
23529 RetOpc = RISCVISD::MNRET_GLUE;
23530 }
else if (Kind ==
"qci-nest" || Kind ==
"qci-nonest") {
23531 assert(STI.hasFeature(RISCV::FeatureVendorXqciint) &&
23532 "Need Xqciint for qci-(no)nest");
23533 RetOpc = RISCVISD::QC_C_MILEAVERET_GLUE;
23535 RetOpc = RISCVISD::MRET_GLUE;
23538 return DAG.
getNode(RetOpc,
DL, MVT::Other, RetOps);
23541void RISCVTargetLowering::validateCCReservedRegs(
23542 const SmallVectorImpl<std::pair<llvm::Register, llvm::SDValue>> &Regs,
23551 F,
"Argument register required, but has been reserved."});
23557 if (
N->getNumValues() != 1)
23559 if (!
N->hasNUsesOfValue(1, 0))
23562 SDNode *Copy = *
N->user_begin();
23564 if (Copy->getOpcode() == ISD::BITCAST) {
23576 if (Copy->getOperand(Copy->getNumOperands() - 1).getValueType() == MVT::Glue)
23580 bool HasRet =
false;
23582 if (
Node->getOpcode() != RISCVISD::RET_GLUE)
23589 Chain = Copy->getOperand(0);
23601 if (Constraint.
size() == 1) {
23602 switch (Constraint[0]) {
23619 if (Constraint ==
"vr" || Constraint ==
"vd" || Constraint ==
"vm")
23621 if (Constraint ==
"cr" || Constraint ==
"cR" || Constraint ==
"cf")
23627std::pair<unsigned, const TargetRegisterClass *>
23633 if (Constraint.
size() == 1) {
23634 switch (Constraint[0]) {
23639 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
23640 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
23641 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
23642 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
23643 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23644 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23645 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
23647 if (VT == MVT::f16) {
23648 if (Subtarget.hasStdExtZfhmin())
23649 return std::make_pair(0U, &RISCV::FPR16RegClass);
23650 if (Subtarget.hasStdExtZhinxmin())
23651 return std::make_pair(0U, &RISCV::GPRF16NoX0RegClass);
23652 }
else if (VT == MVT::f32) {
23653 if (Subtarget.hasStdExtF())
23654 return std::make_pair(0U, &RISCV::FPR32RegClass);
23655 if (Subtarget.hasStdExtZfinx())
23656 return std::make_pair(0U, &RISCV::GPRF32NoX0RegClass);
23657 }
else if (VT == MVT::f64) {
23658 if (Subtarget.hasStdExtD())
23659 return std::make_pair(0U, &RISCV::FPR64RegClass);
23660 if (Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23661 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23662 if (Subtarget.hasStdExtZdinx() && Subtarget.is64Bit())
23663 return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
23667 if (((VT == MVT::i64 || VT == MVT::f64) && !Subtarget.is64Bit()) ||
23668 (VT == MVT::i128 && Subtarget.is64Bit()))
23669 return std::make_pair(0U, &RISCV::GPRPairNoX0RegClass);
23674 }
else if (Constraint ==
"vr") {
23675 for (
const auto *RC :
23676 {&RISCV::VRRegClass, &RISCV::VRM2RegClass, &RISCV::VRM4RegClass,
23677 &RISCV::VRM8RegClass, &RISCV::VRN2M1RegClass, &RISCV::VRN3M1RegClass,
23678 &RISCV::VRN4M1RegClass, &RISCV::VRN5M1RegClass,
23679 &RISCV::VRN6M1RegClass, &RISCV::VRN7M1RegClass,
23680 &RISCV::VRN8M1RegClass, &RISCV::VRN2M2RegClass,
23681 &RISCV::VRN3M2RegClass, &RISCV::VRN4M2RegClass,
23682 &RISCV::VRN2M4RegClass}) {
23684 return std::make_pair(0U, RC);
23688 if (
TRI->isTypeLegalForClass(*RC, ContainerVT))
23689 return std::make_pair(0U, RC);
23692 }
else if (Constraint ==
"vd") {
23693 for (
const auto *RC :
23694 {&RISCV::VRNoV0RegClass, &RISCV::VRM2NoV0RegClass,
23695 &RISCV::VRM4NoV0RegClass, &RISCV::VRM8NoV0RegClass,
23696 &RISCV::VRN2M1NoV0RegClass, &RISCV::VRN3M1NoV0RegClass,
23697 &RISCV::VRN4M1NoV0RegClass, &RISCV::VRN5M1NoV0RegClass,
23698 &RISCV::VRN6M1NoV0RegClass, &RISCV::VRN7M1NoV0RegClass,
23699 &RISCV::VRN8M1NoV0RegClass, &RISCV::VRN2M2NoV0RegClass,
23700 &RISCV::VRN3M2NoV0RegClass, &RISCV::VRN4M2NoV0RegClass,
23701 &RISCV::VRN2M4NoV0RegClass}) {
23703 return std::make_pair(0U, RC);
23707 if (
TRI->isTypeLegalForClass(*RC, ContainerVT))
23708 return std::make_pair(0U, RC);
23711 }
else if (Constraint ==
"vm") {
23712 if (
TRI->isTypeLegalForClass(RISCV::VMV0RegClass, VT.
SimpleTy))
23713 return std::make_pair(0U, &RISCV::VMV0RegClass);
23719 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, ContainerVT))
23720 return std::make_pair(0U, &RISCV::VMV0RegClass);
23722 }
else if (Constraint ==
"cr") {
23723 if (VT == MVT::f16 && Subtarget.hasStdExtZhinxmin())
23724 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
23725 if (VT == MVT::f32 && Subtarget.hasStdExtZfinx())
23726 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
23727 if (VT == MVT::f64 && Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23728 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23730 return std::make_pair(0U, &RISCV::GPRCRegClass);
23731 }
else if (Constraint ==
"cR") {
23732 if (((VT == MVT::i64 || VT == MVT::f64) && !Subtarget.is64Bit()) ||
23733 (VT == MVT::i128 && Subtarget.is64Bit()))
23734 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23735 }
else if (Constraint ==
"cf") {
23736 if (VT == MVT::f16) {
23737 if (Subtarget.hasStdExtZfhmin())
23738 return std::make_pair(0U, &RISCV::FPR16CRegClass);
23739 if (Subtarget.hasStdExtZhinxmin())
23740 return std::make_pair(0U, &RISCV::GPRF16CRegClass);
23741 }
else if (VT == MVT::f32) {
23742 if (Subtarget.hasStdExtF())
23743 return std::make_pair(0U, &RISCV::FPR32CRegClass);
23744 if (Subtarget.hasStdExtZfinx())
23745 return std::make_pair(0U, &RISCV::GPRF32CRegClass);
23746 }
else if (VT == MVT::f64) {
23747 if (Subtarget.hasStdExtD())
23748 return std::make_pair(0U, &RISCV::FPR64CRegClass);
23749 if (Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
23750 return std::make_pair(0U, &RISCV::GPRPairCRegClass);
23751 if (Subtarget.hasStdExtZdinx() && Subtarget.is64Bit())
23752 return std::make_pair(0U, &RISCV::GPRCRegClass);
23761 .
Case(
"{zero}", RISCV::X0)
23762 .
Case(
"{ra}", RISCV::X1)
23763 .
Case(
"{sp}", RISCV::X2)
23764 .
Case(
"{gp}", RISCV::X3)
23765 .
Case(
"{tp}", RISCV::X4)
23766 .
Case(
"{t0}", RISCV::X5)
23767 .
Case(
"{t1}", RISCV::X6)
23768 .
Case(
"{t2}", RISCV::X7)
23769 .
Cases(
"{s0}",
"{fp}", RISCV::X8)
23770 .
Case(
"{s1}", RISCV::X9)
23771 .
Case(
"{a0}", RISCV::X10)
23772 .
Case(
"{a1}", RISCV::X11)
23773 .
Case(
"{a2}", RISCV::X12)
23774 .
Case(
"{a3}", RISCV::X13)
23775 .
Case(
"{a4}", RISCV::X14)
23776 .
Case(
"{a5}", RISCV::X15)
23777 .
Case(
"{a6}", RISCV::X16)
23778 .
Case(
"{a7}", RISCV::X17)
23779 .
Case(
"{s2}", RISCV::X18)
23780 .
Case(
"{s3}", RISCV::X19)
23781 .
Case(
"{s4}", RISCV::X20)
23782 .
Case(
"{s5}", RISCV::X21)
23783 .
Case(
"{s6}", RISCV::X22)
23784 .
Case(
"{s7}", RISCV::X23)
23785 .
Case(
"{s8}", RISCV::X24)
23786 .
Case(
"{s9}", RISCV::X25)
23787 .
Case(
"{s10}", RISCV::X26)
23788 .
Case(
"{s11}", RISCV::X27)
23789 .
Case(
"{t3}", RISCV::X28)
23790 .
Case(
"{t4}", RISCV::X29)
23791 .
Case(
"{t5}", RISCV::X30)
23792 .
Case(
"{t6}", RISCV::X31)
23794 if (XRegFromAlias != RISCV::NoRegister)
23795 return std::make_pair(XRegFromAlias, &RISCV::GPRRegClass);
23804 if (Subtarget.hasStdExtF()) {
23806 .
Cases(
"{f0}",
"{ft0}", RISCV::F0_F)
23807 .
Cases(
"{f1}",
"{ft1}", RISCV::F1_F)
23808 .
Cases(
"{f2}",
"{ft2}", RISCV::F2_F)
23809 .
Cases(
"{f3}",
"{ft3}", RISCV::F3_F)
23810 .
Cases(
"{f4}",
"{ft4}", RISCV::F4_F)
23811 .
Cases(
"{f5}",
"{ft5}", RISCV::F5_F)
23812 .
Cases(
"{f6}",
"{ft6}", RISCV::F6_F)
23813 .
Cases(
"{f7}",
"{ft7}", RISCV::F7_F)
23814 .
Cases(
"{f8}",
"{fs0}", RISCV::F8_F)
23815 .
Cases(
"{f9}",
"{fs1}", RISCV::F9_F)
23816 .
Cases(
"{f10}",
"{fa0}", RISCV::F10_F)
23817 .
Cases(
"{f11}",
"{fa1}", RISCV::F11_F)
23818 .
Cases(
"{f12}",
"{fa2}", RISCV::F12_F)
23819 .
Cases(
"{f13}",
"{fa3}", RISCV::F13_F)
23820 .
Cases(
"{f14}",
"{fa4}", RISCV::F14_F)
23821 .
Cases(
"{f15}",
"{fa5}", RISCV::F15_F)
23822 .
Cases(
"{f16}",
"{fa6}", RISCV::F16_F)
23823 .
Cases(
"{f17}",
"{fa7}", RISCV::F17_F)
23824 .
Cases(
"{f18}",
"{fs2}", RISCV::F18_F)
23825 .
Cases(
"{f19}",
"{fs3}", RISCV::F19_F)
23826 .
Cases(
"{f20}",
"{fs4}", RISCV::F20_F)
23827 .
Cases(
"{f21}",
"{fs5}", RISCV::F21_F)
23828 .
Cases(
"{f22}",
"{fs6}", RISCV::F22_F)
23829 .
Cases(
"{f23}",
"{fs7}", RISCV::F23_F)
23830 .
Cases(
"{f24}",
"{fs8}", RISCV::F24_F)
23831 .
Cases(
"{f25}",
"{fs9}", RISCV::F25_F)
23832 .
Cases(
"{f26}",
"{fs10}", RISCV::F26_F)
23833 .
Cases(
"{f27}",
"{fs11}", RISCV::F27_F)
23834 .
Cases(
"{f28}",
"{ft8}", RISCV::F28_F)
23835 .
Cases(
"{f29}",
"{ft9}", RISCV::F29_F)
23836 .
Cases(
"{f30}",
"{ft10}", RISCV::F30_F)
23837 .
Cases(
"{f31}",
"{ft11}", RISCV::F31_F)
23839 if (FReg != RISCV::NoRegister) {
23840 assert(RISCV::F0_F <= FReg && FReg <= RISCV::F31_F &&
"Unknown fp-reg");
23841 if (Subtarget.hasStdExtD() && (VT == MVT::f64 || VT == MVT::Other)) {
23842 unsigned RegNo = FReg - RISCV::F0_F;
23843 unsigned DReg = RISCV::F0_D + RegNo;
23844 return std::make_pair(DReg, &RISCV::FPR64RegClass);
23846 if (VT == MVT::f32 || VT == MVT::Other)
23847 return std::make_pair(FReg, &RISCV::FPR32RegClass);
23848 if (Subtarget.hasStdExtZfhmin() && VT == MVT::f16) {
23849 unsigned RegNo = FReg - RISCV::F0_F;
23850 unsigned HReg = RISCV::F0_H + RegNo;
23851 return std::make_pair(HReg, &RISCV::FPR16RegClass);
23856 if (Subtarget.hasVInstructions()) {
23858 .
Case(
"{v0}", RISCV::V0)
23859 .
Case(
"{v1}", RISCV::V1)
23860 .
Case(
"{v2}", RISCV::V2)
23861 .
Case(
"{v3}", RISCV::V3)
23862 .
Case(
"{v4}", RISCV::V4)
23863 .
Case(
"{v5}", RISCV::V5)
23864 .
Case(
"{v6}", RISCV::V6)
23865 .
Case(
"{v7}", RISCV::V7)
23866 .
Case(
"{v8}", RISCV::V8)
23867 .
Case(
"{v9}", RISCV::V9)
23868 .
Case(
"{v10}", RISCV::V10)
23869 .
Case(
"{v11}", RISCV::V11)
23870 .
Case(
"{v12}", RISCV::V12)
23871 .
Case(
"{v13}", RISCV::V13)
23872 .
Case(
"{v14}", RISCV::V14)
23873 .
Case(
"{v15}", RISCV::V15)
23874 .
Case(
"{v16}", RISCV::V16)
23875 .
Case(
"{v17}", RISCV::V17)
23876 .
Case(
"{v18}", RISCV::V18)
23877 .
Case(
"{v19}", RISCV::V19)
23878 .
Case(
"{v20}", RISCV::V20)
23879 .
Case(
"{v21}", RISCV::V21)
23880 .
Case(
"{v22}", RISCV::V22)
23881 .
Case(
"{v23}", RISCV::V23)
23882 .
Case(
"{v24}", RISCV::V24)
23883 .
Case(
"{v25}", RISCV::V25)
23884 .
Case(
"{v26}", RISCV::V26)
23885 .
Case(
"{v27}", RISCV::V27)
23886 .
Case(
"{v28}", RISCV::V28)
23887 .
Case(
"{v29}", RISCV::V29)
23888 .
Case(
"{v30}", RISCV::V30)
23889 .
Case(
"{v31}", RISCV::V31)
23891 if (VReg != RISCV::NoRegister) {
23892 if (
TRI->isTypeLegalForClass(RISCV::VMRegClass, VT.
SimpleTy))
23893 return std::make_pair(VReg, &RISCV::VMRegClass);
23894 if (
TRI->isTypeLegalForClass(RISCV::VRRegClass, VT.
SimpleTy))
23895 return std::make_pair(VReg, &RISCV::VRRegClass);
23896 for (
const auto *RC :
23897 {&RISCV::VRM2RegClass, &RISCV::VRM4RegClass, &RISCV::VRM8RegClass}) {
23898 if (
TRI->isTypeLegalForClass(*RC, VT.
SimpleTy)) {
23899 VReg =
TRI->getMatchingSuperReg(VReg, RISCV::sub_vrm1_0, RC);
23900 return std::make_pair(VReg, RC);
23906 std::pair<Register, const TargetRegisterClass *> Res =
23912 if (Res.second == &RISCV::GPRF16RegClass ||
23913 Res.second == &RISCV::GPRF32RegClass ||
23914 Res.second == &RISCV::GPRPairRegClass)
23915 return std::make_pair(Res.first, &RISCV::GPRRegClass);
23923 if (ConstraintCode.
size() == 1) {
23924 switch (ConstraintCode[0]) {
23939 if (Constraint.
size() == 1) {
23940 switch (Constraint[0]) {
23947 Subtarget.getXLenVT()));
23978 if (Subtarget.hasStdExtZtso()) {
23980 return Builder.CreateFence(Ord);
23985 return Builder.CreateFence(Ord);
23994 if (Subtarget.hasStdExtZtso()) {
23996 return Builder.CreateFence(Ord);
24002 if (Subtarget.enableTrailingSeqCstFence() &&
isa<StoreInst>(Inst) &&
24021 if (Subtarget.hasForcedAtomics())
24026 if (Subtarget.hasStdExtZacas() &&
24027 (
Size >= 32 || Subtarget.hasStdExtZabha()))
24033 if (
Size < 32 && !Subtarget.hasStdExtZabha())
24045 return Intrinsic::riscv_masked_atomicrmw_xchg;
24047 return Intrinsic::riscv_masked_atomicrmw_add;
24049 return Intrinsic::riscv_masked_atomicrmw_sub;
24051 return Intrinsic::riscv_masked_atomicrmw_nand;
24053 return Intrinsic::riscv_masked_atomicrmw_max;
24055 return Intrinsic::riscv_masked_atomicrmw_min;
24057 return Intrinsic::riscv_masked_atomicrmw_umax;
24059 return Intrinsic::riscv_masked_atomicrmw_umin;
24075 Builder.CreateNot(Mask,
"Inv_Mask"),
24082 unsigned XLen = Subtarget.getXLen();
24085 Type *Tys[] = {Builder.getIntNTy(XLen), AlignedAddr->
getType()};
24091 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
24092 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
24093 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
24106 unsigned ValWidth =
24109 Builder.CreateSub(Builder.getIntN(XLen, XLen - ValWidth), ShiftAmt);
24110 Result = Builder.CreateCall(LrwOpScwLoop,
24111 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
24114 Builder.CreateCall(LrwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
24118 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
24126 if (Subtarget.hasForcedAtomics())
24130 if (!(Subtarget.hasStdExtZabha() && Subtarget.hasStdExtZacas()) &&
24139 unsigned XLen = Subtarget.getXLen();
24140 Value *Ordering = Builder.getIntN(XLen,
static_cast<uint64_t>(Ord));
24141 Intrinsic::ID CmpXchgIntrID = Intrinsic::riscv_masked_cmpxchg;
24143 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
24144 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
24145 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
24147 Type *Tys[] = {Builder.getIntNTy(XLen), AlignedAddr->
getType()};
24148 Value *Result = Builder.CreateIntrinsic(
24149 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, Ordering});
24151 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
24156 EVT DataVT)
const {
24172 return Subtarget.hasStdExtZfhmin();
24174 return Subtarget.hasStdExtF();
24176 return Subtarget.hasStdExtD();
24206 assert(Subtarget.getRealMinVLen() >= 64 &&
"zve32* unsupported");
24208 "RVVBitsPerBlock changed, audit needed");
24217 if (!Subtarget.hasVendorXTHeadMemIdx())
24223 Base =
Op->getOperand(0);
24225 int64_t RHSC = RHS->getSExtValue();
24231 bool isLegalIndexedOffset =
false;
24232 for (
unsigned i = 0; i < 4; i++)
24233 if (
isInt<5>(RHSC >> i) && ((RHSC % (1LL << i)) == 0)) {
24234 isLegalIndexedOffset =
true;
24238 if (!isLegalIndexedOffset)
24255 VT = LD->getMemoryVT();
24256 Ptr = LD->getBasePtr();
24258 VT = ST->getMemoryVT();
24259 Ptr = ST->getBasePtr();
24275 if (Subtarget.hasVendorXCVmem() && !Subtarget.is64Bit()) {
24280 Base = LS->getBasePtr();
24284 if (
Base ==
Op->getOperand(0))
24286 else if (
Base ==
Op->getOperand(1))
24298 VT = LD->getMemoryVT();
24299 Ptr = LD->getBasePtr();
24301 VT = ST->getMemoryVT();
24302 Ptr = ST->getBasePtr();
24326 return VT.
isVector() ? Subtarget.hasVInstructionsF16()
24327 : Subtarget.hasStdExtZfhOrZhinx();
24329 return Subtarget.hasStdExtFOrZfinx();
24331 return Subtarget.hasStdExtDOrZdinx();
24345 const Constant *PersonalityFn)
const {
24350 const Constant *PersonalityFn)
const {
24357 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
24358 Type.getSizeInBits() < Subtarget.getXLen()))
24365 bool IsSigned)
const {
24366 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
24380 const bool HasZmmul = Subtarget.hasStdExtZmmul();
24385 const APInt &Imm = ConstNode->getAPIntValue();
24388 if (Subtarget.hasVendorXqciac() && Imm.isSignedIntN(12))
24392 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
24393 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
24397 if (Subtarget.hasStdExtZba() && !Imm.isSignedIntN(12) &&
24398 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
24399 (Imm - 8).isPowerOf2()))
24404 if (!Imm.isSignedIntN(12) && Imm.countr_zero() < 12 &&
24405 ConstNode->hasOneUse()) {
24406 APInt ImmS = Imm.ashr(Imm.countr_zero());
24407 if ((ImmS + 1).isPowerOf2() || (ImmS - 1).isPowerOf2() ||
24408 (1 - ImmS).isPowerOf2())
24431 if (C1.
isSignedIntN(12) && !(C1 * C2).isSignedIntN(12))
24440 unsigned *
Fast)
const {
24443 *
Fast = Subtarget.enableUnalignedScalarMem();
24444 return Subtarget.enableUnalignedScalarMem();
24460 *
Fast = Subtarget.enableUnalignedVectorMem();
24461 return Subtarget.enableUnalignedVectorMem();
24466 const AttributeList &FuncAttributes)
const {
24467 if (!Subtarget.hasVInstructions())
24470 if (FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat))
24482 const unsigned MinVLenInBytes =
24483 std::min(Subtarget.getRealMinVLen() / 8, 1024U);
24485 if (
Op.size() < MinVLenInBytes)
24500 MVT PreferredVT = (
Op.isMemset() && !
Op.isZeroMemset()) ? MVT::i8 : ELenVT;
24504 if (PreferredVT != MVT::i8 && !Subtarget.enableUnalignedVectorMem()) {
24506 if (
Op.isFixedDstAlign())
24507 RequiredAlign = std::min(RequiredAlign,
Op.getDstAlign());
24509 RequiredAlign = std::min(RequiredAlign,
Op.getSrcAlign());
24517 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
24518 bool IsABIRegCopy = CC.has_value();
24521 MVT PairVT = Subtarget.is64Bit() ? MVT::i128 : MVT::i64;
24522 if ((ValueVT == PairVT ||
24523 (!Subtarget.is64Bit() && Subtarget.hasStdExtZdinx() &&
24524 ValueVT == MVT::f64)) &&
24525 NumParts == 1 && PartVT == MVT::Untyped) {
24527 MVT XLenVT = Subtarget.getXLenVT();
24528 if (ValueVT == MVT::f64)
24533 Parts[0] = DAG.
getNode(RISCVISD::BuildGPRPair,
DL, PartVT,
Lo,
Hi);
24537 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
24538 PartVT == MVT::f32) {
24541 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::i16, Val);
24545 Val = DAG.
getNode(ISD::BITCAST,
DL, PartVT, Val);
24553 [[maybe_unused]]
unsigned ValLMUL =
24557 [[maybe_unused]]
unsigned PartLMUL =
24560 assert(ValNF == PartNF && ValLMUL == PartLMUL &&
24561 "RISC-V vector tuple type only accepts same register class type "
24582 if (PartVTBitSize % ValueVTBitSize == 0) {
24583 assert(PartVTBitSize >= ValueVTBitSize);
24590 if (ValueEltVT != PartEltVT) {
24591 if (PartVTBitSize > ValueVTBitSize) {
24593 assert(
Count != 0 &&
"The number of element should not be zero.");
24594 EVT SameEltTypeVT =
24598 Val = DAG.
getNode(ISD::BITCAST,
DL, PartVT, Val);
24612 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
24613 bool IsABIRegCopy = CC.has_value();
24615 MVT PairVT = Subtarget.is64Bit() ? MVT::i128 : MVT::i64;
24616 if ((ValueVT == PairVT ||
24617 (!Subtarget.is64Bit() && Subtarget.hasStdExtZdinx() &&
24618 ValueVT == MVT::f64)) &&
24619 NumParts == 1 && PartVT == MVT::Untyped) {
24621 MVT XLenVT = Subtarget.getXLenVT();
24630 if (ValueVT == MVT::f64)
24635 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
24636 PartVT == MVT::f32) {
24640 Val = DAG.
getNode(ISD::BITCAST,
DL, MVT::i32, Val);
24642 Val = DAG.
getNode(ISD::BITCAST,
DL, ValueVT, Val);
24658 if (PartVTBitSize % ValueVTBitSize == 0) {
24659 assert(PartVTBitSize >= ValueVTBitSize);
24660 EVT SameEltTypeVT = ValueVT;
24667 if (ValueEltVT != PartEltVT) {
24669 assert(
Count != 0 &&
"The number of element should not be zero.");
24672 Val = DAG.
getNode(ISD::BITCAST,
DL, SameEltTypeVT, Val);
24688 bool OptSize = Attr.hasFnAttr(Attribute::MinSize);
24695 unsigned Opc =
N->getOpcode();
24704 M, Intrinsic::thread_pointer, IRB.
getPtrTy());
24712 if (Subtarget.isTargetFuchsia())
24718 if (Subtarget.isTargetAndroid())
24723 if (M->getStackProtectorGuard() ==
"tls") {
24725 int Offset = M->getStackProtectorGuardOffset();
24733 Align Alignment)
const {
24734 if (!Subtarget.hasVInstructions())
24738 if (DataType.isFixedLengthVector() && !Subtarget.useRVVForFixedLengthVectors())
24745 if (!Subtarget.enableUnalignedVectorMem() &&
24757 "Invalid call instruction for a KCFI check");
24759 MBBI->getOpcode()));
24762 Target.setIsRenamable(
false);
24770#define GET_REGISTER_MATCHER
24771#include "RISCVGenAsmMatcher.inc"
24782 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
24783 if (!ReservedRegs.
test(Reg) && !Subtarget.isRegisterReservedByUser(Reg))
24791 const MDNode *NontemporalInfo =
I.getMetadata(LLVMContext::MD_nontemporal);
24793 if (NontemporalInfo ==
nullptr)
24801 int NontemporalLevel = 5;
24802 const MDNode *RISCVNontemporalInfo =
24803 I.getMetadata(
"riscv-nontemporal-domain");
24804 if (RISCVNontemporalInfo !=
nullptr)
24811 assert((1 <= NontemporalLevel && NontemporalLevel <= 5) &&
24812 "RISC-V target doesn't support this non-temporal domain.");
24814 NontemporalLevel -= 2;
24816 if (NontemporalLevel & 0b1)
24818 if (NontemporalLevel & 0b10)
24831 return TargetFlags;
24841 return isTypeLegal(VT) && Subtarget.hasStdExtZvbb();
24844 return Subtarget.hasStdExtZbb() &&
24855 if (Subtarget.hasStdExtZalasr()) {
24856 if (Subtarget.hasStdExtZtso()) {
24886 if (
Op == Instruction::Add ||
Op == Instruction::Sub ||
24887 Op == Instruction::And ||
Op == Instruction::Or ||
24888 Op == Instruction::Xor ||
Op == Instruction::InsertElement ||
24889 Op == Instruction::ShuffleVector ||
Op == Instruction::Load ||
24890 Op == Instruction::Freeze ||
Op == Instruction::Store)
24902 if (AI->getAllocatedType()->isScalableTy())
24910RISCVTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
24918 if (!Subtarget.hasShortForwardBranchOpt())
24920 EVT VT =
N->getValueType(0);
24921 if (!(VT == MVT::i32 || (VT == MVT::i64 && Subtarget.
is64Bit())))
24925 if (Divisor.
sgt(2048) || Divisor.
slt(-2048))
24930bool RISCVTargetLowering::shouldFoldSelectWithSingleBitTest(
24931 EVT VT,
const APInt &AndMask)
const {
24933 return !Subtarget.hasStdExtZbs() && AndMask.
ugt(1024);
24938 return Subtarget.getMinimumJumpTableEntries();
24945 if (Subtarget.hasStdExtZicfilp()) {
24952 return DAG.
getNode(RISCVISD::SW_GUARDED_BRIND, dl, MVT::Other, Chain, Addr);
24969std::pair<const TargetRegisterClass *, uint8_t>
24989#define GET_RISCVVIntrinsicsTable_IMPL
24990#include "RISCVGenSearchableTables.inc"
25005 Align StackAlign)
const {
25009 unsigned StackProbeSize =
25013 return StackProbeSize ? StackProbeSize : StackAlign.
value();
25030 EVT VT =
Op.getValueType();
25041 Chain = DAG.
getNode(RISCVISD::PROBED_ALLOCA, dl, MVT::Other, Chain, SP);
25051 Register TargetReg =
MI.getOperand(0).getReg();
25054 bool IsRV64 = Subtarget.is64Bit();
25055 Align StackAlign = Subtarget.getFrameLowering()->getStackAlign();
25062 MF.
insert(MBBInsertPoint, LoopTestMBB);
25064 MF.
insert(MBBInsertPoint, ExitMBB);
25080 TII->get(IsRV64 ? RISCV::SD : RISCV::SW))
25101 MBB->addSuccessor(LoopTestMBB);
25103 MI.eraseFromParent();
25105 return ExitMBB->
begin()->getParent();
25109 if (Subtarget.hasStdExtFOrZfinx()) {
25110 static const MCPhysReg RCRegs[] = {RISCV::FRM, RISCV::FFLAGS};
unsigned const MachineRegisterInfo * MRI
static MCRegister MatchRegisterName(StringRef Name)
static EVT getContainerForFixedLengthVector(SelectionDAG &DAG, EVT VT)
static SDValue performSHLCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
If the operand is a bitwise AND with a constant RHS, and the shift has a constant RHS and is the only...
static SDValue performORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const AArch64Subtarget *Subtarget, const AArch64TargetLowering &TLI)
static SDValue performANDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG)
static SDValue tryWidenMaskForShuffle(SDValue Op, SelectionDAG &DAG)
static SDValue performSETCCCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
static SDValue convertToScalableVector(SelectionDAG &DAG, EVT VT, SDValue V)
static SDValue convertFromScalableVector(SelectionDAG &DAG, EVT VT, SDValue V)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isConstant(const MachineInstr &MI)
AMDGPU Register Bank Select
static bool isZeroOrAllOnes(SDValue N, bool AllOnes)
static SDValue combineSelectAndUseCommutative(SDNode *N, bool AllOnes, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp, TargetLowering::DAGCombinerInfo &DCI, bool AllOnes=false)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static MCRegister MatchRegisterAltName(StringRef Name)
Maps from the set of all alternative registernames to a register number.
Function Alias Analysis Results
static SDValue getTargetNode(GlobalAddressSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, unsigned Flags)
static GCRegistry::Add< 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).
mir Rename Register Operands
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 bool isLowSourceShuffle(ArrayRef< int > Mask, int Span)
Is this mask only using elements from the first span of the input?
static bool isZipOdd(const std::array< std::pair< int, int >, 2 > &SrcInfo, ArrayRef< int > Mask, unsigned &Factor)
Given a shuffle which can be represented as a pair of two slides, see if it is a zipodd idiom.
static SDValue lowerVZIP(unsigned Opc, SDValue Op0, SDValue Op1, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerBuildVectorOfConstants(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue performVECREDUCECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue lowerVECTOR_SHUFFLEAsVSlide1(const SDLoc &DL, MVT VT, SDValue V1, SDValue V2, ArrayRef< int > Mask, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
Match v(f)slide1up/down idioms.
static SDValue combineTruncToVnclip(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::optional< APInt > getExactInteger(const APFloat &APF, uint32_t BitWidth)
static SDValue performVP_TRUNCATECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isInterleaveShuffle(ArrayRef< int > Mask, MVT VT, int &EvenSrc, int &OddSrc, const RISCVSubtarget &Subtarget)
Is this shuffle interleaving contiguous elements from one vector into the even elements and contiguou...
static bool narrowIndex(SDValue &N, ISD::MemIndexType IndexType, SelectionDAG &DAG)
According to the property that indexed load/store instructions zero-extend their indices,...
static SDValue getSingleShuffleSrc(MVT VT, SDValue V1, SDValue V2)
static unsigned getPACKOpcode(unsigned DestBW, const RISCVSubtarget &Subtarget)
static void promoteVCIXScalar(const SDValue &Op, SmallVectorImpl< SDValue > &Operands, SelectionDAG &DAG)
static SDValue splatSplitI64WithVL(const SDLoc &DL, MVT VT, SDValue Passthru, SDValue Scalar, SDValue VL, SelectionDAG &DAG)
static bool isLegalBitRotate(ArrayRef< int > Mask, EVT VT, const RISCVSubtarget &Subtarget, MVT &RotateVT, unsigned &RotateAmt)
static SDValue splatPartsI64WithVL(const SDLoc &DL, MVT VT, SDValue Passthru, SDValue Lo, SDValue Hi, SDValue VL, SelectionDAG &DAG)
static SDValue getWideningInterleave(SDValue EvenV, SDValue OddV, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue getAllOnesMask(MVT VecVT, SDValue VL, const SDLoc &DL, SelectionDAG &DAG)
Creates an all ones mask suitable for masking a vector of type VecTy with vector length VL.
static SDValue simplifyOp_VL(SDNode *N)
static cl::opt< int > FPImmCost(DEBUG_TYPE "-fpimm-cost", cl::Hidden, cl::desc("Give the maximum number of instructions that we will " "use for creating a floating-point immediate value"), cl::init(2))
static SDValue lowerScalarSplat(SDValue Passthru, SDValue Scalar, SDValue VL, MVT VT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isAlternating(const std::array< std::pair< int, int >, 2 > &SrcInfo, ArrayRef< int > Mask, unsigned Factor, bool RequiredPolarity)
static const RISCV::RISCVMaskedPseudoInfo * lookupMaskedIntrinsic(uint16_t MCOpcode, RISCVVType::VLMUL LMul, unsigned SEW)
static SDValue expandMul(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue performVWADDSUBW_VLCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static bool matchIndexAsWiderOp(EVT VT, SDValue Index, SDValue Mask, Align BaseAlign, const RISCVSubtarget &ST)
Match the index of a gather or scatter operation as an operation with twice the element width and hal...
static SDValue combineOp_VLToVWOp_VL(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
Combine a binary or FMA operation to its equivalent VW or VW_W form.
static SDValue combineVFMADD_VLWithVFNEG_VL(SDNode *N, SelectionDAG &DAG)
static SDValue combineOrOfCZERO(SDNode *N, SDValue N0, SDValue N1, SelectionDAG &DAG)
static SDValue useInversedSetcc(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static cl::opt< bool > ReassocShlAddiAdd("reassoc-shl-addi-add", cl::Hidden, cl::desc("Swap add and addi in cases where the add may " "be combined with a shift"), cl::init(true))
static SDValue lowerDisjointIndicesShuffle(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Given a shuffle where the indices are disjoint between the two sources, e.g.:
static SDValue combineVWADDSUBWSelect(SDNode *N, SelectionDAG &DAG)
static MachineBasicBlock * EmitLoweredCascadedSelect(MachineInstr &First, MachineInstr &Second, MachineBasicBlock *ThisMBB, const RISCVSubtarget &Subtarget)
static SDValue performINSERT_VECTOR_ELTCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue lowerFABSorFNEG(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerFMAXIMUM_FMINIMUM(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue foldReduceOperandViaVQDOT(SDValue InVec, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue reverseZExtICmpCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue SplitStrictFPVectorOp(SDValue Op, SelectionDAG &DAG)
static SDValue tryDemorganOfBooleanCondition(SDValue Cond, SelectionDAG &DAG)
static SDValue performMemPairCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue combineDeMorganOfBoolean(SDNode *N, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLEAsVSlidedown(const SDLoc &DL, MVT VT, SDValue V1, SDValue V2, ArrayRef< int > Mask, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
static SDValue reduceANDOfAtomicLoad(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static unsigned getRVVReductionOp(unsigned ISDOpcode)
static SDValue combineSubShiftToOrcB(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerShuffleViaVRegSplitting(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue getVCIXISDNodeVOID(SDValue &Op, SelectionDAG &DAG, unsigned Type)
static SDValue lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static cl::opt< unsigned > NumRepeatedDivisors(DEBUG_TYPE "-fp-repeated-divisors", cl::Hidden, cl::desc("Set the minimum number of repetitions of a divisor to allow " "transformation to multiplications by the reciprocal"), cl::init(2))
static SDValue foldSelectOfCTTZOrCTLZ(SDNode *N, SelectionDAG &DAG)
static SDValue lowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerFixedVectorSegLoadIntrinsics(unsigned IntNo, SDValue Op, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
static SDValue combineVectorMulToSraBitcast(SDNode *N, SelectionDAG &DAG)
static bool isLocalRepeatingShuffle(ArrayRef< int > Mask, int Span)
Is this mask local (i.e.
static bool legalizeScatterGatherIndexType(SDLoc DL, SDValue &Index, ISD::MemIndexType &IndexType, RISCVTargetLowering::DAGCombinerInfo &DCI)
static bool isSpanSplatShuffle(ArrayRef< int > Mask, int Span)
Return true for a mask which performs an arbitrary shuffle within the first span, and then repeats th...
static SDValue getVSlidedown(SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const SDLoc &DL, EVT VT, SDValue Passthru, SDValue Op, SDValue Offset, SDValue Mask, SDValue VL, unsigned Policy=RISCVVType::TAIL_UNDISTURBED_MASK_UNDISTURBED)
static unsigned getRISCVVLOp(SDValue Op)
Get a RISC-V target specified VL op for a given SDNode.
static unsigned getVecReduceOpcode(unsigned Opc)
Given a binary operator, return the associative generic ISD::VECREDUCE_OP which corresponds to it.
static std::pair< SDValue, SDValue > getDefaultVLOps(uint64_t NumElts, MVT ContainerVT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static bool isPromotedOpNeedingSplit(SDValue Op, const RISCVSubtarget &Subtarget)
static SDValue performFP_TO_INT_SATCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue lowerReductionSeq(unsigned RVVOpcode, MVT ResVT, SDValue StartValue, SDValue Vec, SDValue Mask, SDValue VL, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Helper to lower a reduction sequence of the form: scalar = reduce_op vec, scalar_start.
static SDValue expandMulToAddOrSubOfShl(SDNode *N, SelectionDAG &DAG, uint64_t MulAmt)
static SDValue performVP_REVERSECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerGetVectorLength(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::pair< SDValue, SDValue > getDefaultScalableVLOps(MVT VecVT, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue getVLOperand(SDValue Op)
static SDValue performVECTOR_SHUFFLECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
static SDValue performVP_STORECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static MachineBasicBlock * emitFROUND(MachineInstr &MI, MachineBasicBlock *MBB, const RISCVSubtarget &Subtarget)
static SDValue getLargeExternalSymbol(ExternalSymbolSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG)
static SDValue lowerCttzElts(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
const uint64_t ModeMask64
static SDValue lowerVectorIntrinsicScalars(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static cl::opt< unsigned > ExtensionMaxWebSize(DEBUG_TYPE "-ext-max-web-size", cl::Hidden, cl::desc("Give the maximum size (in number of nodes) of the web of " "instructions that we will consider for VW expansion"), cl::init(18))
static SDValue combineShlAddIAddImpl(SDNode *N, SDValue AddI, SDValue Other, SelectionDAG &DAG)
static SDValue getDeinterleaveShiftAndTrunc(const SDLoc &DL, MVT VT, SDValue Src, unsigned Factor, unsigned Index, SelectionDAG &DAG)
static SDValue combineBinOpOfZExt(SDNode *N, SelectionDAG &DAG)
static bool matchSelectAddSub(SDValue TrueVal, SDValue FalseVal, bool &SwapCC)
static SDValue performSIGN_EXTEND_INREGCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue combineXorToBitfieldInsert(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 void processVCIXOperands(SDValue &OrigOp, SmallVectorImpl< SDValue > &Operands, SelectionDAG &DAG)
static SDValue widenVectorOpsToi8(SDValue N, const SDLoc &DL, SelectionDAG &DAG)
static SDValue lowerINT_TO_FP(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerVectorFTRUNC_FCEIL_FFLOOR_FROUND(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue lowerFTRUNC_FCEIL_FFLOOR_FROUND(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static std::optional< VIDSequence > isSimpleVIDSequence(SDValue Op, unsigned EltSizeInBits)
static SDValue lowerVectorXRINT_XROUND(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static uint64_t computeGREVOrGORC(uint64_t x, unsigned ShAmt, bool IsGORC)
static SDValue lowerVECTOR_SHUFFLEAsRotate(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static 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 MVT getQDOTXResultType(MVT OpVT)
static SDValue lowerVECTOR_SHUFFLEAsVSlideup(const SDLoc &DL, MVT VT, SDValue V1, SDValue V2, ArrayRef< int > Mask, const RISCVSubtarget &Subtarget, SelectionDAG &DAG)
static SDValue getVCIXISDNodeWCHAIN(SDValue &Op, SelectionDAG &DAG, unsigned Type)
static SDValue getLargeGlobalAddress(GlobalAddressSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG)
static MachineBasicBlock * emitReadCounterWidePseudo(MachineInstr &MI, MachineBasicBlock *BB)
static SDValue getWideningSpread(SDValue V, unsigned Factor, unsigned Index, const SDLoc &DL, SelectionDAG &DAG)
static cl::opt< bool > AllowSplatInVW_W(DEBUG_TYPE "-form-vw-w-with-splat", cl::Hidden, cl::desc("Allow the formation of VW_W operations (e.g., " "VWADD_W) with splat constants"), cl::init(false))
static SDValue unpackF64OnRV32DSoftABI(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const CCValAssign &HiVA, const SDLoc &DL)
static SDValue foldConcatVector(SDValue V1, SDValue V2)
If concat_vector(V1,V2) could be folded away to some existing vector source, return it.
static SDValue tryMemPairCombine(SelectionDAG &DAG, LSBaseSDNode *LSNode1, LSBaseSDNode *LSNode2, SDValue BasePtr, uint64_t Imm)
static std::tuple< unsigned, SDValue, SDValue > getRVVFPReductionOpAndOperands(SDValue Op, SelectionDAG &DAG, EVT EltVT, const RISCVSubtarget &Subtarget)
static SDValue performFP_TO_INTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget)
static SDValue combineBinOpOfExtractToReduceTree(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Perform two related transforms whose purpose is to incrementally recognize an explode_vector followed...
static SDValue lowerBuildVectorViaPacking(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Double the element size of the build vector to reduce the number of vslide1down in the build vector c...
static SDValue performTRUNCATECombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
static SDValue 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 combineVectorSizedSetCCEquality(EVT VT, SDValue X, SDValue Y, ISD::CondCode CC, const SDLoc &DL, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)
Try to map an integer comparison with size > XLEN to vector instructions before type legalization spl...
static SDValue performBUILD_VECTORCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget, const RISCVTargetLowering &TLI)
If we have a build_vector where each lane is binop X, C, where C is a constant (but not necessarily t...
static LLT getMaskTypeFor(LLT VecTy)
Return the type of the mask type suitable for masking the provided vector type.
static unsigned getRISCVWOpcode(unsigned Opcode)
const SmallVectorImpl< MachineOperand > & Cond
Contains matchers for matching SelectionDAG nodes and values.
static bool isCommutative(Instruction *I, Value *ValWithUses)
static Type * getValueType(Value *V)
Returns the type of the given value/instruction V.
This file defines the SmallSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static 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[]
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.
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
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
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 ...
bool isDesirableToCommuteWithShift(const SDNode *N, CombineLevel Level) const override
Return true if it is profitable to move this shift by a constant amount through its operand,...
bool areTwoSDNodeTargetMMOFlagsMergeable(const MemSDNode &NodeX, const MemSDNode &NodeY) const override
Return true if it is valid to merge the TargetMMOFlags in two SDNodes.
bool hasBitTest(SDValue X, SDValue Y) const override
Return true if the target has a bit-test instruction: (X & (1 << Y)) ==/!= 0 This knowledge can be us...
static unsigned computeVLMAX(unsigned VectorBits, unsigned EltSize, unsigned MinSize)
bool shouldExpandCttzElements(EVT VT) const override
Return true if the @llvm.experimental.cttz.elts intrinsic should be expanded using generic code in Se...
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
Value * emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, AtomicCmpXchgInst *CI, Value *AlignedAddr, Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const override
Perform a masked cmpxchg using a target-specific intrinsic.
bool isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize) const override
Returns true if the target can instruction select the specified FP immediate natively.
InstructionCost getLMULCost(MVT VT) const
Return the cost of LMUL for linear operations.
unsigned getJumpTableEncoding() const override
Return the entry encoding for a jump table in the current function.
bool isMulAddWithConstProfitable(SDValue AddNode, SDValue ConstNode) const override
Return true if it may be profitable to transform (mul (add x, c1), c2) -> (add (mul x,...
InstructionCost getVSlideVICost(MVT VT) const
Return the cost of a vslidedown.vi or vslideup.vi instruction for the type VT.
bool fallBackToDAGISel(const Instruction &Inst) const override
EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
bool isCtpopFast(EVT VT) const override
Return true if ctpop instruction is fast.
unsigned ComputeNumSignBitsForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, unsigned Depth) const override
This method can be implemented by targets that want to expose additional information about sign bits ...
MVT getContainerForFixedLengthVector(MVT VT) const
static unsigned getRegClassIDForVecVT(MVT VT)
Register getExceptionPointerRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
TargetLowering::AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
bool isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return true if EXTRACT_SUBVECTOR is cheap for extracting this result type from this source type with ...
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
MachineBasicBlock * emitDynamicProbedAlloc(MachineInstr &MI, MachineBasicBlock *MBB) const
MachineMemOperand::Flags getTargetMMOFlags(const Instruction &I) const override
This callback is used to inspect load/store instructions and add target-specific MachineMemOperand fl...
SDValue computeVLMax(MVT VecVT, const SDLoc &DL, SelectionDAG &DAG) const
bool signExtendConstant(const ConstantInt *CI) const override
Return true if this constant should be sign extended when promoting to a larger type.
bool shouldTransformSignedTruncationCheck(EVT XVT, unsigned KeptBits) const override
Should we tranform the IR-optimal check for whether given truncation down into KeptBits would be trun...
bool shouldProduceAndByConstByHoistingConstFromShiftsLHSOfAnd(SDValue X, ConstantSDNode *XC, ConstantSDNode *CC, SDValue Y, unsigned OldShiftOpcode, unsigned NewShiftOpcode, SelectionDAG &DAG) const override
Given the pattern (X & (C l>>/<< Y)) ==/!= 0 return true if it should be transformed into: ((X <</l>>...
bool hasInlineStackProbe(const MachineFunction &MF) const override
True if stack clash protection is enabled for this functions.
bool hasAndNot(SDValue Y) const override
Return true if the target has a bitwise and-not operation: X = ~A & B This can be used to simplify se...
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Returns the register with the specified architectural or ABI name.
InstructionCost getVSlideVXCost(MVT VT) const
Return the cost of a vslidedown.vx or vslideup.vx instruction for the type VT.
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override
Return true if result of the specified node is used by a return node only.
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const override
Return true if an FMA operation is faster than a pair of fmul and fadd instructions.
TargetLowering::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *CI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
Register getExceptionSelectorRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
unsigned getCustomCtpopCost(EVT VT, ISD::CondCode Cond) const override
Return the maximum number of "x & (x - 1)" operations that can be done instead of deferring to a cust...
void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override
This method should be implemented by targets that mark instructions with the 'hasPostISelHook' flag.
bool isShuffleMaskLegal(ArrayRef< int > M, EVT VT) const override
Return true if the given shuffle mask can be codegen'd directly, or if it should be stack expanded.
bool isCheapToSpeculateCttz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic cttz.
bool isLegalICmpImmediate(int64_t Imm) const override
Return true if the specified immediate is legal icmp immediate, that is the target has icmp instructi...
ISD::NodeType getExtendForAtomicCmpSwapArg() const override
Returns how the platform's atomic compare and swap expects its comparison value to be extended (ZERO_...
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower the incoming (formal) arguments, described by the Ins array,...
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I, MachineFunction &MF, unsigned Intrinsic) const override
Given an intrinsic, checks if on the target the intrinsic will need to map to a MemIntrinsicNode (tou...
unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const override
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
bool isLegalElementTypeForRVV(EVT ScalarTy) const
bool isVScaleKnownToBeAPowerOfTwo() const override
Return true only if vscale must be a power of two.
int getLegalZfaFPImm(const APFloat &Imm, EVT VT) const
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
Lower the specified operand into the Ops vector.
bool splitValueIntoRegisterParts(SelectionDAG &DAG, const SDLoc &DL, SDValue Val, SDValue *Parts, unsigned NumParts, MVT PartVT, std::optional< CallingConv::ID > CC) const override
Target-specific splitting of values into parts that fit a register storing a legal type.
Instruction * emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Return the number of registers for a given MVT, ensuring vectors are treated as a series of gpr sized...
ConstraintType getConstraintType(StringRef Constraint) const override
getConstraintType - Given a constraint letter, return the type of constraint it is for this target.
MachineInstr * EmitKCFICheck(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator &MBBI, const TargetInstrInfo *TII) const override
bool canCreateUndefOrPoisonForTargetNode(SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool PoisonOnly, bool ConsiderFlags, unsigned Depth) const override
Return true if Op can create undef or poison from non-undef & non-poison operands.
bool isIntDivCheap(EVT VT, AttributeList Attr) const override
Return true if integer divide is usually cheaper than a sequence of several shifts,...
SDValue expandIndirectJTBranch(const SDLoc &dl, SDValue Value, SDValue Addr, int JTI, SelectionDAG &DAG) const override
Expands target specific indirect branch for the case of JumpTable expansion.
static unsigned getRegClassIDForLMUL(RISCVVType::VLMUL LMul)
unsigned getNumRegisters(LLVMContext &Context, EVT VT, std::optional< MVT > RegisterVT=std::nullopt) const override
Return the number of registers for a given MVT, for inline assembly.
bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
Returns true by value, base pointer and offset pointer and addressing mode by reference if this node ...
bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
Returns true by value, base pointer and offset pointer and addressing mode by reference if the node's...
SDValue joinRegisterPartsIntoValue(SelectionDAG &DAG, const SDLoc &DL, const SDValue *Parts, unsigned NumParts, MVT PartVT, EVT ValueVT, std::optional< CallingConv::ID > CC) const override
Target-specific combining of register parts into its original value.
bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const override
Return if the target supports combining a chain like:
bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override
Return true if sign-extension from FromTy to ToTy is cheaper than zero-extension.
bool isLegalStridedLoadStore(EVT DataType, Align Alignment) const
Return true if a stride load store of the given result type and alignment is legal.
static bool isSpreadMask(ArrayRef< int > Mask, unsigned Factor, unsigned &Index)
Match a mask which "spreads" the leading elements of a vector evenly across the result.
static RISCVVType::VLMUL getLMUL(MVT VT)
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
bool SimplifyDemandedBitsForTargetNode(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth) const override
Attempt to simplify any target nodes based on the demanded bits/elts, returning true on success.
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
bool shouldFoldSelectWithIdentityConstant(unsigned BinOpcode, EVT VT, unsigned SelectOpcode, SDValue X, SDValue Y) const override
Return true if pulling a binary operation into a select with an identity constant is profitable.
unsigned getStackProbeSize(const MachineFunction &MF, Align StackAlign) const
bool shouldInsertFencesForAtomic(const Instruction *I) const override
Whether AtomicExpandPass should automatically insert fences and reduce ordering for this atomic.
Wrapper class representing virtual and physical registers.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
ArrayRef< SDUse > ops() const
const APInt & getAsAPIntVal() const
Helper method returns the APInt value of a ConstantSDNode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
iterator_range< use_iterator > uses()
SDNodeFlags getFlags() const
size_t use_size() const
Return the number of uses of this node.
MVT getSimpleValueType(unsigned ResNo) const
Return the type of a specified result as a simple type.
static bool hasPredecessorHelper(const SDNode *N, SmallPtrSetImpl< const SDNode * > &Visited, SmallVectorImpl< const SDNode * > &Worklist, unsigned int MaxSteps=0, bool TopologicalPrune=false)
Returns true if N is a predecessor of any node in Worklist.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
const SDValue & getOperand(unsigned Num) const
std::optional< APInt > bitcastToAPInt() const
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
void setCFIType(uint32_t Type)
bool isUndef() const
Returns true if the node type is UNDEF or POISON.
iterator_range< user_iterator > users()
Represents a use of a SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
const APInt & getConstantOperandAPInt(unsigned i) const
uint64_t getScalarValueSizeInBits() const
uint64_t getConstantOperandVal(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getOpcode() const
unsigned getNumOperands() const
virtual bool isTargetStrictFPOpcode(unsigned Opcode) const
Returns true if a node with the given target-specific opcode has strict floating-point semantics.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI Align getReducedAlign(EVT VT, bool UseABI)
In most cases this function returns the ABI alignment for a given type, except for illegal vector typ...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
SDValue getExtractVectorElt(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Extract element at Idx from Vec.
LLVM_ABI unsigned ComputeMaxSignificantBits(SDValue Op, unsigned Depth=0) const
Get the upper bound on bit size for this Value Op as a signed integer.
LLVM_ABI SDValue getMaskedGather(SDVTList VTs, EVT MemVT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType, ISD::LoadExtType ExtTy)
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL)
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDValue getNeutralElement(unsigned Opcode, const SDLoc &DL, EVT VT, SDNodeFlags Flags)
Get the (commutative) neutral element for the given opcode, if it exists.
LLVM_ABI SDValue getAtomicLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT MemVT, EVT VT, SDValue Chain, SDValue Ptr, MachineMemOperand *MMO)
LLVM_ABI SDValue getVScale(const SDLoc &DL, EVT VT, APInt MulImm, bool ConstantFold=true)
Return a node that represents the runtime scaling 'MulImm * RuntimeVL'.
LLVM_ABI SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
LLVM_ABI SDValue getStridedLoadVP(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, const SDLoc &DL, SDValue Chain, SDValue Ptr, SDValue Offset, SDValue Stride, SDValue Mask, SDValue EVL, EVT MemVT, MachineMemOperand *MMO, bool IsExpanding=false)
LLVM_ABI SDValue makeEquivalentMemoryOrdering(SDValue OldChain, SDValue NewMemOpChain)
If an existing load has uses of its chain, create a token factor node with that chain and the new mem...
LLVM_ABI SDValue getJumpTableDebugInfo(int JTI, SDValue Chain, const SDLoc &DL)
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false)
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
bool isSafeToSpeculativelyExecute(unsigned Opcode) const
Some opcodes may create immediate undefined behavior when used with some values (integer division-by-...
LLVM_ABI SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
SDValue getExtractSubvector(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Return the VT typed sub-vector of Vec at Idx.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getElementCount(const SDLoc &DL, EVT VT, ElementCount EC, bool ConstantFold=true)
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef< SDValue > Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags=MachineMemOperand::MOLoad|MachineMemOperand::MOStore, LocationSize Size=LocationSize::precise(0), const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
SDValue getInsertSubvector(const SDLoc &DL, SDValue Vec, SDValue SubVec, unsigned Idx)
Insert SubVec at the Idx element of Vec.
LLVM_ABI SDValue getStepVector(const SDLoc &DL, EVT ResVT, const APInt &StepVal)
Returns a vector of type ResVT whose elements contain the linear sequence <0, Step,...
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
LLVM_ABI bool shouldOptForSize() const
std::pair< SDValue, SDValue > SplitVectorOperand(const SDNode *N, unsigned OpNo)
Split the node's operand with EXTRACT_SUBVECTOR and return the low/high part.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
LLVM_ABI SDValue getVPZExtOrTrunc(const SDLoc &DL, EVT VT, SDValue Op, SDValue Mask, SDValue EVL)
Convert a vector-predicated Op, which must be an integer vector, to the vector-type VT,...
const TargetLowering & getTargetLoweringInfo() const
LLVM_ABI SDValue getStridedStoreVP(SDValue Chain, const SDLoc &DL, SDValue Val, SDValue Ptr, SDValue Offset, SDValue Stride, SDValue Mask, SDValue EVL, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
bool NewNodesMustHaveLegalTypes
When true, additional steps are taken to ensure that getConstant() and similar functions return DAG n...
LLVM_ABI std::pair< EVT, EVT > GetSplitDestVTs(const EVT &VT) const
Compute the VTs needed for the low/hi parts of a type which is split (or expanded) into two not neces...
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
LLVM_ABI SDValue getGatherVP(SDVTList VTs, EVT VT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType)
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI bool isSplatValue(SDValue V, const APInt &DemandedElts, APInt &UndefElts, unsigned Depth=0) const
Test whether V has a splatted value for all the demanded elements.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
const SelectionDAGTargetInfo & getSelectionDAGInfo() const
LLVM_ABI SDValue getStoreVP(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, SDValue Offset, SDValue Mask, SDValue EVL, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags=SDNodeFlags())
Returns sum of the base pointer and offset.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue getSplatVector(EVT VT, const SDLoc &DL, SDValue Op)
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI bool SignBitIsZero(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero.
SDValue getInsertVectorElt(const SDLoc &DL, SDValue Vec, SDValue Elt, unsigned Idx)
Insert Elt into Vec at offset Idx.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDValue > Ops, SDNodeFlags Flags=SDNodeFlags())
LLVM_ABI SDValue getMaskedStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Base, SDValue Offset, SDValue Mask, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
LLVM_ABI std::pair< SDValue, SDValue > getStrictFPExtendOrRound(SDValue Op, SDValue Chain, const SDLoc &DL, EVT VT)
Convert Op, which must be a STRICT operation of float type, to the float type VT, by either extending...
LLVM_ABI std::pair< SDValue, SDValue > SplitEVL(SDValue N, EVT VecVT, const SDLoc &DL)
Split the explicit vector length parameter of a VP operation.
LLVM_ABI SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either any-extending or truncat...
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getScatterVP(SDVTList VTs, EVT VT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
LLVM_ABI SDValue getFPExtendOrRound(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of float type, to the float type VT, by either extending or rounding (by tr...
LLVM_ABI bool isKnownNeverNaN(SDValue Op, const APInt &DemandedElts, bool SNaN=false, unsigned Depth=0) const
Test whether the given SDValue (or all elements of it, if it is a vector) is known to never be NaN in...
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI SDValue getBoolConstant(bool V, const SDLoc &DL, EVT VT, EVT OpVT)
Create a true or false constant of type VT using the target's BooleanContent for type OpVT.
SDValue getTargetBlockAddress(const BlockAddress *BA, EVT VT, int64_t Offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
void addCallSiteInfo(const SDNode *Node, CallSiteInfo &&CallInfo)
Set CallSiteInfo to be associated with Node.
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset)
Create an add instruction with appropriate flags when used for addressing some offset of an object.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Base, SDValue Offset, SDValue Mask, SDValue Src0, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, ISD::LoadExtType, bool IsExpanding=false)
SDValue getSplat(EVT VT, const SDLoc &DL, SDValue Op)
Returns a node representing a splat of one value into all lanes of the provided vector type.
LLVM_ABI std::pair< SDValue, SDValue > SplitScalar(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the scalar node with EXTRACT_ELEMENT using the provided VTs and return the low/high part.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
LLVM_ABI SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a logical NOT operation as (XOR Val, BooleanOne).
LLVM_ABI SDValue getMaskedScatter(SDVTList VTs, EVT MemVT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType, bool IsTruncating=false)
static LLVM_ABI bool isSelectMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from its source vectors without lane crossings.
static LLVM_ABI bool isBitRotateMask(ArrayRef< int > Mask, unsigned EltSizeInBits, unsigned MinSubElts, unsigned MaxSubElts, unsigned &NumSubElts, unsigned &RotateAmt)
Checks if the shuffle is a bit rotation of the first operand across multiple subelements,...
static LLVM_ABI bool isSingleSourceMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector.
static LLVM_ABI bool isDeInterleaveMaskOfFactor(ArrayRef< int > Mask, unsigned Factor, unsigned &Index)
Check if the mask is a DE-interleave mask of the given factor Factor like: <Index,...
static LLVM_ABI bool isIdentityMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector without lane crossin...
static LLVM_ABI bool isReverseMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask swaps the order of elements from exactly one source vector.
static LLVM_ABI bool isInsertSubvectorMask(ArrayRef< int > Mask, int NumSrcElts, int &NumSubElts, int &Index)
Return true if this shuffle mask is an insert subvector mask.
static LLVM_ABI bool isInterleaveMask(ArrayRef< int > Mask, unsigned Factor, unsigned NumInputElts, SmallVectorImpl< unsigned > &StartIndexes)
Return true if the mask interleaves one or more input vectors together.
This SDNode is used to implement the code generator support for the llvm IR shufflevector instruction...
int getSplatIndex() const
ArrayRef< int > getMask() const
static LLVM_ABI bool isSplatMask(ArrayRef< int > Mask)
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
pointer data()
Return a pointer to the vector's buffer, even if empty().
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
StringRef - Represent a constant reference to a string, i.e.
constexpr size_t size() const
size - Get the string size.
LLVM_ABI std::string lower() const
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, T Value)
Information about stack frame layout on the target.
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
TargetInstrInfo - Interface to description of machine instruction set.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
bool PredictableSelectIsExpensive
Tells the code generator that select is more expensive than a branch if the branch is usually predict...
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
unsigned MaxStoresPerMemcpyOptSize
Likewise for functions with the OptSize attribute.
MachineBasicBlock * emitPatchPoint(MachineInstr &MI, MachineBasicBlock *MBB) const
Replace/modify any TargetFrameIndex operands with a targte-dependent sequence of memory operands that...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
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.
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 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.
User * getUser() const
Returns the User that contains this Use.
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
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)
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)
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)
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)
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.
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.
auto mask(ShuffFunc S, unsigned Length, OptArgs... args) -> MaskT
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
static constexpr roundingMode rmNearestTiesToEven
static LLVM_ABI unsigned int semanticsPrecision(const fltSemantics &)
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint64_t value() const
This is a hole in the type system and should not be abused.
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
uint64_t getScalarStoreSize() const
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
bool isByteSized() const
Return true if the bit size is a multiple of 8.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
unsigned getRISCVVectorTupleNumFields() const
Given a RISCV vector tuple type, return the num_fields.
uint64_t getScalarSizeInBits() const
EVT getHalfSizedIntegerVT(LLVMContext &Context) const
Finds the smallest simple value type that is greater than or equal to half the width of this EVT.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
bool isRISCVVectorTuple() const
Return true if this is a vector value type.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isFixedLengthVector() const
EVT getRoundIntegerType(LLVMContext &Context) const
Rounds the bit-width of the given integer EVT up to the nearest power of two (and at least to eight),...
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
bool bitsGE(EVT VT) const
Return true if this has no less bits than VT.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
EVT changeVectorElementType(EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
bool isInteger() const
Return true if this is an integer or a vector integer type.
static LLVM_ABI KnownBits ashr(const KnownBits &LHS, const KnownBits &RHS, bool ShAmtNonZero=false, bool Exact=false)
Compute known bits for ashr(LHS, RHS).
static LLVM_ABI KnownBits urem(const KnownBits &LHS, const KnownBits &RHS)
Compute known bits for urem(LHS, RHS).
bool isUnknown() const
Returns true if we don't know any bits.
unsigned countMaxTrailingZeros() const
Returns the maximum number of trailing zero bits possible.
KnownBits trunc(unsigned BitWidth) const
Return known bits for a truncation of the value we're tracking.
unsigned getBitWidth() const
Get the bit width of this value.
KnownBits zext(unsigned BitWidth) const
Return known bits for a zero extension of the value we're tracking.
void resetAll()
Resets the known state of all bits.
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 LLVM_ABI KnownBits udiv(const KnownBits &LHS, const KnownBits &RHS, bool Exact=false)
Compute known bits for udiv(LHS, RHS).
unsigned countMaxLeadingZeros() const
Returns the maximum number of leading zero bits possible.
static LLVM_ABI KnownBits shl(const KnownBits &LHS, const KnownBits &RHS, bool NUW=false, bool NSW=false, bool ShAmtNonZero=false)
Compute known bits for shl(LHS, RHS).
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Register getFrameRegister(const MachineFunction &MF) const override
These are IR-level optimization flags that may be propagated to SDNodes.
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This structure contains all information that is necessary for lowering calls.
SmallVector< ISD::InputArg, 32 > Ins
const ConstantInt * CFIType
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
bool isAfterLegalizeDAG() const
LLVM_ABI void AddToWorklist(SDNode *N)
bool isCalledByLegalizer() const
LLVM_ABI bool recursivelyDeleteUnusedNodes(SDNode *N)
bool isBeforeLegalize() const
LLVM_ABI SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
This structure is used to pass arguments to makeLibCall function.
MakeLibCallOptions & setTypeListBeforeSoften(ArrayRef< EVT > OpsVT, EVT RetVT)
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...
bool CombineTo(SDValue O, SDValue N)