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)
114 if (Subtarget.hasBasicF())
172 if (Subtarget.is64Bit()) {
200 if (!Subtarget.is64Bit()) {
206 if (Subtarget.hasBasicD())
218 if (Subtarget.hasBasicF()) {
252 if (Subtarget.is64Bit())
255 if (!Subtarget.hasBasicD()) {
257 if (Subtarget.is64Bit()) {
266 if (Subtarget.hasBasicD()) {
299 if (Subtarget.is64Bit())
305 if (Subtarget.hasExtLSX()) {
320 for (
MVT VT : LSXVTs) {
334 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64}) {
362 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
364 for (
MVT VT : {MVT::v8i16, MVT::v4i32, MVT::v2i64})
366 for (
MVT VT : {MVT::v4i32, MVT::v2i64}) {
372 for (
MVT VT : {MVT::v4f32, MVT::v2f64}) {
396 {MVT::v16i8, MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v8i16, MVT::v4i16,
397 MVT::v2i16, MVT::v4i32, MVT::v2i32, MVT::v2i64}) {
412 for (
MVT VT : {MVT::v2i64, MVT::v4i32, MVT::v8i16})
414 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64, MVT::v16i32, MVT::v8i64,
421 if (Subtarget.hasExtLASX()) {
422 for (
MVT VT : LASXVTs) {
437 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16, MVT::v32i8}) {
466 for (
MVT VT : {MVT::v32i8, MVT::v16i16, MVT::v8i32})
468 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64})
470 for (
MVT VT : {MVT::v8i32, MVT::v4i64})
472 for (
MVT VT : {MVT::v8i32, MVT::v4i32, MVT::v4i64}) {
477 for (
MVT VT : {MVT::v8f32, MVT::v4f64}) {
496 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16}) {
502 {MVT::v2i64, MVT::v4i32, MVT::v4i64, MVT::v8i16, MVT::v8i32}) {
506 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
511 if (Subtarget.hasBasicF()) {
528 if (Subtarget.has32S())
533 if (Subtarget.hasExtLSX()) {
548 if (Subtarget.hasExtLASX()) {
573 if (Subtarget.hasLAMCAS())
576 if (Subtarget.hasSCQ()) {
596 switch (
Op.getOpcode()) {
598 return lowerATOMIC_FENCE(
Op, DAG);
600 return lowerEH_DWARF_CFA(
Op, DAG);
602 return lowerGlobalAddress(
Op, DAG);
604 return lowerGlobalTLSAddress(
Op, DAG);
606 return lowerINTRINSIC_WO_CHAIN(
Op, DAG);
608 return lowerINTRINSIC_W_CHAIN(
Op, DAG);
610 return lowerINTRINSIC_VOID(
Op, DAG);
612 return lowerBlockAddress(
Op, DAG);
614 return lowerJumpTable(
Op, DAG);
616 return lowerShiftLeftParts(
Op, DAG);
618 return lowerShiftRightParts(
Op, DAG,
true);
620 return lowerShiftRightParts(
Op, DAG,
false);
622 return lowerConstantPool(
Op, DAG);
624 return lowerFP_TO_SINT(
Op, DAG);
626 return lowerFP_TO_UINT(
Op, DAG);
628 return lowerFP_TO_SINT_SAT(
Op, DAG);
630 return lowerBITCAST(
Op, DAG);
632 return lowerUINT_TO_FP(
Op, DAG);
634 return lowerSINT_TO_FP(
Op, DAG);
636 return lowerVASTART(
Op, DAG);
638 return lowerFRAMEADDR(
Op, DAG);
640 return lowerRETURNADDR(
Op, DAG);
642 return lowerSET_ROUNDING(
Op, DAG);
644 return lowerGET_ROUNDING(
Op, DAG);
646 return lowerWRITE_REGISTER(
Op, DAG);
648 return lowerINSERT_VECTOR_ELT(
Op, DAG);
650 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
652 return lowerBUILD_VECTOR(
Op, DAG);
654 return lowerCONCAT_VECTORS(
Op, DAG);
656 return lowerVECTOR_SHUFFLE(
Op, DAG);
658 return lowerBITREVERSE(
Op, DAG);
660 return lowerSCALAR_TO_VECTOR(
Op, DAG);
662 return lowerPREFETCH(
Op, DAG);
664 return lowerSELECT(
Op, DAG);
666 return lowerBRCOND(
Op, DAG);
668 return lowerFP_TO_FP16(
Op, DAG);
670 return lowerFP16_TO_FP(
Op, DAG);
672 return lowerFP_TO_BF16(
Op, DAG);
674 return lowerBF16_TO_FP(
Op, DAG);
676 return lowerVECREDUCE_ADD(
Op, DAG);
679 return lowerRotate(
Op, DAG);
687 return lowerVECREDUCE(
Op, DAG);
689 return lowerConstantFP(
Op, DAG);
691 return lowerSETCC(
Op, DAG);
693 return lowerFP_ROUND(
Op, DAG);
695 return lowerFP_EXTEND(
Op, DAG);
697 return lowerSIGN_EXTEND_VECTOR_INREG(
Op, DAG);
699 return lowerDYNAMIC_STACKALLOC(
Op, DAG);
701 return lowerANY_EXTEND(
Op, DAG);
710 EVT VT = V.getValueType();
716 return V.getOperand(0);
720 (
isNullConstant(V.getOperand(1)) || V.getOperand(0).hasOneUse())) {
722 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
732 if (!V->isOnlyUserOf(SplatValue.getNode()))
736 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
744 V.getOperand(0).hasOneUse() && V.getOperand(1).hasOneUse()) {
772 (
N->getOpcode() == LoongArchISD::VPACKEV) ||
773 (
N->getOpcode() == LoongArchISD::VPERMI)) &&
780 if (Opcode0 != Opcode1)
783 if (Opcode0 !=
ISD::FP_ROUND && Opcode0 != LoongArchISD::VFCVT)
790 EVT VT =
N.getValueType();
804 if (Subtarget.hasExtLASX() && VT.
is256BitVector() && SVT0 == MVT::v4f32 &&
805 SSVT0 == MVT::v4f64) {
824 if ((
N->getOpcode() == LoongArchISD::VPACKEV ||
825 N->getOpcode() == LoongArchISD::VPERMI) &&
826 Opcode0 == LoongArchISD::VFCVT) {
831 if (!Subtarget.hasExtLSX() || SVT0 != MVT::v4f32 || SSVT0 != MVT::v2f64)
834 if (
N->getOpcode() == LoongArchISD::VPACKEV &&
835 (VT == MVT::v2i64 || VT == MVT::v2f64)) {
841 if (
N->getOpcode() == LoongArchISD::VPERMI && VT == MVT::v4f32) {
856 SDValue
In =
Op.getOperand(0);
857 MVT VT =
Op.getSimpleValueType();
858 MVT SVT =
In.getSimpleValueType();
860 if (VT == MVT::v4f32 && SVT == MVT::v4f64) {
873 EVT VT =
Op.getValueType();
874 SDValue Src =
Op->getOperand(0);
875 EVT SVT = Src.getValueType();
878 VT == MVT::v2f64 && SVT == MVT::v2f32 && Subtarget.hasExtLSX();
880 VT == MVT::v4f64 && SVT == MVT::v4f32 && Subtarget.hasExtLASX();
881 if (!V2F32ToV2F64 && !V4F32ToV4F64)
885 auto CheckVecHighPart = [](SDValue
Op) {
888 SDValue SOp =
Op.getOperand(0);
908 if (SDValue V = CheckVecHighPart(Src)) {
910 "Unexpected wide vector");
911 Opcode = LoongArchISD::VFCVTH;
914 Opcode = LoongArchISD::VFCVTL;
916 DAG.
getUNDEF(WideOpVT), Src, ZeroIdx);
921 return DAG.
getNode(Opcode,
DL, VT, VFCVTOp);
927 SmallVector<int, 8>
Mask = {0, 1, 4, 5, 2, 3, 6, 7};
939 EVT VT =
Op.getValueType();
944 assert((VT == MVT::f32 && Subtarget.hasBasicF()) ||
945 (VT == MVT::f64 && Subtarget.hasBasicD()));
962 int InsNum = Seq.size() + ((VT == MVT::f64 && !Subtarget.is64Bit()) ? 2 : 1);
972 if (Subtarget.is64Bit())
974 return DAG.
getNode(Subtarget.is64Bit() ? LoongArchISD::MOVGR2FR_W_LA64
975 : LoongArchISD::MOVGR2FR_W,
979 if (Subtarget.is64Bit()) {
981 return DAG.
getNode(LoongArchISD::MOVGR2FR_D,
DL, VT, NewVal);
985 return DAG.
getNode(LoongArchISD::MOVGR2FR_D_LO_HI,
DL, VT,
Lo,
Hi);
997 EVT ResultVT =
Op.getValueType();
998 EVT OperandVT =
Op.getOperand(0).getValueType();
1003 if (ResultVT == SetCCResultVT)
1006 assert(
Op.getOperand(0).getValueType() ==
Op.getOperand(1).getValueType() &&
1007 "SETCC operands must have the same type!");
1011 Op.getOperand(1),
Op.getOperand(2));
1013 if (ResultVT.
bitsGT(SetCCResultVT))
1015 else if (ResultVT.
bitsLT(SetCCResultVT))
1027SDValue LoongArchTargetLowering::lowerSIGN_EXTEND_VECTOR_INREG(
1030 SDValue Src =
Op.getOperand(0);
1031 MVT SrcVT = Src.getSimpleValueType();
1032 MVT DstVT =
Op.getSimpleValueType();
1042 SDValue LoInterleaved =
1043 DAG.
getNode(LoongArchISD::VILVL,
DL, SrcVT, Mask, Src);
1054 assert(Subtarget.hasExtLASX());
1073 MVT OpVT =
Op.getSimpleValueType();
1074 SDValue Val =
Op.getOperand(0);
1080 unsigned LegalVecSize = 128;
1081 bool isLASX256Vector =
1091 if (isLASX256Vector) {
1097 for (
unsigned i = 1; i < NumEles; i *= 2, EleBits *= 2) {
1098 EleBits = std::min(EleBits, 64u);
1101 Val = DAG.
getNode(LoongArchISD::VHADDW,
DL, VecTy, Val, Val);
1104 if (isLASX256Vector) {
1105 SDValue Tmp = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, Val,
1130 MVT OpVT =
Op.getSimpleValueType();
1131 SDValue Val =
Op.getOperand(0);
1143 MVT GRLenVT = Subtarget.getGRLenVT();
1145 for (
int i = NumEles; i > 1; i /= 2) {
1146 SDValue ShiftAmt = DAG.
getConstant(i * EleBits / 16,
DL, GRLenVT);
1147 SDValue Tmp = DAG.
getNode(LoongArchISD::VBSRL,
DL, VecTy, Val, ShiftAmt);
1148 Val = DAG.
getNode(Opcode,
DL, VecTy, Tmp, Val);
1157 unsigned IsData =
Op.getConstantOperandVal(4);
1162 return Op.getOperand(0);
1169 MVT VT =
Op.getSimpleValueType();
1173 SDValue
R =
Op.getOperand(0);
1174 SDValue Amt =
Op.getOperand(1);
1175 unsigned Opcode =
Op.getOpcode();
1178 auto checkCstSplat = [](SDValue
V, APInt &CstSplatValue) {
1181 if (SDValue SplatValue =
1184 CstSplatValue =
C->getAPIntValue();
1192 APInt CstSplatValue;
1193 bool IsCstSplat = checkCstSplat(Amt, CstSplatValue);
1197 if (IsCstSplat && CstSplatValue.
urem(EltSizeInBits) == 0)
1213 return DAG.
getNode(Opcode,
DL, VT, R, Urem);
1229 if (
LHS == LHS2 &&
RHS == RHS2) {
1234 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
1242 return std::nullopt;
1250 MVT VT =
N->getSimpleValueType(0);
1281 if (~TrueVal == FalseVal) {
1321 unsigned SelOpNo = 0;
1331 unsigned ConstSelOpNo = 1;
1332 unsigned OtherSelOpNo = 2;
1339 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
1344 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
1350 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
1352 std::swap(NewConstOps[0], NewConstOps[1]);
1364 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
1366 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
1369 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
1370 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
1390 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
1404 int64_t
C = RHSC->getSExtValue();
1443 SDValue CondV =
Op.getOperand(0);
1444 SDValue TrueV =
Op.getOperand(1);
1445 SDValue FalseV =
Op.getOperand(2);
1447 MVT VT =
Op.getSimpleValueType();
1448 MVT GRLenVT = Subtarget.getGRLenVT();
1453 if (
Op.hasOneUse()) {
1454 unsigned UseOpc =
Op->user_begin()->getOpcode();
1456 SDNode *BinOp = *
Op->user_begin();
1463 return lowerSELECT(NewSel, DAG);
1478 SDValue
Ops[] = {CondV,
Zero, SetNE, TrueV, FalseV};
1480 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1503 if (TrueVal - 1 == FalseVal)
1505 if (TrueVal + 1 == FalseVal)
1512 RHS == TrueV &&
LHS == FalseV) {
1536 SDValue
Ops[] = {
LHS,
RHS, TargetCC, TrueV, FalseV};
1537 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1542 SDValue CondV =
Op.getOperand(1);
1544 MVT GRLenVT = Subtarget.getGRLenVT();
1555 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1556 Op.getOperand(0),
LHS,
RHS, TargetCC,
1559 return DAG.
getNode(LoongArchISD::BRCOND,
DL,
Op.getValueType(),
1560 Op.getOperand(0), CondV,
Op.getOperand(2));
1564 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1570LoongArchTargetLowering::lowerSCALAR_TO_VECTOR(
SDValue Op,
1573 MVT OpVT =
Op.getSimpleValueType();
1576 SDValue Val =
Op.getOperand(0);
1584 EVT ResTy =
Op->getValueType(0);
1585 SDValue Src =
Op->getOperand(0);
1589 if (!Subtarget.is64Bit() && (ResTy == MVT::v16i8 || ResTy == MVT::v32i8))
1599 for (
unsigned int i = 0; i < NewEltNum; i++) {
1602 unsigned RevOp = (ResTy == MVT::v16i8 || ResTy == MVT::v32i8)
1603 ? (
unsigned)LoongArchISD::BITREV_8B
1621 for (
unsigned int i = 0; i < NewEltNum; i++)
1622 for (
int j = OrigEltNum / NewEltNum - 1;
j >= 0;
j--)
1623 Mask.push_back(j + (OrigEltNum / NewEltNum) * i);
1641 if (EltBits > 32 || EltBits == 1)
1669 int MaskOffset,
const APInt &Zeroable) {
1670 int Size = Mask.size();
1671 unsigned SizeInBits =
Size * ScalarSizeInBits;
1673 auto CheckZeros = [&](
int Shift,
int Scale,
bool Left) {
1674 for (
int i = 0; i <
Size; i += Scale)
1675 for (
int j = 0; j < Shift; ++j)
1676 if (!Zeroable[i + j + (
Left ? 0 : (Scale - Shift))])
1684 for (
unsigned i = Pos, e = Pos +
Size; i != e; ++i,
Low += Step)
1685 if (!(Mask[i] == -1 || Mask[i] ==
Low))
1690 auto MatchShift = [&](
int Shift,
int Scale,
bool Left) {
1691 for (
int i = 0; i !=
Size; i += Scale) {
1692 unsigned Pos =
Left ? i + Shift : i;
1693 unsigned Low =
Left ? i : i + Shift;
1694 unsigned Len = Scale - Shift;
1699 int ShiftEltBits = ScalarSizeInBits * Scale;
1700 bool ByteShift = ShiftEltBits > 64;
1701 Opcode =
Left ? (ByteShift ? LoongArchISD::VBSLL : LoongArchISD::VSLLI)
1702 : (ByteShift ? LoongArchISD::VBSRL : LoongArchISD::VSRLI);
1703 int ShiftAmt = Shift * ScalarSizeInBits / (ByteShift ? 8 : 1);
1707 Scale = ByteShift ? Scale / 2 : Scale;
1713 return (
int)ShiftAmt;
1716 unsigned MaxWidth = 128;
1717 for (
int Scale = 2; Scale * ScalarSizeInBits <= MaxWidth; Scale *= 2)
1718 for (
int Shift = 1; Shift != Scale; ++Shift)
1719 for (
bool Left : {
true,
false})
1720 if (CheckZeros(Shift, Scale,
Left)) {
1721 int ShiftAmt = MatchShift(Shift, Scale,
Left);
1746 const APInt &Zeroable) {
1747 int Size = Mask.size();
1761 Mask,
Size, Zeroable);
1769 "Illegal integer vector type");
1778template <
typename ValType>
1781 unsigned CheckStride,
1783 ValType ExpectedIndex,
unsigned ExpectedIndexStride) {
1787 if (*
I != -1 && *
I != ExpectedIndex)
1789 ExpectedIndex += ExpectedIndexStride;
1793 for (
unsigned n = 0; n < CheckStride &&
I !=
End; ++n, ++
I)
1805 int Size = Mask.size();
1814 int VectorSizeInBits =
V1.getValueSizeInBits();
1815 int ScalarSizeInBits = VectorSizeInBits /
Size;
1816 assert(!(VectorSizeInBits % ScalarSizeInBits) &&
"Illegal shuffle mask size");
1817 (void)ScalarSizeInBits;
1819 for (
int i = 0; i <
Size; ++i) {
1825 if ((M >= 0 && M <
Size && V1IsZero) || (M >=
Size && V2IsZero)) {
1842 RepeatedMask.
assign(LaneSize, -1);
1843 int Size = Mask.size();
1844 for (
int i = 0; i <
Size; ++i) {
1845 assert(Mask[i] == -1 || Mask[i] >= 0);
1848 if ((Mask[i] %
Size) / LaneSize != i / LaneSize)
1855 Mask[i] <
Size ? Mask[i] % LaneSize : Mask[i] % LaneSize + LaneSize;
1856 if (RepeatedMask[i % LaneSize] < 0)
1858 RepeatedMask[i % LaneSize] = LocalM;
1859 else if (RepeatedMask[i % LaneSize] != LocalM)
1876 int NumElts = RepeatedMask.
size();
1878 int Scale = 16 / NumElts;
1880 for (
int i = 0; i < NumElts; ++i) {
1881 int M = RepeatedMask[i];
1882 assert((M == -1 || (0 <= M && M < (2 * NumElts))) &&
1883 "Unexpected mask index.");
1888 int StartIdx = i - (M % NumElts);
1895 int CandidateRotation = StartIdx < 0 ? -StartIdx : NumElts - StartIdx;
1898 Rotation = CandidateRotation;
1899 else if (Rotation != CandidateRotation)
1914 else if (TargetV != MaskV)
1919 assert(Rotation != 0 &&
"Failed to locate a viable rotation!");
1920 assert((
Lo ||
Hi) &&
"Failed to find a rotated input vector!");
1929 return Rotation * Scale;
1948 if (ByteRotation <= 0)
1955 int LoByteShift = 16 - ByteRotation;
1956 int HiByteShift = ByteRotation;
1979 const APInt &Zeroable) {
1993 for (
int i = 0; i < NumElements; i++) {
1997 if (i % Scale != 0) {
2009 M = M % NumElements;
2012 Offset = M - (i / Scale);
2015 if (
Offset % (NumElements / Scale))
2017 }
else if (InputV != V)
2020 if (M != (
Offset + (i / Scale)))
2030 unsigned VilVLoHi = LoongArchISD::VILVL;
2031 if (
Offset >= (NumElements / 2)) {
2032 VilVLoHi = LoongArchISD::VILVH;
2033 Offset -= (NumElements / 2);
2041 InputV = DAG.
getNode(VilVLoHi,
DL, InputVT, Ext, InputV);
2045 }
while (Scale > 1);
2051 for (
int NumExtElements = Bits / 64; NumExtElements < NumElements;
2052 NumExtElements *= 2) {
2072 int SplatIndex = -1;
2073 for (
const auto &M : Mask) {
2080 if (SplatIndex == -1)
2083 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2085 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT,
V1,
2115 unsigned SubVecSize = 4;
2116 if (VT == MVT::v2f64 || VT == MVT::v2i64)
2119 int SubMask[4] = {-1, -1, -1, -1};
2120 for (
unsigned i = 0; i < SubVecSize; ++i) {
2121 for (
unsigned j = i; j < Mask.size(); j += SubVecSize) {
2127 M -= 4 * (j / SubVecSize);
2128 if (M < 0 || M >= 4)
2134 if (SubMask[i] == -1)
2138 else if (M != -1 && M != SubMask[i])
2145 for (
int i = SubVecSize - 1; i >= 0; --i) {
2158 if (VT == MVT::v2f64 || VT == MVT::v2i64)
2159 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT,
V1, V2,
2162 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT,
V1,
2180 if (VT != MVT::v16i8 && VT != MVT::v8i16 && VT != MVT::v32i8 &&
2189 for (
int i = 0; i < WidenNumElts; ++i)
2190 WidenMask[i] = WidenNumElts - 1 - i;
2198 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT,
2222 const auto &Begin = Mask.begin();
2223 const auto &
End = Mask.end();
2240 return DAG.
getNode(LoongArchISD::VPACKEV,
DL, VT, V2,
V1);
2262 const auto &Begin = Mask.begin();
2263 const auto &
End = Mask.end();
2280 return DAG.
getNode(LoongArchISD::VPACKOD,
DL, VT, V2,
V1);
2303 const auto &Begin = Mask.begin();
2304 const auto &
End = Mask.end();
2305 unsigned HalfSize = Mask.size() / 2;
2323 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2,
V1);
2346 const auto &Begin = Mask.begin();
2347 const auto &
End = Mask.end();
2364 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2,
V1);
2386 const auto &Begin = Mask.begin();
2387 const auto &Mid = Mask.begin() + Mask.size() / 2;
2388 const auto &
End = Mask.end();
2406 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2,
V1);
2428 const auto &Begin = Mask.begin();
2429 const auto &Mid = Mask.begin() + Mask.size() / 2;
2430 const auto &
End = Mask.end();
2447 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2,
V1);
2473 if (Mask.size() != NumElts)
2476 auto tryLowerToExtrAndIns = [&](
unsigned Base) ->
SDValue {
2479 for (
unsigned i = 0; i < NumElts; ++i) {
2482 if (Mask[i] !=
int(
Base + i)) {
2495 int DiffMask = Mask[DiffPos];
2496 if (DiffMask < 0 || DiffMask >=
int(2 * NumElts))
2502 if (
unsigned(DiffMask) < NumElts) {
2507 SrcIdx =
unsigned(DiffMask) - NumElts;
2523 if (
SDValue Result = tryLowerToExtrAndIns(0))
2525 return tryLowerToExtrAndIns(NumElts);
2533 unsigned &MaskImm) {
2534 unsigned MaskSize = Mask.size();
2537 return (M == -1) || (M >=
Off && M <
Off + 4);
2540 auto buildImm = [&](
int MLo,
int MHi,
unsigned Off,
unsigned I) {
2541 auto immPart = [&](
int M,
unsigned Off) {
2542 return (M == -1 ? 0 : (M -
Off)) & 0x3;
2544 MaskImm |= immPart(MLo,
Off) << (
I * 2);
2545 MaskImm |= immPart(MHi,
Off) << ((
I + 1) * 2);
2548 for (
unsigned i = 0; i < 4; i += 2) {
2550 int MHi = Mask[i + 1];
2552 if (MaskSize == 8) {
2553 auto isValid2 = [&](
int &M,
int M2) {
2560 if ((M2 % MaskSize) < 4)
2568 if (!isValid2(MLo, Mask[i + 4]) || !isValid2(MHi, Mask[i + 5]))
2574 buildImm(MLo, MHi, 0, i);
2577 buildImm(MLo, MHi, MaskSize, i);
2607 if ((VT != MVT::v4i32 && VT != MVT::v4f32) ||
2612 unsigned MaskImm = 0;
2616 return DAG.
getNode(LoongArchISD::VPERMI,
DL, VT, SrcVec[1], SrcVec[0],
2643 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2,
V1);
2656 "Vector type is unsupported for lsx!");
2658 "Two operands have different types!");
2660 "Unexpected mask size for shuffle!");
2661 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
2663 APInt KnownUndef, KnownZero;
2665 APInt Zeroable = KnownUndef | KnownZero;
2738 int SplatIndex = -1;
2739 for (
const auto &M : Mask) {
2746 if (SplatIndex == -1)
2749 const auto &Begin = Mask.begin();
2750 const auto &
End = Mask.end();
2751 int HalfSize = Mask.size() / 2;
2753 if (SplatIndex >= HalfSize)
2756 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2760 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT,
V1,
2774 if (Mask.size() == 4) {
2775 unsigned MaskImm = 0;
2776 for (
int i = 1; i >= 0; --i) {
2778 int MHi = Mask[i + 2];
2779 if (!(MLo == -1 || (MLo >= 0 && MLo <= 1) || (MLo >= 4 && MLo <= 5)) ||
2780 !(MHi == -1 || (MHi >= 2 && MHi <= 3) || (MHi >= 6 && MHi <= 7)))
2782 if (MHi != -1 && MLo != -1 && MHi != MLo + 2)
2787 MaskImm |= ((MLo <= 1) ? MLo : (MLo - 2)) & 0x3;
2789 MaskImm |= ((MHi <= 3) ? (MHi - 2) : (MHi - 4)) & 0x3;
2792 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT,
V1, V2,
2813 return DAG.
getNode(LoongArchISD::XVREPLVE0,
DL, VT,
V1);
2822 unsigned MaskSize = Mask.size();
2827 if (VT == MVT::v8i32 || VT == MVT::v8f32) {
2829 unsigned MaskImm = 0;
2833 return DAG.
getNode(LoongArchISD::VPERMI,
DL, VT, SrcVec[1], SrcVec[0],
2838 if (VT == MVT::v4i64 || VT == MVT::v4f64) {
2839 unsigned MaskImm = 0;
2840 for (
unsigned i = 0; i < MaskSize; ++i) {
2843 if (Mask[i] >= (
int)MaskSize)
2845 MaskImm |= Mask[i] << (i * 2);
2848 return DAG.
getNode(LoongArchISD::XVPERMI,
DL, VT,
V1,
2860 if (Mask.size() != 8 || (VT != MVT::v8i32 && VT != MVT::v8f32))
2864 unsigned HalfSize = NumElts / 2;
2865 bool FrontLo =
true, FrontHi =
true;
2866 bool BackLo =
true, BackHi =
true;
2868 auto inRange = [](
int val,
int low,
int high) {
2869 return (val == -1) || (val >= low && val < high);
2872 for (
unsigned i = 0; i < HalfSize; ++i) {
2873 int Fronti = Mask[i];
2874 int Backi = Mask[i + HalfSize];
2876 FrontLo &=
inRange(Fronti, 0, HalfSize);
2877 FrontHi &=
inRange(Fronti, HalfSize, NumElts);
2878 BackLo &=
inRange(Backi, 0, HalfSize);
2879 BackHi &=
inRange(Backi, HalfSize, NumElts);
2885 if ((FrontLo || FrontHi) && (BackLo || BackHi))
2890 for (
unsigned i = 0; i < NumElts; ++i)
2895 return DAG.
getNode(LoongArchISD::XVPERM,
DL, VT,
V1, MaskVec);
2917 const auto &Begin = Mask.begin();
2918 const auto &
End = Mask.end();
2919 unsigned HalfSize = Mask.size() / 2;
2920 unsigned LeftSize = HalfSize / 2;
2928 Mask.size() + HalfSize - LeftSize, 1) &&
2930 Mask.size() + HalfSize + LeftSize, 1))
2941 Mask.size() + HalfSize - LeftSize, 1) &&
2943 Mask.size() + HalfSize + LeftSize, 1))
2948 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2,
V1);
2956 const auto &Begin = Mask.begin();
2957 const auto &
End = Mask.end();
2958 unsigned HalfSize = Mask.size() / 2;
2966 Mask.size() + HalfSize, 1))
2977 Mask.size() + HalfSize, 1))
2982 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2,
V1);
2990 const auto &Begin = Mask.begin();
2991 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2992 const auto &Mid = Mask.begin() + Mask.size() / 2;
2993 const auto &RightMid = Mask.end() - Mask.size() / 4;
2994 const auto &
End = Mask.end();
2995 unsigned HalfSize = Mask.size() / 2;
3017 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2,
V1);
3025 const auto &Begin = Mask.begin();
3026 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
3027 const auto &Mid = Mask.begin() + Mask.size() / 2;
3028 const auto &RightMid = Mask.end() - Mask.size() / 4;
3029 const auto &
End = Mask.end();
3030 unsigned HalfSize = Mask.size() / 2;
3053 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2,
V1);
3062 int HalfSize = NumElts / 2;
3066 if ((
int)Mask.size() != NumElts)
3069 auto tryLowerToExtrAndIns = [&](
int Base) ->
SDValue {
3071 for (
int i = 0; i < NumElts; ++i) {
3074 if (Mask[i] !=
Base + i) {
3076 if (DiffPos.
size() > 2)
3084 if (DiffPos.
size() == 1) {
3085 if (DiffPos[0] < HalfSize && Mask[DiffPos[0] + HalfSize] == -1)
3086 DiffPos.
push_back(DiffPos[0] + HalfSize);
3087 else if (DiffPos[0] >= HalfSize && Mask[DiffPos[0] - HalfSize] == -1)
3088 DiffPos.
insert(DiffPos.
begin(), DiffPos[0] - HalfSize);
3092 if (DiffPos.
size() != 2 || DiffPos[1] != DiffPos[0] + HalfSize)
3096 int DiffMaskLo = Mask[DiffPos[0]];
3097 int DiffMaskHi = Mask[DiffPos[1]];
3098 DiffMaskLo = DiffMaskLo == -1 ? DiffMaskHi - HalfSize : DiffMaskLo;
3099 DiffMaskHi = DiffMaskHi == -1 ? DiffMaskLo + HalfSize : DiffMaskHi;
3100 if (!(DiffMaskLo >= 0 && DiffMaskLo < HalfSize) &&
3101 !(DiffMaskLo >= NumElts && DiffMaskLo < NumElts + HalfSize))
3103 if (!(DiffMaskHi >= HalfSize && DiffMaskHi < NumElts) &&
3104 !(DiffMaskHi >= NumElts + HalfSize && DiffMaskHi < 2 * NumElts))
3106 if (DiffMaskHi != DiffMaskLo + HalfSize)
3110 SDValue SrcVec = (DiffMaskLo < HalfSize) ?
V1 : V2;
3112 (DiffMaskLo < HalfSize) ? DiffMaskLo : (DiffMaskLo - NumElts);
3133 if (
SDValue Result = tryLowerToExtrAndIns(0))
3135 return tryLowerToExtrAndIns(NumElts);
3144 if (VT != MVT::v8i32 && VT != MVT::v8f32 && VT != MVT::v4i64 &&
3149 int MaskSize = Mask.size();
3155 auto checkReplaceOne = [&](
int Base,
int Replaced) ->
int {
3157 for (
int i = 0; i < MaskSize; ++i) {
3158 if (Mask[i] ==
Base + i || Mask[i] == -1)
3160 if (Mask[i] != Replaced)
3171 int Idx = checkReplaceOne(0, MaskSize);
3173 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT,
V1, V2,
3177 Idx = checkReplaceOne(MaskSize, 0);
3179 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT, V2,
V1,
3190 int MaskSize = Mask.size();
3191 int HalfSize = Mask.size() / 2;
3192 const auto &Begin = Mask.begin();
3193 const auto &Mid = Mask.begin() + HalfSize;
3194 const auto &
End = Mask.end();
3206 for (
auto it = Begin; it < Mid; it++) {
3209 else if ((*it >= 0 && *it < HalfSize) ||
3210 (*it >= MaskSize && *it < MaskSize + HalfSize)) {
3211 int M = *it < HalfSize ? *it : *it - HalfSize;
3216 assert((
int)MaskAlloc.
size() == HalfSize &&
"xvshuf convert failed!");
3218 for (
auto it = Mid; it <
End; it++) {
3221 else if ((*it >= HalfSize && *it < MaskSize) ||
3222 (*it >= MaskSize + HalfSize && *it < MaskSize * 2)) {
3223 int M = *it < MaskSize ? *it - HalfSize : *it - MaskSize;
3228 assert((
int)MaskAlloc.
size() == MaskSize &&
"xvshuf convert failed!");
3232 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2,
V1);
3260 enum HalfMaskType { HighLaneTy, LowLaneTy,
None };
3262 int MaskSize = Mask.size();
3263 int HalfSize = Mask.size() / 2;
3266 HalfMaskType preMask =
None, postMask =
None;
3268 if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
3269 return M < 0 || (M >= 0 && M < HalfSize) ||
3270 (M >= MaskSize && M < MaskSize + HalfSize);
3272 preMask = HighLaneTy;
3273 else if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
3274 return M < 0 || (M >= HalfSize && M < MaskSize) ||
3275 (M >= MaskSize + HalfSize && M < MaskSize * 2);
3277 preMask = LowLaneTy;
3279 if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
3280 return M < 0 || (M >= HalfSize && M < MaskSize) ||
3281 (M >= MaskSize + HalfSize && M < MaskSize * 2);
3283 postMask = LowLaneTy;
3284 else if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
3285 return M < 0 || (M >= 0 && M < HalfSize) ||
3286 (M >= MaskSize && M < MaskSize + HalfSize);
3288 postMask = HighLaneTy;
3296 if (preMask == HighLaneTy && postMask == LowLaneTy) {
3299 if (preMask == LowLaneTy && postMask == HighLaneTy) {
3307 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3312 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
3313 *it = *it < 0 ? *it : *it - HalfSize;
3315 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
3316 *it = *it < 0 ? *it : *it + HalfSize;
3318 }
else if (preMask == LowLaneTy && postMask == LowLaneTy) {
3326 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3331 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
3332 *it = *it < 0 ? *it : *it - HalfSize;
3334 }
else if (preMask == HighLaneTy && postMask == HighLaneTy) {
3342 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3347 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
3348 *it = *it < 0 ? *it : *it + HalfSize;
3373 int Size = Mask.size();
3374 int LaneSize =
Size / 2;
3376 bool LaneCrossing[2] = {
false,
false};
3377 for (
int i = 0; i <
Size; ++i)
3378 if (Mask[i] >= 0 && ((Mask[i] %
Size) / LaneSize) != (i / LaneSize))
3379 LaneCrossing[(Mask[i] %
Size) / LaneSize] =
true;
3382 if (!LaneCrossing[0] && !LaneCrossing[1])
3386 InLaneMask.
assign(Mask.begin(), Mask.end());
3387 for (
int i = 0; i <
Size; ++i) {
3388 int &M = InLaneMask[i];
3391 if (((M %
Size) / LaneSize) != (i / LaneSize))
3392 M = (M % LaneSize) + ((i / LaneSize) * LaneSize) +
Size;
3397 DAG.
getUNDEF(MVT::v4i64), {2, 3, 0, 1});
3412 "Vector type is unsupported for lasx!");
3414 "Two operands have different types!");
3416 "Unexpected mask size for shuffle!");
3417 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
3418 assert(Mask.size() >= 4 &&
"Mask size is less than 4.");
3420 APInt KnownUndef, KnownZero;
3422 APInt Zeroable = KnownUndef | KnownZero;
3511 ArrayRef<int> OrigMask = SVOp->
getMask();
3512 SDValue
V1 =
Op.getOperand(0);
3513 SDValue V2 =
Op.getOperand(1);
3514 MVT VT =
Op.getSimpleValueType();
3518 bool V1IsUndef =
V1.isUndef();
3519 bool V2IsUndef = V2.
isUndef();
3520 if (V1IsUndef && V2IsUndef)
3533 any_of(OrigMask, [NumElements](
int M) {
return M >= NumElements; })) {
3534 SmallVector<int, 8> NewMask(OrigMask);
3535 for (
int &M : NewMask)
3536 if (M >= NumElements)
3542 int MaskUpperLimit = OrigMask.
size() * (V2IsUndef ? 1 : 2);
3543 (void)MaskUpperLimit;
3545 [&](
int M) {
return -1 <=
M &&
M < MaskUpperLimit; }) &&
3546 "Out of bounds shuffle index");
3564 SDValue Op0 =
Op.getOperand(0);
3565 SDValue Chain = SDValue();
3568 std::tie(Res, Chain) =
3569 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
3570 if (Subtarget.is64Bit())
3571 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3581 SDValue Op0 =
Op.getOperand(0);
3582 SDValue Chain = SDValue();
3583 SDValue Arg = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3587 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
3588 CallOptions,
DL, Chain);
3594 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3600 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
3601 if (Subtarget.is64Bit())
3602 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3608 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3609 MVT VT =
Op.getSimpleValueType();
3614 SDValue Res = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3635 "Unsupported vector type for broadcast.");
3638 bool IsIdeneity =
true;
3640 for (
int i = 0; i !=
NumOps; i++) {
3642 if (
Op.getOpcode() !=
ISD::LOAD || (IdentitySrc &&
Op != IdentitySrc)) {
3654 auto ExtType = LN->getExtensionType();
3659 assert(LN->isUnindexed() &&
"Unexpected indexed load.");
3664 SDValue Ops[] = {LN->getChain(), LN->getBasePtr()};
3682 for (
unsigned i = 1; i <
Ops.size(); ++i) {
3696 EVT ResTy,
unsigned first) {
3699 assert(first + NumElts <= Node->getSimpleValueType(0).getVectorNumElements());
3702 Node->op_begin() + first + NumElts);
3711 MVT VT =
Node->getSimpleValueType(0);
3712 EVT ResTy =
Op->getValueType(0);
3715 APInt SplatValue, SplatUndef;
3716 unsigned SplatBitSize;
3719 bool UseSameConstant =
true;
3720 SDValue ConstantValue;
3724 if ((!Subtarget.hasExtLSX() || !Is128Vec) &&
3725 (!Subtarget.hasExtLASX() || !Is256Vec))
3731 if (
Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
3733 SplatBitSize <= 64) {
3735 if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
3739 if (SplatBitSize == 64 && !Subtarget.is64Bit()) {
3746 if ((Is128Vec && ResTy == MVT::v4i32) ||
3747 (Is256Vec && ResTy == MVT::v8i32))
3753 switch (SplatBitSize) {
3757 ViaVecTy = Is128Vec ? MVT::v16i8 : MVT::v32i8;
3760 ViaVecTy = Is128Vec ? MVT::v8i16 : MVT::v16i16;
3763 ViaVecTy = Is128Vec ? MVT::v4i32 : MVT::v8i32;
3766 ViaVecTy = Is128Vec ? MVT::v2i64 : MVT::v4i64;
3774 if (ViaVecTy != ResTy)
3783 for (
unsigned i = 0; i < NumElts; ++i) {
3784 SDValue Opi =
Node->getOperand(i);
3788 ConstantValue = Opi;
3789 else if (ConstantValue != Opi)
3790 UseSameConstant =
false;
3795 if (IsConstant && UseSameConstant && ResTy != MVT::v2f64) {
3797 for (
unsigned i = 0; i < NumElts; ++i) {
3798 SDValue Opi =
Node->getOperand(i);
3815 BitVector UndefElements;
3816 if (
Node->getRepeatedSequence(Sequence, &UndefElements) &&
3817 UndefElements.
count() == 0) {
3821 EVT FillTy = Is256Vec
3827 fillVector(Sequence, DAG,
DL, Subtarget, FillVec, FillTy);
3830 unsigned SplatLen = NumElts / SeqLen;
3836 if (SplatEltTy == MVT::i128)
3837 SplatTy = MVT::v4i64;
3845 DAG.
getNode((SplatEltTy == MVT::i128) ? LoongArchISD::XVREPLVE0Q
3846 : LoongArchISD::XVREPLVE0,
3847 DL, SplatTy, SrcVec);
3849 SplatVec = DAG.
getNode(LoongArchISD::VREPLVEI,
DL, SplatTy, SrcVec,
3862 if (ResTy == MVT::v8i32 || ResTy == MVT::v8f32 || ResTy == MVT::v4i64 ||
3863 ResTy == MVT::v4f64) {
3864 unsigned NonUndefCount = 0;
3865 for (
unsigned i = NumElts / 2; i < NumElts; ++i) {
3866 if (!
Node->getOperand(i).isUndef()) {
3868 if (NonUndefCount > 1)
3872 if (NonUndefCount == 1)
3885 VecTy, NumElts / 2);
3896 MVT ResVT =
Op.getSimpleValueType();
3904 unsigned NumFreezeUndef = 0;
3905 unsigned NumZero = 0;
3906 unsigned NumNonZero = 0;
3907 unsigned NonZeros = 0;
3908 SmallSet<SDValue, 4> Undefs;
3909 for (
unsigned i = 0; i != NumOperands; ++i) {
3910 SDValue SubVec =
Op.getOperand(i);
3924 assert(i <
sizeof(NonZeros) * CHAR_BIT);
3931 if (NumNonZero > 2) {
3935 Ops.slice(0, NumOperands / 2));
3937 Ops.slice(NumOperands / 2));
3947 for (SDValue U : Undefs)
3950 MVT SubVT =
Op.getOperand(0).getSimpleValueType();
3952 for (
unsigned i = 0; i != NumOperands; ++i) {
3953 if ((NonZeros & (1 << i)) == 0)
3964LoongArchTargetLowering::lowerEXTRACT_VECTOR_ELT(
SDValue Op,
3966 MVT EltVT =
Op.getSimpleValueType();
3967 SDValue Vec =
Op->getOperand(0);
3969 SDValue
Idx =
Op->getOperand(1);
3971 MVT GRLenVT = Subtarget.getGRLenVT();
3999 ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Idx)
4003 DAG.
getBitcast((VecTy == MVT::v4f64) ? MVT::v4i64 : VecTy, IdxVec);
4005 DAG.
getNode(LoongArchISD::VSHUF,
DL, VecTy, MaskVec, TmpVec, Vec);
4013 SDValue SplatValue =
4014 DAG.
getNode(LoongArchISD::XVPERM,
DL, VecTy, Vec, SplatIdx);
4023LoongArchTargetLowering::lowerINSERT_VECTOR_ELT(
SDValue Op,
4025 MVT VT =
Op.getSimpleValueType();
4030 SDValue Op0 =
Op.getOperand(0);
4031 SDValue Op1 =
Op.getOperand(1);
4032 SDValue Op2 =
Op.getOperand(2);
4048 if (!Subtarget.is64Bit() && IdxTy == MVT::i64) {
4050 for (
unsigned i = 0; i < NumElts; ++i) {
4058 for (
unsigned i = 0; i < NumElts; ++i) {
4067 for (
unsigned i = 0; i < NumElts; ++i)
4120 MVT GRLenVT = Subtarget.getGRLenVT();
4122 SDValue Chain =
Op.getOperand(0);
4123 SDValue RMValue =
Op.getOperand(1);
4132 "rounding mode is not supported by LoongArch hardware",
4133 DiagnosticLocation(
DL.getDebugLoc()),
DS_Error));
4150 FCSRNo, RMValue, Chain);
4151 return SDValue(RN, 0);
4156 MVT GRLenVT = Subtarget.getGRLenVT();
4158 SDValue Chain =
Op->getOperand(0);
4163 MVT::Other, FCSRNo, Chain);
4164 SDValue RMValue = SDValue(FCSR, 0);
4165 Chain = SDValue(FCSR, 1);
4179 if (Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i32) {
4181 "On LA64, only 64-bit registers can be written.");
4182 return Op.getOperand(0);
4185 if (!Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i64) {
4187 "On LA32, only 32-bit registers can be written.");
4188 return Op.getOperand(0);
4198 "be a constant integer");
4204 Register FrameReg = Subtarget.getRegisterInfo()->getFrameRegister(MF);
4205 EVT VT =
Op.getValueType();
4208 unsigned Depth =
Op.getConstantOperandVal(0);
4209 int GRLenInBytes = Subtarget.getGRLen() / 8;
4212 int Offset = -(GRLenInBytes * 2);
4224 if (
Op.getConstantOperandVal(0) != 0) {
4226 "return address can only be determined for the current frame");
4232 MVT GRLenVT = Subtarget.getGRLenVT();
4244 auto Size = Subtarget.getGRLen() / 8;
4252 auto *FuncInfo = MF.
getInfo<LoongArchMachineFunctionInfo>();
4255 SDValue FI = DAG.
getFrameIndex(FuncInfo->getVarArgsFrameIndex(),
4262 MachinePointerInfo(SV));
4268 SDValue Op0 =
Op.getOperand(0);
4269 EVT VT =
Op.getValueType();
4284 if (Subtarget.hasExtLSX() && Op0VT == MVT::i64 && VT == MVT::f64) {
4292 if (!Subtarget.is64Bit() || !Subtarget.hasBasicF() || Subtarget.hasBasicD())
4295 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
4296 !Subtarget.hasBasicD() &&
"unexpected target features");
4300 if (
C &&
C->getZExtValue() < UINT64_C(0xFFFFFFFF))
4304 if (Op0->
getOpcode() == LoongArchISD::BSTRPICK &&
4314 EVT RetVT =
Op.getValueType();
4318 SDValue Chain = SDValue();
4320 std::tie(Result, Chain) =
4327 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
4328 !Subtarget.hasBasicD() &&
"unexpected target features");
4331 SDValue Op0 =
Op.getOperand(0);
4339 EVT RetVT =
Op.getValueType();
4343 SDValue Chain = SDValue();
4345 std::tie(Result, Chain) =
4354 EVT VT =
Op.getValueType();
4355 SDValue Op0 =
Op.getOperand(0);
4358 if (
Op.getValueType() == MVT::f32 && Op0VT == MVT::i32 &&
4359 Subtarget.is64Bit() && Subtarget.hasBasicF()) {
4361 return DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, NewOp0);
4363 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit()) {
4366 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
4375 SDValue Op0 =
Op.getOperand(0);
4380 if (
Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() &&
4381 !Subtarget.hasBasicD()) {
4382 SDValue Dst = DAG.
getNode(LoongArchISD::FTINT,
DL, MVT::f32, Op0);
4383 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Dst);
4387 SDValue Trunc = DAG.
getNode(LoongArchISD::FTINT,
DL, FPTy, Op0);
4397 SDValue Src =
Op.getOperand(0);
4398 EVT VT =
Op.getValueType();
4399 EVT SrcVT = Src.getValueType();
4400 unsigned SatWidth =
cast<VTSDNode>(
Op.getOperand(1))->getVT().getSizeInBits();
4410 if (SrcVT != MVT::f32 && SrcVT != MVT::f64)
4413 if (SatWidth == 32) {
4414 SDValue Ftint = DAG.
getNode(LoongArchISD::FTINT,
DL, MVT::f32, Src);
4415 if (Subtarget.is64Bit())
4416 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, VT, Ftint);
4420 if (SatWidth == 64 && Subtarget.is64Bit() && Subtarget.hasBasicD()) {
4421 SDValue Ftint = DAG.
getNode(LoongArchISD::FTINT,
DL, MVT::f64, Src);
4430 if (!Subtarget.hasExtLSX())
4434 SDValue Src =
Op.getOperand(0);
4435 EVT VT =
Op.getValueType();
4436 EVT SrcVT = Src.getValueType();
4441 if (SrcVT != MVT::f32 && SrcVT != MVT::f64)
4444 if (SrcVT == MVT::f32)
4466 N->getOffset(), Flags);
4474template <
class NodeTy>
4477 bool IsLocal)
const {
4488 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
4569 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
4571 const GlobalValue *GV =
N->getGlobal();
4583 unsigned Opc,
bool UseGOT,
4587 MVT GRLenVT = Subtarget.getGRLenVT();
4595 SDValue
Offset =
Opc == LoongArch::PseudoLA_TLS_IE_LARGE
4597 : SDValue(DAG.getMachineNode(
Opc,
DL, Ty, Addr), 0);
4601 if (
Opc == LoongArch::PseudoLA_TLS_LE && !Large)
4635 : SDValue(DAG.getMachineNode(
Opc,
DL, Ty, Addr), 0);
4642 TargetLowering::CallLoweringInfo CLI(DAG);
4657 const GlobalValue *GV =
N->getGlobal();
4667 : SDValue(DAG.getMachineNode(
Opc,
DL, Ty, Addr), 0);
4671LoongArchTargetLowering::lowerGlobalTLSAddress(
SDValue Op,
4678 assert((!Large || Subtarget.is64Bit()) &&
"Large code model requires LA64");
4681 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
4694 return getDynamicTLSAddr(
N, DAG,
4695 Large ? LoongArch::PseudoLA_TLS_GD_LARGE
4696 : LoongArch::PseudoLA_TLS_GD,
4703 return getDynamicTLSAddr(
N, DAG,
4704 Large ? LoongArch::PseudoLA_TLS_LD_LARGE
4705 : LoongArch::PseudoLA_TLS_LD,
4710 return getStaticTLSAddr(
N, DAG,
4711 Large ? LoongArch::PseudoLA_TLS_IE_LARGE
4712 : LoongArch::PseudoLA_TLS_IE,
4719 return getStaticTLSAddr(
N, DAG, LoongArch::PseudoLA_TLS_LE,
4723 return getTLSDescAddr(
N, DAG,
4724 Large ? LoongArch::PseudoLA_TLS_DESC_LARGE
4725 : LoongArch::PseudoLA_TLS_DESC,
4729template <
unsigned N>
4734 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
4735 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
4737 ": argument out of range.");
4744LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(
SDValue Op,
4746 switch (
Op.getConstantOperandVal(0)) {
4749 case Intrinsic::thread_pointer: {
4753 case Intrinsic::loongarch_lsx_vpickve2gr_d:
4754 case Intrinsic::loongarch_lsx_vpickve2gr_du:
4755 case Intrinsic::loongarch_lsx_vreplvei_d:
4756 case Intrinsic::loongarch_lasx_xvrepl128vei_d:
4758 case Intrinsic::loongarch_lsx_vreplvei_w:
4759 case Intrinsic::loongarch_lasx_xvrepl128vei_w:
4760 case Intrinsic::loongarch_lasx_xvpickve2gr_d:
4761 case Intrinsic::loongarch_lasx_xvpickve2gr_du:
4762 case Intrinsic::loongarch_lasx_xvpickve_d:
4763 case Intrinsic::loongarch_lasx_xvpickve_d_f:
4765 case Intrinsic::loongarch_lasx_xvinsve0_d:
4767 case Intrinsic::loongarch_lsx_vsat_b:
4768 case Intrinsic::loongarch_lsx_vsat_bu:
4769 case Intrinsic::loongarch_lsx_vrotri_b:
4770 case Intrinsic::loongarch_lsx_vsllwil_h_b:
4771 case Intrinsic::loongarch_lsx_vsllwil_hu_bu:
4772 case Intrinsic::loongarch_lsx_vsrlri_b:
4773 case Intrinsic::loongarch_lsx_vsrari_b:
4774 case Intrinsic::loongarch_lsx_vreplvei_h:
4775 case Intrinsic::loongarch_lasx_xvsat_b:
4776 case Intrinsic::loongarch_lasx_xvsat_bu:
4777 case Intrinsic::loongarch_lasx_xvrotri_b:
4778 case Intrinsic::loongarch_lasx_xvsllwil_h_b:
4779 case Intrinsic::loongarch_lasx_xvsllwil_hu_bu:
4780 case Intrinsic::loongarch_lasx_xvsrlri_b:
4781 case Intrinsic::loongarch_lasx_xvsrari_b:
4782 case Intrinsic::loongarch_lasx_xvrepl128vei_h:
4783 case Intrinsic::loongarch_lasx_xvpickve_w:
4784 case Intrinsic::loongarch_lasx_xvpickve_w_f:
4786 case Intrinsic::loongarch_lasx_xvinsve0_w:
4788 case Intrinsic::loongarch_lsx_vsat_h:
4789 case Intrinsic::loongarch_lsx_vsat_hu:
4790 case Intrinsic::loongarch_lsx_vrotri_h:
4791 case Intrinsic::loongarch_lsx_vsllwil_w_h:
4792 case Intrinsic::loongarch_lsx_vsllwil_wu_hu:
4793 case Intrinsic::loongarch_lsx_vsrlri_h:
4794 case Intrinsic::loongarch_lsx_vsrari_h:
4795 case Intrinsic::loongarch_lsx_vreplvei_b:
4796 case Intrinsic::loongarch_lasx_xvsat_h:
4797 case Intrinsic::loongarch_lasx_xvsat_hu:
4798 case Intrinsic::loongarch_lasx_xvrotri_h:
4799 case Intrinsic::loongarch_lasx_xvsllwil_w_h:
4800 case Intrinsic::loongarch_lasx_xvsllwil_wu_hu:
4801 case Intrinsic::loongarch_lasx_xvsrlri_h:
4802 case Intrinsic::loongarch_lasx_xvsrari_h:
4803 case Intrinsic::loongarch_lasx_xvrepl128vei_b:
4805 case Intrinsic::loongarch_lsx_vsrlni_b_h:
4806 case Intrinsic::loongarch_lsx_vsrani_b_h:
4807 case Intrinsic::loongarch_lsx_vsrlrni_b_h:
4808 case Intrinsic::loongarch_lsx_vsrarni_b_h:
4809 case Intrinsic::loongarch_lsx_vssrlni_b_h:
4810 case Intrinsic::loongarch_lsx_vssrani_b_h:
4811 case Intrinsic::loongarch_lsx_vssrlni_bu_h:
4812 case Intrinsic::loongarch_lsx_vssrani_bu_h:
4813 case Intrinsic::loongarch_lsx_vssrlrni_b_h:
4814 case Intrinsic::loongarch_lsx_vssrarni_b_h:
4815 case Intrinsic::loongarch_lsx_vssrlrni_bu_h:
4816 case Intrinsic::loongarch_lsx_vssrarni_bu_h:
4817 case Intrinsic::loongarch_lasx_xvsrlni_b_h:
4818 case Intrinsic::loongarch_lasx_xvsrani_b_h:
4819 case Intrinsic::loongarch_lasx_xvsrlrni_b_h:
4820 case Intrinsic::loongarch_lasx_xvsrarni_b_h:
4821 case Intrinsic::loongarch_lasx_xvssrlni_b_h:
4822 case Intrinsic::loongarch_lasx_xvssrani_b_h:
4823 case Intrinsic::loongarch_lasx_xvssrlni_bu_h:
4824 case Intrinsic::loongarch_lasx_xvssrani_bu_h:
4825 case Intrinsic::loongarch_lasx_xvssrlrni_b_h:
4826 case Intrinsic::loongarch_lasx_xvssrarni_b_h:
4827 case Intrinsic::loongarch_lasx_xvssrlrni_bu_h:
4828 case Intrinsic::loongarch_lasx_xvssrarni_bu_h:
4830 case Intrinsic::loongarch_lsx_vsat_w:
4831 case Intrinsic::loongarch_lsx_vsat_wu:
4832 case Intrinsic::loongarch_lsx_vrotri_w:
4833 case Intrinsic::loongarch_lsx_vsllwil_d_w:
4834 case Intrinsic::loongarch_lsx_vsllwil_du_wu:
4835 case Intrinsic::loongarch_lsx_vsrlri_w:
4836 case Intrinsic::loongarch_lsx_vsrari_w:
4837 case Intrinsic::loongarch_lsx_vslei_bu:
4838 case Intrinsic::loongarch_lsx_vslei_hu:
4839 case Intrinsic::loongarch_lsx_vslei_wu:
4840 case Intrinsic::loongarch_lsx_vslei_du:
4841 case Intrinsic::loongarch_lsx_vslti_bu:
4842 case Intrinsic::loongarch_lsx_vslti_hu:
4843 case Intrinsic::loongarch_lsx_vslti_wu:
4844 case Intrinsic::loongarch_lsx_vslti_du:
4845 case Intrinsic::loongarch_lsx_vbsll_v:
4846 case Intrinsic::loongarch_lsx_vbsrl_v:
4847 case Intrinsic::loongarch_lasx_xvsat_w:
4848 case Intrinsic::loongarch_lasx_xvsat_wu:
4849 case Intrinsic::loongarch_lasx_xvrotri_w:
4850 case Intrinsic::loongarch_lasx_xvsllwil_d_w:
4851 case Intrinsic::loongarch_lasx_xvsllwil_du_wu:
4852 case Intrinsic::loongarch_lasx_xvsrlri_w:
4853 case Intrinsic::loongarch_lasx_xvsrari_w:
4854 case Intrinsic::loongarch_lasx_xvslei_bu:
4855 case Intrinsic::loongarch_lasx_xvslei_hu:
4856 case Intrinsic::loongarch_lasx_xvslei_wu:
4857 case Intrinsic::loongarch_lasx_xvslei_du:
4858 case Intrinsic::loongarch_lasx_xvslti_bu:
4859 case Intrinsic::loongarch_lasx_xvslti_hu:
4860 case Intrinsic::loongarch_lasx_xvslti_wu:
4861 case Intrinsic::loongarch_lasx_xvslti_du:
4862 case Intrinsic::loongarch_lasx_xvbsll_v:
4863 case Intrinsic::loongarch_lasx_xvbsrl_v:
4865 case Intrinsic::loongarch_lsx_vseqi_b:
4866 case Intrinsic::loongarch_lsx_vseqi_h:
4867 case Intrinsic::loongarch_lsx_vseqi_w:
4868 case Intrinsic::loongarch_lsx_vseqi_d:
4869 case Intrinsic::loongarch_lsx_vslei_b:
4870 case Intrinsic::loongarch_lsx_vslei_h:
4871 case Intrinsic::loongarch_lsx_vslei_w:
4872 case Intrinsic::loongarch_lsx_vslei_d:
4873 case Intrinsic::loongarch_lsx_vslti_b:
4874 case Intrinsic::loongarch_lsx_vslti_h:
4875 case Intrinsic::loongarch_lsx_vslti_w:
4876 case Intrinsic::loongarch_lsx_vslti_d:
4877 case Intrinsic::loongarch_lasx_xvseqi_b:
4878 case Intrinsic::loongarch_lasx_xvseqi_h:
4879 case Intrinsic::loongarch_lasx_xvseqi_w:
4880 case Intrinsic::loongarch_lasx_xvseqi_d:
4881 case Intrinsic::loongarch_lasx_xvslei_b:
4882 case Intrinsic::loongarch_lasx_xvslei_h:
4883 case Intrinsic::loongarch_lasx_xvslei_w:
4884 case Intrinsic::loongarch_lasx_xvslei_d:
4885 case Intrinsic::loongarch_lasx_xvslti_b:
4886 case Intrinsic::loongarch_lasx_xvslti_h:
4887 case Intrinsic::loongarch_lasx_xvslti_w:
4888 case Intrinsic::loongarch_lasx_xvslti_d:
4890 case Intrinsic::loongarch_lsx_vsrlni_h_w:
4891 case Intrinsic::loongarch_lsx_vsrani_h_w:
4892 case Intrinsic::loongarch_lsx_vsrlrni_h_w:
4893 case Intrinsic::loongarch_lsx_vsrarni_h_w:
4894 case Intrinsic::loongarch_lsx_vssrlni_h_w:
4895 case Intrinsic::loongarch_lsx_vssrani_h_w:
4896 case Intrinsic::loongarch_lsx_vssrlni_hu_w:
4897 case Intrinsic::loongarch_lsx_vssrani_hu_w:
4898 case Intrinsic::loongarch_lsx_vssrlrni_h_w:
4899 case Intrinsic::loongarch_lsx_vssrarni_h_w:
4900 case Intrinsic::loongarch_lsx_vssrlrni_hu_w:
4901 case Intrinsic::loongarch_lsx_vssrarni_hu_w:
4902 case Intrinsic::loongarch_lsx_vfrstpi_b:
4903 case Intrinsic::loongarch_lsx_vfrstpi_h:
4904 case Intrinsic::loongarch_lasx_xvsrlni_h_w:
4905 case Intrinsic::loongarch_lasx_xvsrani_h_w:
4906 case Intrinsic::loongarch_lasx_xvsrlrni_h_w:
4907 case Intrinsic::loongarch_lasx_xvsrarni_h_w:
4908 case Intrinsic::loongarch_lasx_xvssrlni_h_w:
4909 case Intrinsic::loongarch_lasx_xvssrani_h_w:
4910 case Intrinsic::loongarch_lasx_xvssrlni_hu_w:
4911 case Intrinsic::loongarch_lasx_xvssrani_hu_w:
4912 case Intrinsic::loongarch_lasx_xvssrlrni_h_w:
4913 case Intrinsic::loongarch_lasx_xvssrarni_h_w:
4914 case Intrinsic::loongarch_lasx_xvssrlrni_hu_w:
4915 case Intrinsic::loongarch_lasx_xvssrarni_hu_w:
4916 case Intrinsic::loongarch_lasx_xvfrstpi_b:
4917 case Intrinsic::loongarch_lasx_xvfrstpi_h:
4919 case Intrinsic::loongarch_lsx_vsat_d:
4920 case Intrinsic::loongarch_lsx_vsat_du:
4921 case Intrinsic::loongarch_lsx_vrotri_d:
4922 case Intrinsic::loongarch_lsx_vsrlri_d:
4923 case Intrinsic::loongarch_lsx_vsrari_d:
4924 case Intrinsic::loongarch_lasx_xvsat_d:
4925 case Intrinsic::loongarch_lasx_xvsat_du:
4926 case Intrinsic::loongarch_lasx_xvrotri_d:
4927 case Intrinsic::loongarch_lasx_xvsrlri_d:
4928 case Intrinsic::loongarch_lasx_xvsrari_d:
4930 case Intrinsic::loongarch_lsx_vsrlni_w_d:
4931 case Intrinsic::loongarch_lsx_vsrani_w_d:
4932 case Intrinsic::loongarch_lsx_vsrlrni_w_d:
4933 case Intrinsic::loongarch_lsx_vsrarni_w_d:
4934 case Intrinsic::loongarch_lsx_vssrlni_w_d:
4935 case Intrinsic::loongarch_lsx_vssrani_w_d:
4936 case Intrinsic::loongarch_lsx_vssrlni_wu_d:
4937 case Intrinsic::loongarch_lsx_vssrani_wu_d:
4938 case Intrinsic::loongarch_lsx_vssrlrni_w_d:
4939 case Intrinsic::loongarch_lsx_vssrarni_w_d:
4940 case Intrinsic::loongarch_lsx_vssrlrni_wu_d:
4941 case Intrinsic::loongarch_lsx_vssrarni_wu_d:
4942 case Intrinsic::loongarch_lasx_xvsrlni_w_d:
4943 case Intrinsic::loongarch_lasx_xvsrani_w_d:
4944 case Intrinsic::loongarch_lasx_xvsrlrni_w_d:
4945 case Intrinsic::loongarch_lasx_xvsrarni_w_d:
4946 case Intrinsic::loongarch_lasx_xvssrlni_w_d:
4947 case Intrinsic::loongarch_lasx_xvssrani_w_d:
4948 case Intrinsic::loongarch_lasx_xvssrlni_wu_d:
4949 case Intrinsic::loongarch_lasx_xvssrani_wu_d:
4950 case Intrinsic::loongarch_lasx_xvssrlrni_w_d:
4951 case Intrinsic::loongarch_lasx_xvssrarni_w_d:
4952 case Intrinsic::loongarch_lasx_xvssrlrni_wu_d:
4953 case Intrinsic::loongarch_lasx_xvssrarni_wu_d:
4955 case Intrinsic::loongarch_lsx_vsrlni_d_q:
4956 case Intrinsic::loongarch_lsx_vsrani_d_q:
4957 case Intrinsic::loongarch_lsx_vsrlrni_d_q:
4958 case Intrinsic::loongarch_lsx_vsrarni_d_q:
4959 case Intrinsic::loongarch_lsx_vssrlni_d_q:
4960 case Intrinsic::loongarch_lsx_vssrani_d_q:
4961 case Intrinsic::loongarch_lsx_vssrlni_du_q:
4962 case Intrinsic::loongarch_lsx_vssrani_du_q:
4963 case Intrinsic::loongarch_lsx_vssrlrni_d_q:
4964 case Intrinsic::loongarch_lsx_vssrarni_d_q:
4965 case Intrinsic::loongarch_lsx_vssrlrni_du_q:
4966 case Intrinsic::loongarch_lsx_vssrarni_du_q:
4967 case Intrinsic::loongarch_lasx_xvsrlni_d_q:
4968 case Intrinsic::loongarch_lasx_xvsrani_d_q:
4969 case Intrinsic::loongarch_lasx_xvsrlrni_d_q:
4970 case Intrinsic::loongarch_lasx_xvsrarni_d_q:
4971 case Intrinsic::loongarch_lasx_xvssrlni_d_q:
4972 case Intrinsic::loongarch_lasx_xvssrani_d_q:
4973 case Intrinsic::loongarch_lasx_xvssrlni_du_q:
4974 case Intrinsic::loongarch_lasx_xvssrani_du_q:
4975 case Intrinsic::loongarch_lasx_xvssrlrni_d_q:
4976 case Intrinsic::loongarch_lasx_xvssrarni_d_q:
4977 case Intrinsic::loongarch_lasx_xvssrlrni_du_q:
4978 case Intrinsic::loongarch_lasx_xvssrarni_du_q:
4980 case Intrinsic::loongarch_lsx_vnori_b:
4981 case Intrinsic::loongarch_lsx_vshuf4i_b:
4982 case Intrinsic::loongarch_lsx_vshuf4i_h:
4983 case Intrinsic::loongarch_lsx_vshuf4i_w:
4984 case Intrinsic::loongarch_lasx_xvnori_b:
4985 case Intrinsic::loongarch_lasx_xvshuf4i_b:
4986 case Intrinsic::loongarch_lasx_xvshuf4i_h:
4987 case Intrinsic::loongarch_lasx_xvshuf4i_w:
4988 case Intrinsic::loongarch_lasx_xvpermi_d:
4990 case Intrinsic::loongarch_lsx_vshuf4i_d:
4991 case Intrinsic::loongarch_lsx_vpermi_w:
4992 case Intrinsic::loongarch_lsx_vbitseli_b:
4993 case Intrinsic::loongarch_lsx_vextrins_b:
4994 case Intrinsic::loongarch_lsx_vextrins_h:
4995 case Intrinsic::loongarch_lsx_vextrins_w:
4996 case Intrinsic::loongarch_lsx_vextrins_d:
4997 case Intrinsic::loongarch_lasx_xvshuf4i_d:
4998 case Intrinsic::loongarch_lasx_xvpermi_w:
4999 case Intrinsic::loongarch_lasx_xvpermi_q:
5000 case Intrinsic::loongarch_lasx_xvbitseli_b:
5001 case Intrinsic::loongarch_lasx_xvextrins_b:
5002 case Intrinsic::loongarch_lasx_xvextrins_h:
5003 case Intrinsic::loongarch_lasx_xvextrins_w:
5004 case Intrinsic::loongarch_lasx_xvextrins_d:
5006 case Intrinsic::loongarch_lsx_vrepli_b:
5007 case Intrinsic::loongarch_lsx_vrepli_h:
5008 case Intrinsic::loongarch_lsx_vrepli_w:
5009 case Intrinsic::loongarch_lsx_vrepli_d:
5010 case Intrinsic::loongarch_lasx_xvrepli_b:
5011 case Intrinsic::loongarch_lasx_xvrepli_h:
5012 case Intrinsic::loongarch_lasx_xvrepli_w:
5013 case Intrinsic::loongarch_lasx_xvrepli_d:
5015 case Intrinsic::loongarch_lsx_vldi:
5016 case Intrinsic::loongarch_lasx_xvldi:
5032LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(
SDValue Op,
5035 MVT GRLenVT = Subtarget.getGRLenVT();
5036 EVT VT =
Op.getValueType();
5037 SDValue Chain =
Op.getOperand(0);
5038 const StringRef ErrorMsgOOR =
"argument out of range";
5039 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
5040 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
5042 switch (
Op.getConstantOperandVal(1)) {
5045 case Intrinsic::loongarch_crc_w_b_w:
5046 case Intrinsic::loongarch_crc_w_h_w:
5047 case Intrinsic::loongarch_crc_w_w_w:
5048 case Intrinsic::loongarch_crc_w_d_w:
5049 case Intrinsic::loongarch_crcc_w_b_w:
5050 case Intrinsic::loongarch_crcc_w_h_w:
5051 case Intrinsic::loongarch_crcc_w_w_w:
5052 case Intrinsic::loongarch_crcc_w_d_w:
5054 case Intrinsic::loongarch_csrrd_w:
5055 case Intrinsic::loongarch_csrrd_d: {
5056 unsigned Imm =
Op.getConstantOperandVal(2);
5059 : DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
5062 case Intrinsic::loongarch_csrwr_w:
5063 case Intrinsic::loongarch_csrwr_d: {
5064 unsigned Imm =
Op.getConstantOperandVal(3);
5067 : DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
5068 {Chain,
Op.getOperand(2),
5071 case Intrinsic::loongarch_csrxchg_w:
5072 case Intrinsic::loongarch_csrxchg_d: {
5073 unsigned Imm =
Op.getConstantOperandVal(4);
5076 : DAG.
getNode(LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
5077 {Chain,
Op.getOperand(2),
Op.getOperand(3),
5080 case Intrinsic::loongarch_iocsrrd_d: {
5082 LoongArchISD::IOCSRRD_D,
DL, {GRLenVT, MVT::Other},
5085#define IOCSRRD_CASE(NAME, NODE) \
5086 case Intrinsic::loongarch_##NAME: { \
5087 return DAG.getNode(LoongArchISD::NODE, DL, {GRLenVT, MVT::Other}, \
5088 {Chain, Op.getOperand(2)}); \
5094 case Intrinsic::loongarch_cpucfg: {
5095 return DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
5096 {Chain,
Op.getOperand(2)});
5098 case Intrinsic::loongarch_lddir_d: {
5099 unsigned Imm =
Op.getConstantOperandVal(3);
5104 case Intrinsic::loongarch_movfcsr2gr: {
5105 if (!Subtarget.hasBasicF())
5107 unsigned Imm =
Op.getConstantOperandVal(2);
5110 : DAG.
getNode(LoongArchISD::MOVFCSR2GR,
DL, {VT, MVT::Other},
5113 case Intrinsic::loongarch_lsx_vld:
5114 case Intrinsic::loongarch_lsx_vldrepl_b:
5115 case Intrinsic::loongarch_lasx_xvld:
5116 case Intrinsic::loongarch_lasx_xvldrepl_b:
5120 case Intrinsic::loongarch_lsx_vldrepl_h:
5121 case Intrinsic::loongarch_lasx_xvldrepl_h:
5125 Op,
"argument out of range or not a multiple of 2", DAG)
5127 case Intrinsic::loongarch_lsx_vldrepl_w:
5128 case Intrinsic::loongarch_lasx_xvldrepl_w:
5132 Op,
"argument out of range or not a multiple of 4", DAG)
5134 case Intrinsic::loongarch_lsx_vldrepl_d:
5135 case Intrinsic::loongarch_lasx_xvldrepl_d:
5139 Op,
"argument out of range or not a multiple of 8", DAG)
5150 return Op.getOperand(0);
5156 MVT GRLenVT = Subtarget.getGRLenVT();
5157 SDValue Chain =
Op.getOperand(0);
5158 uint64_t IntrinsicEnum =
Op.getConstantOperandVal(1);
5159 SDValue Op2 =
Op.getOperand(2);
5160 const StringRef ErrorMsgOOR =
"argument out of range";
5161 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
5162 const StringRef ErrorMsgReqLA32 =
"requires loongarch32";
5163 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
5165 switch (IntrinsicEnum) {
5169 case Intrinsic::loongarch_cacop_d:
5170 case Intrinsic::loongarch_cacop_w: {
5171 if (IntrinsicEnum == Intrinsic::loongarch_cacop_d && !Subtarget.is64Bit())
5173 if (IntrinsicEnum == Intrinsic::loongarch_cacop_w && Subtarget.is64Bit())
5182 case Intrinsic::loongarch_dbar: {
5189 case Intrinsic::loongarch_ibar: {
5196 case Intrinsic::loongarch_break: {
5203 case Intrinsic::loongarch_movgr2fcsr: {
5204 if (!Subtarget.hasBasicF())
5214 case Intrinsic::loongarch_syscall: {
5221#define IOCSRWR_CASE(NAME, NODE) \
5222 case Intrinsic::loongarch_##NAME: { \
5223 SDValue Op3 = Op.getOperand(3); \
5224 return Subtarget.is64Bit() \
5225 ? DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, \
5226 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
5227 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op3)) \
5228 : DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, Op2, \
5235 case Intrinsic::loongarch_iocsrwr_d: {
5236 return !Subtarget.is64Bit()
5243#define ASRT_LE_GT_CASE(NAME) \
5244 case Intrinsic::loongarch_##NAME: { \
5245 return !Subtarget.is64Bit() \
5246 ? emitIntrinsicErrorMessage(Op, ErrorMsgReqLA64, DAG) \
5251#undef ASRT_LE_GT_CASE
5252 case Intrinsic::loongarch_ldpte_d: {
5253 unsigned Imm =
Op.getConstantOperandVal(3);
5254 return !Subtarget.is64Bit()
5259 case Intrinsic::loongarch_lsx_vst:
5260 case Intrinsic::loongarch_lasx_xvst:
5264 case Intrinsic::loongarch_lasx_xvstelm_b:
5269 case Intrinsic::loongarch_lsx_vstelm_b:
5274 case Intrinsic::loongarch_lasx_xvstelm_h:
5279 Op,
"argument out of range or not a multiple of 2", DAG)
5281 case Intrinsic::loongarch_lsx_vstelm_h:
5286 Op,
"argument out of range or not a multiple of 2", DAG)
5288 case Intrinsic::loongarch_lasx_xvstelm_w:
5293 Op,
"argument out of range or not a multiple of 4", DAG)
5295 case Intrinsic::loongarch_lsx_vstelm_w:
5300 Op,
"argument out of range or not a multiple of 4", DAG)
5302 case Intrinsic::loongarch_lasx_xvstelm_d:
5307 Op,
"argument out of range or not a multiple of 8", DAG)
5309 case Intrinsic::loongarch_lsx_vstelm_d:
5314 Op,
"argument out of range or not a multiple of 8", DAG)
5322 SDValue
Lo =
Op.getOperand(0);
5323 SDValue
Hi =
Op.getOperand(1);
5324 SDValue Shamt =
Op.getOperand(2);
5325 EVT VT =
Lo.getValueType();
5336 SDValue MinusGRLen =
5338 SDValue GRLenMinus1 = DAG.
getConstant(Subtarget.getGRLen() - 1,
DL, VT);
5344 SDValue ShiftRightLo =
5355 SDValue Parts[2] = {
Lo,
Hi};
5363 SDValue
Lo =
Op.getOperand(0);
5364 SDValue
Hi =
Op.getOperand(1);
5365 SDValue Shamt =
Op.getOperand(2);
5366 EVT VT =
Lo.getValueType();
5388 SDValue MinusGRLen =
5390 SDValue GRLenMinus1 = DAG.
getConstant(Subtarget.getGRLen() - 1,
DL, VT);
5396 SDValue ShiftLeftHi =
5399 SDValue HiTrue = DAG.
getNode(ShiftRightOp,
DL, VT,
Hi, Shamt);
5400 SDValue LoFalse = DAG.
getNode(ShiftRightOp,
DL, VT,
Hi, ShamtMinusGRLen);
5409 SDValue Parts[2] = {
Lo,
Hi};
5420 return LoongArchISD::DIV_W;
5422 return LoongArchISD::DIV_WU;
5424 return LoongArchISD::MOD_W;
5426 return LoongArchISD::MOD_WU;
5428 return LoongArchISD::SLL_W;
5430 return LoongArchISD::SRA_W;
5432 return LoongArchISD::SRL_W;
5435 return LoongArchISD::ROTR_W;
5437 return LoongArchISD::CTZ_W;
5439 return LoongArchISD::CLZ_W;
5458 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
5459 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0);
5463 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
5469 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0, NewOp1);
5496 StringRef ErrorMsg,
bool WithChain =
true) {
5501 Results.push_back(
N->getOperand(0));
5504template <
unsigned N>
5509 const StringRef ErrorMsgOOR =
"argument out of range";
5510 unsigned Imm =
Node->getConstantOperandVal(2);
5544 switch (
N->getConstantOperandVal(0)) {
5547 case Intrinsic::loongarch_lsx_vpickve2gr_b:
5549 LoongArchISD::VPICK_SEXT_ELT);
5551 case Intrinsic::loongarch_lsx_vpickve2gr_h:
5552 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
5554 LoongArchISD::VPICK_SEXT_ELT);
5556 case Intrinsic::loongarch_lsx_vpickve2gr_w:
5558 LoongArchISD::VPICK_SEXT_ELT);
5560 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
5562 LoongArchISD::VPICK_ZEXT_ELT);
5564 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
5565 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
5567 LoongArchISD::VPICK_ZEXT_ELT);
5569 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
5571 LoongArchISD::VPICK_ZEXT_ELT);
5573 case Intrinsic::loongarch_lsx_bz_b:
5574 case Intrinsic::loongarch_lsx_bz_h:
5575 case Intrinsic::loongarch_lsx_bz_w:
5576 case Intrinsic::loongarch_lsx_bz_d:
5577 case Intrinsic::loongarch_lasx_xbz_b:
5578 case Intrinsic::loongarch_lasx_xbz_h:
5579 case Intrinsic::loongarch_lasx_xbz_w:
5580 case Intrinsic::loongarch_lasx_xbz_d:
5582 LoongArchISD::VALL_ZERO);
5584 case Intrinsic::loongarch_lsx_bz_v:
5585 case Intrinsic::loongarch_lasx_xbz_v:
5587 LoongArchISD::VANY_ZERO);
5589 case Intrinsic::loongarch_lsx_bnz_b:
5590 case Intrinsic::loongarch_lsx_bnz_h:
5591 case Intrinsic::loongarch_lsx_bnz_w:
5592 case Intrinsic::loongarch_lsx_bnz_d:
5593 case Intrinsic::loongarch_lasx_xbnz_b:
5594 case Intrinsic::loongarch_lasx_xbnz_h:
5595 case Intrinsic::loongarch_lasx_xbnz_w:
5596 case Intrinsic::loongarch_lasx_xbnz_d:
5598 LoongArchISD::VALL_NONZERO);
5600 case Intrinsic::loongarch_lsx_bnz_v:
5601 case Intrinsic::loongarch_lasx_xbnz_v:
5603 LoongArchISD::VANY_NONZERO);
5611 assert(
N->getValueType(0) == MVT::i128 &&
5612 "AtomicCmpSwap on types less than 128 should be legal");
5616 switch (
MemOp->getMergedOrdering()) {
5620 Opcode = LoongArch::PseudoCmpXchg128Acquire;
5624 Opcode = LoongArch::PseudoCmpXchg128;
5631 auto CmpVal = DAG.
SplitScalar(
N->getOperand(2),
DL, MVT::i64, MVT::i64);
5632 auto NewVal = DAG.
SplitScalar(
N->getOperand(3),
DL, MVT::i64, MVT::i64);
5633 SDValue Ops[] = {
N->getOperand(1), CmpVal.first, CmpVal.second,
5634 NewVal.first, NewVal.second,
N->getOperand(0)};
5637 Opcode,
SDLoc(
N), DAG.
getVTList(MVT::i64, MVT::i64, MVT::i64, MVT::Other),
5648 EVT VT =
N->getValueType(0);
5649 switch (
N->getOpcode()) {
5654 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
5655 "Unexpected custom legalisation");
5662 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5663 "Unexpected custom legalisation");
5665 Subtarget.hasDiv32() && VT == MVT::i32
5672 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5673 "Unexpected custom legalisation");
5681 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5682 "Unexpected custom legalisation");
5689 MVT VT =
N->getSimpleValueType(0);
5690 assert(VT == MVT::v2f32 && Subtarget.hasExtLSX() &&
5691 "Unexpected custom legalisation");
5693 "Unexpected type action!");
5698 Ld->getPointerInfo(), Ld->getBaseAlign(),
5699 Ld->getMemOperand()->getFlags());
5710 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5711 "Unexpected custom legalisation");
5718 if (Src.getValueType() == MVT::f16)
5729 EVT OpVT = Src.getValueType();
5733 std::tie(Result, Chain) =
5740 EVT SrcVT = Src.getValueType();
5741 if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.is64Bit() &&
5742 Subtarget.hasBasicF()) {
5744 DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Src);
5746 }
else if (VT == MVT::i64 && SrcVT == MVT::f64 && !Subtarget.is64Bit()) {
5748 DAG.
getVTList(MVT::i32, MVT::i32), Src);
5756 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5757 "Unexpected custom legalisation");
5760 TLI.expandFP_TO_UINT(
N, Tmp1, Tmp2, DAG);
5765 assert(VT == MVT::v2f32 && Subtarget.hasExtLSX() &&
5766 "Unexpected custom legalisation");
5772 if (OpVT == MVT::v2f64) {
5782 assert((VT == MVT::i16 || VT == MVT::i32) &&
5783 "Unexpected custom legalization");
5784 MVT GRLenVT = Subtarget.getGRLenVT();
5791 Tmp = DAG.
getNode(LoongArchISD::REVB_2H,
DL, GRLenVT, NewSrc);
5796 Tmp = DAG.
getNode(LoongArchISD::REVB_2W,
DL, GRLenVT, NewSrc);
5804 assert((VT == MVT::i8 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
5805 "Unexpected custom legalization");
5806 MVT GRLenVT = Subtarget.getGRLenVT();
5813 Tmp = DAG.
getNode(LoongArchISD::BITREV_4B,
DL, GRLenVT, NewSrc);
5816 Tmp = DAG.
getNode(LoongArchISD::BITREV_W,
DL, GRLenVT, NewSrc);
5824 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5825 "Unexpected custom legalisation");
5832 MVT GRLenVT = Subtarget.getGRLenVT();
5833 const StringRef ErrorMsgOOR =
"argument out of range";
5834 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
5835 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
5837 switch (
N->getConstantOperandVal(1)) {
5840 case Intrinsic::loongarch_movfcsr2gr: {
5841 if (!Subtarget.hasBasicF()) {
5851 LoongArchISD::MOVFCSR2GR,
SDLoc(
N), {MVT::i64, MVT::Other},
5858#define CRC_CASE_EXT_BINARYOP(NAME, NODE) \
5859 case Intrinsic::loongarch_##NAME: { \
5860 SDValue NODE = DAG.getNode( \
5861 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5862 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
5863 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5864 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5865 Results.push_back(NODE.getValue(1)); \
5874#undef CRC_CASE_EXT_BINARYOP
5876#define CRC_CASE_EXT_UNARYOP(NAME, NODE) \
5877 case Intrinsic::loongarch_##NAME: { \
5878 SDValue NODE = DAG.getNode( \
5879 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5881 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5882 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5883 Results.push_back(NODE.getValue(1)); \
5888#undef CRC_CASE_EXT_UNARYOP
5889#define CSR_CASE(ID) \
5890 case Intrinsic::loongarch_##ID: { \
5891 if (!Subtarget.is64Bit()) \
5892 emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgReqLA64); \
5900 case Intrinsic::loongarch_csrrd_w: {
5907 DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
5914 case Intrinsic::loongarch_csrwr_w: {
5915 unsigned Imm =
N->getConstantOperandVal(3);
5921 DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
5929 case Intrinsic::loongarch_csrxchg_w: {
5930 unsigned Imm =
N->getConstantOperandVal(4);
5936 LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
5945#define IOCSRRD_CASE(NAME, NODE) \
5946 case Intrinsic::loongarch_##NAME: { \
5947 SDValue IOCSRRDResults = \
5948 DAG.getNode(LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5949 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2)}); \
5950 Results.push_back( \
5951 DAG.getNode(ISD::TRUNCATE, DL, VT, IOCSRRDResults.getValue(0))); \
5952 Results.push_back(IOCSRRDResults.getValue(1)); \
5959 case Intrinsic::loongarch_cpucfg: {
5961 DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
5968 case Intrinsic::loongarch_lddir_d: {
5969 if (!Subtarget.is64Bit()) {
5979 if (Subtarget.is64Bit())
5981 "On LA64, only 64-bit registers can be read.");
5984 "On LA32, only 32-bit registers can be read.");
5986 Results.push_back(
N->getOperand(0));
5997 OpVT == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
6010 MVT VT =
N->getSimpleValueType(0);
6016 EVT InVT = In.getValueType();
6026 In = DAG.
getNode(
N->getOpcode(),
DL, InVT, In);
6031 if ((InVT == MVT::v8i32 || InVT == MVT::v4i64) &&
6034 In = DAG.
getNode(
N->getOpcode(),
DL, InVT, In);
6043 for (
unsigned I = 0;
I < MinElts; ++
I)
6044 TruncMask[
I] = Scale *
I;
6046 unsigned WidenNumElts = 128 / In.getScalarValueSizeInBits();
6047 MVT SVT = In.getSimpleValueType().getScalarType();
6053 "Illegal vector type in truncation");
6065 if (!Subtarget.hasExtLSX() || Subtarget.hasExtLASX())
6068 EVT DstVT =
N->getValueType(0);
6070 MVT SrcVT = Src.getSimpleValueType();
6084 unsigned WidenSrcElts = 128 / SrcEltBits;
6091 unsigned FirstStageEltBits = 128 / NumElts;
6095 SrcVT = FirstStageVT;
6096 SrcEltBits = FirstStageEltBits;
6103 while (SrcEltBits < DstEltBits) {
6104 unsigned NextEltBits = SrcEltBits * 2;
6107 unsigned NextEltsPerBlock = CurEltsPerBlock / 2;
6125 Blocks = std::move(NextBlocks);
6126 SrcVT = NextBlockVT;
6127 SrcEltBits = NextEltBits;
6144 assert(
N->getOpcode() ==
ISD::AND &&
"Unexpected opcode combine into ANDN");
6146 MVT VT =
N->getSimpleValueType(0);
6165 return DAG.
getNode(LoongArchISD::VANDN,
DL, VT,
X,
Y);
6169 unsigned MinSizeInBits) {
6177 unsigned SplatBitSize;
6180 return Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
6181 HasAnyUndefs, MinSizeInBits,
6193 for (
unsigned i = 0, NumElts = BV->getNumOperands(); i < NumElts; ++i) {
6204 unsigned EltIdx = IdxC->getZExtValue();
6206 Start = (int)EltIdx - (
int)(i * 2);
6207 if (Start < 0 || Start > 1 || EltIdx != (
unsigned)(Start + (
int)(i * 2)))
6213 else if (Src != CurSrc)
6217 if (!Src || Start < 0)
6227 if (!Subtarget.hasExtLSX())
6230 unsigned Opc =
N->getOpcode();
6233 EVT VT =
N->getValueType(0);
6240 unsigned ExtOpc =
LHS.getOpcode();
6248 if (ExtOpc !=
RHS.getOpcode())
6251 if (!
LHS.hasOneUse() || !
RHS.hasOneUse())
6254 unsigned OddIdx, EvenIdx;
6258 if (!LHSVec || !RHSVec)
6260 if (OddIdx != 1 || EvenIdx != 0)
6270 if (!TLI.isTypeLegal(VT) || !TLI.isTypeLegal(SrcVT))
6283 TargetOpc =
isSigned ? LoongArchISD::VHADDW : LoongArchISD::VHADDW_U;
6285 TargetOpc =
isSigned ? LoongArchISD::VHSUBW : LoongArchISD::VHSUBW_U;
6287 return DAG.
getNode(TargetOpc,
DL, VT, LHSVec, RHSVec);
6299 EVT VT =
N->getValueType(0);
6365 if (
And.getOperand(0) ==
X) {
6394 if (ShiftVal != (SplatVal + 1))
6403 : LoongArchISD::VSRAR,
6413 SDValue FirstOperand =
N->getOperand(0);
6414 SDValue SecondOperand =
N->getOperand(1);
6415 unsigned FirstOperandOpc = FirstOperand.
getOpcode();
6416 EVT ValTy =
N->getValueType(0);
6419 unsigned SMIdx, SMLen;
6428 if (!Subtarget.has32S())
6484 NewOperand = FirstOperand;
6487 msb = lsb + SMLen - 1;
6491 if (FirstOperandOpc ==
ISD::SRA || FirstOperandOpc ==
ISD::SRL || lsb == 0)
6505 EVT DstVT =
N.getValueType();
6514 EVT SrcVT = Src.getValueType();
6522 if (
N.getConstantOperandVal(1) != (isLow ? 0 : NumElts))
6533 if (NumElts % 2 != 0)
6539 for (
unsigned I = 0;
I != NumElts; ++
I) {
6554 SrcVT = Src.getValueType();
6564 }
else if (ThisSrc != Src) {
6568 unsigned Half = NumElts / 2;
6569 unsigned ExpectedIdx = (
I < Half) ?
I : (
I + Half);
6570 ExpectedIdx += isLow ? 0 : Half;
6572 if (CI->getZExtValue() != ExpectedIdx)
6584 EVT VT =
N->getValueType(0);
6591 unsigned ExtOpc =
LHS.getOpcode();
6599 if (!
LHS.hasOneUse())
6603 N->getValueSizeInBits(0) !=
LHS->getOperand(0).getValueSizeInBits() * 2)
6619 unsigned Opc =
isSigned ? LoongArchISD::VSLLWIL : LoongArchISD::VSLLWIL_U;
6628 if (!Subtarget.has32S())
6640 SDValue FirstOperand =
N->getOperand(0);
6642 EVT ValTy =
N->getValueType(0);
6645 unsigned MaskIdx, MaskLen;
6660 if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1)
6661 return DAG.
getNode(LoongArchISD::BSTRPICK,
DL, ValTy,
6685 switch (Src.getOpcode()) {
6688 return Src.getOperand(0).getValueSizeInBits() ==
Size;
6698 return Src.getOperand(0).getScalarValueSizeInBits() == 1 &&
6711 switch (Src.getOpcode()) {
6721 Src.getOpcode(),
DL, SExtVT,
6727 DL, SExtVT, Src.getOperand(0),
6739 EVT VT =
N->getValueType(0);
6741 EVT SrcVT = Src.getValueType();
6743 if (Src.getOpcode() !=
ISD::SETCC || !Src.hasOneUse())
6748 EVT CmpVT = Src.getOperand(0).getValueType();
6753 else if (Subtarget.has32S() && Subtarget.hasExtLASX() &&
6766 Opc = UseLASX ? LoongArchISD::XVMSKEQZ : LoongArchISD::VMSKEQZ;
6771 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
6776 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
6781 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
6783 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6788 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
6790 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6795 Opc = UseLASX ? LoongArchISD::XVMSKNEZ : LoongArchISD::VMSKNEZ;
6812 EVT VT =
N->getValueType(0);
6814 EVT SrcVT = Src.getValueType();
6831 bool UseLASX =
false;
6832 bool PropagateSExt =
false;
6834 if (Src.getOpcode() ==
ISD::SETCC && Src.hasOneUse()) {
6835 EVT CmpVT = Src.getOperand(0).getValueType();
6844 SExtVT = MVT::v2i64;
6847 SExtVT = MVT::v4i32;
6849 SExtVT = MVT::v4i64;
6851 PropagateSExt =
true;
6855 SExtVT = MVT::v8i16;
6857 SExtVT = MVT::v8i32;
6859 PropagateSExt =
true;
6863 SExtVT = MVT::v16i8;
6865 SExtVT = MVT::v16i16;
6867 PropagateSExt =
true;
6871 SExtVT = MVT::v32i8;
6879 if (!Subtarget.has32S() || !Subtarget.hasExtLASX()) {
6880 if (Src.getSimpleValueType() == MVT::v32i8) {
6888 }
else if (UseLASX) {
6894 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6907 EVT ValTy =
N->getValueType(0);
6908 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
6912 unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1;
6914 bool SwapAndRetried =
false;
6917 if (!Subtarget.has32S())
6923 if (ValBits != 32 && ValBits != 64)
6938 MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 &&
6941 (MaskIdx0 + MaskLen0 <= ValBits)) {
6962 MaskLen0 == MaskLen1 && MaskIdx1 == 0 &&
6963 (MaskIdx0 + MaskLen0 <= ValBits)) {
6980 (MaskIdx0 + MaskLen0 <= 64) &&
6988 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
6989 : (MaskIdx0 + MaskLen0 - 1),
7005 (MaskIdx0 + MaskLen0 <= ValBits)) {
7028 DAG.
getConstant(ValBits == 32 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
7029 : (MaskIdx0 + MaskLen0 - 1),
7044 unsigned MaskIdx, MaskLen;
7045 if (N1.getOpcode() ==
ISD::SHL && N1.getOperand(0).getOpcode() ==
ISD::AND &&
7054 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
7072 N1.getOperand(0).getOpcode() ==
ISD::SHL &&
7078 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
7086 if (!SwapAndRetried) {
7088 SwapAndRetried =
true;
7092 SwapAndRetried =
false;
7109 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
7118 if (!SwapAndRetried) {
7120 SwapAndRetried =
true;
7130 switch (V.getNode()->getOpcode()) {
7142 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
7150 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
7180 unsigned MskOpc =
LHS.getOpcode();
7181 if (MskOpc != LoongArchISD::VMSKLTZ && MskOpc != LoongArchISD::XVMSKLTZ)
7184 if (!
LHS.hasOneUse())
7188 EVT SrcVT = Src.getValueType();
7195 : LoongArchISD::VALLZERO,
7265 SDLoc(
N), DAG, Subtarget))
7268 SDNode *AndNode =
N->getOperand(0).getNode();
7276 SDValue CmpInputValue =
N->getOperand(1);
7285 if (!CN || !CN->
isZero())
7287 AndInputValue1 = AndInputValue1.
getOperand(0);
7291 if (AndInputValue2 != CmpInputValue)
7324 TruncInputValue1, TruncInputValue2);
7326 DAG.
getSetCC(
SDLoc(
N),
N->getValueType(0), NewAnd, TruncInputValue2, CC);
7345 return {V.getOperand(0),
cast<VTSDNode>(V.getOperand(1))->getVT()};
7366static std::tuple<unsigned, SDValue, EVT>
7370 unsigned Opc = Inner.getOpcode();
7375 if (Inner.getOperand(0) ==
X)
7376 return {
Opc, Inner.getOperand(1), ExtVT};
7377 if (Inner.getOperand(1) ==
X)
7378 return {
Opc, Inner.getOperand(0), ExtVT};
7382 if (Inner.getOperand(0) ==
X)
7383 return {
Opc, Inner.getOperand(1), ExtVT};
7405 EVT VT =
N->getValueType(0);
7417 bool BinIsTrueArm) ->
SDValue {
7425 if (Delta.getNode() ==
N)
7447 if (
SDValue R = TryFold(TrueV, FalseV,
true))
7449 if (
SDValue R = TryFold(FalseV, TrueV,
false))
7463 if (Src.getOpcode() != LoongArchISD::REVB_2W)
7466 return DAG.
getNode(LoongArchISD::BITREV_4B,
SDLoc(
N),
N->getValueType(0),
7491 LHS.getOperand(0).getValueType() == Subtarget.
getGRLenVT()) {
7519 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
7546 unsigned Sht =
LHS.getConstantOperandVal(1);
7550 if ((EleBits + Sht) == Subtarget.
getGRLen()) {
7560 EVT VT =
LHS.getValueType();
7584 DL, DAG, Subtarget))
7585 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
N->getValueType(0),
7586 N->getOperand(0), V,
7591 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
N->getValueType(0),
7592 N->getOperand(0),
LHS,
RHS, CC,
N->getOperand(4));
7608 EVT VT =
N->getValueType(0);
7611 if (TrueV == FalseV)
7642 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL,
N->getValueType(0),
7643 {LHS, RHS, CC, TrueV, FalseV});
7648template <
unsigned N>
7652 bool IsSigned =
false) {
7656 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
7657 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
7659 ": argument out of range.");
7665template <
unsigned N>
7669 EVT ResTy =
Node->getValueType(0);
7673 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
7674 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
7676 ": argument out of range.");
7681 IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned),
7687 EVT ResTy =
Node->getValueType(0);
7695 EVT ResTy =
Node->getValueType(0);
7704template <
unsigned N>
7707 EVT ResTy =
Node->getValueType(0);
7712 ": argument out of range.");
7722template <
unsigned N>
7725 EVT ResTy =
Node->getValueType(0);
7730 ": argument out of range.");
7739template <
unsigned N>
7742 EVT ResTy =
Node->getValueType(0);
7747 ": argument out of range.");
7756template <
unsigned W>
7759 unsigned Imm =
N->getConstantOperandVal(2);
7761 const StringRef ErrorMsg =
"argument out of range";
7763 return DAG.
getUNDEF(
N->getValueType(0));
7769 return DAG.
getNode(ResOp,
DL,
N->getValueType(0), Vec, Idx, EltVT);
7777 switch (
N->getConstantOperandVal(0)) {
7780 case Intrinsic::loongarch_lsx_vadd_b:
7781 case Intrinsic::loongarch_lsx_vadd_h:
7782 case Intrinsic::loongarch_lsx_vadd_w:
7783 case Intrinsic::loongarch_lsx_vadd_d:
7784 case Intrinsic::loongarch_lasx_xvadd_b:
7785 case Intrinsic::loongarch_lasx_xvadd_h:
7786 case Intrinsic::loongarch_lasx_xvadd_w:
7787 case Intrinsic::loongarch_lasx_xvadd_d:
7790 case Intrinsic::loongarch_lsx_vaddi_bu:
7791 case Intrinsic::loongarch_lsx_vaddi_hu:
7792 case Intrinsic::loongarch_lsx_vaddi_wu:
7793 case Intrinsic::loongarch_lsx_vaddi_du:
7794 case Intrinsic::loongarch_lasx_xvaddi_bu:
7795 case Intrinsic::loongarch_lasx_xvaddi_hu:
7796 case Intrinsic::loongarch_lasx_xvaddi_wu:
7797 case Intrinsic::loongarch_lasx_xvaddi_du:
7800 case Intrinsic::loongarch_lsx_vsub_b:
7801 case Intrinsic::loongarch_lsx_vsub_h:
7802 case Intrinsic::loongarch_lsx_vsub_w:
7803 case Intrinsic::loongarch_lsx_vsub_d:
7804 case Intrinsic::loongarch_lasx_xvsub_b:
7805 case Intrinsic::loongarch_lasx_xvsub_h:
7806 case Intrinsic::loongarch_lasx_xvsub_w:
7807 case Intrinsic::loongarch_lasx_xvsub_d:
7810 case Intrinsic::loongarch_lsx_vsubi_bu:
7811 case Intrinsic::loongarch_lsx_vsubi_hu:
7812 case Intrinsic::loongarch_lsx_vsubi_wu:
7813 case Intrinsic::loongarch_lsx_vsubi_du:
7814 case Intrinsic::loongarch_lasx_xvsubi_bu:
7815 case Intrinsic::loongarch_lasx_xvsubi_hu:
7816 case Intrinsic::loongarch_lasx_xvsubi_wu:
7817 case Intrinsic::loongarch_lasx_xvsubi_du:
7820 case Intrinsic::loongarch_lsx_vneg_b:
7821 case Intrinsic::loongarch_lsx_vneg_h:
7822 case Intrinsic::loongarch_lsx_vneg_w:
7823 case Intrinsic::loongarch_lsx_vneg_d:
7824 case Intrinsic::loongarch_lasx_xvneg_b:
7825 case Intrinsic::loongarch_lasx_xvneg_h:
7826 case Intrinsic::loongarch_lasx_xvneg_w:
7827 case Intrinsic::loongarch_lasx_xvneg_d:
7831 APInt(
N->getValueType(0).getScalarType().getSizeInBits(), 0,
7833 SDLoc(
N),
N->getValueType(0)),
7835 case Intrinsic::loongarch_lsx_vmax_b:
7836 case Intrinsic::loongarch_lsx_vmax_h:
7837 case Intrinsic::loongarch_lsx_vmax_w:
7838 case Intrinsic::loongarch_lsx_vmax_d:
7839 case Intrinsic::loongarch_lasx_xvmax_b:
7840 case Intrinsic::loongarch_lasx_xvmax_h:
7841 case Intrinsic::loongarch_lasx_xvmax_w:
7842 case Intrinsic::loongarch_lasx_xvmax_d:
7845 case Intrinsic::loongarch_lsx_vmax_bu:
7846 case Intrinsic::loongarch_lsx_vmax_hu:
7847 case Intrinsic::loongarch_lsx_vmax_wu:
7848 case Intrinsic::loongarch_lsx_vmax_du:
7849 case Intrinsic::loongarch_lasx_xvmax_bu:
7850 case Intrinsic::loongarch_lasx_xvmax_hu:
7851 case Intrinsic::loongarch_lasx_xvmax_wu:
7852 case Intrinsic::loongarch_lasx_xvmax_du:
7855 case Intrinsic::loongarch_lsx_vmaxi_b:
7856 case Intrinsic::loongarch_lsx_vmaxi_h:
7857 case Intrinsic::loongarch_lsx_vmaxi_w:
7858 case Intrinsic::loongarch_lsx_vmaxi_d:
7859 case Intrinsic::loongarch_lasx_xvmaxi_b:
7860 case Intrinsic::loongarch_lasx_xvmaxi_h:
7861 case Intrinsic::loongarch_lasx_xvmaxi_w:
7862 case Intrinsic::loongarch_lasx_xvmaxi_d:
7865 case Intrinsic::loongarch_lsx_vmaxi_bu:
7866 case Intrinsic::loongarch_lsx_vmaxi_hu:
7867 case Intrinsic::loongarch_lsx_vmaxi_wu:
7868 case Intrinsic::loongarch_lsx_vmaxi_du:
7869 case Intrinsic::loongarch_lasx_xvmaxi_bu:
7870 case Intrinsic::loongarch_lasx_xvmaxi_hu:
7871 case Intrinsic::loongarch_lasx_xvmaxi_wu:
7872 case Intrinsic::loongarch_lasx_xvmaxi_du:
7875 case Intrinsic::loongarch_lsx_vmin_b:
7876 case Intrinsic::loongarch_lsx_vmin_h:
7877 case Intrinsic::loongarch_lsx_vmin_w:
7878 case Intrinsic::loongarch_lsx_vmin_d:
7879 case Intrinsic::loongarch_lasx_xvmin_b:
7880 case Intrinsic::loongarch_lasx_xvmin_h:
7881 case Intrinsic::loongarch_lasx_xvmin_w:
7882 case Intrinsic::loongarch_lasx_xvmin_d:
7885 case Intrinsic::loongarch_lsx_vmin_bu:
7886 case Intrinsic::loongarch_lsx_vmin_hu:
7887 case Intrinsic::loongarch_lsx_vmin_wu:
7888 case Intrinsic::loongarch_lsx_vmin_du:
7889 case Intrinsic::loongarch_lasx_xvmin_bu:
7890 case Intrinsic::loongarch_lasx_xvmin_hu:
7891 case Intrinsic::loongarch_lasx_xvmin_wu:
7892 case Intrinsic::loongarch_lasx_xvmin_du:
7895 case Intrinsic::loongarch_lsx_vmini_b:
7896 case Intrinsic::loongarch_lsx_vmini_h:
7897 case Intrinsic::loongarch_lsx_vmini_w:
7898 case Intrinsic::loongarch_lsx_vmini_d:
7899 case Intrinsic::loongarch_lasx_xvmini_b:
7900 case Intrinsic::loongarch_lasx_xvmini_h:
7901 case Intrinsic::loongarch_lasx_xvmini_w:
7902 case Intrinsic::loongarch_lasx_xvmini_d:
7905 case Intrinsic::loongarch_lsx_vmini_bu:
7906 case Intrinsic::loongarch_lsx_vmini_hu:
7907 case Intrinsic::loongarch_lsx_vmini_wu:
7908 case Intrinsic::loongarch_lsx_vmini_du:
7909 case Intrinsic::loongarch_lasx_xvmini_bu:
7910 case Intrinsic::loongarch_lasx_xvmini_hu:
7911 case Intrinsic::loongarch_lasx_xvmini_wu:
7912 case Intrinsic::loongarch_lasx_xvmini_du:
7915 case Intrinsic::loongarch_lsx_vmul_b:
7916 case Intrinsic::loongarch_lsx_vmul_h:
7917 case Intrinsic::loongarch_lsx_vmul_w:
7918 case Intrinsic::loongarch_lsx_vmul_d:
7919 case Intrinsic::loongarch_lasx_xvmul_b:
7920 case Intrinsic::loongarch_lasx_xvmul_h:
7921 case Intrinsic::loongarch_lasx_xvmul_w:
7922 case Intrinsic::loongarch_lasx_xvmul_d:
7925 case Intrinsic::loongarch_lsx_vmadd_b:
7926 case Intrinsic::loongarch_lsx_vmadd_h:
7927 case Intrinsic::loongarch_lsx_vmadd_w:
7928 case Intrinsic::loongarch_lsx_vmadd_d:
7929 case Intrinsic::loongarch_lasx_xvmadd_b:
7930 case Intrinsic::loongarch_lasx_xvmadd_h:
7931 case Intrinsic::loongarch_lasx_xvmadd_w:
7932 case Intrinsic::loongarch_lasx_xvmadd_d: {
7933 EVT ResTy =
N->getValueType(0);
7938 case Intrinsic::loongarch_lsx_vmsub_b:
7939 case Intrinsic::loongarch_lsx_vmsub_h:
7940 case Intrinsic::loongarch_lsx_vmsub_w:
7941 case Intrinsic::loongarch_lsx_vmsub_d:
7942 case Intrinsic::loongarch_lasx_xvmsub_b:
7943 case Intrinsic::loongarch_lasx_xvmsub_h:
7944 case Intrinsic::loongarch_lasx_xvmsub_w:
7945 case Intrinsic::loongarch_lasx_xvmsub_d: {
7946 EVT ResTy =
N->getValueType(0);
7951 case Intrinsic::loongarch_lsx_vdiv_b:
7952 case Intrinsic::loongarch_lsx_vdiv_h:
7953 case Intrinsic::loongarch_lsx_vdiv_w:
7954 case Intrinsic::loongarch_lsx_vdiv_d:
7955 case Intrinsic::loongarch_lasx_xvdiv_b:
7956 case Intrinsic::loongarch_lasx_xvdiv_h:
7957 case Intrinsic::loongarch_lasx_xvdiv_w:
7958 case Intrinsic::loongarch_lasx_xvdiv_d:
7961 case Intrinsic::loongarch_lsx_vdiv_bu:
7962 case Intrinsic::loongarch_lsx_vdiv_hu:
7963 case Intrinsic::loongarch_lsx_vdiv_wu:
7964 case Intrinsic::loongarch_lsx_vdiv_du:
7965 case Intrinsic::loongarch_lasx_xvdiv_bu:
7966 case Intrinsic::loongarch_lasx_xvdiv_hu:
7967 case Intrinsic::loongarch_lasx_xvdiv_wu:
7968 case Intrinsic::loongarch_lasx_xvdiv_du:
7971 case Intrinsic::loongarch_lsx_vmod_b:
7972 case Intrinsic::loongarch_lsx_vmod_h:
7973 case Intrinsic::loongarch_lsx_vmod_w:
7974 case Intrinsic::loongarch_lsx_vmod_d:
7975 case Intrinsic::loongarch_lasx_xvmod_b:
7976 case Intrinsic::loongarch_lasx_xvmod_h:
7977 case Intrinsic::loongarch_lasx_xvmod_w:
7978 case Intrinsic::loongarch_lasx_xvmod_d:
7981 case Intrinsic::loongarch_lsx_vmod_bu:
7982 case Intrinsic::loongarch_lsx_vmod_hu:
7983 case Intrinsic::loongarch_lsx_vmod_wu:
7984 case Intrinsic::loongarch_lsx_vmod_du:
7985 case Intrinsic::loongarch_lasx_xvmod_bu:
7986 case Intrinsic::loongarch_lasx_xvmod_hu:
7987 case Intrinsic::loongarch_lasx_xvmod_wu:
7988 case Intrinsic::loongarch_lasx_xvmod_du:
7991 case Intrinsic::loongarch_lsx_vand_v:
7992 case Intrinsic::loongarch_lasx_xvand_v:
7995 case Intrinsic::loongarch_lsx_vor_v:
7996 case Intrinsic::loongarch_lasx_xvor_v:
7999 case Intrinsic::loongarch_lsx_vxor_v:
8000 case Intrinsic::loongarch_lasx_xvxor_v:
8003 case Intrinsic::loongarch_lsx_vnor_v:
8004 case Intrinsic::loongarch_lasx_xvnor_v: {
8009 case Intrinsic::loongarch_lsx_vandi_b:
8010 case Intrinsic::loongarch_lasx_xvandi_b:
8013 case Intrinsic::loongarch_lsx_vori_b:
8014 case Intrinsic::loongarch_lasx_xvori_b:
8017 case Intrinsic::loongarch_lsx_vxori_b:
8018 case Intrinsic::loongarch_lasx_xvxori_b:
8021 case Intrinsic::loongarch_lsx_vsll_b:
8022 case Intrinsic::loongarch_lsx_vsll_h:
8023 case Intrinsic::loongarch_lsx_vsll_w:
8024 case Intrinsic::loongarch_lsx_vsll_d:
8025 case Intrinsic::loongarch_lasx_xvsll_b:
8026 case Intrinsic::loongarch_lasx_xvsll_h:
8027 case Intrinsic::loongarch_lasx_xvsll_w:
8028 case Intrinsic::loongarch_lasx_xvsll_d:
8031 case Intrinsic::loongarch_lsx_vslli_b:
8032 case Intrinsic::loongarch_lasx_xvslli_b:
8035 case Intrinsic::loongarch_lsx_vslli_h:
8036 case Intrinsic::loongarch_lasx_xvslli_h:
8039 case Intrinsic::loongarch_lsx_vslli_w:
8040 case Intrinsic::loongarch_lasx_xvslli_w:
8043 case Intrinsic::loongarch_lsx_vslli_d:
8044 case Intrinsic::loongarch_lasx_xvslli_d:
8047 case Intrinsic::loongarch_lsx_vsrl_b:
8048 case Intrinsic::loongarch_lsx_vsrl_h:
8049 case Intrinsic::loongarch_lsx_vsrl_w:
8050 case Intrinsic::loongarch_lsx_vsrl_d:
8051 case Intrinsic::loongarch_lasx_xvsrl_b:
8052 case Intrinsic::loongarch_lasx_xvsrl_h:
8053 case Intrinsic::loongarch_lasx_xvsrl_w:
8054 case Intrinsic::loongarch_lasx_xvsrl_d:
8057 case Intrinsic::loongarch_lsx_vsrli_b:
8058 case Intrinsic::loongarch_lasx_xvsrli_b:
8061 case Intrinsic::loongarch_lsx_vsrli_h:
8062 case Intrinsic::loongarch_lasx_xvsrli_h:
8065 case Intrinsic::loongarch_lsx_vsrli_w:
8066 case Intrinsic::loongarch_lasx_xvsrli_w:
8069 case Intrinsic::loongarch_lsx_vsrli_d:
8070 case Intrinsic::loongarch_lasx_xvsrli_d:
8073 case Intrinsic::loongarch_lsx_vsra_b:
8074 case Intrinsic::loongarch_lsx_vsra_h:
8075 case Intrinsic::loongarch_lsx_vsra_w:
8076 case Intrinsic::loongarch_lsx_vsra_d:
8077 case Intrinsic::loongarch_lasx_xvsra_b:
8078 case Intrinsic::loongarch_lasx_xvsra_h:
8079 case Intrinsic::loongarch_lasx_xvsra_w:
8080 case Intrinsic::loongarch_lasx_xvsra_d:
8083 case Intrinsic::loongarch_lsx_vsrai_b:
8084 case Intrinsic::loongarch_lasx_xvsrai_b:
8087 case Intrinsic::loongarch_lsx_vsrai_h:
8088 case Intrinsic::loongarch_lasx_xvsrai_h:
8091 case Intrinsic::loongarch_lsx_vsrai_w:
8092 case Intrinsic::loongarch_lasx_xvsrai_w:
8095 case Intrinsic::loongarch_lsx_vsrai_d:
8096 case Intrinsic::loongarch_lasx_xvsrai_d:
8099 case Intrinsic::loongarch_lsx_vclz_b:
8100 case Intrinsic::loongarch_lsx_vclz_h:
8101 case Intrinsic::loongarch_lsx_vclz_w:
8102 case Intrinsic::loongarch_lsx_vclz_d:
8103 case Intrinsic::loongarch_lasx_xvclz_b:
8104 case Intrinsic::loongarch_lasx_xvclz_h:
8105 case Intrinsic::loongarch_lasx_xvclz_w:
8106 case Intrinsic::loongarch_lasx_xvclz_d:
8108 case Intrinsic::loongarch_lsx_vpcnt_b:
8109 case Intrinsic::loongarch_lsx_vpcnt_h:
8110 case Intrinsic::loongarch_lsx_vpcnt_w:
8111 case Intrinsic::loongarch_lsx_vpcnt_d:
8112 case Intrinsic::loongarch_lasx_xvpcnt_b:
8113 case Intrinsic::loongarch_lasx_xvpcnt_h:
8114 case Intrinsic::loongarch_lasx_xvpcnt_w:
8115 case Intrinsic::loongarch_lasx_xvpcnt_d:
8117 case Intrinsic::loongarch_lsx_vbitclr_b:
8118 case Intrinsic::loongarch_lsx_vbitclr_h:
8119 case Intrinsic::loongarch_lsx_vbitclr_w:
8120 case Intrinsic::loongarch_lsx_vbitclr_d:
8121 case Intrinsic::loongarch_lasx_xvbitclr_b:
8122 case Intrinsic::loongarch_lasx_xvbitclr_h:
8123 case Intrinsic::loongarch_lasx_xvbitclr_w:
8124 case Intrinsic::loongarch_lasx_xvbitclr_d:
8126 case Intrinsic::loongarch_lsx_vbitclri_b:
8127 case Intrinsic::loongarch_lasx_xvbitclri_b:
8129 case Intrinsic::loongarch_lsx_vbitclri_h:
8130 case Intrinsic::loongarch_lasx_xvbitclri_h:
8132 case Intrinsic::loongarch_lsx_vbitclri_w:
8133 case Intrinsic::loongarch_lasx_xvbitclri_w:
8135 case Intrinsic::loongarch_lsx_vbitclri_d:
8136 case Intrinsic::loongarch_lasx_xvbitclri_d:
8138 case Intrinsic::loongarch_lsx_vbitset_b:
8139 case Intrinsic::loongarch_lsx_vbitset_h:
8140 case Intrinsic::loongarch_lsx_vbitset_w:
8141 case Intrinsic::loongarch_lsx_vbitset_d:
8142 case Intrinsic::loongarch_lasx_xvbitset_b:
8143 case Intrinsic::loongarch_lasx_xvbitset_h:
8144 case Intrinsic::loongarch_lasx_xvbitset_w:
8145 case Intrinsic::loongarch_lasx_xvbitset_d: {
8146 EVT VecTy =
N->getValueType(0);
8152 case Intrinsic::loongarch_lsx_vbitseti_b:
8153 case Intrinsic::loongarch_lasx_xvbitseti_b:
8155 case Intrinsic::loongarch_lsx_vbitseti_h:
8156 case Intrinsic::loongarch_lasx_xvbitseti_h:
8158 case Intrinsic::loongarch_lsx_vbitseti_w:
8159 case Intrinsic::loongarch_lasx_xvbitseti_w:
8161 case Intrinsic::loongarch_lsx_vbitseti_d:
8162 case Intrinsic::loongarch_lasx_xvbitseti_d:
8164 case Intrinsic::loongarch_lsx_vbitrev_b:
8165 case Intrinsic::loongarch_lsx_vbitrev_h:
8166 case Intrinsic::loongarch_lsx_vbitrev_w:
8167 case Intrinsic::loongarch_lsx_vbitrev_d:
8168 case Intrinsic::loongarch_lasx_xvbitrev_b:
8169 case Intrinsic::loongarch_lasx_xvbitrev_h:
8170 case Intrinsic::loongarch_lasx_xvbitrev_w:
8171 case Intrinsic::loongarch_lasx_xvbitrev_d: {
8172 EVT VecTy =
N->getValueType(0);
8178 case Intrinsic::loongarch_lsx_vbitrevi_b:
8179 case Intrinsic::loongarch_lasx_xvbitrevi_b:
8181 case Intrinsic::loongarch_lsx_vbitrevi_h:
8182 case Intrinsic::loongarch_lasx_xvbitrevi_h:
8184 case Intrinsic::loongarch_lsx_vbitrevi_w:
8185 case Intrinsic::loongarch_lasx_xvbitrevi_w:
8187 case Intrinsic::loongarch_lsx_vbitrevi_d:
8188 case Intrinsic::loongarch_lasx_xvbitrevi_d:
8190 case Intrinsic::loongarch_lsx_vfadd_s:
8191 case Intrinsic::loongarch_lsx_vfadd_d:
8192 case Intrinsic::loongarch_lasx_xvfadd_s:
8193 case Intrinsic::loongarch_lasx_xvfadd_d:
8196 case Intrinsic::loongarch_lsx_vfsub_s:
8197 case Intrinsic::loongarch_lsx_vfsub_d:
8198 case Intrinsic::loongarch_lasx_xvfsub_s:
8199 case Intrinsic::loongarch_lasx_xvfsub_d:
8202 case Intrinsic::loongarch_lsx_vfmul_s:
8203 case Intrinsic::loongarch_lsx_vfmul_d:
8204 case Intrinsic::loongarch_lasx_xvfmul_s:
8205 case Intrinsic::loongarch_lasx_xvfmul_d:
8208 case Intrinsic::loongarch_lsx_vfdiv_s:
8209 case Intrinsic::loongarch_lsx_vfdiv_d:
8210 case Intrinsic::loongarch_lasx_xvfdiv_s:
8211 case Intrinsic::loongarch_lasx_xvfdiv_d:
8214 case Intrinsic::loongarch_lsx_vfmadd_s:
8215 case Intrinsic::loongarch_lsx_vfmadd_d:
8216 case Intrinsic::loongarch_lasx_xvfmadd_s:
8217 case Intrinsic::loongarch_lasx_xvfmadd_d:
8219 N->getOperand(2),
N->getOperand(3));
8220 case Intrinsic::loongarch_lsx_vinsgr2vr_b:
8222 N->getOperand(1),
N->getOperand(2),
8224 case Intrinsic::loongarch_lsx_vinsgr2vr_h:
8225 case Intrinsic::loongarch_lasx_xvinsgr2vr_w:
8227 N->getOperand(1),
N->getOperand(2),
8229 case Intrinsic::loongarch_lsx_vinsgr2vr_w:
8230 case Intrinsic::loongarch_lasx_xvinsgr2vr_d:
8232 N->getOperand(1),
N->getOperand(2),
8234 case Intrinsic::loongarch_lsx_vinsgr2vr_d:
8236 N->getOperand(1),
N->getOperand(2),
8238 case Intrinsic::loongarch_lsx_vreplgr2vr_b:
8239 case Intrinsic::loongarch_lsx_vreplgr2vr_h:
8240 case Intrinsic::loongarch_lsx_vreplgr2vr_w:
8241 case Intrinsic::loongarch_lsx_vreplgr2vr_d:
8242 case Intrinsic::loongarch_lasx_xvreplgr2vr_b:
8243 case Intrinsic::loongarch_lasx_xvreplgr2vr_h:
8244 case Intrinsic::loongarch_lasx_xvreplgr2vr_w:
8245 case Intrinsic::loongarch_lasx_xvreplgr2vr_d:
8246 return DAG.
getNode(LoongArchISD::VREPLGR2VR,
DL,
N->getValueType(0),
8249 case Intrinsic::loongarch_lsx_vreplve_b:
8250 case Intrinsic::loongarch_lsx_vreplve_h:
8251 case Intrinsic::loongarch_lsx_vreplve_w:
8252 case Intrinsic::loongarch_lsx_vreplve_d:
8253 case Intrinsic::loongarch_lasx_xvreplve_b:
8254 case Intrinsic::loongarch_lasx_xvreplve_h:
8255 case Intrinsic::loongarch_lasx_xvreplve_w:
8256 case Intrinsic::loongarch_lasx_xvreplve_d:
8257 return DAG.
getNode(LoongArchISD::VREPLVE,
DL,
N->getValueType(0),
8261 case Intrinsic::loongarch_lsx_vpickve2gr_b:
8265 case Intrinsic::loongarch_lsx_vpickve2gr_h:
8266 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
8270 case Intrinsic::loongarch_lsx_vpickve2gr_w:
8274 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
8278 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
8279 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
8283 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
8287 case Intrinsic::loongarch_lsx_bz_b:
8288 case Intrinsic::loongarch_lsx_bz_h:
8289 case Intrinsic::loongarch_lsx_bz_w:
8290 case Intrinsic::loongarch_lsx_bz_d:
8291 case Intrinsic::loongarch_lasx_xbz_b:
8292 case Intrinsic::loongarch_lasx_xbz_h:
8293 case Intrinsic::loongarch_lasx_xbz_w:
8294 case Intrinsic::loongarch_lasx_xbz_d:
8296 return DAG.
getNode(LoongArchISD::VALL_ZERO,
DL,
N->getValueType(0),
8299 case Intrinsic::loongarch_lsx_bz_v:
8300 case Intrinsic::loongarch_lasx_xbz_v:
8302 return DAG.
getNode(LoongArchISD::VANY_ZERO,
DL,
N->getValueType(0),
8305 case Intrinsic::loongarch_lsx_bnz_b:
8306 case Intrinsic::loongarch_lsx_bnz_h:
8307 case Intrinsic::loongarch_lsx_bnz_w:
8308 case Intrinsic::loongarch_lsx_bnz_d:
8309 case Intrinsic::loongarch_lasx_xbnz_b:
8310 case Intrinsic::loongarch_lasx_xbnz_h:
8311 case Intrinsic::loongarch_lasx_xbnz_w:
8312 case Intrinsic::loongarch_lasx_xbnz_d:
8314 return DAG.
getNode(LoongArchISD::VALL_NONZERO,
DL,
N->getValueType(0),
8317 case Intrinsic::loongarch_lsx_bnz_v:
8318 case Intrinsic::loongarch_lasx_xbnz_v:
8320 return DAG.
getNode(LoongArchISD::VANY_NONZERO,
DL,
N->getValueType(0),
8323 case Intrinsic::loongarch_lasx_concat_128_s:
8324 case Intrinsic::loongarch_lasx_concat_128_d:
8325 case Intrinsic::loongarch_lasx_concat_128:
8327 N->getOperand(1),
N->getOperand(2));
8339 if (Op0.
getOpcode() == LoongArchISD::MOVFR2GR_S_LA64)
8351 if (Op0->
getOpcode() == LoongArchISD::MOVGR2FR_W_LA64) {
8353 "Unexpected value type!");
8362 MVT VT =
N->getSimpleValueType(0);
8383 if (Op0->
getOpcode() == LoongArchISD::BUILD_PAIR_F64)
8396 APInt V =
C->getValueAPF().bitcastToAPInt();
8411 MVT VT =
N->getSimpleValueType(0);
8470 EVT VT =
N->getValueType(0);
8472 EVT SrcVT = Src.getValueType();
8478 if (SrcEltBits >= DstEltBits)
8485 return DAG.
getNode(
N->getOpcode(),
DL, VT, Extend);
8497 unsigned BlockBits) {
8499 MVT DstVT =
N->getSimpleValueType(0);
8501 MVT SrcVT = Src.getSimpleValueType();
8508 Src.getOperand(0).getValueType() == BlockVT) {
8509 for (
unsigned i = 0; i < Src.getNumOperands(); ++i)
8511 }
else if (SrcBits > BlockBits) {
8513 for (
unsigned i = 0; i < SrcBits / BlockBits; ++i)
8518 BlockBits = SrcBits;
8525 for (
unsigned i = 0; i < Blocks.
size(); i += 2) {
8530 if (BlockBits == 256) {
8540 if (Blocks.
size() == 1)
8550 EVT VT =
N->getValueType(0);
8552 EVT SrcVT = Src.getValueType();
8558 unsigned BlockBits = Subtarget.hasExtLASX() ? 256 : 128;
8561 if (SrcEltBits <= DstEltBits)
8564 if (SrcEltBits != 64 || DstEltBits != 32 || !
isPowerOf2_32(NumElts))
8578 if (VT != MVT::f32 && VT != MVT::f64)
8580 if (VT == MVT::f32 && !Subtarget.hasBasicF())
8582 if (VT == MVT::f64 && !Subtarget.hasBasicD())
8614 EVT VT =
N->getValueType(0);
8631 if (!Subtarget.hasExtLSX())
8635 EVT DstVT =
N->getValueType(0);
8637 EVT SrcVT = Src.getValueType();
8647 unsigned BlockBits = Subtarget.hasExtLASX() ? 256 : 128;
8652 if (SrcBits % BlockBits != 0 && SrcBits != 128)
8655 if (DstEltBits < 32) {
8661 if (SrcEltBits != 64 || DstEltBits != 32)
8666 if (Subtarget.hasExtLASX())
8727 Subtarget.hasExtLASX() && N1.
hasOneUse())
8739 return DAG.
getNode(
N.getOpcode(),
DL, VT, N0, N1);
8749 EVT VT =
N.getValueType();
8766 switch (
N.getOpcode()) {
8782 EVT VT =
N->getValueType(0);
8790 N->getValueSizeInBits(0) !=
N->getOperand(0).getValueSizeInBits() * 2)
8795 return DAG.
getNode(LoongArchISD::VEXTH,
DL, VT, R);
8797 return DAG.
getNode(LoongArchISD::VEXTH_U,
DL, VT, R);
8809 EVT VT =
N->getValueType(0);
8811 if (VT.
isVector() &&
N->getNumOperands() == 2)
8824 EVT VT =
N->getValueType(0);
8836 SDValue TrueVal =
N->getOperand(1);
8837 SDValue FalseVal =
N->getOperand(2);
8871 if (FalseVal.getOpcode() !=
ISD::ADD)
8874 SDValue Add0 = FalseVal.getOperand(0);
8875 SDValue Add1 = FalseVal.getOperand(1);
8945 : LoongArchISD::VSRAR,
8952 switch (
N->getOpcode()) {
8984 case LoongArchISD::BITREV_W:
8986 case LoongArchISD::BR_CC:
8988 case LoongArchISD::SELECT_CC:
8992 case LoongArchISD::MOVGR2FR_W_LA64:
8994 case LoongArchISD::MOVFR2GR_S_LA64:
8996 case LoongArchISD::CRC_W_B_W:
8997 case LoongArchISD::CRC_W_H_W:
8998 case LoongArchISD::CRCC_W_B_W:
8999 case LoongArchISD::CRCC_W_H_W:
9000 case LoongArchISD::VMSKLTZ:
9001 case LoongArchISD::XVMSKLTZ:
9003 case LoongArchISD::SPLIT_PAIR_F64:
9005 case LoongArchISD::VANDN:
9011 case LoongArchISD::VPACKEV:
9012 case LoongArchISD::VPERMI:
9038 MF->
insert(It, BreakMBB);
9042 SinkMBB->splice(SinkMBB->end(),
MBB, std::next(
MI.getIterator()),
MBB->end());
9043 SinkMBB->transferSuccessorsAndUpdatePHIs(
MBB);
9055 MBB->addSuccessor(BreakMBB);
9056 MBB->addSuccessor(SinkMBB);
9062 BreakMBB->addSuccessor(SinkMBB);
9074 switch (
MI.getOpcode()) {
9077 case LoongArch::PseudoVBZ:
9078 CondOpc = LoongArch::VSETEQZ_V;
9080 case LoongArch::PseudoVBZ_B:
9081 CondOpc = LoongArch::VSETANYEQZ_B;
9083 case LoongArch::PseudoVBZ_H:
9084 CondOpc = LoongArch::VSETANYEQZ_H;
9086 case LoongArch::PseudoVBZ_W:
9087 CondOpc = LoongArch::VSETANYEQZ_W;
9089 case LoongArch::PseudoVBZ_D:
9090 CondOpc = LoongArch::VSETANYEQZ_D;
9092 case LoongArch::PseudoVBNZ:
9093 CondOpc = LoongArch::VSETNEZ_V;
9095 case LoongArch::PseudoVBNZ_B:
9096 CondOpc = LoongArch::VSETALLNEZ_B;
9098 case LoongArch::PseudoVBNZ_H:
9099 CondOpc = LoongArch::VSETALLNEZ_H;
9101 case LoongArch::PseudoVBNZ_W:
9102 CondOpc = LoongArch::VSETALLNEZ_W;
9104 case LoongArch::PseudoVBNZ_D:
9105 CondOpc = LoongArch::VSETALLNEZ_D;
9107 case LoongArch::PseudoXVBZ:
9108 CondOpc = LoongArch::XVSETEQZ_V;
9110 case LoongArch::PseudoXVBZ_B:
9111 CondOpc = LoongArch::XVSETANYEQZ_B;
9113 case LoongArch::PseudoXVBZ_H:
9114 CondOpc = LoongArch::XVSETANYEQZ_H;
9116 case LoongArch::PseudoXVBZ_W:
9117 CondOpc = LoongArch::XVSETANYEQZ_W;
9119 case LoongArch::PseudoXVBZ_D:
9120 CondOpc = LoongArch::XVSETANYEQZ_D;
9122 case LoongArch::PseudoXVBNZ:
9123 CondOpc = LoongArch::XVSETNEZ_V;
9125 case LoongArch::PseudoXVBNZ_B:
9126 CondOpc = LoongArch::XVSETALLNEZ_B;
9128 case LoongArch::PseudoXVBNZ_H:
9129 CondOpc = LoongArch::XVSETALLNEZ_H;
9131 case LoongArch::PseudoXVBNZ_W:
9132 CondOpc = LoongArch::XVSETALLNEZ_W;
9134 case LoongArch::PseudoXVBNZ_D:
9135 CondOpc = LoongArch::XVSETALLNEZ_D;
9150 F->insert(It, FalseBB);
9151 F->insert(It, TrueBB);
9152 F->insert(It, SinkBB);
9155 SinkBB->
splice(SinkBB->
end(), BB, std::next(
MI.getIterator()), BB->
end());
9184 MI.getOperand(0).getReg())
9191 MI.eraseFromParent();
9199 unsigned BroadcastOp;
9201 switch (
MI.getOpcode()) {
9204 case LoongArch::PseudoXVINSGR2VR_B:
9206 BroadcastOp = LoongArch::XVREPLGR2VR_B;
9207 InsOp = LoongArch::XVEXTRINS_B;
9209 case LoongArch::PseudoXVINSGR2VR_H:
9211 BroadcastOp = LoongArch::XVREPLGR2VR_H;
9212 InsOp = LoongArch::XVEXTRINS_H;
9224 unsigned Idx =
MI.getOperand(3).getImm();
9232 .
addReg(XSrc, {}, LoongArch::sub_128);
9234 TII->get(HalfSize == 8 ? LoongArch::VINSGR2VR_H
9235 : LoongArch::VINSGR2VR_B),
9243 .
addImm(LoongArch::sub_128);
9250 BuildMI(*BB,
MI,
DL,
TII->get(LoongArch::XVPERMI_Q), ScratchReg2)
9253 .
addImm(Idx >= HalfSize ? 48 : 18);
9258 .
addImm((Idx >= HalfSize ? Idx - HalfSize : Idx) * 17);
9261 MI.eraseFromParent();
9268 assert(Subtarget.hasExtLSX());
9276 unsigned BroadcastOp, CTOp, PickOp;
9277 switch (
MI.getOpcode()) {
9280 case LoongArch::PseudoCTPOP_B:
9281 BroadcastOp = LoongArch::VREPLGR2VR_B;
9282 CTOp = LoongArch::VPCNT_B;
9283 PickOp = LoongArch::VPICKVE2GR_B;
9285 case LoongArch::PseudoCTPOP_H:
9286 case LoongArch::PseudoCTPOP_H_LA32:
9287 BroadcastOp = LoongArch::VREPLGR2VR_H;
9288 CTOp = LoongArch::VPCNT_H;
9289 PickOp = LoongArch::VPICKVE2GR_H;
9291 case LoongArch::PseudoCTPOP_W:
9292 case LoongArch::PseudoCTPOP_W_LA32:
9293 BroadcastOp = LoongArch::VREPLGR2VR_W;
9294 CTOp = LoongArch::VPCNT_W;
9295 PickOp = LoongArch::VPICKVE2GR_W;
9297 case LoongArch::PseudoCTPOP_D:
9298 BroadcastOp = LoongArch::VREPLGR2VR_D;
9299 CTOp = LoongArch::VPCNT_D;
9300 PickOp = LoongArch::VPICKVE2GR_D;
9310 MI.eraseFromParent();
9324 unsigned EleBits = 8;
9325 unsigned NotOpc = 0;
9328 switch (
MI.getOpcode()) {
9331 case LoongArch::PseudoVMSKLTZ_B:
9332 MskOpc = LoongArch::VMSKLTZ_B;
9334 case LoongArch::PseudoVMSKLTZ_H:
9335 MskOpc = LoongArch::VMSKLTZ_H;
9338 case LoongArch::PseudoVMSKLTZ_W:
9339 MskOpc = LoongArch::VMSKLTZ_W;
9342 case LoongArch::PseudoVMSKLTZ_D:
9343 MskOpc = LoongArch::VMSKLTZ_D;
9346 case LoongArch::PseudoVMSKGEZ_B:
9347 MskOpc = LoongArch::VMSKGEZ_B;
9349 case LoongArch::PseudoVMSKEQZ_B:
9350 MskOpc = LoongArch::VMSKNZ_B;
9351 NotOpc = LoongArch::VNOR_V;
9353 case LoongArch::PseudoVMSKNEZ_B:
9354 MskOpc = LoongArch::VMSKNZ_B;
9356 case LoongArch::PseudoXVMSKLTZ_B:
9357 MskOpc = LoongArch::XVMSKLTZ_B;
9358 RC = &LoongArch::LASX256RegClass;
9360 case LoongArch::PseudoXVMSKLTZ_H:
9361 MskOpc = LoongArch::XVMSKLTZ_H;
9362 RC = &LoongArch::LASX256RegClass;
9365 case LoongArch::PseudoXVMSKLTZ_W:
9366 MskOpc = LoongArch::XVMSKLTZ_W;
9367 RC = &LoongArch::LASX256RegClass;
9370 case LoongArch::PseudoXVMSKLTZ_D:
9371 MskOpc = LoongArch::XVMSKLTZ_D;
9372 RC = &LoongArch::LASX256RegClass;
9375 case LoongArch::PseudoXVMSKGEZ_B:
9376 MskOpc = LoongArch::XVMSKGEZ_B;
9377 RC = &LoongArch::LASX256RegClass;
9379 case LoongArch::PseudoXVMSKEQZ_B:
9380 MskOpc = LoongArch::XVMSKNZ_B;
9381 NotOpc = LoongArch::XVNOR_V;
9382 RC = &LoongArch::LASX256RegClass;
9384 case LoongArch::PseudoXVMSKNEZ_B:
9385 MskOpc = LoongArch::XVMSKNZ_B;
9386 RC = &LoongArch::LASX256RegClass;
9401 if (
TRI->getRegSizeInBits(*RC) > 128) {
9411 TII->get(Subtarget.
is64Bit() ? LoongArch::BSTRINS_D
9412 : LoongArch::BSTRINS_W),
9416 .
addImm(256 / EleBits - 1)
9424 MI.eraseFromParent();
9431 assert(
MI.getOpcode() == LoongArch::SplitPairF64Pseudo &&
9432 "Unexpected instruction");
9444 MI.eraseFromParent();
9451 assert(
MI.getOpcode() == LoongArch::BuildPairF64Pseudo &&
9452 "Unexpected instruction");
9468 MI.eraseFromParent();
9473 switch (
MI.getOpcode()) {
9476 case LoongArch::Select_GPR_Using_CC_GPR:
9512 if (
MI.getOperand(2).isReg())
9513 RHS =
MI.getOperand(2).getReg();
9514 auto CC =
static_cast<unsigned>(
MI.getOperand(3).
getImm());
9518 SelectDests.
insert(
MI.getOperand(0).getReg());
9522 SequenceMBBI !=
E; ++SequenceMBBI) {
9523 if (SequenceMBBI->isDebugInstr())
9526 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
9527 !SequenceMBBI->getOperand(2).isReg() ||
9528 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
9529 SequenceMBBI->getOperand(3).getImm() != CC ||
9530 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
9531 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
9533 LastSelectPseudo = &*SequenceMBBI;
9535 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
9538 if (SequenceMBBI->hasUnmodeledSideEffects() ||
9539 SequenceMBBI->mayLoadOrStore() ||
9540 SequenceMBBI->usesCustomInsertionHook())
9543 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
9558 F->insert(
I, IfFalseMBB);
9559 F->insert(
I, TailMBB);
9562 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
9568 TailMBB->
push_back(DebugInstr->removeFromParent());
9572 TailMBB->
splice(TailMBB->
end(), HeadMBB,
9582 if (
MI.getOperand(2).isImm())
9594 auto SelectMBBI =
MI.getIterator();
9595 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
9597 while (SelectMBBI != SelectEnd) {
9598 auto Next = std::next(SelectMBBI);
9602 TII.get(LoongArch::PHI), SelectMBBI->getOperand(0).getReg())
9603 .
addReg(SelectMBBI->getOperand(4).getReg())
9605 .
addReg(SelectMBBI->getOperand(5).getReg())
9612 F->getProperties().resetNoPHIs();
9618 const TargetInstrInfo *
TII = Subtarget.getInstrInfo();
9621 switch (
MI.getOpcode()) {
9624 case LoongArch::DIV_W:
9625 case LoongArch::DIV_WU:
9626 case LoongArch::MOD_W:
9627 case LoongArch::MOD_WU:
9628 case LoongArch::DIV_D:
9629 case LoongArch::DIV_DU:
9630 case LoongArch::MOD_D:
9631 case LoongArch::MOD_DU:
9634 case LoongArch::WRFCSR: {
9636 LoongArch::FCSR0 +
MI.getOperand(0).getImm())
9637 .
addReg(
MI.getOperand(1).getReg());
9638 MI.eraseFromParent();
9641 case LoongArch::RDFCSR: {
9642 MachineInstr *ReadFCSR =
9644 MI.getOperand(0).getReg())
9645 .
addReg(LoongArch::FCSR0 +
MI.getOperand(1).getImm());
9647 MI.eraseFromParent();
9650 case LoongArch::Select_GPR_Using_CC_GPR:
9652 case LoongArch::BuildPairF64Pseudo:
9654 case LoongArch::SplitPairF64Pseudo:
9656 case LoongArch::PseudoVBZ:
9657 case LoongArch::PseudoVBZ_B:
9658 case LoongArch::PseudoVBZ_H:
9659 case LoongArch::PseudoVBZ_W:
9660 case LoongArch::PseudoVBZ_D:
9661 case LoongArch::PseudoVBNZ:
9662 case LoongArch::PseudoVBNZ_B:
9663 case LoongArch::PseudoVBNZ_H:
9664 case LoongArch::PseudoVBNZ_W:
9665 case LoongArch::PseudoVBNZ_D:
9666 case LoongArch::PseudoXVBZ:
9667 case LoongArch::PseudoXVBZ_B:
9668 case LoongArch::PseudoXVBZ_H:
9669 case LoongArch::PseudoXVBZ_W:
9670 case LoongArch::PseudoXVBZ_D:
9671 case LoongArch::PseudoXVBNZ:
9672 case LoongArch::PseudoXVBNZ_B:
9673 case LoongArch::PseudoXVBNZ_H:
9674 case LoongArch::PseudoXVBNZ_W:
9675 case LoongArch::PseudoXVBNZ_D:
9677 case LoongArch::PseudoXVINSGR2VR_B:
9678 case LoongArch::PseudoXVINSGR2VR_H:
9680 case LoongArch::PseudoCTPOP_B:
9681 case LoongArch::PseudoCTPOP_H:
9682 case LoongArch::PseudoCTPOP_W:
9683 case LoongArch::PseudoCTPOP_D:
9684 case LoongArch::PseudoCTPOP_H_LA32:
9685 case LoongArch::PseudoCTPOP_W_LA32:
9687 case LoongArch::PseudoVMSKLTZ_B:
9688 case LoongArch::PseudoVMSKLTZ_H:
9689 case LoongArch::PseudoVMSKLTZ_W:
9690 case LoongArch::PseudoVMSKLTZ_D:
9691 case LoongArch::PseudoVMSKGEZ_B:
9692 case LoongArch::PseudoVMSKEQZ_B:
9693 case LoongArch::PseudoVMSKNEZ_B:
9694 case LoongArch::PseudoXVMSKLTZ_B:
9695 case LoongArch::PseudoXVMSKLTZ_H:
9696 case LoongArch::PseudoXVMSKLTZ_W:
9697 case LoongArch::PseudoXVMSKLTZ_D:
9698 case LoongArch::PseudoXVMSKGEZ_B:
9699 case LoongArch::PseudoXVMSKEQZ_B:
9700 case LoongArch::PseudoXVMSKNEZ_B:
9702 case TargetOpcode::STATEPOINT:
9708 MI.addOperand(*
MI.getMF(),
9710 LoongArch::R1,
true,
9713 if (!Subtarget.is64Bit())
9716 case LoongArch::PROBED_STACKALLOC_DYN:
9723 unsigned *
Fast)
const {
9724 if (!Subtarget.hasUAL())
9742 LoongArch::R7, LoongArch::R8, LoongArch::R9,
9743 LoongArch::R10, LoongArch::R11};
9758 LoongArch::R23, LoongArch::R24, LoongArch::R25, LoongArch::R26,
9759 LoongArch::R27, LoongArch::R28, LoongArch::R29, LoongArch::R30,
9760 LoongArch::R4, LoongArch::R5, LoongArch::R6, LoongArch::R7,
9761 LoongArch::R8, LoongArch::R9, LoongArch::R10, LoongArch::R11,
9762 LoongArch::R12, LoongArch::R13, LoongArch::R14, LoongArch::R15,
9763 LoongArch::R16, LoongArch::R17, LoongArch::R18, LoongArch::R19,
9769 LoongArch::F3, LoongArch::F4, LoongArch::F5,
9770 LoongArch::F6, LoongArch::F7};
9773 LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64,
9774 LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64};
9777 LoongArch::VR3, LoongArch::VR4, LoongArch::VR5,
9778 LoongArch::VR6, LoongArch::VR7};
9781 LoongArch::XR3, LoongArch::XR4, LoongArch::XR5,
9782 LoongArch::XR6, LoongArch::XR7};
9785 switch (State.getCallingConv()) {
9787 if (!State.isVarArg())
9791 return State.AllocateReg(
ArgGPRs);
9799 unsigned ValNo2,
MVT ValVT2,
MVT LocVT2,
9801 unsigned GRLenInBytes = GRLen / 8;
9812 State.AllocateStack(GRLenInBytes, StackAlign),
9815 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
9826 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
9834 unsigned ValNo,
MVT ValVT,
9837 unsigned GRLen =
DL.getLargestLegalIntTypeSizeInBits();
9838 assert((GRLen == 32 || GRLen == 64) &&
"Unspport GRLen");
9839 MVT GRLenVT = GRLen == 32 ? MVT::i32 : MVT::i64;
9844 if (IsRet && ValNo > 1)
9848 bool UseGPRForFloat =
true;
9858 UseGPRForFloat = ArgFlags.
isVarArg();
9871 unsigned TwoGRLenInBytes = (2 * GRLen) / 8;
9874 DL.getTypeAllocSize(OrigTy) == TwoGRLenInBytes) {
9875 unsigned RegIdx = State.getFirstUnallocated(
ArgGPRs);
9877 if (RegIdx != std::size(
ArgGPRs) && RegIdx % 2 == 1)
9883 State.getPendingArgFlags();
9886 "PendingLocs and PendingArgFlags out of sync");
9890 UseGPRForFloat =
true;
9892 if (UseGPRForFloat && ValVT == MVT::f32) {
9895 }
else if (UseGPRForFloat && GRLen == 64 && ValVT == MVT::f64) {
9898 }
else if (UseGPRForFloat && GRLen == 32 && ValVT == MVT::f64) {
9901 assert(PendingLocs.
empty() &&
"Can't lower f64 if it is split");
9943 PendingLocs.
size() <= 2) {
9944 assert(PendingLocs.
size() == 2 &&
"Unexpected PendingLocs.size()");
9949 PendingLocs.
clear();
9950 PendingArgFlags.
clear();
9957 unsigned StoreSizeBytes = GRLen / 8;
9960 if (ValVT == MVT::f32 && !UseGPRForFloat) {
9962 }
else if (ValVT == MVT::f64 && !UseGPRForFloat) {
9966 UseGPRForFloat =
false;
9967 StoreSizeBytes = 16;
9968 StackAlign =
Align(16);
9971 UseGPRForFloat =
false;
9972 StoreSizeBytes = 32;
9973 StackAlign =
Align(32);
9979 Reg ? 0 : State.AllocateStack(StoreSizeBytes, StackAlign);
9983 if (!PendingLocs.
empty()) {
9985 assert(PendingLocs.
size() > 2 &&
"Unexpected PendingLocs.size()");
9986 for (
auto &It : PendingLocs) {
9988 It.convertToReg(
Reg);
9993 PendingLocs.clear();
9994 PendingArgFlags.
clear();
9997 assert((!UseGPRForFloat || LocVT == GRLenVT) &&
9998 "Expected an GRLenVT at this stage");
10015void LoongArchTargetLowering::analyzeInputArgs(
10018 LoongArchCCAssignFn Fn)
const {
10020 for (
unsigned i = 0, e = Ins.
size(); i != e; ++i) {
10021 MVT ArgVT = Ins[i].VT;
10022 Type *ArgTy =
nullptr;
10024 ArgTy = FType->getReturnType();
10025 else if (Ins[i].isOrigArg())
10026 ArgTy = FType->getParamType(Ins[i].getOrigArgIndex());
10030 CCInfo, IsRet, ArgTy)) {
10031 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type " << ArgVT
10038void LoongArchTargetLowering::analyzeOutputArgs(
10041 CallLoweringInfo *CLI, LoongArchCCAssignFn Fn)
const {
10042 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
10043 MVT ArgVT = Outs[i].VT;
10044 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
10048 CCInfo, IsRet, OrigTy)) {
10049 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type " << ArgVT
10068 Val = DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Val);
10090 if (In.isOrigArg()) {
10095 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
10096 (
BitWidth < 32 && In.Flags.isZExt())) {
10146 Register LoVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
10159 Register HiVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
10163 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
10177 Val = DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Val);
10189 if (LocVT == MVT::i32 || LocVT == MVT::i64) {
10193 LoongArch::R23, LoongArch::R24, LoongArch::R25,
10194 LoongArch::R26, LoongArch::R27, LoongArch::R28,
10195 LoongArch::R29, LoongArch::R30, LoongArch::R31};
10202 if (LocVT == MVT::f32) {
10205 static const MCPhysReg FPR32List[] = {LoongArch::F24, LoongArch::F25,
10206 LoongArch::F26, LoongArch::F27};
10213 if (LocVT == MVT::f64) {
10216 static const MCPhysReg FPR64List[] = {LoongArch::F28_64, LoongArch::F29_64,
10217 LoongArch::F30_64, LoongArch::F31_64};
10236 switch (CallConv) {
10248 "GHC calling convention requires the F and D extensions");
10253 MVT GRLenVT = Subtarget.getGRLenVT();
10254 unsigned GRLenInBytes = Subtarget.getGRLen() / 8;
10263 return CI->isMustTailCall();
10268 std::vector<SDValue> OutChains;
10277 analyzeInputArgs(MF, CCInfo, Ins,
false,
CC_LoongArch);
10279 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
10296 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
10305 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
10306 assert(ArgPartOffset == 0);
10307 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
10309 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
10333 int VaArgOffset, VarArgsSaveSize;
10337 if (ArgRegs.
size() == Idx) {
10339 VarArgsSaveSize = 0;
10341 VarArgsSaveSize = GRLenInBytes * (ArgRegs.
size() - Idx);
10342 VaArgOffset = -VarArgsSaveSize;
10348 LoongArchFI->setVarArgsFrameIndex(FI);
10356 VarArgsSaveSize += GRLenInBytes;
10361 for (
unsigned I = Idx;
I < ArgRegs.
size();
10362 ++
I, VaArgOffset += GRLenInBytes) {
10363 const Register Reg = RegInfo.createVirtualRegister(RC);
10364 RegInfo.addLiveIn(ArgRegs[
I], Reg);
10372 ->setValue((
Value *)
nullptr);
10373 OutChains.push_back(
Store);
10375 LoongArchFI->setVarArgsSaveSize(VarArgsSaveSize);
10380 if (!OutChains.empty()) {
10381 OutChains.push_back(Chain);
10396 if (
N->getNumValues() != 1)
10398 if (!
N->hasNUsesOfValue(1, 0))
10401 SDNode *Copy = *
N->user_begin();
10407 if (Copy->getGluedNode())
10411 bool HasRet =
false;
10413 if (
Node->getOpcode() != LoongArchISD::RET)
10421 Chain = Copy->getOperand(0);
10426bool LoongArchTargetLowering::isEligibleForTailCallOptimization(
10430 auto CalleeCC = CLI.CallConv;
10431 auto &Outs = CLI.Outs;
10433 auto CallerCC = Caller.getCallingConv();
10435 bool IsMustTail = CLI.CB && CLI.CB->isMustTailCall();
10444 for (
auto &Arg : Outs)
10445 if (Arg.Flags.isByVal())
10461 for (
auto &VA : ArgLocs)
10467 auto IsCallerStructRet = Caller.hasStructRetAttr();
10468 auto IsCalleeStructRet = Outs.empty() ?
false : Outs[0].Flags.isSRet();
10469 if (IsCallerStructRet || IsCalleeStructRet)
10474 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
10475 if (CalleeCC != CallerCC) {
10476 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
10477 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
10503 MVT GRLenVT = Subtarget.getGRLenVT();
10515 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
CC_LoongArch);
10519 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
10525 "site marked musttail");
10532 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
10534 if (!Flags.isByVal())
10538 unsigned Size = Flags.getByValSize();
10539 Align Alignment = Flags.getNonZeroByValAlign();
10546 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment, Alignment,
10548 false,
nullptr, std::nullopt,
10560 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
10563 SDValue ArgValue = OutVals[OutIdx];
10571 DAG.
getNode(LoongArchISD::SPLIT_PAIR_F64,
DL,
10572 DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
10584 if (!StackPtr.getNode())
10596 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
10610 unsigned CallArgIdx = Outs[OutIdx].OrigArgIndex;
10630 const Argument *FormalArg =
nullptr;
10631 unsigned FilteredIdx = 0;
10632 for (
const auto &CallArg : CLI.
CB->
args()) {
10633 if (CallArg->getType()->isEmptyTy())
10635 if (FilteredIdx == CallArgIdx) {
10644 unsigned FormalArgIdx = CallArgIdx;
10646 FormalArgIdx = FormalArg->
getArgNo();
10650 if (Arg.getType()->isEmptyTy())
10652 if (FilteredIdx == CallArgIdx) {
10653 FormalArgIdx = Arg.getArgNo();
10666 SDValue IncomingPtr = CopyOp;
10683 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
10684 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == CallArgIdx) {
10685 SDValue PartValue = OutVals[OutIdx + 1];
10686 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
10697 ArgValue = IncomingPtr;
10701 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == CallArgIdx) {
10713 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
10714 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
10715 assert(ArgPartOffset == 0);
10720 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
10721 SDValue PartValue = OutVals[OutIdx + 1];
10722 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
10734 DAG.
getStore(Chain,
DL, ArgValue, SpillSlot,
10736 for (
const auto &Part : Parts) {
10737 SDValue PartValue = Part.first;
10738 SDValue PartOffset = Part.second;
10745 ArgValue = SpillSlot;
10752 if (Flags.isByVal())
10753 ArgValue = ByValArgs[j++];
10761 "Tail call not allowed if stack is used for passing parameters");
10764 if (!StackPtr.getNode())
10777 if (!MemOpChains.
empty())
10783 for (
auto &Reg : RegsToPass) {
10784 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
10806 Ops.push_back(Chain);
10807 Ops.push_back(Callee);
10811 for (
auto &Reg : RegsToPass)
10812 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
10817 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
10818 assert(Mask &&
"Missing call preserved mask for calling convention");
10824 Ops.push_back(Glue);
10833 Op = IsTailCall ? LoongArchISD::TAIL : LoongArchISD::CALL;
10836 Op = IsTailCall ? LoongArchISD::TAIL_MEDIUM : LoongArchISD::CALL_MEDIUM;
10839 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
10840 Op = IsTailCall ? LoongArchISD::TAIL_LARGE : LoongArchISD::CALL_LARGE;
10862 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_LoongArch);
10865 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
10866 auto &VA = RVLocs[i];
10874 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
10875 assert(VA.needsCustom());
10880 RetValue = DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
10881 RetValue, RetValue2);
10894 const Type *RetTy)
const {
10896 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
10898 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
10902 Outs[i].Flags, CCInfo,
true,
nullptr))
10928 for (
unsigned i = 0, e = RVLocs.
size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
10929 SDValue Val = OutVals[OutIdx];
10938 DAG.
getVTList(MVT::i32, MVT::i32), Val);
10942 Register RegHi = RVLocs[++i].getLocReg();
10967 return DAG.
getNode(LoongArchISD::RET,
DL, MVT::Other, RetOps);
10975 const APInt &SplatValue,
const unsigned SplatBitSize)
const {
10976 uint64_t RequiredImm = 0;
10978 if (SplatBitSize == 16 && !(V & 0x00FF)) {
10980 RequiredImm = (0b10101 << 8) | (V >> 8);
10981 return {
true, RequiredImm};
10982 }
else if (SplatBitSize == 32) {
10984 if (!(V & 0xFFFF00FF)) {
10985 RequiredImm = (0b10001 << 8) | (V >> 8);
10986 return {
true, RequiredImm};
10989 if (!(V & 0xFF00FFFF)) {
10990 RequiredImm = (0b10010 << 8) | (V >> 16);
10991 return {
true, RequiredImm};
10994 if (!(V & 0x00FFFFFF)) {
10995 RequiredImm = (0b10011 << 8) | (V >> 24);
10996 return {
true, RequiredImm};
10999 if ((V & 0xFFFF00FF) == 0xFF) {
11000 RequiredImm = (0b10110 << 8) | (V >> 8);
11001 return {
true, RequiredImm};
11004 if ((V & 0xFF00FFFF) == 0xFFFF) {
11005 RequiredImm = (0b10111 << 8) | (V >> 16);
11006 return {
true, RequiredImm};
11009 if ((V & 0x7E07FFFF) == 0x3E000000 || (V & 0x7E07FFFF) == 0x40000000) {
11011 (0b11010 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
11012 return {
true, RequiredImm};
11014 }
else if (SplatBitSize == 64) {
11016 if ((V & 0xFFFFFFFF7E07FFFFULL) == 0x3E000000ULL ||
11017 (V & 0xFFFFFFFF7E07FFFFULL) == 0x40000000ULL) {
11019 (0b11011 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
11020 return {
true, RequiredImm};
11023 if ((V & 0x7FC0FFFFFFFFFFFFULL) == 0x4000000000000000ULL ||
11024 (V & 0x7FC0FFFFFFFFFFFFULL) == 0x3FC0000000000000ULL) {
11026 (0b11100 << 8) | (((V >> 56) & 0xC0) ^ 0x40) | ((V >> 48) & 0x3F);
11027 return {
true, RequiredImm};
11030 auto sameBitsPreByte = [](uint64_t x) -> std::pair<bool, uint8_t> {
11032 for (
int i = 0; i < 8; ++i) {
11034 if (
byte == 0 ||
byte == 0xFF)
11035 res |= ((
byte & 1) << i);
11040 return {
true, res};
11042 auto [IsSame, Suffix] = sameBitsPreByte(V);
11044 RequiredImm = (0b11001 << 8) | Suffix;
11045 return {
true, RequiredImm};
11048 return {
false, RequiredImm};
11053 if (!Subtarget.hasExtLSX())
11056 if (VT == MVT::f32) {
11057 uint64_t masked =
Imm.bitcastToAPInt().getZExtValue() & 0x7e07ffff;
11058 return (masked == 0x3e000000 || masked == 0x40000000);
11061 if (VT == MVT::f64) {
11062 uint64_t masked =
Imm.bitcastToAPInt().getZExtValue() & 0x7fc0ffffffffffff;
11063 return (masked == 0x3fc0000000000000 || masked == 0x4000000000000000);
11072bool LoongArchTargetLowering::shouldConvertFpToSat(
unsigned Op,
EVT FPVT,
11078 if (FPVT == MVT::f32)
11080 return FPVT == MVT::f64 && Subtarget.hasBasicD();
11084LoongArchTargetLowering::getFPImmAction(
const APFloat &
Imm,
EVT VT,
11085 bool ForCodeSize)
const {
11087 if (VT == MVT::f32 && !Subtarget.hasBasicF())
11089 if (VT == MVT::f64 && !Subtarget.hasBasicD())
11104bool LoongArchTargetLowering::shouldInsertFencesForAtomic(
11114 Type *Ty =
I->getOperand(0)->getType();
11116 unsigned Size = Ty->getIntegerBitWidth();
11136 unsigned MaxIntSize = Subtarget.is64Bit() ? 64 : 32;
11141 if (Subtarget.hasExtLASX())
11143 else if (Subtarget.hasExtLSX())
11150 EVT VT =
Y.getValueType();
11153 return Subtarget.hasExtLSX() && VT.
isInteger();
11164 case Intrinsic::loongarch_masked_atomicrmw_xchg_i32:
11165 case Intrinsic::loongarch_masked_atomicrmw_add_i32:
11166 case Intrinsic::loongarch_masked_atomicrmw_sub_i32:
11167 case Intrinsic::loongarch_masked_atomicrmw_nand_i32: {
11170 Info.memVT = MVT::i32;
11171 Info.ptrVal =
I.getArgOperand(0);
11173 Info.align =
Align(4);
11192 "Unable to expand");
11193 unsigned MinWordSize = 4;
11205 Value *AlignedAddr = Builder.CreateIntrinsic(
11206 Intrinsic::ptrmask, {PtrTy, IntTy},
11207 {Addr, ConstantInt::get(IntTy, ~(uint64_t)(MinWordSize - 1))},
nullptr,
11210 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
11211 Value *PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
11212 Value *ShiftAmt = Builder.CreateShl(PtrLSB, 3);
11213 ShiftAmt = Builder.CreateTrunc(ShiftAmt, WordType,
"ShiftAmt");
11214 Value *Mask = Builder.CreateShl(
11215 ConstantInt::get(WordType,
11216 (1 << (
DL.getTypeStoreSize(
ValueType) * 8)) - 1),
11218 Value *Inv_Mask = Builder.CreateNot(Mask,
"Inv_Mask");
11219 Value *ValOperand_Shifted =
11220 Builder.CreateShl(Builder.CreateZExt(AI->
getValOperand(), WordType),
11221 ShiftAmt,
"ValOperand_Shifted");
11224 NewOperand = Builder.CreateOr(ValOperand_Shifted, Inv_Mask,
"AndOperand");
11226 NewOperand = ValOperand_Shifted;
11229 Builder.CreateAtomicRMW(
Op, AlignedAddr, NewOperand,
Align(MinWordSize),
11232 Value *Shift = Builder.CreateLShr(NewAI, ShiftAmt,
"shifted");
11233 Value *Trunc = Builder.CreateTrunc(Shift,
ValueType,
"extracted");
11234 Value *FinalOldResult = Builder.CreateBitCast(Trunc,
ValueType);
11253 if (Subtarget.hasLAM_BH() && Subtarget.is64Bit() &&
11261 if (Subtarget.hasLAMCAS()) {
11283 return Intrinsic::loongarch_masked_atomicrmw_xchg_i64;
11285 return Intrinsic::loongarch_masked_atomicrmw_add_i64;
11287 return Intrinsic::loongarch_masked_atomicrmw_sub_i64;
11289 return Intrinsic::loongarch_masked_atomicrmw_nand_i64;
11291 return Intrinsic::loongarch_masked_atomicrmw_umax_i64;
11293 return Intrinsic::loongarch_masked_atomicrmw_umin_i64;
11295 return Intrinsic::loongarch_masked_atomicrmw_max_i64;
11297 return Intrinsic::loongarch_masked_atomicrmw_min_i64;
11307 return Intrinsic::loongarch_masked_atomicrmw_xchg_i32;
11309 return Intrinsic::loongarch_masked_atomicrmw_add_i32;
11311 return Intrinsic::loongarch_masked_atomicrmw_sub_i32;
11313 return Intrinsic::loongarch_masked_atomicrmw_nand_i32;
11315 return Intrinsic::loongarch_masked_atomicrmw_umax_i32;
11317 return Intrinsic::loongarch_masked_atomicrmw_umin_i32;
11319 return Intrinsic::loongarch_masked_atomicrmw_max_i32;
11321 return Intrinsic::loongarch_masked_atomicrmw_min_i32;
11333 if (Subtarget.hasLAMCAS())
11345 unsigned GRLen = Subtarget.getGRLen();
11347 Value *FailureOrdering =
11348 Builder.getIntN(Subtarget.getGRLen(),
static_cast<uint64_t
>(FailOrd));
11349 Intrinsic::ID CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i32;
11351 CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i64;
11352 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
11353 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
11354 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
11357 Value *Result = Builder.CreateIntrinsic(
11358 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, FailureOrdering});
11360 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
11376 Builder.CreateNot(Mask,
"Inv_Mask"),
11383 unsigned GRLen = Subtarget.getGRLen();
11385 Builder.getIntN(GRLen,
static_cast<uint64_t
>(AI->
getOrdering()));
11392 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
11393 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
11394 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
11407 unsigned ValWidth =
11410 Builder.CreateSub(Builder.getIntN(GRLen, GRLen - ValWidth), ShiftAmt);
11411 Result = Builder.CreateCall(LlwOpScwLoop,
11412 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
11415 Builder.CreateCall(LlwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
11419 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
11443 return LoongArch::R4;
11448 return LoongArch::R5;
11459 int RefinementSteps = VT.
getScalarType() == MVT::f64 ? 2 : 1;
11460 return RefinementSteps;
11465 assert(Subtarget.hasFrecipe() &&
11466 "Reciprocal estimate queried on unsupported target");
11477 return Subtarget.hasBasicD();
11481 return Subtarget.hasExtLSX();
11485 return Subtarget.hasExtLASX();
11494 int &RefinementSteps,
11495 bool &UseOneConstNR,
11496 bool Reciprocal)
const {
11498 "Enabled should never be Disabled here");
11500 if (!Subtarget.hasFrecipe())
11515 UseOneConstNR =
false;
11521 if (Reciprocal || RefinementSteps > 0)
11531 int &RefinementSteps)
const {
11533 "Enabled should never be Disabled here");
11535 if (!Subtarget.hasFrecipe())
11549 return DAG.
getNode(LoongArchISD::FRECIPE,
DL, VT, Operand);
11557LoongArchTargetLowering::getConstraintType(
StringRef Constraint)
const {
11577 if (Constraint.
size() == 1) {
11578 switch (Constraint[0]) {
11594 if (Constraint ==
"ZC" || Constraint ==
"ZB")
11603 return StringSwitch<InlineAsm::ConstraintCode>(ConstraintCode)
11610std::pair<unsigned, const TargetRegisterClass *>
11611LoongArchTargetLowering::getRegForInlineAsmConstraint(
11615 if (Constraint.
size() == 1) {
11616 switch (Constraint[0]) {
11621 return std::make_pair(0U, &LoongArch::GPRRegClass);
11623 return std::make_pair(0U, &LoongArch::GPRNoR0R1RegClass);
11625 if (Subtarget.hasBasicF() && VT == MVT::f32)
11626 return std::make_pair(0U, &LoongArch::FPR32RegClass);
11627 if (Subtarget.hasBasicD() && VT == MVT::f64)
11628 return std::make_pair(0U, &LoongArch::FPR64RegClass);
11629 if (Subtarget.hasExtLSX() &&
11630 TRI->isTypeLegalForClass(LoongArch::LSX128RegClass, VT))
11631 return std::make_pair(0U, &LoongArch::LSX128RegClass);
11632 if (Subtarget.hasExtLSX() && VT == MVT::i128)
11633 return std::make_pair(0U, &LoongArch::LSX128RegClass);
11634 if (Subtarget.hasExtLASX() &&
11635 TRI->isTypeLegalForClass(LoongArch::LASX256RegClass, VT))
11636 return std::make_pair(0U, &LoongArch::LASX256RegClass);
11656 bool IsFP = Constraint[2] ==
'f';
11657 std::pair<StringRef, StringRef> Temp = Constraint.
split(
'$');
11658 std::pair<unsigned, const TargetRegisterClass *>
R;
11663 unsigned RegNo =
R.first;
11664 if (LoongArch::F0 <= RegNo && RegNo <= LoongArch::F31) {
11665 if (Subtarget.hasBasicD() && (VT == MVT::f64 || VT == MVT::Other)) {
11666 unsigned DReg = RegNo - LoongArch::F0 + LoongArch::F0_64;
11667 return std::make_pair(DReg, &LoongArch::FPR64RegClass);
11677void LoongArchTargetLowering::LowerAsmOperandForConstraint(
11681 if (Constraint.
size() == 1) {
11682 switch (Constraint[0]) {
11689 Subtarget.getGRLenVT()));
11698 Subtarget.getGRLenVT()));
11704 if (
C->getZExtValue() == 0)
11724#define GET_REGISTER_MATCHER
11725#include "LoongArchGenAsmMatcher.inc"
11731 std::string NewRegName = Name.second.str();
11737 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
11738 if (!ReservedRegs.
test(Reg))
11755 const APInt &
Imm = ConstNode->getAPIntValue();
11757 if ((
Imm + 1).isPowerOf2() || (
Imm - 1).isPowerOf2() ||
11758 (1 -
Imm).isPowerOf2() || (-1 -
Imm).isPowerOf2())
11761 if (ConstNode->hasOneUse() &&
11762 ((
Imm - 2).isPowerOf2() || (
Imm - 4).isPowerOf2() ||
11763 (
Imm - 8).isPowerOf2() || (
Imm - 16).isPowerOf2()))
11769 if (ConstNode->hasOneUse() && !(
Imm.sge(-2048) &&
Imm.sle(4095))) {
11770 unsigned Shifts =
Imm.countr_zero();
11777 if (ImmPop == 3 || ImmPop == 5 || ImmPop == 9 || ImmPop == 17)
11781 APInt ImmSmall =
APInt(
Imm.getBitWidth(), 1ULL << Shifts,
true);
11782 if ((
Imm - ImmSmall).isPowerOf2() || (
Imm + ImmSmall).isPowerOf2() ||
11783 (ImmSmall -
Imm).isPowerOf2())
11793 Type *Ty,
unsigned AS,
11812 switch (AM.
Scale) {
11848 EVT MemVT = LD->getMemoryVT();
11849 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
11860 return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
11869 if (
Y.getValueType().isVector())
11881 Type *Ty,
bool IsSigned)
const {
11882 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
11891 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
11892 Type.getSizeInBits() < Subtarget.getGRLen()))
11902 Align &PrefAlign)
const {
11906 if (Subtarget.is64Bit()) {
11908 PrefAlign =
Align(8);
11911 PrefAlign =
Align(4);
11926bool LoongArchTargetLowering::splitValueIntoRegisterParts(
11928 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
11929 bool IsABIRegCopy = CC.has_value();
11932 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
11933 PartVT == MVT::f32) {
11948SDValue LoongArchTargetLowering::joinRegisterPartsIntoValue(
11950 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
11951 bool IsABIRegCopy = CC.has_value();
11953 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
11954 PartVT == MVT::f32) {
11955 SDValue Val = Parts[0];
11971 if (VT == MVT::f16 && Subtarget.hasBasicF())
11977unsigned LoongArchTargetLowering::getNumRegistersForCallingConv(
11980 if (VT == MVT::f16 && Subtarget.hasBasicF())
11989 unsigned Opc =
Op.getOpcode();
11994 case LoongArchISD::VANYNONZERO:
11995 case LoongArchISD::VALLZERO: {
11997 Known.Zero.setBitsFrom(1);
12000 case LoongArchISD::VALL_ZERO:
12001 case LoongArchISD::VANY_ZERO:
12002 case LoongArchISD::VALL_NONZERO:
12003 case LoongArchISD::VANY_NONZERO: {
12006 Known.Zero.setBitsFrom(1);
12009 case LoongArchISD::VPICK_ZEXT_ELT: {
12013 assert(
Known.getBitWidth() >= VTBits &&
"Unexpected width!");
12014 Known.Zero.setBitsFrom(VTBits);
12023 unsigned Depth)
const {
12024 EVT VT =
Op.getValueType();
12026 unsigned Opc =
Op.getOpcode();
12030 case LoongArchISD::CRC_W_B_W:
12031 case LoongArchISD::CRC_W_H_W:
12032 case LoongArchISD::CRCC_W_B_W:
12033 case LoongArchISD::CRCC_W_H_W: {
12035 APInt DemandedSrcBits =
12037 Opc == LoongArchISD::CRCC_W_B_W)
12041 OriginalDemandedElts, KnownSrc, TLO,
Depth + 1);
12043 case LoongArchISD::VMSKLTZ:
12044 case LoongArchISD::XVMSKLTZ: {
12046 MVT SrcVT = Src.getSimpleValueType();
12051 if (OriginalDemandedBits.
countr_zero() >= NumElts)
12055 APInt KnownUndef, KnownZero;
12071 if (KnownSrc.
One[SrcBits - 1])
12072 Known.One.setLowBits(NumElts);
12073 else if (KnownSrc.
Zero[SrcBits - 1])
12074 Known.Zero.setLowBits(NumElts);
12078 Src, DemandedSrcBits, DemandedElts, TLO.
DAG,
Depth + 1))
12085 Op, OriginalDemandedBits, OriginalDemandedElts,
Known, TLO,
Depth);
12109 unsigned Index)
const {
12120 unsigned Index)
const {
12124 return (EltVT == MVT::f32 || EltVT == MVT::f64) && Index == 0;
12139 Align StackAlign)
const {
12143 unsigned StackProbeSize =
12147 return StackProbeSize ? StackProbeSize : StackAlign.
value();
12151LoongArchTargetLowering::lowerDYNAMIC_STACKALLOC(
SDValue Op,
12165 const EVT VT =
Op.getValueType();
12176 Chain = DAG.
getNode(LoongArchISD::PROBED_ALLOCA, dl, MVT::Other, Chain, SP);
12186 const Register TargetReg =
MI.getOperand(0).getReg();
12189 const bool IsLA64 = Subtarget.is64Bit();
12190 const Align StackAlign = Subtarget.getFrameLowering()->getStackAlign();
12197 MF.
insert(MBBInsertPoint, LoopTestMBB);
12200 MF.
insert(MBBInsertPoint, ExitMBB);
12211 TII->get(IsLA64 ? LoongArch::SUB_D : LoongArch::SUB_W),
SPReg)
12217 TII->get(IsLA64 ? LoongArch::ST_D : LoongArch::ST_W))
12223 BuildMI(*LoopTestMBB, LoopTestMBB->
end(),
DL,
TII->get(LoongArch::BLTU))
12238 MBB->addSuccessor(LoopTestMBB);
12240 MI.eraseFromParent();
12242 return ExitMBB->
begin()->getParent();
static MCRegister MatchRegisterName(StringRef Name)
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 bool checkValueWidth(SDValue V, unsigned width, ISD::LoadExtType &ExtType)
static SDValue performORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue performANDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue performSELECT_CCCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
static SDValue performSETCCCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
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 uint64_t getConstant(const Value *IndexValue)
static SDValue getTargetNode(ConstantPoolSDNode *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, unsigned Flags)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val, const CCValAssign &VA, const SDLoc &DL)
static MachineBasicBlock * emitSelectPseudo(MachineInstr &MI, MachineBasicBlock *BB, unsigned Opcode)
static SDValue unpackFromRegLoc(const CSKYSubtarget &Subtarget, SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const SDLoc &DL)
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
static bool isSigned(unsigned Opcode)
const HexagonInstrInfo * TII
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static SDValue performINTRINSIC_WO_CHAINCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
const MCPhysReg ArgFPR32s[]
static SDValue lower128BitShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Dispatching routine to lower various 128-bit LoongArch vector shuffles.
static SDValue lowerVECTOR_SHUFFLE_XVSHUF4I(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVSHUF4I (if possible).
static SDValue lowerVECTOR_SHUFFLE_VPICKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPICKEV (if possible).
static SDValue combineSelectToBinOp(SDNode *N, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVPICKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPICKOD (if possible).
static SDValue unpackF64OnLA32DSoftABI(SelectionDAG &DAG, SDValue Chain, const CCValAssign &VA, const CCValAssign &HiVA, const SDLoc &DL)
static bool fitsRegularPattern(typename SmallVectorImpl< ValType >::const_iterator Begin, unsigned CheckStride, typename SmallVectorImpl< ValType >::const_iterator End, ValType ExpectedIndex, unsigned ExpectedIndexStride)
Determine whether a range fits a regular pattern of values.
static SDValue lowerVECTOR_SHUFFLE_IsReverse(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE whose result is the reversed source vector.
static SDValue PromoteMaskArithmetic(SDValue N, const SDLoc &DL, EVT VT, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned Depth)
static SDValue performUINT_TO_FPCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performHorizWideningCombine(SDNode *N, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static std::pair< SDValue, EVT > stripSignExtendInReg(SDValue V)
static SDValue emitIntrinsicErrorMessage(SDValue Op, StringRef ErrorMsg, SelectionDAG &DAG)
static SDValue ExtendSrcToDst(SDNode *N, SelectionDAG &DAG, unsigned ExtendOp)
static cl::opt< bool > ZeroDivCheck("loongarch-check-zero-division", cl::Hidden, cl::desc("Trap on integer division by zero."), cl::init(false))
static SDValue lowerVECTOR_SHUFFLE_XVPERMI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVPERMI (if possible).
static SDValue lowerVECTOR_SHUFFLE_VSHUF(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VSHUF.
static int getEstimateRefinementSteps(EVT VT, const LoongArchSubtarget &Subtarget)
static bool isSupportedReciprocalEstimateType(EVT VT, const LoongArchSubtarget &Subtarget)
static void emitErrorAndReplaceIntrinsicResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, StringRef ErrorMsg, bool WithChain=true)
static SDValue lowerVECTOR_SHUFFLEAsByteRotate(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE as byte rotate (if possible).
static SDValue checkIntrinsicImmArg(SDValue Op, unsigned ImmOp, SelectionDAG &DAG, bool IsSigned=false)
static SDValue performSUBCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVINSVE0(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVINSVE0 (if possible).
static SDValue performMOVFR2GR_SCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VILVH(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VILVH (if possible).
static SDValue performDemandedBitsCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI)
static bool CC_LoongArch(const DataLayout &DL, LoongArchABI::ABI ABI, unsigned ValNo, MVT ValVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsRet, Type *OrigTy)
static std::tuple< unsigned, SDValue, EVT > matchBinOpWithSharedOperand(SDValue BinV, SDValue X)
static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static Align getPrefTypeAlign(EVT VT, SelectionDAG &DAG)
static SDValue performSPLIT_PAIR_F64Combine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performBITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static MachineBasicBlock * emitSplitPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue lowerVectorBitSetImm(SDNode *Node, SelectionDAG &DAG)
static SDValue performSETCC_BITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performEXTENDCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_XVPACKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPACKOD (if possible).
static bool buildVPERMIInfo(ArrayRef< int > Mask, SDValue V1, SDValue V2, SmallVectorImpl< SDValue > &SrcVec, unsigned &MaskImm)
static std::optional< bool > matchSetCC(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue Val)
static SDValue combineAndNotIntoVANDN(SDNode *N, const SDLoc &DL, SelectionDAG &DAG)
Try to fold: (and (xor X, -1), Y) -> (vandn X, Y).
static SDValue lowerBUILD_VECTORAsBroadCastLoad(BuildVectorSDNode *BVOp, const SDLoc &DL, SelectionDAG &DAG)
#define CRC_CASE_EXT_BINARYOP(NAME, NODE)
static SDValue lowerVectorBitRevImm(SDNode *Node, SelectionDAG &DAG)
static bool checkBitcastSrcVectorSize(SDValue Src, unsigned Size, unsigned Depth)
static bool isConstantSplatVector(SDValue N, APInt &SplatValue, unsigned MinSizeInBits)
static SDValue lowerVECTOR_SHUFFLEAsShift(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, const APInt &Zeroable)
Lower VECTOR_SHUFFLE as shift (if possible).
static SDValue lowerVECTOR_SHUFFLE_VSHUF4I(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VSHUF4I (if possible).
static SDValue truncateVecElts(SDNode *Node, SelectionDAG &DAG)
static bool CC_LoongArch_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static MachineBasicBlock * insertDivByZeroTrap(MachineInstr &MI, MachineBasicBlock *MBB)
static SDValue customLegalizeToWOpWithSExt(SDNode *N, SelectionDAG &DAG)
static SDValue lowerVECTOR_SHUFFLE_VEXTRINS(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VEXTRINS (if possible).
static SDValue lowerVectorBitClear(SDNode *Node, SelectionDAG &DAG)
static SDValue performSELECTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VPACKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPACKEV (if possible).
static MachineBasicBlock * emitPseudoVMSKCOND(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue performSINT_TO_FPCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue performVANDNCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
Do target-specific dag combines on LoongArchISD::VANDN nodes.
static void replaceVPICKVE2GRResults(SDNode *Node, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned ResOp)
static SDValue lowerVECTOR_SHUFFLEAsZeroOrAnyExtend(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const APInt &Zeroable)
Lower VECTOR_SHUFFLE as ZERO_EXTEND Or ANY_EXTEND (if possible).
static SDValue legalizeIntrinsicImmArg(SDNode *Node, unsigned ImmOp, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, bool IsSigned=false)
static cl::opt< MaterializeFPImm > MaterializeFPImmInsNum("loongarch-materialize-float-imm", cl::Hidden, cl::desc("Maximum number of instructions used (including code sequence " "to generate the value and moving the value to FPR) when " "materializing floating-point immediates (default = 3)"), cl::init(MaterializeFPImm3Ins), cl::values(clEnumValN(NoMaterializeFPImm, "0", "Use constant pool"), clEnumValN(MaterializeFPImm2Ins, "2", "Materialize FP immediate within 2 instructions"), clEnumValN(MaterializeFPImm3Ins, "3", "Materialize FP immediate within 3 instructions"), clEnumValN(MaterializeFPImm4Ins, "4", "Materialize FP immediate within 4 instructions"), clEnumValN(MaterializeFPImm5Ins, "5", "Materialize FP immediate within 5 instructions"), clEnumValN(MaterializeFPImm6Ins, "6", "Materialize FP immediate within 6 instructions " "(behaves same as 5 on loongarch64)")))
static SDValue emitIntrinsicWithChainErrorMessage(SDValue Op, StringRef ErrorMsg, SelectionDAG &DAG)
static bool CC_LoongArchAssign2GRLen(unsigned GRLen, CCState &State, CCValAssign VA1, ISD::ArgFlagsTy ArgFlags1, unsigned ValNo2, MVT ValVT2, MVT LocVT2, ISD::ArgFlagsTy ArgFlags2)
static unsigned getLoongArchWOpcode(unsigned Opcode)
const MCPhysReg ArgFPR64s[]
static MachineBasicBlock * emitPseudoCTPOP(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue performMOVGR2FR_WCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
#define IOCSRWR_CASE(NAME, NODE)
#define CRC_CASE_EXT_UNARYOP(NAME, NODE)
static SDValue lowerVECTOR_SHUFFLE_VPACKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPACKOD (if possible).
static SDValue signExtendBitcastSrcVector(SelectionDAG &DAG, EVT SExtVT, SDValue Src, const SDLoc &DL)
static SDValue isNOT(SDValue V, SelectionDAG &DAG)
static SDValue lower256BitShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Dispatching routine to lower various 256-bit LoongArch vector shuffles.
static SDValue lowerVECTOR_SHUFFLE_VREPLVEI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VREPLVEI (if possible).
static MachineBasicBlock * emitPseudoXVINSGR2VR(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
const MCPhysReg PreserveNoneArgGPRs[]
static void fillVector(ArrayRef< SDValue > Ops, SelectionDAG &DAG, SDLoc DL, const LoongArchSubtarget &Subtarget, SDValue &Vector, EVT ResTy)
static SDValue fillSubVectorFromBuildVector(BuildVectorSDNode *Node, SelectionDAG &DAG, SDLoc DL, const LoongArchSubtarget &Subtarget, EVT ResTy, unsigned first)
static bool isSelectPseudo(MachineInstr &MI)
static SDValue foldVMskZeroTest(SDValue LHS, SDValue RHS, ISD::CondCode CC, const SDLoc &DL, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue foldBinOpIntoSelectIfProfitable(SDNode *BO, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue lowerVectorSplatImm(SDNode *Node, unsigned ImmOp, SelectionDAG &DAG, bool IsSigned=false)
const MCPhysReg ArgGPRs[]
static SDValue lowerVECTOR_SHUFFLE_XVPERM(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVPERM (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVILVL(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVILVL (if possible).
static SDValue performFP_TO_INTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLE_VPERMI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into VPERMI (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVEXTRINS(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVEXTRINS (if possible).
static SDValue customLegalizeToWOp(SDNode *N, SelectionDAG &DAG, int NumOp, unsigned ExtOpc=ISD::ANY_EXTEND)
static void replaceVecCondBranchResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget, unsigned ResOp)
#define ASRT_LE_GT_CASE(NAME)
static SDValue lowerVECTOR_SHUFFLE_XVPACKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPACKEV (if possible).
static SDValue matchDeinterleaveBuildVector(SDValue N, unsigned &StartIndex)
static SDValue performBR_CCCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static void computeZeroableShuffleElements(ArrayRef< int > Mask, SDValue V1, SDValue V2, APInt &KnownUndef, APInt &KnownZero)
Compute whether each element of a shuffle is zeroable.
static SDValue combineFP_ROUND(SDValue N, const SDLoc &DL, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static bool combine_CC(SDValue &LHS, SDValue &RHS, SDValue &CC, const SDLoc &DL, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue performCONCAT_VECTORSCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue widenShuffleMask(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
static MachineBasicBlock * emitVecCondBranchPseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static bool canonicalizeShuffleVectorByLane(const SDLoc &DL, MutableArrayRef< int > Mask, MVT VT, SDValue &V1, SDValue &V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Shuffle vectors by lane to generate more optimized instructions.
static SDValue lowerVECTOR_SHUFFLE_XVILVH(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVILVH (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVSHUF(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVSHUF (if possible).
static void replaceCMP_XCHG_128Results(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static SDValue lowerVectorPickVE2GR(SDNode *N, SelectionDAG &DAG, unsigned ResOp)
static SDValue performBITREV_WCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static SDValue matchHalfOf128BitLanes(SDValue N, bool isLow)
#define IOCSRRD_CASE(NAME, NODE)
static int matchShuffleAsByteRotate(MVT VT, SDValue &V1, SDValue &V2, ArrayRef< int > Mask)
Attempts to match vector shuffle as byte rotation.
static SDValue lowerVECTOR_SHUFFLE_XVREPLVE0(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVREPLVE0 (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVPICKEV(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into XVPICKEV (if possible).
static SDValue lowerVECTOR_SHUFFLE_XVREPLVEI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVREPLVEI (if possible).
static int matchShuffleAsShift(MVT &ShiftVT, unsigned &Opcode, unsigned ScalarSizeInBits, ArrayRef< int > Mask, int MaskOffset, const APInt &Zeroable)
Attempts to match a shuffle mask against the VBSLL, VBSRL, VSLLI and VSRLI instruction.
static SDValue lowerVECTOR_SHUFFLE_VILVL(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VILVL (if possible).
static SDValue lowerVectorBitClearImm(SDNode *Node, SelectionDAG &DAG)
static MachineBasicBlock * emitBuildPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const LoongArchSubtarget &Subtarget)
static SDValue lowerVECTOR_SHUFFLEAsLanePermuteAndShuffle(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE as lane permute and then shuffle (if possible).
static void replaceINTRINSIC_WO_CHAINResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
static SDValue MergeBlocksConvert(SDNode *N, SelectionDAG &DAG, unsigned Opcode, unsigned BlockBits)
static SDValue lowerVECTOR_SHUFFLE_VPICKOD(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SDValue V2, SelectionDAG &DAG)
Lower VECTOR_SHUFFLE into VPICKOD (if possible).
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 Register allocateArgGPR(CCState &State)
static bool isRepeatedShuffleMask(unsigned LaneSizeInBits, MVT VT, ArrayRef< int > Mask, SmallVectorImpl< int > &RepeatedMask)
Test whether a shuffle mask is equivalent within each sub-lane.
static SDValue convertRMEncoding(SelectionDAG &DAG, const SDLoc &DL, MVT GRLenVT, SDValue RMValue)
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static CodeModel::Model getCodeModel(const PPCSubtarget &S, const TargetMachine &TM, const MachineOperand &MO)
static constexpr MCPhysReg SPReg
const SmallVectorImpl< MachineOperand > & Cond
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
This file defines the SmallSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue, bool AllowSymbol=false)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static bool isSequentialOrUndefInRange(ArrayRef< int > Mask, unsigned Pos, unsigned Size, int Low, int Step=1)
Return true if every element in Mask, beginning from position Pos and ending in Pos + Size,...
LLVM_READONLY bool isOne() const
APInt bitcastToAPInt() const
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
uint64_t getZExtValue() const
Get zero extended value.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
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 isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
LLVM_ABI APInt urem(const APInt &RHS) const
Unsigned remainder operation.
unsigned getBitWidth() const
Return the number of bits in the APInt.
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.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)
Constructs an APInt value that has a contiguous range of bits set.
int64_t getSExtValue() const
Get sign extended value.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
This class represents an incoming formal argument to a Function.
unsigned getArgNo() const
Return the index of this formal argument in its containing function.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
An instruction that atomically checks whether a specified value is in a memory location,...
Value * getCompareOperand()
AtomicOrdering getFailureOrdering() const
Returns the failure ordering constraint of this cmpxchg instruction.
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.
Value * getPointerOperand()
bool isFloatingPointOperation() const
BinOp getOperation() const
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this rmw instruction.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this rmw instruction.
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
LLVM Basic Block Representation.
bool test(unsigned Idx) const
Returns true if bit Idx is set.
size_type count() const
Returns the number of bits which are set.
A "pseudo-class" with methods for operating on BUILD_VECTORs.
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.
static CCValAssign getPending(unsigned ValNo, MVT ValVT, MVT LocVT, LocInfo HTP, unsigned ExtraInfo=0)
Register getLocReg() const
LocInfo getLocInfo() const
static CCValAssign getReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP, bool IsCustom=false)
static CCValAssign getCustomReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP)
static CCValAssign getMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP, bool IsCustom=false)
int64_t getLocMemOffset() const
unsigned getValNo() const
static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP)
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.
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
This class represents a function call, abstracting a target machine's calling convention.
const APFloat & getValueAPF() const
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
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.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
iterator_range< arg_iterator > args()
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.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
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.
Common base class shared among various IRBuilders.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Class to represent integer types.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
ISD::LoadExtType getExtensionType() const
Return whether this is a plain node, or one of the varieties of value-extending loads.
LoongArchMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private Lo...
void setIncomingIndirectArg(unsigned ArgIndex, Register Reg)
void addSExt32Register(Register Reg)
Register getIncomingIndirectArg(unsigned ArgIndex) const
const LoongArchRegisterInfo * getRegisterInfo() const override
const LoongArchTargetLowering * getTargetLowering() const override
const LoongArchInstrInfo * getInstrInfo() const override
unsigned getGRLen() const
bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override
Return true if result of the specified node is used by a return node only.
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...
Register getExceptionPointerRegister(ExceptionHandling EH, const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
SDValue getSqrtEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps, bool &UseOneConstNR, bool Reciprocal) const override
Hooks for building estimates in place of slower divisions and square roots.
bool isLegalICmpImmediate(int64_t Imm) const override
Return true if the specified immediate is legal icmp immediate, that is the target has icmp instructi...
TargetLowering::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *CI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
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.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
std::pair< bool, uint64_t > isImmVLDILegalForMode1(const APInt &SplatValue, const unsigned SplatBitSize) const
Check if a constant splat can be generated using [x]vldi, where imm[12] is 1.
void getTgtMemIntrinsic(SmallVectorImpl< IntrinsicInfo > &Infos, const CallBase &I, MachineFunction &MF, unsigned Intrinsic) const override
Given an intrinsic, checks if on the target the intrinsic will need to map to a MemIntrinsicNode (tou...
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.
bool hasInlineStackProbe(const MachineFunction &MF) const override
True if stack clash protection is enabled for this function.
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
Register getExceptionSelectorRegister(ExceptionHandling EH, const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
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 isExtractVecEltCheap(EVT VT, unsigned Index) const override
Return true if extraction of a scalar element from the given vector type at the given index is cheap.
LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Return the preferred vector type legalization action.
bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override
Return true if sign-extension from FromTy to ToTy is cheaper than zero-extension.
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const override
Determine if the target supports unaligned memory accesses.
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
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 shouldAlignPointerArgs(CallInst *CI, unsigned &MinSize, Align &PrefAlign) const override
Return true if the pointer arguments to CI should be aligned by aligning the object whose address is ...
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 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...
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 signExtendConstant(const ConstantInt *CI) const override
Return true if this constant should be sign extended when promoting to a larger type.
ExtractSubvectorCost getExtractSubvectorCost(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return the cost of extracting a subvector of type ResVT from a vector of type SrcVT,...
TargetLowering::AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
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 isCheapToSpeculateCttz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic cttz.
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...
MachineBasicBlock * emitDynamicProbedAlloc(MachineInstr &MI, MachineBasicBlock *MBB) const
bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const override
Returns true if arguments should be sign-extended in lib calls.
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 isFPImmVLDILegal(const APFloat &Imm, EVT VT) const
bool shouldExtendTypeInLibCall(EVT Type) const override
Returns true if arguments should be extended in lib calls.
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Return the register ID of the name passed in.
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...
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
unsigned getStackProbeSize(const MachineFunction &MF, Align StackAlign) const
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 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.
void emitExpandAtomicRMW(AtomicRMWInst *AI) const override
Perform a atomicrmw expansion using a target-specific way.
ISD::NodeType getExtendForAtomicCmpSwapArg() const override
Returns how the platform's atomic compare and swap expects its comparison value to be extended (ZERO_...
LoongArchTargetLowering(const TargetMachine &TM, const LoongArchSubtarget &STI)
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 hasAndNotCompare(SDValue Y) const override
Return true if the target should transform: (X & Y) == Y ---> (~X & Y) == 0 (X & Y) !...
SDValue getRecipEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps) const override
Return a reciprocal estimate value for the input operand.
bool canMergeStoresTo(unsigned AddressSpace, EVT MemVT, const MachineFunction &MF) const override
Returns if it's reasonable to merge stores to MemVT size.
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...
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,...
bool mayBeEmittedAsTailCall(const CallInst *CI) const override
Return true if the target may be able emit the call instruction as a tail call.
Wrapper class representing physical registers. Should be passed by value.
bool hasFeature(unsigned Feature) const
static MVT getFloatingPointVT(unsigned BitWidth)
bool is128BitVector() const
Return true if this is a 128-bit vector type.
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
static auto fixedlen_vector_valuetypes()
bool is256BitVector() const
Return true if this is a 256-bit vector type.
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.
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.
MVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
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.
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.
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...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
bool isImplicitDef() const
LLVM_ABI void collectDebugValues(SmallVectorImpl< MachineInstr * > &DbgValues)
Scan instructions immediately following MI and collect any matching DBG_VALUEs.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
A description of a memory reference used in the backend.
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.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
void setIsKill(bool Val=true)
void setIsUndef(bool Val=true)
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 LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
const MachinePointerInfo & getPointerInfo() const
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
Class to represent pointers.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
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.
LLVM_ABI bool isOnlyUserOf(const SDNode *N) const
Return true if this node is the only use of N.
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.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
bool isUndef() const
Returns true if the node type is UNDEF or POISON.
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, in exactly one operand.
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
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
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue FoldSetCC(EVT VT, SDValue N1, SDValue N2, ISD::CondCode Cond, const SDLoc &dl, SDNodeFlags Flags={})
Constant fold a setcc to true or false.
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 getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
bool isSafeToSpeculativelyExecute(unsigned Opcode) const
Some opcodes may create immediate undefined behavior when used with some values (integer division-by-...
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)
SDValue getInsertSubvector(const SDLoc &DL, SDValue Vec, SDValue SubVec, unsigned Idx)
Insert SubVec at the Idx element of Vec.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false, SDNodeFlags Flags={})
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align DstAlign, Align SrcAlign, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
const TargetLowering & getTargetLoweringInfo() const
static constexpr unsigned MaxRecursionDepth
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).
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
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Helper function to build ISD::STORE nodes.
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.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getCommutedVectorShuffle(const ShuffleVectorSDNode &SV)
Returns an ISD::VECTOR_SHUFFLE node semantically equivalent to the shuffle node in input but with swa...
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 MMOMetadata &Metadata=MMOMetadata())
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 getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
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.
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDValue > Ops, SDNodeFlags Flags=SDNodeFlags())
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
LLVM_ABI SDValue WidenVector(const SDValue &N, const SDLoc &DL)
Widen the vector up to the next power of two using INSERT_SUBVECTOR.
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
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.
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.
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)
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
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.
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.
static LLVM_ABI bool isZeroEltSplatMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses all elements with the same value as the first element of exa...
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.
ArrayRef< int > getMask() const
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...
void assign(size_type NumElts, ValueParamT Elt)
void reserve(size_type N)
typename SuperClass::const_iterator const_iterator
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr size_t size() const
Get the string size.
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...
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.
const TargetMachine & getTargetMachine() const
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain targets require unusual breakdowns of certain types.
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...
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
void setMaxBytesForAlignment(unsigned MaxBytes)
bool isOperationLegalOrPromote(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal using promotion.
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
virtual TargetLoweringBase::LegalizeTypeAction getPreferredVectorAction(MVT VT) const
Return the preferred vector type legalization action.
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
virtual EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const
For types supported by the target, this is an identity function.
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.
ExtractSubvectorCost
Enum that specifies how expensive lowering an EXTRACT_SUBVECTOR is.
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.
FPImmAction
How the legalizer should materialize a floating-point immediate.
@ ConstantPool
Load the immediate from the constant pool.
@ Legal
The target can instruction select the immediate natively.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrOneBooleanContent
@ ZeroOrNegativeOneBooleanContent
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
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...
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 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...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedEltMask, APInt &KnownUndef, APInt &KnownZero, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Vector Op.
virtual InlineAsm::ConstraintCode getInlineAsmMemConstraint(StringRef ConstraintCode) const
SDValue SimplifyMultipleUseDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, SelectionDAG &DAG, unsigned Depth=0) const
More limited version of SimplifyDemandedBits that can be used to "lookthrough" ops that don't contrib...
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
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 void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::LibcallImpl LibcallImpl, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
Primary interface to the complete machine description for the target machine.
bool useTLSDESC() const
Returns true if this target uses TLS Descriptors.
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
bool shouldAssumeDSOLocal(const GlobalValue *GV) const
CodeModel::Model getCodeModel() const
Returns the code model.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetInstrInfo * getInstrInfo() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
This class is used to represent EVT's, which are used to parameterize some operations.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
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.
@ PreserveMost
Used for runtime calls that preserves most registers.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ Fast
Attempts to make calls as fast as possible (e.g.
@ PreserveNone
Used for runtime calls that preserves none general registers.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI bool isConstantSplatVectorAllOnes(const SDNode *N, bool BuildVectorOnly=false)
Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where all of the elements are ~0 ...
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ STACKRESTORE
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain.
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ POISON
POISON - A poison node.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ 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.
@ MEMBARRIER
MEMBARRIER - Compiler barrier only; generate a no-op.
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
@ SIGN_EXTEND_VECTOR_INREG
SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register sign-extension of the low ...
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ SET_ROUNDING
Set rounding mode.
@ SIGN_EXTEND
Conversion operators.
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ PREFETCH
PREFETCH - This corresponds to a prefetch intrinsic.
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ BR_JT
BR_JT - Jumptable branch.
@ 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.
@ VACOPY
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer,...
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ GET_ROUNDING
Returns current rounding mode: -1 Undefined 0 Round to 0 1 Round to nearest, ties to even 2 Round to ...
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ 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.
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Same as FMINNUM/FMAXNUM, except that a signaling NaN operand deterministi...
@ READ_REGISTER
READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on the DAG, which implements the n...
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ DEBUGTRAP
DEBUGTRAP - Trap intended to get the attention of a debugger.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ FMINNUM
FMINNUM/FMAXNUM - Same semantics as the llvm.minnum/maxnum intrinsics.
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ EH_DWARF_CFA
EH_DWARF_CFA - This node represents the pointer to the DWARF Canonical Frame Address (CFA),...
@ BF16_TO_FP
BF16_TO_FP, FP_TO_BF16 - These operators are used to perform promotions and truncation for bfloat16.
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ TRAP
TRAP - Trapping instruction.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
@ FREEZE
FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or is evaluated to UNDEF),...
@ 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.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
@ BRCOND
BRCOND - Conditional branch.
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ 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,...
bool isExtVecInRegOpcode(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.
bool isBitwiseLogicOp(unsigned Opcode)
Whether this is bitwise logic opcode.
LLVM_ABI bool isFreezeUndef(const SDNode *N)
Return true if the specified node is FREEZE(UNDEF).
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
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.
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).
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 * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
ABI getTargetABI(StringRef ABIName)
InstSeq generateInstSeq(int64_t Val)
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* 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.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
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.
@ Known
Known to have no common set bits.
@ Undef
Value of the register doesn't matter.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
bool isIntOrFPConstant(SDValue V)
Return true if V is either a integer or FP constant.
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
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...
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
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.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
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...
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
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...
AtomicOrdering
Atomic ordering for LLVM's memory model.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
@ Fast
Assign the register banks as fast as possible (default).
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr bool isShiftedInt(int64_t x)
Checks if a signed integer is an N bit number shifted left by S.
constexpr unsigned BitWidth
std::string join_items(Sep Separator, Args &&... Items)
Joins the strings in the parameter pack Items, adding Separator between the elements....
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
@ End
Run the machine verifier once, at the end of the pipeline.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
MCRegisterClass TargetRegisterClass
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
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.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
uint64_t getScalarSizeInBits() const
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
static EVT getFloatingPointVT(unsigned BitWidth)
Returns the EVT that represents a floating-point type with the given number of bits.
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 is256BitVector() const
Return true if this is a 256-bit vector type.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
bool isInteger() const
Return true if this is an integer or a vector integer type.
Align getNonZeroOrigAlign() const
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 getUnknownStack(MachineFunction &MF)
Stack memory without other information.
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.
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
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
bool isBeforeLegalizeOps() 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)