32#include "llvm/IR/IntrinsicsLoongArch.h"
42#define DEBUG_TYPE "loongarch-isel-lowering"
57 cl::desc(
"Maximum number of instructions used (including code sequence "
58 "to generate the value and moving the value to FPR) when "
59 "materializing floating-point immediates (default = 3)"),
63 "Materialize FP immediate within 2 instructions"),
65 "Materialize FP immediate within 3 instructions"),
67 "Materialize FP immediate within 4 instructions"),
69 "Materialize FP immediate within 5 instructions"),
71 "Materialize FP immediate within 6 instructions "
72 "(behaves same as 5 on loongarch64)")));
75 cl::desc(
"Trap on integer division by zero."),
82 MVT GRLenVT = Subtarget.getGRLenVT();
87 if (Subtarget.hasBasicF())
89 if (Subtarget.hasBasicD())
93 MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64, MVT::v4f32, MVT::v2f64};
95 MVT::v32i8, MVT::v16i16, MVT::v8i32, MVT::v4i64, MVT::v8f32, MVT::v4f64};
97 if (Subtarget.hasExtLSX())
101 if (Subtarget.hasExtLASX())
102 for (
MVT VT : LASXVTs)
170 if (Subtarget.is64Bit()) {
198 if (!Subtarget.is64Bit()) {
204 if (Subtarget.hasBasicD())
216 if (Subtarget.hasBasicF()) {
250 if (Subtarget.is64Bit())
253 if (!Subtarget.hasBasicD()) {
255 if (Subtarget.is64Bit()) {
264 if (Subtarget.hasBasicD()) {
297 if (Subtarget.is64Bit())
303 if (Subtarget.hasExtLSX()) {
318 for (
MVT VT : LSXVTs) {
332 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64}) {
360 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
362 for (
MVT VT : {MVT::v8i16, MVT::v4i32, MVT::v2i64})
364 for (
MVT VT : {MVT::v4i32, MVT::v2i64}) {
369 for (
MVT VT : {MVT::v4f32, MVT::v2f64}) {
393 {MVT::v16i8, MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v8i16, MVT::v4i16,
394 MVT::v2i16, MVT::v4i32, MVT::v2i32, MVT::v2i64}) {
409 for (
MVT VT : {MVT::v2i64, MVT::v4i32, MVT::v8i16})
411 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64, MVT::v16i32, MVT::v8i64,
418 if (Subtarget.hasExtLASX()) {
419 for (
MVT VT : LASXVTs) {
434 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16, MVT::v32i8}) {
463 for (
MVT VT : {MVT::v32i8, MVT::v16i16, MVT::v8i32})
465 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64})
467 for (
MVT VT : {MVT::v8i32, MVT::v4i32, MVT::v4i64}) {
472 for (
MVT VT : {MVT::v8f32, MVT::v4f64}) {
491 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16}) {
497 {MVT::v2i64, MVT::v4i32, MVT::v4i64, MVT::v8i16, MVT::v8i32}) {
501 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
506 if (Subtarget.hasBasicF()) {
517 if (Subtarget.hasExtLSX()) {
532 if (Subtarget.hasExtLASX()) {
557 if (Subtarget.hasLAMCAS())
560 if (Subtarget.hasSCQ()) {
580 switch (
Op.getOpcode()) {
582 return lowerATOMIC_FENCE(
Op, DAG);
584 return lowerEH_DWARF_CFA(
Op, DAG);
586 return lowerGlobalAddress(
Op, DAG);
588 return lowerGlobalTLSAddress(
Op, DAG);
590 return lowerINTRINSIC_WO_CHAIN(
Op, DAG);
592 return lowerINTRINSIC_W_CHAIN(
Op, DAG);
594 return lowerINTRINSIC_VOID(
Op, DAG);
596 return lowerBlockAddress(
Op, DAG);
598 return lowerJumpTable(
Op, DAG);
600 return lowerShiftLeftParts(
Op, DAG);
602 return lowerShiftRightParts(
Op, DAG,
true);
604 return lowerShiftRightParts(
Op, DAG,
false);
606 return lowerConstantPool(
Op, DAG);
608 return lowerFP_TO_SINT(
Op, DAG);
610 return lowerFP_TO_UINT(
Op, DAG);
612 return lowerBITCAST(
Op, DAG);
614 return lowerUINT_TO_FP(
Op, DAG);
616 return lowerSINT_TO_FP(
Op, DAG);
618 return lowerVASTART(
Op, DAG);
620 return lowerFRAMEADDR(
Op, DAG);
622 return lowerRETURNADDR(
Op, DAG);
624 return lowerSET_ROUNDING(
Op, DAG);
626 return lowerGET_ROUNDING(
Op, DAG);
628 return lowerWRITE_REGISTER(
Op, DAG);
630 return lowerINSERT_VECTOR_ELT(
Op, DAG);
632 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
634 return lowerBUILD_VECTOR(
Op, DAG);
636 return lowerCONCAT_VECTORS(
Op, DAG);
638 return lowerVECTOR_SHUFFLE(
Op, DAG);
640 return lowerBITREVERSE(
Op, DAG);
642 return lowerSCALAR_TO_VECTOR(
Op, DAG);
644 return lowerPREFETCH(
Op, DAG);
646 return lowerSELECT(
Op, DAG);
648 return lowerBRCOND(
Op, DAG);
650 return lowerFP_TO_FP16(
Op, DAG);
652 return lowerFP16_TO_FP(
Op, DAG);
654 return lowerFP_TO_BF16(
Op, DAG);
656 return lowerBF16_TO_FP(
Op, DAG);
658 return lowerVECREDUCE_ADD(
Op, DAG);
661 return lowerRotate(
Op, DAG);
669 return lowerVECREDUCE(
Op, DAG);
671 return lowerConstantFP(
Op, DAG);
673 return lowerSETCC(
Op, DAG);
675 return lowerFP_ROUND(
Op, DAG);
677 return lowerFP_EXTEND(
Op, DAG);
679 return lowerSIGN_EXTEND_VECTOR_INREG(
Op, DAG);
681 return lowerDYNAMIC_STACKALLOC(
Op, DAG);
683 return lowerANY_EXTEND(
Op, DAG);
692 EVT VT = V.getValueType();
698 return V.getOperand(0);
702 (
isNullConstant(V.getOperand(1)) || V.getOperand(0).hasOneUse())) {
704 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
714 if (!V->isOnlyUserOf(SplatValue.getNode()))
718 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
726 V.getOperand(0).hasOneUse() && V.getOperand(1).hasOneUse()) {
754 (
N->getOpcode() == LoongArchISD::VPACKEV) ||
755 (
N->getOpcode() == LoongArchISD::VPERMI)) &&
762 if (Opcode0 != Opcode1)
765 if (Opcode0 !=
ISD::FP_ROUND && Opcode0 != LoongArchISD::VFCVT)
772 EVT VT =
N.getValueType();
786 if (Subtarget.hasExtLASX() && VT.
is256BitVector() && SVT0 == MVT::v4f32 &&
787 SSVT0 == MVT::v4f64) {
806 if ((
N->getOpcode() == LoongArchISD::VPACKEV ||
807 N->getOpcode() == LoongArchISD::VPERMI) &&
808 Opcode0 == LoongArchISD::VFCVT) {
813 if (!Subtarget.hasExtLSX() || SVT0 != MVT::v4f32 || SSVT0 != MVT::v2f64)
816 if (
N->getOpcode() == LoongArchISD::VPACKEV &&
817 (VT == MVT::v2i64 || VT == MVT::v2f64)) {
823 if (
N->getOpcode() == LoongArchISD::VPERMI && VT == MVT::v4f32) {
839 MVT VT =
Op.getSimpleValueType();
840 MVT SVT =
In.getSimpleValueType();
842 if (VT == MVT::v4f32 && SVT == MVT::v4f64) {
855 EVT VT =
Op.getValueType();
857 EVT SVT = Src.getValueType();
860 VT == MVT::v2f64 && SVT == MVT::v2f32 && Subtarget.hasExtLSX();
862 VT == MVT::v4f64 && SVT == MVT::v4f32 && Subtarget.hasExtLASX();
863 if (!V2F32ToV2F64 && !V4F32ToV4F64)
890 if (
SDValue V = CheckVecHighPart(Src)) {
892 "Unexpected wide vector");
893 Opcode = LoongArchISD::VFCVTH;
896 Opcode = LoongArchISD::VFCVTL;
898 DAG.
getUNDEF(WideOpVT), Src, ZeroIdx);
903 return DAG.
getNode(Opcode,
DL, VT, VFCVTOp);
909 SmallVector<int, 8>
Mask = {0, 1, 4, 5, 2, 3, 6, 7};
921 EVT VT =
Op.getValueType();
926 assert((VT == MVT::f32 && Subtarget.hasBasicF()) ||
927 (VT == MVT::f64 && Subtarget.hasBasicD()));
944 int InsNum = Seq.size() + ((VT == MVT::f64 && !Subtarget.is64Bit()) ? 2 : 1);
954 if (Subtarget.is64Bit())
956 return DAG.
getNode(Subtarget.is64Bit() ? LoongArchISD::MOVGR2FR_W_LA64
957 : LoongArchISD::MOVGR2FR_W,
961 if (Subtarget.is64Bit()) {
963 return DAG.
getNode(LoongArchISD::MOVGR2FR_D,
DL, VT, NewVal);
967 return DAG.
getNode(LoongArchISD::MOVGR2FR_D_LO_HI,
DL, VT,
Lo,
Hi);
979 EVT ResultVT =
Op.getValueType();
980 EVT OperandVT =
Op.getOperand(0).getValueType();
985 if (ResultVT == SetCCResultVT)
988 assert(
Op.getOperand(0).getValueType() ==
Op.getOperand(1).getValueType() &&
989 "SETCC operands must have the same type!");
993 Op.getOperand(1),
Op.getOperand(2));
995 if (ResultVT.
bitsGT(SetCCResultVT))
997 else if (ResultVT.
bitsLT(SetCCResultVT))
1009SDValue LoongArchTargetLowering::lowerSIGN_EXTEND_VECTOR_INREG(
1013 MVT SrcVT = Src.getSimpleValueType();
1014 MVT DstVT =
Op.getSimpleValueType();
1025 DAG.
getNode(LoongArchISD::VILVL,
DL, SrcVT, Mask, Src);
1036 assert(Subtarget.hasExtLASX());
1055 MVT OpVT =
Op.getSimpleValueType();
1062 unsigned LegalVecSize = 128;
1063 bool isLASX256Vector =
1073 if (isLASX256Vector) {
1079 for (
unsigned i = 1; i < NumEles; i *= 2, EleBits *= 2) {
1080 EleBits = std::min(EleBits, 64u);
1083 Val = DAG.
getNode(LoongArchISD::VHADDW,
DL, VecTy, Val, Val);
1086 if (isLASX256Vector) {
1112 MVT OpVT =
Op.getSimpleValueType();
1125 MVT GRLenVT = Subtarget.getGRLenVT();
1127 for (
int i = NumEles; i > 1; i /= 2) {
1130 Val = DAG.
getNode(Opcode,
DL, VecTy, Tmp, Val);
1139 unsigned IsData =
Op.getConstantOperandVal(4);
1144 return Op.getOperand(0);
1151 MVT VT =
Op.getSimpleValueType();
1157 unsigned Opcode =
Op.getOpcode();
1160 auto checkCstSplat = [](
SDValue V, APInt &CstSplatValue) {
1166 CstSplatValue =
C->getAPIntValue();
1174 APInt CstSplatValue;
1175 bool IsCstSplat = checkCstSplat(Amt, CstSplatValue);
1179 if (IsCstSplat && CstSplatValue.
urem(EltSizeInBits) == 0)
1195 return DAG.
getNode(Opcode,
DL, VT, R, Urem);
1211 if (
LHS == LHS2 &&
RHS == RHS2) {
1216 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
1224 return std::nullopt;
1232 MVT VT =
N->getSimpleValueType(0);
1263 if (~TrueVal == FalseVal) {
1303 unsigned SelOpNo = 0;
1313 unsigned ConstSelOpNo = 1;
1314 unsigned OtherSelOpNo = 2;
1321 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
1326 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
1332 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
1334 std::swap(NewConstOps[0], NewConstOps[1]);
1346 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
1348 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
1351 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
1352 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
1372 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
1386 int64_t
C = RHSC->getSExtValue();
1429 MVT VT =
Op.getSimpleValueType();
1430 MVT GRLenVT = Subtarget.getGRLenVT();
1435 if (
Op.hasOneUse()) {
1436 unsigned UseOpc =
Op->user_begin()->getOpcode();
1438 SDNode *BinOp = *
Op->user_begin();
1445 return lowerSELECT(NewSel, DAG);
1462 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1485 if (TrueVal - 1 == FalseVal)
1487 if (TrueVal + 1 == FalseVal)
1494 RHS == TrueV &&
LHS == FalseV) {
1519 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1526 MVT GRLenVT = Subtarget.getGRLenVT();
1537 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1538 Op.getOperand(0),
LHS,
RHS, TargetCC,
1541 return DAG.
getNode(LoongArchISD::BRCOND,
DL,
Op.getValueType(),
1542 Op.getOperand(0), CondV,
Op.getOperand(2));
1546 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1552LoongArchTargetLowering::lowerSCALAR_TO_VECTOR(
SDValue Op,
1555 MVT OpVT =
Op.getSimpleValueType();
1566 EVT ResTy =
Op->getValueType(0);
1571 if (!Subtarget.is64Bit() && (ResTy == MVT::v16i8 || ResTy == MVT::v32i8))
1581 for (
unsigned int i = 0; i < NewEltNum; i++) {
1584 unsigned RevOp = (ResTy == MVT::v16i8 || ResTy == MVT::v32i8)
1585 ? (
unsigned)LoongArchISD::BITREV_8B
1603 for (
unsigned int i = 0; i < NewEltNum; i++)
1604 for (
int j = OrigEltNum / NewEltNum - 1;
j >= 0;
j--)
1605 Mask.push_back(j + (OrigEltNum / NewEltNum) * i);
1623 if (EltBits > 32 || EltBits == 1)
1651 int MaskOffset,
const APInt &Zeroable) {
1652 int Size = Mask.size();
1653 unsigned SizeInBits =
Size * ScalarSizeInBits;
1655 auto CheckZeros = [&](
int Shift,
int Scale,
bool Left) {
1656 for (
int i = 0; i <
Size; i += Scale)
1657 for (
int j = 0; j < Shift; ++j)
1658 if (!Zeroable[i + j + (
Left ? 0 : (Scale - Shift))])
1666 for (
unsigned i = Pos, e = Pos +
Size; i != e; ++i,
Low += Step)
1667 if (!(Mask[i] == -1 || Mask[i] ==
Low))
1672 auto MatchShift = [&](
int Shift,
int Scale,
bool Left) {
1673 for (
int i = 0; i !=
Size; i += Scale) {
1674 unsigned Pos =
Left ? i + Shift : i;
1675 unsigned Low =
Left ? i : i + Shift;
1676 unsigned Len = Scale - Shift;
1681 int ShiftEltBits = ScalarSizeInBits * Scale;
1682 bool ByteShift = ShiftEltBits > 64;
1683 Opcode =
Left ? (ByteShift ? LoongArchISD::VBSLL : LoongArchISD::VSLLI)
1684 : (ByteShift ? LoongArchISD::VBSRL : LoongArchISD::VSRLI);
1685 int ShiftAmt = Shift * ScalarSizeInBits / (ByteShift ? 8 : 1);
1689 Scale = ByteShift ? Scale / 2 : Scale;
1695 return (
int)ShiftAmt;
1698 unsigned MaxWidth = 128;
1699 for (
int Scale = 2; Scale * ScalarSizeInBits <= MaxWidth; Scale *= 2)
1700 for (
int Shift = 1; Shift != Scale; ++Shift)
1701 for (
bool Left : {
true,
false})
1702 if (CheckZeros(Shift, Scale,
Left)) {
1703 int ShiftAmt = MatchShift(Shift, Scale,
Left);
1728 const APInt &Zeroable) {
1729 int Size = Mask.size();
1743 Mask,
Size, Zeroable);
1751 "Illegal integer vector type");
1760template <
typename ValType>
1763 unsigned CheckStride,
1765 ValType ExpectedIndex,
unsigned ExpectedIndexStride) {
1769 if (*
I != -1 && *
I != ExpectedIndex)
1771 ExpectedIndex += ExpectedIndexStride;
1775 for (
unsigned n = 0; n < CheckStride &&
I != End; ++n, ++
I)
1787 int Size = Mask.size();
1796 int VectorSizeInBits =
V1.getValueSizeInBits();
1797 int ScalarSizeInBits = VectorSizeInBits /
Size;
1798 assert(!(VectorSizeInBits % ScalarSizeInBits) &&
"Illegal shuffle mask size");
1799 (void)ScalarSizeInBits;
1801 for (
int i = 0; i <
Size; ++i) {
1807 if ((M >= 0 && M <
Size && V1IsZero) || (M >=
Size && V2IsZero)) {
1824 RepeatedMask.
assign(LaneSize, -1);
1825 int Size = Mask.size();
1826 for (
int i = 0; i <
Size; ++i) {
1827 assert(Mask[i] == -1 || Mask[i] >= 0);
1830 if ((Mask[i] %
Size) / LaneSize != i / LaneSize)
1837 Mask[i] <
Size ? Mask[i] % LaneSize : Mask[i] % LaneSize + LaneSize;
1838 if (RepeatedMask[i % LaneSize] < 0)
1840 RepeatedMask[i % LaneSize] = LocalM;
1841 else if (RepeatedMask[i % LaneSize] != LocalM)
1858 int NumElts = RepeatedMask.
size();
1860 int Scale = 16 / NumElts;
1862 for (
int i = 0; i < NumElts; ++i) {
1863 int M = RepeatedMask[i];
1864 assert((M == -1 || (0 <= M && M < (2 * NumElts))) &&
1865 "Unexpected mask index.");
1870 int StartIdx = i - (M % NumElts);
1877 int CandidateRotation = StartIdx < 0 ? -StartIdx : NumElts - StartIdx;
1880 Rotation = CandidateRotation;
1881 else if (Rotation != CandidateRotation)
1896 else if (TargetV != MaskV)
1901 assert(Rotation != 0 &&
"Failed to locate a viable rotation!");
1902 assert((
Lo ||
Hi) &&
"Failed to find a rotated input vector!");
1911 return Rotation * Scale;
1930 if (ByteRotation <= 0)
1937 int LoByteShift = 16 - ByteRotation;
1938 int HiByteShift = ByteRotation;
1961 const APInt &Zeroable) {
1975 for (
int i = 0; i < NumElements; i++) {
1979 if (i % Scale != 0) {
1991 M = M % NumElements;
1994 Offset = M - (i / Scale);
1997 if (
Offset % (NumElements / Scale))
1999 }
else if (InputV != V)
2002 if (M != (
Offset + (i / Scale)))
2012 unsigned VilVLoHi = LoongArchISD::VILVL;
2013 if (
Offset >= (NumElements / 2)) {
2014 VilVLoHi = LoongArchISD::VILVH;
2015 Offset -= (NumElements / 2);
2022 InputV = DAG.
getNode(VilVLoHi,
DL, InputVT, Ext, InputV);
2026 }
while (Scale > 1);
2032 for (
int NumExtElements = Bits / 64; NumExtElements < NumElements;
2033 NumExtElements *= 2) {
2053 int SplatIndex = -1;
2054 for (
const auto &M : Mask) {
2061 if (SplatIndex == -1)
2064 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2066 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT,
V1,
2096 unsigned SubVecSize = 4;
2097 if (VT == MVT::v2f64 || VT == MVT::v2i64)
2100 int SubMask[4] = {-1, -1, -1, -1};
2101 for (
unsigned i = 0; i < SubVecSize; ++i) {
2102 for (
unsigned j = i; j < Mask.size(); j += SubVecSize) {
2108 M -= 4 * (j / SubVecSize);
2109 if (M < 0 || M >= 4)
2115 if (SubMask[i] == -1)
2119 else if (M != -1 && M != SubMask[i])
2126 for (
int i = SubVecSize - 1; i >= 0; --i) {
2139 if (VT == MVT::v2f64 || VT == MVT::v2i64)
2140 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT,
V1, V2,
2143 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT,
V1,
2161 if (VT != MVT::v16i8 && VT != MVT::v8i16 && VT != MVT::v32i8 &&
2170 for (
int i = 0; i < WidenNumElts; ++i)
2171 WidenMask[i] = WidenNumElts - 1 - i;
2179 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT,
2203 const auto &Begin = Mask.begin();
2204 const auto &End = Mask.end();
2221 return DAG.
getNode(LoongArchISD::VPACKEV,
DL, VT, V2,
V1);
2243 const auto &Begin = Mask.begin();
2244 const auto &End = Mask.end();
2261 return DAG.
getNode(LoongArchISD::VPACKOD,
DL, VT, V2,
V1);
2284 const auto &Begin = Mask.begin();
2285 const auto &End = Mask.end();
2286 unsigned HalfSize = Mask.size() / 2;
2304 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2,
V1);
2327 const auto &Begin = Mask.begin();
2328 const auto &End = Mask.end();
2345 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2,
V1);
2367 const auto &Begin = Mask.begin();
2368 const auto &Mid = Mask.begin() + Mask.size() / 2;
2369 const auto &End = Mask.end();
2387 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2,
V1);
2409 const auto &Begin = Mask.begin();
2410 const auto &Mid = Mask.begin() + Mask.size() / 2;
2411 const auto &End = Mask.end();
2428 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2,
V1);
2454 if (Mask.size() != NumElts)
2457 auto tryLowerToExtrAndIns = [&](
unsigned Base) ->
SDValue {
2460 for (
unsigned i = 0; i < NumElts; ++i) {
2463 if (Mask[i] !=
int(
Base + i)) {
2476 int DiffMask = Mask[DiffPos];
2477 if (DiffMask < 0 || DiffMask >=
int(2 * NumElts))
2483 if (
unsigned(DiffMask) < NumElts) {
2488 SrcIdx =
unsigned(DiffMask) - NumElts;
2504 if (
SDValue Result = tryLowerToExtrAndIns(0))
2506 return tryLowerToExtrAndIns(NumElts);
2514 unsigned &MaskImm) {
2515 unsigned MaskSize = Mask.size();
2517 auto isValid = [&](
int M,
int Off) {
2518 return (M == -1) || (M >= Off && M < Off + 4);
2521 auto buildImm = [&](
int MLo,
int MHi,
unsigned Off,
unsigned I) {
2522 auto immPart = [&](
int M,
unsigned Off) {
2523 return (M == -1 ? 0 : (M - Off)) & 0x3;
2525 MaskImm |= immPart(MLo, Off) << (
I * 2);
2526 MaskImm |= immPart(MHi, Off) << ((
I + 1) * 2);
2529 for (
unsigned i = 0; i < 4; i += 2) {
2531 int MHi = Mask[i + 1];
2533 if (MaskSize == 8) {
2534 auto isValid2 = [&](
int &M,
int M2) {
2541 if ((M2 % MaskSize) < 4)
2549 if (!isValid2(MLo, Mask[i + 4]) || !isValid2(MHi, Mask[i + 5]))
2555 buildImm(MLo, MHi, 0, i);
2558 buildImm(MLo, MHi, MaskSize, i);
2588 if ((VT != MVT::v4i32 && VT != MVT::v4f32) ||
2593 unsigned MaskImm = 0;
2597 return DAG.
getNode(LoongArchISD::VPERMI,
DL, VT, SrcVec[1], SrcVec[0],
2624 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2,
V1);
2637 "Vector type is unsupported for lsx!");
2639 "Two operands have different types!");
2641 "Unexpected mask size for shuffle!");
2642 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
2644 APInt KnownUndef, KnownZero;
2646 APInt Zeroable = KnownUndef | KnownZero;
2719 int SplatIndex = -1;
2720 for (
const auto &M : Mask) {
2727 if (SplatIndex == -1)
2730 const auto &Begin = Mask.begin();
2731 const auto &End = Mask.end();
2732 int HalfSize = Mask.size() / 2;
2734 if (SplatIndex >= HalfSize)
2737 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2741 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT,
V1,
2755 if (Mask.size() == 4) {
2756 unsigned MaskImm = 0;
2757 for (
int i = 1; i >= 0; --i) {
2759 int MHi = Mask[i + 2];
2760 if (!(MLo == -1 || (MLo >= 0 && MLo <= 1) || (MLo >= 4 && MLo <= 5)) ||
2761 !(MHi == -1 || (MHi >= 2 && MHi <= 3) || (MHi >= 6 && MHi <= 7)))
2763 if (MHi != -1 && MLo != -1 && MHi != MLo + 2)
2768 MaskImm |= ((MLo <= 1) ? MLo : (MLo - 2)) & 0x3;
2770 MaskImm |= ((MHi <= 3) ? (MHi - 2) : (MHi - 4)) & 0x3;
2773 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT,
V1, V2,
2786 unsigned MaskSize = Mask.size();
2791 if (VT == MVT::v8i32 || VT == MVT::v8f32) {
2793 unsigned MaskImm = 0;
2797 return DAG.
getNode(LoongArchISD::VPERMI,
DL, VT, SrcVec[1], SrcVec[0],
2802 if (VT == MVT::v4i64 || VT == MVT::v4f64) {
2803 unsigned MaskImm = 0;
2804 for (
unsigned i = 0; i < MaskSize; ++i) {
2807 if (Mask[i] >= (
int)MaskSize)
2809 MaskImm |= Mask[i] << (i * 2);
2812 return DAG.
getNode(LoongArchISD::XVPERMI,
DL, VT,
V1,
2824 if (Mask.size() != 8 || (VT != MVT::v8i32 && VT != MVT::v8f32))
2828 unsigned HalfSize = NumElts / 2;
2829 bool FrontLo =
true, FrontHi =
true;
2830 bool BackLo =
true, BackHi =
true;
2832 auto inRange = [](
int val,
int low,
int high) {
2833 return (val == -1) || (val >= low && val < high);
2836 for (
unsigned i = 0; i < HalfSize; ++i) {
2837 int Fronti = Mask[i];
2838 int Backi = Mask[i + HalfSize];
2840 FrontLo &=
inRange(Fronti, 0, HalfSize);
2841 FrontHi &=
inRange(Fronti, HalfSize, NumElts);
2842 BackLo &=
inRange(Backi, 0, HalfSize);
2843 BackHi &=
inRange(Backi, HalfSize, NumElts);
2849 if ((FrontLo || FrontHi) && (BackLo || BackHi))
2854 for (
unsigned i = 0; i < NumElts; ++i)
2859 return DAG.
getNode(LoongArchISD::XVPERM,
DL, VT,
V1, MaskVec);
2881 const auto &Begin = Mask.begin();
2882 const auto &End = Mask.end();
2883 unsigned HalfSize = Mask.size() / 2;
2884 unsigned LeftSize = HalfSize / 2;
2892 Mask.size() + HalfSize - LeftSize, 1) &&
2894 Mask.size() + HalfSize + LeftSize, 1))
2905 Mask.size() + HalfSize - LeftSize, 1) &&
2907 Mask.size() + HalfSize + LeftSize, 1))
2912 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2,
V1);
2920 const auto &Begin = Mask.begin();
2921 const auto &End = Mask.end();
2922 unsigned HalfSize = Mask.size() / 2;
2930 Mask.size() + HalfSize, 1))
2941 Mask.size() + HalfSize, 1))
2946 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2,
V1);
2954 const auto &Begin = Mask.begin();
2955 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2956 const auto &Mid = Mask.begin() + Mask.size() / 2;
2957 const auto &RightMid = Mask.end() - Mask.size() / 4;
2958 const auto &End = Mask.end();
2959 unsigned HalfSize = Mask.size() / 2;
2981 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2,
V1);
2989 const auto &Begin = Mask.begin();
2990 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2991 const auto &Mid = Mask.begin() + Mask.size() / 2;
2992 const auto &RightMid = Mask.end() - Mask.size() / 4;
2993 const auto &End = Mask.end();
2994 unsigned HalfSize = Mask.size() / 2;
3017 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2,
V1);
3026 int HalfSize = NumElts / 2;
3030 if ((
int)Mask.size() != NumElts)
3033 auto tryLowerToExtrAndIns = [&](
int Base) ->
SDValue {
3035 for (
int i = 0; i < NumElts; ++i) {
3038 if (Mask[i] !=
Base + i) {
3040 if (DiffPos.
size() > 2)
3048 if (DiffPos.
size() == 1) {
3049 if (DiffPos[0] < HalfSize && Mask[DiffPos[0] + HalfSize] == -1)
3050 DiffPos.
push_back(DiffPos[0] + HalfSize);
3051 else if (DiffPos[0] >= HalfSize && Mask[DiffPos[0] - HalfSize] == -1)
3052 DiffPos.
insert(DiffPos.
begin(), DiffPos[0] - HalfSize);
3056 if (DiffPos.
size() != 2 || DiffPos[1] != DiffPos[0] + HalfSize)
3060 int DiffMaskLo = Mask[DiffPos[0]];
3061 int DiffMaskHi = Mask[DiffPos[1]];
3062 DiffMaskLo = DiffMaskLo == -1 ? DiffMaskHi - HalfSize : DiffMaskLo;
3063 DiffMaskHi = DiffMaskHi == -1 ? DiffMaskLo + HalfSize : DiffMaskHi;
3064 if (!(DiffMaskLo >= 0 && DiffMaskLo < HalfSize) &&
3065 !(DiffMaskLo >= NumElts && DiffMaskLo < NumElts + HalfSize))
3067 if (!(DiffMaskHi >= HalfSize && DiffMaskHi < NumElts) &&
3068 !(DiffMaskHi >= NumElts + HalfSize && DiffMaskHi < 2 * NumElts))
3070 if (DiffMaskHi != DiffMaskLo + HalfSize)
3074 SDValue SrcVec = (DiffMaskLo < HalfSize) ?
V1 : V2;
3076 (DiffMaskLo < HalfSize) ? DiffMaskLo : (DiffMaskLo - NumElts);
3097 if (
SDValue Result = tryLowerToExtrAndIns(0))
3099 return tryLowerToExtrAndIns(NumElts);
3108 if (VT != MVT::v8i32 && VT != MVT::v8f32 && VT != MVT::v4i64 &&
3113 int MaskSize = Mask.size();
3119 auto checkReplaceOne = [&](
int Base,
int Replaced) ->
int {
3121 for (
int i = 0; i < MaskSize; ++i) {
3122 if (Mask[i] ==
Base + i || Mask[i] == -1)
3124 if (Mask[i] != Replaced)
3135 int Idx = checkReplaceOne(0, MaskSize);
3137 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT,
V1, V2,
3141 Idx = checkReplaceOne(MaskSize, 0);
3143 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT, V2,
V1,
3154 int MaskSize = Mask.size();
3155 int HalfSize = Mask.size() / 2;
3156 const auto &Begin = Mask.begin();
3157 const auto &Mid = Mask.begin() + HalfSize;
3158 const auto &End = Mask.end();
3170 for (
auto it = Begin; it < Mid; it++) {
3173 else if ((*it >= 0 && *it < HalfSize) ||
3174 (*it >= MaskSize && *it < MaskSize + HalfSize)) {
3175 int M = *it < HalfSize ? *it : *it - HalfSize;
3180 assert((
int)MaskAlloc.
size() == HalfSize &&
"xvshuf convert failed!");
3182 for (
auto it = Mid; it < End; it++) {
3185 else if ((*it >= HalfSize && *it < MaskSize) ||
3186 (*it >= MaskSize + HalfSize && *it < MaskSize * 2)) {
3187 int M = *it < MaskSize ? *it - HalfSize : *it - MaskSize;
3192 assert((
int)MaskAlloc.
size() == MaskSize &&
"xvshuf convert failed!");
3196 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2,
V1);
3224 enum HalfMaskType { HighLaneTy, LowLaneTy,
None };
3226 int MaskSize = Mask.size();
3227 int HalfSize = Mask.size() / 2;
3230 HalfMaskType preMask =
None, postMask =
None;
3232 if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
3233 return M < 0 || (M >= 0 && M < HalfSize) ||
3234 (M >= MaskSize && M < MaskSize + HalfSize);
3236 preMask = HighLaneTy;
3237 else if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
3238 return M < 0 || (M >= HalfSize && M < MaskSize) ||
3239 (M >= MaskSize + HalfSize && M < MaskSize * 2);
3241 preMask = LowLaneTy;
3243 if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
3244 return M < 0 || (M >= HalfSize && M < MaskSize) ||
3245 (M >= MaskSize + HalfSize && M < MaskSize * 2);
3247 postMask = LowLaneTy;
3248 else if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
3249 return M < 0 || (M >= 0 && M < HalfSize) ||
3250 (M >= MaskSize && M < MaskSize + HalfSize);
3252 postMask = HighLaneTy;
3260 if (preMask == HighLaneTy && postMask == LowLaneTy) {
3263 if (preMask == LowLaneTy && postMask == HighLaneTy) {
3271 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3276 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
3277 *it = *it < 0 ? *it : *it - HalfSize;
3279 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
3280 *it = *it < 0 ? *it : *it + HalfSize;
3282 }
else if (preMask == LowLaneTy && postMask == LowLaneTy) {
3290 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3295 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
3296 *it = *it < 0 ? *it : *it - HalfSize;
3298 }
else if (preMask == HighLaneTy && postMask == HighLaneTy) {
3306 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3311 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
3312 *it = *it < 0 ? *it : *it + HalfSize;
3337 int Size = Mask.size();
3338 int LaneSize =
Size / 2;
3340 bool LaneCrossing[2] = {
false,
false};
3341 for (
int i = 0; i <
Size; ++i)
3342 if (Mask[i] >= 0 && ((Mask[i] %
Size) / LaneSize) != (i / LaneSize))
3343 LaneCrossing[(Mask[i] %
Size) / LaneSize] =
true;
3346 if (!LaneCrossing[0] && !LaneCrossing[1])
3350 InLaneMask.
assign(Mask.begin(), Mask.end());
3351 for (
int i = 0; i <
Size; ++i) {
3352 int &M = InLaneMask[i];
3355 if (((M %
Size) / LaneSize) != (i / LaneSize))
3356 M = (M % LaneSize) + ((i / LaneSize) * LaneSize) +
Size;
3361 DAG.
getUNDEF(MVT::v4i64), {2, 3, 0, 1});
3376 "Vector type is unsupported for lasx!");
3378 "Two operands have different types!");
3380 "Unexpected mask size for shuffle!");
3381 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
3382 assert(Mask.size() >= 4 &&
"Mask size is less than 4.");
3384 APInt KnownUndef, KnownZero;
3386 APInt Zeroable = KnownUndef | KnownZero;
3473 ArrayRef<int> OrigMask = SVOp->
getMask();
3476 MVT VT =
Op.getSimpleValueType();
3480 bool V1IsUndef =
V1.isUndef();
3481 bool V2IsUndef = V2.
isUndef();
3482 if (V1IsUndef && V2IsUndef)
3495 any_of(OrigMask, [NumElements](
int M) {
return M >= NumElements; })) {
3496 SmallVector<int, 8> NewMask(OrigMask);
3497 for (
int &M : NewMask)
3498 if (M >= NumElements)
3504 int MaskUpperLimit = OrigMask.
size() * (V2IsUndef ? 1 : 2);
3505 (void)MaskUpperLimit;
3507 [&](
int M) {
return -1 <=
M &&
M < MaskUpperLimit; }) &&
3508 "Out of bounds shuffle index");
3530 std::tie(Res, Chain) =
3531 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
3532 if (Subtarget.is64Bit())
3533 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3545 SDValue Arg = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3549 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
3550 CallOptions,
DL, Chain);
3556 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3562 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
3563 if (Subtarget.is64Bit())
3564 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3570 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3571 MVT VT =
Op.getSimpleValueType();
3576 SDValue Res = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3597 "Unsupported vector type for broadcast.");
3600 bool IsIdeneity =
true;
3602 for (
int i = 0; i !=
NumOps; i++) {
3604 if (
Op.getOpcode() !=
ISD::LOAD || (IdentitySrc &&
Op != IdentitySrc)) {
3616 auto ExtType = LN->getExtensionType();
3621 assert(LN->isUnindexed() &&
"Unexpected indexed load.");
3626 SDValue Ops[] = {LN->getChain(), LN->getBasePtr()};
3644 for (
unsigned i = 1; i <
Ops.size(); ++i) {
3658 EVT ResTy,
unsigned first) {
3661 assert(first + NumElts <= Node->getSimpleValueType(0).getVectorNumElements());
3664 Node->op_begin() + first + NumElts);
3673 MVT VT =
Node->getSimpleValueType(0);
3674 EVT ResTy =
Op->getValueType(0);
3677 APInt SplatValue, SplatUndef;
3678 unsigned SplatBitSize;
3681 bool UseSameConstant =
true;
3686 if ((!Subtarget.hasExtLSX() || !Is128Vec) &&
3687 (!Subtarget.hasExtLASX() || !Is256Vec))
3693 if (
Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
3695 SplatBitSize <= 64) {
3697 if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
3701 if (SplatBitSize == 64 && !Subtarget.is64Bit()) {
3708 if ((Is128Vec && ResTy == MVT::v4i32) ||
3709 (Is256Vec && ResTy == MVT::v8i32))
3715 switch (SplatBitSize) {
3719 ViaVecTy = Is128Vec ? MVT::v16i8 : MVT::v32i8;
3722 ViaVecTy = Is128Vec ? MVT::v8i16 : MVT::v16i16;
3725 ViaVecTy = Is128Vec ? MVT::v4i32 : MVT::v8i32;
3728 ViaVecTy = Is128Vec ? MVT::v2i64 : MVT::v4i64;
3736 if (ViaVecTy != ResTy)
3745 for (
unsigned i = 0; i < NumElts; ++i) {
3750 ConstantValue = Opi;
3751 else if (ConstantValue != Opi)
3752 UseSameConstant =
false;
3757 if (IsConstant && UseSameConstant && ResTy != MVT::v2f64) {
3759 for (
unsigned i = 0; i < NumElts; ++i) {
3777 BitVector UndefElements;
3778 if (
Node->getRepeatedSequence(Sequence, &UndefElements) &&
3779 UndefElements.
count() == 0) {
3783 EVT FillTy = Is256Vec
3789 fillVector(Sequence, DAG,
DL, Subtarget, FillVec, FillTy);
3792 unsigned SplatLen = NumElts / SeqLen;
3798 if (SplatEltTy == MVT::i128)
3799 SplatTy = MVT::v4i64;
3807 DAG.
getNode((SplatEltTy == MVT::i128) ? LoongArchISD::XVREPLVE0Q
3808 : LoongArchISD::XVREPLVE0,
3809 DL, SplatTy, SrcVec);
3811 SplatVec = DAG.
getNode(LoongArchISD::VREPLVEI,
DL, SplatTy, SrcVec,
3824 if (ResTy == MVT::v8i32 || ResTy == MVT::v8f32 || ResTy == MVT::v4i64 ||
3825 ResTy == MVT::v4f64) {
3826 unsigned NonUndefCount = 0;
3827 for (
unsigned i = NumElts / 2; i < NumElts; ++i) {
3828 if (!
Node->getOperand(i).isUndef()) {
3830 if (NonUndefCount > 1)
3834 if (NonUndefCount == 1)
3847 VecTy, NumElts / 2);
3858 MVT ResVT =
Op.getSimpleValueType();
3866 unsigned NumFreezeUndef = 0;
3867 unsigned NumZero = 0;
3868 unsigned NumNonZero = 0;
3869 unsigned NonZeros = 0;
3870 SmallSet<SDValue, 4> Undefs;
3871 for (
unsigned i = 0; i != NumOperands; ++i) {
3886 assert(i <
sizeof(NonZeros) * CHAR_BIT);
3893 if (NumNonZero > 2) {
3897 Ops.slice(0, NumOperands / 2));
3899 Ops.slice(NumOperands / 2));
3912 MVT SubVT =
Op.getOperand(0).getSimpleValueType();
3914 for (
unsigned i = 0; i != NumOperands; ++i) {
3915 if ((NonZeros & (1 << i)) == 0)
3926LoongArchTargetLowering::lowerEXTRACT_VECTOR_ELT(
SDValue Op,
3928 MVT EltVT =
Op.getSimpleValueType();
3933 MVT GRLenVT = Subtarget.getGRLenVT();
3961 ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Idx)
3965 DAG.
getBitcast((VecTy == MVT::v4f64) ? MVT::v4i64 : VecTy, IdxVec);
3967 DAG.
getNode(LoongArchISD::VSHUF,
DL, VecTy, MaskVec, TmpVec, Vec);
3976 DAG.
getNode(LoongArchISD::XVPERM,
DL, VecTy, Vec, SplatIdx);
3985LoongArchTargetLowering::lowerINSERT_VECTOR_ELT(
SDValue Op,
3987 MVT VT =
Op.getSimpleValueType();
4010 if (!Subtarget.is64Bit() && IdxTy == MVT::i64) {
4012 for (
unsigned i = 0; i < NumElts; ++i) {
4020 for (
unsigned i = 0; i < NumElts; ++i) {
4029 for (
unsigned i = 0; i < NumElts; ++i)
4082 MVT GRLenVT = Subtarget.getGRLenVT();
4094 "rounding mode is not supported by LoongArch hardware",
4095 DiagnosticLocation(
DL.getDebugLoc()),
DS_Error));
4112 FCSRNo, RMValue, Chain);
4118 MVT GRLenVT = Subtarget.getGRLenVT();
4125 MVT::Other, FCSRNo, Chain);
4141 if (Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i32) {
4143 "On LA64, only 64-bit registers can be written.");
4144 return Op.getOperand(0);
4147 if (!Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i64) {
4149 "On LA32, only 32-bit registers can be written.");
4150 return Op.getOperand(0);
4160 "be a constant integer");
4166 Register FrameReg = Subtarget.getRegisterInfo()->getFrameRegister(MF);
4167 EVT VT =
Op.getValueType();
4170 unsigned Depth =
Op.getConstantOperandVal(0);
4171 int GRLenInBytes = Subtarget.getGRLen() / 8;
4174 int Offset = -(GRLenInBytes * 2);
4186 if (
Op.getConstantOperandVal(0) != 0) {
4188 "return address can only be determined for the current frame");
4194 MVT GRLenVT = Subtarget.getGRLenVT();
4206 auto Size = Subtarget.getGRLen() / 8;
4214 auto *FuncInfo = MF.
getInfo<LoongArchMachineFunctionInfo>();
4224 MachinePointerInfo(SV));
4231 EVT VT =
Op.getValueType();
4246 if (Subtarget.hasExtLSX() && Op0VT == MVT::i64 && VT == MVT::f64) {
4254 if (!Subtarget.is64Bit() || !Subtarget.hasBasicF() || Subtarget.hasBasicD())
4257 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
4258 !Subtarget.hasBasicD() &&
"unexpected target features");
4262 if (
C &&
C->getZExtValue() < UINT64_C(0xFFFFFFFF))
4266 if (Op0->
getOpcode() == LoongArchISD::BSTRPICK &&
4276 EVT RetVT =
Op.getValueType();
4282 std::tie(Result, Chain) =
4289 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
4290 !Subtarget.hasBasicD() &&
"unexpected target features");
4301 EVT RetVT =
Op.getValueType();
4307 std::tie(Result, Chain) =
4316 EVT VT =
Op.getValueType();
4320 if (
Op.getValueType() == MVT::f32 && Op0VT == MVT::i32 &&
4321 Subtarget.is64Bit() && Subtarget.hasBasicF()) {
4323 return DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, NewOp0);
4325 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit()) {
4328 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
4342 if (
Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() &&
4343 !Subtarget.hasBasicD()) {
4345 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Dst);
4355 if (!Subtarget.hasExtLSX())
4360 EVT VT =
Op.getValueType();
4361 EVT SrcVT = Src.getValueType();
4366 if (SrcVT != MVT::f32 && SrcVT != MVT::f64)
4369 if (SrcVT == MVT::f32)
4391 N->getOffset(), Flags);
4399template <
class NodeTy>
4402 bool IsLocal)
const {
4413 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
4494 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
4496 const GlobalValue *GV =
N->getGlobal();
4508 unsigned Opc,
bool UseGOT,
4512 MVT GRLenVT = Subtarget.getGRLenVT();
4526 if (
Opc == LoongArch::PseudoLA_TLS_LE && !Large)
4567 TargetLowering::CallLoweringInfo CLI(DAG);
4582 const GlobalValue *GV =
N->getGlobal();
4596LoongArchTargetLowering::lowerGlobalTLSAddress(
SDValue Op,
4603 assert((!Large || Subtarget.is64Bit()) &&
"Large code model requires LA64");
4606 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
4619 return getDynamicTLSAddr(
N, DAG,
4620 Large ? LoongArch::PseudoLA_TLS_GD_LARGE
4621 : LoongArch::PseudoLA_TLS_GD,
4628 return getDynamicTLSAddr(
N, DAG,
4629 Large ? LoongArch::PseudoLA_TLS_LD_LARGE
4630 : LoongArch::PseudoLA_TLS_LD,
4635 return getStaticTLSAddr(
N, DAG,
4636 Large ? LoongArch::PseudoLA_TLS_IE_LARGE
4637 : LoongArch::PseudoLA_TLS_IE,
4644 return getStaticTLSAddr(
N, DAG, LoongArch::PseudoLA_TLS_LE,
4648 return getTLSDescAddr(
N, DAG,
4649 Large ? LoongArch::PseudoLA_TLS_DESC_LARGE
4650 : LoongArch::PseudoLA_TLS_DESC,
4654template <
unsigned N>
4659 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
4660 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
4662 ": argument out of range.");
4669LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(
SDValue Op,
4671 switch (
Op.getConstantOperandVal(0)) {
4674 case Intrinsic::thread_pointer: {
4678 case Intrinsic::loongarch_lsx_vpickve2gr_d:
4679 case Intrinsic::loongarch_lsx_vpickve2gr_du:
4680 case Intrinsic::loongarch_lsx_vreplvei_d:
4681 case Intrinsic::loongarch_lasx_xvrepl128vei_d:
4683 case Intrinsic::loongarch_lsx_vreplvei_w:
4684 case Intrinsic::loongarch_lasx_xvrepl128vei_w:
4685 case Intrinsic::loongarch_lasx_xvpickve2gr_d:
4686 case Intrinsic::loongarch_lasx_xvpickve2gr_du:
4687 case Intrinsic::loongarch_lasx_xvpickve_d:
4688 case Intrinsic::loongarch_lasx_xvpickve_d_f:
4690 case Intrinsic::loongarch_lasx_xvinsve0_d:
4692 case Intrinsic::loongarch_lsx_vsat_b:
4693 case Intrinsic::loongarch_lsx_vsat_bu:
4694 case Intrinsic::loongarch_lsx_vrotri_b:
4695 case Intrinsic::loongarch_lsx_vsllwil_h_b:
4696 case Intrinsic::loongarch_lsx_vsllwil_hu_bu:
4697 case Intrinsic::loongarch_lsx_vsrlri_b:
4698 case Intrinsic::loongarch_lsx_vsrari_b:
4699 case Intrinsic::loongarch_lsx_vreplvei_h:
4700 case Intrinsic::loongarch_lasx_xvsat_b:
4701 case Intrinsic::loongarch_lasx_xvsat_bu:
4702 case Intrinsic::loongarch_lasx_xvrotri_b:
4703 case Intrinsic::loongarch_lasx_xvsllwil_h_b:
4704 case Intrinsic::loongarch_lasx_xvsllwil_hu_bu:
4705 case Intrinsic::loongarch_lasx_xvsrlri_b:
4706 case Intrinsic::loongarch_lasx_xvsrari_b:
4707 case Intrinsic::loongarch_lasx_xvrepl128vei_h:
4708 case Intrinsic::loongarch_lasx_xvpickve_w:
4709 case Intrinsic::loongarch_lasx_xvpickve_w_f:
4711 case Intrinsic::loongarch_lasx_xvinsve0_w:
4713 case Intrinsic::loongarch_lsx_vsat_h:
4714 case Intrinsic::loongarch_lsx_vsat_hu:
4715 case Intrinsic::loongarch_lsx_vrotri_h:
4716 case Intrinsic::loongarch_lsx_vsllwil_w_h:
4717 case Intrinsic::loongarch_lsx_vsllwil_wu_hu:
4718 case Intrinsic::loongarch_lsx_vsrlri_h:
4719 case Intrinsic::loongarch_lsx_vsrari_h:
4720 case Intrinsic::loongarch_lsx_vreplvei_b:
4721 case Intrinsic::loongarch_lasx_xvsat_h:
4722 case Intrinsic::loongarch_lasx_xvsat_hu:
4723 case Intrinsic::loongarch_lasx_xvrotri_h:
4724 case Intrinsic::loongarch_lasx_xvsllwil_w_h:
4725 case Intrinsic::loongarch_lasx_xvsllwil_wu_hu:
4726 case Intrinsic::loongarch_lasx_xvsrlri_h:
4727 case Intrinsic::loongarch_lasx_xvsrari_h:
4728 case Intrinsic::loongarch_lasx_xvrepl128vei_b:
4730 case Intrinsic::loongarch_lsx_vsrlni_b_h:
4731 case Intrinsic::loongarch_lsx_vsrani_b_h:
4732 case Intrinsic::loongarch_lsx_vsrlrni_b_h:
4733 case Intrinsic::loongarch_lsx_vsrarni_b_h:
4734 case Intrinsic::loongarch_lsx_vssrlni_b_h:
4735 case Intrinsic::loongarch_lsx_vssrani_b_h:
4736 case Intrinsic::loongarch_lsx_vssrlni_bu_h:
4737 case Intrinsic::loongarch_lsx_vssrani_bu_h:
4738 case Intrinsic::loongarch_lsx_vssrlrni_b_h:
4739 case Intrinsic::loongarch_lsx_vssrarni_b_h:
4740 case Intrinsic::loongarch_lsx_vssrlrni_bu_h:
4741 case Intrinsic::loongarch_lsx_vssrarni_bu_h:
4742 case Intrinsic::loongarch_lasx_xvsrlni_b_h:
4743 case Intrinsic::loongarch_lasx_xvsrani_b_h:
4744 case Intrinsic::loongarch_lasx_xvsrlrni_b_h:
4745 case Intrinsic::loongarch_lasx_xvsrarni_b_h:
4746 case Intrinsic::loongarch_lasx_xvssrlni_b_h:
4747 case Intrinsic::loongarch_lasx_xvssrani_b_h:
4748 case Intrinsic::loongarch_lasx_xvssrlni_bu_h:
4749 case Intrinsic::loongarch_lasx_xvssrani_bu_h:
4750 case Intrinsic::loongarch_lasx_xvssrlrni_b_h:
4751 case Intrinsic::loongarch_lasx_xvssrarni_b_h:
4752 case Intrinsic::loongarch_lasx_xvssrlrni_bu_h:
4753 case Intrinsic::loongarch_lasx_xvssrarni_bu_h:
4755 case Intrinsic::loongarch_lsx_vsat_w:
4756 case Intrinsic::loongarch_lsx_vsat_wu:
4757 case Intrinsic::loongarch_lsx_vrotri_w:
4758 case Intrinsic::loongarch_lsx_vsllwil_d_w:
4759 case Intrinsic::loongarch_lsx_vsllwil_du_wu:
4760 case Intrinsic::loongarch_lsx_vsrlri_w:
4761 case Intrinsic::loongarch_lsx_vsrari_w:
4762 case Intrinsic::loongarch_lsx_vslei_bu:
4763 case Intrinsic::loongarch_lsx_vslei_hu:
4764 case Intrinsic::loongarch_lsx_vslei_wu:
4765 case Intrinsic::loongarch_lsx_vslei_du:
4766 case Intrinsic::loongarch_lsx_vslti_bu:
4767 case Intrinsic::loongarch_lsx_vslti_hu:
4768 case Intrinsic::loongarch_lsx_vslti_wu:
4769 case Intrinsic::loongarch_lsx_vslti_du:
4770 case Intrinsic::loongarch_lsx_vbsll_v:
4771 case Intrinsic::loongarch_lsx_vbsrl_v:
4772 case Intrinsic::loongarch_lasx_xvsat_w:
4773 case Intrinsic::loongarch_lasx_xvsat_wu:
4774 case Intrinsic::loongarch_lasx_xvrotri_w:
4775 case Intrinsic::loongarch_lasx_xvsllwil_d_w:
4776 case Intrinsic::loongarch_lasx_xvsllwil_du_wu:
4777 case Intrinsic::loongarch_lasx_xvsrlri_w:
4778 case Intrinsic::loongarch_lasx_xvsrari_w:
4779 case Intrinsic::loongarch_lasx_xvslei_bu:
4780 case Intrinsic::loongarch_lasx_xvslei_hu:
4781 case Intrinsic::loongarch_lasx_xvslei_wu:
4782 case Intrinsic::loongarch_lasx_xvslei_du:
4783 case Intrinsic::loongarch_lasx_xvslti_bu:
4784 case Intrinsic::loongarch_lasx_xvslti_hu:
4785 case Intrinsic::loongarch_lasx_xvslti_wu:
4786 case Intrinsic::loongarch_lasx_xvslti_du:
4787 case Intrinsic::loongarch_lasx_xvbsll_v:
4788 case Intrinsic::loongarch_lasx_xvbsrl_v:
4790 case Intrinsic::loongarch_lsx_vseqi_b:
4791 case Intrinsic::loongarch_lsx_vseqi_h:
4792 case Intrinsic::loongarch_lsx_vseqi_w:
4793 case Intrinsic::loongarch_lsx_vseqi_d:
4794 case Intrinsic::loongarch_lsx_vslei_b:
4795 case Intrinsic::loongarch_lsx_vslei_h:
4796 case Intrinsic::loongarch_lsx_vslei_w:
4797 case Intrinsic::loongarch_lsx_vslei_d:
4798 case Intrinsic::loongarch_lsx_vslti_b:
4799 case Intrinsic::loongarch_lsx_vslti_h:
4800 case Intrinsic::loongarch_lsx_vslti_w:
4801 case Intrinsic::loongarch_lsx_vslti_d:
4802 case Intrinsic::loongarch_lasx_xvseqi_b:
4803 case Intrinsic::loongarch_lasx_xvseqi_h:
4804 case Intrinsic::loongarch_lasx_xvseqi_w:
4805 case Intrinsic::loongarch_lasx_xvseqi_d:
4806 case Intrinsic::loongarch_lasx_xvslei_b:
4807 case Intrinsic::loongarch_lasx_xvslei_h:
4808 case Intrinsic::loongarch_lasx_xvslei_w:
4809 case Intrinsic::loongarch_lasx_xvslei_d:
4810 case Intrinsic::loongarch_lasx_xvslti_b:
4811 case Intrinsic::loongarch_lasx_xvslti_h:
4812 case Intrinsic::loongarch_lasx_xvslti_w:
4813 case Intrinsic::loongarch_lasx_xvslti_d:
4815 case Intrinsic::loongarch_lsx_vsrlni_h_w:
4816 case Intrinsic::loongarch_lsx_vsrani_h_w:
4817 case Intrinsic::loongarch_lsx_vsrlrni_h_w:
4818 case Intrinsic::loongarch_lsx_vsrarni_h_w:
4819 case Intrinsic::loongarch_lsx_vssrlni_h_w:
4820 case Intrinsic::loongarch_lsx_vssrani_h_w:
4821 case Intrinsic::loongarch_lsx_vssrlni_hu_w:
4822 case Intrinsic::loongarch_lsx_vssrani_hu_w:
4823 case Intrinsic::loongarch_lsx_vssrlrni_h_w:
4824 case Intrinsic::loongarch_lsx_vssrarni_h_w:
4825 case Intrinsic::loongarch_lsx_vssrlrni_hu_w:
4826 case Intrinsic::loongarch_lsx_vssrarni_hu_w:
4827 case Intrinsic::loongarch_lsx_vfrstpi_b:
4828 case Intrinsic::loongarch_lsx_vfrstpi_h:
4829 case Intrinsic::loongarch_lasx_xvsrlni_h_w:
4830 case Intrinsic::loongarch_lasx_xvsrani_h_w:
4831 case Intrinsic::loongarch_lasx_xvsrlrni_h_w:
4832 case Intrinsic::loongarch_lasx_xvsrarni_h_w:
4833 case Intrinsic::loongarch_lasx_xvssrlni_h_w:
4834 case Intrinsic::loongarch_lasx_xvssrani_h_w:
4835 case Intrinsic::loongarch_lasx_xvssrlni_hu_w:
4836 case Intrinsic::loongarch_lasx_xvssrani_hu_w:
4837 case Intrinsic::loongarch_lasx_xvssrlrni_h_w:
4838 case Intrinsic::loongarch_lasx_xvssrarni_h_w:
4839 case Intrinsic::loongarch_lasx_xvssrlrni_hu_w:
4840 case Intrinsic::loongarch_lasx_xvssrarni_hu_w:
4841 case Intrinsic::loongarch_lasx_xvfrstpi_b:
4842 case Intrinsic::loongarch_lasx_xvfrstpi_h:
4844 case Intrinsic::loongarch_lsx_vsat_d:
4845 case Intrinsic::loongarch_lsx_vsat_du:
4846 case Intrinsic::loongarch_lsx_vrotri_d:
4847 case Intrinsic::loongarch_lsx_vsrlri_d:
4848 case Intrinsic::loongarch_lsx_vsrari_d:
4849 case Intrinsic::loongarch_lasx_xvsat_d:
4850 case Intrinsic::loongarch_lasx_xvsat_du:
4851 case Intrinsic::loongarch_lasx_xvrotri_d:
4852 case Intrinsic::loongarch_lasx_xvsrlri_d:
4853 case Intrinsic::loongarch_lasx_xvsrari_d:
4855 case Intrinsic::loongarch_lsx_vsrlni_w_d:
4856 case Intrinsic::loongarch_lsx_vsrani_w_d:
4857 case Intrinsic::loongarch_lsx_vsrlrni_w_d:
4858 case Intrinsic::loongarch_lsx_vsrarni_w_d:
4859 case Intrinsic::loongarch_lsx_vssrlni_w_d:
4860 case Intrinsic::loongarch_lsx_vssrani_w_d:
4861 case Intrinsic::loongarch_lsx_vssrlni_wu_d:
4862 case Intrinsic::loongarch_lsx_vssrani_wu_d:
4863 case Intrinsic::loongarch_lsx_vssrlrni_w_d:
4864 case Intrinsic::loongarch_lsx_vssrarni_w_d:
4865 case Intrinsic::loongarch_lsx_vssrlrni_wu_d:
4866 case Intrinsic::loongarch_lsx_vssrarni_wu_d:
4867 case Intrinsic::loongarch_lasx_xvsrlni_w_d:
4868 case Intrinsic::loongarch_lasx_xvsrani_w_d:
4869 case Intrinsic::loongarch_lasx_xvsrlrni_w_d:
4870 case Intrinsic::loongarch_lasx_xvsrarni_w_d:
4871 case Intrinsic::loongarch_lasx_xvssrlni_w_d:
4872 case Intrinsic::loongarch_lasx_xvssrani_w_d:
4873 case Intrinsic::loongarch_lasx_xvssrlni_wu_d:
4874 case Intrinsic::loongarch_lasx_xvssrani_wu_d:
4875 case Intrinsic::loongarch_lasx_xvssrlrni_w_d:
4876 case Intrinsic::loongarch_lasx_xvssrarni_w_d:
4877 case Intrinsic::loongarch_lasx_xvssrlrni_wu_d:
4878 case Intrinsic::loongarch_lasx_xvssrarni_wu_d:
4880 case Intrinsic::loongarch_lsx_vsrlni_d_q:
4881 case Intrinsic::loongarch_lsx_vsrani_d_q:
4882 case Intrinsic::loongarch_lsx_vsrlrni_d_q:
4883 case Intrinsic::loongarch_lsx_vsrarni_d_q:
4884 case Intrinsic::loongarch_lsx_vssrlni_d_q:
4885 case Intrinsic::loongarch_lsx_vssrani_d_q:
4886 case Intrinsic::loongarch_lsx_vssrlni_du_q:
4887 case Intrinsic::loongarch_lsx_vssrani_du_q:
4888 case Intrinsic::loongarch_lsx_vssrlrni_d_q:
4889 case Intrinsic::loongarch_lsx_vssrarni_d_q:
4890 case Intrinsic::loongarch_lsx_vssrlrni_du_q:
4891 case Intrinsic::loongarch_lsx_vssrarni_du_q:
4892 case Intrinsic::loongarch_lasx_xvsrlni_d_q:
4893 case Intrinsic::loongarch_lasx_xvsrani_d_q:
4894 case Intrinsic::loongarch_lasx_xvsrlrni_d_q:
4895 case Intrinsic::loongarch_lasx_xvsrarni_d_q:
4896 case Intrinsic::loongarch_lasx_xvssrlni_d_q:
4897 case Intrinsic::loongarch_lasx_xvssrani_d_q:
4898 case Intrinsic::loongarch_lasx_xvssrlni_du_q:
4899 case Intrinsic::loongarch_lasx_xvssrani_du_q:
4900 case Intrinsic::loongarch_lasx_xvssrlrni_d_q:
4901 case Intrinsic::loongarch_lasx_xvssrarni_d_q:
4902 case Intrinsic::loongarch_lasx_xvssrlrni_du_q:
4903 case Intrinsic::loongarch_lasx_xvssrarni_du_q:
4905 case Intrinsic::loongarch_lsx_vnori_b:
4906 case Intrinsic::loongarch_lsx_vshuf4i_b:
4907 case Intrinsic::loongarch_lsx_vshuf4i_h:
4908 case Intrinsic::loongarch_lsx_vshuf4i_w:
4909 case Intrinsic::loongarch_lasx_xvnori_b:
4910 case Intrinsic::loongarch_lasx_xvshuf4i_b:
4911 case Intrinsic::loongarch_lasx_xvshuf4i_h:
4912 case Intrinsic::loongarch_lasx_xvshuf4i_w:
4913 case Intrinsic::loongarch_lasx_xvpermi_d:
4915 case Intrinsic::loongarch_lsx_vshuf4i_d:
4916 case Intrinsic::loongarch_lsx_vpermi_w:
4917 case Intrinsic::loongarch_lsx_vbitseli_b:
4918 case Intrinsic::loongarch_lsx_vextrins_b:
4919 case Intrinsic::loongarch_lsx_vextrins_h:
4920 case Intrinsic::loongarch_lsx_vextrins_w:
4921 case Intrinsic::loongarch_lsx_vextrins_d:
4922 case Intrinsic::loongarch_lasx_xvshuf4i_d:
4923 case Intrinsic::loongarch_lasx_xvpermi_w:
4924 case Intrinsic::loongarch_lasx_xvpermi_q:
4925 case Intrinsic::loongarch_lasx_xvbitseli_b:
4926 case Intrinsic::loongarch_lasx_xvextrins_b:
4927 case Intrinsic::loongarch_lasx_xvextrins_h:
4928 case Intrinsic::loongarch_lasx_xvextrins_w:
4929 case Intrinsic::loongarch_lasx_xvextrins_d:
4931 case Intrinsic::loongarch_lsx_vrepli_b:
4932 case Intrinsic::loongarch_lsx_vrepli_h:
4933 case Intrinsic::loongarch_lsx_vrepli_w:
4934 case Intrinsic::loongarch_lsx_vrepli_d:
4935 case Intrinsic::loongarch_lasx_xvrepli_b:
4936 case Intrinsic::loongarch_lasx_xvrepli_h:
4937 case Intrinsic::loongarch_lasx_xvrepli_w:
4938 case Intrinsic::loongarch_lasx_xvrepli_d:
4940 case Intrinsic::loongarch_lsx_vldi:
4941 case Intrinsic::loongarch_lasx_xvldi:
4957LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(
SDValue Op,
4960 MVT GRLenVT = Subtarget.getGRLenVT();
4961 EVT VT =
Op.getValueType();
4963 const StringRef ErrorMsgOOR =
"argument out of range";
4964 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4965 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4967 switch (
Op.getConstantOperandVal(1)) {
4970 case Intrinsic::loongarch_crc_w_b_w:
4971 case Intrinsic::loongarch_crc_w_h_w:
4972 case Intrinsic::loongarch_crc_w_w_w:
4973 case Intrinsic::loongarch_crc_w_d_w:
4974 case Intrinsic::loongarch_crcc_w_b_w:
4975 case Intrinsic::loongarch_crcc_w_h_w:
4976 case Intrinsic::loongarch_crcc_w_w_w:
4977 case Intrinsic::loongarch_crcc_w_d_w:
4979 case Intrinsic::loongarch_csrrd_w:
4980 case Intrinsic::loongarch_csrrd_d: {
4981 unsigned Imm =
Op.getConstantOperandVal(2);
4984 : DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
4987 case Intrinsic::loongarch_csrwr_w:
4988 case Intrinsic::loongarch_csrwr_d: {
4989 unsigned Imm =
Op.getConstantOperandVal(3);
4992 : DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
4993 {Chain,
Op.getOperand(2),
4996 case Intrinsic::loongarch_csrxchg_w:
4997 case Intrinsic::loongarch_csrxchg_d: {
4998 unsigned Imm =
Op.getConstantOperandVal(4);
5001 : DAG.
getNode(LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
5002 {Chain,
Op.getOperand(2),
Op.getOperand(3),
5005 case Intrinsic::loongarch_iocsrrd_d: {
5007 LoongArchISD::IOCSRRD_D,
DL, {GRLenVT, MVT::Other},
5010#define IOCSRRD_CASE(NAME, NODE) \
5011 case Intrinsic::loongarch_##NAME: { \
5012 return DAG.getNode(LoongArchISD::NODE, DL, {GRLenVT, MVT::Other}, \
5013 {Chain, Op.getOperand(2)}); \
5019 case Intrinsic::loongarch_cpucfg: {
5020 return DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
5021 {Chain,
Op.getOperand(2)});
5023 case Intrinsic::loongarch_lddir_d: {
5024 unsigned Imm =
Op.getConstantOperandVal(3);
5029 case Intrinsic::loongarch_movfcsr2gr: {
5030 if (!Subtarget.hasBasicF())
5032 unsigned Imm =
Op.getConstantOperandVal(2);
5035 : DAG.
getNode(LoongArchISD::MOVFCSR2GR,
DL, {VT, MVT::Other},
5038 case Intrinsic::loongarch_lsx_vld:
5039 case Intrinsic::loongarch_lsx_vldrepl_b:
5040 case Intrinsic::loongarch_lasx_xvld:
5041 case Intrinsic::loongarch_lasx_xvldrepl_b:
5045 case Intrinsic::loongarch_lsx_vldrepl_h:
5046 case Intrinsic::loongarch_lasx_xvldrepl_h:
5050 Op,
"argument out of range or not a multiple of 2", DAG)
5052 case Intrinsic::loongarch_lsx_vldrepl_w:
5053 case Intrinsic::loongarch_lasx_xvldrepl_w:
5057 Op,
"argument out of range or not a multiple of 4", DAG)
5059 case Intrinsic::loongarch_lsx_vldrepl_d:
5060 case Intrinsic::loongarch_lasx_xvldrepl_d:
5064 Op,
"argument out of range or not a multiple of 8", DAG)
5075 return Op.getOperand(0);
5081 MVT GRLenVT = Subtarget.getGRLenVT();
5083 uint64_t IntrinsicEnum =
Op.getConstantOperandVal(1);
5085 const StringRef ErrorMsgOOR =
"argument out of range";
5086 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
5087 const StringRef ErrorMsgReqLA32 =
"requires loongarch32";
5088 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
5090 switch (IntrinsicEnum) {
5094 case Intrinsic::loongarch_cacop_d:
5095 case Intrinsic::loongarch_cacop_w: {
5096 if (IntrinsicEnum == Intrinsic::loongarch_cacop_d && !Subtarget.is64Bit())
5098 if (IntrinsicEnum == Intrinsic::loongarch_cacop_w && Subtarget.is64Bit())
5107 case Intrinsic::loongarch_dbar: {
5114 case Intrinsic::loongarch_ibar: {
5121 case Intrinsic::loongarch_break: {
5128 case Intrinsic::loongarch_movgr2fcsr: {
5129 if (!Subtarget.hasBasicF())
5139 case Intrinsic::loongarch_syscall: {
5146#define IOCSRWR_CASE(NAME, NODE) \
5147 case Intrinsic::loongarch_##NAME: { \
5148 SDValue Op3 = Op.getOperand(3); \
5149 return Subtarget.is64Bit() \
5150 ? DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, \
5151 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
5152 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op3)) \
5153 : DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, Op2, \
5160 case Intrinsic::loongarch_iocsrwr_d: {
5161 return !Subtarget.is64Bit()
5168#define ASRT_LE_GT_CASE(NAME) \
5169 case Intrinsic::loongarch_##NAME: { \
5170 return !Subtarget.is64Bit() \
5171 ? emitIntrinsicErrorMessage(Op, ErrorMsgReqLA64, DAG) \
5176#undef ASRT_LE_GT_CASE
5177 case Intrinsic::loongarch_ldpte_d: {
5178 unsigned Imm =
Op.getConstantOperandVal(3);
5179 return !Subtarget.is64Bit()
5184 case Intrinsic::loongarch_lsx_vst:
5185 case Intrinsic::loongarch_lasx_xvst:
5189 case Intrinsic::loongarch_lasx_xvstelm_b:
5194 case Intrinsic::loongarch_lsx_vstelm_b:
5199 case Intrinsic::loongarch_lasx_xvstelm_h:
5204 Op,
"argument out of range or not a multiple of 2", DAG)
5206 case Intrinsic::loongarch_lsx_vstelm_h:
5211 Op,
"argument out of range or not a multiple of 2", DAG)
5213 case Intrinsic::loongarch_lasx_xvstelm_w:
5218 Op,
"argument out of range or not a multiple of 4", DAG)
5220 case Intrinsic::loongarch_lsx_vstelm_w:
5225 Op,
"argument out of range or not a multiple of 4", DAG)
5227 case Intrinsic::loongarch_lasx_xvstelm_d:
5232 Op,
"argument out of range or not a multiple of 8", DAG)
5234 case Intrinsic::loongarch_lsx_vstelm_d:
5239 Op,
"argument out of range or not a multiple of 8", DAG)
5250 EVT VT =
Lo.getValueType();
5291 EVT VT =
Lo.getValueType();
5345 return LoongArchISD::DIV_W;
5347 return LoongArchISD::DIV_WU;
5349 return LoongArchISD::MOD_W;
5351 return LoongArchISD::MOD_WU;
5353 return LoongArchISD::SLL_W;
5355 return LoongArchISD::SRA_W;
5357 return LoongArchISD::SRL_W;
5360 return LoongArchISD::ROTR_W;
5362 return LoongArchISD::CTZ_W;
5364 return LoongArchISD::CLZ_W;
5383 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
5384 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0);
5388 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
5394 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0, NewOp1);
5421 StringRef ErrorMsg,
bool WithChain =
true) {
5426 Results.push_back(
N->getOperand(0));
5429template <
unsigned N>
5434 const StringRef ErrorMsgOOR =
"argument out of range";
5435 unsigned Imm =
Node->getConstantOperandVal(2);
5469 switch (
N->getConstantOperandVal(0)) {
5472 case Intrinsic::loongarch_lsx_vpickve2gr_b:
5474 LoongArchISD::VPICK_SEXT_ELT);
5476 case Intrinsic::loongarch_lsx_vpickve2gr_h:
5477 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
5479 LoongArchISD::VPICK_SEXT_ELT);
5481 case Intrinsic::loongarch_lsx_vpickve2gr_w:
5483 LoongArchISD::VPICK_SEXT_ELT);
5485 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
5487 LoongArchISD::VPICK_ZEXT_ELT);
5489 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
5490 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
5492 LoongArchISD::VPICK_ZEXT_ELT);
5494 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
5496 LoongArchISD::VPICK_ZEXT_ELT);
5498 case Intrinsic::loongarch_lsx_bz_b:
5499 case Intrinsic::loongarch_lsx_bz_h:
5500 case Intrinsic::loongarch_lsx_bz_w:
5501 case Intrinsic::loongarch_lsx_bz_d:
5502 case Intrinsic::loongarch_lasx_xbz_b:
5503 case Intrinsic::loongarch_lasx_xbz_h:
5504 case Intrinsic::loongarch_lasx_xbz_w:
5505 case Intrinsic::loongarch_lasx_xbz_d:
5507 LoongArchISD::VALL_ZERO);
5509 case Intrinsic::loongarch_lsx_bz_v:
5510 case Intrinsic::loongarch_lasx_xbz_v:
5512 LoongArchISD::VANY_ZERO);
5514 case Intrinsic::loongarch_lsx_bnz_b:
5515 case Intrinsic::loongarch_lsx_bnz_h:
5516 case Intrinsic::loongarch_lsx_bnz_w:
5517 case Intrinsic::loongarch_lsx_bnz_d:
5518 case Intrinsic::loongarch_lasx_xbnz_b:
5519 case Intrinsic::loongarch_lasx_xbnz_h:
5520 case Intrinsic::loongarch_lasx_xbnz_w:
5521 case Intrinsic::loongarch_lasx_xbnz_d:
5523 LoongArchISD::VALL_NONZERO);
5525 case Intrinsic::loongarch_lsx_bnz_v:
5526 case Intrinsic::loongarch_lasx_xbnz_v:
5528 LoongArchISD::VANY_NONZERO);
5536 assert(
N->getValueType(0) == MVT::i128 &&
5537 "AtomicCmpSwap on types less than 128 should be legal");
5541 switch (
MemOp->getMergedOrdering()) {
5545 Opcode = LoongArch::PseudoCmpXchg128Acquire;
5549 Opcode = LoongArch::PseudoCmpXchg128;
5556 auto CmpVal = DAG.
SplitScalar(
N->getOperand(2),
DL, MVT::i64, MVT::i64);
5557 auto NewVal = DAG.
SplitScalar(
N->getOperand(3),
DL, MVT::i64, MVT::i64);
5558 SDValue Ops[] = {
N->getOperand(1), CmpVal.first, CmpVal.second,
5559 NewVal.first, NewVal.second,
N->getOperand(0)};
5562 Opcode,
SDLoc(
N), DAG.
getVTList(MVT::i64, MVT::i64, MVT::i64, MVT::Other),
5573 EVT VT =
N->getValueType(0);
5574 switch (
N->getOpcode()) {
5579 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
5580 "Unexpected custom legalisation");
5587 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5588 "Unexpected custom legalisation");
5590 Subtarget.hasDiv32() && VT == MVT::i32
5597 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5598 "Unexpected custom legalisation");
5606 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5607 "Unexpected custom legalisation");
5614 MVT VT =
N->getSimpleValueType(0);
5615 assert(VT == MVT::v2f32 && Subtarget.hasExtLSX() &&
5616 "Unexpected custom legalisation");
5618 "Unexpected type action!");
5623 Ld->getPointerInfo(), Ld->getBaseAlign(),
5624 Ld->getMemOperand()->getFlags());
5635 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5636 "Unexpected custom legalisation");
5643 if (Src.getValueType() == MVT::f16)
5654 EVT OpVT = Src.getValueType();
5658 std::tie(Result, Chain) =
5665 EVT SrcVT = Src.getValueType();
5666 if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.is64Bit() &&
5667 Subtarget.hasBasicF()) {
5669 DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Src);
5671 }
else if (VT == MVT::i64 && SrcVT == MVT::f64 && !Subtarget.is64Bit()) {
5673 DAG.
getVTList(MVT::i32, MVT::i32), Src);
5681 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5682 "Unexpected custom legalisation");
5685 TLI.expandFP_TO_UINT(
N, Tmp1, Tmp2, DAG);
5690 assert(VT == MVT::v2f32 && Subtarget.hasExtLSX() &&
5691 "Unexpected custom legalisation");
5697 if (OpVT == MVT::v2f64) {
5707 assert((VT == MVT::i16 || VT == MVT::i32) &&
5708 "Unexpected custom legalization");
5709 MVT GRLenVT = Subtarget.getGRLenVT();
5716 Tmp = DAG.
getNode(LoongArchISD::REVB_2H,
DL, GRLenVT, NewSrc);
5721 Tmp = DAG.
getNode(LoongArchISD::REVB_2W,
DL, GRLenVT, NewSrc);
5729 assert((VT == MVT::i8 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
5730 "Unexpected custom legalization");
5731 MVT GRLenVT = Subtarget.getGRLenVT();
5738 Tmp = DAG.
getNode(LoongArchISD::BITREV_4B,
DL, GRLenVT, NewSrc);
5741 Tmp = DAG.
getNode(LoongArchISD::BITREV_W,
DL, GRLenVT, NewSrc);
5749 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5750 "Unexpected custom legalisation");
5757 MVT GRLenVT = Subtarget.getGRLenVT();
5758 const StringRef ErrorMsgOOR =
"argument out of range";
5759 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
5760 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
5762 switch (
N->getConstantOperandVal(1)) {
5765 case Intrinsic::loongarch_movfcsr2gr: {
5766 if (!Subtarget.hasBasicF()) {
5776 LoongArchISD::MOVFCSR2GR,
SDLoc(
N), {MVT::i64, MVT::Other},
5783#define CRC_CASE_EXT_BINARYOP(NAME, NODE) \
5784 case Intrinsic::loongarch_##NAME: { \
5785 SDValue NODE = DAG.getNode( \
5786 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5787 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
5788 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5789 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5790 Results.push_back(NODE.getValue(1)); \
5799#undef CRC_CASE_EXT_BINARYOP
5801#define CRC_CASE_EXT_UNARYOP(NAME, NODE) \
5802 case Intrinsic::loongarch_##NAME: { \
5803 SDValue NODE = DAG.getNode( \
5804 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5806 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5807 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5808 Results.push_back(NODE.getValue(1)); \
5813#undef CRC_CASE_EXT_UNARYOP
5814#define CSR_CASE(ID) \
5815 case Intrinsic::loongarch_##ID: { \
5816 if (!Subtarget.is64Bit()) \
5817 emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgReqLA64); \
5825 case Intrinsic::loongarch_csrrd_w: {
5832 DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
5839 case Intrinsic::loongarch_csrwr_w: {
5840 unsigned Imm =
N->getConstantOperandVal(3);
5846 DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
5854 case Intrinsic::loongarch_csrxchg_w: {
5855 unsigned Imm =
N->getConstantOperandVal(4);
5861 LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
5870#define IOCSRRD_CASE(NAME, NODE) \
5871 case Intrinsic::loongarch_##NAME: { \
5872 SDValue IOCSRRDResults = \
5873 DAG.getNode(LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5874 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2)}); \
5875 Results.push_back( \
5876 DAG.getNode(ISD::TRUNCATE, DL, VT, IOCSRRDResults.getValue(0))); \
5877 Results.push_back(IOCSRRDResults.getValue(1)); \
5884 case Intrinsic::loongarch_cpucfg: {
5886 DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
5893 case Intrinsic::loongarch_lddir_d: {
5894 if (!Subtarget.is64Bit()) {
5904 if (Subtarget.is64Bit())
5906 "On LA64, only 64-bit registers can be read.");
5909 "On LA32, only 32-bit registers can be read.");
5911 Results.push_back(
N->getOperand(0));
5922 OpVT == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
5935 MVT VT =
N->getSimpleValueType(0);
5941 EVT InVT = In.getValueType();
5951 In = DAG.
getNode(
N->getOpcode(),
DL, InVT, In);
5956 if ((InVT == MVT::v8i32 || InVT == MVT::v4i64) &&
5959 In = DAG.
getNode(
N->getOpcode(),
DL, InVT, In);
5968 for (
unsigned I = 0;
I < MinElts; ++
I)
5969 TruncMask[
I] = Scale *
I;
5971 unsigned WidenNumElts = 128 / In.getScalarValueSizeInBits();
5972 MVT SVT = In.getSimpleValueType().getScalarType();
5978 "Illegal vector type in truncation");
5990 if (!Subtarget.hasExtLSX() || Subtarget.hasExtLASX())
5993 EVT DstVT =
N->getValueType(0);
5995 MVT SrcVT = Src.getSimpleValueType();
6009 unsigned WidenSrcElts = 128 / SrcEltBits;
6016 unsigned FirstStageEltBits = 128 / NumElts;
6020 SrcVT = FirstStageVT;
6021 SrcEltBits = FirstStageEltBits;
6028 while (SrcEltBits < DstEltBits) {
6029 unsigned NextEltBits = SrcEltBits * 2;
6032 unsigned NextEltsPerBlock = CurEltsPerBlock / 2;
6050 Blocks = std::move(NextBlocks);
6051 SrcVT = NextBlockVT;
6052 SrcEltBits = NextEltBits;
6069 assert(
N->getOpcode() ==
ISD::AND &&
"Unexpected opcode combine into ANDN");
6071 MVT VT =
N->getSimpleValueType(0);
6090 return DAG.
getNode(LoongArchISD::VANDN,
DL, VT,
X,
Y);
6094 unsigned MinSizeInBits) {
6102 unsigned SplatBitSize;
6105 return Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
6106 HasAnyUndefs, MinSizeInBits,
6118 for (
unsigned i = 0, NumElts = BV->getNumOperands(); i < NumElts; ++i) {
6129 unsigned EltIdx = IdxC->getZExtValue();
6131 Start = (int)EltIdx - (
int)(i * 2);
6132 if (Start < 0 || Start > 1 || EltIdx != (
unsigned)(Start + (
int)(i * 2)))
6138 else if (Src != CurSrc)
6142 if (!Src || Start < 0)
6152 if (!Subtarget.hasExtLSX())
6155 unsigned Opc =
N->getOpcode();
6158 EVT VT =
N->getValueType(0);
6165 unsigned ExtOpc =
LHS.getOpcode();
6173 if (ExtOpc !=
RHS.getOpcode())
6176 if (!
LHS.hasOneUse() || !
RHS.hasOneUse())
6179 unsigned OddIdx, EvenIdx;
6183 if (!LHSVec || !RHSVec)
6185 if (OddIdx != 1 || EvenIdx != 0)
6195 if (!TLI.isTypeLegal(VT) || !TLI.isTypeLegal(SrcVT))
6208 TargetOpc =
isSigned ? LoongArchISD::VHADDW : LoongArchISD::VHADDW_U;
6210 TargetOpc =
isSigned ? LoongArchISD::VHSUBW : LoongArchISD::VHSUBW_U;
6212 return DAG.
getNode(TargetOpc,
DL, VT, LHSVec, RHSVec);
6224 EVT VT =
N->getValueType(0);
6290 if (
And.getOperand(0) ==
X) {
6319 if (ShiftVal != (SplatVal + 1))
6328 : LoongArchISD::VSRAR,
6338 SDValue FirstOperand =
N->getOperand(0);
6339 SDValue SecondOperand =
N->getOperand(1);
6340 unsigned FirstOperandOpc = FirstOperand.
getOpcode();
6341 EVT ValTy =
N->getValueType(0);
6344 unsigned SMIdx, SMLen;
6353 if (!Subtarget.has32S())
6409 NewOperand = FirstOperand;
6412 msb = lsb + SMLen - 1;
6416 if (FirstOperandOpc ==
ISD::SRA || FirstOperandOpc ==
ISD::SRL || lsb == 0)
6430 EVT DstVT =
N.getValueType();
6439 EVT SrcVT = Src.getValueType();
6447 if (
N.getConstantOperandVal(1) != (isLow ? 0 : NumElts))
6458 if (NumElts % 2 != 0)
6464 for (
unsigned I = 0;
I != NumElts; ++
I) {
6479 SrcVT = Src.getValueType();
6489 }
else if (ThisSrc != Src) {
6493 unsigned Half = NumElts / 2;
6494 unsigned ExpectedIdx = (
I < Half) ?
I : (
I + Half);
6495 ExpectedIdx += isLow ? 0 : Half;
6497 if (CI->getZExtValue() != ExpectedIdx)
6509 EVT VT =
N->getValueType(0);
6516 unsigned ExtOpc =
LHS.getOpcode();
6524 if (!
LHS.hasOneUse())
6528 N->getValueSizeInBits(0) !=
LHS->getOperand(0).getValueSizeInBits() * 2)
6544 unsigned Opc =
isSigned ? LoongArchISD::VSLLWIL : LoongArchISD::VSLLWIL_U;
6553 if (!Subtarget.has32S())
6565 SDValue FirstOperand =
N->getOperand(0);
6567 EVT ValTy =
N->getValueType(0);
6570 unsigned MaskIdx, MaskLen;
6585 if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1)
6586 return DAG.
getNode(LoongArchISD::BSTRPICK,
DL, ValTy,
6610 switch (Src.getOpcode()) {
6613 return Src.getOperand(0).getValueSizeInBits() ==
Size;
6623 return Src.getOperand(0).getScalarValueSizeInBits() == 1 &&
6636 switch (Src.getOpcode()) {
6646 Src.getOpcode(),
DL, SExtVT,
6652 DL, SExtVT, Src.getOperand(0),
6664 EVT VT =
N->getValueType(0);
6666 EVT SrcVT = Src.getValueType();
6668 if (Src.getOpcode() !=
ISD::SETCC || !Src.hasOneUse())
6673 EVT CmpVT = Src.getOperand(0).getValueType();
6678 else if (Subtarget.has32S() && Subtarget.hasExtLASX() &&
6691 Opc = UseLASX ? LoongArchISD::XVMSKEQZ : LoongArchISD::VMSKEQZ;
6696 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
6701 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
6706 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
6708 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6713 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
6715 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6720 Opc = UseLASX ? LoongArchISD::XVMSKNEZ : LoongArchISD::VMSKNEZ;
6737 EVT VT =
N->getValueType(0);
6739 EVT SrcVT = Src.getValueType();
6756 bool UseLASX =
false;
6757 bool PropagateSExt =
false;
6759 if (Src.getOpcode() ==
ISD::SETCC && Src.hasOneUse()) {
6760 EVT CmpVT = Src.getOperand(0).getValueType();
6769 SExtVT = MVT::v2i64;
6772 SExtVT = MVT::v4i32;
6774 SExtVT = MVT::v4i64;
6776 PropagateSExt =
true;
6780 SExtVT = MVT::v8i16;
6782 SExtVT = MVT::v8i32;
6784 PropagateSExt =
true;
6788 SExtVT = MVT::v16i8;
6790 SExtVT = MVT::v16i16;
6792 PropagateSExt =
true;
6796 SExtVT = MVT::v32i8;
6804 if (!Subtarget.has32S() || !Subtarget.hasExtLASX()) {
6805 if (Src.getSimpleValueType() == MVT::v32i8) {
6813 }
else if (UseLASX) {
6819 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6832 EVT ValTy =
N->getValueType(0);
6833 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
6837 unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1;
6839 bool SwapAndRetried =
false;
6842 if (!Subtarget.has32S())
6848 if (ValBits != 32 && ValBits != 64)
6863 MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 &&
6866 (MaskIdx0 + MaskLen0 <= ValBits)) {
6887 MaskLen0 == MaskLen1 && MaskIdx1 == 0 &&
6888 (MaskIdx0 + MaskLen0 <= ValBits)) {
6905 (MaskIdx0 + MaskLen0 <= 64) &&
6913 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
6914 : (MaskIdx0 + MaskLen0 - 1),
6930 (MaskIdx0 + MaskLen0 <= ValBits)) {
6953 DAG.
getConstant(ValBits == 32 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
6954 : (MaskIdx0 + MaskLen0 - 1),
6969 unsigned MaskIdx, MaskLen;
6970 if (N1.getOpcode() ==
ISD::SHL && N1.getOperand(0).getOpcode() ==
ISD::AND &&
6979 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
6997 N1.getOperand(0).getOpcode() ==
ISD::SHL &&
7003 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
7011 if (!SwapAndRetried) {
7013 SwapAndRetried =
true;
7017 SwapAndRetried =
false;
7034 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
7043 if (!SwapAndRetried) {
7045 SwapAndRetried =
true;
7055 switch (V.getNode()->getOpcode()) {
7067 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
7075 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
7152 SDNode *AndNode =
N->getOperand(0).getNode();
7160 SDValue CmpInputValue =
N->getOperand(1);
7169 if (!CN || !CN->
isZero())
7171 AndInputValue1 = AndInputValue1.
getOperand(0);
7175 if (AndInputValue2 != CmpInputValue)
7208 TruncInputValue1, TruncInputValue2);
7210 DAG.
getSetCC(
SDLoc(
N),
N->getValueType(0), NewAnd, TruncInputValue2, CC);
7223 if (Src.getOpcode() != LoongArchISD::REVB_2W)
7226 return DAG.
getNode(LoongArchISD::BITREV_4B,
SDLoc(
N),
N->getValueType(0),
7251 LHS.getOperand(0).getValueType() == Subtarget.
getGRLenVT()) {
7279 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
7306 unsigned Sht =
LHS.getConstantOperandVal(1);
7310 if ((EleBits + Sht) == Subtarget.
getGRLen()) {
7329 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
N->getValueType(0),
7330 N->getOperand(0),
LHS,
RHS, CC,
N->getOperand(4));
7346 EVT VT =
N->getValueType(0);
7349 if (TrueV == FalseV)
7380 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL,
N->getValueType(0),
7381 {LHS, RHS, CC, TrueV, FalseV});
7386template <
unsigned N>
7390 bool IsSigned =
false) {
7394 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
7395 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
7397 ": argument out of range.");
7403template <
unsigned N>
7407 EVT ResTy =
Node->getValueType(0);
7411 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
7412 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
7414 ": argument out of range.");
7419 IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned),
7425 EVT ResTy =
Node->getValueType(0);
7433 EVT ResTy =
Node->getValueType(0);
7442template <
unsigned N>
7445 EVT ResTy =
Node->getValueType(0);
7450 ": argument out of range.");
7460template <
unsigned N>
7463 EVT ResTy =
Node->getValueType(0);
7468 ": argument out of range.");
7477template <
unsigned N>
7480 EVT ResTy =
Node->getValueType(0);
7485 ": argument out of range.");
7494template <
unsigned W>
7497 unsigned Imm =
N->getConstantOperandVal(2);
7499 const StringRef ErrorMsg =
"argument out of range";
7501 return DAG.
getUNDEF(
N->getValueType(0));
7507 return DAG.
getNode(ResOp,
DL,
N->getValueType(0), Vec, Idx, EltVT);
7515 switch (
N->getConstantOperandVal(0)) {
7518 case Intrinsic::loongarch_lsx_vadd_b:
7519 case Intrinsic::loongarch_lsx_vadd_h:
7520 case Intrinsic::loongarch_lsx_vadd_w:
7521 case Intrinsic::loongarch_lsx_vadd_d:
7522 case Intrinsic::loongarch_lasx_xvadd_b:
7523 case Intrinsic::loongarch_lasx_xvadd_h:
7524 case Intrinsic::loongarch_lasx_xvadd_w:
7525 case Intrinsic::loongarch_lasx_xvadd_d:
7528 case Intrinsic::loongarch_lsx_vaddi_bu:
7529 case Intrinsic::loongarch_lsx_vaddi_hu:
7530 case Intrinsic::loongarch_lsx_vaddi_wu:
7531 case Intrinsic::loongarch_lsx_vaddi_du:
7532 case Intrinsic::loongarch_lasx_xvaddi_bu:
7533 case Intrinsic::loongarch_lasx_xvaddi_hu:
7534 case Intrinsic::loongarch_lasx_xvaddi_wu:
7535 case Intrinsic::loongarch_lasx_xvaddi_du:
7538 case Intrinsic::loongarch_lsx_vsub_b:
7539 case Intrinsic::loongarch_lsx_vsub_h:
7540 case Intrinsic::loongarch_lsx_vsub_w:
7541 case Intrinsic::loongarch_lsx_vsub_d:
7542 case Intrinsic::loongarch_lasx_xvsub_b:
7543 case Intrinsic::loongarch_lasx_xvsub_h:
7544 case Intrinsic::loongarch_lasx_xvsub_w:
7545 case Intrinsic::loongarch_lasx_xvsub_d:
7548 case Intrinsic::loongarch_lsx_vsubi_bu:
7549 case Intrinsic::loongarch_lsx_vsubi_hu:
7550 case Intrinsic::loongarch_lsx_vsubi_wu:
7551 case Intrinsic::loongarch_lsx_vsubi_du:
7552 case Intrinsic::loongarch_lasx_xvsubi_bu:
7553 case Intrinsic::loongarch_lasx_xvsubi_hu:
7554 case Intrinsic::loongarch_lasx_xvsubi_wu:
7555 case Intrinsic::loongarch_lasx_xvsubi_du:
7558 case Intrinsic::loongarch_lsx_vneg_b:
7559 case Intrinsic::loongarch_lsx_vneg_h:
7560 case Intrinsic::loongarch_lsx_vneg_w:
7561 case Intrinsic::loongarch_lsx_vneg_d:
7562 case Intrinsic::loongarch_lasx_xvneg_b:
7563 case Intrinsic::loongarch_lasx_xvneg_h:
7564 case Intrinsic::loongarch_lasx_xvneg_w:
7565 case Intrinsic::loongarch_lasx_xvneg_d:
7569 APInt(
N->getValueType(0).getScalarType().getSizeInBits(), 0,
7571 SDLoc(
N),
N->getValueType(0)),
7573 case Intrinsic::loongarch_lsx_vmax_b:
7574 case Intrinsic::loongarch_lsx_vmax_h:
7575 case Intrinsic::loongarch_lsx_vmax_w:
7576 case Intrinsic::loongarch_lsx_vmax_d:
7577 case Intrinsic::loongarch_lasx_xvmax_b:
7578 case Intrinsic::loongarch_lasx_xvmax_h:
7579 case Intrinsic::loongarch_lasx_xvmax_w:
7580 case Intrinsic::loongarch_lasx_xvmax_d:
7583 case Intrinsic::loongarch_lsx_vmax_bu:
7584 case Intrinsic::loongarch_lsx_vmax_hu:
7585 case Intrinsic::loongarch_lsx_vmax_wu:
7586 case Intrinsic::loongarch_lsx_vmax_du:
7587 case Intrinsic::loongarch_lasx_xvmax_bu:
7588 case Intrinsic::loongarch_lasx_xvmax_hu:
7589 case Intrinsic::loongarch_lasx_xvmax_wu:
7590 case Intrinsic::loongarch_lasx_xvmax_du:
7593 case Intrinsic::loongarch_lsx_vmaxi_b:
7594 case Intrinsic::loongarch_lsx_vmaxi_h:
7595 case Intrinsic::loongarch_lsx_vmaxi_w:
7596 case Intrinsic::loongarch_lsx_vmaxi_d:
7597 case Intrinsic::loongarch_lasx_xvmaxi_b:
7598 case Intrinsic::loongarch_lasx_xvmaxi_h:
7599 case Intrinsic::loongarch_lasx_xvmaxi_w:
7600 case Intrinsic::loongarch_lasx_xvmaxi_d:
7603 case Intrinsic::loongarch_lsx_vmaxi_bu:
7604 case Intrinsic::loongarch_lsx_vmaxi_hu:
7605 case Intrinsic::loongarch_lsx_vmaxi_wu:
7606 case Intrinsic::loongarch_lsx_vmaxi_du:
7607 case Intrinsic::loongarch_lasx_xvmaxi_bu:
7608 case Intrinsic::loongarch_lasx_xvmaxi_hu:
7609 case Intrinsic::loongarch_lasx_xvmaxi_wu:
7610 case Intrinsic::loongarch_lasx_xvmaxi_du:
7613 case Intrinsic::loongarch_lsx_vmin_b:
7614 case Intrinsic::loongarch_lsx_vmin_h:
7615 case Intrinsic::loongarch_lsx_vmin_w:
7616 case Intrinsic::loongarch_lsx_vmin_d:
7617 case Intrinsic::loongarch_lasx_xvmin_b:
7618 case Intrinsic::loongarch_lasx_xvmin_h:
7619 case Intrinsic::loongarch_lasx_xvmin_w:
7620 case Intrinsic::loongarch_lasx_xvmin_d:
7623 case Intrinsic::loongarch_lsx_vmin_bu:
7624 case Intrinsic::loongarch_lsx_vmin_hu:
7625 case Intrinsic::loongarch_lsx_vmin_wu:
7626 case Intrinsic::loongarch_lsx_vmin_du:
7627 case Intrinsic::loongarch_lasx_xvmin_bu:
7628 case Intrinsic::loongarch_lasx_xvmin_hu:
7629 case Intrinsic::loongarch_lasx_xvmin_wu:
7630 case Intrinsic::loongarch_lasx_xvmin_du:
7633 case Intrinsic::loongarch_lsx_vmini_b:
7634 case Intrinsic::loongarch_lsx_vmini_h:
7635 case Intrinsic::loongarch_lsx_vmini_w:
7636 case Intrinsic::loongarch_lsx_vmini_d:
7637 case Intrinsic::loongarch_lasx_xvmini_b:
7638 case Intrinsic::loongarch_lasx_xvmini_h:
7639 case Intrinsic::loongarch_lasx_xvmini_w:
7640 case Intrinsic::loongarch_lasx_xvmini_d:
7643 case Intrinsic::loongarch_lsx_vmini_bu:
7644 case Intrinsic::loongarch_lsx_vmini_hu:
7645 case Intrinsic::loongarch_lsx_vmini_wu:
7646 case Intrinsic::loongarch_lsx_vmini_du:
7647 case Intrinsic::loongarch_lasx_xvmini_bu:
7648 case Intrinsic::loongarch_lasx_xvmini_hu:
7649 case Intrinsic::loongarch_lasx_xvmini_wu:
7650 case Intrinsic::loongarch_lasx_xvmini_du:
7653 case Intrinsic::loongarch_lsx_vmul_b:
7654 case Intrinsic::loongarch_lsx_vmul_h:
7655 case Intrinsic::loongarch_lsx_vmul_w:
7656 case Intrinsic::loongarch_lsx_vmul_d:
7657 case Intrinsic::loongarch_lasx_xvmul_b:
7658 case Intrinsic::loongarch_lasx_xvmul_h:
7659 case Intrinsic::loongarch_lasx_xvmul_w:
7660 case Intrinsic::loongarch_lasx_xvmul_d:
7663 case Intrinsic::loongarch_lsx_vmadd_b:
7664 case Intrinsic::loongarch_lsx_vmadd_h:
7665 case Intrinsic::loongarch_lsx_vmadd_w:
7666 case Intrinsic::loongarch_lsx_vmadd_d:
7667 case Intrinsic::loongarch_lasx_xvmadd_b:
7668 case Intrinsic::loongarch_lasx_xvmadd_h:
7669 case Intrinsic::loongarch_lasx_xvmadd_w:
7670 case Intrinsic::loongarch_lasx_xvmadd_d: {
7671 EVT ResTy =
N->getValueType(0);
7676 case Intrinsic::loongarch_lsx_vmsub_b:
7677 case Intrinsic::loongarch_lsx_vmsub_h:
7678 case Intrinsic::loongarch_lsx_vmsub_w:
7679 case Intrinsic::loongarch_lsx_vmsub_d:
7680 case Intrinsic::loongarch_lasx_xvmsub_b:
7681 case Intrinsic::loongarch_lasx_xvmsub_h:
7682 case Intrinsic::loongarch_lasx_xvmsub_w:
7683 case Intrinsic::loongarch_lasx_xvmsub_d: {
7684 EVT ResTy =
N->getValueType(0);
7689 case Intrinsic::loongarch_lsx_vdiv_b:
7690 case Intrinsic::loongarch_lsx_vdiv_h:
7691 case Intrinsic::loongarch_lsx_vdiv_w:
7692 case Intrinsic::loongarch_lsx_vdiv_d:
7693 case Intrinsic::loongarch_lasx_xvdiv_b:
7694 case Intrinsic::loongarch_lasx_xvdiv_h:
7695 case Intrinsic::loongarch_lasx_xvdiv_w:
7696 case Intrinsic::loongarch_lasx_xvdiv_d:
7699 case Intrinsic::loongarch_lsx_vdiv_bu:
7700 case Intrinsic::loongarch_lsx_vdiv_hu:
7701 case Intrinsic::loongarch_lsx_vdiv_wu:
7702 case Intrinsic::loongarch_lsx_vdiv_du:
7703 case Intrinsic::loongarch_lasx_xvdiv_bu:
7704 case Intrinsic::loongarch_lasx_xvdiv_hu:
7705 case Intrinsic::loongarch_lasx_xvdiv_wu:
7706 case Intrinsic::loongarch_lasx_xvdiv_du:
7709 case Intrinsic::loongarch_lsx_vmod_b:
7710 case Intrinsic::loongarch_lsx_vmod_h:
7711 case Intrinsic::loongarch_lsx_vmod_w:
7712 case Intrinsic::loongarch_lsx_vmod_d:
7713 case Intrinsic::loongarch_lasx_xvmod_b:
7714 case Intrinsic::loongarch_lasx_xvmod_h:
7715 case Intrinsic::loongarch_lasx_xvmod_w:
7716 case Intrinsic::loongarch_lasx_xvmod_d:
7719 case Intrinsic::loongarch_lsx_vmod_bu:
7720 case Intrinsic::loongarch_lsx_vmod_hu:
7721 case Intrinsic::loongarch_lsx_vmod_wu:
7722 case Intrinsic::loongarch_lsx_vmod_du:
7723 case Intrinsic::loongarch_lasx_xvmod_bu:
7724 case Intrinsic::loongarch_lasx_xvmod_hu:
7725 case Intrinsic::loongarch_lasx_xvmod_wu:
7726 case Intrinsic::loongarch_lasx_xvmod_du:
7729 case Intrinsic::loongarch_lsx_vand_v:
7730 case Intrinsic::loongarch_lasx_xvand_v:
7733 case Intrinsic::loongarch_lsx_vor_v:
7734 case Intrinsic::loongarch_lasx_xvor_v:
7737 case Intrinsic::loongarch_lsx_vxor_v:
7738 case Intrinsic::loongarch_lasx_xvxor_v:
7741 case Intrinsic::loongarch_lsx_vnor_v:
7742 case Intrinsic::loongarch_lasx_xvnor_v: {
7747 case Intrinsic::loongarch_lsx_vandi_b:
7748 case Intrinsic::loongarch_lasx_xvandi_b:
7751 case Intrinsic::loongarch_lsx_vori_b:
7752 case Intrinsic::loongarch_lasx_xvori_b:
7755 case Intrinsic::loongarch_lsx_vxori_b:
7756 case Intrinsic::loongarch_lasx_xvxori_b:
7759 case Intrinsic::loongarch_lsx_vsll_b:
7760 case Intrinsic::loongarch_lsx_vsll_h:
7761 case Intrinsic::loongarch_lsx_vsll_w:
7762 case Intrinsic::loongarch_lsx_vsll_d:
7763 case Intrinsic::loongarch_lasx_xvsll_b:
7764 case Intrinsic::loongarch_lasx_xvsll_h:
7765 case Intrinsic::loongarch_lasx_xvsll_w:
7766 case Intrinsic::loongarch_lasx_xvsll_d:
7769 case Intrinsic::loongarch_lsx_vslli_b:
7770 case Intrinsic::loongarch_lasx_xvslli_b:
7773 case Intrinsic::loongarch_lsx_vslli_h:
7774 case Intrinsic::loongarch_lasx_xvslli_h:
7777 case Intrinsic::loongarch_lsx_vslli_w:
7778 case Intrinsic::loongarch_lasx_xvslli_w:
7781 case Intrinsic::loongarch_lsx_vslli_d:
7782 case Intrinsic::loongarch_lasx_xvslli_d:
7785 case Intrinsic::loongarch_lsx_vsrl_b:
7786 case Intrinsic::loongarch_lsx_vsrl_h:
7787 case Intrinsic::loongarch_lsx_vsrl_w:
7788 case Intrinsic::loongarch_lsx_vsrl_d:
7789 case Intrinsic::loongarch_lasx_xvsrl_b:
7790 case Intrinsic::loongarch_lasx_xvsrl_h:
7791 case Intrinsic::loongarch_lasx_xvsrl_w:
7792 case Intrinsic::loongarch_lasx_xvsrl_d:
7795 case Intrinsic::loongarch_lsx_vsrli_b:
7796 case Intrinsic::loongarch_lasx_xvsrli_b:
7799 case Intrinsic::loongarch_lsx_vsrli_h:
7800 case Intrinsic::loongarch_lasx_xvsrli_h:
7803 case Intrinsic::loongarch_lsx_vsrli_w:
7804 case Intrinsic::loongarch_lasx_xvsrli_w:
7807 case Intrinsic::loongarch_lsx_vsrli_d:
7808 case Intrinsic::loongarch_lasx_xvsrli_d:
7811 case Intrinsic::loongarch_lsx_vsra_b:
7812 case Intrinsic::loongarch_lsx_vsra_h:
7813 case Intrinsic::loongarch_lsx_vsra_w:
7814 case Intrinsic::loongarch_lsx_vsra_d:
7815 case Intrinsic::loongarch_lasx_xvsra_b:
7816 case Intrinsic::loongarch_lasx_xvsra_h:
7817 case Intrinsic::loongarch_lasx_xvsra_w:
7818 case Intrinsic::loongarch_lasx_xvsra_d:
7821 case Intrinsic::loongarch_lsx_vsrai_b:
7822 case Intrinsic::loongarch_lasx_xvsrai_b:
7825 case Intrinsic::loongarch_lsx_vsrai_h:
7826 case Intrinsic::loongarch_lasx_xvsrai_h:
7829 case Intrinsic::loongarch_lsx_vsrai_w:
7830 case Intrinsic::loongarch_lasx_xvsrai_w:
7833 case Intrinsic::loongarch_lsx_vsrai_d:
7834 case Intrinsic::loongarch_lasx_xvsrai_d:
7837 case Intrinsic::loongarch_lsx_vclz_b:
7838 case Intrinsic::loongarch_lsx_vclz_h:
7839 case Intrinsic::loongarch_lsx_vclz_w:
7840 case Intrinsic::loongarch_lsx_vclz_d:
7841 case Intrinsic::loongarch_lasx_xvclz_b:
7842 case Intrinsic::loongarch_lasx_xvclz_h:
7843 case Intrinsic::loongarch_lasx_xvclz_w:
7844 case Intrinsic::loongarch_lasx_xvclz_d:
7846 case Intrinsic::loongarch_lsx_vpcnt_b:
7847 case Intrinsic::loongarch_lsx_vpcnt_h:
7848 case Intrinsic::loongarch_lsx_vpcnt_w:
7849 case Intrinsic::loongarch_lsx_vpcnt_d:
7850 case Intrinsic::loongarch_lasx_xvpcnt_b:
7851 case Intrinsic::loongarch_lasx_xvpcnt_h:
7852 case Intrinsic::loongarch_lasx_xvpcnt_w:
7853 case Intrinsic::loongarch_lasx_xvpcnt_d:
7855 case Intrinsic::loongarch_lsx_vbitclr_b:
7856 case Intrinsic::loongarch_lsx_vbitclr_h:
7857 case Intrinsic::loongarch_lsx_vbitclr_w:
7858 case Intrinsic::loongarch_lsx_vbitclr_d:
7859 case Intrinsic::loongarch_lasx_xvbitclr_b:
7860 case Intrinsic::loongarch_lasx_xvbitclr_h:
7861 case Intrinsic::loongarch_lasx_xvbitclr_w:
7862 case Intrinsic::loongarch_lasx_xvbitclr_d:
7864 case Intrinsic::loongarch_lsx_vbitclri_b:
7865 case Intrinsic::loongarch_lasx_xvbitclri_b:
7867 case Intrinsic::loongarch_lsx_vbitclri_h:
7868 case Intrinsic::loongarch_lasx_xvbitclri_h:
7870 case Intrinsic::loongarch_lsx_vbitclri_w:
7871 case Intrinsic::loongarch_lasx_xvbitclri_w:
7873 case Intrinsic::loongarch_lsx_vbitclri_d:
7874 case Intrinsic::loongarch_lasx_xvbitclri_d:
7876 case Intrinsic::loongarch_lsx_vbitset_b:
7877 case Intrinsic::loongarch_lsx_vbitset_h:
7878 case Intrinsic::loongarch_lsx_vbitset_w:
7879 case Intrinsic::loongarch_lsx_vbitset_d:
7880 case Intrinsic::loongarch_lasx_xvbitset_b:
7881 case Intrinsic::loongarch_lasx_xvbitset_h:
7882 case Intrinsic::loongarch_lasx_xvbitset_w:
7883 case Intrinsic::loongarch_lasx_xvbitset_d: {
7884 EVT VecTy =
N->getValueType(0);
7890 case Intrinsic::loongarch_lsx_vbitseti_b:
7891 case Intrinsic::loongarch_lasx_xvbitseti_b:
7893 case Intrinsic::loongarch_lsx_vbitseti_h:
7894 case Intrinsic::loongarch_lasx_xvbitseti_h:
7896 case Intrinsic::loongarch_lsx_vbitseti_w:
7897 case Intrinsic::loongarch_lasx_xvbitseti_w:
7899 case Intrinsic::loongarch_lsx_vbitseti_d:
7900 case Intrinsic::loongarch_lasx_xvbitseti_d:
7902 case Intrinsic::loongarch_lsx_vbitrev_b:
7903 case Intrinsic::loongarch_lsx_vbitrev_h:
7904 case Intrinsic::loongarch_lsx_vbitrev_w:
7905 case Intrinsic::loongarch_lsx_vbitrev_d:
7906 case Intrinsic::loongarch_lasx_xvbitrev_b:
7907 case Intrinsic::loongarch_lasx_xvbitrev_h:
7908 case Intrinsic::loongarch_lasx_xvbitrev_w:
7909 case Intrinsic::loongarch_lasx_xvbitrev_d: {
7910 EVT VecTy =
N->getValueType(0);
7916 case Intrinsic::loongarch_lsx_vbitrevi_b:
7917 case Intrinsic::loongarch_lasx_xvbitrevi_b:
7919 case Intrinsic::loongarch_lsx_vbitrevi_h:
7920 case Intrinsic::loongarch_lasx_xvbitrevi_h:
7922 case Intrinsic::loongarch_lsx_vbitrevi_w:
7923 case Intrinsic::loongarch_lasx_xvbitrevi_w:
7925 case Intrinsic::loongarch_lsx_vbitrevi_d:
7926 case Intrinsic::loongarch_lasx_xvbitrevi_d:
7928 case Intrinsic::loongarch_lsx_vfadd_s:
7929 case Intrinsic::loongarch_lsx_vfadd_d:
7930 case Intrinsic::loongarch_lasx_xvfadd_s:
7931 case Intrinsic::loongarch_lasx_xvfadd_d:
7934 case Intrinsic::loongarch_lsx_vfsub_s:
7935 case Intrinsic::loongarch_lsx_vfsub_d:
7936 case Intrinsic::loongarch_lasx_xvfsub_s:
7937 case Intrinsic::loongarch_lasx_xvfsub_d:
7940 case Intrinsic::loongarch_lsx_vfmul_s:
7941 case Intrinsic::loongarch_lsx_vfmul_d:
7942 case Intrinsic::loongarch_lasx_xvfmul_s:
7943 case Intrinsic::loongarch_lasx_xvfmul_d:
7946 case Intrinsic::loongarch_lsx_vfdiv_s:
7947 case Intrinsic::loongarch_lsx_vfdiv_d:
7948 case Intrinsic::loongarch_lasx_xvfdiv_s:
7949 case Intrinsic::loongarch_lasx_xvfdiv_d:
7952 case Intrinsic::loongarch_lsx_vfmadd_s:
7953 case Intrinsic::loongarch_lsx_vfmadd_d:
7954 case Intrinsic::loongarch_lasx_xvfmadd_s:
7955 case Intrinsic::loongarch_lasx_xvfmadd_d:
7957 N->getOperand(2),
N->getOperand(3));
7958 case Intrinsic::loongarch_lsx_vinsgr2vr_b:
7960 N->getOperand(1),
N->getOperand(2),
7962 case Intrinsic::loongarch_lsx_vinsgr2vr_h:
7963 case Intrinsic::loongarch_lasx_xvinsgr2vr_w:
7965 N->getOperand(1),
N->getOperand(2),
7967 case Intrinsic::loongarch_lsx_vinsgr2vr_w:
7968 case Intrinsic::loongarch_lasx_xvinsgr2vr_d:
7970 N->getOperand(1),
N->getOperand(2),
7972 case Intrinsic::loongarch_lsx_vinsgr2vr_d:
7974 N->getOperand(1),
N->getOperand(2),
7976 case Intrinsic::loongarch_lsx_vreplgr2vr_b:
7977 case Intrinsic::loongarch_lsx_vreplgr2vr_h:
7978 case Intrinsic::loongarch_lsx_vreplgr2vr_w:
7979 case Intrinsic::loongarch_lsx_vreplgr2vr_d:
7980 case Intrinsic::loongarch_lasx_xvreplgr2vr_b:
7981 case Intrinsic::loongarch_lasx_xvreplgr2vr_h:
7982 case Intrinsic::loongarch_lasx_xvreplgr2vr_w:
7983 case Intrinsic::loongarch_lasx_xvreplgr2vr_d:
7984 return DAG.
getNode(LoongArchISD::VREPLGR2VR,
DL,
N->getValueType(0),
7987 case Intrinsic::loongarch_lsx_vreplve_b:
7988 case Intrinsic::loongarch_lsx_vreplve_h:
7989 case Intrinsic::loongarch_lsx_vreplve_w:
7990 case Intrinsic::loongarch_lsx_vreplve_d:
7991 case Intrinsic::loongarch_lasx_xvreplve_b:
7992 case Intrinsic::loongarch_lasx_xvreplve_h:
7993 case Intrinsic::loongarch_lasx_xvreplve_w:
7994 case Intrinsic::loongarch_lasx_xvreplve_d:
7995 return DAG.
getNode(LoongArchISD::VREPLVE,
DL,
N->getValueType(0),
7999 case Intrinsic::loongarch_lsx_vpickve2gr_b:
8003 case Intrinsic::loongarch_lsx_vpickve2gr_h:
8004 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
8008 case Intrinsic::loongarch_lsx_vpickve2gr_w:
8012 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
8016 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
8017 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
8021 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
8025 case Intrinsic::loongarch_lsx_bz_b:
8026 case Intrinsic::loongarch_lsx_bz_h:
8027 case Intrinsic::loongarch_lsx_bz_w:
8028 case Intrinsic::loongarch_lsx_bz_d:
8029 case Intrinsic::loongarch_lasx_xbz_b:
8030 case Intrinsic::loongarch_lasx_xbz_h:
8031 case Intrinsic::loongarch_lasx_xbz_w:
8032 case Intrinsic::loongarch_lasx_xbz_d:
8034 return DAG.
getNode(LoongArchISD::VALL_ZERO,
DL,
N->getValueType(0),
8037 case Intrinsic::loongarch_lsx_bz_v:
8038 case Intrinsic::loongarch_lasx_xbz_v:
8040 return DAG.
getNode(LoongArchISD::VANY_ZERO,
DL,
N->getValueType(0),
8043 case Intrinsic::loongarch_lsx_bnz_b:
8044 case Intrinsic::loongarch_lsx_bnz_h:
8045 case Intrinsic::loongarch_lsx_bnz_w:
8046 case Intrinsic::loongarch_lsx_bnz_d:
8047 case Intrinsic::loongarch_lasx_xbnz_b:
8048 case Intrinsic::loongarch_lasx_xbnz_h:
8049 case Intrinsic::loongarch_lasx_xbnz_w:
8050 case Intrinsic::loongarch_lasx_xbnz_d:
8052 return DAG.
getNode(LoongArchISD::VALL_NONZERO,
DL,
N->getValueType(0),
8055 case Intrinsic::loongarch_lsx_bnz_v:
8056 case Intrinsic::loongarch_lasx_xbnz_v:
8058 return DAG.
getNode(LoongArchISD::VANY_NONZERO,
DL,
N->getValueType(0),
8061 case Intrinsic::loongarch_lasx_concat_128_s:
8062 case Intrinsic::loongarch_lasx_concat_128_d:
8063 case Intrinsic::loongarch_lasx_concat_128:
8065 N->getOperand(1),
N->getOperand(2));
8077 if (Op0.
getOpcode() == LoongArchISD::MOVFR2GR_S_LA64)
8089 if (Op0->
getOpcode() == LoongArchISD::MOVGR2FR_W_LA64) {
8091 "Unexpected value type!");
8100 MVT VT =
N->getSimpleValueType(0);
8121 if (Op0->
getOpcode() == LoongArchISD::BUILD_PAIR_F64)
8134 APInt V =
C->getValueAPF().bitcastToAPInt();
8149 MVT VT =
N->getSimpleValueType(0);
8208 EVT VT =
N->getValueType(0);
8210 EVT SrcVT = Src.getValueType();
8216 if (SrcEltBits >= DstEltBits)
8223 return DAG.
getNode(
N->getOpcode(),
DL, VT, Extend);
8235 unsigned BlockBits) {
8237 MVT DstVT =
N->getSimpleValueType(0);
8239 MVT SrcVT = Src.getSimpleValueType();
8246 Src.getOperand(0).getValueType() == BlockVT) {
8247 for (
unsigned i = 0; i < Src.getNumOperands(); ++i)
8249 }
else if (SrcBits > BlockBits) {
8251 for (
unsigned i = 0; i < SrcBits / BlockBits; ++i)
8256 BlockBits = SrcBits;
8263 for (
unsigned i = 0; i < Blocks.
size(); i += 2) {
8268 if (BlockBits == 256) {
8278 if (Blocks.
size() == 1)
8288 EVT VT =
N->getValueType(0);
8290 EVT SrcVT = Src.getValueType();
8296 unsigned BlockBits = Subtarget.hasExtLASX() ? 256 : 128;
8299 if (SrcEltBits <= DstEltBits)
8302 if (SrcEltBits != 64 || DstEltBits != 32 || !
isPowerOf2_32(NumElts))
8312 if (VT != MVT::f32 && VT != MVT::f64)
8314 if (VT == MVT::f32 && !Subtarget.hasBasicF())
8316 if (VT == MVT::f64 && !Subtarget.hasBasicD())
8348 EVT VT =
N->getValueType(0);
8365 if (!Subtarget.hasExtLSX())
8369 EVT DstVT =
N->getValueType(0);
8371 EVT SrcVT = Src.getValueType();
8381 unsigned BlockBits = Subtarget.hasExtLASX() ? 256 : 128;
8386 if (SrcBits % BlockBits != 0 && SrcBits != 128)
8389 if (DstEltBits < 32) {
8395 if (SrcEltBits != 64 || DstEltBits != 32)
8400 if (Subtarget.hasExtLASX())