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}) {
354 for (
MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
356 for (
MVT VT : {MVT::v8i16, MVT::v4i32, MVT::v2i64})
358 for (
MVT VT : {MVT::v4i32, MVT::v2i64}) {
362 for (
MVT VT : {MVT::v4f32, MVT::v2f64}) {
386 {MVT::v16i8, MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v8i16, MVT::v4i16,
387 MVT::v2i16, MVT::v4i32, MVT::v2i32, MVT::v2i64}) {
404 if (Subtarget.hasExtLASX()) {
405 for (
MVT VT : LASXVTs) {
420 for (
MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16, MVT::v32i8}) {
445 for (
MVT VT : {MVT::v32i8, MVT::v16i16, MVT::v8i32})
447 for (
MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64})
449 for (
MVT VT : {MVT::v8i32, MVT::v4i32, MVT::v4i64}) {
453 for (
MVT VT : {MVT::v8f32, MVT::v4f64}) {
475 if (Subtarget.hasBasicF()) {
486 if (Subtarget.hasExtLSX()) {
494 if (Subtarget.hasExtLASX()) {
521 if (Subtarget.hasLAMCAS())
524 if (Subtarget.hasSCQ()) {
544 switch (
Op.getOpcode()) {
546 return lowerATOMIC_FENCE(
Op, DAG);
548 return lowerEH_DWARF_CFA(
Op, DAG);
550 return lowerGlobalAddress(
Op, DAG);
552 return lowerGlobalTLSAddress(
Op, DAG);
554 return lowerINTRINSIC_WO_CHAIN(
Op, DAG);
556 return lowerINTRINSIC_W_CHAIN(
Op, DAG);
558 return lowerINTRINSIC_VOID(
Op, DAG);
560 return lowerBlockAddress(
Op, DAG);
562 return lowerJumpTable(
Op, DAG);
564 return lowerShiftLeftParts(
Op, DAG);
566 return lowerShiftRightParts(
Op, DAG,
true);
568 return lowerShiftRightParts(
Op, DAG,
false);
570 return lowerConstantPool(
Op, DAG);
572 return lowerFP_TO_SINT(
Op, DAG);
574 return lowerBITCAST(
Op, DAG);
576 return lowerUINT_TO_FP(
Op, DAG);
578 return lowerSINT_TO_FP(
Op, DAG);
580 return lowerVASTART(
Op, DAG);
582 return lowerFRAMEADDR(
Op, DAG);
584 return lowerRETURNADDR(
Op, DAG);
586 return lowerWRITE_REGISTER(
Op, DAG);
588 return lowerINSERT_VECTOR_ELT(
Op, DAG);
590 return lowerEXTRACT_VECTOR_ELT(
Op, DAG);
592 return lowerBUILD_VECTOR(
Op, DAG);
594 return lowerCONCAT_VECTORS(
Op, DAG);
596 return lowerVECTOR_SHUFFLE(
Op, DAG);
598 return lowerBITREVERSE(
Op, DAG);
600 return lowerSCALAR_TO_VECTOR(
Op, DAG);
602 return lowerPREFETCH(
Op, DAG);
604 return lowerSELECT(
Op, DAG);
606 return lowerBRCOND(
Op, DAG);
608 return lowerFP_TO_FP16(
Op, DAG);
610 return lowerFP16_TO_FP(
Op, DAG);
612 return lowerFP_TO_BF16(
Op, DAG);
614 return lowerBF16_TO_FP(
Op, DAG);
616 return lowerVECREDUCE_ADD(
Op, DAG);
619 return lowerRotate(
Op, DAG);
627 return lowerVECREDUCE(
Op, DAG);
629 return lowerConstantFP(
Op, DAG);
631 return lowerSETCC(
Op, DAG);
633 return lowerFP_ROUND(
Op, DAG);
635 return lowerFP_EXTEND(
Op, DAG);
644 EVT VT = V.getValueType();
650 return V.getOperand(0);
654 (
isNullConstant(V.getOperand(1)) || V.getOperand(0).hasOneUse())) {
656 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
666 if (!V->isOnlyUserOf(SplatValue.getNode()))
670 Not = DAG.
getBitcast(V.getOperand(0).getValueType(), Not);
678 V.getOperand(0).hasOneUse() && V.getOperand(1).hasOneUse()) {
706 (
N->getOpcode() == LoongArchISD::VPACKEV)) &&
713 if (Opcode0 != Opcode1)
716 if (Opcode0 !=
ISD::FP_ROUND && Opcode0 != LoongArchISD::VFCVT)
723 EVT VT =
N.getValueType();
737 if (Subtarget.hasExtLASX() && VT.
is256BitVector() && SVT0 == MVT::v4f32 &&
738 SSVT0 == MVT::v4f64) {
757 if (
N->getOpcode() == LoongArchISD::VPACKEV &&
758 Opcode0 == LoongArchISD::VFCVT) {
764 if (Subtarget.hasExtLSX() && (VT == MVT::v2i64 || VT == MVT::v2f64) &&
765 SVT0 == MVT::v4f32 && SSVT0 == MVT::v2f64) {
779 MVT VT =
Op.getSimpleValueType();
780 MVT SVT =
In.getSimpleValueType();
782 if (VT == MVT::v4f32 && SVT == MVT::v4f64) {
795 EVT VT =
Op.getValueType();
797 EVT SVT = Src.getValueType();
800 VT == MVT::v2f64 && SVT == MVT::v2f32 && Subtarget.hasExtLSX();
802 VT == MVT::v4f64 && SVT == MVT::v4f32 && Subtarget.hasExtLASX();
803 if (!V2F32ToV2F64 && !V4F32ToV4F64)
815 const uint64_t
Imm =
Op.getConstantOperandVal(1);
830 if (
SDValue V = CheckVecHighPart(Src)) {
832 "Unexpected wide vector");
833 Opcode = LoongArchISD::VFCVTH;
836 Opcode = LoongArchISD::VFCVTL;
838 DAG.
getUNDEF(WideOpVT), Src, ZeroIdx);
843 return DAG.
getNode(Opcode,
DL, VT, VFCVTOp);
849 SmallVector<int, 8>
Mask = {0, 1, 4, 5, 2, 3, 6, 7};
861 EVT VT =
Op.getValueType();
866 assert((VT == MVT::f32 && Subtarget.hasBasicF()) ||
867 (VT == MVT::f64 && Subtarget.hasBasicD()));
884 int InsNum = Seq.size() + ((VT == MVT::f64 && !Subtarget.is64Bit()) ? 2 : 1);
894 if (Subtarget.is64Bit())
896 return DAG.
getNode(Subtarget.is64Bit() ? LoongArchISD::MOVGR2FR_W_LA64
897 : LoongArchISD::MOVGR2FR_W,
901 if (Subtarget.is64Bit()) {
903 return DAG.
getNode(LoongArchISD::MOVGR2FR_D,
DL, VT, NewVal);
907 return DAG.
getNode(LoongArchISD::MOVGR2FR_D_LO_HI,
DL, VT,
Lo,
Hi);
919 EVT ResultVT =
Op.getValueType();
920 EVT OperandVT =
Op.getOperand(0).getValueType();
925 if (ResultVT == SetCCResultVT)
928 assert(
Op.getOperand(0).getValueType() ==
Op.getOperand(1).getValueType() &&
929 "SETCC operands must have the same type!");
933 Op.getOperand(1),
Op.getOperand(2));
935 if (ResultVT.
bitsGT(SetCCResultVT))
937 else if (ResultVT.
bitsLT(SetCCResultVT))
955 MVT OpVT =
Op.getSimpleValueType();
962 unsigned LegalVecSize = 128;
963 bool isLASX256Vector =
973 if (isLASX256Vector) {
978 for (
unsigned i = 1; i < NumEles; i *= 2, EleBits *= 2) {
981 Val = DAG.
getNode(LoongArchISD::VHADDW,
DL, VecTy, Val, Val);
984 if (isLASX256Vector) {
1010 MVT OpVT =
Op.getSimpleValueType();
1023 MVT GRLenVT = Subtarget.getGRLenVT();
1025 for (
int i = NumEles; i > 1; i /= 2) {
1028 Val = DAG.
getNode(Opcode,
DL, VecTy, Tmp, Val);
1037 unsigned IsData =
Op.getConstantOperandVal(4);
1042 return Op.getOperand(0);
1049 MVT VT =
Op.getSimpleValueType();
1055 unsigned Opcode =
Op.getOpcode();
1058 auto checkCstSplat = [](
SDValue V, APInt &CstSplatValue) {
1064 CstSplatValue =
C->getAPIntValue();
1072 APInt CstSplatValue;
1073 bool IsCstSplat = checkCstSplat(Amt, CstSplatValue);
1077 if (IsCstSplat && CstSplatValue.
urem(EltSizeInBits) == 0)
1093 return DAG.
getNode(Opcode,
DL, VT, R, Urem);
1109 if (
LHS == LHS2 &&
RHS == RHS2) {
1114 }
else if (
LHS == RHS2 &&
RHS == LHS2) {
1122 return std::nullopt;
1130 MVT VT =
N->getSimpleValueType(0);
1161 if (~TrueVal == FalseVal) {
1201 unsigned SelOpNo = 0;
1211 unsigned ConstSelOpNo = 1;
1212 unsigned OtherSelOpNo = 2;
1219 if (!ConstSelOpNode || ConstSelOpNode->
isOpaque())
1224 if (!ConstBinOpNode || ConstBinOpNode->
isOpaque())
1230 SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};
1232 std::swap(NewConstOps[0], NewConstOps[1]);
1244 SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};
1246 std::swap(NewNonConstOps[0], NewNonConstOps[1]);
1249 SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;
1250 SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;
1270 ShAmt =
LHS.getValueSizeInBits() - 1 -
Log2_64(Mask);
1284 int64_t
C = RHSC->getSExtValue();
1327 MVT VT =
Op.getSimpleValueType();
1328 MVT GRLenVT = Subtarget.getGRLenVT();
1333 if (
Op.hasOneUse()) {
1334 unsigned UseOpc =
Op->user_begin()->getOpcode();
1336 SDNode *BinOp = *
Op->user_begin();
1343 return lowerSELECT(NewSel, DAG);
1360 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1383 if (TrueVal - 1 == FalseVal)
1385 if (TrueVal + 1 == FalseVal)
1392 RHS == TrueV &&
LHS == FalseV) {
1417 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL, VT,
Ops);
1424 MVT GRLenVT = Subtarget.getGRLenVT();
1435 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1436 Op.getOperand(0),
LHS,
RHS, TargetCC,
1439 return DAG.
getNode(LoongArchISD::BRCOND,
DL,
Op.getValueType(),
1440 Op.getOperand(0), CondV,
Op.getOperand(2));
1444 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
Op.getValueType(),
1450LoongArchTargetLowering::lowerSCALAR_TO_VECTOR(
SDValue Op,
1453 MVT OpVT =
Op.getSimpleValueType();
1464 EVT ResTy =
Op->getValueType(0);
1469 if (!Subtarget.is64Bit() && (ResTy == MVT::v16i8 || ResTy == MVT::v32i8))
1479 for (
unsigned int i = 0; i < NewEltNum; i++) {
1482 unsigned RevOp = (ResTy == MVT::v16i8 || ResTy == MVT::v32i8)
1483 ? (
unsigned)LoongArchISD::BITREV_8B
1501 for (
unsigned int i = 0; i < NewEltNum; i++)
1502 for (
int j = OrigEltNum / NewEltNum - 1;
j >= 0;
j--)
1503 Mask.push_back(j + (OrigEltNum / NewEltNum) * i);
1521 if (EltBits > 32 || EltBits == 1)
1549 int MaskOffset,
const APInt &Zeroable) {
1550 int Size = Mask.size();
1551 unsigned SizeInBits =
Size * ScalarSizeInBits;
1553 auto CheckZeros = [&](
int Shift,
int Scale,
bool Left) {
1554 for (
int i = 0; i <
Size; i += Scale)
1555 for (
int j = 0; j < Shift; ++j)
1556 if (!Zeroable[i + j + (
Left ? 0 : (Scale - Shift))])
1564 for (
unsigned i = Pos, e = Pos +
Size; i != e; ++i,
Low += Step)
1565 if (!(Mask[i] == -1 || Mask[i] ==
Low))
1570 auto MatchShift = [&](
int Shift,
int Scale,
bool Left) {
1571 for (
int i = 0; i !=
Size; i += Scale) {
1572 unsigned Pos =
Left ? i + Shift : i;
1573 unsigned Low =
Left ? i : i + Shift;
1574 unsigned Len = Scale - Shift;
1579 int ShiftEltBits = ScalarSizeInBits * Scale;
1580 bool ByteShift = ShiftEltBits > 64;
1581 Opcode =
Left ? (ByteShift ? LoongArchISD::VBSLL : LoongArchISD::VSLLI)
1582 : (ByteShift ? LoongArchISD::VBSRL : LoongArchISD::VSRLI);
1583 int ShiftAmt = Shift * ScalarSizeInBits / (ByteShift ? 8 : 1);
1587 Scale = ByteShift ? Scale / 2 : Scale;
1593 return (
int)ShiftAmt;
1596 unsigned MaxWidth = 128;
1597 for (
int Scale = 2; Scale * ScalarSizeInBits <= MaxWidth; Scale *= 2)
1598 for (
int Shift = 1; Shift != Scale; ++Shift)
1599 for (
bool Left : {
true,
false})
1600 if (CheckZeros(Shift, Scale,
Left)) {
1601 int ShiftAmt = MatchShift(Shift, Scale,
Left);
1626 const APInt &Zeroable) {
1627 int Size = Mask.size();
1641 Mask,
Size, Zeroable);
1649 "Illegal integer vector type");
1658template <
typename ValType>
1661 unsigned CheckStride,
1663 ValType ExpectedIndex,
unsigned ExpectedIndexStride) {
1667 if (*
I != -1 && *
I != ExpectedIndex)
1669 ExpectedIndex += ExpectedIndexStride;
1673 for (
unsigned n = 0; n < CheckStride &&
I != End; ++n, ++
I)
1685 int Size = Mask.size();
1695 int ScalarSizeInBits = VectorSizeInBits /
Size;
1696 assert(!(VectorSizeInBits % ScalarSizeInBits) &&
"Illegal shuffle mask size");
1697 (void)ScalarSizeInBits;
1699 for (
int i = 0; i <
Size; ++i) {
1705 if ((M >= 0 && M <
Size && V1IsZero) || (M >=
Size && V2IsZero)) {
1722 RepeatedMask.
assign(LaneSize, -1);
1723 int Size = Mask.size();
1724 for (
int i = 0; i <
Size; ++i) {
1725 assert(Mask[i] == -1 || Mask[i] >= 0);
1728 if ((Mask[i] %
Size) / LaneSize != i / LaneSize)
1735 Mask[i] <
Size ? Mask[i] % LaneSize : Mask[i] % LaneSize + LaneSize;
1736 if (RepeatedMask[i % LaneSize] < 0)
1738 RepeatedMask[i % LaneSize] = LocalM;
1739 else if (RepeatedMask[i % LaneSize] != LocalM)
1756 int NumElts = RepeatedMask.
size();
1758 int Scale = 16 / NumElts;
1760 for (
int i = 0; i < NumElts; ++i) {
1761 int M = RepeatedMask[i];
1762 assert((M == -1 || (0 <= M && M < (2 * NumElts))) &&
1763 "Unexpected mask index.");
1768 int StartIdx = i - (M % NumElts);
1775 int CandidateRotation = StartIdx < 0 ? -StartIdx : NumElts - StartIdx;
1778 Rotation = CandidateRotation;
1779 else if (Rotation != CandidateRotation)
1783 SDValue MaskV = M < NumElts ? V1 : V2;
1794 else if (TargetV != MaskV)
1799 assert(Rotation != 0 &&
"Failed to locate a viable rotation!");
1800 assert((
Lo ||
Hi) &&
"Failed to find a rotated input vector!");
1809 return Rotation * Scale;
1828 if (ByteRotation <= 0)
1835 int LoByteShift = 16 - ByteRotation;
1836 int HiByteShift = ByteRotation;
1859 const APInt &Zeroable) {
1873 for (
int i = 0; i < NumElements; i++) {
1877 if (i % Scale != 0) {
1888 SDValue V = M < NumElements ? V1 : V2;
1889 M = M % NumElements;
1892 Offset = M - (i / Scale);
1895 if (
Offset % (NumElements / Scale))
1897 }
else if (InputV != V)
1900 if (M != (
Offset + (i / Scale)))
1910 unsigned VilVLoHi = LoongArchISD::VILVL;
1911 if (
Offset >= (NumElements / 2)) {
1912 VilVLoHi = LoongArchISD::VILVH;
1913 Offset -= (NumElements / 2);
1920 InputV = DAG.
getNode(VilVLoHi,
DL, InputVT, Ext, InputV);
1924 }
while (Scale > 1);
1930 for (
int NumExtElements = Bits / 64; NumExtElements < NumElements;
1931 NumExtElements *= 2) {
1951 int SplatIndex = -1;
1952 for (
const auto &M : Mask) {
1959 if (SplatIndex == -1)
1962 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
1964 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT, V1,
1994 unsigned SubVecSize = 4;
1995 if (VT == MVT::v2f64 || VT == MVT::v2i64)
1998 int SubMask[4] = {-1, -1, -1, -1};
1999 for (
unsigned i = 0; i < SubVecSize; ++i) {
2000 for (
unsigned j = i; j < Mask.size(); j += SubVecSize) {
2006 M -= 4 * (j / SubVecSize);
2007 if (M < 0 || M >= 4)
2013 if (SubMask[i] == -1)
2017 else if (M != -1 && M != SubMask[i])
2024 for (
int i = SubVecSize - 1; i >= 0; --i) {
2037 if (VT == MVT::v2f64 || VT == MVT::v2i64)
2038 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT, V1, V2,
2041 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT, V1,
2059 if (VT != MVT::v16i8 && VT != MVT::v8i16 && VT != MVT::v32i8 &&
2068 for (
int i = 0; i < WidenNumElts; ++i)
2069 WidenMask[i] = WidenNumElts - 1 - i;
2077 return DAG.
getNode(LoongArchISD::VSHUF4I,
DL, VT,
2101 const auto &Begin = Mask.begin();
2102 const auto &End = Mask.end();
2103 SDValue OriV1 = V1, OriV2 = V2;
2119 return DAG.
getNode(LoongArchISD::VPACKEV,
DL, VT, V2, V1);
2141 const auto &Begin = Mask.begin();
2142 const auto &End = Mask.end();
2143 SDValue OriV1 = V1, OriV2 = V2;
2159 return DAG.
getNode(LoongArchISD::VPACKOD,
DL, VT, V2, V1);
2182 const auto &Begin = Mask.begin();
2183 const auto &End = Mask.end();
2184 unsigned HalfSize = Mask.size() / 2;
2185 SDValue OriV1 = V1, OriV2 = V2;
2202 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2, V1);
2225 const auto &Begin = Mask.begin();
2226 const auto &End = Mask.end();
2227 SDValue OriV1 = V1, OriV2 = V2;
2243 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2, V1);
2265 const auto &Begin = Mask.begin();
2266 const auto &Mid = Mask.begin() + Mask.size() / 2;
2267 const auto &End = Mask.end();
2268 SDValue OriV1 = V1, OriV2 = V2;
2285 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2, V1);
2307 const auto &Begin = Mask.begin();
2308 const auto &Mid = Mask.begin() + Mask.size() / 2;
2309 const auto &End = Mask.end();
2310 SDValue OriV1 = V1, OriV2 = V2;
2326 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2, V1);
2352 if (Mask.size() != NumElts)
2355 auto tryLowerToExtrAndIns = [&](
unsigned Base) ->
SDValue {
2358 for (
unsigned i = 0; i < NumElts; ++i) {
2361 if (Mask[i] !=
int(
Base + i)) {
2374 int DiffMask = Mask[DiffPos];
2375 if (DiffMask < 0 || DiffMask >=
int(2 * NumElts))
2381 if (
unsigned(DiffMask) < NumElts) {
2386 SrcIdx =
unsigned(DiffMask) - NumElts;
2402 if (
SDValue Result = tryLowerToExtrAndIns(0))
2404 return tryLowerToExtrAndIns(NumElts);
2430 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2, V1);
2443 "Vector type is unsupported for lsx!");
2445 "Two operands have different types!");
2447 "Unexpected mask size for shuffle!");
2448 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
2450 APInt KnownUndef, KnownZero;
2452 APInt Zeroable = KnownUndef | KnownZero;
2522 int SplatIndex = -1;
2523 for (
const auto &M : Mask) {
2530 if (SplatIndex == -1)
2533 const auto &Begin = Mask.begin();
2534 const auto &End = Mask.end();
2535 int HalfSize = Mask.size() / 2;
2537 if (SplatIndex >= HalfSize)
2540 assert(SplatIndex < (
int)Mask.size() &&
"Out of bounds mask index");
2544 return DAG.
getNode(LoongArchISD::VREPLVEI,
DL, VT, V1,
2558 if (Mask.size() == 4) {
2559 unsigned MaskImm = 0;
2560 for (
int i = 1; i >= 0; --i) {
2562 int MHi = Mask[i + 2];
2563 if (!(MLo == -1 || (MLo >= 0 && MLo <= 1) || (MLo >= 4 && MLo <= 5)) ||
2564 !(MHi == -1 || (MHi >= 2 && MHi <= 3) || (MHi >= 6 && MHi <= 7)))
2566 if (MHi != -1 && MLo != -1 && MHi != MLo + 2)
2571 MaskImm |= ((MLo <= 1) ? MLo : (MLo - 2)) & 0x3;
2573 MaskImm |= ((MHi <= 3) ? (MHi - 2) : (MHi - 4)) & 0x3;
2576 return DAG.
getNode(LoongArchISD::VSHUF4I_D,
DL, VT, V1, V2,
2589 if (Mask.size() != 4 || (VT != MVT::v4i64 && VT != MVT::v4f64))
2592 unsigned MaskImm = 0;
2593 for (
unsigned i = 0; i < Mask.size(); ++i) {
2596 MaskImm |= Mask[i] << (i * 2);
2599 return DAG.
getNode(LoongArchISD::XVPERMI,
DL, VT, V1,
2608 if (Mask.size() != 8 || (VT != MVT::v8i32 && VT != MVT::v8f32))
2612 unsigned HalfSize = NumElts / 2;
2613 bool FrontLo =
true, FrontHi =
true;
2614 bool BackLo =
true, BackHi =
true;
2616 auto inRange = [](
int val,
int low,
int high) {
2617 return (val == -1) || (val >= low && val < high);
2620 for (
unsigned i = 0; i < HalfSize; ++i) {
2621 int Fronti = Mask[i];
2622 int Backi = Mask[i + HalfSize];
2624 FrontLo &=
inRange(Fronti, 0, HalfSize);
2625 FrontHi &=
inRange(Fronti, HalfSize, NumElts);
2626 BackLo &=
inRange(Backi, 0, HalfSize);
2627 BackHi &=
inRange(Backi, HalfSize, NumElts);
2633 if ((FrontLo || FrontHi) && (BackLo || BackHi))
2638 for (
unsigned i = 0; i < NumElts; ++i)
2643 return DAG.
getNode(LoongArchISD::XVPERM,
DL, VT, V1, MaskVec);
2665 const auto &Begin = Mask.begin();
2666 const auto &End = Mask.end();
2667 unsigned HalfSize = Mask.size() / 2;
2668 unsigned LeftSize = HalfSize / 2;
2669 SDValue OriV1 = V1, OriV2 = V2;
2676 Mask.size() + HalfSize - LeftSize, 1) &&
2678 Mask.size() + HalfSize + LeftSize, 1))
2689 Mask.size() + HalfSize - LeftSize, 1) &&
2691 Mask.size() + HalfSize + LeftSize, 1))
2696 return DAG.
getNode(LoongArchISD::VILVH,
DL, VT, V2, V1);
2704 const auto &Begin = Mask.begin();
2705 const auto &End = Mask.end();
2706 unsigned HalfSize = Mask.size() / 2;
2707 SDValue OriV1 = V1, OriV2 = V2;
2714 Mask.size() + HalfSize, 1))
2725 Mask.size() + HalfSize, 1))
2730 return DAG.
getNode(LoongArchISD::VILVL,
DL, VT, V2, V1);
2738 const auto &Begin = Mask.begin();
2739 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2740 const auto &Mid = Mask.begin() + Mask.size() / 2;
2741 const auto &RightMid = Mask.end() - Mask.size() / 4;
2742 const auto &End = Mask.end();
2743 unsigned HalfSize = Mask.size() / 2;
2744 SDValue OriV1 = V1, OriV2 = V2;
2765 return DAG.
getNode(LoongArchISD::VPICKEV,
DL, VT, V2, V1);
2773 const auto &Begin = Mask.begin();
2774 const auto &LeftMid = Mask.begin() + Mask.size() / 4;
2775 const auto &Mid = Mask.begin() + Mask.size() / 2;
2776 const auto &RightMid = Mask.end() - Mask.size() / 4;
2777 const auto &End = Mask.end();
2778 unsigned HalfSize = Mask.size() / 2;
2779 SDValue OriV1 = V1, OriV2 = V2;
2801 return DAG.
getNode(LoongArchISD::VPICKOD,
DL, VT, V2, V1);
2810 int HalfSize = NumElts / 2;
2814 if ((
int)Mask.size() != NumElts)
2817 auto tryLowerToExtrAndIns = [&](
int Base) ->
SDValue {
2819 for (
int i = 0; i < NumElts; ++i) {
2822 if (Mask[i] !=
Base + i) {
2824 if (DiffPos.
size() > 2)
2832 if (DiffPos.
size() == 1) {
2833 if (DiffPos[0] < HalfSize && Mask[DiffPos[0] + HalfSize] == -1)
2834 DiffPos.
push_back(DiffPos[0] + HalfSize);
2835 else if (DiffPos[0] >= HalfSize && Mask[DiffPos[0] - HalfSize] == -1)
2836 DiffPos.
insert(DiffPos.
begin(), DiffPos[0] - HalfSize);
2840 if (DiffPos.
size() != 2 || DiffPos[1] != DiffPos[0] + HalfSize)
2844 int DiffMaskLo = Mask[DiffPos[0]];
2845 int DiffMaskHi = Mask[DiffPos[1]];
2846 DiffMaskLo = DiffMaskLo == -1 ? DiffMaskHi - HalfSize : DiffMaskLo;
2847 DiffMaskHi = DiffMaskHi == -1 ? DiffMaskLo + HalfSize : DiffMaskHi;
2848 if (!(DiffMaskLo >= 0 && DiffMaskLo < HalfSize) &&
2849 !(DiffMaskLo >= NumElts && DiffMaskLo < NumElts + HalfSize))
2851 if (!(DiffMaskHi >= HalfSize && DiffMaskHi < NumElts) &&
2852 !(DiffMaskHi >= NumElts + HalfSize && DiffMaskHi < 2 * NumElts))
2854 if (DiffMaskHi != DiffMaskLo + HalfSize)
2858 SDValue SrcVec = (DiffMaskLo < HalfSize) ? V1 : V2;
2860 (DiffMaskLo < HalfSize) ? DiffMaskLo : (DiffMaskLo - NumElts);
2881 if (
SDValue Result = tryLowerToExtrAndIns(0))
2883 return tryLowerToExtrAndIns(NumElts);
2892 if (VT != MVT::v8i32 && VT != MVT::v8f32 && VT != MVT::v4i64 &&
2897 int MaskSize = Mask.size();
2903 auto checkReplaceOne = [&](
int Base,
int Replaced) ->
int {
2905 for (
int i = 0; i < MaskSize; ++i) {
2906 if (Mask[i] ==
Base + i || Mask[i] == -1)
2908 if (Mask[i] != Replaced)
2919 int Idx = checkReplaceOne(0, MaskSize);
2921 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT, V1, V2,
2925 Idx = checkReplaceOne(MaskSize, 0);
2927 return DAG.
getNode(LoongArchISD::XVINSVE0,
DL, VT, V2, V1,
2938 int MaskSize = Mask.size();
2939 int HalfSize = Mask.size() / 2;
2940 const auto &Begin = Mask.begin();
2941 const auto &Mid = Mask.begin() + HalfSize;
2942 const auto &End = Mask.end();
2954 for (
auto it = Begin; it < Mid; it++) {
2957 else if ((*it >= 0 && *it < HalfSize) ||
2958 (*it >= MaskSize && *it < MaskSize + HalfSize)) {
2959 int M = *it < HalfSize ? *it : *it - HalfSize;
2964 assert((
int)MaskAlloc.
size() == HalfSize &&
"xvshuf convert failed!");
2966 for (
auto it = Mid; it < End; it++) {
2969 else if ((*it >= HalfSize && *it < MaskSize) ||
2970 (*it >= MaskSize + HalfSize && *it < MaskSize * 2)) {
2971 int M = *it < MaskSize ? *it - HalfSize : *it - MaskSize;
2976 assert((
int)MaskAlloc.
size() == MaskSize &&
"xvshuf convert failed!");
2980 return DAG.
getNode(LoongArchISD::VSHUF,
DL, VT, MaskVec, V2, V1);
3008 enum HalfMaskType { HighLaneTy, LowLaneTy,
None };
3010 int MaskSize = Mask.size();
3011 int HalfSize = Mask.size() / 2;
3014 HalfMaskType preMask =
None, postMask =
None;
3016 if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
3017 return M < 0 || (M >= 0 && M < HalfSize) ||
3018 (M >= MaskSize && M < MaskSize + HalfSize);
3020 preMask = HighLaneTy;
3021 else if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](
int M) {
3022 return M < 0 || (M >= HalfSize && M < MaskSize) ||
3023 (M >= MaskSize + HalfSize && M < MaskSize * 2);
3025 preMask = LowLaneTy;
3027 if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
3028 return M < 0 || (M >= HalfSize && M < MaskSize) ||
3029 (M >= MaskSize + HalfSize && M < MaskSize * 2);
3031 postMask = LowLaneTy;
3032 else if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](
int M) {
3033 return M < 0 || (M >= 0 && M < HalfSize) ||
3034 (M >= MaskSize && M < MaskSize + HalfSize);
3036 postMask = HighLaneTy;
3044 if (preMask == HighLaneTy && postMask == LowLaneTy) {
3047 if (preMask == LowLaneTy && postMask == HighLaneTy) {
3049 V1 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V1,
3055 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3060 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
3061 *it = *it < 0 ? *it : *it - HalfSize;
3063 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
3064 *it = *it < 0 ? *it : *it + HalfSize;
3066 }
else if (preMask == LowLaneTy && postMask == LowLaneTy) {
3068 V1 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V1,
3074 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3079 for (
auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {
3080 *it = *it < 0 ? *it : *it - HalfSize;
3082 }
else if (preMask == HighLaneTy && postMask == HighLaneTy) {
3084 V1 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V1,
3090 V2 = DAG.
getNode(LoongArchISD::XVPERMI,
DL, MVT::v4i64, V2,
3095 for (
auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {
3096 *it = *it < 0 ? *it : *it + HalfSize;
3121 int Size = Mask.size();
3122 int LaneSize =
Size / 2;
3124 bool LaneCrossing[2] = {
false,
false};
3125 for (
int i = 0; i <
Size; ++i)
3126 if (Mask[i] >= 0 && ((Mask[i] %
Size) / LaneSize) != (i / LaneSize))
3127 LaneCrossing[(Mask[i] %
Size) / LaneSize] =
true;
3130 if (!LaneCrossing[0] && !LaneCrossing[1])
3134 InLaneMask.
assign(Mask.begin(), Mask.end());
3135 for (
int i = 0; i <
Size; ++i) {
3136 int &M = InLaneMask[i];
3139 if (((M %
Size) / LaneSize) != (i / LaneSize))
3140 M = (M % LaneSize) + ((i / LaneSize) * LaneSize) +
Size;
3145 DAG.
getUNDEF(MVT::v4i64), {2, 3, 0, 1});
3160 "Vector type is unsupported for lasx!");
3162 "Two operands have different types!");
3164 "Unexpected mask size for shuffle!");
3165 assert(Mask.size() % 2 == 0 &&
"Expected even mask size.");
3166 assert(Mask.size() >= 4 &&
"Mask size is less than 4.");
3168 APInt KnownUndef, KnownZero;
3170 APInt Zeroable = KnownUndef | KnownZero;
3254 ArrayRef<int> OrigMask = SVOp->
getMask();
3257 MVT VT =
Op.getSimpleValueType();
3261 bool V1IsUndef = V1.
isUndef();
3262 bool V2IsUndef = V2.
isUndef();
3263 if (V1IsUndef && V2IsUndef)
3276 any_of(OrigMask, [NumElements](
int M) {
return M >= NumElements; })) {
3277 SmallVector<int, 8> NewMask(OrigMask);
3278 for (
int &M : NewMask)
3279 if (M >= NumElements)
3285 int MaskUpperLimit = OrigMask.
size() * (V2IsUndef ? 1 : 2);
3286 (void)MaskUpperLimit;
3288 [&](
int M) {
return -1 <=
M &&
M < MaskUpperLimit; }) &&
3289 "Out of bounds shuffle index");
3311 std::tie(Res, Chain) =
3312 makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions,
DL, Chain);
3313 if (Subtarget.is64Bit())
3314 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3326 SDValue Arg = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3330 std::tie(Res, Chain) =
makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,
3331 CallOptions,
DL, Chain);
3337 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3343 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
3344 if (Subtarget.is64Bit())
3345 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Res);
3351 assert(Subtarget.hasBasicF() &&
"Unexpected custom legalization");
3352 MVT VT =
Op.getSimpleValueType();
3357 SDValue Res = Subtarget.is64Bit() ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
3378 "Unsupported vector type for broadcast.");
3381 bool IsIdeneity =
true;
3383 for (
int i = 0; i !=
NumOps; i++) {
3385 if (
Op.getOpcode() !=
ISD::LOAD || (IdentitySrc &&
Op != IdentitySrc)) {
3397 auto ExtType = LN->getExtensionType();
3402 assert(LN->isUnindexed() &&
"Unexpected indexed load.");
3407 SDValue Ops[] = {LN->getChain(), LN->getBasePtr()};
3425 for (
unsigned i = 1; i <
Ops.size(); ++i) {
3439 EVT ResTy,
unsigned first) {
3442 assert(first + NumElts <= Node->getSimpleValueType(0).getVectorNumElements());
3445 Node->op_begin() + first + NumElts);
3454 MVT VT =
Node->getSimpleValueType(0);
3455 EVT ResTy =
Op->getValueType(0);
3458 APInt SplatValue, SplatUndef;
3459 unsigned SplatBitSize;
3462 bool UseSameConstant =
true;
3467 if ((!Subtarget.hasExtLSX() || !Is128Vec) &&
3468 (!Subtarget.hasExtLASX() || !Is256Vec))
3474 if (
Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
3476 SplatBitSize <= 64) {
3478 if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
3482 if (SplatBitSize == 64 && !Subtarget.is64Bit()) {
3489 if ((Is128Vec && ResTy == MVT::v4i32) ||
3490 (Is256Vec && ResTy == MVT::v8i32))
3496 switch (SplatBitSize) {
3500 ViaVecTy = Is128Vec ? MVT::v16i8 : MVT::v32i8;
3503 ViaVecTy = Is128Vec ? MVT::v8i16 : MVT::v16i16;
3506 ViaVecTy = Is128Vec ? MVT::v4i32 : MVT::v8i32;
3509 ViaVecTy = Is128Vec ? MVT::v2i64 : MVT::v4i64;
3517 if (ViaVecTy != ResTy)
3526 for (
unsigned i = 0; i < NumElts; ++i) {
3531 ConstantValue = Opi;
3532 else if (ConstantValue != Opi)
3533 UseSameConstant =
false;
3538 if (IsConstant && UseSameConstant && ResTy != MVT::v2f64) {
3540 for (
unsigned i = 0; i < NumElts; ++i) {
3558 BitVector UndefElements;
3559 if (
Node->getRepeatedSequence(Sequence, &UndefElements) &&
3560 UndefElements.
count() == 0) {
3564 EVT FillTy = Is256Vec
3570 fillVector(Sequence, DAG,
DL, Subtarget, FillVec, FillTy);
3573 unsigned SplatLen = NumElts / SeqLen;
3579 if (SplatEltTy == MVT::i128)
3580 SplatTy = MVT::v4i64;
3588 DAG.
getNode((SplatEltTy == MVT::i128) ? LoongArchISD::XVREPLVE0Q
3589 : LoongArchISD::XVREPLVE0,
3590 DL, SplatTy, SrcVec);
3592 SplatVec = DAG.
getNode(LoongArchISD::VREPLVEI,
DL, SplatTy, SrcVec,
3605 if (ResTy == MVT::v8i32 || ResTy == MVT::v8f32 || ResTy == MVT::v4i64 ||
3606 ResTy == MVT::v4f64) {
3607 unsigned NonUndefCount = 0;
3608 for (
unsigned i = NumElts / 2; i < NumElts; ++i) {
3609 if (!
Node->getOperand(i).isUndef()) {
3611 if (NonUndefCount > 1)
3615 if (NonUndefCount == 1)
3628 VecTy, NumElts / 2);
3639 MVT ResVT =
Op.getSimpleValueType();
3643 unsigned NumFreezeUndef = 0;
3644 unsigned NumZero = 0;
3645 unsigned NumNonZero = 0;
3646 unsigned NonZeros = 0;
3647 SmallSet<SDValue, 4> Undefs;
3648 for (
unsigned i = 0; i != NumOperands; ++i) {
3663 assert(i <
sizeof(NonZeros) * CHAR_BIT);
3670 if (NumNonZero > 2) {
3674 Ops.slice(0, NumOperands / 2));
3676 Ops.slice(NumOperands / 2));
3689 MVT SubVT =
Op.getOperand(0).getSimpleValueType();
3691 for (
unsigned i = 0; i != NumOperands; ++i) {
3692 if ((NonZeros & (1 << i)) == 0)
3703LoongArchTargetLowering::lowerEXTRACT_VECTOR_ELT(
SDValue Op,
3705 MVT EltVT =
Op.getSimpleValueType();
3710 MVT GRLenVT = Subtarget.getGRLenVT();
3738 ? DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Idx)
3742 DAG.
getBitcast((VecTy == MVT::v4f64) ? MVT::v4i64 : VecTy, IdxVec);
3744 DAG.
getNode(LoongArchISD::VSHUF,
DL, VecTy, MaskVec, TmpVec, Vec);
3753 DAG.
getNode(LoongArchISD::XVPERM,
DL, VecTy, Vec, SplatIdx);
3762LoongArchTargetLowering::lowerINSERT_VECTOR_ELT(
SDValue Op,
3764 MVT VT =
Op.getSimpleValueType();
3787 if (!Subtarget.is64Bit() && IdxTy == MVT::i64) {
3789 for (
unsigned i = 0; i < NumElts; ++i) {
3797 for (
unsigned i = 0; i < NumElts; ++i) {
3806 for (
unsigned i = 0; i < NumElts; ++i)
3838 if (Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i32) {
3840 "On LA64, only 64-bit registers can be written.");
3841 return Op.getOperand(0);
3844 if (!Subtarget.is64Bit() &&
Op.getOperand(2).getValueType() == MVT::i64) {
3846 "On LA32, only 32-bit registers can be written.");
3847 return Op.getOperand(0);
3857 "be a constant integer");
3863 Register FrameReg = Subtarget.getRegisterInfo()->getFrameRegister(MF);
3864 EVT VT =
Op.getValueType();
3867 unsigned Depth =
Op.getConstantOperandVal(0);
3868 int GRLenInBytes = Subtarget.getGRLen() / 8;
3871 int Offset = -(GRLenInBytes * 2);
3883 if (
Op.getConstantOperandVal(0) != 0) {
3885 "return address can only be determined for the current frame");
3891 MVT GRLenVT = Subtarget.getGRLenVT();
3903 auto Size = Subtarget.getGRLen() / 8;
3911 auto *FuncInfo = MF.
getInfo<LoongArchMachineFunctionInfo>();
3921 MachinePointerInfo(SV));
3926 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
3927 !Subtarget.hasBasicD() &&
"unexpected target features");
3933 if (
C &&
C->getZExtValue() < UINT64_C(0xFFFFFFFF))
3937 if (Op0->
getOpcode() == LoongArchISD::BSTRPICK &&
3947 EVT RetVT =
Op.getValueType();
3953 std::tie(Result, Chain) =
3960 assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
3961 !Subtarget.hasBasicD() &&
"unexpected target features");
3972 EVT RetVT =
Op.getValueType();
3978 std::tie(Result, Chain) =
3987 EVT VT =
Op.getValueType();
3991 if (
Op.getValueType() == MVT::f32 && Op0VT == MVT::i32 &&
3992 Subtarget.is64Bit() && Subtarget.hasBasicF()) {
3994 return DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, NewOp0);
3996 if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit()) {
3999 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
4013 if (
Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() &&
4014 !Subtarget.hasBasicD()) {
4016 return DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Dst);
4038 N->getOffset(), Flags);
4046template <
class NodeTy>
4049 bool IsLocal)
const {
4060 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
4141 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
4143 const GlobalValue *GV =
N->getGlobal();
4155 unsigned Opc,
bool UseGOT,
4159 MVT GRLenVT = Subtarget.getGRLenVT();
4173 if (
Opc == LoongArch::PseudoLA_TLS_LE && !Large)
4211 Args.emplace_back(Load, CallTy);
4214 TargetLowering::CallLoweringInfo CLI(DAG);
4229 const GlobalValue *GV =
N->getGlobal();
4243LoongArchTargetLowering::lowerGlobalTLSAddress(
SDValue Op,
4250 assert((!Large || Subtarget.is64Bit()) &&
"Large code model requires LA64");
4253 assert(
N->getOffset() == 0 &&
"unexpected offset in global node");
4266 return getDynamicTLSAddr(
N, DAG,
4267 Large ? LoongArch::PseudoLA_TLS_GD_LARGE
4268 : LoongArch::PseudoLA_TLS_GD,
4275 return getDynamicTLSAddr(
N, DAG,
4276 Large ? LoongArch::PseudoLA_TLS_LD_LARGE
4277 : LoongArch::PseudoLA_TLS_LD,
4282 return getStaticTLSAddr(
N, DAG,
4283 Large ? LoongArch::PseudoLA_TLS_IE_LARGE
4284 : LoongArch::PseudoLA_TLS_IE,
4291 return getStaticTLSAddr(
N, DAG, LoongArch::PseudoLA_TLS_LE,
4295 return getTLSDescAddr(
N, DAG,
4296 Large ? LoongArch::PseudoLA_TLS_DESC_LARGE
4297 : LoongArch::PseudoLA_TLS_DESC,
4301template <
unsigned N>
4306 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
4307 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
4309 ": argument out of range.");
4316LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(
SDValue Op,
4318 switch (
Op.getConstantOperandVal(0)) {
4321 case Intrinsic::thread_pointer: {
4325 case Intrinsic::loongarch_lsx_vpickve2gr_d:
4326 case Intrinsic::loongarch_lsx_vpickve2gr_du:
4327 case Intrinsic::loongarch_lsx_vreplvei_d:
4328 case Intrinsic::loongarch_lasx_xvrepl128vei_d:
4330 case Intrinsic::loongarch_lsx_vreplvei_w:
4331 case Intrinsic::loongarch_lasx_xvrepl128vei_w:
4332 case Intrinsic::loongarch_lasx_xvpickve2gr_d:
4333 case Intrinsic::loongarch_lasx_xvpickve2gr_du:
4334 case Intrinsic::loongarch_lasx_xvpickve_d:
4335 case Intrinsic::loongarch_lasx_xvpickve_d_f:
4337 case Intrinsic::loongarch_lasx_xvinsve0_d:
4339 case Intrinsic::loongarch_lsx_vsat_b:
4340 case Intrinsic::loongarch_lsx_vsat_bu:
4341 case Intrinsic::loongarch_lsx_vrotri_b:
4342 case Intrinsic::loongarch_lsx_vsllwil_h_b:
4343 case Intrinsic::loongarch_lsx_vsllwil_hu_bu:
4344 case Intrinsic::loongarch_lsx_vsrlri_b:
4345 case Intrinsic::loongarch_lsx_vsrari_b:
4346 case Intrinsic::loongarch_lsx_vreplvei_h:
4347 case Intrinsic::loongarch_lasx_xvsat_b:
4348 case Intrinsic::loongarch_lasx_xvsat_bu:
4349 case Intrinsic::loongarch_lasx_xvrotri_b:
4350 case Intrinsic::loongarch_lasx_xvsllwil_h_b:
4351 case Intrinsic::loongarch_lasx_xvsllwil_hu_bu:
4352 case Intrinsic::loongarch_lasx_xvsrlri_b:
4353 case Intrinsic::loongarch_lasx_xvsrari_b:
4354 case Intrinsic::loongarch_lasx_xvrepl128vei_h:
4355 case Intrinsic::loongarch_lasx_xvpickve_w:
4356 case Intrinsic::loongarch_lasx_xvpickve_w_f:
4358 case Intrinsic::loongarch_lasx_xvinsve0_w:
4360 case Intrinsic::loongarch_lsx_vsat_h:
4361 case Intrinsic::loongarch_lsx_vsat_hu:
4362 case Intrinsic::loongarch_lsx_vrotri_h:
4363 case Intrinsic::loongarch_lsx_vsllwil_w_h:
4364 case Intrinsic::loongarch_lsx_vsllwil_wu_hu:
4365 case Intrinsic::loongarch_lsx_vsrlri_h:
4366 case Intrinsic::loongarch_lsx_vsrari_h:
4367 case Intrinsic::loongarch_lsx_vreplvei_b:
4368 case Intrinsic::loongarch_lasx_xvsat_h:
4369 case Intrinsic::loongarch_lasx_xvsat_hu:
4370 case Intrinsic::loongarch_lasx_xvrotri_h:
4371 case Intrinsic::loongarch_lasx_xvsllwil_w_h:
4372 case Intrinsic::loongarch_lasx_xvsllwil_wu_hu:
4373 case Intrinsic::loongarch_lasx_xvsrlri_h:
4374 case Intrinsic::loongarch_lasx_xvsrari_h:
4375 case Intrinsic::loongarch_lasx_xvrepl128vei_b:
4377 case Intrinsic::loongarch_lsx_vsrlni_b_h:
4378 case Intrinsic::loongarch_lsx_vsrani_b_h:
4379 case Intrinsic::loongarch_lsx_vsrlrni_b_h:
4380 case Intrinsic::loongarch_lsx_vsrarni_b_h:
4381 case Intrinsic::loongarch_lsx_vssrlni_b_h:
4382 case Intrinsic::loongarch_lsx_vssrani_b_h:
4383 case Intrinsic::loongarch_lsx_vssrlni_bu_h:
4384 case Intrinsic::loongarch_lsx_vssrani_bu_h:
4385 case Intrinsic::loongarch_lsx_vssrlrni_b_h:
4386 case Intrinsic::loongarch_lsx_vssrarni_b_h:
4387 case Intrinsic::loongarch_lsx_vssrlrni_bu_h:
4388 case Intrinsic::loongarch_lsx_vssrarni_bu_h:
4389 case Intrinsic::loongarch_lasx_xvsrlni_b_h:
4390 case Intrinsic::loongarch_lasx_xvsrani_b_h:
4391 case Intrinsic::loongarch_lasx_xvsrlrni_b_h:
4392 case Intrinsic::loongarch_lasx_xvsrarni_b_h:
4393 case Intrinsic::loongarch_lasx_xvssrlni_b_h:
4394 case Intrinsic::loongarch_lasx_xvssrani_b_h:
4395 case Intrinsic::loongarch_lasx_xvssrlni_bu_h:
4396 case Intrinsic::loongarch_lasx_xvssrani_bu_h:
4397 case Intrinsic::loongarch_lasx_xvssrlrni_b_h:
4398 case Intrinsic::loongarch_lasx_xvssrarni_b_h:
4399 case Intrinsic::loongarch_lasx_xvssrlrni_bu_h:
4400 case Intrinsic::loongarch_lasx_xvssrarni_bu_h:
4402 case Intrinsic::loongarch_lsx_vsat_w:
4403 case Intrinsic::loongarch_lsx_vsat_wu:
4404 case Intrinsic::loongarch_lsx_vrotri_w:
4405 case Intrinsic::loongarch_lsx_vsllwil_d_w:
4406 case Intrinsic::loongarch_lsx_vsllwil_du_wu:
4407 case Intrinsic::loongarch_lsx_vsrlri_w:
4408 case Intrinsic::loongarch_lsx_vsrari_w:
4409 case Intrinsic::loongarch_lsx_vslei_bu:
4410 case Intrinsic::loongarch_lsx_vslei_hu:
4411 case Intrinsic::loongarch_lsx_vslei_wu:
4412 case Intrinsic::loongarch_lsx_vslei_du:
4413 case Intrinsic::loongarch_lsx_vslti_bu:
4414 case Intrinsic::loongarch_lsx_vslti_hu:
4415 case Intrinsic::loongarch_lsx_vslti_wu:
4416 case Intrinsic::loongarch_lsx_vslti_du:
4417 case Intrinsic::loongarch_lsx_vbsll_v:
4418 case Intrinsic::loongarch_lsx_vbsrl_v:
4419 case Intrinsic::loongarch_lasx_xvsat_w:
4420 case Intrinsic::loongarch_lasx_xvsat_wu:
4421 case Intrinsic::loongarch_lasx_xvrotri_w:
4422 case Intrinsic::loongarch_lasx_xvsllwil_d_w:
4423 case Intrinsic::loongarch_lasx_xvsllwil_du_wu:
4424 case Intrinsic::loongarch_lasx_xvsrlri_w:
4425 case Intrinsic::loongarch_lasx_xvsrari_w:
4426 case Intrinsic::loongarch_lasx_xvslei_bu:
4427 case Intrinsic::loongarch_lasx_xvslei_hu:
4428 case Intrinsic::loongarch_lasx_xvslei_wu:
4429 case Intrinsic::loongarch_lasx_xvslei_du:
4430 case Intrinsic::loongarch_lasx_xvslti_bu:
4431 case Intrinsic::loongarch_lasx_xvslti_hu:
4432 case Intrinsic::loongarch_lasx_xvslti_wu:
4433 case Intrinsic::loongarch_lasx_xvslti_du:
4434 case Intrinsic::loongarch_lasx_xvbsll_v:
4435 case Intrinsic::loongarch_lasx_xvbsrl_v:
4437 case Intrinsic::loongarch_lsx_vseqi_b:
4438 case Intrinsic::loongarch_lsx_vseqi_h:
4439 case Intrinsic::loongarch_lsx_vseqi_w:
4440 case Intrinsic::loongarch_lsx_vseqi_d:
4441 case Intrinsic::loongarch_lsx_vslei_b:
4442 case Intrinsic::loongarch_lsx_vslei_h:
4443 case Intrinsic::loongarch_lsx_vslei_w:
4444 case Intrinsic::loongarch_lsx_vslei_d:
4445 case Intrinsic::loongarch_lsx_vslti_b:
4446 case Intrinsic::loongarch_lsx_vslti_h:
4447 case Intrinsic::loongarch_lsx_vslti_w:
4448 case Intrinsic::loongarch_lsx_vslti_d:
4449 case Intrinsic::loongarch_lasx_xvseqi_b:
4450 case Intrinsic::loongarch_lasx_xvseqi_h:
4451 case Intrinsic::loongarch_lasx_xvseqi_w:
4452 case Intrinsic::loongarch_lasx_xvseqi_d:
4453 case Intrinsic::loongarch_lasx_xvslei_b:
4454 case Intrinsic::loongarch_lasx_xvslei_h:
4455 case Intrinsic::loongarch_lasx_xvslei_w:
4456 case Intrinsic::loongarch_lasx_xvslei_d:
4457 case Intrinsic::loongarch_lasx_xvslti_b:
4458 case Intrinsic::loongarch_lasx_xvslti_h:
4459 case Intrinsic::loongarch_lasx_xvslti_w:
4460 case Intrinsic::loongarch_lasx_xvslti_d:
4462 case Intrinsic::loongarch_lsx_vsrlni_h_w:
4463 case Intrinsic::loongarch_lsx_vsrani_h_w:
4464 case Intrinsic::loongarch_lsx_vsrlrni_h_w:
4465 case Intrinsic::loongarch_lsx_vsrarni_h_w:
4466 case Intrinsic::loongarch_lsx_vssrlni_h_w:
4467 case Intrinsic::loongarch_lsx_vssrani_h_w:
4468 case Intrinsic::loongarch_lsx_vssrlni_hu_w:
4469 case Intrinsic::loongarch_lsx_vssrani_hu_w:
4470 case Intrinsic::loongarch_lsx_vssrlrni_h_w:
4471 case Intrinsic::loongarch_lsx_vssrarni_h_w:
4472 case Intrinsic::loongarch_lsx_vssrlrni_hu_w:
4473 case Intrinsic::loongarch_lsx_vssrarni_hu_w:
4474 case Intrinsic::loongarch_lsx_vfrstpi_b:
4475 case Intrinsic::loongarch_lsx_vfrstpi_h:
4476 case Intrinsic::loongarch_lasx_xvsrlni_h_w:
4477 case Intrinsic::loongarch_lasx_xvsrani_h_w:
4478 case Intrinsic::loongarch_lasx_xvsrlrni_h_w:
4479 case Intrinsic::loongarch_lasx_xvsrarni_h_w:
4480 case Intrinsic::loongarch_lasx_xvssrlni_h_w:
4481 case Intrinsic::loongarch_lasx_xvssrani_h_w:
4482 case Intrinsic::loongarch_lasx_xvssrlni_hu_w:
4483 case Intrinsic::loongarch_lasx_xvssrani_hu_w:
4484 case Intrinsic::loongarch_lasx_xvssrlrni_h_w:
4485 case Intrinsic::loongarch_lasx_xvssrarni_h_w:
4486 case Intrinsic::loongarch_lasx_xvssrlrni_hu_w:
4487 case Intrinsic::loongarch_lasx_xvssrarni_hu_w:
4488 case Intrinsic::loongarch_lasx_xvfrstpi_b:
4489 case Intrinsic::loongarch_lasx_xvfrstpi_h:
4491 case Intrinsic::loongarch_lsx_vsat_d:
4492 case Intrinsic::loongarch_lsx_vsat_du:
4493 case Intrinsic::loongarch_lsx_vrotri_d:
4494 case Intrinsic::loongarch_lsx_vsrlri_d:
4495 case Intrinsic::loongarch_lsx_vsrari_d:
4496 case Intrinsic::loongarch_lasx_xvsat_d:
4497 case Intrinsic::loongarch_lasx_xvsat_du:
4498 case Intrinsic::loongarch_lasx_xvrotri_d:
4499 case Intrinsic::loongarch_lasx_xvsrlri_d:
4500 case Intrinsic::loongarch_lasx_xvsrari_d:
4502 case Intrinsic::loongarch_lsx_vsrlni_w_d:
4503 case Intrinsic::loongarch_lsx_vsrani_w_d:
4504 case Intrinsic::loongarch_lsx_vsrlrni_w_d:
4505 case Intrinsic::loongarch_lsx_vsrarni_w_d:
4506 case Intrinsic::loongarch_lsx_vssrlni_w_d:
4507 case Intrinsic::loongarch_lsx_vssrani_w_d:
4508 case Intrinsic::loongarch_lsx_vssrlni_wu_d:
4509 case Intrinsic::loongarch_lsx_vssrani_wu_d:
4510 case Intrinsic::loongarch_lsx_vssrlrni_w_d:
4511 case Intrinsic::loongarch_lsx_vssrarni_w_d:
4512 case Intrinsic::loongarch_lsx_vssrlrni_wu_d:
4513 case Intrinsic::loongarch_lsx_vssrarni_wu_d:
4514 case Intrinsic::loongarch_lasx_xvsrlni_w_d:
4515 case Intrinsic::loongarch_lasx_xvsrani_w_d:
4516 case Intrinsic::loongarch_lasx_xvsrlrni_w_d:
4517 case Intrinsic::loongarch_lasx_xvsrarni_w_d:
4518 case Intrinsic::loongarch_lasx_xvssrlni_w_d:
4519 case Intrinsic::loongarch_lasx_xvssrani_w_d:
4520 case Intrinsic::loongarch_lasx_xvssrlni_wu_d:
4521 case Intrinsic::loongarch_lasx_xvssrani_wu_d:
4522 case Intrinsic::loongarch_lasx_xvssrlrni_w_d:
4523 case Intrinsic::loongarch_lasx_xvssrarni_w_d:
4524 case Intrinsic::loongarch_lasx_xvssrlrni_wu_d:
4525 case Intrinsic::loongarch_lasx_xvssrarni_wu_d:
4527 case Intrinsic::loongarch_lsx_vsrlni_d_q:
4528 case Intrinsic::loongarch_lsx_vsrani_d_q:
4529 case Intrinsic::loongarch_lsx_vsrlrni_d_q:
4530 case Intrinsic::loongarch_lsx_vsrarni_d_q:
4531 case Intrinsic::loongarch_lsx_vssrlni_d_q:
4532 case Intrinsic::loongarch_lsx_vssrani_d_q:
4533 case Intrinsic::loongarch_lsx_vssrlni_du_q:
4534 case Intrinsic::loongarch_lsx_vssrani_du_q:
4535 case Intrinsic::loongarch_lsx_vssrlrni_d_q:
4536 case Intrinsic::loongarch_lsx_vssrarni_d_q:
4537 case Intrinsic::loongarch_lsx_vssrlrni_du_q:
4538 case Intrinsic::loongarch_lsx_vssrarni_du_q:
4539 case Intrinsic::loongarch_lasx_xvsrlni_d_q:
4540 case Intrinsic::loongarch_lasx_xvsrani_d_q:
4541 case Intrinsic::loongarch_lasx_xvsrlrni_d_q:
4542 case Intrinsic::loongarch_lasx_xvsrarni_d_q:
4543 case Intrinsic::loongarch_lasx_xvssrlni_d_q:
4544 case Intrinsic::loongarch_lasx_xvssrani_d_q:
4545 case Intrinsic::loongarch_lasx_xvssrlni_du_q:
4546 case Intrinsic::loongarch_lasx_xvssrani_du_q:
4547 case Intrinsic::loongarch_lasx_xvssrlrni_d_q:
4548 case Intrinsic::loongarch_lasx_xvssrarni_d_q:
4549 case Intrinsic::loongarch_lasx_xvssrlrni_du_q:
4550 case Intrinsic::loongarch_lasx_xvssrarni_du_q:
4552 case Intrinsic::loongarch_lsx_vnori_b:
4553 case Intrinsic::loongarch_lsx_vshuf4i_b:
4554 case Intrinsic::loongarch_lsx_vshuf4i_h:
4555 case Intrinsic::loongarch_lsx_vshuf4i_w:
4556 case Intrinsic::loongarch_lasx_xvnori_b:
4557 case Intrinsic::loongarch_lasx_xvshuf4i_b:
4558 case Intrinsic::loongarch_lasx_xvshuf4i_h:
4559 case Intrinsic::loongarch_lasx_xvshuf4i_w:
4560 case Intrinsic::loongarch_lasx_xvpermi_d:
4562 case Intrinsic::loongarch_lsx_vshuf4i_d:
4563 case Intrinsic::loongarch_lsx_vpermi_w:
4564 case Intrinsic::loongarch_lsx_vbitseli_b:
4565 case Intrinsic::loongarch_lsx_vextrins_b:
4566 case Intrinsic::loongarch_lsx_vextrins_h:
4567 case Intrinsic::loongarch_lsx_vextrins_w:
4568 case Intrinsic::loongarch_lsx_vextrins_d:
4569 case Intrinsic::loongarch_lasx_xvshuf4i_d:
4570 case Intrinsic::loongarch_lasx_xvpermi_w:
4571 case Intrinsic::loongarch_lasx_xvpermi_q:
4572 case Intrinsic::loongarch_lasx_xvbitseli_b:
4573 case Intrinsic::loongarch_lasx_xvextrins_b:
4574 case Intrinsic::loongarch_lasx_xvextrins_h:
4575 case Intrinsic::loongarch_lasx_xvextrins_w:
4576 case Intrinsic::loongarch_lasx_xvextrins_d:
4578 case Intrinsic::loongarch_lsx_vrepli_b:
4579 case Intrinsic::loongarch_lsx_vrepli_h:
4580 case Intrinsic::loongarch_lsx_vrepli_w:
4581 case Intrinsic::loongarch_lsx_vrepli_d:
4582 case Intrinsic::loongarch_lasx_xvrepli_b:
4583 case Intrinsic::loongarch_lasx_xvrepli_h:
4584 case Intrinsic::loongarch_lasx_xvrepli_w:
4585 case Intrinsic::loongarch_lasx_xvrepli_d:
4587 case Intrinsic::loongarch_lsx_vldi:
4588 case Intrinsic::loongarch_lasx_xvldi:
4604LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(
SDValue Op,
4607 MVT GRLenVT = Subtarget.getGRLenVT();
4608 EVT VT =
Op.getValueType();
4610 const StringRef ErrorMsgOOR =
"argument out of range";
4611 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4612 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4614 switch (
Op.getConstantOperandVal(1)) {
4617 case Intrinsic::loongarch_crc_w_b_w:
4618 case Intrinsic::loongarch_crc_w_h_w:
4619 case Intrinsic::loongarch_crc_w_w_w:
4620 case Intrinsic::loongarch_crc_w_d_w:
4621 case Intrinsic::loongarch_crcc_w_b_w:
4622 case Intrinsic::loongarch_crcc_w_h_w:
4623 case Intrinsic::loongarch_crcc_w_w_w:
4624 case Intrinsic::loongarch_crcc_w_d_w:
4626 case Intrinsic::loongarch_csrrd_w:
4627 case Intrinsic::loongarch_csrrd_d: {
4628 unsigned Imm =
Op.getConstantOperandVal(2);
4631 : DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
4634 case Intrinsic::loongarch_csrwr_w:
4635 case Intrinsic::loongarch_csrwr_d: {
4636 unsigned Imm =
Op.getConstantOperandVal(3);
4639 : DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
4640 {Chain,
Op.getOperand(2),
4643 case Intrinsic::loongarch_csrxchg_w:
4644 case Intrinsic::loongarch_csrxchg_d: {
4645 unsigned Imm =
Op.getConstantOperandVal(4);
4648 : DAG.
getNode(LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
4649 {Chain,
Op.getOperand(2),
Op.getOperand(3),
4652 case Intrinsic::loongarch_iocsrrd_d: {
4654 LoongArchISD::IOCSRRD_D,
DL, {GRLenVT, MVT::Other},
4657#define IOCSRRD_CASE(NAME, NODE) \
4658 case Intrinsic::loongarch_##NAME: { \
4659 return DAG.getNode(LoongArchISD::NODE, DL, {GRLenVT, MVT::Other}, \
4660 {Chain, Op.getOperand(2)}); \
4666 case Intrinsic::loongarch_cpucfg: {
4667 return DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
4668 {Chain,
Op.getOperand(2)});
4670 case Intrinsic::loongarch_lddir_d: {
4671 unsigned Imm =
Op.getConstantOperandVal(3);
4676 case Intrinsic::loongarch_movfcsr2gr: {
4677 if (!Subtarget.hasBasicF())
4679 unsigned Imm =
Op.getConstantOperandVal(2);
4682 : DAG.
getNode(LoongArchISD::MOVFCSR2GR,
DL, {VT, MVT::Other},
4685 case Intrinsic::loongarch_lsx_vld:
4686 case Intrinsic::loongarch_lsx_vldrepl_b:
4687 case Intrinsic::loongarch_lasx_xvld:
4688 case Intrinsic::loongarch_lasx_xvldrepl_b:
4692 case Intrinsic::loongarch_lsx_vldrepl_h:
4693 case Intrinsic::loongarch_lasx_xvldrepl_h:
4697 Op,
"argument out of range or not a multiple of 2", DAG)
4699 case Intrinsic::loongarch_lsx_vldrepl_w:
4700 case Intrinsic::loongarch_lasx_xvldrepl_w:
4704 Op,
"argument out of range or not a multiple of 4", DAG)
4706 case Intrinsic::loongarch_lsx_vldrepl_d:
4707 case Intrinsic::loongarch_lasx_xvldrepl_d:
4711 Op,
"argument out of range or not a multiple of 8", DAG)
4722 return Op.getOperand(0);
4728 MVT GRLenVT = Subtarget.getGRLenVT();
4730 uint64_t IntrinsicEnum =
Op.getConstantOperandVal(1);
4732 const StringRef ErrorMsgOOR =
"argument out of range";
4733 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
4734 const StringRef ErrorMsgReqLA32 =
"requires loongarch32";
4735 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
4737 switch (IntrinsicEnum) {
4741 case Intrinsic::loongarch_cacop_d:
4742 case Intrinsic::loongarch_cacop_w: {
4743 if (IntrinsicEnum == Intrinsic::loongarch_cacop_d && !Subtarget.is64Bit())
4745 if (IntrinsicEnum == Intrinsic::loongarch_cacop_w && Subtarget.is64Bit())
4754 case Intrinsic::loongarch_dbar: {
4761 case Intrinsic::loongarch_ibar: {
4768 case Intrinsic::loongarch_break: {
4775 case Intrinsic::loongarch_movgr2fcsr: {
4776 if (!Subtarget.hasBasicF())
4786 case Intrinsic::loongarch_syscall: {
4793#define IOCSRWR_CASE(NAME, NODE) \
4794 case Intrinsic::loongarch_##NAME: { \
4795 SDValue Op3 = Op.getOperand(3); \
4796 return Subtarget.is64Bit() \
4797 ? DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, \
4798 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
4799 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op3)) \
4800 : DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, Op2, \
4807 case Intrinsic::loongarch_iocsrwr_d: {
4808 return !Subtarget.is64Bit()
4815#define ASRT_LE_GT_CASE(NAME) \
4816 case Intrinsic::loongarch_##NAME: { \
4817 return !Subtarget.is64Bit() \
4818 ? emitIntrinsicErrorMessage(Op, ErrorMsgReqLA64, DAG) \
4823#undef ASRT_LE_GT_CASE
4824 case Intrinsic::loongarch_ldpte_d: {
4825 unsigned Imm =
Op.getConstantOperandVal(3);
4826 return !Subtarget.is64Bit()
4831 case Intrinsic::loongarch_lsx_vst:
4832 case Intrinsic::loongarch_lasx_xvst:
4836 case Intrinsic::loongarch_lasx_xvstelm_b:
4841 case Intrinsic::loongarch_lsx_vstelm_b:
4846 case Intrinsic::loongarch_lasx_xvstelm_h:
4851 Op,
"argument out of range or not a multiple of 2", DAG)
4853 case Intrinsic::loongarch_lsx_vstelm_h:
4858 Op,
"argument out of range or not a multiple of 2", DAG)
4860 case Intrinsic::loongarch_lasx_xvstelm_w:
4865 Op,
"argument out of range or not a multiple of 4", DAG)
4867 case Intrinsic::loongarch_lsx_vstelm_w:
4872 Op,
"argument out of range or not a multiple of 4", DAG)
4874 case Intrinsic::loongarch_lasx_xvstelm_d:
4879 Op,
"argument out of range or not a multiple of 8", DAG)
4881 case Intrinsic::loongarch_lsx_vstelm_d:
4886 Op,
"argument out of range or not a multiple of 8", DAG)
4897 EVT VT =
Lo.getValueType();
4938 EVT VT =
Lo.getValueType();
4992 return LoongArchISD::DIV_W;
4994 return LoongArchISD::DIV_WU;
4996 return LoongArchISD::MOD_W;
4998 return LoongArchISD::MOD_WU;
5000 return LoongArchISD::SLL_W;
5002 return LoongArchISD::SRA_W;
5004 return LoongArchISD::SRL_W;
5007 return LoongArchISD::ROTR_W;
5009 return LoongArchISD::CTZ_W;
5011 return LoongArchISD::CLZ_W;
5030 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
5031 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0);
5035 NewOp0 = DAG.
getNode(ExtOpc,
DL, MVT::i64,
N->getOperand(0));
5041 NewRes = DAG.
getNode(WOpcode,
DL, MVT::i64, NewOp0, NewOp1);
5068 StringRef ErrorMsg,
bool WithChain =
true) {
5073 Results.push_back(
N->getOperand(0));
5076template <
unsigned N>
5081 const StringRef ErrorMsgOOR =
"argument out of range";
5082 unsigned Imm =
Node->getConstantOperandVal(2);
5116 switch (
N->getConstantOperandVal(0)) {
5119 case Intrinsic::loongarch_lsx_vpickve2gr_b:
5121 LoongArchISD::VPICK_SEXT_ELT);
5123 case Intrinsic::loongarch_lsx_vpickve2gr_h:
5124 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
5126 LoongArchISD::VPICK_SEXT_ELT);
5128 case Intrinsic::loongarch_lsx_vpickve2gr_w:
5130 LoongArchISD::VPICK_SEXT_ELT);
5132 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
5134 LoongArchISD::VPICK_ZEXT_ELT);
5136 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
5137 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
5139 LoongArchISD::VPICK_ZEXT_ELT);
5141 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
5143 LoongArchISD::VPICK_ZEXT_ELT);
5145 case Intrinsic::loongarch_lsx_bz_b:
5146 case Intrinsic::loongarch_lsx_bz_h:
5147 case Intrinsic::loongarch_lsx_bz_w:
5148 case Intrinsic::loongarch_lsx_bz_d:
5149 case Intrinsic::loongarch_lasx_xbz_b:
5150 case Intrinsic::loongarch_lasx_xbz_h:
5151 case Intrinsic::loongarch_lasx_xbz_w:
5152 case Intrinsic::loongarch_lasx_xbz_d:
5154 LoongArchISD::VALL_ZERO);
5156 case Intrinsic::loongarch_lsx_bz_v:
5157 case Intrinsic::loongarch_lasx_xbz_v:
5159 LoongArchISD::VANY_ZERO);
5161 case Intrinsic::loongarch_lsx_bnz_b:
5162 case Intrinsic::loongarch_lsx_bnz_h:
5163 case Intrinsic::loongarch_lsx_bnz_w:
5164 case Intrinsic::loongarch_lsx_bnz_d:
5165 case Intrinsic::loongarch_lasx_xbnz_b:
5166 case Intrinsic::loongarch_lasx_xbnz_h:
5167 case Intrinsic::loongarch_lasx_xbnz_w:
5168 case Intrinsic::loongarch_lasx_xbnz_d:
5170 LoongArchISD::VALL_NONZERO);
5172 case Intrinsic::loongarch_lsx_bnz_v:
5173 case Intrinsic::loongarch_lasx_xbnz_v:
5175 LoongArchISD::VANY_NONZERO);
5183 assert(
N->getValueType(0) == MVT::i128 &&
5184 "AtomicCmpSwap on types less than 128 should be legal");
5188 switch (
MemOp->getMergedOrdering()) {
5192 Opcode = LoongArch::PseudoCmpXchg128Acquire;
5196 Opcode = LoongArch::PseudoCmpXchg128;
5203 auto CmpVal = DAG.
SplitScalar(
N->getOperand(2),
DL, MVT::i64, MVT::i64);
5204 auto NewVal = DAG.
SplitScalar(
N->getOperand(3),
DL, MVT::i64, MVT::i64);
5205 SDValue Ops[] = {
N->getOperand(1), CmpVal.first, CmpVal.second,
5206 NewVal.first, NewVal.second,
N->getOperand(0)};
5209 Opcode,
SDLoc(
N), DAG.
getVTList(MVT::i64, MVT::i64, MVT::i64, MVT::Other),
5220 EVT VT =
N->getValueType(0);
5221 switch (
N->getOpcode()) {
5226 assert(
N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
5227 "Unexpected custom legalisation");
5234 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5235 "Unexpected custom legalisation");
5237 Subtarget.hasDiv32() && VT == MVT::i32
5244 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5245 "Unexpected custom legalisation");
5253 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5254 "Unexpected custom legalisation");
5258 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5259 "Unexpected custom legalisation");
5266 if (Src.getValueType() == MVT::f16)
5277 EVT OpVT = Src.getValueType();
5281 std::tie(Result, Chain) =
5288 EVT SrcVT = Src.getValueType();
5289 if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.is64Bit() &&
5290 Subtarget.hasBasicF()) {
5292 DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Src);
5294 }
else if (VT == MVT::i64 && SrcVT == MVT::f64 && !Subtarget.is64Bit()) {
5296 DAG.
getVTList(MVT::i32, MVT::i32), Src);
5304 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5305 "Unexpected custom legalisation");
5308 TLI.expandFP_TO_UINT(
N, Tmp1, Tmp2, DAG);
5313 assert(VT == MVT::v2f32 && Subtarget.hasExtLSX() &&
5314 "Unexpected custom legalisation");
5320 if (OpVT == MVT::v2f64) {
5330 assert((VT == MVT::i16 || VT == MVT::i32) &&
5331 "Unexpected custom legalization");
5332 MVT GRLenVT = Subtarget.getGRLenVT();
5339 Tmp = DAG.
getNode(LoongArchISD::REVB_2H,
DL, GRLenVT, NewSrc);
5344 Tmp = DAG.
getNode(LoongArchISD::REVB_2W,
DL, GRLenVT, NewSrc);
5352 assert((VT == MVT::i8 || (VT == MVT::i32 && Subtarget.is64Bit())) &&
5353 "Unexpected custom legalization");
5354 MVT GRLenVT = Subtarget.getGRLenVT();
5361 Tmp = DAG.
getNode(LoongArchISD::BITREV_4B,
DL, GRLenVT, NewSrc);
5364 Tmp = DAG.
getNode(LoongArchISD::BITREV_W,
DL, GRLenVT, NewSrc);
5372 assert(VT == MVT::i32 && Subtarget.is64Bit() &&
5373 "Unexpected custom legalisation");
5380 MVT GRLenVT = Subtarget.getGRLenVT();
5381 const StringRef ErrorMsgOOR =
"argument out of range";
5382 const StringRef ErrorMsgReqLA64 =
"requires loongarch64";
5383 const StringRef ErrorMsgReqF =
"requires basic 'f' target feature";
5385 switch (
N->getConstantOperandVal(1)) {
5388 case Intrinsic::loongarch_movfcsr2gr: {
5389 if (!Subtarget.hasBasicF()) {
5399 LoongArchISD::MOVFCSR2GR,
SDLoc(
N), {MVT::i64, MVT::Other},
5406#define CRC_CASE_EXT_BINARYOP(NAME, NODE) \
5407 case Intrinsic::loongarch_##NAME: { \
5408 SDValue NODE = DAG.getNode( \
5409 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5410 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), \
5411 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5412 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5413 Results.push_back(NODE.getValue(1)); \
5422#undef CRC_CASE_EXT_BINARYOP
5424#define CRC_CASE_EXT_UNARYOP(NAME, NODE) \
5425 case Intrinsic::loongarch_##NAME: { \
5426 SDValue NODE = DAG.getNode( \
5427 LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5429 DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))}); \
5430 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0))); \
5431 Results.push_back(NODE.getValue(1)); \
5436#undef CRC_CASE_EXT_UNARYOP
5437#define CSR_CASE(ID) \
5438 case Intrinsic::loongarch_##ID: { \
5439 if (!Subtarget.is64Bit()) \
5440 emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgReqLA64); \
5448 case Intrinsic::loongarch_csrrd_w: {
5455 DAG.
getNode(LoongArchISD::CSRRD,
DL, {GRLenVT, MVT::Other},
5462 case Intrinsic::loongarch_csrwr_w: {
5463 unsigned Imm =
N->getConstantOperandVal(3);
5469 DAG.
getNode(LoongArchISD::CSRWR,
DL, {GRLenVT, MVT::Other},
5477 case Intrinsic::loongarch_csrxchg_w: {
5478 unsigned Imm =
N->getConstantOperandVal(4);
5484 LoongArchISD::CSRXCHG,
DL, {GRLenVT, MVT::Other},
5493#define IOCSRRD_CASE(NAME, NODE) \
5494 case Intrinsic::loongarch_##NAME: { \
5495 SDValue IOCSRRDResults = \
5496 DAG.getNode(LoongArchISD::NODE, DL, {MVT::i64, MVT::Other}, \
5497 {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2)}); \
5498 Results.push_back( \
5499 DAG.getNode(ISD::TRUNCATE, DL, VT, IOCSRRDResults.getValue(0))); \
5500 Results.push_back(IOCSRRDResults.getValue(1)); \
5507 case Intrinsic::loongarch_cpucfg: {
5509 DAG.
getNode(LoongArchISD::CPUCFG,
DL, {GRLenVT, MVT::Other},
5516 case Intrinsic::loongarch_lddir_d: {
5517 if (!Subtarget.is64Bit()) {
5527 if (Subtarget.is64Bit())
5529 "On LA64, only 64-bit registers can be read.");
5532 "On LA32, only 32-bit registers can be read.");
5534 Results.push_back(
N->getOperand(0));
5545 OpVT == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;
5558 MVT VT =
N->getSimpleValueType(0);
5564 EVT InVT = In.getValueType();
5575 for (
unsigned I = 0;
I < MinElts; ++
I)
5576 TruncMask[
I] = Scale *
I;
5578 unsigned WidenNumElts = 128 / In.getScalarValueSizeInBits();
5579 MVT SVT = In.getSimpleValueType().getScalarType();
5585 "Illegal vector type in truncation");
5601 assert(
N->getOpcode() ==
ISD::AND &&
"Unexpected opcode combine into ANDN");
5603 MVT VT =
N->getSimpleValueType(0);
5622 return DAG.
getNode(LoongArchISD::VANDN,
DL, VT,
X,
Y);
5626 unsigned MinSizeInBits) {
5634 unsigned SplatBitSize;
5637 return Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
5638 HasAnyUndefs, MinSizeInBits,
5648 EVT VT =
N->getValueType(0);
5714 if (
And.getOperand(0) ==
X) {
5743 if (ShiftVal != (SplatVal + 1))
5752 : LoongArchISD::VSRAR,
5762 SDValue FirstOperand =
N->getOperand(0);
5763 SDValue SecondOperand =
N->getOperand(1);
5764 unsigned FirstOperandOpc = FirstOperand.
getOpcode();
5765 EVT ValTy =
N->getValueType(0);
5768 unsigned SMIdx, SMLen;
5777 if (!Subtarget.has32S())
5833 NewOperand = FirstOperand;
5836 msb = lsb + SMLen - 1;
5840 if (FirstOperandOpc ==
ISD::SRA || FirstOperandOpc ==
ISD::SRL || lsb == 0)
5853 if (!Subtarget.has32S())
5865 SDValue FirstOperand =
N->getOperand(0);
5867 EVT ValTy =
N->getValueType(0);
5870 unsigned MaskIdx, MaskLen;
5885 if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1)
5886 return DAG.
getNode(LoongArchISD::BSTRPICK,
DL, ValTy,
5901 switch (Src.getOpcode()) {
5904 return Src.getOperand(0).getValueSizeInBits() ==
Size;
5914 return Src.getOperand(0).getScalarValueSizeInBits() == 1 &&
5927 switch (Src.getOpcode()) {
5937 Src.getOpcode(),
DL, SExtVT,
5943 DL, SExtVT, Src.getOperand(0),
5955 EVT VT =
N->getValueType(0);
5957 EVT SrcVT = Src.getValueType();
5959 if (Src.getOpcode() !=
ISD::SETCC || !Src.hasOneUse())
5964 EVT CmpVT = Src.getOperand(0).getValueType();
5969 else if (Subtarget.has32S() && Subtarget.hasExtLASX() &&
5982 Opc = UseLASX ? LoongArchISD::XVMSKEQZ : LoongArchISD::VMSKEQZ;
5987 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
5992 Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;
5997 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
5999 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6004 (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
6006 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6011 Opc = UseLASX ? LoongArchISD::XVMSKNEZ : LoongArchISD::VMSKNEZ;
6028 EVT VT =
N->getValueType(0);
6030 EVT SrcVT = Src.getValueType();
6047 bool UseLASX =
false;
6048 bool PropagateSExt =
false;
6050 if (Src.getOpcode() ==
ISD::SETCC && Src.hasOneUse()) {
6051 EVT CmpVT = Src.getOperand(0).getValueType();
6060 SExtVT = MVT::v2i64;
6063 SExtVT = MVT::v4i32;
6065 SExtVT = MVT::v4i64;
6067 PropagateSExt =
true;
6071 SExtVT = MVT::v8i16;
6073 SExtVT = MVT::v8i32;
6075 PropagateSExt =
true;
6079 SExtVT = MVT::v16i8;
6081 SExtVT = MVT::v16i16;
6083 PropagateSExt =
true;
6087 SExtVT = MVT::v32i8;
6095 if (!Subtarget.has32S() || !Subtarget.hasExtLASX()) {
6096 if (Src.getSimpleValueType() == MVT::v32i8) {
6104 }
else if (UseLASX) {
6110 Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;
6123 EVT ValTy =
N->getValueType(0);
6124 SDValue N0 =
N->getOperand(0), N1 =
N->getOperand(1);
6128 unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1;
6130 bool SwapAndRetried =
false;
6133 if (!Subtarget.has32S())
6139 if (ValBits != 32 && ValBits != 64)
6154 MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 &&
6157 (MaskIdx0 + MaskLen0 <= ValBits)) {
6178 MaskLen0 == MaskLen1 && MaskIdx1 == 0 &&
6179 (MaskIdx0 + MaskLen0 <= ValBits)) {
6196 (MaskIdx0 + MaskLen0 <= 64) &&
6204 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
6205 : (MaskIdx0 + MaskLen0 - 1),
6221 (MaskIdx0 + MaskLen0 <= ValBits)) {
6244 DAG.
getConstant(ValBits == 32 ? (MaskIdx0 + (MaskLen0 & 31) - 1)
6245 : (MaskIdx0 + MaskLen0 - 1),
6260 unsigned MaskIdx, MaskLen;
6261 if (N1.getOpcode() ==
ISD::SHL && N1.getOperand(0).getOpcode() ==
ISD::AND &&
6270 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
6288 N1.getOperand(0).getOpcode() ==
ISD::SHL &&
6294 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
6302 if (!SwapAndRetried) {
6304 SwapAndRetried =
true;
6308 SwapAndRetried =
false;
6325 return DAG.
getNode(LoongArchISD::BSTRINS,
DL, ValTy, N0,
6334 if (!SwapAndRetried) {
6336 SwapAndRetried =
true;
6346 switch (V.getNode()->getOpcode()) {
6358 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
6366 if ((TypeNode->
getVT() == MVT::i8) || (TypeNode->
getVT() == MVT::i16)) {
6443 SDNode *AndNode =
N->getOperand(0).getNode();
6451 SDValue CmpInputValue =
N->getOperand(1);
6460 if (!CN || !CN->
isZero())
6462 AndInputValue1 = AndInputValue1.
getOperand(0);
6466 if (AndInputValue2 != CmpInputValue)
6499 TruncInputValue1, TruncInputValue2);
6501 DAG.
getSetCC(
SDLoc(
N),
N->getValueType(0), NewAnd, TruncInputValue2, CC);
6514 if (Src.getOpcode() != LoongArchISD::REVB_2W)
6517 return DAG.
getNode(LoongArchISD::BITREV_4B,
SDLoc(
N),
N->getValueType(0),
6542 LHS.getOperand(0).getValueType() == Subtarget.
getGRLenVT()) {
6570 ShAmt =
LHS.getValueSizeInBits() - 1 - ShAmt;
6603 return DAG.
getNode(LoongArchISD::BR_CC,
DL,
N->getValueType(0),
6604 N->getOperand(0),
LHS,
RHS, CC,
N->getOperand(4));
6620 EVT VT =
N->getValueType(0);
6623 if (TrueV == FalseV)
6654 return DAG.
getNode(LoongArchISD::SELECT_CC,
DL,
N->getValueType(0),
6655 {LHS, RHS, CC, TrueV, FalseV});
6660template <
unsigned N>
6664 bool IsSigned =
false) {
6668 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
6669 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
6671 ": argument out of range.");
6677template <
unsigned N>
6681 EVT ResTy =
Node->getValueType(0);
6685 if ((IsSigned && !
isInt<N>(CImm->getSExtValue())) ||
6686 (!IsSigned && !
isUInt<N>(CImm->getZExtValue()))) {
6688 ": argument out of range.");
6693 IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned),
6699 EVT ResTy =
Node->getValueType(0);
6707 EVT ResTy =
Node->getValueType(0);
6716template <
unsigned N>
6719 EVT ResTy =
Node->getValueType(0);
6724 ": argument out of range.");
6734template <
unsigned N>
6737 EVT ResTy =
Node->getValueType(0);
6742 ": argument out of range.");
6751template <
unsigned N>
6754 EVT ResTy =
Node->getValueType(0);
6759 ": argument out of range.");
6768template <
unsigned W>
6771 unsigned Imm =
N->getConstantOperandVal(2);
6773 const StringRef ErrorMsg =
"argument out of range";
6775 return DAG.
getUNDEF(
N->getValueType(0));
6781 return DAG.
getNode(ResOp,
DL,
N->getValueType(0), Vec, Idx, EltVT);
6789 switch (
N->getConstantOperandVal(0)) {
6792 case Intrinsic::loongarch_lsx_vadd_b:
6793 case Intrinsic::loongarch_lsx_vadd_h:
6794 case Intrinsic::loongarch_lsx_vadd_w:
6795 case Intrinsic::loongarch_lsx_vadd_d:
6796 case Intrinsic::loongarch_lasx_xvadd_b:
6797 case Intrinsic::loongarch_lasx_xvadd_h:
6798 case Intrinsic::loongarch_lasx_xvadd_w:
6799 case Intrinsic::loongarch_lasx_xvadd_d:
6802 case Intrinsic::loongarch_lsx_vaddi_bu:
6803 case Intrinsic::loongarch_lsx_vaddi_hu:
6804 case Intrinsic::loongarch_lsx_vaddi_wu:
6805 case Intrinsic::loongarch_lsx_vaddi_du:
6806 case Intrinsic::loongarch_lasx_xvaddi_bu:
6807 case Intrinsic::loongarch_lasx_xvaddi_hu:
6808 case Intrinsic::loongarch_lasx_xvaddi_wu:
6809 case Intrinsic::loongarch_lasx_xvaddi_du:
6812 case Intrinsic::loongarch_lsx_vsub_b:
6813 case Intrinsic::loongarch_lsx_vsub_h:
6814 case Intrinsic::loongarch_lsx_vsub_w:
6815 case Intrinsic::loongarch_lsx_vsub_d:
6816 case Intrinsic::loongarch_lasx_xvsub_b:
6817 case Intrinsic::loongarch_lasx_xvsub_h:
6818 case Intrinsic::loongarch_lasx_xvsub_w:
6819 case Intrinsic::loongarch_lasx_xvsub_d:
6822 case Intrinsic::loongarch_lsx_vsubi_bu:
6823 case Intrinsic::loongarch_lsx_vsubi_hu:
6824 case Intrinsic::loongarch_lsx_vsubi_wu:
6825 case Intrinsic::loongarch_lsx_vsubi_du:
6826 case Intrinsic::loongarch_lasx_xvsubi_bu:
6827 case Intrinsic::loongarch_lasx_xvsubi_hu:
6828 case Intrinsic::loongarch_lasx_xvsubi_wu:
6829 case Intrinsic::loongarch_lasx_xvsubi_du:
6832 case Intrinsic::loongarch_lsx_vneg_b:
6833 case Intrinsic::loongarch_lsx_vneg_h:
6834 case Intrinsic::loongarch_lsx_vneg_w:
6835 case Intrinsic::loongarch_lsx_vneg_d:
6836 case Intrinsic::loongarch_lasx_xvneg_b:
6837 case Intrinsic::loongarch_lasx_xvneg_h:
6838 case Intrinsic::loongarch_lasx_xvneg_w:
6839 case Intrinsic::loongarch_lasx_xvneg_d:
6843 APInt(
N->getValueType(0).getScalarType().getSizeInBits(), 0,
6845 SDLoc(
N),
N->getValueType(0)),
6847 case Intrinsic::loongarch_lsx_vmax_b:
6848 case Intrinsic::loongarch_lsx_vmax_h:
6849 case Intrinsic::loongarch_lsx_vmax_w:
6850 case Intrinsic::loongarch_lsx_vmax_d:
6851 case Intrinsic::loongarch_lasx_xvmax_b:
6852 case Intrinsic::loongarch_lasx_xvmax_h:
6853 case Intrinsic::loongarch_lasx_xvmax_w:
6854 case Intrinsic::loongarch_lasx_xvmax_d:
6857 case Intrinsic::loongarch_lsx_vmax_bu:
6858 case Intrinsic::loongarch_lsx_vmax_hu:
6859 case Intrinsic::loongarch_lsx_vmax_wu:
6860 case Intrinsic::loongarch_lsx_vmax_du:
6861 case Intrinsic::loongarch_lasx_xvmax_bu:
6862 case Intrinsic::loongarch_lasx_xvmax_hu:
6863 case Intrinsic::loongarch_lasx_xvmax_wu:
6864 case Intrinsic::loongarch_lasx_xvmax_du:
6867 case Intrinsic::loongarch_lsx_vmaxi_b:
6868 case Intrinsic::loongarch_lsx_vmaxi_h:
6869 case Intrinsic::loongarch_lsx_vmaxi_w:
6870 case Intrinsic::loongarch_lsx_vmaxi_d:
6871 case Intrinsic::loongarch_lasx_xvmaxi_b:
6872 case Intrinsic::loongarch_lasx_xvmaxi_h:
6873 case Intrinsic::loongarch_lasx_xvmaxi_w:
6874 case Intrinsic::loongarch_lasx_xvmaxi_d:
6877 case Intrinsic::loongarch_lsx_vmaxi_bu:
6878 case Intrinsic::loongarch_lsx_vmaxi_hu:
6879 case Intrinsic::loongarch_lsx_vmaxi_wu:
6880 case Intrinsic::loongarch_lsx_vmaxi_du:
6881 case Intrinsic::loongarch_lasx_xvmaxi_bu:
6882 case Intrinsic::loongarch_lasx_xvmaxi_hu:
6883 case Intrinsic::loongarch_lasx_xvmaxi_wu:
6884 case Intrinsic::loongarch_lasx_xvmaxi_du:
6887 case Intrinsic::loongarch_lsx_vmin_b:
6888 case Intrinsic::loongarch_lsx_vmin_h:
6889 case Intrinsic::loongarch_lsx_vmin_w:
6890 case Intrinsic::loongarch_lsx_vmin_d:
6891 case Intrinsic::loongarch_lasx_xvmin_b:
6892 case Intrinsic::loongarch_lasx_xvmin_h:
6893 case Intrinsic::loongarch_lasx_xvmin_w:
6894 case Intrinsic::loongarch_lasx_xvmin_d:
6897 case Intrinsic::loongarch_lsx_vmin_bu:
6898 case Intrinsic::loongarch_lsx_vmin_hu:
6899 case Intrinsic::loongarch_lsx_vmin_wu:
6900 case Intrinsic::loongarch_lsx_vmin_du:
6901 case Intrinsic::loongarch_lasx_xvmin_bu:
6902 case Intrinsic::loongarch_lasx_xvmin_hu:
6903 case Intrinsic::loongarch_lasx_xvmin_wu:
6904 case Intrinsic::loongarch_lasx_xvmin_du:
6907 case Intrinsic::loongarch_lsx_vmini_b:
6908 case Intrinsic::loongarch_lsx_vmini_h:
6909 case Intrinsic::loongarch_lsx_vmini_w:
6910 case Intrinsic::loongarch_lsx_vmini_d:
6911 case Intrinsic::loongarch_lasx_xvmini_b:
6912 case Intrinsic::loongarch_lasx_xvmini_h:
6913 case Intrinsic::loongarch_lasx_xvmini_w:
6914 case Intrinsic::loongarch_lasx_xvmini_d:
6917 case Intrinsic::loongarch_lsx_vmini_bu:
6918 case Intrinsic::loongarch_lsx_vmini_hu:
6919 case Intrinsic::loongarch_lsx_vmini_wu:
6920 case Intrinsic::loongarch_lsx_vmini_du:
6921 case Intrinsic::loongarch_lasx_xvmini_bu:
6922 case Intrinsic::loongarch_lasx_xvmini_hu:
6923 case Intrinsic::loongarch_lasx_xvmini_wu:
6924 case Intrinsic::loongarch_lasx_xvmini_du:
6927 case Intrinsic::loongarch_lsx_vmul_b:
6928 case Intrinsic::loongarch_lsx_vmul_h:
6929 case Intrinsic::loongarch_lsx_vmul_w:
6930 case Intrinsic::loongarch_lsx_vmul_d:
6931 case Intrinsic::loongarch_lasx_xvmul_b:
6932 case Intrinsic::loongarch_lasx_xvmul_h:
6933 case Intrinsic::loongarch_lasx_xvmul_w:
6934 case Intrinsic::loongarch_lasx_xvmul_d:
6937 case Intrinsic::loongarch_lsx_vmadd_b:
6938 case Intrinsic::loongarch_lsx_vmadd_h:
6939 case Intrinsic::loongarch_lsx_vmadd_w:
6940 case Intrinsic::loongarch_lsx_vmadd_d:
6941 case Intrinsic::loongarch_lasx_xvmadd_b:
6942 case Intrinsic::loongarch_lasx_xvmadd_h:
6943 case Intrinsic::loongarch_lasx_xvmadd_w:
6944 case Intrinsic::loongarch_lasx_xvmadd_d: {
6945 EVT ResTy =
N->getValueType(0);
6950 case Intrinsic::loongarch_lsx_vmsub_b:
6951 case Intrinsic::loongarch_lsx_vmsub_h:
6952 case Intrinsic::loongarch_lsx_vmsub_w:
6953 case Intrinsic::loongarch_lsx_vmsub_d:
6954 case Intrinsic::loongarch_lasx_xvmsub_b:
6955 case Intrinsic::loongarch_lasx_xvmsub_h:
6956 case Intrinsic::loongarch_lasx_xvmsub_w:
6957 case Intrinsic::loongarch_lasx_xvmsub_d: {
6958 EVT ResTy =
N->getValueType(0);
6963 case Intrinsic::loongarch_lsx_vdiv_b:
6964 case Intrinsic::loongarch_lsx_vdiv_h:
6965 case Intrinsic::loongarch_lsx_vdiv_w:
6966 case Intrinsic::loongarch_lsx_vdiv_d:
6967 case Intrinsic::loongarch_lasx_xvdiv_b:
6968 case Intrinsic::loongarch_lasx_xvdiv_h:
6969 case Intrinsic::loongarch_lasx_xvdiv_w:
6970 case Intrinsic::loongarch_lasx_xvdiv_d:
6973 case Intrinsic::loongarch_lsx_vdiv_bu:
6974 case Intrinsic::loongarch_lsx_vdiv_hu:
6975 case Intrinsic::loongarch_lsx_vdiv_wu:
6976 case Intrinsic::loongarch_lsx_vdiv_du:
6977 case Intrinsic::loongarch_lasx_xvdiv_bu:
6978 case Intrinsic::loongarch_lasx_xvdiv_hu:
6979 case Intrinsic::loongarch_lasx_xvdiv_wu:
6980 case Intrinsic::loongarch_lasx_xvdiv_du:
6983 case Intrinsic::loongarch_lsx_vmod_b:
6984 case Intrinsic::loongarch_lsx_vmod_h:
6985 case Intrinsic::loongarch_lsx_vmod_w:
6986 case Intrinsic::loongarch_lsx_vmod_d:
6987 case Intrinsic::loongarch_lasx_xvmod_b:
6988 case Intrinsic::loongarch_lasx_xvmod_h:
6989 case Intrinsic::loongarch_lasx_xvmod_w:
6990 case Intrinsic::loongarch_lasx_xvmod_d:
6993 case Intrinsic::loongarch_lsx_vmod_bu:
6994 case Intrinsic::loongarch_lsx_vmod_hu:
6995 case Intrinsic::loongarch_lsx_vmod_wu:
6996 case Intrinsic::loongarch_lsx_vmod_du:
6997 case Intrinsic::loongarch_lasx_xvmod_bu:
6998 case Intrinsic::loongarch_lasx_xvmod_hu:
6999 case Intrinsic::loongarch_lasx_xvmod_wu:
7000 case Intrinsic::loongarch_lasx_xvmod_du:
7003 case Intrinsic::loongarch_lsx_vand_v:
7004 case Intrinsic::loongarch_lasx_xvand_v:
7007 case Intrinsic::loongarch_lsx_vor_v:
7008 case Intrinsic::loongarch_lasx_xvor_v:
7011 case Intrinsic::loongarch_lsx_vxor_v:
7012 case Intrinsic::loongarch_lasx_xvxor_v:
7015 case Intrinsic::loongarch_lsx_vnor_v:
7016 case Intrinsic::loongarch_lasx_xvnor_v: {
7021 case Intrinsic::loongarch_lsx_vandi_b:
7022 case Intrinsic::loongarch_lasx_xvandi_b:
7025 case Intrinsic::loongarch_lsx_vori_b:
7026 case Intrinsic::loongarch_lasx_xvori_b:
7029 case Intrinsic::loongarch_lsx_vxori_b:
7030 case Intrinsic::loongarch_lasx_xvxori_b:
7033 case Intrinsic::loongarch_lsx_vsll_b:
7034 case Intrinsic::loongarch_lsx_vsll_h:
7035 case Intrinsic::loongarch_lsx_vsll_w:
7036 case Intrinsic::loongarch_lsx_vsll_d:
7037 case Intrinsic::loongarch_lasx_xvsll_b:
7038 case Intrinsic::loongarch_lasx_xvsll_h:
7039 case Intrinsic::loongarch_lasx_xvsll_w:
7040 case Intrinsic::loongarch_lasx_xvsll_d:
7043 case Intrinsic::loongarch_lsx_vslli_b:
7044 case Intrinsic::loongarch_lasx_xvslli_b:
7047 case Intrinsic::loongarch_lsx_vslli_h:
7048 case Intrinsic::loongarch_lasx_xvslli_h:
7051 case Intrinsic::loongarch_lsx_vslli_w:
7052 case Intrinsic::loongarch_lasx_xvslli_w:
7055 case Intrinsic::loongarch_lsx_vslli_d:
7056 case Intrinsic::loongarch_lasx_xvslli_d:
7059 case Intrinsic::loongarch_lsx_vsrl_b:
7060 case Intrinsic::loongarch_lsx_vsrl_h:
7061 case Intrinsic::loongarch_lsx_vsrl_w:
7062 case Intrinsic::loongarch_lsx_vsrl_d:
7063 case Intrinsic::loongarch_lasx_xvsrl_b:
7064 case Intrinsic::loongarch_lasx_xvsrl_h:
7065 case Intrinsic::loongarch_lasx_xvsrl_w:
7066 case Intrinsic::loongarch_lasx_xvsrl_d:
7069 case Intrinsic::loongarch_lsx_vsrli_b:
7070 case Intrinsic::loongarch_lasx_xvsrli_b:
7073 case Intrinsic::loongarch_lsx_vsrli_h:
7074 case Intrinsic::loongarch_lasx_xvsrli_h:
7077 case Intrinsic::loongarch_lsx_vsrli_w:
7078 case Intrinsic::loongarch_lasx_xvsrli_w:
7081 case Intrinsic::loongarch_lsx_vsrli_d:
7082 case Intrinsic::loongarch_lasx_xvsrli_d:
7085 case Intrinsic::loongarch_lsx_vsra_b:
7086 case Intrinsic::loongarch_lsx_vsra_h:
7087 case Intrinsic::loongarch_lsx_vsra_w:
7088 case Intrinsic::loongarch_lsx_vsra_d:
7089 case Intrinsic::loongarch_lasx_xvsra_b:
7090 case Intrinsic::loongarch_lasx_xvsra_h:
7091 case Intrinsic::loongarch_lasx_xvsra_w:
7092 case Intrinsic::loongarch_lasx_xvsra_d:
7095 case Intrinsic::loongarch_lsx_vsrai_b:
7096 case Intrinsic::loongarch_lasx_xvsrai_b:
7099 case Intrinsic::loongarch_lsx_vsrai_h:
7100 case Intrinsic::loongarch_lasx_xvsrai_h:
7103 case Intrinsic::loongarch_lsx_vsrai_w:
7104 case Intrinsic::loongarch_lasx_xvsrai_w:
7107 case Intrinsic::loongarch_lsx_vsrai_d:
7108 case Intrinsic::loongarch_lasx_xvsrai_d:
7111 case Intrinsic::loongarch_lsx_vclz_b:
7112 case Intrinsic::loongarch_lsx_vclz_h:
7113 case Intrinsic::loongarch_lsx_vclz_w:
7114 case Intrinsic::loongarch_lsx_vclz_d:
7115 case Intrinsic::loongarch_lasx_xvclz_b:
7116 case Intrinsic::loongarch_lasx_xvclz_h:
7117 case Intrinsic::loongarch_lasx_xvclz_w:
7118 case Intrinsic::loongarch_lasx_xvclz_d:
7120 case Intrinsic::loongarch_lsx_vpcnt_b:
7121 case Intrinsic::loongarch_lsx_vpcnt_h:
7122 case Intrinsic::loongarch_lsx_vpcnt_w:
7123 case Intrinsic::loongarch_lsx_vpcnt_d:
7124 case Intrinsic::loongarch_lasx_xvpcnt_b:
7125 case Intrinsic::loongarch_lasx_xvpcnt_h:
7126 case Intrinsic::loongarch_lasx_xvpcnt_w:
7127 case Intrinsic::loongarch_lasx_xvpcnt_d:
7129 case Intrinsic::loongarch_lsx_vbitclr_b:
7130 case Intrinsic::loongarch_lsx_vbitclr_h:
7131 case Intrinsic::loongarch_lsx_vbitclr_w:
7132 case Intrinsic::loongarch_lsx_vbitclr_d:
7133 case Intrinsic::loongarch_lasx_xvbitclr_b:
7134 case Intrinsic::loongarch_lasx_xvbitclr_h:
7135 case Intrinsic::loongarch_lasx_xvbitclr_w:
7136 case Intrinsic::loongarch_lasx_xvbitclr_d:
7138 case Intrinsic::loongarch_lsx_vbitclri_b:
7139 case Intrinsic::loongarch_lasx_xvbitclri_b:
7141 case Intrinsic::loongarch_lsx_vbitclri_h:
7142 case Intrinsic::loongarch_lasx_xvbitclri_h:
7144 case Intrinsic::loongarch_lsx_vbitclri_w:
7145 case Intrinsic::loongarch_lasx_xvbitclri_w:
7147 case Intrinsic::loongarch_lsx_vbitclri_d:
7148 case Intrinsic::loongarch_lasx_xvbitclri_d:
7150 case Intrinsic::loongarch_lsx_vbitset_b:
7151 case Intrinsic::loongarch_lsx_vbitset_h:
7152 case Intrinsic::loongarch_lsx_vbitset_w:
7153 case Intrinsic::loongarch_lsx_vbitset_d:
7154 case Intrinsic::loongarch_lasx_xvbitset_b:
7155 case Intrinsic::loongarch_lasx_xvbitset_h:
7156 case Intrinsic::loongarch_lasx_xvbitset_w:
7157 case Intrinsic::loongarch_lasx_xvbitset_d: {
7158 EVT VecTy =
N->getValueType(0);
7164 case Intrinsic::loongarch_lsx_vbitseti_b:
7165 case Intrinsic::loongarch_lasx_xvbitseti_b:
7167 case Intrinsic::loongarch_lsx_vbitseti_h:
7168 case Intrinsic::loongarch_lasx_xvbitseti_h:
7170 case Intrinsic::loongarch_lsx_vbitseti_w:
7171 case Intrinsic::loongarch_lasx_xvbitseti_w:
7173 case Intrinsic::loongarch_lsx_vbitseti_d:
7174 case Intrinsic::loongarch_lasx_xvbitseti_d:
7176 case Intrinsic::loongarch_lsx_vbitrev_b:
7177 case Intrinsic::loongarch_lsx_vbitrev_h:
7178 case Intrinsic::loongarch_lsx_vbitrev_w:
7179 case Intrinsic::loongarch_lsx_vbitrev_d:
7180 case Intrinsic::loongarch_lasx_xvbitrev_b:
7181 case Intrinsic::loongarch_lasx_xvbitrev_h:
7182 case Intrinsic::loongarch_lasx_xvbitrev_w:
7183 case Intrinsic::loongarch_lasx_xvbitrev_d: {
7184 EVT VecTy =
N->getValueType(0);
7190 case Intrinsic::loongarch_lsx_vbitrevi_b:
7191 case Intrinsic::loongarch_lasx_xvbitrevi_b:
7193 case Intrinsic::loongarch_lsx_vbitrevi_h:
7194 case Intrinsic::loongarch_lasx_xvbitrevi_h:
7196 case Intrinsic::loongarch_lsx_vbitrevi_w:
7197 case Intrinsic::loongarch_lasx_xvbitrevi_w:
7199 case Intrinsic::loongarch_lsx_vbitrevi_d:
7200 case Intrinsic::loongarch_lasx_xvbitrevi_d:
7202 case Intrinsic::loongarch_lsx_vfadd_s:
7203 case Intrinsic::loongarch_lsx_vfadd_d:
7204 case Intrinsic::loongarch_lasx_xvfadd_s:
7205 case Intrinsic::loongarch_lasx_xvfadd_d:
7208 case Intrinsic::loongarch_lsx_vfsub_s:
7209 case Intrinsic::loongarch_lsx_vfsub_d:
7210 case Intrinsic::loongarch_lasx_xvfsub_s:
7211 case Intrinsic::loongarch_lasx_xvfsub_d:
7214 case Intrinsic::loongarch_lsx_vfmul_s:
7215 case Intrinsic::loongarch_lsx_vfmul_d:
7216 case Intrinsic::loongarch_lasx_xvfmul_s:
7217 case Intrinsic::loongarch_lasx_xvfmul_d:
7220 case Intrinsic::loongarch_lsx_vfdiv_s:
7221 case Intrinsic::loongarch_lsx_vfdiv_d:
7222 case Intrinsic::loongarch_lasx_xvfdiv_s:
7223 case Intrinsic::loongarch_lasx_xvfdiv_d:
7226 case Intrinsic::loongarch_lsx_vfmadd_s:
7227 case Intrinsic::loongarch_lsx_vfmadd_d:
7228 case Intrinsic::loongarch_lasx_xvfmadd_s:
7229 case Intrinsic::loongarch_lasx_xvfmadd_d:
7231 N->getOperand(2),
N->getOperand(3));
7232 case Intrinsic::loongarch_lsx_vinsgr2vr_b:
7234 N->getOperand(1),
N->getOperand(2),
7236 case Intrinsic::loongarch_lsx_vinsgr2vr_h:
7237 case Intrinsic::loongarch_lasx_xvinsgr2vr_w:
7239 N->getOperand(1),
N->getOperand(2),
7241 case Intrinsic::loongarch_lsx_vinsgr2vr_w:
7242 case Intrinsic::loongarch_lasx_xvinsgr2vr_d:
7244 N->getOperand(1),
N->getOperand(2),
7246 case Intrinsic::loongarch_lsx_vinsgr2vr_d:
7248 N->getOperand(1),
N->getOperand(2),
7250 case Intrinsic::loongarch_lsx_vreplgr2vr_b:
7251 case Intrinsic::loongarch_lsx_vreplgr2vr_h:
7252 case Intrinsic::loongarch_lsx_vreplgr2vr_w:
7253 case Intrinsic::loongarch_lsx_vreplgr2vr_d:
7254 case Intrinsic::loongarch_lasx_xvreplgr2vr_b:
7255 case Intrinsic::loongarch_lasx_xvreplgr2vr_h:
7256 case Intrinsic::loongarch_lasx_xvreplgr2vr_w:
7257 case Intrinsic::loongarch_lasx_xvreplgr2vr_d:
7258 return DAG.
getNode(LoongArchISD::VREPLGR2VR,
DL,
N->getValueType(0),
7261 case Intrinsic::loongarch_lsx_vreplve_b:
7262 case Intrinsic::loongarch_lsx_vreplve_h:
7263 case Intrinsic::loongarch_lsx_vreplve_w:
7264 case Intrinsic::loongarch_lsx_vreplve_d:
7265 case Intrinsic::loongarch_lasx_xvreplve_b:
7266 case Intrinsic::loongarch_lasx_xvreplve_h:
7267 case Intrinsic::loongarch_lasx_xvreplve_w:
7268 case Intrinsic::loongarch_lasx_xvreplve_d:
7269 return DAG.
getNode(LoongArchISD::VREPLVE,
DL,
N->getValueType(0),
7273 case Intrinsic::loongarch_lsx_vpickve2gr_b:
7277 case Intrinsic::loongarch_lsx_vpickve2gr_h:
7278 case Intrinsic::loongarch_lasx_xvpickve2gr_w:
7282 case Intrinsic::loongarch_lsx_vpickve2gr_w:
7286 case Intrinsic::loongarch_lsx_vpickve2gr_bu:
7290 case Intrinsic::loongarch_lsx_vpickve2gr_hu:
7291 case Intrinsic::loongarch_lasx_xvpickve2gr_wu:
7295 case Intrinsic::loongarch_lsx_vpickve2gr_wu:
7299 case Intrinsic::loongarch_lsx_bz_b:
7300 case Intrinsic::loongarch_lsx_bz_h:
7301 case Intrinsic::loongarch_lsx_bz_w:
7302 case Intrinsic::loongarch_lsx_bz_d:
7303 case Intrinsic::loongarch_lasx_xbz_b:
7304 case Intrinsic::loongarch_lasx_xbz_h:
7305 case Intrinsic::loongarch_lasx_xbz_w:
7306 case Intrinsic::loongarch_lasx_xbz_d:
7308 return DAG.
getNode(LoongArchISD::VALL_ZERO,
DL,
N->getValueType(0),
7311 case Intrinsic::loongarch_lsx_bz_v:
7312 case Intrinsic::loongarch_lasx_xbz_v:
7314 return DAG.
getNode(LoongArchISD::VANY_ZERO,
DL,
N->getValueType(0),
7317 case Intrinsic::loongarch_lsx_bnz_b:
7318 case Intrinsic::loongarch_lsx_bnz_h:
7319 case Intrinsic::loongarch_lsx_bnz_w:
7320 case Intrinsic::loongarch_lsx_bnz_d:
7321 case Intrinsic::loongarch_lasx_xbnz_b:
7322 case Intrinsic::loongarch_lasx_xbnz_h:
7323 case Intrinsic::loongarch_lasx_xbnz_w:
7324 case Intrinsic::loongarch_lasx_xbnz_d:
7326 return DAG.
getNode(LoongArchISD::VALL_NONZERO,
DL,
N->getValueType(0),
7329 case Intrinsic::loongarch_lsx_bnz_v:
7330 case Intrinsic::loongarch_lasx_xbnz_v:
7332 return DAG.
getNode(LoongArchISD::VANY_NONZERO,
DL,
N->getValueType(0),
7335 case Intrinsic::loongarch_lasx_concat_128_s:
7336 case Intrinsic::loongarch_lasx_concat_128_d:
7337 case Intrinsic::loongarch_lasx_concat_128:
7339 N->getOperand(1),
N->getOperand(2));
7351 if (Op0.
getOpcode() == LoongArchISD::MOVFR2GR_S_LA64)
7363 if (Op0->
getOpcode() == LoongArchISD::MOVGR2FR_W_LA64) {
7365 "Unexpected value type!");
7374 MVT VT =
N->getSimpleValueType(0);
7395 if (Op0->
getOpcode() == LoongArchISD::BUILD_PAIR_F64)
7408 APInt V =
C->getValueAPF().bitcastToAPInt();
7423 MVT VT =
N->getSimpleValueType(0);
7484 EVT VT =
N->getValueType(0);
7486 if (VT != MVT::f32 && VT != MVT::f64)
7488 if (VT == MVT::f32 && !Subtarget.hasBasicF())
7490 if (VT == MVT::f64 && !Subtarget.hasBasicD())
7513 return DAG.
getNode(LoongArchISD::SITOF,
SDLoc(
N), VT, Load);
7570 Subtarget.hasExtLASX() && N1.
hasOneUse())
7582 return DAG.
getNode(
N.getOpcode(),
DL, VT, N0, N1);
7592 EVT VT =
N.getValueType();
7609 switch (
N.getOpcode()) {
7625 EVT VT =
N->getValueType(0);
7640 EVT VT =
N->getValueType(0);
7642 if (VT.
isVector() &&
N->getNumOperands() == 2)
7655 EVT VT =
N->getValueType(0);
7667 SDValue TrueVal =
N->getOperand(1);
7668 SDValue FalseVal =
N->getOperand(2);
7702 if (FalseVal.getOpcode() !=
ISD::ADD)
7705 SDValue Add0 = FalseVal.getOperand(0);
7706 SDValue Add1 = FalseVal.getOperand(1);
7776 : LoongArchISD::VSRAR,
7783 switch (
N->getOpcode()) {
7804 case LoongArchISD::BITREV_W:
7806 case LoongArchISD::BR_CC:
7808 case LoongArchISD::SELECT_CC:
7812 case LoongArchISD::MOVGR2FR_W_LA64:
7814 case LoongArchISD::MOVFR2GR_S_LA64:
7816 case LoongArchISD::VMSKLTZ:
7817 case LoongArchISD::XVMSKLTZ:
7819 case LoongArchISD::SPLIT_PAIR_F64:
7821 case LoongArchISD::VANDN:
7827 case LoongArchISD::VPACKEV:
7853 MF->
insert(It, BreakMBB);
7857 SinkMBB->splice(SinkMBB->end(),
MBB, std::next(
MI.getIterator()),
MBB->end());
7858 SinkMBB->transferSuccessorsAndUpdatePHIs(
MBB);
7870 MBB->addSuccessor(BreakMBB);
7871 MBB->addSuccessor(SinkMBB);
7877 BreakMBB->addSuccessor(SinkMBB);
7889 switch (
MI.getOpcode()) {
7892 case LoongArch::PseudoVBZ:
7893 CondOpc = LoongArch::VSETEQZ_V;
7895 case LoongArch::PseudoVBZ_B:
7896 CondOpc = LoongArch::VSETANYEQZ_B;
7898 case LoongArch::PseudoVBZ_H:
7899 CondOpc = LoongArch::VSETANYEQZ_H;
7901 case LoongArch::PseudoVBZ_W:
7902 CondOpc = LoongArch::VSETANYEQZ_W;
7904 case LoongArch::PseudoVBZ_D:
7905 CondOpc = LoongArch::VSETANYEQZ_D;
7907 case LoongArch::PseudoVBNZ:
7908 CondOpc = LoongArch::VSETNEZ_V;
7910 case LoongArch::PseudoVBNZ_B:
7911 CondOpc = LoongArch::VSETALLNEZ_B;
7913 case LoongArch::PseudoVBNZ_H:
7914 CondOpc = LoongArch::VSETALLNEZ_H;
7916 case LoongArch::PseudoVBNZ_W:
7917 CondOpc = LoongArch::VSETALLNEZ_W;
7919 case LoongArch::PseudoVBNZ_D:
7920 CondOpc = LoongArch::VSETALLNEZ_D;
7922 case LoongArch::PseudoXVBZ:
7923 CondOpc = LoongArch::XVSETEQZ_V;
7925 case LoongArch::PseudoXVBZ_B:
7926 CondOpc = LoongArch::XVSETANYEQZ_B;
7928 case LoongArch::PseudoXVBZ_H:
7929 CondOpc = LoongArch::XVSETANYEQZ_H;
7931 case LoongArch::PseudoXVBZ_W:
7932 CondOpc = LoongArch::XVSETANYEQZ_W;
7934 case LoongArch::PseudoXVBZ_D:
7935 CondOpc = LoongArch::XVSETANYEQZ_D;
7937 case LoongArch::PseudoXVBNZ:
7938 CondOpc = LoongArch::XVSETNEZ_V;
7940 case LoongArch::PseudoXVBNZ_B:
7941 CondOpc = LoongArch::XVSETALLNEZ_B;
7943 case LoongArch::PseudoXVBNZ_H:
7944 CondOpc = LoongArch::XVSETALLNEZ_H;
7946 case LoongArch::PseudoXVBNZ_W:
7947 CondOpc = LoongArch::XVSETALLNEZ_W;
7949 case LoongArch::PseudoXVBNZ_D:
7950 CondOpc = LoongArch::XVSETALLNEZ_D;
7965 F->insert(It, FalseBB);
7966 F->insert(It, TrueBB);
7967 F->insert(It, SinkBB);
7970 SinkBB->
splice(SinkBB->
end(), BB, std::next(
MI.getIterator()), BB->
end());
7999 MI.getOperand(0).getReg())
8006 MI.eraseFromParent();
8014 unsigned BroadcastOp;
8016 switch (
MI.getOpcode()) {
8019 case LoongArch::PseudoXVINSGR2VR_B:
8021 BroadcastOp = LoongArch::XVREPLGR2VR_B;
8022 InsOp = LoongArch::XVEXTRINS_B;
8024 case LoongArch::PseudoXVINSGR2VR_H:
8026 BroadcastOp = LoongArch::XVREPLGR2VR_H;
8027 InsOp = LoongArch::XVEXTRINS_H;
8039 unsigned Idx =
MI.getOperand(3).getImm();
8047 .
addReg(XSrc, {}, LoongArch::sub_128);
8049 TII->get(HalfSize == 8 ? LoongArch::VINSGR2VR_H
8050 : LoongArch::VINSGR2VR_B),
8058 .
addImm(LoongArch::sub_128);
8065 BuildMI(*BB,
MI,
DL,
TII->get(LoongArch::XVPERMI_Q), ScratchReg2)
8068 .
addImm(Idx >= HalfSize ? 48 : 18);
8073 .
addImm((Idx >= HalfSize ? Idx - HalfSize : Idx) * 17);
8076 MI.eraseFromParent();
8083 assert(Subtarget.hasExtLSX());
8096 TII->get(Subtarget.
is64Bit() ? LoongArch::VINSGR2VR_D
8097 : LoongArch::VINSGR2VR_W),
8104 TII->get(Subtarget.
is64Bit() ? LoongArch::VPCNT_D : LoongArch::VPCNT_W),
8108 TII->get(Subtarget.
is64Bit() ? LoongArch::VPICKVE2GR_D
8109 : LoongArch::VPICKVE2GR_W),
8114 MI.eraseFromParent();
8128 unsigned EleBits = 8;
8129 unsigned NotOpc = 0;
8132 switch (
MI.getOpcode()) {
8135 case LoongArch::PseudoVMSKLTZ_B:
8136 MskOpc = LoongArch::VMSKLTZ_B;
8138 case LoongArch::PseudoVMSKLTZ_H:
8139 MskOpc = LoongArch::VMSKLTZ_H;
8142 case LoongArch::PseudoVMSKLTZ_W:
8143 MskOpc = LoongArch::VMSKLTZ_W;
8146 case LoongArch::PseudoVMSKLTZ_D:
8147 MskOpc = LoongArch::VMSKLTZ_D;
8150 case LoongArch::PseudoVMSKGEZ_B:
8151 MskOpc = LoongArch::VMSKGEZ_B;
8153 case LoongArch::PseudoVMSKEQZ_B:
8154 MskOpc = LoongArch::VMSKNZ_B;
8155 NotOpc = LoongArch::VNOR_V;
8157 case LoongArch::PseudoVMSKNEZ_B:
8158 MskOpc = LoongArch::VMSKNZ_B;
8160 case LoongArch::PseudoXVMSKLTZ_B:
8161 MskOpc = LoongArch::XVMSKLTZ_B;
8162 RC = &LoongArch::LASX256RegClass;
8164 case LoongArch::PseudoXVMSKLTZ_H:
8165 MskOpc = LoongArch::XVMSKLTZ_H;
8166 RC = &LoongArch::LASX256RegClass;
8169 case LoongArch::PseudoXVMSKLTZ_W:
8170 MskOpc = LoongArch::XVMSKLTZ_W;
8171 RC = &LoongArch::LASX256RegClass;
8174 case LoongArch::PseudoXVMSKLTZ_D:
8175 MskOpc = LoongArch::XVMSKLTZ_D;
8176 RC = &LoongArch::LASX256RegClass;
8179 case LoongArch::PseudoXVMSKGEZ_B:
8180 MskOpc = LoongArch::XVMSKGEZ_B;
8181 RC = &LoongArch::LASX256RegClass;
8183 case LoongArch::PseudoXVMSKEQZ_B:
8184 MskOpc = LoongArch::XVMSKNZ_B;
8185 NotOpc = LoongArch::XVNOR_V;
8186 RC = &LoongArch::LASX256RegClass;
8188 case LoongArch::PseudoXVMSKNEZ_B:
8189 MskOpc = LoongArch::XVMSKNZ_B;
8190 RC = &LoongArch::LASX256RegClass;
8205 if (
TRI->getRegSizeInBits(*RC) > 128) {
8215 TII->get(Subtarget.
is64Bit() ? LoongArch::BSTRINS_D
8216 : LoongArch::BSTRINS_W),
8220 .
addImm(256 / EleBits - 1)
8228 MI.eraseFromParent();
8235 assert(
MI.getOpcode() == LoongArch::SplitPairF64Pseudo &&
8236 "Unexpected instruction");
8248 MI.eraseFromParent();
8255 assert(
MI.getOpcode() == LoongArch::BuildPairF64Pseudo &&
8256 "Unexpected instruction");
8272 MI.eraseFromParent();
8277 switch (
MI.getOpcode()) {
8280 case LoongArch::Select_GPR_Using_CC_GPR:
8316 if (
MI.getOperand(2).isReg())
8317 RHS =
MI.getOperand(2).getReg();
8318 auto CC =
static_cast<unsigned>(
MI.getOperand(3).
getImm());
8322 SelectDests.
insert(
MI.getOperand(0).getReg());
8326 SequenceMBBI !=
E; ++SequenceMBBI) {
8327 if (SequenceMBBI->isDebugInstr())
8330 if (SequenceMBBI->getOperand(1).getReg() !=
LHS ||
8331 !SequenceMBBI->getOperand(2).isReg() ||
8332 SequenceMBBI->getOperand(2).getReg() !=
RHS ||
8333 SequenceMBBI->getOperand(3).getImm() != CC ||
8334 SelectDests.
count(SequenceMBBI->getOperand(4).getReg()) ||
8335 SelectDests.
count(SequenceMBBI->getOperand(5).getReg()))
8337 LastSelectPseudo = &*SequenceMBBI;
8339 SelectDests.
insert(SequenceMBBI->getOperand(0).getReg());
8342 if (SequenceMBBI->hasUnmodeledSideEffects() ||
8343 SequenceMBBI->mayLoadOrStore() ||
8344 SequenceMBBI->usesCustomInsertionHook())
8347 return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());
8362 F->insert(
I, IfFalseMBB);
8363 F->insert(
I, TailMBB);
8366 unsigned CallFrameSize =
TII.getCallFrameSizeAt(*LastSelectPseudo);
8372 TailMBB->
push_back(DebugInstr->removeFromParent());
8376 TailMBB->
splice(TailMBB->
end(), HeadMBB,
8386 if (
MI.getOperand(2).isImm())
8398 auto SelectMBBI =
MI.getIterator();
8399 auto SelectEnd = std::next(LastSelectPseudo->
getIterator());
8401 while (SelectMBBI != SelectEnd) {
8402 auto Next = std::next(SelectMBBI);
8406 TII.get(LoongArch::PHI), SelectMBBI->getOperand(0).getReg())
8407 .
addReg(SelectMBBI->getOperand(4).getReg())
8409 .
addReg(SelectMBBI->getOperand(5).getReg())
8416 F->getProperties().resetNoPHIs();
8422 const TargetInstrInfo *
TII = Subtarget.getInstrInfo();
8425 switch (
MI.getOpcode()) {
8428 case LoongArch::DIV_W:
8429 case LoongArch::DIV_WU:
8430 case LoongArch::MOD_W:
8431 case LoongArch::MOD_WU:
8432 case LoongArch::DIV_D:
8433 case LoongArch::DIV_DU:
8434 case LoongArch::MOD_D:
8435 case LoongArch::MOD_DU:
8438 case LoongArch::WRFCSR: {
8440 LoongArch::FCSR0 +
MI.getOperand(0).getImm())
8441 .
addReg(
MI.getOperand(1).getReg());
8442 MI.eraseFromParent();
8445 case LoongArch::RDFCSR: {
8446 MachineInstr *ReadFCSR =
8448 MI.getOperand(0).getReg())
8449 .
addReg(LoongArch::FCSR0 +
MI.getOperand(1).getImm());
8451 MI.eraseFromParent();
8454 case LoongArch::Select_GPR_Using_CC_GPR:
8456 case LoongArch::BuildPairF64Pseudo:
8458 case LoongArch::SplitPairF64Pseudo:
8460 case LoongArch::PseudoVBZ:
8461 case LoongArch::PseudoVBZ_B:
8462 case LoongArch::PseudoVBZ_H:
8463 case LoongArch::PseudoVBZ_W:
8464 case LoongArch::PseudoVBZ_D:
8465 case LoongArch::PseudoVBNZ:
8466 case LoongArch::PseudoVBNZ_B:
8467 case LoongArch::PseudoVBNZ_H:
8468 case LoongArch::PseudoVBNZ_W:
8469 case LoongArch::PseudoVBNZ_D:
8470 case LoongArch::PseudoXVBZ:
8471 case LoongArch::PseudoXVBZ_B:
8472 case LoongArch::PseudoXVBZ_H:
8473 case LoongArch::PseudoXVBZ_W:
8474 case LoongArch::PseudoXVBZ_D:
8475 case LoongArch::PseudoXVBNZ:
8476 case LoongArch::PseudoXVBNZ_B:
8477 case LoongArch::PseudoXVBNZ_H:
8478 case LoongArch::PseudoXVBNZ_W:
8479 case LoongArch::PseudoXVBNZ_D:
8481 case LoongArch::PseudoXVINSGR2VR_B:
8482 case LoongArch::PseudoXVINSGR2VR_H:
8484 case LoongArch::PseudoCTPOP:
8486 case LoongArch::PseudoVMSKLTZ_B:
8487 case LoongArch::PseudoVMSKLTZ_H:
8488 case LoongArch::PseudoVMSKLTZ_W:
8489 case LoongArch::PseudoVMSKLTZ_D:
8490 case LoongArch::PseudoVMSKGEZ_B:
8491 case LoongArch::PseudoVMSKEQZ_B:
8492 case LoongArch::PseudoVMSKNEZ_B:
8493 case LoongArch::PseudoXVMSKLTZ_B:
8494 case LoongArch::PseudoXVMSKLTZ_H:
8495 case LoongArch::PseudoXVMSKLTZ_W:
8496 case LoongArch::PseudoXVMSKLTZ_D:
8497 case LoongArch::PseudoXVMSKGEZ_B:
8498 case LoongArch::PseudoXVMSKEQZ_B:
8499 case LoongArch::PseudoXVMSKNEZ_B:
8501 case TargetOpcode::STATEPOINT:
8507 MI.addOperand(*
MI.getMF(),
8509 LoongArch::R1,
true,
8512 if (!Subtarget.is64Bit())
8520 unsigned *
Fast)
const {
8521 if (!Subtarget.hasUAL())
8539 LoongArch::R7, LoongArch::R8, LoongArch::R9,
8540 LoongArch::R10, LoongArch::R11};
8555 LoongArch::R23, LoongArch::R24, LoongArch::R25, LoongArch::R26,
8556 LoongArch::R27, LoongArch::R28, LoongArch::R29, LoongArch::R30,
8557 LoongArch::R4, LoongArch::R5, LoongArch::R6, LoongArch::R7,
8558 LoongArch::R8, LoongArch::R9, LoongArch::R10, LoongArch::R11,
8559 LoongArch::R12, LoongArch::R13, LoongArch::R14, LoongArch::R15,
8560 LoongArch::R16, LoongArch::R17, LoongArch::R18, LoongArch::R19,
8566 LoongArch::F3, LoongArch::F4, LoongArch::F5,
8567 LoongArch::F6, LoongArch::F7};
8570 LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64,
8571 LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64};
8574 LoongArch::VR3, LoongArch::VR4, LoongArch::VR5,
8575 LoongArch::VR6, LoongArch::VR7};
8578 LoongArch::XR3, LoongArch::XR4, LoongArch::XR5,
8579 LoongArch::XR6, LoongArch::XR7};
8582 switch (State.getCallingConv()) {
8584 if (!State.isVarArg())
8588 return State.AllocateReg(
ArgGPRs);
8596 unsigned ValNo2,
MVT ValVT2,
MVT LocVT2,
8598 unsigned GRLenInBytes = GRLen / 8;
8609 State.AllocateStack(GRLenInBytes, StackAlign),
8612 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
8623 ValNo2, ValVT2, State.AllocateStack(GRLenInBytes,
Align(GRLenInBytes)),
8631 unsigned ValNo,
MVT ValVT,
8634 unsigned GRLen =
DL.getLargestLegalIntTypeSizeInBits();
8635 assert((GRLen == 32 || GRLen == 64) &&
"Unspport GRLen");
8636 MVT GRLenVT = GRLen == 32 ? MVT::i32 : MVT::i64;
8641 if (IsRet && ValNo > 1)
8645 bool UseGPRForFloat =
true;
8655 UseGPRForFloat = ArgFlags.
isVarArg();
8668 unsigned TwoGRLenInBytes = (2 * GRLen) / 8;
8671 DL.getTypeAllocSize(OrigTy) == TwoGRLenInBytes) {
8672 unsigned RegIdx = State.getFirstUnallocated(
ArgGPRs);
8674 if (RegIdx != std::size(
ArgGPRs) && RegIdx % 2 == 1)
8680 State.getPendingArgFlags();
8683 "PendingLocs and PendingArgFlags out of sync");
8687 UseGPRForFloat =
true;
8689 if (UseGPRForFloat && ValVT == MVT::f32) {
8692 }
else if (UseGPRForFloat && GRLen == 64 && ValVT == MVT::f64) {
8695 }
else if (UseGPRForFloat && GRLen == 32 && ValVT == MVT::f64) {
8698 assert(PendingLocs.
empty() &&
"Can't lower f64 if it is split");
8740 PendingLocs.
size() <= 2) {
8741 assert(PendingLocs.
size() == 2 &&
"Unexpected PendingLocs.size()");
8746 PendingLocs.
clear();
8747 PendingArgFlags.
clear();
8754 unsigned StoreSizeBytes = GRLen / 8;
8757 if (ValVT == MVT::f32 && !UseGPRForFloat) {
8759 }
else if (ValVT == MVT::f64 && !UseGPRForFloat) {
8763 UseGPRForFloat =
false;
8764 StoreSizeBytes = 16;
8765 StackAlign =
Align(16);
8768 UseGPRForFloat =
false;
8769 StoreSizeBytes = 32;
8770 StackAlign =
Align(32);
8776 Reg ? 0 : State.AllocateStack(StoreSizeBytes, StackAlign);
8780 if (!PendingLocs.
empty()) {
8782 assert(PendingLocs.
size() > 2 &&
"Unexpected PendingLocs.size()");
8783 for (
auto &It : PendingLocs) {
8785 It.convertToReg(
Reg);
8790 PendingLocs.clear();
8791 PendingArgFlags.
clear();
8794 assert((!UseGPRForFloat || LocVT == GRLenVT) &&
8795 "Expected an GRLenVT at this stage");
8812void LoongArchTargetLowering::analyzeInputArgs(
8815 LoongArchCCAssignFn Fn)
const {
8817 for (
unsigned i = 0, e = Ins.
size(); i != e; ++i) {
8818 MVT ArgVT = Ins[i].VT;
8819 Type *ArgTy =
nullptr;
8821 ArgTy = FType->getReturnType();
8822 else if (Ins[i].isOrigArg())
8823 ArgTy = FType->getParamType(Ins[i].getOrigArgIndex());
8827 CCInfo, IsRet, ArgTy)) {
8828 LLVM_DEBUG(
dbgs() <<
"InputArg #" << i <<
" has unhandled type " << ArgVT
8835void LoongArchTargetLowering::analyzeOutputArgs(
8838 CallLoweringInfo *CLI, LoongArchCCAssignFn Fn)
const {
8839 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
8840 MVT ArgVT = Outs[i].VT;
8841 Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty :
nullptr;
8845 CCInfo, IsRet, OrigTy)) {
8846 LLVM_DEBUG(
dbgs() <<
"OutputArg #" << i <<
" has unhandled type " << ArgVT
8865 Val = DAG.
getNode(LoongArchISD::MOVGR2FR_W_LA64,
DL, MVT::f32, Val);
8887 if (In.isOrigArg()) {
8892 if ((
BitWidth <= 32 && In.Flags.isSExt()) ||
8893 (
BitWidth < 32 && In.Flags.isZExt())) {
8943 Register LoVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
8956 Register HiVReg =
RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);
8960 return DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
Lo,
Hi);
8974 Val = DAG.
getNode(LoongArchISD::MOVFR2GR_S_LA64,
DL, MVT::i64, Val);
8986 if (LocVT == MVT::i32 || LocVT == MVT::i64) {
8990 LoongArch::R23, LoongArch::R24, LoongArch::R25,
8991 LoongArch::R26, LoongArch::R27, LoongArch::R28,
8992 LoongArch::R29, LoongArch::R30, LoongArch::R31};
8999 if (LocVT == MVT::f32) {
9002 static const MCPhysReg FPR32List[] = {LoongArch::F24, LoongArch::F25,
9003 LoongArch::F26, LoongArch::F27};
9010 if (LocVT == MVT::f64) {
9013 static const MCPhysReg FPR64List[] = {LoongArch::F28_64, LoongArch::F29_64,
9014 LoongArch::F30_64, LoongArch::F31_64};
9045 "GHC calling convention requires the F and D extensions");
9049 MVT GRLenVT = Subtarget.getGRLenVT();
9050 unsigned GRLenInBytes = Subtarget.getGRLen() / 8;
9052 std::vector<SDValue> OutChains;
9061 analyzeInputArgs(MF, CCInfo, Ins,
false,
CC_LoongArch);
9063 for (
unsigned i = 0, e = ArgLocs.
size(), InsIdx = 0; i != e; ++i, ++InsIdx) {
9080 unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;
9081 unsigned ArgPartOffset = Ins[InsIdx].PartOffset;
9082 assert(ArgPartOffset == 0);
9083 while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {
9085 unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;
9109 int VaArgOffset, VarArgsSaveSize;
9113 if (ArgRegs.
size() == Idx) {
9115 VarArgsSaveSize = 0;
9117 VarArgsSaveSize = GRLenInBytes * (ArgRegs.
size() - Idx);
9118 VaArgOffset = -VarArgsSaveSize;
9124 LoongArchFI->setVarArgsFrameIndex(FI);
9132 VarArgsSaveSize += GRLenInBytes;
9137 for (
unsigned I = Idx;
I < ArgRegs.
size();
9138 ++
I, VaArgOffset += GRLenInBytes) {
9139 const Register Reg = RegInfo.createVirtualRegister(RC);
9140 RegInfo.addLiveIn(ArgRegs[
I], Reg);
9148 ->setValue((
Value *)
nullptr);
9149 OutChains.push_back(Store);
9151 LoongArchFI->setVarArgsSaveSize(VarArgsSaveSize);
9156 if (!OutChains.empty()) {
9157 OutChains.push_back(Chain);
9172 if (
N->getNumValues() != 1)
9174 if (!
N->hasNUsesOfValue(1, 0))
9177 SDNode *Copy = *
N->user_begin();
9183 if (Copy->getGluedNode())
9187 bool HasRet =
false;
9189 if (
Node->getOpcode() != LoongArchISD::RET)
9197 Chain = Copy->getOperand(0);
9202bool LoongArchTargetLowering::isEligibleForTailCallOptimization(
9206 auto CalleeCC = CLI.CallConv;
9207 auto &Outs = CLI.Outs;
9209 auto CallerCC = Caller.getCallingConv();
9216 for (
auto &VA : ArgLocs)
9222 auto IsCallerStructRet = Caller.hasStructRetAttr();
9223 auto IsCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
9224 if (IsCallerStructRet || IsCalleeStructRet)
9228 for (
auto &Arg : Outs)
9229 if (Arg.Flags.isByVal())
9234 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
9235 if (CalleeCC != CallerCC) {
9236 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
9237 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
9263 MVT GRLenVT = Subtarget.getGRLenVT();
9275 analyzeOutputArgs(MF, ArgCCInfo, Outs,
false, &CLI,
CC_LoongArch);
9279 IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);
9285 "site marked musttail");
9292 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
9294 if (!Flags.isByVal())
9298 unsigned Size = Flags.getByValSize();
9299 Align Alignment = Flags.getNonZeroByValAlign();
9306 Chain = DAG.
getMemcpy(Chain,
DL, FIPtr, Arg, SizeNode, Alignment,
9308 false,
nullptr, std::nullopt,
9320 for (
unsigned i = 0, j = 0, e = ArgLocs.
size(), OutIdx = 0; i != e;
9323 SDValue ArgValue = OutVals[OutIdx];
9331 DAG.
getNode(LoongArchISD::SPLIT_PAIR_F64,
DL,
9332 DAG.
getVTList(MVT::i32, MVT::i32), ArgValue);
9344 if (!StackPtr.getNode())
9356 RegsToPass.
push_back(std::make_pair(RegHigh,
Hi));
9371 unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;
9372 unsigned ArgPartOffset = Outs[OutIdx].PartOffset;
9373 assert(ArgPartOffset == 0);
9378 while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {
9379 SDValue PartValue = OutVals[OutIdx + 1];
9380 unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;
9395 for (
const auto &Part : Parts) {
9396 SDValue PartValue = Part.first;
9397 SDValue PartOffset = Part.second;
9404 ArgValue = SpillSlot;
9410 if (Flags.isByVal())
9411 ArgValue = ByValArgs[j++];
9418 assert(!IsTailCall &&
"Tail call not allowed if stack is used "
9419 "for passing parameters");
9422 if (!StackPtr.getNode())
9435 if (!MemOpChains.
empty())
9441 for (
auto &Reg : RegsToPass) {
9442 Chain = DAG.
getCopyToReg(Chain,
DL, Reg.first, Reg.second, Glue);
9464 Ops.push_back(Chain);
9465 Ops.push_back(Callee);
9469 for (
auto &Reg : RegsToPass)
9470 Ops.push_back(DAG.
getRegister(Reg.first, Reg.second.getValueType()));
9475 const uint32_t *Mask =
TRI->getCallPreservedMask(MF, CallConv);
9476 assert(Mask &&
"Missing call preserved mask for calling convention");
9482 Ops.push_back(Glue);
9491 Op = IsTailCall ? LoongArchISD::TAIL : LoongArchISD::CALL;
9494 Op = IsTailCall ? LoongArchISD::TAIL_MEDIUM : LoongArchISD::CALL_MEDIUM;
9497 assert(Subtarget.is64Bit() &&
"Large code model requires LA64");
9498 Op = IsTailCall ? LoongArchISD::TAIL_LARGE : LoongArchISD::CALL_LARGE;
9520 analyzeInputArgs(MF, RetCCInfo, Ins,
true,
CC_LoongArch);
9523 for (
unsigned i = 0, e = RVLocs.
size(); i != e; ++i) {
9524 auto &VA = RVLocs[i];
9532 if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {
9533 assert(VA.needsCustom());
9538 RetValue = DAG.
getNode(LoongArchISD::BUILD_PAIR_F64,
DL, MVT::f64,
9539 RetValue, RetValue2);
9552 const Type *RetTy)
const {
9554 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
9556 for (
unsigned i = 0, e = Outs.
size(); i != e; ++i) {
9560 Outs[i].Flags, CCInfo,
true,
nullptr))
9586 for (
unsigned i = 0, e = RVLocs.
size(), OutIdx = 0; i < e; ++i, ++OutIdx) {
9587 SDValue Val = OutVals[OutIdx];
9596 DAG.
getVTList(MVT::i32, MVT::i32), Val);
9600 Register RegHi = RVLocs[++i].getLocReg();
9625 return DAG.
getNode(LoongArchISD::RET,
DL, MVT::Other, RetOps);
9633 const APInt &SplatValue,
const unsigned SplatBitSize)
const {
9636 if (SplatBitSize == 16 && !(V & 0x00FF)) {
9638 RequiredImm = (0b10101 << 8) | (V >> 8);
9639 return {
true, RequiredImm};
9640 }
else if (SplatBitSize == 32) {
9642 if (!(V & 0xFFFF00FF)) {
9643 RequiredImm = (0b10001 << 8) | (V >> 8);
9644 return {
true, RequiredImm};
9647 if (!(V & 0xFF00FFFF)) {
9648 RequiredImm = (0b10010 << 8) | (V >> 16);
9649 return {
true, RequiredImm};
9652 if (!(V & 0x00FFFFFF)) {
9653 RequiredImm = (0b10011 << 8) | (V >> 24);
9654 return {
true, RequiredImm};
9657 if ((V & 0xFFFF00FF) == 0xFF) {
9658 RequiredImm = (0b10110 << 8) | (V >> 8);
9659 return {
true, RequiredImm};
9662 if ((V & 0xFF00FFFF) == 0xFFFF) {
9663 RequiredImm = (0b10111 << 8) | (V >> 16);
9664 return {
true, RequiredImm};
9667 if ((V & 0x7E07FFFF) == 0x3E000000 || (V & 0x7E07FFFF) == 0x40000000) {
9669 (0b11010 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
9670 return {
true, RequiredImm};
9672 }
else if (SplatBitSize == 64) {
9674 if ((V & 0xFFFFFFFF7E07FFFFULL) == 0x3E000000ULL ||
9675 (V & 0xFFFFFFFF7E07FFFFULL) == 0x40000000ULL) {
9677 (0b11011 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);
9678 return {
true, RequiredImm};
9681 if ((V & 0x7FC0FFFFFFFFFFFFULL) == 0x4000000000000000ULL ||
9682 (V & 0x7FC0FFFFFFFFFFFFULL) == 0x3FC0000000000000ULL) {
9684 (0b11100 << 8) | (((V >> 56) & 0xC0) ^ 0x40) | ((V >> 48) & 0x3F);
9685 return {
true, RequiredImm};
9688 auto sameBitsPreByte = [](
uint64_t x) -> std::pair<bool, uint8_t> {
9690 for (
int i = 0; i < 8; ++i) {
9692 if (
byte == 0 ||
byte == 0xFF)
9693 res |= ((
byte & 1) << i);
9700 auto [IsSame, Suffix] = sameBitsPreByte(V);
9702 RequiredImm = (0b11001 << 8) | Suffix;
9703 return {
true, RequiredImm};
9706 return {
false, RequiredImm};
9711 if (!Subtarget.hasExtLSX())
9714 if (VT == MVT::f32) {
9715 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7e07ffff;
9716 return (masked == 0x3e000000 || masked == 0x40000000);
9719 if (VT == MVT::f64) {
9720 uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7fc0ffffffffffff;
9721 return (masked == 0x3fc0000000000000 || masked == 0x4000000000000000);
9727bool LoongArchTargetLowering::isFPImmLegal(
const APFloat &Imm,
EVT VT,
9728 bool ForCodeSize)
const {
9730 if (VT == MVT::f32 && !Subtarget.hasBasicF())
9732 if (VT == MVT::f64 && !Subtarget.hasBasicD())
9734 return (Imm.isZero() || Imm.isExactlyValue(1.0) ||
isFPImmVLDILegal(Imm, VT));
9745bool LoongArchTargetLowering::shouldInsertFencesForAtomic(
9755 Type *Ty =
I->getOperand(0)->getType();
9757 unsigned Size = Ty->getIntegerBitWidth();
9777 unsigned MaxIntSize = Subtarget.is64Bit() ? 64 : 32;
9782 if (Subtarget.hasExtLASX())
9784 else if (Subtarget.hasExtLSX())
9791 EVT VT =
Y.getValueType();
9794 return Subtarget.hasExtLSX() && VT.
isInteger();
9805 case Intrinsic::loongarch_masked_atomicrmw_xchg_i32:
9806 case Intrinsic::loongarch_masked_atomicrmw_add_i32:
9807 case Intrinsic::loongarch_masked_atomicrmw_sub_i32:
9808 case Intrinsic::loongarch_masked_atomicrmw_nand_i32: {
9811 Info.memVT = MVT::i32;
9812 Info.ptrVal =
I.getArgOperand(0);
9814 Info.align =
Align(4);
9833 "Unable to expand");
9834 unsigned MinWordSize = 4;
9846 Value *AlignedAddr = Builder.CreateIntrinsic(
9847 Intrinsic::ptrmask, {PtrTy, IntTy},
9848 {Addr, ConstantInt::get(IntTy, ~(
uint64_t)(MinWordSize - 1))},
nullptr,
9851 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
9852 Value *PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
9853 Value *ShiftAmt = Builder.CreateShl(PtrLSB, 3);
9854 ShiftAmt = Builder.CreateTrunc(ShiftAmt, WordType,
"ShiftAmt");
9855 Value *Mask = Builder.CreateShl(
9856 ConstantInt::get(WordType,
9859 Value *Inv_Mask = Builder.CreateNot(Mask,
"Inv_Mask");
9860 Value *ValOperand_Shifted =
9861 Builder.CreateShl(Builder.CreateZExt(AI->
getValOperand(), WordType),
9862 ShiftAmt,
"ValOperand_Shifted");
9865 NewOperand = Builder.CreateOr(ValOperand_Shifted, Inv_Mask,
"AndOperand");
9867 NewOperand = ValOperand_Shifted;
9870 Builder.CreateAtomicRMW(
Op, AlignedAddr, NewOperand,
Align(MinWordSize),
9873 Value *Shift = Builder.CreateLShr(NewAI, ShiftAmt,
"shifted");
9874 Value *Trunc = Builder.CreateTrunc(Shift,
ValueType,
"extracted");
9894 if (Subtarget.hasLAM_BH() && Subtarget.is64Bit() &&
9902 if (Subtarget.hasLAMCAS()) {
9924 return Intrinsic::loongarch_masked_atomicrmw_xchg_i64;
9926 return Intrinsic::loongarch_masked_atomicrmw_add_i64;
9928 return Intrinsic::loongarch_masked_atomicrmw_sub_i64;
9930 return Intrinsic::loongarch_masked_atomicrmw_nand_i64;
9932 return Intrinsic::loongarch_masked_atomicrmw_umax_i64;
9934 return Intrinsic::loongarch_masked_atomicrmw_umin_i64;
9936 return Intrinsic::loongarch_masked_atomicrmw_max_i64;
9938 return Intrinsic::loongarch_masked_atomicrmw_min_i64;
9948 return Intrinsic::loongarch_masked_atomicrmw_xchg_i32;
9950 return Intrinsic::loongarch_masked_atomicrmw_add_i32;
9952 return Intrinsic::loongarch_masked_atomicrmw_sub_i32;
9954 return Intrinsic::loongarch_masked_atomicrmw_nand_i32;
9956 return Intrinsic::loongarch_masked_atomicrmw_umax_i32;
9958 return Intrinsic::loongarch_masked_atomicrmw_umin_i32;
9960 return Intrinsic::loongarch_masked_atomicrmw_max_i32;
9962 return Intrinsic::loongarch_masked_atomicrmw_min_i32;
9974 if (Subtarget.hasLAMCAS())
9986 unsigned GRLen = Subtarget.getGRLen();
9988 Value *FailureOrdering =
9989 Builder.getIntN(Subtarget.getGRLen(),
static_cast<uint64_t>(FailOrd));
9990 Intrinsic::ID CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i32;
9992 CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i64;
9993 CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());
9994 NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());
9995 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
9998 Value *Result = Builder.CreateIntrinsic(
9999 CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, FailureOrdering});
10001 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
10017 Builder.CreateNot(Mask,
"Inv_Mask"),
10024 unsigned GRLen = Subtarget.getGRLen();
10033 Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());
10034 Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());
10035 ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());
10048 unsigned ValWidth =
10051 Builder.CreateSub(Builder.getIntN(GRLen, GRLen - ValWidth), ShiftAmt);
10052 Result = Builder.CreateCall(LlwOpScwLoop,
10053 {AlignedAddr, Incr, Mask, SextShamt, Ordering});
10056 Builder.CreateCall(LlwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});
10060 Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
10083 const Constant *PersonalityFn)
const {
10084 return LoongArch::R4;
10088 const Constant *PersonalityFn)
const {
10089 return LoongArch::R5;
10100 int RefinementSteps = VT.
getScalarType() == MVT::f64 ? 2 : 1;
10101 return RefinementSteps;
10106 assert(Subtarget.hasFrecipe() &&
10107 "Reciprocal estimate queried on unsupported target");
10118 return Subtarget.hasBasicD();
10122 return Subtarget.hasExtLSX();
10126 return Subtarget.hasExtLASX();
10135 int &RefinementSteps,
10136 bool &UseOneConstNR,
10137 bool Reciprocal)
const {
10139 "Enabled should never be Disabled here");
10141 if (!Subtarget.hasFrecipe())
10156 UseOneConstNR =
false;
10162 if (Reciprocal || RefinementSteps > 0)
10172 int &RefinementSteps)
const {
10174 "Enabled should never be Disabled here");
10176 if (!Subtarget.hasFrecipe())
10190 return DAG.
getNode(LoongArchISD::FRECIPE,
DL, VT, Operand);
10198LoongArchTargetLowering::getConstraintType(
StringRef Constraint)
const {
10218 if (Constraint.
size() == 1) {
10219 switch (Constraint[0]) {
10235 if (Constraint ==
"ZC" || Constraint ==
"ZB")
10244 return StringSwitch<InlineAsm::ConstraintCode>(ConstraintCode)
10251std::pair<unsigned, const TargetRegisterClass *>
10252LoongArchTargetLowering::getRegForInlineAsmConstraint(
10256 if (Constraint.
size() == 1) {
10257 switch (Constraint[0]) {
10262 return std::make_pair(0U, &LoongArch::GPRRegClass);
10264 return std::make_pair(0U, &LoongArch::GPRNoR0R1RegClass);
10266 if (Subtarget.hasBasicF() && VT == MVT::f32)
10267 return std::make_pair(0U, &LoongArch::FPR32RegClass);
10268 if (Subtarget.hasBasicD() && VT == MVT::f64)
10269 return std::make_pair(0U, &LoongArch::FPR64RegClass);
10270 if (Subtarget.hasExtLSX() &&
10271 TRI->isTypeLegalForClass(LoongArch::LSX128RegClass, VT))
10272 return std::make_pair(0U, &LoongArch::LSX128RegClass);
10273 if (Subtarget.hasExtLASX() &&
10274 TRI->isTypeLegalForClass(LoongArch::LASX256RegClass, VT))
10275 return std::make_pair(0U, &LoongArch::LASX256RegClass);
10295 bool IsFP = Constraint[2] ==
'f';
10296 std::pair<StringRef, StringRef> Temp = Constraint.
split(
'$');
10297 std::pair<unsigned, const TargetRegisterClass *>
R;
10302 unsigned RegNo =
R.first;
10303 if (LoongArch::F0 <= RegNo && RegNo <= LoongArch::F31) {
10304 if (Subtarget.hasBasicD() && (VT == MVT::f64 || VT == MVT::Other)) {
10305 unsigned DReg = RegNo - LoongArch::F0 + LoongArch::F0_64;
10306 return std::make_pair(DReg, &LoongArch::FPR64RegClass);
10316void LoongArchTargetLowering::LowerAsmOperandForConstraint(
10320 if (Constraint.
size() == 1) {
10321 switch (Constraint[0]) {
10325 uint64_t CVal =
C->getSExtValue();
10328 Subtarget.getGRLenVT()));
10334 uint64_t CVal =
C->getSExtValue();
10337 Subtarget.getGRLenVT()));
10343 if (
C->getZExtValue() == 0)
10350 uint64_t CVal =
C->getZExtValue();
10363#define GET_REGISTER_MATCHER
10364#include "LoongArchGenAsmMatcher.inc"
10370 std::string NewRegName = Name.second.str();
10376 BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
10377 if (!ReservedRegs.
test(Reg))
10394 const APInt &Imm = ConstNode->getAPIntValue();
10396 if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
10397 (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
10400 if (ConstNode->hasOneUse() &&
10401 ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||
10402 (Imm - 8).isPowerOf2() || (Imm - 16).isPowerOf2()))
10408 if (ConstNode->hasOneUse() && !(Imm.sge(-2048) && Imm.sle(4095))) {
10409 unsigned Shifts = Imm.countr_zero();
10415 APInt ImmPop = Imm.ashr(Shifts);
10416 if (ImmPop == 3 || ImmPop == 5 || ImmPop == 9 || ImmPop == 17)
10420 APInt ImmSmall =
APInt(Imm.getBitWidth(), 1ULL << Shifts,
true);
10421 if ((Imm - ImmSmall).isPowerOf2() || (Imm + ImmSmall).isPowerOf2() ||
10422 (ImmSmall - Imm).isPowerOf2())
10432 Type *Ty,
unsigned AS,
10451 switch (AM.
Scale) {
10487 EVT MemVT = LD->getMemoryVT();
10488 if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&
10499 return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
10508 if (
Y.getValueType().isVector())
10520 Type *Ty,
bool IsSigned)
const {
10521 if (Subtarget.is64Bit() && Ty->isIntegerTy(32))
10530 if (Subtarget.isSoftFPABI() && (
Type.isFloatingPoint() && !
Type.isVector() &&
10531 Type.getSizeInBits() < Subtarget.getGRLen()))
10541 Align &PrefAlign)
const {
10545 if (Subtarget.is64Bit()) {
10547 PrefAlign =
Align(8);
10550 PrefAlign =
Align(4);
10565bool LoongArchTargetLowering::splitValueIntoRegisterParts(
10567 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
10568 bool IsABIRegCopy = CC.has_value();
10571 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
10572 PartVT == MVT::f32) {
10587SDValue LoongArchTargetLowering::joinRegisterPartsIntoValue(
10589 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
10590 bool IsABIRegCopy = CC.has_value();
10592 if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&
10593 PartVT == MVT::f32) {
10610 if (VT == MVT::f16 && Subtarget.hasBasicF())
10616unsigned LoongArchTargetLowering::getNumRegistersForCallingConv(
10619 if (VT == MVT::f16 && Subtarget.hasBasicF())
10628 unsigned Opc =
Op.getOpcode();
10633 case LoongArchISD::VPICK_ZEXT_ELT: {
10647 unsigned Depth)
const {
10648 EVT VT =
Op.getValueType();
10650 unsigned Opc =
Op.getOpcode();
10654 case LoongArchISD::VMSKLTZ:
10655 case LoongArchISD::XVMSKLTZ: {
10657 MVT SrcVT = Src.getSimpleValueType();
10662 if (OriginalDemandedBits.
countr_zero() >= NumElts)
10666 APInt KnownUndef, KnownZero;
10682 if (KnownSrc.
One[SrcBits - 1])
10684 else if (KnownSrc.
Zero[SrcBits - 1])
10689 Src, DemandedSrcBits, DemandedElts, TLO.
DAG,
Depth + 1))
10696 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
10719 unsigned Index)
const {
10728 unsigned Index)
const {
10732 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 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_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 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 performSELECT_CCCombine(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 lowerVECTOR_SHUFFLE_XVPERMI(const SDLoc &DL, ArrayRef< int > Mask, MVT VT, SDValue V1, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget)
Lower VECTOR_SHUFFLE into XVPERMI (if possible).
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_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
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 ...
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.
@ 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.
@ 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...
@ 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 ...
@ 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)