32#include "llvm/IR/IntrinsicsLoongArch.h"
42#define DEBUG_TYPE "loongarch-isel-lowering"
57 cl::desc(
"Maximum number of instructions used (including code sequence "
58 "to generate the value and moving the value to FPR) when "
59 "materializing floating-point immediates (default = 3)"),
63 "Materialize FP immediate within 2 instructions"),
65 "Materialize FP immediate within 3 instructions"),
67 "Materialize FP immediate within 4 instructions"),
69 "Materialize FP immediate within 5 instructions"),
71 "Materialize FP immediate within 6 instructions "
72 "(behaves same as 5 on loongarch64)")));
75 cl::desc(
"Trap on integer division by zero."),
82 MVT GRLenVT = Subtarget.getGRLenVT();
87 if (Subtarget.hasBasicF())
89 if (Subtarget.hasBasicD())
93 MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64, MVT::v4f32, MVT::v2f64};
95 MVT::v32i8, MVT::v16i16, MVT::v8i32, MVT::v4i64, MVT::v8f32, MVT::v4f64};
97 if (Subtarget.hasExtLSX())
101 if (Subtarget.hasExtLASX())
102 for (
MVT VT : LASXVTs)
170 if (Subtarget.is64Bit()) {
198 if (!Subtarget.is64Bit()) {
204 if (Subtarget.hasBasicD())
216 if (Subtarget.hasBasicF()) {
248 if (Subtarget.is64Bit())
251 if (!Subtarget.hasBasicD()) {
253 if (Subtarget.is64Bit()) {
262 if (Subtarget.hasBasicD()) {
295 if (Subtarget.is64Bit())
301 if (Subtarget.hasExtLSX()) {
316 for (
MVT VT : LSXVTs) {
330 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64}) {
358 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
360 for (
MVT VT : {MVT::v8i16, MVT::v4i32, MVT::v2i64})
362 for (
MVT VT : {MVT::v4i32, MVT::v2i64}) {
366 for (
MVT VT : {MVT::v4f32, MVT::v2f64}) {
390 {MVT::v16i8, MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v8i16, MVT::v4i16,
391 MVT::v2i16, MVT::v4i32, MVT::v2i32, MVT::v2i64}) {
410 if (Subtarget.hasExtLASX()) {
411 for (
MVT VT : LASXVTs) {
426 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16, MVT::v32i8}) {
455 for (
MVT VT : {MVT::v32i8, MVT::v16i16, MVT::v8i32})
457 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64})
459 for (
MVT VT : {MVT::v8i32, MVT::v4i32, MVT::v4i64}) {
463 for (
MVT VT : {MVT::v8f32, MVT::v4f64}) {
482 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16}) {
487 {MVT::v2i64, MVT::v4i32, MVT::v4i64, MVT::v8i16, MVT::v8i32}) {
494 if (Subtarget.hasBasicF()) {
505 if (Subtarget.hasExtLSX()) {
513 if (Subtarget.hasExtLASX()) {
540 if (Subtarget.hasLAMCAS())
543 if (Subtarget.hasSCQ()) {
563 switch (
Op.getOpcode()) {
565 return lowerATOMIC_FENCE(
Op, DAG);
567 return lowerEH_DWARF_CFA(
Op, DAG);
569 return lowerGlobalAddress(
Op, DAG);
571 return lowerGlobalTLSAddress(
Op, DAG);
573 return lowerINTRINSIC_WO_CHAIN(
Op, DAG);
575 return lowerINTRINSIC_W_CHAIN(
Op, DAG);
577 return lowerINTRINSIC_VOID(
Op, DAG);
579 return lowerBlockAddress(
Op, DAG);
581 return lowerJumpTable(
Op, DAG);
583 return lowerShiftLeftParts(
Op, DAG);
585 return lowerShiftRightParts(
Op, DAG,
true);
587 return lowerShiftRightParts(
Op, DAG,
false);
589 return lowerConstantPool(
Op, DAG);
591 return lowerFP_TO_SINT(
Op, DAG);
593 return lowerBITCAST(
Op, DAG);
595 return lowerUINT_TO_FP(
Op, DAG);
597 return lowerSINT_TO_FP(
Op, DAG);
599 return lowerVASTART(
Op, DAG);
601 return lowerFRAMEADDR(
Op, DAG);
603 return lowerRETURNADDR(
Op, DAG);
605 return lowerWRITE_REGISTER(
Op, DAG);
607 return lowerINSERT_VECTOR_ELT(
Op, DAG);
609 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
611 return lowerBUILD_VECTOR(
Op, DAG);
613 return lowerCONCAT_VECTORS(
Op, DAG);
615 return lowerVECTOR_SHUFFLE(
Op, DAG);
617 return lowerBITREVERSE(
Op, DAG);
619 return lowerSCALAR_TO_VECTOR(
Op, DAG);
621 return lowerPREFETCH(
Op, DAG);
623 return lowerSELECT(
Op, DAG);
625 return lowerBRCOND(
Op, DAG);
627 return lowerFP_TO_FP16(
Op, DAG);
629 return lowerFP16_TO_FP(
Op, DAG);
631 return lowerFP_TO_BF16(
Op, DAG);
633 return lowerBF16_TO_FP(
Op, DAG);
635 return lowerVECREDUCE_ADD(
Op, DAG);
638 return lowerRotate(
Op, DAG);
646 return lowerVECREDUCE(
Op, DAG);
648 return lowerConstantFP(
Op, DAG);
650 return lowerSETCC(
Op, DAG);
652 return lowerFP_ROUND(
Op, DAG);
654 return lowerFP_EXTEND(
Op, DAG);
663 EVT VT = V.getValueType();
669 return V.getOperand(0);
673 (
isNullConstant(V.getOperand(1)) || V.getOperand(0).hasOneUse())) {
675 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
685 if (!V->isOnlyUserOf(SplatValue.getNode()))
689 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
697 V.getOperand(0).hasOneUse() && V.getOperand(1).hasOneUse()) {
725 (
N->getOpcode() == LoongArchISD::VPACKEV) ||
726 (
N->getOpcode() == LoongArchISD::VPERMI)) &&
733 if (Opcode0 != Opcode1)
736 if (Opcode0 !=
ISD::FP_ROUND && Opcode0 != LoongArchISD::VFCVT)
743 EVT VT =
N.getValueType();
757 if (Subtarget.hasExtLASX() && VT.
is256BitVector() && SVT0 == MVT::v4f32 &&
758 SSVT0 == MVT::v4f64) {
777 if ((
N->getOpcode() == LoongArchISD::VPACKEV ||
778 N->getOpcode() == LoongArchISD::VPERMI) &&
779 Opcode0 == LoongArchISD::VFCVT) {
784 if (!Subtarget.hasExtLSX() || SVT0 != MVT::v4f32 || SSVT0 != MVT::v2f64)
787 if (
N->getOpcode() == LoongArchISD::VPACKEV &&
788 (VT == MVT::v2i64 || VT == MVT::v2f64)) {
794 if (
N->getOpcode() == LoongArchISD::VPERMI && VT == MVT::v4f32) {
810 MVT VT =
Op.getSimpleValueType();
811 MVT SVT =
In.getSimpleValueType();
813 if (VT == MVT::v4f32 && SVT == MVT::v4f64) {
826 EVT VT =
Op.getValueType();
828 EVT SVT = Src.getValueType();
831 VT == MVT::v2f64 && SVT == MVT::v2f32 && Subtarget.hasExtLSX();
833 VT == MVT::v4f64 && SVT == MVT::v4f32 && Subtarget.hasExtLASX();
834 if (!V2F32ToV2F64 && !V4F32ToV4F64)
846 const uint64_t
Imm =
Op.getConstantOperandVal(1);
861 if (
SDValue V = CheckVecHighPart(Src)) {
863 "Unexpected wide vector");
864 Opcode = LoongArchISD::VFCVTH;
867 Opcode = LoongArchISD::VFCVTL;
869 DAG.
getUNDEF(WideOpVT), Src, ZeroIdx);
874 return DAG.
getNode(Opcode,
DL, VT, VFCVTOp);
880 SmallVector<int, 8>
Mask = {0, 1, 4, 5, 2, 3, 6, 7};
892 EVT VT =
Op.getValueType();
897 assert((VT == MVT::f32 && Subtarget.hasBasicF()) ||
898 (VT == MVT::f64 && Subtarget.hasBasicD()));
915 int InsNum = Seq.size() + ((VT == MVT::f64 && !Subtarget.is64Bit()) ? 2 : 1);
925 if (Subtarget.is64Bit())
927 return DAG.
getNode(Subtarget.is64Bit() ? LoongArchISD::MOVGR2FR_W_LA64
928 : LoongArchISD::MOVGR2FR_W,
932 if (Subtarget.is64Bit()) {
934 return DAG.
getNode(LoongArchISD::MOVGR2FR_D,
DL, VT, NewVal);
938 return DAG.
getNode(LoongArchISD::MOVGR2FR_D_LO_HI,
DL, VT,
Lo,
Hi);
950 EVT ResultVT =
Op.getValueType();
951 EVT OperandVT =
Op.getOperand(0).getValueType();
956 if (ResultVT == SetCCResultVT)
959 assert(
Op.getOperand(0).getValueType() ==
Op.getOperand(1).getValueType() &&
960 "SETCC operands must have the same type!");
964 Op.getOperand(1),
Op.getOperand(2));
966 if (ResultVT.
bitsGT(SetCCResultVT))
968 else if (ResultVT.
bitsLT(SetCCResultVT))
986 MVT OpVT =
Op.getSimpleValueType();
993 unsigned LegalVecSize = 128;
994 bool isLASX256Vector =
1004 if (isLASX256Vector) {
1009 for (
unsigned i = 1; i < NumEles; i *= 2, EleBits *= 2) {
1012 Val = DAG.
getNode(LoongArchISD::VHADDW,
DL, VecTy, Val, Val);
1015 if (isLASX256Vector) {
1041 MVT OpVT =
Op.getSimpleValueType();
1054 MVT GRLenVT = Subtarget.getGRLenVT();
1056 for (
int i = NumEles; i > 1; i /= 2) {
1059 Val = DAG.
getNode(Opcode,
DL, VecTy, Tmp, Val);
1068 unsigned IsData =
Op.getConstantOperandVal(4);
1073 return Op.getOperand(0);
1080 MVT VT =
Op.getSimpleValueType();
1086 unsigned Opcode =
Op.getOpcode();
1089 auto checkCstSplat = [](
SDValue V, APInt &CstSplatValue) {
1095 CstSplatValue =
C->getAPIntValue();
1103 APInt CstSplatValue;
1104 bool IsCstSplat = checkCstSplat(Amt, CstSplatValue);
1108 if (IsCstSplat && CstSplatValue.
urem(EltSizeInBits) == 0)
1124 return DAG.
getNode(Opcode,
DL, VT, R, Urem);
1140 if (
LHS == LHS2 &&
RHS == RHS2) {
1145 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
1153 return std::nullopt;
1161 MVT VT =
N->getSimpleValueType(0);
1192 if (~TrueVal == FalseVal) {
1232 unsigned SelOpNo = 0;
1242 unsigned ConstSelOpNo = 1;
1243 unsigned OtherSelOpNo = 2;
1250 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
1255 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
1261 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
1263 std::swap(NewConstOps[0], NewConstOps[1]);
1275 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
1277 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
1280 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
1281 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
1301 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
1315 int64_t
C = RHSC->getSExtValue();
1358 MVT VT =
Op.getSimpleValueType();
1359 MVT GRLenVT = Subtarget.getGRLenVT();
1364 if (
Op.hasOneUse()) {
1365 unsigned UseOpc =
Op->user_begin()->getOpcode();
1367 SDNode *BinOp = *
Op->user_begin();
1374 return lowerSELECT(NewSel, DAG);
1391 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1414 if (TrueVal - 1 == FalseVal)
1416 if (TrueVal + 1 == FalseVal)
1423 RHS == TrueV &&
LHS == FalseV) {
1448 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1455 MVT GRLenVT = Subtarget.getGRLenVT();
1466 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1467 Op.getOperand(0),
LHS,
RHS, TargetCC,
1470 return DAG.
getNode(LoongArchISD::BRCOND,
DL,
Op.getValueType(),
1471 Op.getOperand(0), CondV,
Op.getOperand(2));
1475 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1481LoongArchTargetLowering::lowerSCALAR_TO_VECTOR(
SDValue Op,
1484 MVT OpVT =
Op.getSimpleValueType();
1495 EVT ResTy =
Op->getValueType(0);
1500 if (!Subtarget.is64Bit() && (ResTy == MVT::v16i8 || ResTy == MVT::v32i8))
1510 for (
unsigned int i = 0; i < NewEltNum; i++) {
1513 unsigned RevOp = (ResTy == MVT::v16i8 || ResTy == MVT::v32i8)
1514 ? (
unsigned)LoongArchISD::BITREV_8B
1532 for (
unsigned int i = 0; i < NewEltNum; i++)
1533 for (
int j = OrigEltNum / NewEltNum - 1;
j >= 0;
j--)
1534 Mask.push_back(j + (OrigEltNum / NewEltNum) * i);
1552 if (EltBits > 32 || EltBits == 1)
1580 int MaskOffset,
const APInt &Zeroable) {
1581 int Size = Mask.size();
1582 unsigned SizeInBits =
Size * ScalarSizeInBits;
1584 auto CheckZeros = [&](
int Shift,
int Scale,
bool Left) {
1585 for (
int i = 0; i <
Size; i += Scale)
1586 for (
int j = 0; j < Shift; ++j)
1587 if (!Zeroable[i + j + (
Left ? 0 : (Scale - Shift))])
1595 for (
unsigned i = Pos, e = Pos +
Size; i != e; ++i,
Low += Step)
1596 if (!(Mask[i] == -1 || Mask[i] ==
Low))
1601 auto MatchShift = [&](
int Shift,
int Scale,
bool Left) {
1602 for (
int i = 0; i !=
Size; i += Scale) {
1603 unsigned Pos =
Left ? i + Shift : i;
1604 unsigned Low =
Left ? i : i + Shift;
1605 unsigned Len = Scale - Shift;
1610 int ShiftEltBits = ScalarSizeInBits * Scale;
1611 bool ByteShift = ShiftEltBits > 64;
1612 Opcode =
Left ? (ByteShift ? LoongArchISD::VBSLL : LoongArchISD::VSLLI)
1613 : (ByteShift ? LoongArchISD::VBSRL : LoongArchISD::VSRLI);
1614 int ShiftAmt = Shift * ScalarSizeInBits / (ByteShift ? 8 : 1);
1618 Scale = ByteShift ? Scale / 2 : Scale;
1624 return (
int)ShiftAmt;
1627 unsigned MaxWidth = 128;
1628 for (
int Scale = 2; Scale * ScalarSizeInBits <= MaxWidth; Scale *= 2)
1629 for (
int Shift = 1; Shift != Scale; ++Shift)
1630 for (
bool Left : {
true,
false})
1631 if (CheckZeros(Shift, Scale,
Left)) {
1632 int ShiftAmt = MatchShift(Shift, Scale,
Left);
1657 const APInt &Zeroable) {
1658 int Size = Mask.size();
1672 Mask,
Size, Zeroable);
1680 "Illegal integer vector type");
1689template <
typename ValType>
1692 unsigned CheckStride,
1694 ValType ExpectedIndex,
unsigned ExpectedIndexStride) {
1698 if (*
I != -1 && *
I != ExpectedIndex)
1700 ExpectedIndex += ExpectedIndexStride;
1704 for (
unsigned n = 0; n < CheckStride &&
I != End; ++n, ++
I)
1716 int Size = Mask.size();
1726 int ScalarSizeInBits = VectorSizeInBits /
Size;
1727 assert(!(VectorSizeInBits % ScalarSizeInBits) &&
"Illegal shuffle mask size");
1728 (void)ScalarSizeInBits;
1730 for (
int i = 0; i <
Size; ++i) {
1736 if ((M >= 0 && M <
Size && V1IsZero) || (M >=
Size && V2IsZero)) {
1753 RepeatedMask.
assign(LaneSize, -1);
1754 int Size = Mask.size();
1755 for (
int i = 0; i <
Size; ++i) {
1756 assert(Mask[i] == -1 || Mask[i] >= 0);
1759 if ((Mask[i] %
Size) / LaneSize != i / LaneSize)
1766 Mask[i] <
Size ? Mask[i] % LaneSize : Mask[i] % LaneSize + LaneSize;
1767 if (RepeatedMask[i % LaneSize] < 0)
1769 RepeatedMask[i % LaneSize] = LocalM;
1770 else if (RepeatedMask[i % LaneSize] != LocalM)
1787 int NumElts = RepeatedMask.
size();
1789 int Scale = 16 / NumElts;
1791 for (
int i = 0; i < NumElts; ++i) {
1792 int M = RepeatedMask[i];
1793 assert((M == -1 || (0 <= M && M < (2 * NumElts))) &&
1794 "Unexpected mask index.");
1799 int StartIdx = i - (M % NumElts);
1806 int CandidateRotation = StartIdx < 0 ? -StartIdx : NumElts - StartIdx;
1809 Rotation = CandidateRotation;
1810 else if (Rotation != CandidateRotation)
1814 SDValue MaskV = M < NumElts ? V1 : V2;
1825 else if (TargetV != MaskV)
1830 assert(Rotation != 0 &&
"Failed to locate a viable rotation!");
1831 assert((
Lo ||
Hi) &&
"Failed to find a rotated input vector!");
1840 return Rotation * Scale;
1859 if (ByteRotation <= 0)
1866 int LoByteShift = 16 - ByteRotation;
1867 int HiByteShift = ByteRotation;
1890 const APInt &Zeroable) {
1904 for (
int i = 0; i < NumElements; i++) {
1908 if (i % Scale != 0) {
1919 SDValue V = M < NumElements ? V1 : V2;
1920 M = M % NumElements;
1923 Offset = M - (i / Scale);
1926 if (
Offset % (NumElements / Scale))
1928 }
else if (InputV != V)
1931 if (M != (
Offset + (i / Scale)))
1941 unsigned VilVLoHi = LoongArchISD::VILVL;
1942 if (
Offset >= (NumElements / 2)) {
1943 VilVLoHi = LoongArchISD::VILVH;
1944 Offset -= (NumElements / 2);
1951 InputV = DAG.
getNode(VilVLoHi,
DL, InputVT, Ext, InputV);
1955 }
while (Scale > 1);
1961 for (
int NumExtElements = Bits / 64; NumExtElements < NumElements;
1962 NumExtElements *= 2) {
1982 int SplatIndex = -1;
1983 for (
const auto &M : Mask) {
1990 if (SplatIndex == -1)
1993 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
1995 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT, V1,
2025 unsigned SubVecSize = 4;
2026 if (VT == MVT::v2f64 || VT == MVT::v2i64)
2029 int SubMask[4] = {-1, -1, -1, -1};
2030 for (
unsigned i = 0; i < SubVecSize; ++i) {
2031 for (
unsigned j = i; j < Mask.size(); j += SubVecSize) {
2037 M -= 4 * (j / SubVecSize);
2038 if (M < 0 || M >= 4)
2044 if (SubMask[i] == -1)
2048 else if (M != -1 && M != SubMask[i])
2055 for (
int i = SubVecSize - 1; i >= 0; --i) {
2068 if (VT == MVT::v2f64 || VT == MVT::v2i64)
2069 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT, V1, V2,
2072 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT, V1,
2090 if (VT != MVT::v16i8 && VT != MVT::v8i16 && VT != MVT::v32i8 &&
2099 for (
int i = 0; i < WidenNumElts; ++i)
2100 WidenMask[i] = WidenNumElts - 1 - i;
2108 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT,
2132 const auto &Begin = Mask.begin();
2133 const auto &End = Mask.end();
2134 SDValue OriV1 = V1, OriV2 = V2;
2150 return DAG.
getNode(LoongArchISD::VPACKEV,
DL, VT, V2, V1);
2172 const auto &Begin = Mask.begin();
2173 const auto &End = Mask.end();
2174 SDValue OriV1 = V1, OriV2 = V2;
2190 return DAG.
getNode(LoongArchISD::VPACKOD,
DL, VT, V2, V1);
2213 const auto &Begin = Mask.begin();
2214 const auto &End = Mask.end();
2215 unsigned HalfSize = Mask.size() / 2;
2216 SDValue OriV1 = V1, OriV2 = V2;
2233 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2, V1);
2256 const auto &Begin = Mask.begin();
2257 const auto &End = Mask.end();
2258 SDValue OriV1 = V1, OriV2 = V2;
2274 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2, V1);
2296 const auto &Begin = Mask.begin();
2297 const auto &Mid = Mask.begin() + Mask.size() / 2;
2298 const auto &End = Mask.end();
2299 SDValue OriV1 = V1, OriV2 = V2;
2316 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2, V1);
2338 const auto &Begin = Mask.begin();
2339 const auto &Mid = Mask.begin() + Mask.size() / 2;
2340 const auto &End = Mask.end();
2341 SDValue OriV1 = V1, OriV2 = V2;
2357 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2, V1);
2383 if (Mask.size() != NumElts)
2386 auto tryLowerToExtrAndIns = [&](
unsigned Base) ->
SDValue {
2389 for (
unsigned i = 0; i < NumElts; ++i) {
2392 if (Mask[i] !=
int(
Base + i)) {
2405 int DiffMask = Mask[DiffPos];
2406 if (DiffMask < 0 || DiffMask >=
int(2 * NumElts))
2412 if (
unsigned(DiffMask) < NumElts) {
2417 SrcIdx =
unsigned(DiffMask) - NumElts;
2433 if (
SDValue Result = tryLowerToExtrAndIns(0))
2435 return tryLowerToExtrAndIns(NumElts);
2443 unsigned &MaskImm) {
2444 unsigned MaskSize = Mask.size();
2446 auto isValid = [&](
int M,
int Off) {
2447 return (M == -1) || (M >= Off && M < Off + 4);
2450 auto buildImm = [&](
int MLo,
int MHi,
unsigned Off,
unsigned I) {
2451 auto immPart = [&](
int M,
unsigned Off) {
2452 return (M == -1 ? 0 : (M - Off)) & 0x3;
2454 MaskImm |= immPart(MLo, Off) << (
I * 2);
2455 MaskImm |= immPart(MHi, Off) << ((
I + 1) * 2);
2458 for (
unsigned i = 0; i < 4; i += 2) {
2460 int MHi = Mask[i + 1];
2462 if (MaskSize == 8) {
2463 int M2Lo = Mask[i + 4];
2464 int M2Hi = Mask[i + 5];
2465 if (M2Lo != MLo + 4 || M2Hi != MHi + 4)
2471 buildImm(MLo, MHi, 0, i);
2474 buildImm(MLo, MHi, MaskSize, i);
2504 if ((VT != MVT::v4i32 && VT != MVT::v4f32) ||
2509 unsigned MaskImm = 0;
2513 return DAG.
getNode(LoongArchISD::VPERMI,
DL, VT, SrcVec[1], SrcVec[0],
2540 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2, V1);
2553 "Vector type is unsupported for lsx!");
2555 "Two operands have different types!");
2557 "Unexpected mask size for shuffle!");
2558 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
2560 APInt KnownUndef, KnownZero;
2562 APInt Zeroable = KnownUndef | KnownZero;
2635 int SplatIndex = -1;
2636 for (
const auto &M : Mask) {
2643 if (SplatIndex == -1)
2646 const auto &Begin = Mask.begin();
2647 const auto &End = Mask.end();
2648 int HalfSize = Mask.size() / 2;
2650 if (SplatIndex >= HalfSize)
2653 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2657 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT, V1,
2671 if (Mask.size() == 4) {
2672 unsigned MaskImm = 0;
2673 for (
int i = 1; i >= 0; --i) {
2675 int MHi = Mask[i + 2];
2676 if (!(MLo == -1 || (MLo >= 0 && MLo <= 1) || (MLo >= 4 && MLo <= 5)) ||
2677 !(MHi == -1 || (MHi >= 2 && MHi <= 3) || (MHi >= 6 && MHi <= 7)))
2679 if (MHi != -1 && MLo != -1 && MHi != MLo + 2)
2684 MaskImm |= ((MLo <= 1) ? MLo : (MLo - 2)) & 0x3;
2686 MaskImm |= ((MHi <= 3) ? (MHi - 2) : (MHi - 4)) & 0x3;
2689 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT, V1, V2,
2702 unsigned MaskSize = Mask.size();
2707 if (VT == MVT::v8i32 || VT == MVT::v8f32) {
2709 unsigned MaskImm = 0;
2713 return DAG.
getNode(LoongArchISD::VPERMI,
DL, VT, SrcVec[1], SrcVec[0],
2718 if (VT == MVT::v4i64 || VT == MVT::v4f64) {
2719 unsigned MaskImm = 0;
2720 for (
unsigned i = 0; i < MaskSize; ++i) {
2723 if (Mask[i] >= (
int)MaskSize)
2725 MaskImm |= Mask[i] << (i * 2);
2728 return DAG.
getNode(LoongArchISD::XVPERMI,
DL, VT, V1,
2740 if (Mask.size() != 8 || (VT != MVT::v8i32 && VT != MVT::v8f32))
2744 unsigned HalfSize = NumElts / 2;
2745 bool FrontLo =
true, FrontHi =
true;
2746 bool BackLo =
true, BackHi =
true;
2748 auto inRange = [](
int val,
int low,
int high) {
2749 return (val == -1) || (val >= low && val < high);
2752 for (
unsigned i = 0; i < HalfSize; ++i) {
2753 int Fronti = Mask[i];
2754 int Backi = Mask[i + HalfSize];
2756 FrontLo &=
inRange(Fronti, 0, HalfSize);
2757 FrontHi &=
inRange(Fronti, HalfSize, NumElts);
2758 BackLo &=
inRange(Backi, 0, HalfSize);
2759 BackHi &=
inRange(Backi, HalfSize, NumElts);
2765 if ((FrontLo || FrontHi) && (BackLo || BackHi))
2770 for (
unsigned i = 0; i < NumElts; ++i)
2775 return DAG.
getNode(LoongArchISD::XVPERM,
DL, VT, V1, MaskVec);
2797 const auto &Begin = Mask.begin();
2798 const auto &End = Mask.end();
2799 unsigned HalfSize = Mask.size() / 2;
2800 unsigned LeftSize = HalfSize / 2;
2801 SDValue OriV1 = V1, OriV2 = V2;
2808 Mask.size() + HalfSize - LeftSize, 1) &&
2810 Mask.size() + HalfSize + LeftSize, 1))
2821 Mask.size() + HalfSize - LeftSize, 1) &&
2823 Mask.size() + HalfSize + LeftSize, 1))
2828 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2, V1);
2836 const auto &Begin = Mask.begin();
2837 const auto &End = Mask.end();
2838 unsigned HalfSize = Mask.size() / 2;
2839 SDValue OriV1 = V1, OriV2 = V2;
2846 Mask.size() + HalfSize, 1))
2857 Mask.size() + HalfSize, 1))
2862 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2, V1);
2870 const auto &Begin = Mask.begin();
2871 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2872 const auto &Mid = Mask.begin() + Mask.size() / 2;
2873 const auto &RightMid = Mask.end() - Mask.size() / 4;
2874 const auto &End = Mask.end();
2875 unsigned HalfSize = Mask.size() / 2;
2876 SDValue OriV1 = V1, OriV2 = V2;
2897 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2, V1);
2905 const auto &Begin = Mask.begin();
2906 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2907 const auto &Mid = Mask.begin() + Mask.size() / 2;
2908 const auto &RightMid = Mask.end() - Mask.size() / 4;
2909 const auto &End = Mask.end();
2910 unsigned HalfSize = Mask.size() / 2;
2911 SDValue OriV1 = V1, OriV2 = V2;
2933 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2, V1);
2942 int HalfSize = NumElts / 2;
2946 if ((
int)Mask.size() != NumElts)
2949 auto tryLowerToExtrAndIns = [&](
int Base) ->
SDValue {
2951 for (
int i = 0; i < NumElts; ++i) {
2954 if (Mask[i] !=
Base + i) {
2956 if (DiffPos.
size() > 2)
2964 if (DiffPos.
size() == 1) {
2965 if (DiffPos[0] < HalfSize && Mask[DiffPos[0] + HalfSize] == -1)
2966 DiffPos.
push_back(DiffPos[0] + HalfSize);
2967 else if (DiffPos[0] >= HalfSize && Mask[DiffPos[0] - HalfSize] == -1)
2968 DiffPos.
insert(DiffPos.
begin(), DiffPos[0] - HalfSize);
2972 if (DiffPos.
size() != 2 || DiffPos[1] != DiffPos[0] + HalfSize)
2976 int DiffMaskLo = Mask[DiffPos[0]];
2977 int DiffMaskHi = Mask[DiffPos[1]];
2978 DiffMaskLo = DiffMaskLo == -1 ? DiffMaskHi - HalfSize : DiffMaskLo;
2979 DiffMaskHi = DiffMaskHi == -1 ? DiffMaskLo + HalfSize : DiffMaskHi;
2980 if (!(DiffMaskLo >= 0 && DiffMaskLo < HalfSize) &&
2981 !(DiffMaskLo >= NumElts && DiffMaskLo < NumElts + HalfSize))
2983 if (!(DiffMaskHi >= HalfSize && DiffMaskHi < NumElts) &&
2984 !(DiffMaskHi >= NumElts + HalfSize && DiffMaskHi < 2 * NumElts))
2986 if (DiffMaskHi != DiffMaskLo + HalfSize)
2990 SDValue SrcVec = (DiffMaskLo < HalfSize) ? V1 : V2;
2992 (DiffMaskLo < HalfSize) ? DiffMaskLo : (DiffMaskLo - NumElts);
3013 if (
SDValue Result = tryLowerToExtrAndIns(0))
3015 return tryLowerToExtrAndIns(NumElts);
3024 if (VT != MVT::v8i32 && VT != MVT::v8f32 && VT != MVT::v4i64 &&
3029 int MaskSize = Mask.size();
3035 auto checkReplaceOne = [&](
int Base,
int Replaced) ->
int {
3037 for (
int i = 0; i < MaskSize; ++i) {
3038 if (Mask[i] ==
Base + i || Mask[i] == -1)
3040 if (Mask[i] != Replaced)
3051 int Idx = checkReplaceOne(0, MaskSize);
3053 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT, V1, V2,
3057 Idx = checkReplaceOne(MaskSize, 0);
3059 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT, V2, V1,
3070 int MaskSize = Mask.size();
3071 int HalfSize = Mask.size() / 2;
3072 const auto &Begin = Mask.begin();
3073 const auto &Mid = Mask.begin() + HalfSize;
3074 const auto &End = Mask.end();
3086 for (
auto it = Begin; it < Mid; it++) {
3089 else if ((*it >= 0 && *it < HalfSize) ||
3090 (*it >= MaskSize && *it < MaskSize + HalfSize)) {
3091 int M = *it < HalfSize ? *it : *it - HalfSize;
3096 assert((
int)MaskAlloc.
size() == HalfSize &&
"xvshuf convert failed!");
3098 for (
auto it = Mid; it < End; it++) {
3101 else if ((*it >= HalfSize && *it < MaskSize) ||
3102 (*it >= MaskSize + HalfSize && *it < MaskSize * 2)) {
3103 int M = *it < MaskSize ? *it - HalfSize : *it - MaskSize;
3108 assert((
int)MaskAlloc.
size() == MaskSize &&
"xvshuf convert failed!");
3112 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2, V1);
3140 enum HalfMaskType { HighLaneTy, LowLaneTy,
None };
3142 int MaskSize = Mask.size();
3143 int HalfSize = Mask.size() / 2;
3146 HalfMaskType preMask =
None, postMask =
None;
3148 if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
3149 return M < 0 || (M >= 0 && M < HalfSize) ||
3150 (M >= MaskSize && M < MaskSize + HalfSize);
3152 preMask = HighLaneTy;
3153 else if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
3154 return M < 0 || (M >= HalfSize && M < MaskSize) ||
3155 (M >= MaskSize + HalfSize && M < MaskSize * 2);
3157 preMask = LowLaneTy;
3159 if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
3160 return M < 0 || (M >= HalfSize && M < MaskSize) ||
3161 (M >= MaskSize + HalfSize && M < MaskSize * 2);
3163 postMask = LowLaneTy;
3164 else if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
3165 return M < 0 || (M >= 0 && M < HalfSize) ||
3166 (M >= MaskSize && M < MaskSize + HalfSize);
3168 postMask = HighLaneTy;
3176 if (preMask == HighLaneTy && postMask == LowLaneTy) {
3179 if (preMask == LowLaneTy && postMask == HighLaneTy) {
3181 V1 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V1,
3187 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3192 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
3193 *it = *it < 0 ? *it : *it - HalfSize;
3195 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
3196 *it = *it < 0 ? *it : *it + HalfSize;
3198 }
else if (preMask == LowLaneTy && postMask == LowLaneTy) {
3200 V1 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V1,
3206 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3211 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
3212 *it = *it < 0 ? *it : *it - HalfSize;
3214 }
else if (preMask == HighLaneTy && postMask == HighLaneTy) {
3216 V1 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V1,
3222 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3227 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
3228 *it = *it < 0 ? *it : *it + HalfSize;
3253 int Size = Mask.size();
3254 int LaneSize =
Size / 2;
3256 bool LaneCrossing[2] = {
false,
false};
3257 for (
int i = 0; i <
Size; ++i)
3258 if (Mask[i] >= 0 && ((Mask[i] %
Size) / LaneSize) != (i / LaneSize))
3259 LaneCrossing[(Mask[i] %
Size) / LaneSize] =
true;
3262 if (!LaneCrossing[0] && !LaneCrossing[1])
3266 InLaneMask.
assign(Mask.begin(), Mask.end());
3267 for (
int i = 0; i <
Size; ++i) {
3268 int &M = InLaneMask[i];
3271 if (((M %
Size) / LaneSize) != (i / LaneSize))
3272 M = (M % LaneSize) + ((i / LaneSize) * LaneSize) +
Size;
3277 DAG.
getUNDEF(MVT::v4i64), {2, 3, 0, 1});
3292 "Vector type is unsupported for lasx!");
3294 "Two operands have different types!");
3296 "Unexpected mask size for shuffle!");
3297 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
3298 assert(Mask.size() >= 4 &&
"Mask size is less than 4.");
3300 APInt KnownUndef, KnownZero;
3302 APInt Zeroable = KnownUndef | KnownZero;
3389 ArrayRef<int> OrigMask = SVOp->
getMask();
3392 MVT VT =
Op.getSimpleValueType();
3396 bool V1IsUndef = V1.
isUndef();
3397 bool V2IsUndef = V2.
isUndef();
3398 if (V1IsUndef && V2IsUndef)
3411 any_of(OrigMask, [NumElements](
int M) {
return M >= NumElements; })) {
3412 SmallVector<int, 8> NewMask(OrigMask);
3413 for (
int &M : NewMask)
3414 if (M >= NumElements)
3420 int MaskUpperLimit = OrigMask.
size() * (V2IsUndef ? 1 : 2);
3421 (void)MaskUpperLimit;
3423 [&](
int M) {
return -1 <=
M &&
M < MaskUpperLimit; }) &&
3424 "Out of bounds shuffle index");
3446 std::tie(Res, Chain) =
3447 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
3448 if (Subtarget.is64Bit())
3449 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3461 SDValue Arg = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3465 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
3466 CallOptions,
DL, Chain);
3472 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3478 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
3479 if (Subtarget.is64Bit())
3480 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3486 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3487 MVT VT =
Op.getSimpleValueType();
3492 SDValue Res = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3513 "Unsupported vector type for broadcast.");
3516 bool IsIdeneity =
true;
3518 for (
int i = 0; i !=
NumOps; i++) {
3520 if (
Op.getOpcode() !=
ISD::LOAD || (IdentitySrc &&
Op != IdentitySrc)) {
3532 auto ExtType = LN->getExtensionType();
3537 assert(LN->isUnindexed() &&
"Unexpected indexed load.");
3542 SDValue Ops[] = {LN->getChain(), LN->getBasePtr()};
3560 for (
unsigned i = 1; i <
Ops.size(); ++i) {
3574 EVT ResTy,
unsigned first) {
3577 assert(first + NumElts <= Node->getSimpleValueType(0).getVectorNumElements());
3580 Node->op_begin() + first + NumElts);
3589 MVT VT =
Node->getSimpleValueType(0);
3590 EVT ResTy =
Op->getValueType(0);
3593 APInt SplatValue, SplatUndef;
3594 unsigned SplatBitSize;
3597 bool UseSameConstant =
true;
3602 if ((!Subtarget.hasExtLSX() || !Is128Vec) &&
3603 (!Subtarget.hasExtLASX() || !Is256Vec))
3609 if (
Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
3611 SplatBitSize <= 64) {
3613 if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
3617 if (SplatBitSize == 64 && !Subtarget.is64Bit()) {
3624 if ((Is128Vec && ResTy == MVT::v4i32) ||
3625 (Is256Vec && ResTy == MVT::v8i32))
3631 switch (SplatBitSize) {
3635 ViaVecTy = Is128Vec ? MVT::v16i8 : MVT::v32i8;
3638 ViaVecTy = Is128Vec ? MVT::v8i16 : MVT::v16i16;
3641 ViaVecTy = Is128Vec ? MVT::v4i32 : MVT::v8i32;
3644 ViaVecTy = Is128Vec ? MVT::v2i64 : MVT::v4i64;
3652 if (ViaVecTy != ResTy)
3661 for (
unsigned i = 0; i < NumElts; ++i) {
3666 ConstantValue = Opi;
3667 else if (ConstantValue != Opi)
3668 UseSameConstant =
false;
3673 if (IsConstant && UseSameConstant && ResTy != MVT::v2f64) {
3675 for (
unsigned i = 0; i < NumElts; ++i) {
3693 BitVector UndefElements;
3694 if (
Node->getRepeatedSequence(Sequence, &UndefElements) &&
3695 UndefElements.
count() == 0) {
3699 EVT FillTy = Is256Vec
3705 fillVector(Sequence, DAG,
DL, Subtarget, FillVec, FillTy);
3708 unsigned SplatLen = NumElts / SeqLen;
3714 if (SplatEltTy == MVT::i128)
3715 SplatTy = MVT::v4i64;
3723 DAG.
getNode((SplatEltTy == MVT::i128) ? LoongArchISD::XVREPLVE0Q
3724 : LoongArchISD::XVREPLVE0,
3725 DL, SplatTy, SrcVec);
3727 SplatVec = DAG.
getNode(LoongArchISD::VREPLVEI,
DL, SplatTy, SrcVec,
3740 if (ResTy == MVT::v8i32 || ResTy == MVT::v8f32 || ResTy == MVT::v4i64 ||
3741 ResTy == MVT::v4f64) {
3742 unsigned NonUndefCount = 0;
3743 for (
unsigned i = NumElts / 2; i < NumElts; ++i) {
3744 if (!
Node->getOperand(i).isUndef()) {
3746 if (NonUndefCount > 1)
3750 if (NonUndefCount == 1)
3763 VecTy, NumElts / 2);
3774 MVT ResVT =
Op.getSimpleValueType();
3778 unsigned NumFreezeUndef = 0;
3779 unsigned NumZero = 0;
3780 unsigned NumNonZero = 0;
3781 unsigned NonZeros = 0;
3782 SmallSet<SDValue, 4> Undefs;
3783 for (
unsigned i = 0; i != NumOperands; ++i) {
3798 assert(i <
sizeof(NonZeros) * CHAR_BIT);
3805 if (NumNonZero > 2) {
3809 Ops.slice(0, NumOperands / 2));
3811 Ops.slice(NumOperands / 2));
3824 MVT SubVT =
Op.getOperand(0).getSimpleValueType();
3826 for (
unsigned i = 0; i != NumOperands; ++i) {
3827 if ((NonZeros & (1 << i)) == 0)
3838LoongArchTargetLowering::lowerEXTRACT_VECTOR_ELT(
SDValue Op,
3840 MVT EltVT =
Op.getSimpleValueType();
3845 MVT GRLenVT = Subtarget.getGRLenVT();
3873 ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Idx)
3877 DAG.
getBitcast((VecTy == MVT::v4f64) ? MVT::v4i64 : VecTy, IdxVec);
3879 DAG.
getNode(LoongArchISD::VSHUF,
DL, VecTy, MaskVec, TmpVec, Vec);
3888 DAG.
getNode(LoongArchISD::XVPERM,
DL, VecTy, Vec, SplatIdx);
3897LoongArchTargetLowering::lowerINSERT_VECTOR_ELT(
SDValue Op,
3899 MVT VT =
Op.getSimpleValueType();
3922 if (!Subtarget.is64Bit() && IdxTy == MVT::i64) {
3924 for (
unsigned i = 0; i < NumElts; ++i) {
3932 for (
unsigned i = 0; i < NumElts; ++i) {
3941 for (
unsigned i = 0; i < NumElts; ++i)
3973 if (Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i32) {
3975 "On LA64, only 64-bit registers can be written.");
3976 return Op.getOperand(0);
3979 if (!Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i64) {
3981 "On LA32, only 32-bit registers can be written.");
3982 return Op.getOperand(0);
3992 "be a constant integer");
3998 Register FrameReg = Subtarget.getRegisterInfo()->getFrameRegister(MF);
3999 EVT VT =
Op.getValueType();
4002 unsigned Depth =
Op.getConstantOperandVal(0);
4003 int GRLenInBytes = Subtarget.getGRLen() / 8;
4006 int Offset = -(GRLenInBytes * 2);
4018 if (
Op.getConstantOperandVal(0) != 0) {
4020 "return address can only be determined for the current frame");
4026 MVT GRLenVT = Subtarget.getGRLenVT();
4038 auto Size = Subtarget.getGRLen() / 8;
4046 auto *FuncInfo = MF.
getInfo<LoongArchMachineFunctionInfo>();
4056 MachinePointerInfo(SV));
4061 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
4062 !Subtarget.hasBasicD() &&
"unexpected target features");
4068 if (
C &&
C->getZExtValue() < UINT64_C(0xFFFFFFFF))
4072 if (Op0->
getOpcode() == LoongArchISD::BSTRPICK &&
4082 EVT RetVT =
Op.getValueType();
4088 std::tie(Result, Chain) =
4095 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
4096 !Subtarget.hasBasicD() &&
"unexpected target features");
4107 EVT RetVT =
Op.getValueType();
4113 std::tie(Result, Chain) =
4122 EVT VT =
Op.getValueType();
4126 if (
Op.getValueType() == MVT::f32 && Op0VT == MVT::i32 &&
4127 Subtarget.is64Bit() && Subtarget.hasBasicF()) {
4129 return DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, NewOp0);
4131 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit()) {
4134 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
4148 if (
Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() &&
4149 !Subtarget.hasBasicD()) {
4151 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Dst);
4173 N->getOffset(), Flags);
4181template <
class NodeTy>
4184 bool IsLocal)
const {
4195 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
4276 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
4278 const GlobalValue *GV =
N->getGlobal();
4290 unsigned Opc,
bool UseGOT,
4294 MVT GRLenVT = Subtarget.getGRLenVT();
4308 if (
Opc == LoongArch::PseudoLA_TLS_LE && !Large)
4346 Args.emplace_back(Load, CallTy);
4349 TargetLowering::CallLoweringInfo CLI(DAG);
4364 const GlobalValue *GV =
N->getGlobal();
4378LoongArchTargetLowering::lowerGlobalTLSAddress(
SDValue Op,
4385 assert((!Large || Subtarget.is64Bit()) &&
"Large code model requires LA64");
4388 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
4401 return getDynamicTLSAddr(
N, DAG,
4402 Large ? LoongArch::PseudoLA_TLS_GD_LARGE
4403 : LoongArch::PseudoLA_TLS_GD,
4410 return getDynamicTLSAddr(
N, DAG,
4411 Large ? LoongArch::PseudoLA_TLS_LD_LARGE
4412 : LoongArch::PseudoLA_TLS_LD,
4417 return getStaticTLSAddr(
N, DAG,
4418 Large ? LoongArch::PseudoLA_TLS_IE_LARGE
4419 : LoongArch::PseudoLA_TLS_IE,
4426 return getStaticTLSAddr(
N, DAG, LoongArch::PseudoLA_TLS_LE,
4430 return getTLSDescAddr(
N, DAG,
4431 Large ? LoongArch::PseudoLA_TLS_DESC_LARGE
4432 : LoongArch::PseudoLA_TLS_DESC,
4436template <
unsigned N>
4441 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
4442 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
4444 ": argument out of range.");
4451LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(
SDValue Op,
4453 switch (
Op.getConstantOperandVal(0)) {
4456 case Intrinsic::thread_pointer: {
4460 case Intrinsic::loongarch_lsx_vpickve2gr_d:
4461 case Intrinsic::loongarch_lsx_vpickve2gr_du:
4462 case Intrinsic::loongarch_lsx_vreplvei_d:
4463 case Intrinsic::loongarch_lasx_xvrepl128vei_d:
4465 case Intrinsic::loongarch_lsx_vreplvei_w:
4466 case Intrinsic::loongarch_lasx_xvrepl128vei_w:
4467 case Intrinsic::loongarch_lasx_xvpickve2gr_d:
4468 case Intrinsic::loongarch_lasx_xvpickve2gr_du:
4469 case Intrinsic::loongarch_lasx_xvpickve_d:
4470 case Intrinsic::loongarch_lasx_xvpickve_d_f:
4472 case Intrinsic::loongarch_lasx_xvinsve0_d:
4474 case Intrinsic::loongarch_lsx_vsat_b:
4475 case Intrinsic::loongarch_lsx_vsat_bu:
4476 case Intrinsic::loongarch_lsx_vrotri_b:
4477 case Intrinsic::loongarch_lsx_vsllwil_h_b:
4478 case Intrinsic::loongarch_lsx_vsllwil_hu_bu:
4479 case Intrinsic::loongarch_lsx_vsrlri_b:
4480 case Intrinsic::loongarch_lsx_vsrari_b:
4481 case Intrinsic::loongarch_lsx_vreplvei_h:
4482 case Intrinsic::loongarch_lasx_xvsat_b:
4483 case Intrinsic::loongarch_lasx_xvsat_bu:
4484 case Intrinsic::loongarch_lasx_xvrotri_b:
4485 case Intrinsic::loongarch_lasx_xvsllwil_h_b:
4486 case Intrinsic::loongarch_lasx_xvsllwil_hu_bu:
4487 case Intrinsic::loongarch_lasx_xvsrlri_b:
4488 case Intrinsic::loongarch_lasx_xvsrari_b:
4489 case Intrinsic::loongarch_lasx_xvrepl128vei_h:
4490 case Intrinsic::loongarch_lasx_xvpickve_w:
4491 case Intrinsic::loongarch_lasx_xvpickve_w_f:
4493 case Intrinsic::loongarch_lasx_xvinsve0_w:
4495 case Intrinsic::loongarch_lsx_vsat_h:
4496 case Intrinsic::loongarch_lsx_vsat_hu:
4497 case Intrinsic::loongarch_lsx_vrotri_h:
4498 case Intrinsic::loongarch_lsx_vsllwil_w_h:
4499 case Intrinsic::loongarch_lsx_vsllwil_wu_hu:
4500 case Intrinsic::loongarch_lsx_vsrlri_h:
4501 case Intrinsic::loongarch_lsx_vsrari_h:
4502 case Intrinsic::loongarch_lsx_vreplvei_b:
4503 case Intrinsic::loongarch_lasx_xvsat_h:
4504 case Intrinsic::loongarch_lasx_xvsat_hu:
4505 case Intrinsic::loongarch_lasx_xvrotri_h:
4506 case Intrinsic::loongarch_lasx_xvsllwil_w_h:
4507 case Intrinsic::loongarch_lasx_xvsllwil_wu_hu:
4508 case Intrinsic::loongarch_lasx_xvsrlri_h:
4509 case Intrinsic::loongarch_lasx_xvsrari_h:
4510 case Intrinsic::loongarch_lasx_xvrepl128vei_b:
4512 case Intrinsic::loongarch_lsx_vsrlni_b_h:
4513 case Intrinsic::loongarch_lsx_vsrani_b_h:
4514 case Intrinsic::loongarch_lsx_vsrlrni_b_h:
4515 case Intrinsic::loongarch_lsx_vsrarni_b_h:
4516 case Intrinsic::loongarch_lsx_vssrlni_b_h:
4517 case Intrinsic::loongarch_lsx_vssrani_b_h:
4518 case Intrinsic::loongarch_lsx_vssrlni_bu_h:
4519 case Intrinsic::loongarch_lsx_vssrani_bu_h:
4520 case Intrinsic::loongarch_lsx_vssrlrni_b_h:
4521 case Intrinsic::loongarch_lsx_vssrarni_b_h:
4522 case Intrinsic::loongarch_lsx_vssrlrni_bu_h:
4523 case Intrinsic::loongarch_lsx_vssrarni_bu_h:
4524 case Intrinsic::loongarch_lasx_xvsrlni_b_h:
4525 case Intrinsic::loongarch_lasx_xvsrani_b_h:
4526 case Intrinsic::loongarch_lasx_xvsrlrni_b_h:
4527 case Intrinsic::loongarch_lasx_xvsrarni_b_h:
4528 case Intrinsic::loongarch_lasx_xvssrlni_b_h:
4529 case Intrinsic::loongarch_lasx_xvssrani_b_h:
4530 case Intrinsic::loongarch_lasx_xvssrlni_bu_h:
4531 case Intrinsic::loongarch_lasx_xvssrani_bu_h:
4532 case Intrinsic::loongarch_lasx_xvssrlrni_b_h:
4533 case Intrinsic::loongarch_lasx_xvssrarni_b_h:
4534 case Intrinsic::loongarch_lasx_xvssrlrni_bu_h:
4535 case Intrinsic::loongarch_lasx_xvssrarni_bu_h:
4537 case Intrinsic::loongarch_lsx_vsat_w:
4538 case Intrinsic::loongarch_lsx_vsat_wu:
4539 case Intrinsic::loongarch_lsx_vrotri_w:
4540 case Intrinsic::loongarch_lsx_vsllwil_d_w:
4541 case Intrinsic::loongarch_lsx_vsllwil_du_wu:
4542 case Intrinsic::loongarch_lsx_vsrlri_w:
4543 case Intrinsic::loongarch_lsx_vsrari_w:
4544 case Intrinsic::loongarch_lsx_vslei_bu:
4545 case Intrinsic::loongarch_lsx_vslei_hu:
4546 case Intrinsic::loongarch_lsx_vslei_wu:
4547 case Intrinsic::loongarch_lsx_vslei_du:
4548 case Intrinsic::loongarch_lsx_vslti_bu:
4549 case Intrinsic::loongarch_lsx_vslti_hu:
4550 case Intrinsic::loongarch_lsx_vslti_wu:
4551 case Intrinsic::loongarch_lsx_vslti_du:
4552 case Intrinsic::loongarch_lsx_vbsll_v:
4553 case Intrinsic::loongarch_lsx_vbsrl_v:
4554 case Intrinsic::loongarch_lasx_xvsat_w:
4555 case Intrinsic::loongarch_lasx_xvsat_wu:
4556 case Intrinsic::loongarch_lasx_xvrotri_w:
4557 case Intrinsic::loongarch_lasx_xvsllwil_d_w:
4558 case Intrinsic::loongarch_lasx_xvsllwil_du_wu:
4559 case Intrinsic::loongarch_lasx_xvsrlri_w:
4560 case Intrinsic::loongarch_lasx_xvsrari_w:
4561 case Intrinsic::loongarch_lasx_xvslei_bu:
4562 case Intrinsic::loongarch_lasx_xvslei_hu:
4563 case Intrinsic::loongarch_lasx_xvslei_wu:
4564 case Intrinsic::loongarch_lasx_xvslei_du:
4565 case Intrinsic::loongarch_lasx_xvslti_bu:
4566 case Intrinsic::loongarch_lasx_xvslti_hu:
4567 case Intrinsic::loongarch_lasx_xvslti_wu:
4568 case Intrinsic::loongarch_lasx_xvslti_du:
4569 case Intrinsic::loongarch_lasx_xvbsll_v:
4570 case Intrinsic::loongarch_lasx_xvbsrl_v:
4572 case Intrinsic::loongarch_lsx_vseqi_b:
4573 case Intrinsic::loongarch_lsx_vseqi_h:
4574 case Intrinsic::loongarch_lsx_vseqi_w:
4575 case Intrinsic::loongarch_lsx_vseqi_d:
4576 case Intrinsic::loongarch_lsx_vslei_b:
4577 case Intrinsic::loongarch_lsx_vslei_h:
4578 case Intrinsic::loongarch_lsx_vslei_w:
4579 case Intrinsic::loongarch_lsx_vslei_d:
4580 case Intrinsic::loongarch_lsx_vslti_b:
4581 case Intrinsic::loongarch_lsx_vslti_h:
4582 case Intrinsic::loongarch_lsx_vslti_w:
4583 case Intrinsic::loongarch_lsx_vslti_d:
4584 case Intrinsic::loongarch_lasx_xvseqi_b:
4585 case Intrinsic::loongarch_lasx_xvseqi_h:
4586 case Intrinsic::loongarch_lasx_xvseqi_w:
4587 case Intrinsic::loongarch_lasx_xvseqi_d:
4588 case Intrinsic::loongarch_lasx_xvslei_b:
4589 case Intrinsic::loongarch_lasx_xvslei_h:
4590 case Intrinsic::loongarch_lasx_xvslei_w:
4591 case Intrinsic::loongarch_lasx_xvslei_d:
4592 case Intrinsic::loongarch_lasx_xvslti_b:
4593 case Intrinsic::loongarch_lasx_xvslti_h:
4594 case Intrinsic::loongarch_lasx_xvslti_w:
4595 case Intrinsic::loongarch_lasx_xvslti_d:
4597 case Intrinsic::loongarch_lsx_vsrlni_h_w:
4598 case Intrinsic::loongarch_lsx_vsrani_h_w:
4599 case Intrinsic::loongarch_lsx_vsrlrni_h_w:
4600 case Intrinsic::loongarch_lsx_vsrarni_h_w:
4601 case Intrinsic::loongarch_lsx_vssrlni_h_w:
4602 case Intrinsic::loongarch_lsx_vssrani_h_w:
4603 case Intrinsic::loongarch_lsx_vssrlni_hu_w:
4604 case Intrinsic::loongarch_lsx_vssrani_hu_w:
4605 case Intrinsic::loongarch_lsx_vssrlrni_h_w:
4606 case Intrinsic::loongarch_lsx_vssrarni_h_w:
4607 case Intrinsic::loongarch_lsx_vssrlrni_hu_w:
4608 case Intrinsic::loongarch_lsx_vssrarni_hu_w:
4609 case Intrinsic::loongarch_lsx_vfrstpi_b:
4610 case Intrinsic::loongarch_lsx_vfrstpi_h:
4611 case Intrinsic::loongarch_lasx_xvsrlni_h_w:
4612 case Intrinsic::loongarch_lasx_xvsrani_h_w:
4613 case Intrinsic::loongarch_lasx_xvsrlrni_h_w:
4614 case Intrinsic::loongarch_lasx_xvsrarni_h_w:
4615 case Intrinsic::loongarch_lasx_xvssrlni_h_w:
4616 case Intrinsic::loongarch_lasx_xvssrani_h_w:
4617 case Intrinsic::loongarch_lasx_xvssrlni_hu_w:
4618 case Intrinsic::loongarch_lasx_xvssrani_hu_w:
4619 case Intrinsic::loongarch_lasx_xvssrlrni_h_w:
4620 case Intrinsic::loongarch_lasx_xvssrarni_h_w:
4621 case Intrinsic::loongarch_lasx_xvssrlrni_hu_w:
4622 case Intrinsic::loongarch_lasx_xvssrarni_hu_w:
4623 case Intrinsic::loongarch_lasx_xvfrstpi_b:
4624 case Intrinsic::loongarch_lasx_xvfrstpi_h:
4626 case Intrinsic::loongarch_lsx_vsat_d:
4627 case Intrinsic::loongarch_lsx_vsat_du:
4628 case Intrinsic::loongarch_lsx_vrotri_d:
4629 case Intrinsic::loongarch_lsx_vsrlri_d:
4630 case Intrinsic::loongarch_lsx_vsrari_d:
4631 case Intrinsic::loongarch_lasx_xvsat_d:
4632 case Intrinsic::loongarch_lasx_xvsat_du:
4633 case Intrinsic::loongarch_lasx_xvrotri_d:
4634 case Intrinsic::loongarch_lasx_xvsrlri_d:
4635 case Intrinsic::loongarch_lasx_xvsrari_d:
4637 case Intrinsic::loongarch_lsx_vsrlni_w_d:
4638 case Intrinsic::loongarch_lsx_vsrani_w_d:
4639 case Intrinsic::loongarch_lsx_vsrlrni_w_d:
4640 case Intrinsic::loongarch_lsx_vsrarni_w_d:
4641 case Intrinsic::loongarch_lsx_vssrlni_w_d:
4642 case Intrinsic::loongarch_lsx_vssrani_w_d:
4643 case Intrinsic::loongarch_lsx_vssrlni_wu_d:
4644 case Intrinsic::loongarch_lsx_vssrani_wu_d:
4645 case Intrinsic::loongarch_lsx_vssrlrni_w_d:
4646 case Intrinsic::loongarch_lsx_vssrarni_w_d:
4647 case Intrinsic::loongarch_lsx_vssrlrni_wu_d:
4648 case Intrinsic::loongarch_lsx_vssrarni_wu_d:
4649 case Intrinsic::loongarch_lasx_xvsrlni_w_d:
4650 case Intrinsic::loongarch_lasx_xvsrani_w_d:
4651 case Intrinsic::loongarch_lasx_xvsrlrni_w_d:
4652 case Intrinsic::loongarch_lasx_xvsrarni_w_d:
4653 case Intrinsic::loongarch_lasx_xvssrlni_w_d:
4654 case Intrinsic::loongarch_lasx_xvssrani_w_d:
4655 case Intrinsic::loongarch_lasx_xvssrlni_wu_d:
4656 case Intrinsic::loongarch_lasx_xvssrani_wu_d:
4657 case Intrinsic::loongarch_lasx_xvssrlrni_w_d:
4658 case Intrinsic::loongarch_lasx_xvssrarni_w_d:
4659 case Intrinsic::loongarch_lasx_xvssrlrni_wu_d:
4660 case Intrinsic::loongarch_lasx_xvssrarni_wu_d:
4662 case Intrinsic::loongarch_lsx_vsrlni_d_q:
4663 case Intrinsic::loongarch_lsx_vsrani_d_q:
4664 case Intrinsic::loongarch_lsx_vsrlrni_d_q:
4665 case Intrinsic::loongarch_lsx_vsrarni_d_q:
4666 case Intrinsic::loongarch_lsx_vssrlni_d_q:
4667 case Intrinsic::loongarch_lsx_vssrani_d_q:
4668 case Intrinsic::loongarch_lsx_vssrlni_du_q:
4669 case Intrinsic::loongarch_lsx_vssrani_du_q:
4670 case Intrinsic::loongarch_lsx_vssrlrni_d_q:
4671 case Intrinsic::loongarch_lsx_vssrarni_d_q:
4672 case Intrinsic::loongarch_lsx_vssrlrni_du_q:
4673 case Intrinsic::loongarch_lsx_vssrarni_du_q:
4674 case Intrinsic::loongarch_lasx_xvsrlni_d_q:
4675 case Intrinsic::loongarch_lasx_xvsrani_d_q:
4676 case Intrinsic::loongarch_lasx_xvsrlrni_d_q:
4677 case Intrinsic::loongarch_lasx_xvsrarni_d_q:
4678 case Intrinsic::loongarch_lasx_xvssrlni_d_q:
4679 case Intrinsic::loongarch_lasx_xvssrani_d_q:
4680 case Intrinsic::loongarch_lasx_xvssrlni_du_q:
4681 case Intrinsic::loongarch_lasx_xvssrani_du_q:
4682 case Intrinsic::loongarch_lasx_xvssrlrni_d_q:
4683 case Intrinsic::loongarch_lasx_xvssrarni_d_q:
4684 case Intrinsic::loongarch_lasx_xvssrlrni_du_q:
4685 case Intrinsic::loongarch_lasx_xvssrarni_du_q:
4687 case Intrinsic::loongarch_lsx_vnori_b:
4688 case Intrinsic::loongarch_lsx_vshuf4i_b:
4689 case Intrinsic::loongarch_lsx_vshuf4i_h:
4690 case Intrinsic::loongarch_lsx_vshuf4i_w:
4691 case Intrinsic::loongarch_lasx_xvnori_b:
4692 case Intrinsic::loongarch_lasx_xvshuf4i_b:
4693 case Intrinsic::loongarch_lasx_xvshuf4i_h:
4694 case Intrinsic::loongarch_lasx_xvshuf4i_w:
4695 case Intrinsic::loongarch_lasx_xvpermi_d:
4697 case Intrinsic::loongarch_lsx_vshuf4i_d:
4698 case Intrinsic::loongarch_lsx_vpermi_w:
4699 case Intrinsic::loongarch_lsx_vbitseli_b:
4700 case Intrinsic::loongarch_lsx_vextrins_b:
4701 case Intrinsic::loongarch_lsx_vextrins_h:
4702 case Intrinsic::loongarch_lsx_vextrins_w:
4703 case Intrinsic::loongarch_lsx_vextrins_d:
4704 case Intrinsic::loongarch_lasx_xvshuf4i_d:
4705 case Intrinsic::loongarch_lasx_xvpermi_w:
4706 case Intrinsic::loongarch_lasx_xvpermi_q:
4707 case Intrinsic::loongarch_lasx_xvbitseli_b:
4708 case Intrinsic::loongarch_lasx_xvextrins_b:
4709 case Intrinsic::loongarch_lasx_xvextrins_h:
4710 case Intrinsic::loongarch_lasx_xvextrins_w:
4711 case Intrinsic::loongarch_lasx_xvextrins_d:
4713 case Intrinsic::loongarch_lsx_vrepli_b:
4714 case Intrinsic::loongarch_lsx_vrepli_h:
4715 case Intrinsic::loongarch_lsx_vrepli_w:
4716 case Intrinsic::loongarch_lsx_vrepli_d:
4717 case Intrinsic::loongarch_lasx_xvrepli_b:
4718 case Intrinsic::loongarch_lasx_xvrepli_h:
4719 case Intrinsic::loongarch_lasx_xvrepli_w:
4720 case Intrinsic::loongarch_lasx_xvrepli_d:
4722 case Intrinsic::loongarch_lsx_vldi:
4723 case Intrinsic::loongarch_lasx_xvldi:
4739LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(
SDValue Op,
4742 MVT GRLenVT = Subtarget.getGRLenVT();
4743 EVT VT =
Op.getValueType();
4745 const StringRef ErrorMsgOOR =
"argument out of range";
4746 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4747 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4749 switch (
Op.getConstantOperandVal(1)) {
4752 case Intrinsic::loongarch_crc_w_b_w:
4753 case Intrinsic::loongarch_crc_w_h_w:
4754 case Intrinsic::loongarch_crc_w_w_w:
4755 case Intrinsic::loongarch_crc_w_d_w:
4756 case Intrinsic::loongarch_crcc_w_b_w:
4757 case Intrinsic::loongarch_crcc_w_h_w:
4758 case Intrinsic::loongarch_crcc_w_w_w:
4759 case Intrinsic::loongarch_crcc_w_d_w:
4761 case Intrinsic::loongarch_csrrd_w:
4762 case Intrinsic::loongarch_csrrd_d: {
4763 unsigned Imm =
Op.getConstantOperandVal(2);
4766 : DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
4769 case Intrinsic::loongarch_csrwr_w:
4770 case Intrinsic::loongarch_csrwr_d: {
4771 unsigned Imm =
Op.getConstantOperandVal(3);
4774 : DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
4775 {Chain,
Op.getOperand(2),
4778 case Intrinsic::loongarch_csrxchg_w:
4779 case Intrinsic::loongarch_csrxchg_d: {
4780 unsigned Imm =
Op.getConstantOperandVal(4);
4783 : DAG.
getNode(LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
4784 {Chain,
Op.getOperand(2),
Op.getOperand(3),
4787 case Intrinsic::loongarch_iocsrrd_d: {
4789 LoongArchISD::IOCSRRD_D,
DL, {GRLenVT, MVT::Other},
4792#define IOCSRRD_CASE(NAME, NODE) \
4793 case Intrinsic::loongarch_##NAME: { \
4794 return DAG.getNode(LoongArchISD::NODE, DL, {GRLenVT, MVT::Other}, \
4795 {Chain, Op.getOperand(2)}); \
4801 case Intrinsic::loongarch_cpucfg: {
4802 return DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
4803 {Chain,
Op.getOperand(2)});
4805 case Intrinsic::loongarch_lddir_d: {
4806 unsigned Imm =
Op.getConstantOperandVal(3);
4811 case Intrinsic::loongarch_movfcsr2gr: {
4812 if (!Subtarget.hasBasicF())
4814 unsigned Imm =
Op.getConstantOperandVal(2);
4817 : DAG.
getNode(LoongArchISD::MOVFCSR2GR,
DL, {VT, MVT::Other},
4820 case Intrinsic::loongarch_lsx_vld:
4821 case Intrinsic::loongarch_lsx_vldrepl_b:
4822 case Intrinsic::loongarch_lasx_xvld:
4823 case Intrinsic::loongarch_lasx_xvldrepl_b:
4827 case Intrinsic::loongarch_lsx_vldrepl_h:
4828 case Intrinsic::loongarch_lasx_xvldrepl_h:
4832 Op,
"argument out of range or not a multiple of 2", DAG)
4834 case Intrinsic::loongarch_lsx_vldrepl_w:
4835 case Intrinsic::loongarch_lasx_xvldrepl_w:
4839 Op,
"argument out of range or not a multiple of 4", DAG)
4841 case Intrinsic::loongarch_lsx_vldrepl_d:
4842 case Intrinsic::loongarch_lasx_xvldrepl_d:
4846 Op,
"argument out of range or not a multiple of 8", DAG)
4857 return Op.getOperand(0);
4863 MVT GRLenVT = Subtarget.getGRLenVT();
4865 uint64_t IntrinsicEnum =
Op.getConstantOperandVal(1);
4867 const StringRef ErrorMsgOOR =
"argument out of range";
4868 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4869 const StringRef ErrorMsgReqLA32 =
"requires loongarch32";
4870 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4872 switch (IntrinsicEnum) {
4876 case Intrinsic::loongarch_cacop_d:
4877 case Intrinsic::loongarch_cacop_w: {
4878 if (IntrinsicEnum == Intrinsic::loongarch_cacop_d && !Subtarget.is64Bit())
4880 if (IntrinsicEnum == Intrinsic::loongarch_cacop_w && Subtarget.is64Bit())
4889 case Intrinsic::loongarch_dbar: {
4896 case Intrinsic::loongarch_ibar: {
4903 case Intrinsic::loongarch_break: {
4910 case Intrinsic::loongarch_movgr2fcsr: {
4911 if (!Subtarget.hasBasicF())
4921 case Intrinsic::loongarch_syscall: {
4928#define IOCSRWR_CASE(NAME, NODE) \
4929 case Intrinsic::loongarch_##NAME: { \
4930 SDValue Op3 = Op.getOperand(3); \
4931 return Subtarget.is64Bit() \
4932 ? DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, \
4933 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
4934 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op3)) \
4935 : DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, Op2, \
4942 case Intrinsic::loongarch_iocsrwr_d: {
4943 return !Subtarget.is64Bit()
4950#define ASRT_LE_GT_CASE(NAME) \
4951 case Intrinsic::loongarch_##NAME: { \
4952 return !Subtarget.is64Bit() \
4953 ? emitIntrinsicErrorMessage(Op, ErrorMsgReqLA64, DAG) \
4958#undef ASRT_LE_GT_CASE
4959 case Intrinsic::loongarch_ldpte_d: {
4960 unsigned Imm =
Op.getConstantOperandVal(3);
4961 return !Subtarget.is64Bit()
4966 case Intrinsic::loongarch_lsx_vst:
4967 case Intrinsic::loongarch_lasx_xvst:
4971 case Intrinsic::loongarch_lasx_xvstelm_b:
4976 case Intrinsic::loongarch_lsx_vstelm_b:
4981 case Intrinsic::loongarch_lasx_xvstelm_h:
4986 Op,
"argument out of range or not a multiple of 2", DAG)
4988 case Intrinsic::loongarch_lsx_vstelm_h:
4993 Op,
"argument out of range or not a multiple of 2", DAG)
4995 case Intrinsic::loongarch_lasx_xvstelm_w:
5000 Op,
"argument out of range or not a multiple of 4", DAG)
5002 case Intrinsic::loongarch_lsx_vstelm_w:
5007 Op,
"argument out of range or not a multiple of 4", DAG)
5009 case Intrinsic::loongarch_lasx_xvstelm_d:
5014 Op,
"argument out of range or not a multiple of 8", DAG)
5016 case Intrinsic::loongarch_lsx_vstelm_d:
5021 Op,
"argument out of range or not a multiple of 8", DAG)
5032 EVT VT =
Lo.getValueType();
5073 EVT VT =
Lo.getValueType();
5127 return LoongArchISD::DIV_W;
5129 return LoongArchISD::DIV_WU;
5131 return LoongArchISD::MOD_W;
5133 return LoongArchISD::MOD_WU;
5135 return LoongArchISD::SLL_W;
5137 return LoongArchISD::SRA_W;
5139 return LoongArchISD::SRL_W;
5142 return LoongArchISD::ROTR_W;
5144 return LoongArchISD::CTZ_W;
5146 return LoongArchISD::CLZ_W;
5165 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
5166 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0);
5170 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
5176 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0, NewOp1);
5203 StringRef ErrorMsg,
bool WithChain =
true) {
5208 Results.push_back(
N->getOperand(0));
5211template <
unsigned N>
5216 const StringRef ErrorMsgOOR =
"argument out of range";
5217 unsigned Imm =
Node->getConstantOperandVal(2);
5251 switch (
N->getConstantOperandVal(0)) {
5254 case Intrinsic::loongarch_lsx_vpickve2gr_b:
5256 LoongArchISD::VPICK_SEXT_ELT);
5258 case Intrinsic::loongarch_lsx_vpickve2gr_h:
5259 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
5261 LoongArchISD::VPICK_SEXT_ELT);
5263 case Intrinsic::loongarch_lsx_vpickve2gr_w:
5265 LoongArchISD::VPICK_SEXT_ELT);
5267 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
5269 LoongArchISD::VPICK_ZEXT_ELT);
5271 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
5272 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
5274 LoongArchISD::VPICK_ZEXT_ELT);
5276 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
5278 LoongArchISD::VPICK_ZEXT_ELT);
5280 case Intrinsic::loongarch_lsx_bz_b:
5281 case Intrinsic::loongarch_lsx_bz_h:
5282 case Intrinsic::loongarch_lsx_bz_w:
5283 case Intrinsic::loongarch_lsx_bz_d:
5284 case Intrinsic::loongarch_lasx_xbz_b:
5285 case Intrinsic::loongarch_lasx_xbz_h:
5286 case Intrinsic::loongarch_lasx_xbz_w:
5287 case Intrinsic::loongarch_lasx_xbz_d:
5289 LoongArchISD::VALL_ZERO);
5291 case Intrinsic::loongarch_lsx_bz_v:
5292 case Intrinsic::loongarch_lasx_xbz_v:
5294 LoongArchISD::VANY_ZERO);
5296 case Intrinsic::loongarch_lsx_bnz_b:
5297 case Intrinsic::loongarch_lsx_bnz_h:
5298 case Intrinsic::loongarch_lsx_bnz_w:
5299 case Intrinsic::loongarch_lsx_bnz_d:
5300 case Intrinsic::loongarch_lasx_xbnz_b:
5301 case Intrinsic::loongarch_lasx_xbnz_h:
5302 case Intrinsic::loongarch_lasx_xbnz_w:
5303 case Intrinsic::loongarch_lasx_xbnz_d:
5305 LoongArchISD::VALL_NONZERO);
5307 case Intrinsic::loongarch_lsx_bnz_v:
5308 case Intrinsic::loongarch_lasx_xbnz_v:
5310 LoongArchISD::VANY_NONZERO);
5318 assert(
N->getValueType(0) == MVT::i128 &&
5319 "AtomicCmpSwap on types less than 128 should be legal");
5323 switch (
MemOp->getMergedOrdering()) {
5327 Opcode = LoongArch::PseudoCmpXchg128Acquire;
5331 Opcode = LoongArch::PseudoCmpXchg128;
5338 auto CmpVal = DAG.
SplitScalar(
N->getOperand(2),
DL, MVT::i64, MVT::i64);
5339 auto NewVal = DAG.
SplitScalar(
N->getOperand(3),
DL, MVT::i64, MVT::i64);
5340 SDValue Ops[] = {
N->getOperand(1), CmpVal.first, CmpVal.second,
5341 NewVal.first, NewVal.second,
N->getOperand(0)};
5344 Opcode,
SDLoc(
N), DAG.
getVTList(MVT::i64, MVT::i64, MVT::i64, MVT::Other),
5355 EVT VT =
N->getValueType(0);
5356 switch (
N->getOpcode()) {
5361 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
5362 "Unexpected custom legalisation");
5369 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5370 "Unexpected custom legalisation");
5372 Subtarget.hasDiv32() && VT == MVT::i32
5379 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5380 "Unexpected custom legalisation");
5388 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5389 "Unexpected custom legalisation");
5396 MVT VT =
N->getSimpleValueType(0);
5397 assert(VT == MVT::v2f32 && Subtarget.hasExtLSX() &&
5398 "Unexpected custom legalisation");
5400 "Unexpected type action!");
5405 Ld->getPointerInfo(), Ld->getBaseAlign(),
5406 Ld->getMemOperand()->getFlags());
5417 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5418 "Unexpected custom legalisation");
5425 if (Src.getValueType() == MVT::f16)
5436 EVT OpVT = Src.getValueType();
5440 std::tie(Result, Chain) =
5447 EVT SrcVT = Src.getValueType();
5448 if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.is64Bit() &&
5449 Subtarget.hasBasicF()) {
5451 DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Src);
5453 }
else if (VT == MVT::i64 && SrcVT == MVT::f64 && !Subtarget.is64Bit()) {
5455 DAG.
getVTList(MVT::i32, MVT::i32), Src);
5463 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5464 "Unexpected custom legalisation");
5467 TLI.expandFP_TO_UINT(
N, Tmp1, Tmp2, DAG);
5472 assert(VT == MVT::v2f32 && Subtarget.hasExtLSX() &&
5473 "Unexpected custom legalisation");
5479 if (OpVT == MVT::v2f64) {
5489 assert((VT == MVT::i16 || VT == MVT::i32) &&
5490 "Unexpected custom legalization");
5491 MVT GRLenVT = Subtarget.getGRLenVT();
5498 Tmp = DAG.
getNode(LoongArchISD::REVB_2H,
DL, GRLenVT, NewSrc);
5503 Tmp = DAG.
getNode(LoongArchISD::REVB_2W,
DL, GRLenVT, NewSrc);
5511 assert((VT == MVT::i8 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
5512 "Unexpected custom legalization");
5513 MVT GRLenVT = Subtarget.getGRLenVT();
5520 Tmp = DAG.
getNode(LoongArchISD::BITREV_4B,
DL, GRLenVT, NewSrc);
5523 Tmp = DAG.
getNode(LoongArchISD::BITREV_W,
DL, GRLenVT, NewSrc);
5531 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5532 "Unexpected custom legalisation");
5539 MVT GRLenVT = Subtarget.getGRLenVT();
5540 const StringRef ErrorMsgOOR =
"argument out of range";
5541 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
5542 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
5544 switch (
N->getConstantOperandVal(1)) {
5547 case Intrinsic::loongarch_movfcsr2gr: {
5548 if (!Subtarget.hasBasicF()) {
5558 LoongArchISD::MOVFCSR2GR,
SDLoc(
N), {MVT::i64, MVT::Other},
5565#define CRC_CASE_EXT_BINARYOP(NAME, NODE) \
5566 case Intrinsic::loongarch_##NAME: { \
5567 SDValue NODE = DAG.getNode( \
5568 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5569 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
5570 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5571 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5572 Results.push_back(NODE.getValue(1)); \
5581#undef CRC_CASE_EXT_BINARYOP
5583#define CRC_CASE_EXT_UNARYOP(NAME, NODE) \
5584 case Intrinsic::loongarch_##NAME: { \
5585 SDValue NODE = DAG.getNode( \
5586 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5588 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5589 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5590 Results.push_back(NODE.getValue(1)); \
5595#undef CRC_CASE_EXT_UNARYOP
5596#define CSR_CASE(ID) \
5597 case Intrinsic::loongarch_##ID: { \
5598 if (!Subtarget.is64Bit()) \
5599 emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgReqLA64); \
5607 case Intrinsic::loongarch_csrrd_w: {
5614 DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
5621 case Intrinsic::loongarch_csrwr_w: {
5622 unsigned Imm =
N->getConstantOperandVal(3);
5628 DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
5636 case Intrinsic::loongarch_csrxchg_w: {
5637 unsigned Imm =
N->getConstantOperandVal(4);
5643 LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
5652#define IOCSRRD_CASE(NAME, NODE) \
5653 case Intrinsic::loongarch_##NAME: { \
5654 SDValue IOCSRRDResults = \
5655 DAG.getNode(LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5656 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2)}); \
5657 Results.push_back( \
5658 DAG.getNode(ISD::TRUNCATE, DL, VT, IOCSRRDResults.getValue(0))); \
5659 Results.push_back(IOCSRRDResults.getValue(1)); \
5666 case Intrinsic::loongarch_cpucfg: {
5668 DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
5675 case Intrinsic::loongarch_lddir_d: {
5676 if (!Subtarget.is64Bit()) {
5686 if (Subtarget.is64Bit())
5688 "On LA64, only 64-bit registers can be read.");
5691 "On LA32, only 32-bit registers can be read.");
5693 Results.push_back(
N->getOperand(0));
5704 OpVT == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
5717 MVT VT =
N->getSimpleValueType(0);
5723 EVT InVT = In.getValueType();
5734 for (
unsigned I = 0;
I < MinElts; ++
I)
5735 TruncMask[
I] = Scale *
I;
5737 unsigned WidenNumElts = 128 / In.getScalarValueSizeInBits();
5738 MVT SVT = In.getSimpleValueType().getScalarType();
5744 "Illegal vector type in truncation");
5760 assert(
N->getOpcode() ==
ISD::AND &&
"Unexpected opcode combine into ANDN");
5762 MVT VT =
N->getSimpleValueType(0);
5781 return DAG.
getNode(LoongArchISD::VANDN,
DL, VT,
X,
Y);
5785 unsigned MinSizeInBits) {
5793 unsigned SplatBitSize;
5796 return Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
5797 HasAnyUndefs, MinSizeInBits,
5807 EVT VT =
N->getValueType(0);
5873 if (
And.getOperand(0) ==
X) {
5902 if (ShiftVal != (SplatVal + 1))
5911 : LoongArchISD::VSRAR,
5921 SDValue FirstOperand =
N->getOperand(0);
5922 SDValue SecondOperand =
N->getOperand(1);
5923 unsigned FirstOperandOpc = FirstOperand.
getOpcode();
5924 EVT ValTy =
N->getValueType(0);
5927 unsigned SMIdx, SMLen;
5936 if (!Subtarget.has32S())
5992 NewOperand = FirstOperand;
5995 msb = lsb + SMLen - 1;
5999 if (FirstOperandOpc ==
ISD::SRA || FirstOperandOpc ==
ISD::SRL || lsb == 0)
6012 if (!Subtarget.has32S())
6024 SDValue FirstOperand =
N->getOperand(0);
6026 EVT ValTy =
N->getValueType(0);
6029 unsigned MaskIdx, MaskLen;
6044 if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1)
6045 return DAG.
getNode(LoongArchISD::BSTRPICK,
DL, ValTy,
6060 switch (Src.getOpcode()) {
6063 return Src.getOperand(0).getValueSizeInBits() ==
Size;
6073 return Src.getOperand(0).getScalarValueSizeInBits() == 1 &&
6086 switch (Src.getOpcode()) {
6096 Src.getOpcode(),
DL, SExtVT,
6102 DL, SExtVT, Src.getOperand(0),
6114 EVT VT =
N->getValueType(0);
6116 EVT SrcVT = Src.getValueType();
6118 if (Src.getOpcode() !=
ISD::SETCC || !Src.hasOneUse())
6123 EVT CmpVT = Src.getOperand(0).getValueType();
6128 else if (Subtarget.has32S() && Subtarget.hasExtLASX() &&
6141 Opc = UseLASX ? LoongArchISD::XVMSKEQZ : LoongArchISD::VMSKEQZ;
6146 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
6151 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
6156 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
6158 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6163 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
6165 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6170 Opc = UseLASX ? LoongArchISD::XVMSKNEZ : LoongArchISD::VMSKNEZ;
6187 EVT VT =
N->getValueType(0);
6189 EVT SrcVT = Src.getValueType();
6206 bool UseLASX =
false;
6207 bool PropagateSExt =
false;
6209 if (Src.getOpcode() ==
ISD::SETCC && Src.hasOneUse()) {
6210 EVT CmpVT = Src.getOperand(0).getValueType();
6219 SExtVT = MVT::v2i64;
6222 SExtVT = MVT::v4i32;
6224 SExtVT = MVT::v4i64;
6226 PropagateSExt =
true;
6230 SExtVT = MVT::v8i16;
6232 SExtVT = MVT::v8i32;
6234 PropagateSExt =
true;
6238 SExtVT = MVT::v16i8;
6240 SExtVT = MVT::v16i16;
6242 PropagateSExt =
true;
6246 SExtVT = MVT::v32i8;
6254 if (!Subtarget.has32S() || !Subtarget.hasExtLASX()) {
6255 if (Src.getSimpleValueType() == MVT::v32i8) {
6263 }
else if (UseLASX) {
6269 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6282 EVT ValTy =
N->getValueType(0);
6283 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
6287 unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1;
6289 bool SwapAndRetried =
false;
6292 if (!Subtarget.has32S())
6298 if (ValBits != 32 && ValBits != 64)
6313 MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 &&
6316 (MaskIdx0 + MaskLen0 <= ValBits)) {
6337 MaskLen0 == MaskLen1 && MaskIdx1 == 0 &&
6338 (MaskIdx0 + MaskLen0 <= ValBits)) {
6355 (MaskIdx0 + MaskLen0 <= 64) &&
6363 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
6364 : (MaskIdx0 + MaskLen0 - 1),
6380 (MaskIdx0 + MaskLen0 <= ValBits)) {
6403 DAG.
getConstant(ValBits == 32 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
6404 : (MaskIdx0 + MaskLen0 - 1),
6419 unsigned MaskIdx, MaskLen;
6420 if (N1.getOpcode() ==
ISD::SHL && N1.getOperand(0).getOpcode() ==
ISD::AND &&
6429 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
6447 N1.getOperand(0).getOpcode() ==
ISD::SHL &&
6453 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
6461 if (!SwapAndRetried) {
6463 SwapAndRetried =
true;
6467 SwapAndRetried =
false;
6484 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
6493 if (!SwapAndRetried) {
6495 SwapAndRetried =
true;
6505 switch (V.getNode()->getOpcode()) {
6517 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
6525 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
6602 SDNode *AndNode =
N->getOperand(0).getNode();
6610 SDValue CmpInputValue =
N->getOperand(1);
6619 if (!CN || !CN->
isZero())
6621 AndInputValue1 = AndInputValue1.
getOperand(0);
6625 if (AndInputValue2 != CmpInputValue)
6658 TruncInputValue1, TruncInputValue2);
6660 DAG.
getSetCC(
SDLoc(
N),
N->getValueType(0), NewAnd, TruncInputValue2, CC);
6673 if (Src.getOpcode() != LoongArchISD::REVB_2W)
6676 return DAG.
getNode(LoongArchISD::BITREV_4B,
SDLoc(
N),
N->getValueType(0),
6701 LHS.getOperand(0).getValueType() == Subtarget.
getGRLenVT()) {
6729 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
6762 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
N->getValueType(0),
6763 N->getOperand(0),
LHS,
RHS, CC,
N->getOperand(4));
6779 EVT VT =
N->getValueType(0);
6782 if (TrueV == FalseV)
6813 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL,
N->getValueType(0),
6814 {LHS, RHS, CC, TrueV, FalseV});
6819template <
unsigned N>
6823 bool IsSigned =
false) {
6827 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
6828 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
6830 ": argument out of range.");
6836template <
unsigned N>
6840 EVT ResTy =
Node->getValueType(0);
6844 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
6845 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
6847 ": argument out of range.");
6852 IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned),
6858 EVT ResTy =
Node->getValueType(0);
6866 EVT ResTy =
Node->getValueType(0);
6875template <
unsigned N>
6878 EVT ResTy =
Node->getValueType(0);
6883 ": argument out of range.");
6893template <
unsigned N>
6896 EVT ResTy =
Node->getValueType(0);
6901 ": argument out of range.");
6910template <
unsigned N>
6913 EVT ResTy =
Node->getValueType(0);
6918 ": argument out of range.");
6927template <
unsigned W>
6930 unsigned Imm =
N->getConstantOperandVal(2);
6932 const StringRef ErrorMsg =
"argument out of range";
6934 return DAG.
getUNDEF(
N->getValueType(0));
6940 return DAG.
getNode(ResOp,
DL,
N->getValueType(0), Vec, Idx, EltVT);
6948 switch (
N->getConstantOperandVal(0)) {
6951 case Intrinsic::loongarch_lsx_vadd_b:
6952 case Intrinsic::loongarch_lsx_vadd_h:
6953 case Intrinsic::loongarch_lsx_vadd_w:
6954 case Intrinsic::loongarch_lsx_vadd_d:
6955 case Intrinsic::loongarch_lasx_xvadd_b:
6956 case Intrinsic::loongarch_lasx_xvadd_h:
6957 case Intrinsic::loongarch_lasx_xvadd_w:
6958 case Intrinsic::loongarch_lasx_xvadd_d:
6961 case Intrinsic::loongarch_lsx_vaddi_bu:
6962 case Intrinsic::loongarch_lsx_vaddi_hu:
6963 case Intrinsic::loongarch_lsx_vaddi_wu:
6964 case Intrinsic::loongarch_lsx_vaddi_du:
6965 case Intrinsic::loongarch_lasx_xvaddi_bu:
6966 case Intrinsic::loongarch_lasx_xvaddi_hu:
6967 case Intrinsic::loongarch_lasx_xvaddi_wu:
6968 case Intrinsic::loongarch_lasx_xvaddi_du:
6971 case Intrinsic::loongarch_lsx_vsub_b:
6972 case Intrinsic::loongarch_lsx_vsub_h:
6973 case Intrinsic::loongarch_lsx_vsub_w:
6974 case Intrinsic::loongarch_lsx_vsub_d:
6975 case Intrinsic::loongarch_lasx_xvsub_b:
6976 case Intrinsic::loongarch_lasx_xvsub_h:
6977 case Intrinsic::loongarch_lasx_xvsub_w:
6978 case Intrinsic::loongarch_lasx_xvsub_d:
6981 case Intrinsic::loongarch_lsx_vsubi_bu:
6982 case Intrinsic::loongarch_lsx_vsubi_hu:
6983 case Intrinsic::loongarch_lsx_vsubi_wu:
6984 case Intrinsic::loongarch_lsx_vsubi_du:
6985 case Intrinsic::loongarch_lasx_xvsubi_bu:
6986 case Intrinsic::loongarch_lasx_xvsubi_hu:
6987 case Intrinsic::loongarch_lasx_xvsubi_wu:
6988 case Intrinsic::loongarch_lasx_xvsubi_du:
6991 case Intrinsic::loongarch_lsx_vneg_b:
6992 case Intrinsic::loongarch_lsx_vneg_h:
6993 case Intrinsic::loongarch_lsx_vneg_w:
6994 case Intrinsic::loongarch_lsx_vneg_d:
6995 case Intrinsic::loongarch_lasx_xvneg_b:
6996 case Intrinsic::loongarch_lasx_xvneg_h:
6997 case Intrinsic::loongarch_lasx_xvneg_w:
6998 case Intrinsic::loongarch_lasx_xvneg_d:
7002 APInt(
N->getValueType(0).getScalarType().getSizeInBits(), 0,
7004 SDLoc(
N),
N->getValueType(0)),
7006 case Intrinsic::loongarch_lsx_vmax_b:
7007 case Intrinsic::loongarch_lsx_vmax_h:
7008 case Intrinsic::loongarch_lsx_vmax_w:
7009 case Intrinsic::loongarch_lsx_vmax_d:
7010 case Intrinsic::loongarch_lasx_xvmax_b:
7011 case Intrinsic::loongarch_lasx_xvmax_h:
7012 case Intrinsic::loongarch_lasx_xvmax_w:
7013 case Intrinsic::loongarch_lasx_xvmax_d:
7016 case Intrinsic::loongarch_lsx_vmax_bu:
7017 case Intrinsic::loongarch_lsx_vmax_hu:
7018 case Intrinsic::loongarch_lsx_vmax_wu:
7019 case Intrinsic::loongarch_lsx_vmax_du:
7020 case Intrinsic::loongarch_lasx_xvmax_bu:
7021 case Intrinsic::loongarch_lasx_xvmax_hu:
7022 case Intrinsic::loongarch_lasx_xvmax_wu:
7023 case Intrinsic::loongarch_lasx_xvmax_du:
7026 case Intrinsic::loongarch_lsx_vmaxi_b:
7027 case Intrinsic::loongarch_lsx_vmaxi_h:
7028 case Intrinsic::loongarch_lsx_vmaxi_w:
7029 case Intrinsic::loongarch_lsx_vmaxi_d:
7030 case Intrinsic::loongarch_lasx_xvmaxi_b:
7031 case Intrinsic::loongarch_lasx_xvmaxi_h:
7032 case Intrinsic::loongarch_lasx_xvmaxi_w:
7033 case Intrinsic::loongarch_lasx_xvmaxi_d:
7036 case Intrinsic::loongarch_lsx_vmaxi_bu:
7037 case Intrinsic::loongarch_lsx_vmaxi_hu:
7038 case Intrinsic::loongarch_lsx_vmaxi_wu:
7039 case Intrinsic::loongarch_lsx_vmaxi_du:
7040 case Intrinsic::loongarch_lasx_xvmaxi_bu:
7041 case Intrinsic::loongarch_lasx_xvmaxi_hu:
7042 case Intrinsic::loongarch_lasx_xvmaxi_wu:
7043 case Intrinsic::loongarch_lasx_xvmaxi_du:
7046 case Intrinsic::loongarch_lsx_vmin_b:
7047 case Intrinsic::loongarch_lsx_vmin_h:
7048 case Intrinsic::loongarch_lsx_vmin_w:
7049 case Intrinsic::loongarch_lsx_vmin_d:
7050 case Intrinsic::loongarch_lasx_xvmin_b:
7051 case Intrinsic::loongarch_lasx_xvmin_h:
7052 case Intrinsic::loongarch_lasx_xvmin_w:
7053 case Intrinsic::loongarch_lasx_xvmin_d:
7056 case Intrinsic::loongarch_lsx_vmin_bu:
7057 case Intrinsic::loongarch_lsx_vmin_hu:
7058 case Intrinsic::loongarch_lsx_vmin_wu:
7059 case Intrinsic::loongarch_lsx_vmin_du:
7060 case Intrinsic::loongarch_lasx_xvmin_bu:
7061 case Intrinsic::loongarch_lasx_xvmin_hu:
7062 case Intrinsic::loongarch_lasx_xvmin_wu:
7063 case Intrinsic::loongarch_lasx_xvmin_du:
7066 case Intrinsic::loongarch_lsx_vmini_b:
7067 case Intrinsic::loongarch_lsx_vmini_h:
7068 case Intrinsic::loongarch_lsx_vmini_w:
7069 case Intrinsic::loongarch_lsx_vmini_d:
7070 case Intrinsic::loongarch_lasx_xvmini_b:
7071 case Intrinsic::loongarch_lasx_xvmini_h:
7072 case Intrinsic::loongarch_lasx_xvmini_w:
7073 case Intrinsic::loongarch_lasx_xvmini_d:
7076 case Intrinsic::loongarch_lsx_vmini_bu:
7077 case Intrinsic::loongarch_lsx_vmini_hu:
7078 case Intrinsic::loongarch_lsx_vmini_wu:
7079 case Intrinsic::loongarch_lsx_vmini_du:
7080 case Intrinsic::loongarch_lasx_xvmini_bu:
7081 case Intrinsic::loongarch_lasx_xvmini_hu:
7082 case Intrinsic::loongarch_lasx_xvmini_wu:
7083 case Intrinsic::loongarch_lasx_xvmini_du:
7086 case Intrinsic::loongarch_lsx_vmul_b:
7087 case Intrinsic::loongarch_lsx_vmul_h:
7088 case Intrinsic::loongarch_lsx_vmul_w:
7089 case Intrinsic::loongarch_lsx_vmul_d:
7090 case Intrinsic::loongarch_lasx_xvmul_b:
7091 case Intrinsic::loongarch_lasx_xvmul_h:
7092 case Intrinsic::loongarch_lasx_xvmul_w:
7093 case Intrinsic::loongarch_lasx_xvmul_d:
7096 case Intrinsic::loongarch_lsx_vmadd_b:
7097 case Intrinsic::loongarch_lsx_vmadd_h:
7098 case Intrinsic::loongarch_lsx_vmadd_w:
7099 case Intrinsic::loongarch_lsx_vmadd_d:
7100 case Intrinsic::loongarch_lasx_xvmadd_b:
7101 case Intrinsic::loongarch_lasx_xvmadd_h:
7102 case Intrinsic::loongarch_lasx_xvmadd_w:
7103 case Intrinsic::loongarch_lasx_xvmadd_d: {
7104 EVT ResTy =
N->getValueType(0);
7109 case Intrinsic::loongarch_lsx_vmsub_b:
7110 case Intrinsic::loongarch_lsx_vmsub_h:
7111 case Intrinsic::loongarch_lsx_vmsub_w:
7112 case Intrinsic::loongarch_lsx_vmsub_d:
7113 case Intrinsic::loongarch_lasx_xvmsub_b:
7114 case Intrinsic::loongarch_lasx_xvmsub_h:
7115 case Intrinsic::loongarch_lasx_xvmsub_w:
7116 case Intrinsic::loongarch_lasx_xvmsub_d: {
7117 EVT ResTy =
N->getValueType(0);
7122 case Intrinsic::loongarch_lsx_vdiv_b:
7123 case Intrinsic::loongarch_lsx_vdiv_h:
7124 case Intrinsic::loongarch_lsx_vdiv_w:
7125 case Intrinsic::loongarch_lsx_vdiv_d:
7126 case Intrinsic::loongarch_lasx_xvdiv_b:
7127 case Intrinsic::loongarch_lasx_xvdiv_h:
7128 case Intrinsic::loongarch_lasx_xvdiv_w:
7129 case Intrinsic::loongarch_lasx_xvdiv_d:
7132 case Intrinsic::loongarch_lsx_vdiv_bu:
7133 case Intrinsic::loongarch_lsx_vdiv_hu:
7134 case Intrinsic::loongarch_lsx_vdiv_wu:
7135 case Intrinsic::loongarch_lsx_vdiv_du:
7136 case Intrinsic::loongarch_lasx_xvdiv_bu:
7137 case Intrinsic::loongarch_lasx_xvdiv_hu:
7138 case Intrinsic::loongarch_lasx_xvdiv_wu:
7139 case Intrinsic::loongarch_lasx_xvdiv_du:
7142 case Intrinsic::loongarch_lsx_vmod_b:
7143 case Intrinsic::loongarch_lsx_vmod_h:
7144 case Intrinsic::loongarch_lsx_vmod_w:
7145 case Intrinsic::loongarch_lsx_vmod_d:
7146 case Intrinsic::loongarch_lasx_xvmod_b:
7147 case Intrinsic::loongarch_lasx_xvmod_h:
7148 case Intrinsic::loongarch_lasx_xvmod_w:
7149 case Intrinsic::loongarch_lasx_xvmod_d:
7152 case Intrinsic::loongarch_lsx_vmod_bu:
7153 case Intrinsic::loongarch_lsx_vmod_hu:
7154 case Intrinsic::loongarch_lsx_vmod_wu:
7155 case Intrinsic::loongarch_lsx_vmod_du:
7156 case Intrinsic::loongarch_lasx_xvmod_bu:
7157 case Intrinsic::loongarch_lasx_xvmod_hu:
7158 case Intrinsic::loongarch_lasx_xvmod_wu:
7159 case Intrinsic::loongarch_lasx_xvmod_du:
7162 case Intrinsic::loongarch_lsx_vand_v:
7163 case Intrinsic::loongarch_lasx_xvand_v:
7166 case Intrinsic::loongarch_lsx_vor_v:
7167 case Intrinsic::loongarch_lasx_xvor_v:
7170 case Intrinsic::loongarch_lsx_vxor_v:
7171 case Intrinsic::loongarch_lasx_xvxor_v:
7174 case Intrinsic::loongarch_lsx_vnor_v:
7175 case Intrinsic::loongarch_lasx_xvnor_v: {
7180 case Intrinsic::loongarch_lsx_vandi_b:
7181 case Intrinsic::loongarch_lasx_xvandi_b:
7184 case Intrinsic::loongarch_lsx_vori_b:
7185 case Intrinsic::loongarch_lasx_xvori_b:
7188 case Intrinsic::loongarch_lsx_vxori_b:
7189 case Intrinsic::loongarch_lasx_xvxori_b:
7192 case Intrinsic::loongarch_lsx_vsll_b:
7193 case Intrinsic::loongarch_lsx_vsll_h:
7194 case Intrinsic::loongarch_lsx_vsll_w:
7195 case Intrinsic::loongarch_lsx_vsll_d:
7196 case Intrinsic::loongarch_lasx_xvsll_b:
7197 case Intrinsic::loongarch_lasx_xvsll_h:
7198 case Intrinsic::loongarch_lasx_xvsll_w:
7199 case Intrinsic::loongarch_lasx_xvsll_d:
7202 case Intrinsic::loongarch_lsx_vslli_b:
7203 case Intrinsic::loongarch_lasx_xvslli_b:
7206 case Intrinsic::loongarch_lsx_vslli_h:
7207 case Intrinsic::loongarch_lasx_xvslli_h:
7210 case Intrinsic::loongarch_lsx_vslli_w:
7211 case Intrinsic::loongarch_lasx_xvslli_w:
7214 case Intrinsic::loongarch_lsx_vslli_d:
7215 case Intrinsic::loongarch_lasx_xvslli_d:
7218 case Intrinsic::loongarch_lsx_vsrl_b:
7219 case Intrinsic::loongarch_lsx_vsrl_h:
7220 case Intrinsic::loongarch_lsx_vsrl_w:
7221 case Intrinsic::loongarch_lsx_vsrl_d:
7222 case Intrinsic::loongarch_lasx_xvsrl_b:
7223 case Intrinsic::loongarch_lasx_xvsrl_h:
7224 case Intrinsic::loongarch_lasx_xvsrl_w:
7225 case Intrinsic::loongarch_lasx_xvsrl_d:
7228 case Intrinsic::loongarch_lsx_vsrli_b:
7229 case Intrinsic::loongarch_lasx_xvsrli_b:
7232 case Intrinsic::loongarch_lsx_vsrli_h:
7233 case Intrinsic::loongarch_lasx_xvsrli_h:
7236 case Intrinsic::loongarch_lsx_vsrli_w:
7237 case Intrinsic::loongarch_lasx_xvsrli_w:
7240 case Intrinsic::loongarch_lsx_vsrli_d:
7241 case Intrinsic::loongarch_lasx_xvsrli_d:
7244 case Intrinsic::loongarch_lsx_vsra_b:
7245 case Intrinsic::loongarch_lsx_vsra_h:
7246 case Intrinsic::loongarch_lsx_vsra_w:
7247 case Intrinsic::loongarch_lsx_vsra_d:
7248 case Intrinsic::loongarch_lasx_xvsra_b:
7249 case Intrinsic::loongarch_lasx_xvsra_h:
7250 case Intrinsic::loongarch_lasx_xvsra_w:
7251 case Intrinsic::loongarch_lasx_xvsra_d:
7254 case Intrinsic::loongarch_lsx_vsrai_b:
7255 case Intrinsic::loongarch_lasx_xvsrai_b:
7258 case Intrinsic::loongarch_lsx_vsrai_h:
7259 case Intrinsic::loongarch_lasx_xvsrai_h:
7262 case Intrinsic::loongarch_lsx_vsrai_w:
7263 case Intrinsic::loongarch_lasx_xvsrai_w:
7266 case Intrinsic::loongarch_lsx_vsrai_d:
7267 case Intrinsic::loongarch_lasx_xvsrai_d:
7270 case Intrinsic::loongarch_lsx_vclz_b:
7271 case Intrinsic::loongarch_lsx_vclz_h:
7272 case Intrinsic::loongarch_lsx_vclz_w:
7273 case Intrinsic::loongarch_lsx_vclz_d:
7274 case Intrinsic::loongarch_lasx_xvclz_b:
7275 case Intrinsic::loongarch_lasx_xvclz_h:
7276 case Intrinsic::loongarch_lasx_xvclz_w:
7277 case Intrinsic::loongarch_lasx_xvclz_d:
7279 case Intrinsic::loongarch_lsx_vpcnt_b:
7280 case Intrinsic::loongarch_lsx_vpcnt_h:
7281 case Intrinsic::loongarch_lsx_vpcnt_w:
7282 case Intrinsic::loongarch_lsx_vpcnt_d:
7283 case Intrinsic::loongarch_lasx_xvpcnt_b:
7284 case Intrinsic::loongarch_lasx_xvpcnt_h:
7285 case Intrinsic::loongarch_lasx_xvpcnt_w:
7286 case Intrinsic::loongarch_lasx_xvpcnt_d:
7288 case Intrinsic::loongarch_lsx_vbitclr_b:
7289 case Intrinsic::loongarch_lsx_vbitclr_h:
7290 case Intrinsic::loongarch_lsx_vbitclr_w:
7291 case Intrinsic::loongarch_lsx_vbitclr_d:
7292 case Intrinsic::loongarch_lasx_xvbitclr_b:
7293 case Intrinsic::loongarch_lasx_xvbitclr_h:
7294 case Intrinsic::loongarch_lasx_xvbitclr_w:
7295 case Intrinsic::loongarch_lasx_xvbitclr_d:
7297 case Intrinsic::loongarch_lsx_vbitclri_b:
7298 case Intrinsic::loongarch_lasx_xvbitclri_b:
7300 case Intrinsic::loongarch_lsx_vbitclri_h:
7301 case Intrinsic::loongarch_lasx_xvbitclri_h:
7303 case Intrinsic::loongarch_lsx_vbitclri_w:
7304 case Intrinsic::loongarch_lasx_xvbitclri_w:
7306 case Intrinsic::loongarch_lsx_vbitclri_d:
7307 case Intrinsic::loongarch_lasx_xvbitclri_d:
7309 case Intrinsic::loongarch_lsx_vbitset_b:
7310 case Intrinsic::loongarch_lsx_vbitset_h:
7311 case Intrinsic::loongarch_lsx_vbitset_w:
7312 case Intrinsic::loongarch_lsx_vbitset_d:
7313 case Intrinsic::loongarch_lasx_xvbitset_b:
7314 case Intrinsic::loongarch_lasx_xvbitset_h:
7315 case Intrinsic::loongarch_lasx_xvbitset_w:
7316 case Intrinsic::loongarch_lasx_xvbitset_d: {
7317 EVT VecTy =
N->getValueType(0);
7323 case Intrinsic::loongarch_lsx_vbitseti_b:
7324 case Intrinsic::loongarch_lasx_xvbitseti_b:
7326 case Intrinsic::loongarch_lsx_vbitseti_h:
7327 case Intrinsic::loongarch_lasx_xvbitseti_h:
7329 case Intrinsic::loongarch_lsx_vbitseti_w:
7330 case Intrinsic::loongarch_lasx_xvbitseti_w:
7332 case Intrinsic::loongarch_lsx_vbitseti_d:
7333 case Intrinsic::loongarch_lasx_xvbitseti_d:
7335 case Intrinsic::loongarch_lsx_vbitrev_b:
7336 case Intrinsic::loongarch_lsx_vbitrev_h:
7337 case Intrinsic::loongarch_lsx_vbitrev_w:
7338 case Intrinsic::loongarch_lsx_vbitrev_d:
7339 case Intrinsic::loongarch_lasx_xvbitrev_b:
7340 case Intrinsic::loongarch_lasx_xvbitrev_h:
7341 case Intrinsic::loongarch_lasx_xvbitrev_w:
7342 case Intrinsic::loongarch_lasx_xvbitrev_d: {
7343 EVT VecTy =
N->getValueType(0);
7349 case Intrinsic::loongarch_lsx_vbitrevi_b:
7350 case Intrinsic::loongarch_lasx_xvbitrevi_b:
7352 case Intrinsic::loongarch_lsx_vbitrevi_h:
7353 case Intrinsic::loongarch_lasx_xvbitrevi_h:
7355 case Intrinsic::loongarch_lsx_vbitrevi_w:
7356 case Intrinsic::loongarch_lasx_xvbitrevi_w:
7358 case Intrinsic::loongarch_lsx_vbitrevi_d:
7359 case Intrinsic::loongarch_lasx_xvbitrevi_d:
7361 case Intrinsic::loongarch_lsx_vfadd_s:
7362 case Intrinsic::loongarch_lsx_vfadd_d:
7363 case Intrinsic::loongarch_lasx_xvfadd_s:
7364 case Intrinsic::loongarch_lasx_xvfadd_d:
7367 case Intrinsic::loongarch_lsx_vfsub_s:
7368 case Intrinsic::loongarch_lsx_vfsub_d:
7369 case Intrinsic::loongarch_lasx_xvfsub_s:
7370 case Intrinsic::loongarch_lasx_xvfsub_d:
7373 case Intrinsic::loongarch_lsx_vfmul_s:
7374 case Intrinsic::loongarch_lsx_vfmul_d:
7375 case Intrinsic::loongarch_lasx_xvfmul_s:
7376 case Intrinsic::loongarch_lasx_xvfmul_d:
7379 case Intrinsic::loongarch_lsx_vfdiv_s:
7380 case Intrinsic::loongarch_lsx_vfdiv_d:
7381 case Intrinsic::loongarch_lasx_xvfdiv_s:
7382 case Intrinsic::loongarch_lasx_xvfdiv_d:
7385 case Intrinsic::loongarch_lsx_vfmadd_s:
7386 case Intrinsic::loongarch_lsx_vfmadd_d:
7387 case Intrinsic::loongarch_lasx_xvfmadd_s:
7388 case Intrinsic::loongarch_lasx_xvfmadd_d:
7390 N->getOperand(2),
N->getOperand(3));
7391 case Intrinsic::loongarch_lsx_vinsgr2vr_b:
7393 N->getOperand(1),
N->getOperand(2),
7395 case Intrinsic::loongarch_lsx_vinsgr2vr_h:
7396 case Intrinsic::loongarch_lasx_xvinsgr2vr_w:
7398 N->getOperand(1),
N->getOperand(2),
7400 case Intrinsic::loongarch_lsx_vinsgr2vr_w:
7401 case Intrinsic::loongarch_lasx_xvinsgr2vr_d:
7403 N->getOperand(1),
N->getOperand(2),
7405 case Intrinsic::loongarch_lsx_vinsgr2vr_d:
7407 N->getOperand(1),
N->getOperand(2),
7409 case Intrinsic::loongarch_lsx_vreplgr2vr_b:
7410 case Intrinsic::loongarch_lsx_vreplgr2vr_h:
7411 case Intrinsic::loongarch_lsx_vreplgr2vr_w:
7412 case Intrinsic::loongarch_lsx_vreplgr2vr_d:
7413 case Intrinsic::loongarch_lasx_xvreplgr2vr_b:
7414 case Intrinsic::loongarch_lasx_xvreplgr2vr_h:
7415 case Intrinsic::loongarch_lasx_xvreplgr2vr_w:
7416 case Intrinsic::loongarch_lasx_xvreplgr2vr_d:
7417 return DAG.
getNode(LoongArchISD::VREPLGR2VR,
DL,
N->getValueType(0),
7420 case Intrinsic::loongarch_lsx_vreplve_b:
7421 case Intrinsic::loongarch_lsx_vreplve_h:
7422 case Intrinsic::loongarch_lsx_vreplve_w:
7423 case Intrinsic::loongarch_lsx_vreplve_d:
7424 case Intrinsic::loongarch_lasx_xvreplve_b:
7425 case Intrinsic::loongarch_lasx_xvreplve_h:
7426 case Intrinsic::loongarch_lasx_xvreplve_w:
7427 case Intrinsic::loongarch_lasx_xvreplve_d:
7428 return DAG.
getNode(LoongArchISD::VREPLVE,
DL,
N->getValueType(0),
7432 case Intrinsic::loongarch_lsx_vpickve2gr_b:
7436 case Intrinsic::loongarch_lsx_vpickve2gr_h:
7437 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
7441 case Intrinsic::loongarch_lsx_vpickve2gr_w:
7445 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
7449 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
7450 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
7454 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
7458 case Intrinsic::loongarch_lsx_bz_b:
7459 case Intrinsic::loongarch_lsx_bz_h:
7460 case Intrinsic::loongarch_lsx_bz_w:
7461 case Intrinsic::loongarch_lsx_bz_d:
7462 case Intrinsic::loongarch_lasx_xbz_b:
7463 case Intrinsic::loongarch_lasx_xbz_h:
7464 case Intrinsic::loongarch_lasx_xbz_w:
7465 case Intrinsic::loongarch_lasx_xbz_d:
7467 return DAG.
getNode(LoongArchISD::VALL_ZERO,
DL,
N->getValueType(0),
7470 case Intrinsic::loongarch_lsx_bz_v:
7471 case Intrinsic::loongarch_lasx_xbz_v:
7473 return DAG.
getNode(LoongArchISD::VANY_ZERO,
DL,
N->getValueType(0),
7476 case Intrinsic::loongarch_lsx_bnz_b:
7477 case Intrinsic::loongarch_lsx_bnz_h:
7478 case Intrinsic::loongarch_lsx_bnz_w:
7479 case Intrinsic::loongarch_lsx_bnz_d:
7480 case Intrinsic::loongarch_lasx_xbnz_b:
7481 case Intrinsic::loongarch_lasx_xbnz_h:
7482 case Intrinsic::loongarch_lasx_xbnz_w:
7483 case Intrinsic::loongarch_lasx_xbnz_d:
7485 return DAG.
getNode(LoongArchISD::VALL_NONZERO,
DL,
N->getValueType(0),
7488 case Intrinsic::loongarch_lsx_bnz_v:
7489 case Intrinsic::loongarch_lasx_xbnz_v:
7491 return DAG.
getNode(LoongArchISD::VANY_NONZERO,
DL,
N->getValueType(0),
7494 case Intrinsic::loongarch_lasx_concat_128_s:
7495 case Intrinsic::loongarch_lasx_concat_128_d:
7496 case Intrinsic::loongarch_lasx_concat_128:
7498 N->getOperand(1),
N->getOperand(2));
7510 if (Op0.
getOpcode() == LoongArchISD::MOVFR2GR_S_LA64)
7522 if (Op0->
getOpcode() == LoongArchISD::MOVGR2FR_W_LA64) {
7524 "Unexpected value type!");
7533 MVT VT =
N->getSimpleValueType(0);
7554 if (Op0->
getOpcode() == LoongArchISD::BUILD_PAIR_F64)
7567 APInt V =
C->getValueAPF().bitcastToAPInt();
7582 MVT VT =
N->getSimpleValueType(0);
7643 EVT VT =
N->getValueType(0);
7645 if (VT != MVT::f32 && VT != MVT::f64)
7647 if (VT == MVT::f32 && !Subtarget.hasBasicF())
7649 if (VT == MVT::f64 && !Subtarget.hasBasicD())
7672 return DAG.
getNode(LoongArchISD::SITOF,
SDLoc(
N), VT, Load);
7729 Subtarget.hasExtLASX() && N1.
hasOneUse())
7741 return DAG.
getNode(
N.getOpcode(),
DL, VT, N0, N1);
7751 EVT VT =
N.getValueType();
7768 switch (
N.getOpcode()) {
7784 EVT VT =
N->getValueType(0);
7799 EVT VT =
N->getValueType(0);
7801 if (VT.
isVector() &&
N->getNumOperands() == 2)
7814 EVT VT =
N->getValueType(0);
7826 SDValue TrueVal =
N->getOperand(1);
7827 SDValue FalseVal =
N->getOperand(2);
7861 if (FalseVal.getOpcode() !=
ISD::ADD)
7864 SDValue Add0 = FalseVal.getOperand(0);
7865 SDValue Add1 = FalseVal.getOperand(1);
7935 : LoongArchISD::VSRAR,
7942 switch (
N->getOpcode()) {
7963 case LoongArchISD::BITREV_W:
7965 case LoongArchISD::BR_CC:
7967 case LoongArchISD::SELECT_CC:
7971 case LoongArchISD::MOVGR2FR_W_LA64:
7973 case LoongArchISD::MOVFR2GR_S_LA64:
7975 case LoongArchISD::VMSKLTZ:
7976 case LoongArchISD::XVMSKLTZ:
7978 case LoongArchISD::SPLIT_PAIR_F64:
7980 case LoongArchISD::VANDN:
7986 case LoongArchISD::VPACKEV:
7987 case LoongArchISD::VPERMI:
8013 MF->
insert(It, BreakMBB);
8017 SinkMBB->splice(SinkMBB->end(),
MBB, std::next(
MI.getIterator()),
MBB->end());
8018 SinkMBB->transferSuccessorsAndUpdatePHIs(
MBB);
8030 MBB->addSuccessor(BreakMBB);
8031 MBB->addSuccessor(SinkMBB);
8037 BreakMBB->addSuccessor(SinkMBB);
8049 switch (
MI.getOpcode()) {
8052 case LoongArch::PseudoVBZ:
8053 CondOpc = LoongArch::VSETEQZ_V;
8055 case LoongArch::PseudoVBZ_B:
8056 CondOpc = LoongArch::VSETANYEQZ_B;
8058 case LoongArch::PseudoVBZ_H:
8059 CondOpc = LoongArch::VSETANYEQZ_H;
8061 case LoongArch::PseudoVBZ_W:
8062 CondOpc = LoongArch::VSETANYEQZ_W;
8064 case LoongArch::PseudoVBZ_D:
8065 CondOpc = LoongArch::VSETANYEQZ_D;
8067 case LoongArch::PseudoVBNZ:
8068 CondOpc = LoongArch::VSETNEZ_V;
8070 case LoongArch::PseudoVBNZ_B:
8071 CondOpc = LoongArch::VSETALLNEZ_B;
8073 case LoongArch::PseudoVBNZ_H:
8074 CondOpc = LoongArch::VSETALLNEZ_H;
8076 case LoongArch::PseudoVBNZ_W:
8077 CondOpc = LoongArch::VSETALLNEZ_W;
8079 case LoongArch::PseudoVBNZ_D:
8080 CondOpc = LoongArch::VSETALLNEZ_D;
8082 case LoongArch::PseudoXVBZ:
8083 CondOpc = LoongArch::XVSETEQZ_V;
8085 case LoongArch::PseudoXVBZ_B:
8086 CondOpc = LoongArch::XVSETANYEQZ_B;
8088 case LoongArch::PseudoXVBZ_H:
8089 CondOpc = LoongArch::XVSETANYEQZ_H;
8091 case LoongArch::PseudoXVBZ_W:
8092 CondOpc = LoongArch::XVSETANYEQZ_W;
8094 case LoongArch::PseudoXVBZ_D:
8095 CondOpc = LoongArch::XVSETANYEQZ_D;
8097 case LoongArch::PseudoXVBNZ:
8098 CondOpc = LoongArch::XVSETNEZ_V;
8100 case LoongArch::PseudoXVBNZ_B:
8101 CondOpc = LoongArch::XVSETALLNEZ_B;
8103 case LoongArch::PseudoXVBNZ_H:
8104 CondOpc = LoongArch::XVSETALLNEZ_H;
8106 case LoongArch::PseudoXVBNZ_W:
8107 CondOpc = LoongArch::XVSETALLNEZ_W;
8109 case LoongArch::PseudoXVBNZ_D:
8110 CondOpc = LoongArch::XVSETALLNEZ_D;
8125 F->insert(It, FalseBB);
8126 F->insert(It, TrueBB);
8127 F->insert(It, SinkBB);
8130 SinkBB->
splice(SinkBB->
end(), BB, std::next(
MI.getIterator()), BB->
end());
8159 MI.getOperand(0).getReg())
8166 MI.eraseFromParent();
8174 unsigned BroadcastOp;
8176 switch (
MI.getOpcode()) {
8179 case LoongArch::PseudoXVINSGR2VR_B:
8181 BroadcastOp = LoongArch::XVREPLGR2VR_B;
8182 InsOp = LoongArch::XVEXTRINS_B;
8184 case LoongArch::PseudoXVINSGR2VR_H:
8186 BroadcastOp = LoongArch::XVREPLGR2VR_H;
8187 InsOp = LoongArch::XVEXTRINS_H;
8199 unsigned Idx =
MI.getOperand(3).getImm();
8207 .
addReg(XSrc, {}, LoongArch::sub_128);
8209 TII->get(HalfSize == 8 ? LoongArch::VINSGR2VR_H
8210 : LoongArch::VINSGR2VR_B),
8218 .
addImm(LoongArch::sub_128);
8225 BuildMI(*BB,
MI,
DL,
TII->get(LoongArch::XVPERMI_Q), ScratchReg2)
8228 .
addImm(Idx >= HalfSize ? 48 : 18);
8233 .
addImm((Idx >= HalfSize ? Idx - HalfSize : Idx) * 17);
8236 MI.eraseFromParent();
8243 assert(Subtarget.hasExtLSX());
8251 unsigned BroadcastOp, CTOp, PickOp;
8252 switch (
MI.getOpcode()) {
8255 case LoongArch::PseudoCTPOP_B:
8256 BroadcastOp = LoongArch::VREPLGR2VR_B;
8257 CTOp = LoongArch::VPCNT_B;
8258 PickOp = LoongArch::VPICKVE2GR_B;
8260 case LoongArch::PseudoCTPOP_H:
8261 case LoongArch::PseudoCTPOP_H_LA32:
8262 BroadcastOp = LoongArch::VREPLGR2VR_H;
8263 CTOp = LoongArch::VPCNT_H;
8264 PickOp = LoongArch::VPICKVE2GR_H;
8266 case LoongArch::PseudoCTPOP_W:
8267 case LoongArch::PseudoCTPOP_W_LA32:
8268 BroadcastOp = LoongArch::VREPLGR2VR_W;
8269 CTOp = LoongArch::VPCNT_W;
8270 PickOp = LoongArch::VPICKVE2GR_W;
8272 case LoongArch::PseudoCTPOP_D:
8273 BroadcastOp = LoongArch::VREPLGR2VR_D;
8274 CTOp = LoongArch::VPCNT_D;
8275 PickOp = LoongArch::VPICKVE2GR_D;
8285 MI.eraseFromParent();
8299 unsigned EleBits = 8;
8300 unsigned NotOpc = 0;
8303 switch (
MI.getOpcode()) {
8306 case LoongArch::PseudoVMSKLTZ_B:
8307 MskOpc = LoongArch::VMSKLTZ_B;
8309 case LoongArch::PseudoVMSKLTZ_H:
8310 MskOpc = LoongArch::VMSKLTZ_H;
8313 case LoongArch::PseudoVMSKLTZ_W:
8314 MskOpc = LoongArch::VMSKLTZ_W;
8317 case LoongArch::PseudoVMSKLTZ_D:
8318 MskOpc = LoongArch::VMSKLTZ_D;
8321 case LoongArch::PseudoVMSKGEZ_B:
8322 MskOpc = LoongArch::VMSKGEZ_B;
8324 case LoongArch::PseudoVMSKEQZ_B:
8325 MskOpc = LoongArch::VMSKNZ_B;
8326 NotOpc = LoongArch::VNOR_V;
8328 case LoongArch::PseudoVMSKNEZ_B:
8329 MskOpc = LoongArch::VMSKNZ_B;
8331 case LoongArch::PseudoXVMSKLTZ_B:
8332 MskOpc = LoongArch::XVMSKLTZ_B;
8333 RC = &LoongArch::LASX256RegClass;
8335 case LoongArch::PseudoXVMSKLTZ_H:
8336 MskOpc = LoongArch::XVMSKLTZ_H;
8337 RC = &LoongArch::LASX256RegClass;
8340 case LoongArch::PseudoXVMSKLTZ_W:
8341 MskOpc = LoongArch::XVMSKLTZ_W;
8342 RC = &LoongArch::LASX256RegClass;
8345 case LoongArch::PseudoXVMSKLTZ_D:
8346 MskOpc = LoongArch::XVMSKLTZ_D;
8347 RC = &LoongArch::LASX256RegClass;
8350 case LoongArch::PseudoXVMSKGEZ_B:
8351 MskOpc = LoongArch::XVMSKGEZ_B;
8352 RC = &LoongArch::LASX256RegClass;
8354 case LoongArch::PseudoXVMSKEQZ_B:
8355 MskOpc = LoongArch::XVMSKNZ_B;
8356 NotOpc = LoongArch::XVNOR_V;
8357 RC = &LoongArch::LASX256RegClass;
8359 case LoongArch::PseudoXVMSKNEZ_B:
8360 MskOpc = LoongArch::XVMSKNZ_B;
8361 RC = &LoongArch::LASX256RegClass;
8376 if (
TRI->getRegSizeInBits(*RC) > 128) {
8386 TII->get(Subtarget.
is64Bit() ? LoongArch::BSTRINS_D
8387 : LoongArch::BSTRINS_W),
8391 .
addImm(256 / EleBits - 1)
8399 MI.eraseFromParent();
8406 assert(
MI.getOpcode() == LoongArch::SplitPairF64Pseudo &&
8407 "Unexpected instruction");
8419 MI.eraseFromParent();
8426 assert(
MI.getOpcode() == LoongArch::BuildPairF64Pseudo &&
8427 "Unexpected instruction");
8443 MI.eraseFromParent();
8448 switch (
MI.getOpcode()) {
8451 case LoongArch::Select_GPR_Using_CC_GPR:
8487 if (
MI.getOperand(2).isReg())
8488 RHS =
MI.getOperand(2).getReg();
8489 auto CC =
static_cast<unsigned>(
MI.getOperand(3).
getImm());
8493 SelectDests.
insert(
MI.getOperand(0).getReg());
8497 SequenceMBBI !=
E; ++SequenceMBBI) {
8498 if (SequenceMBBI->isDebugInstr())
8501 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
8502 !SequenceMBBI->getOperand(2).isReg() ||
8503 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
8504 SequenceMBBI->getOperand(3).getImm() != CC ||
8505 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
8506 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
8508 LastSelectPseudo = &*SequenceMBBI;
8510 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
8513 if (SequenceMBBI->hasUnmodeledSideEffects() ||
8514 SequenceMBBI->mayLoadOrStore() ||
8515 SequenceMBBI->usesCustomInsertionHook())
8518 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
8533 F->insert(
I, IfFalseMBB);
8534 F->insert(
I, TailMBB);
8537 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
8543 TailMBB->
push_back(DebugInstr->removeFromParent());
8547 TailMBB->
splice(TailMBB->
end(), HeadMBB,
8557 if (
MI.getOperand(2).isImm())
8569 auto SelectMBBI =
MI.getIterator();
8570 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
8572 while (SelectMBBI != SelectEnd) {
8573 auto Next = std::next(SelectMBBI);
8577 TII.get(LoongArch::PHI), SelectMBBI->getOperand(0).getReg())
8578 .
addReg(SelectMBBI->getOperand(4).getReg())
8580 .
addReg(SelectMBBI->getOperand(5).getReg())
8587 F->getProperties().resetNoPHIs();
8593 const TargetInstrInfo *
TII = Subtarget.getInstrInfo();
8596 switch (
MI.getOpcode()) {
8599 case LoongArch::DIV_W:
8600 case LoongArch::DIV_WU:
8601 case LoongArch::MOD_W:
8602 case LoongArch::MOD_WU:
8603 case LoongArch::DIV_D:
8604 case LoongArch::DIV_DU:
8605 case LoongArch::MOD_D:
8606 case LoongArch::MOD_DU:
8609 case LoongArch::WRFCSR: {
8611 LoongArch::FCSR0 +
MI.getOperand(0).getImm())
8612 .
addReg(
MI.getOperand(1).getReg());
8613 MI.eraseFromParent();
8616 case LoongArch::RDFCSR: {
8617 MachineInstr *ReadFCSR =
8619 MI.getOperand(0).getReg())
8620 .
addReg(LoongArch::FCSR0 +
MI.getOperand(1).getImm());
8622 MI.eraseFromParent();
8625 case LoongArch::Select_GPR_Using_CC_GPR:
8627 case LoongArch::BuildPairF64Pseudo:
8629 case LoongArch::SplitPairF64Pseudo:
8631 case LoongArch::PseudoVBZ:
8632 case LoongArch::PseudoVBZ_B:
8633 case LoongArch::PseudoVBZ_H:
8634 case LoongArch::PseudoVBZ_W:
8635 case LoongArch::PseudoVBZ_D:
8636 case LoongArch::PseudoVBNZ:
8637 case LoongArch::PseudoVBNZ_B:
8638 case LoongArch::PseudoVBNZ_H:
8639 case LoongArch::PseudoVBNZ_W:
8640 case LoongArch::PseudoVBNZ_D:
8641 case LoongArch::PseudoXVBZ:
8642 case LoongArch::PseudoXVBZ_B:
8643 case LoongArch::PseudoXVBZ_H:
8644 case LoongArch::PseudoXVBZ_W:
8645 case LoongArch::PseudoXVBZ_D:
8646 case LoongArch::PseudoXVBNZ:
8647 case LoongArch::PseudoXVBNZ_B:
8648 case LoongArch::PseudoXVBNZ_H:
8649 case LoongArch::PseudoXVBNZ_W:
8650 case LoongArch::PseudoXVBNZ_D:
8652 case LoongArch::PseudoXVINSGR2VR_B:
8653 case LoongArch::PseudoXVINSGR2VR_H:
8655 case LoongArch::PseudoCTPOP_B:
8656 case LoongArch::PseudoCTPOP_H:
8657 case LoongArch::PseudoCTPOP_W:
8658 case LoongArch::PseudoCTPOP_D:
8659 case LoongArch::PseudoCTPOP_H_LA32:
8660 case LoongArch::PseudoCTPOP_W_LA32:
8662 case LoongArch::PseudoVMSKLTZ_B:
8663 case LoongArch::PseudoVMSKLTZ_H:
8664 case LoongArch::PseudoVMSKLTZ_W:
8665 case LoongArch::PseudoVMSKLTZ_D:
8666 case LoongArch::PseudoVMSKGEZ_B:
8667 case LoongArch::PseudoVMSKEQZ_B:
8668 case LoongArch::PseudoVMSKNEZ_B:
8669 case LoongArch::PseudoXVMSKLTZ_B:
8670 case LoongArch::PseudoXVMSKLTZ_H:
8671 case LoongArch::PseudoXVMSKLTZ_W:
8672 case LoongArch::PseudoXVMSKLTZ_D:
8673 case LoongArch::PseudoXVMSKGEZ_B:
8674 case LoongArch::PseudoXVMSKEQZ_B:
8675 case LoongArch::PseudoXVMSKNEZ_B:
8677 case TargetOpcode::STATEPOINT:
8683 MI.addOperand(*
MI.getMF(),
8685 LoongArch::R1,
true,
8688 if (!Subtarget.is64Bit())
8696 unsigned *
Fast)
const {
8697 if (!Subtarget.hasUAL())
8715 LoongArch::R7, LoongArch::R8, LoongArch::R9,
8716 LoongArch::R10, LoongArch::R11};
8731 LoongArch::R23, LoongArch::R24, LoongArch::R25, LoongArch::R26,
8732 LoongArch::R27, LoongArch::R28, LoongArch::R29, LoongArch::R30,
8733 LoongArch::R4, LoongArch::R5, LoongArch::R6, LoongArch::R7,
8734 LoongArch::R8, LoongArch::R9, LoongArch::R10, LoongArch::R11,
8735 LoongArch::R12, LoongArch::R13, LoongArch::R14, LoongArch::R15,
8736 LoongArch::R16, LoongArch::R17, LoongArch::R18, LoongArch::R19,
8742 LoongArch::F3, LoongArch::F4, LoongArch::F5,
8743 LoongArch::F6, LoongArch::F7};
8746 LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64,
8747 LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64};
8750 LoongArch::VR3, LoongArch::VR4, LoongArch::VR5,
8751 LoongArch::VR6, LoongArch::VR7};
8754 LoongArch::XR3, LoongArch::XR4, LoongArch::XR5,
8755 LoongArch::XR6, LoongArch::XR7};
8758 switch (State.getCallingConv()) {
8760 if (!State.isVarArg())
8764 return State.AllocateReg(
ArgGPRs);
8772 unsigned ValNo2,
MVT ValVT2,
MVT LocVT2,
8774 unsigned GRLenInBytes = GRLen / 8;
8785 State.AllocateStack(GRLenInBytes, StackAlign),
8788 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
8799 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
8807 unsigned ValNo,
MVT ValVT,
8810 unsigned GRLen =
DL.getLargestLegalIntTypeSizeInBits();
8811 assert((GRLen == 32 || GRLen == 64) &&
"Unspport GRLen");
8812 MVT GRLenVT = GRLen == 32 ? MVT::i32 : MVT::i64;
8817 if (IsRet && ValNo > 1)
8821 bool UseGPRForFloat =
true;
8831 UseGPRForFloat = ArgFlags.
isVarArg();
8844 unsigned TwoGRLenInBytes = (2 * GRLen) / 8;
8847 DL.getTypeAllocSize(OrigTy) == TwoGRLenInBytes) {
8848 unsigned RegIdx = State.getFirstUnallocated(
ArgGPRs);
8850 if (RegIdx != std::size(
ArgGPRs) && RegIdx % 2 == 1)
8856 State.getPendingArgFlags();
8859 "PendingLocs and PendingArgFlags out of sync");
8863 UseGPRForFloat =
true;
8865 if (UseGPRForFloat && ValVT == MVT::f32) {
8868 }
else if (UseGPRForFloat && GRLen == 64 && ValVT == MVT::f64) {
8871 }
else if (UseGPRForFloat && GRLen == 32 && ValVT == MVT::f64) {
8874 assert(PendingLocs.
empty() &&
"Can't lower f64 if it is split");
8916 PendingLocs.
size() <= 2) {
8917 assert(PendingLocs.
size() == 2 &&
"Unexpected PendingLocs.size()");
8922 PendingLocs.
clear();
8923 PendingArgFlags.
clear();
8930 unsigned StoreSizeBytes = GRLen / 8;
8933 if (ValVT == MVT::f32 && !UseGPRForFloat) {
8935 }
else if (ValVT == MVT::f64 && !UseGPRForFloat) {
8939 UseGPRForFloat =
false;
8940 StoreSizeBytes = 16;
8941 StackAlign =
Align(16);
8944 UseGPRForFloat =
false;
8945 StoreSizeBytes = 32;
8946 StackAlign =
Align(32);
8952 Reg ? 0 : State.AllocateStack(StoreSizeBytes, StackAlign);
8956 if (!PendingLocs.
empty()) {
8958 assert(PendingLocs.
size() > 2 &&
"Unexpected PendingLocs.size()");
8959 for (
auto &It : PendingLocs) {
8961 It.convertToReg(
Reg);
8966 PendingLocs.clear();
8967 PendingArgFlags.
clear();
8970 assert((!UseGPRForFloat || LocVT == GRLenVT) &&
8971 "Expected an GRLenVT at this stage");
8988void LoongArchTargetLowering::analyzeInputArgs(
8991 LoongArchCCAssignFn Fn)
const {
8993 for (
unsigned i = 0, e = Ins.
size(); i != e; ++i) {
8994 MVT ArgVT = Ins[i].VT;
8995 Type *ArgTy =
nullptr;
8997 ArgTy = FType->getReturnType();
8998 else if (Ins[i].isOrigArg())
8999 ArgTy = FType->getParamType(Ins[i].getOrigArgIndex());
9003 CCInfo, IsRet, ArgTy)) {
9004 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type " << ArgVT
9011void LoongArchTargetLowering::analyzeOutputArgs(
9014 CallLoweringInfo *CLI, LoongArchCCAssignFn Fn)
const {
9015 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
9016 MVT ArgVT = Outs[i].VT;
9017 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
9021 CCInfo, IsRet, OrigTy)) {
9022 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type " << ArgVT
9041 Val = DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Val);
9063 if (In.isOrigArg()) {
9068 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
9069 (
BitWidth < 32 && In.Flags.isZExt())) {
9119 Register LoVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
9132 Register HiVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
9136 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
9150 Val = DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Val);
9162 if (LocVT == MVT::i32 || LocVT == MVT::i64) {
9166 LoongArch::R23, LoongArch::R24, LoongArch::R25,
9167 LoongArch::R26, LoongArch::R27, LoongArch::R28,
9168 LoongArch::R29, LoongArch::R30, LoongArch::R31};
9175 if (LocVT == MVT::f32) {
9178 static const MCPhysReg FPR32List[] = {LoongArch::F24, LoongArch::F25,
9179 LoongArch::F26, LoongArch::F27};
9186 if (LocVT == MVT::f64) {
9189 static const MCPhysReg FPR64List[] = {LoongArch::F28_64, LoongArch::F29_64,
9190 LoongArch::F30_64, LoongArch::F31_64};
9221 "GHC calling convention requires the F and D extensions");
9225 MVT GRLenVT = Subtarget.getGRLenVT();
9226 unsigned GRLenInBytes = Subtarget.getGRLen() / 8;
9228 std::vector<SDValue> OutChains;
9237 analyzeInputArgs(MF, CCInfo, Ins,
false,
CC_LoongArch);
9239 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
9256 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
9257 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
9258 assert(ArgPartOffset == 0);
9259 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
9261 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
9285 int VaArgOffset, VarArgsSaveSize;
9289 if (ArgRegs.
size() == Idx) {
9291 VarArgsSaveSize = 0;
9293 VarArgsSaveSize = GRLenInBytes * (ArgRegs.
size() - Idx);
9294 VaArgOffset = -VarArgsSaveSize;
9300 LoongArchFI->setVarArgsFrameIndex(FI);
9308 VarArgsSaveSize += GRLenInBytes;
9313 for (
unsigned I = Idx;
I < ArgRegs.
size();
9314 ++
I, VaArgOffset += GRLenInBytes) {
9315 const Register Reg = RegInfo.createVirtualRegister(RC);
9316 RegInfo.addLiveIn(ArgRegs[
I], Reg);
9324 ->setValue((
Value *)
nullptr);
9325 OutChains.push_back(Store);
9327 LoongArchFI->setVarArgsSaveSize(VarArgsSaveSize);
9332 if (!OutChains.empty()) {
9333 OutChains.push_back(Chain);
9348 if (
N->getNumValues() != 1)
9350 if (!
N->hasNUsesOfValue(1, 0))
9353 SDNode *Copy = *
N->user_begin();
9359 if (Copy->getGluedNode())
9363 bool HasRet =
false;
9365 if (
Node->getOpcode() != LoongArchISD::RET)
9373 Chain = Copy->getOperand(0);
9378bool LoongArchTargetLowering::isEligibleForTailCallOptimization(
9382 auto CalleeCC = CLI.CallConv;
9383 auto &Outs = CLI.Outs;
9385 auto CallerCC = Caller.getCallingConv();
9392 for (
auto &VA : ArgLocs)
9398 auto IsCallerStructRet = Caller.hasStructRetAttr();
9399 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
9400 if (IsCallerStructRet || IsCalleeStructRet)
9404 for (
auto &Arg : Outs)
9405 if (Arg.Flags.isByVal())
9410 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
9411 if (CalleeCC != CallerCC) {
9412 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
9413 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
9439 MVT GRLenVT = Subtarget.getGRLenVT();
9451 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
CC_LoongArch);
9455 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
9461 "site marked musttail");
9468 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
9470 if (!Flags.isByVal())
9474 unsigned Size = Flags.getByValSize();
9475 Align Alignment = Flags.getNonZeroByValAlign();
9482 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
9484 false,
nullptr, std::nullopt,
9496 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
9499 SDValue ArgValue = OutVals[OutIdx];
9507 DAG.
getNode(LoongArchISD::SPLIT_PAIR_F64,
DL,
9508 DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
9520 if (!StackPtr.getNode())
9532 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
9547 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
9548 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
9549 assert(ArgPartOffset == 0);
9554 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
9555 SDValue PartValue = OutVals[OutIdx + 1];
9556 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
9571 for (
const auto &Part : Parts) {
9572 SDValue PartValue = Part.first;
9573 SDValue PartOffset = Part.second;
9580 ArgValue = SpillSlot;
9586 if (Flags.isByVal())
9587 ArgValue = ByValArgs[j++];
9594 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
9595 "for passing parameters");
9598 if (!StackPtr.getNode())
9611 if (!MemOpChains.
empty())
9617 for (
auto &Reg : RegsToPass) {
9618 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
9640 Ops.push_back(Chain);
9641 Ops.push_back(Callee);
9645 for (
auto &Reg : RegsToPass)
9646 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
9651 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
9652 assert(Mask &&
"Missing call preserved mask for calling convention");
9658 Ops.push_back(Glue);
9667 Op = IsTailCall ? LoongArchISD::TAIL : LoongArchISD::CALL;
9670 Op = IsTailCall ? LoongArchISD::TAIL_MEDIUM : LoongArchISD::CALL_MEDIUM;
9673 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
9674 Op = IsTailCall ? LoongArchISD::TAIL_LARGE : LoongArchISD::CALL_LARGE;
9696 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_LoongArch);
9699 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
9700 auto &VA = RVLocs[i];
9708 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
9709 assert(VA.needsCustom());
9714 RetValue = DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
9715 RetValue, RetValue2);
9728 const Type *RetTy)
const {
9730 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
9732 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
9736 Outs[i].Flags, CCInfo,
true,
nullptr))
9762 for (
unsigned i = 0, e = RVLocs.
size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
9763 SDValue Val = OutVals[OutIdx];
9772 DAG.
getVTList(MVT::i32, MVT::i32), Val);
9776 Register RegHi = RVLocs[++i].getLocReg();
9801 return DAG.
getNode(LoongArchISD::RET,
DL, MVT::Other, RetOps);
9809 const APInt &SplatValue,
const unsigned SplatBitSize)
const {
9812 if (SplatBitSize == 16 && !(V & 0x00FF)) {
9814 RequiredImm = (0b10101 << 8) | (V >> 8);
9815 return {
true, RequiredImm};
9816 }
else if (SplatBitSize == 32) {
9818 if (!(V & 0xFFFF00FF)) {
9819 RequiredImm = (0b10001 << 8) | (V >> 8);
9820 return {
true, RequiredImm};
9823 if (!(V & 0xFF00FFFF)) {
9824 RequiredImm = (0b10010 << 8) | (V >> 16);
9825 return {
true, RequiredImm};
9828 if (!(V & 0x00FFFFFF)) {
9829 RequiredImm = (0b10011 << 8) | (V >> 24);
9830 return {
true, RequiredImm};
9833 if ((V & 0xFFFF00FF) == 0xFF) {
9834 RequiredImm = (0b10110 << 8) | (V >> 8);
9835 return {
true, RequiredImm};
9838 if ((V & 0xFF00FFFF) == 0xFFFF) {
9839 RequiredImm = (0b10111 << 8) | (V >> 16);
9840 return {
true, RequiredImm};
9843 if ((V & 0x7E07FFFF) == 0x3E000000 || (V & 0x7E07FFFF) == 0x40000000) {
9845 (0b11010 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
9846 return {
true, RequiredImm};
9848 }
else if (SplatBitSize == 64) {
9850 if ((V & 0xFFFFFFFF7E07FFFFULL) == 0x3E000000ULL ||
9851 (V & 0xFFFFFFFF7E07FFFFULL) == 0x40000000ULL) {
9853 (0b11011 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
9854 return {
true, RequiredImm};
9857 if ((V & 0x7FC0FFFFFFFFFFFFULL) == 0x4000000000000000ULL ||
9858 (V & 0x7FC0FFFFFFFFFFFFULL) == 0x3FC0000000000000ULL) {
9860 (0b11100 << 8) | (((V >> 56) & 0xC0) ^ 0x40) | ((V >> 48) & 0x3F);
9861 return {
true, RequiredImm};
9864 auto sameBitsPreByte = [](
uint64_t x) -> std::pair<bool, uint8_t> {
9866 for (
int i = 0; i < 8; ++i) {
9868 if (
byte == 0 ||
byte == 0xFF)
9869 res |= ((
byte & 1) << i);
9876 auto [IsSame, Suffix] = sameBitsPreByte(V);
9878 RequiredImm = (0b11001 << 8) | Suffix;
9879 return {
true, RequiredImm};
9882 return {
false, RequiredImm};
9887 if (!Subtarget.hasExtLSX())
9890 if (VT == MVT::f32) {
9891 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7e07ffff;
9892 return (masked == 0x3e000000 || masked == 0x40000000);
9895 if (VT == MVT::f64) {
9896 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7fc0ffffffffffff;
9897 return (masked == 0x3fc0000000000000 || masked == 0x4000000000000000);
9903bool LoongArchTargetLowering::isFPImmLegal(
const APFloat &Imm,
EVT VT,
9904 bool ForCodeSize)
const {
9906 if (VT == MVT::f32 && !Subtarget.hasBasicF())
9908 if (VT == MVT::f64 && !Subtarget.hasBasicD())
9910 return (Imm.isZero() || Imm.isExactlyValue(1.0) ||
isFPImmVLDILegal(Imm, VT));
9921bool LoongArchTargetLowering::shouldInsertFencesForAtomic(
9931 Type *Ty =
I->getOperand(0)->getType();
9933 unsigned Size = Ty->getIntegerBitWidth();
9953 unsigned MaxIntSize = Subtarget.is64Bit() ? 64 : 32;
9958 if (Subtarget.hasExtLASX())
9960 else if (Subtarget.hasExtLSX())
9967 EVT VT =
Y.getValueType();
9970 return Subtarget.hasExtLSX() && VT.
isInteger();
9981 case Intrinsic::loongarch_masked_atomicrmw_xchg_i32:
9982 case Intrinsic::loongarch_masked_atomicrmw_add_i32:
9983 case Intrinsic::loongarch_masked_atomicrmw_sub_i32:
9984 case Intrinsic::loongarch_masked_atomicrmw_nand_i32: {
9987 Info.memVT = MVT::i32;
9988 Info.ptrVal =
I.getArgOperand(0);
9990 Info.align =
Align(4);
10009 "Unable to expand");
10010 unsigned MinWordSize = 4;
10022 Value *AlignedAddr = Builder.CreateIntrinsic(
10023 Intrinsic::ptrmask, {PtrTy, IntTy},
10024 {Addr, ConstantInt::get(IntTy, ~(
uint64_t)(MinWordSize - 1))},
nullptr,
10027 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
10028 Value *PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
10029 Value *ShiftAmt = Builder.CreateShl(PtrLSB, 3);
10030 ShiftAmt = Builder.CreateTrunc(ShiftAmt, WordType,
"ShiftAmt");
10031 Value *Mask = Builder.CreateShl(
10032 ConstantInt::get(WordType,
10033 (1 << (
DL.getTypeStoreSize(
ValueType) * 8)) - 1),
10035 Value *Inv_Mask = Builder.CreateNot(Mask,
"Inv_Mask");
10036 Value *ValOperand_Shifted =
10037 Builder.CreateShl(Builder.CreateZExt(AI->
getValOperand(), WordType),
10038 ShiftAmt,
"ValOperand_Shifted");
10041 NewOperand = Builder.CreateOr(ValOperand_Shifted, Inv_Mask,
"AndOperand");
10043 NewOperand = ValOperand_Shifted;
10046 Builder.CreateAtomicRMW(
Op, AlignedAddr, NewOperand,
Align(MinWordSize),
10049 Value *Shift = Builder.CreateLShr(NewAI, ShiftAmt,
"shifted");
10050 Value *Trunc = Builder.CreateTrunc(Shift,
ValueType,
"extracted");
10051 Value *FinalOldResult = Builder.CreateBitCast(Trunc,
ValueType);
10070 if (Subtarget.hasLAM_BH() && Subtarget.is64Bit() &&
10078 if (Subtarget.hasLAMCAS()) {
10100 return Intrinsic::loongarch_masked_atomicrmw_xchg_i64;
10102 return Intrinsic::loongarch_masked_atomicrmw_add_i64;
10104 return Intrinsic::loongarch_masked_atomicrmw_sub_i64;
10106 return Intrinsic::loongarch_masked_atomicrmw_nand_i64;
10108 return Intrinsic::loongarch_masked_atomicrmw_umax_i64;
10110 return Intrinsic::loongarch_masked_atomicrmw_umin_i64;
10112 return Intrinsic::loongarch_masked_atomicrmw_max_i64;
10114 return Intrinsic::loongarch_masked_atomicrmw_min_i64;
10124 return Intrinsic::loongarch_masked_atomicrmw_xchg_i32;
10126 return Intrinsic::loongarch_masked_atomicrmw_add_i32;
10128 return Intrinsic::loongarch_masked_atomicrmw_sub_i32;
10130 return Intrinsic::loongarch_masked_atomicrmw_nand_i32;
10132 return Intrinsic::loongarch_masked_atomicrmw_umax_i32;
10134 return Intrinsic::loongarch_masked_atomicrmw_umin_i32;
10136 return Intrinsic::loongarch_masked_atomicrmw_max_i32;
10138 return Intrinsic::loongarch_masked_atomicrmw_min_i32;
10150 if (Subtarget.hasLAMCAS())
10162 unsigned GRLen = Subtarget.getGRLen();
10164 Value *FailureOrdering =
10165 Builder.getIntN(Subtarget.getGRLen(),
static_cast<uint64_t>(FailOrd));
10166 Intrinsic::ID CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i32;
10168 CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i64;
10169 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
10170 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
10171 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
10174 Value *Result = Builder.CreateIntrinsic(
10175 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, FailureOrdering});
10177 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
10193 Builder.CreateNot(Mask,
"Inv_Mask"),
10200 unsigned GRLen = Subtarget.getGRLen();
10209 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
10210 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
10211 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
10224 unsigned ValWidth =
10227 Builder.CreateSub(Builder.getIntN(GRLen, GRLen - ValWidth), ShiftAmt);
10228 Result = Builder.CreateCall(LlwOpScwLoop,
10229 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
10232 Builder.CreateCall(LlwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
10236 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
10259 const Constant *PersonalityFn)
const {
10260 return LoongArch::R4;
10264 const Constant *PersonalityFn)
const {
10265 return LoongArch::R5;
10276 int RefinementSteps = VT.
getScalarType() == MVT::f64 ? 2 : 1;
10277 return RefinementSteps;
10282 assert(Subtarget.hasFrecipe() &&
10283 "Reciprocal estimate queried on unsupported target");
10294 return Subtarget.hasBasicD();
10298 return Subtarget.hasExtLSX();
10302 return Subtarget.hasExtLASX();
10311 int &RefinementSteps,
10312 bool &UseOneConstNR,
10313 bool Reciprocal)
const {
10315 "Enabled should never be Disabled here");
10317 if (!Subtarget.hasFrecipe())
10332 UseOneConstNR =
false;
10338 if (Reciprocal || RefinementSteps > 0)
10348 int &RefinementSteps)
const {
10350 "Enabled should never be Disabled here");
10352 if (!Subtarget.hasFrecipe())
10366 return DAG.
getNode(LoongArchISD::FRECIPE,
DL, VT, Operand);
10374LoongArchTargetLowering::getConstraintType(
StringRef Constraint)
const {
10394 if (Constraint.
size() == 1) {
10395 switch (Constraint[0]) {
10411 if (Constraint ==
"ZC" || Constraint ==
"ZB")
10420 return StringSwitch<InlineAsm::ConstraintCode>(ConstraintCode)
10427std::pair<unsigned, const TargetRegisterClass *>
10428LoongArchTargetLowering::getRegForInlineAsmConstraint(
10432 if (Constraint.
size() == 1) {
10433 switch (Constraint[0]) {
10438 return std::make_pair(0U, &LoongArch::GPRRegClass);
10440 return std::make_pair(0U, &LoongArch::GPRNoR0R1RegClass);
10442 if (Subtarget.hasBasicF() && VT == MVT::f32)
10443 return std::make_pair(0U, &LoongArch::FPR32RegClass);
10444 if (Subtarget.hasBasicD() && VT == MVT::f64)
10445 return std::make_pair(0U, &LoongArch::FPR64RegClass);
10446 if (Subtarget.hasExtLSX() &&
10447 TRI->isTypeLegalForClass(LoongArch::LSX128RegClass, VT))
10448 return std::make_pair(0U, &LoongArch::LSX128RegClass);
10449 if (Subtarget.hasExtLASX() &&
10450 TRI->isTypeLegalForClass(LoongArch::LASX256RegClass, VT))
10451 return std::make_pair(0U, &LoongArch::LASX256RegClass);
10471 bool IsFP = Constraint[2] ==
'f';
10472 std::pair<StringRef, StringRef> Temp = Constraint.
split(
'$');
10473 std::pair<unsigned, const TargetRegisterClass *>
R;
10478 unsigned RegNo =
R.first;
10479 if (LoongArch::F0 <= RegNo && RegNo <= LoongArch::F31) {
10480 if (Subtarget.hasBasicD() && (VT == MVT::f64 || VT == MVT::Other)) {
10481 unsigned DReg = RegNo - LoongArch::F0 + LoongArch::F0_64;
10482 return std::make_pair(DReg, &LoongArch::FPR64RegClass);
10492void LoongArchTargetLowering::LowerAsmOperandForConstraint(
10496 if (Constraint.
size() == 1) {
10497 switch (Constraint[0]) {
10501 uint64_t CVal =
C->getSExtValue();
10504 Subtarget.getGRLenVT()));
10510 uint64_t CVal =
C->getSExtValue();
10513 Subtarget.getGRLenVT()));
10519 if (
C->getZExtValue() == 0)
10526 uint64_t CVal =
C->getZExtValue();
10539#define GET_REGISTER_MATCHER
10540#include "LoongArchGenAsmMatcher.inc"
10546 std::string NewRegName = Name.second.str();
10552 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
10553 if (!ReservedRegs.
test(Reg))
10570 const APInt &Imm = ConstNode->getAPIntValue();
10572 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
10573 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
10576 if (ConstNode->hasOneUse() &&
10577 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
10578 (Imm - 8).isPowerOf2() || (Imm - 16).isPowerOf2()))
10584 if (ConstNode->hasOneUse() && !(Imm.sge(-2048) && Imm.sle(4095))) {
10585 unsigned Shifts = Imm.countr_zero();
10591 APInt ImmPop = Imm.ashr(Shifts);
10592 if (ImmPop == 3 || ImmPop == 5 || ImmPop == 9 || ImmPop == 17)
10596 APInt ImmSmall =
APInt(Imm.getBitWidth(), 1ULL << Shifts,
true);
10597 if ((Imm - ImmSmall).isPowerOf2() || (Imm + ImmSmall).isPowerOf2() ||
10598 (ImmSmall - Imm).isPowerOf2())
10608 Type *Ty,
unsigned AS,
10627 switch (AM.
Scale) {
10663 EVT MemVT = LD->getMemoryVT();
10664 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
10675 return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
10684 if (
Y.getValueType().isVector())
10696 Type *Ty,
bool IsSigned)
const {
10697 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
10706 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
10707 Type.getSizeInBits() < Subtarget.getGRLen()))
10717 Align &PrefAlign)
const {
10721 if (Subtarget.is64Bit()) {
10723 PrefAlign =
Align(8);
10726 PrefAlign =
Align(4);
10741bool LoongArchTargetLowering::splitValueIntoRegisterParts(
10743 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
10744 bool IsABIRegCopy = CC.has_value();
10747 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
10748 PartVT == MVT::f32) {
10763SDValue LoongArchTargetLowering::joinRegisterPartsIntoValue(
10765 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
10766 bool IsABIRegCopy = CC.has_value();
10768 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
10769 PartVT == MVT::f32) {
10786 if (VT == MVT::f16 && Subtarget.hasBasicF())
10792unsigned LoongArchTargetLowering::getNumRegistersForCallingConv(
10795 if (VT == MVT::f16 && Subtarget.hasBasicF())
10804 unsigned Opc =
Op.getOpcode();
10809 case LoongArchISD::VPICK_ZEXT_ELT: {
10823 unsigned Depth)
const {
10824 EVT VT =
Op.getValueType();
10826 unsigned Opc =
Op.getOpcode();
10830 case LoongArchISD::VMSKLTZ:
10831 case LoongArchISD::XVMSKLTZ: {
10833 MVT SrcVT = Src.getSimpleValueType();
10838 if (OriginalDemandedBits.
countr_zero() >= NumElts)
10842 APInt KnownUndef, KnownZero;
10858 if (KnownSrc.
One[SrcBits - 1])
10860 else if (KnownSrc.
Zero[SrcBits - 1])
10865 Src, DemandedSrcBits, DemandedElts, TLO.
DAG,
Depth + 1))
10872 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
10895 unsigned Index)
const {
10904 unsigned Index)
const {
10908 return (EltVT == MVT::f32 || EltVT == MVT::f64) && Index == 0;
static MCRegister MatchRegisterName(StringRef Name)
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
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< 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)
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 emitIntrinsicErrorMessage(SDValue Op, StringRef ErrorMsg, SelectionDAG &DAG)
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 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 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 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 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 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 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 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)
#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_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 SDValue performVMSKLTZCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget)
static void replaceINTRINSIC_WO_CHAINResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
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.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static CodeModel::Model getCodeModel(const PPCSubtarget &S, const TargetMachine &TM, const MachineOperand &MO)
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,...
bool isExactlyValue(double V) const
We don't rely on operator== working on double values, as it returns true for things that are clearly ...
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.
void setHighBits(unsigned hiBits)
Set the top hiBits bits.
void setBitsFrom(unsigned loBit)
Set the top bits starting from loBit.
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 getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
void setLowBits(unsigned loBits)
Set the bottom loBits bits.
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.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
An instruction that atomically checks whether a specified value is in a memory location,...
Value * getCompareOperand()
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 Basic Block Representation.
bool test(unsigned Idx) const
size_type count() const
count - 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.
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.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
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...
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 addSExt32Register(Register Reg)
const LoongArchRegisterInfo * getRegisterInfo() 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...
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.
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
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 isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return true if EXTRACT_SUBVECTOR is cheap for extracting this result type from this source type with ...
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...
Register getExceptionPointerRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
bool signExtendConstant(const ConstantInt *CI) const override
Return true if this constant should be sign extended when promoting to a larger type.
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...
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.
Register getExceptionSelectorRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
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 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.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & 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 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.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
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.
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...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
SDValue 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)
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
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...
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge)
Set NoMergeSiteInfo to be associated with Node if NoMerge is true.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
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 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 std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue 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 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)
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 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)
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.
StringRef - 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
size - 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.
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.
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.
@ 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.
@ 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.
@ 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 - Perform floating-point minimumNumber or maximumNumber on two values,...
@ 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 - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ 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 ...
@ 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.
FunctionAddr VTableAddr Value
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.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool 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 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.
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)
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...
FunctionAddr VTableAddr Next
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
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
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).
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
unsigned getBitWidth() const
Get the bit width of this value.
void resetAll()
Resets the known state of all bits.
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 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 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)